@golemui/gui-mcp 1.0.0-rc.3 → 1.0.0-rc.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/CHANGELOG.md +21 -0
- package/LICENSE +21 -0
- package/README.md +64 -23
- package/cli.js +43 -35
- package/dx/check-dx-code.d.ts +25 -0
- package/dx/dx-lint.d.ts +27 -0
- package/dx/dx-specs.d.ts +70 -0
- package/dx/get-dx-spec.d.ts +27 -0
- package/dx/instructions.d.ts +7 -0
- package/dx/list-dx-factories.d.ts +19 -0
- package/dx/tools.d.ts +3 -0
- package/dx/type-graph.d.ts +10 -0
- package/dx/typecheck.d.ts +41 -0
- package/{get-concept-B7s_l8Qs.js → get-concept-Cy3zD1BS.js} +22 -16
- package/{tools → json}/generate-from-json-schema.d.ts +3 -3
- package/{tools → json}/generate-from-openapi.d.ts +3 -3
- package/{tools → json}/get-widget-spec.d.ts +3 -3
- package/json/instructions.d.ts +6 -0
- package/json/tools.d.ts +3 -0
- package/{tools → json}/validate-form-definition.d.ts +5 -5
- package/json.d.ts +7 -0
- package/json.js +13 -0
- package/lib.d.ts +11 -7
- package/lib.js +17 -6
- package/list-dx-factories-CF4ExKyx.js +602 -0
- package/package.json +16 -7
- package/{lint → shared/lint}/reactive-expressions.d.ts +8 -0
- package/shared/tool.d.ts +49 -0
- package/shared/tools.d.ts +7 -0
- /package/{utils → json}/errors.d.ts +0 -0
- /package/{mapping → json/mapping}/json-schema-to-gui.d.ts +0 -0
- /package/{mapping → json/mapping}/validator.d.ts +0 -0
- /package/{schemas → json/schemas}/ajv.d.ts +0 -0
- /package/{schemas → json/schemas}/index.d.ts +0 -0
- /package/{schemas → json/schemas}/shallow-validators.d.ts +0 -0
- /package/{lint → json}/string-interpolation.d.ts +0 -0
- /package/{tools → shared}/get-concept.d.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## 1.0.0-rc.4 (2026-06-14)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **mcp:** add type-checked gui.* DX authoring surface ([#185](https://github.com/golemui/golemui/pull/185))
|
|
6
|
+
|
|
7
|
+
### 🩹 Fixes
|
|
8
|
+
|
|
9
|
+
- **gui-shared:** make dx event handlers function-only ([#190](https://github.com/golemui/golemui/pull/190))
|
|
10
|
+
- added license field and copied license to all publishable packages ([#189](https://github.com/golemui/golemui/pull/189))
|
|
11
|
+
|
|
12
|
+
### ❤️ Thank You
|
|
13
|
+
|
|
14
|
+
- alberto-golem-ui
|
|
15
|
+
- Mud Scientist @mudscientist
|
|
16
|
+
- Raúl Jiménez @Elecash
|
|
17
|
+
|
|
18
|
+
## 1.0.0-rc.3 (2026-06-13)
|
|
19
|
+
|
|
20
|
+
This was a version bump only for gui-mcp to align it with other projects, there were no code changes.
|
|
21
|
+
|
|
1
22
|
## 1.0.0-rc.2 (2026-06-10)
|
|
2
23
|
|
|
3
24
|
This was a version bump only for gui-mcp to align it with other projects, there were no code changes.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GolemUI S.L.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -9,6 +9,30 @@ strict enough that one wrong property name breaks the runtime. This server close
|
|
|
9
9
|
your AI calls it to **validate** what it wrote and to **generate** forms from existing
|
|
10
10
|
JSON Schemas or OpenAPI operations, with the bundled GolemUI schemas as the source of truth.
|
|
11
11
|
|
|
12
|
+
## Two entry points (one surface, two ways to author it)
|
|
13
|
+
|
|
14
|
+
A GolemUI form can be written two ways, and the MCP serves both:
|
|
15
|
+
|
|
16
|
+
- a **JSON form definition**: the serializable object `{ form: [...widgets], states?: {...} }`;
|
|
17
|
+
- **`gui.*` DX code**: the fluent TypeScript builder that _produces_ that same definition.
|
|
18
|
+
|
|
19
|
+
There is no toggle. On connect the server sends one block of guidance (the MCP `initialize.instructions`
|
|
20
|
+
field, `SERVER_INSTRUCTIONS` in [`src/cli.ts`](./src/cli.ts)) and the agent self-routes by what it is
|
|
21
|
+
producing:
|
|
22
|
+
|
|
23
|
+
1. **JSON path**: generate or hand-author, then **always finish with `json_validate_form_definition`**.
|
|
24
|
+
2. **`gui.*` path**: call **`dx_list_factories` first** (the complete reference), write the form, then
|
|
25
|
+
**always finish with `dx_check_code`**.
|
|
26
|
+
|
|
27
|
+
The two terminal checks are not interchangeable: `dx_check_code` validates `gui.*` _code_,
|
|
28
|
+
`json_validate_form_definition` validates a JSON _object_. Each tool's own `description` reinforces the routing
|
|
29
|
+
(e.g. `json_get_widget_spec` tells a `gui.*` author it isn't needed). To read what a client actually sees, run
|
|
30
|
+
`npm run start:mcp` (the MCP Inspector).
|
|
31
|
+
|
|
32
|
+
The split is structural, not just textual: the two paths live in separate modules
|
|
33
|
+
([`src/json/`](./src/json) and [`src/dx/`](./src/dx)) over a small shared surface
|
|
34
|
+
([`src/shared/`](./src/shared)); neither imports the other.
|
|
35
|
+
|
|
12
36
|
## Install
|
|
13
37
|
|
|
14
38
|
The server is a standalone Node CLI distributed on npm. Add it to your IDE's MCP config —
|
|
@@ -46,7 +70,7 @@ npx -y @golemui/gui-mcp < /dev/null
|
|
|
46
70
|
|
|
47
71
|
## Tools
|
|
48
72
|
|
|
49
|
-
### `
|
|
73
|
+
### `json_validate_form_definition`
|
|
50
74
|
|
|
51
75
|
Validates a GolemUI form definition against the bundled JSON Schemas. Returns
|
|
52
76
|
`{ valid: true }` on success, or a structured list of errors with JSON Pointer paths
|
|
@@ -56,7 +80,7 @@ like missing `$form.` prefixes, single `=` in equality checks, and unbalanced br
|
|
|
56
80
|
|
|
57
81
|
**Input:** `{ formDefinition: { form: [...], states?: {...} } }`
|
|
58
82
|
|
|
59
|
-
### `
|
|
83
|
+
### `json_generate_from_schema`
|
|
60
84
|
|
|
61
85
|
Maps a JSON Schema (the form-data shape, e.g. a Zod-derived schema) into a GolemUI
|
|
62
86
|
form definition. Handles strings (with `format` → specialized widgets), numbers,
|
|
@@ -66,7 +90,7 @@ not be mapped.
|
|
|
66
90
|
|
|
67
91
|
**Input:** `{ jsonSchema, submitAction?, submitLabel?, layout? }`
|
|
68
92
|
|
|
69
|
-
### `
|
|
93
|
+
### `json_generate_from_openapi`
|
|
70
94
|
|
|
71
95
|
Resolves an OpenAPI 3.x operation (e.g. `"POST /users"` or an `operationId`), dereferences
|
|
72
96
|
its request body schema, and emits a validated GolemUI form. Falls back to operation
|
|
@@ -74,7 +98,7 @@ parameters when no JSON request body is present.
|
|
|
74
98
|
|
|
75
99
|
**Input:** `{ document | documentUrl, operation, submitAction?, submitLabel? }`
|
|
76
100
|
|
|
77
|
-
### `
|
|
101
|
+
### `json_get_widget_spec`
|
|
78
102
|
|
|
79
103
|
Returns the JSON Schema, kind, a minimal working example, and authoring notes for a
|
|
80
104
|
single GolemUI widget. Cheaper than dumping the whole API into the model's context.
|
|
@@ -84,12 +108,42 @@ single GolemUI widget. Cheaper than dumping the whole API into the model's conte
|
|
|
84
108
|
|
|
85
109
|
### `get_concept`
|
|
86
110
|
|
|
87
|
-
Returns a detailed guide for a cross-cutting concept
|
|
88
|
-
and affect the whole form
|
|
89
|
-
(`"label.stateName": "..."`)
|
|
90
|
-
|
|
111
|
+
Returns a detailed guide for a cross-cutting concept — things that span multiple widgets
|
|
112
|
+
and affect the whole form: conditional rendering (`include`/`exclude`, named-state and
|
|
113
|
+
inline `when`), state-suffixed props (`"label.stateName": "..."`), the reactive scope
|
|
114
|
+
(`$form`, `$meta`, `$errors`, `$formIsInvalid`), and widget icons.
|
|
115
|
+
|
|
116
|
+
**Input:** `{ concept }` — one of `"states"`, `"string-interpolation"`, `"reactive-scope"`, `"icons"`
|
|
117
|
+
|
|
118
|
+
> The five tools above serve the **JSON** surface. The three below serve the **`gui.*`** (DX code) surface —
|
|
119
|
+
> see [Two entry points](#two-entry-points-one-surface-two-ways-to-author-it).
|
|
120
|
+
|
|
121
|
+
### `dx_list_factories`
|
|
91
122
|
|
|
92
|
-
**
|
|
123
|
+
**Call this first when writing `gui.*` code.** Returns the complete `gui.*` DX reference in one call: every
|
|
124
|
+
factory with its namespace, calling convention, a **compile-verified** example, and its gotchas — plus the
|
|
125
|
+
cross-cutting patterns and the common authoring rules. Its imports + render snippet are **tailored to your
|
|
126
|
+
target framework** (`GOLEMUI_FRAMEWORK`). Self-sufficient for most forms; keep it in context and write from it.
|
|
127
|
+
|
|
128
|
+
**Input:** none.
|
|
129
|
+
|
|
130
|
+
### `dx_get_spec`
|
|
131
|
+
|
|
132
|
+
A rare single-factory deep-dive — one factory's calling convention, example, and notes. Usually unneeded
|
|
133
|
+
(`dx_list_factories` already carries every factory); reach here only to re-confirm one in isolation.
|
|
134
|
+
|
|
135
|
+
**Input:** `{ factory }` — the camelCase name (`textInput`, `dropdown`, `radiogroup`, `button`, …).
|
|
136
|
+
|
|
137
|
+
### `dx_check_code`
|
|
138
|
+
|
|
139
|
+
**The `gui.*` terminal check** — the counterpart of `json_validate_form_definition` for _code_ instead of a JSON
|
|
140
|
+
_object_. Type-checks the snippet against the **real `@golemui` type declarations** (compile-is-truth: GolemUI
|
|
141
|
+
isn't in any model's training data, so generated `gui.*` is often a confident fabrication that doesn't
|
|
142
|
+
compile). Also catches two compiler-invisible footguns — a misplaced `include`/`exclude` on a `gui.*` spread,
|
|
143
|
+
and reactive-expression mistakes in `when` strings. Returns `{ ok, diagnostics }`; each diagnostic carries a
|
|
144
|
+
fix `hint`. Treat `ok: false` as blocking.
|
|
145
|
+
|
|
146
|
+
**Input:** `{ code }` — the `gui.*` snippet (a bare `gui.inputs.*` array is fine; the import is added if missing).
|
|
93
147
|
|
|
94
148
|
## Library usage
|
|
95
149
|
|
|
@@ -126,17 +180,6 @@ const { form } = await generateFromOpenapi({
|
|
|
126
180
|
The tool descriptor objects (`VALIDATE_FORM_DEFINITION_TOOL`, `GENERATE_FROM_JSON_SCHEMA_TOOL`, ...)
|
|
127
181
|
are also exported if you want to register the tools in your own MCP server.
|
|
128
182
|
|
|
129
|
-
## How it stays accurate
|
|
130
|
-
|
|
131
|
-
The server ships a frozen snapshot of the GolemUI JSON Schemas inside its npm package,
|
|
132
|
-
version-locked to a specific GolemUI release. A CI check in this monorepo
|
|
133
|
-
(`npm run check:mcp-schemas`) fails if the snapshot drifts from the source schemas in
|
|
134
|
-
`@golemui/gui-shared`, so a published `@golemui/gui-mcp@X.Y.Z` always validates
|
|
135
|
-
against the exact same schema definitions as `@golemui/gui-*@X.Y.Z`.
|
|
136
|
-
|
|
137
|
-
No LLM calls happen inside this server — every tool is deterministic. The MCP is the
|
|
138
|
-
_grounding layer_ the host IDE's model calls into.
|
|
139
|
-
|
|
140
183
|
## Development
|
|
141
184
|
|
|
142
185
|
### Interactive testing with MCP Inspector
|
|
@@ -174,7 +217,7 @@ Create or edit the project-level MCP config at .mcp.json in the workspace root:
|
|
|
174
217
|
}
|
|
175
218
|
```
|
|
176
219
|
|
|
177
|
-
Then reload the VS Code window (Cmd+Shift+P -> "Developer: Reload Window"). The
|
|
220
|
+
Then reload the VS Code window (Cmd+Shift+P -> "Developer: Reload Window"). The tools will appear in Claude's tool list for this workspace.
|
|
178
221
|
|
|
179
222
|
Remove the entry from .mcp.json when done.
|
|
180
223
|
|
|
@@ -182,6 +225,4 @@ Remove the entry from .mcp.json when done.
|
|
|
182
225
|
|
|
183
226
|
```bash
|
|
184
227
|
npx nx run gui-mcp:vite:test # run the test suite
|
|
185
|
-
npm run sync:mcp-schemas # refresh bundled schemas from libs/gui/shared
|
|
186
|
-
npm run check:mcp-schemas # CI mode — exits non-zero if out of sync
|
|
187
228
|
```
|
package/cli.js
CHANGED
|
@@ -5,7 +5,38 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
6
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
7
|
import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
-
import {
|
|
8
|
+
import { r as resolveDxFramework, f as listDxFactoriesCatalog, b as DX_LIST_FACTORIES_TOOL, g as getDxSpec, a as DX_GET_SPEC_TOOL, d as checkDxCode, D as DX_CHECK_CODE_TOOL } from "./list-dx-factories-CF4ExKyx.js";
|
|
9
|
+
import { v as validateFormDefinition, c as JSON_VALIDATE_FORM_DEFINITION_TOOL, g as generateFromJsonSchema, a as JSON_GENERATE_FROM_SCHEMA_TOOL, d as generateFromOpenapi, J as JSON_GENERATE_FROM_OPENAPI_TOOL, f as getWidgetSpec, b as JSON_GET_WIDGET_SPEC_TOOL, e as getConcept, G as GET_CONCEPT_TOOL } from "./get-concept-Cy3zD1BS.js";
|
|
10
|
+
const DX_INSTRUCTIONS = "Writing GolemUI as DX code (the `gui.*` fluent builder in TypeScript) instead of a JSON definition? GolemUI is not in any model training data, so `gui.*` code is easy to fabricate — do NOT guess the API. FIRST call `dx_list_factories` once: it is the COMPLETE reference — every factory with its signature, a compile-verified example, and its gotchas, plus the cross-cutting patterns and common rules. Its imports + render snippet are tailored to your target framework (" + resolveDxFramework() + ") — use them verbatim; import `gui` ONLY from `@golemui/gui-shared`, never hand-write raw `{ kind, type, path }` widget JSON or cast to `any`. Keep it in context and write your whole form from it; it is self-sufficient for most forms. `dx_get_spec` is only a rare single-factory deep-dive — you usually will not need it, and you do NOT need `json_get_widget_spec` here (that is the JSON surface). Then ALWAYS finish by calling `dx_check_code` with the snippet — it type-checks against the real `@golemui` declarations and returns `{ ok, diagnostics }` (each with a fix `hint` for recognized mistakes). Treat `ok: false` as blocking: apply the fixes and re-check until `ok` is true. Use `dx_check_code` for `gui.*` *code* and `json_validate_form_definition` for a JSON *definition object* — they are not interchangeable.\n\n";
|
|
11
|
+
function defineTool(tool, handler) {
|
|
12
|
+
return { tool, run: (args) => handler(args) };
|
|
13
|
+
}
|
|
14
|
+
function ok(payload) {
|
|
15
|
+
return {
|
|
16
|
+
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }]
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function err(message) {
|
|
20
|
+
return {
|
|
21
|
+
isError: true,
|
|
22
|
+
content: [{ type: "text", text: message }]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const dxTools = [
|
|
26
|
+
// `dx_list_factories` takes no arguments — it defaults the framework from the env, so
|
|
27
|
+
// its handler ignores the (empty) MCP arguments object.
|
|
28
|
+
defineTool(DX_LIST_FACTORIES_TOOL, () => listDxFactoriesCatalog()),
|
|
29
|
+
defineTool(DX_GET_SPEC_TOOL, getDxSpec),
|
|
30
|
+
defineTool(DX_CHECK_CODE_TOOL, checkDxCode)
|
|
31
|
+
];
|
|
32
|
+
const JSON_INSTRUCTIONS = '1. Starting from an existing schema? Use a generator — both return a pre-validated definition, so check the returned `unmapped` list and surface anything left over to the user. For a raw JSON Schema (e.g. an API request body), call `json_generate_from_schema`. For an OpenAPI 3.x spec, call `json_generate_from_openapi`: pass `operation` as "METHOD /path" (e.g. "POST /users") or an exact operationId, plus the spec as a parsed `document` or a `documentUrl` to fetch — it resolves the operation\'s request body, dereferences `$ref`s, and falls back to the operation\'s parameters when there is no request body.\n2. Building or editing by hand? Look up a single widget with `json_get_widget_spec` (its `kind`, `props`, and `validator` shape), and cross-cutting behavior that spans widgets — conditional rendering, per-state prop overrides — with `get_concept`.\n3. ALWAYS finish by calling `json_validate_form_definition`. It checks the definition against the bundled JSON Schemas and returns `{ valid, errors, warnings, expressionWarnings }`. Treat `errors` as blocking: fix them and re-validate until `valid` is true. `warnings` (likely-custom widgets) and `expressionWarnings` (linted reactive expressions) are advisory — surface them, but they do not flip `valid`.\n\n';
|
|
33
|
+
const jsonTools = [
|
|
34
|
+
defineTool(JSON_VALIDATE_FORM_DEFINITION_TOOL, validateFormDefinition),
|
|
35
|
+
defineTool(JSON_GENERATE_FROM_SCHEMA_TOOL, generateFromJsonSchema),
|
|
36
|
+
defineTool(JSON_GENERATE_FROM_OPENAPI_TOOL, generateFromOpenapi),
|
|
37
|
+
defineTool(JSON_GET_WIDGET_SPEC_TOOL, getWidgetSpec)
|
|
38
|
+
];
|
|
39
|
+
const sharedTools = [defineTool(GET_CONCEPT_TOOL, getConcept)];
|
|
9
40
|
function readPackageMeta() {
|
|
10
41
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
11
42
|
for (const candidate of [join(here, "package.json"), join(here, "..", "package.json")]) {
|
|
@@ -18,51 +49,28 @@ function readPackageMeta() {
|
|
|
18
49
|
return { name: "@golemui/gui-mcp", version: "0.0.0" };
|
|
19
50
|
}
|
|
20
51
|
const { name: PKG_NAME, version: PKG_VERSION } = readPackageMeta();
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
GET_CONCEPT_TOOL
|
|
27
|
-
];
|
|
28
|
-
const SERVER_INSTRUCTIONS = 'This server builds and validates GolemUI form definitions — declarative, JSON-serializable forms shaped as `{ form: [...widgets], states?: {...} }`. Its job is to help you produce a form definition that is guaranteed correct before the user pastes it into their codebase.\n\nRecommended workflow:\n1. Starting from an existing schema? Use a generator — both return a pre-validated definition, so check the returned `unmapped` list and surface anything left over to the user. For a raw JSON Schema (e.g. an API request body), call `generate_from_json_schema`. For an OpenAPI 3.x spec, call `generate_from_openapi`: pass `operation` as "METHOD /path" (e.g. "POST /users") or an exact operationId, plus the spec as a parsed `document` or a `documentUrl` to fetch — it resolves the operation\'s request body, dereferences `$ref`s, and falls back to the operation\'s parameters when there is no request body.\n2. Building or editing by hand? Look up a single widget with `get_widget_spec` (its `kind`, `props`, and `validator` shape), and cross-cutting behavior that spans widgets — conditional rendering, per-state prop overrides — with `get_concept`.\n3. ALWAYS finish by calling `validate_form_definition`. It checks the definition against the bundled JSON Schemas and returns `{ valid, errors, warnings, expressionWarnings }`. Treat `errors` as blocking: fix them and re-validate until `valid` is true. `warnings` (likely-custom widgets) and `expressionWarnings` (linted reactive expressions) are advisory — surface them, but they do not flip `valid`.\n\nDo not hand a form definition to the user until `validate_form_definition` reports `valid: true`.';
|
|
52
|
+
const TOOL_ENTRIES = [...jsonTools, ...sharedTools, ...dxTools];
|
|
53
|
+
const TOOL_BY_NAME = new Map(TOOL_ENTRIES.map((e) => [e.tool.name, e]));
|
|
54
|
+
const PREAMBLE = "This server builds and validates GolemUI form definitions — declarative, JSON-serializable forms shaped as `{ form: [...widgets], states?: {...} }`. Its job is to help you produce a form definition that is guaranteed correct before the user pastes it into their codebase.\n\nRecommended workflow:\n";
|
|
55
|
+
const CLOSER = "Do not hand a form definition to the user until `json_validate_form_definition` reports `valid: true`.";
|
|
56
|
+
const SERVER_INSTRUCTIONS = PREAMBLE + JSON_INSTRUCTIONS + DX_INSTRUCTIONS + CLOSER;
|
|
29
57
|
const server = new Server(
|
|
30
58
|
{ name: PKG_NAME, version: PKG_VERSION },
|
|
31
59
|
{ capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS }
|
|
32
60
|
);
|
|
33
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
61
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
62
|
+
tools: TOOL_ENTRIES.map((e) => e.tool)
|
|
63
|
+
}));
|
|
34
64
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
35
65
|
const { name, arguments: args } = request.params;
|
|
66
|
+
const entry = TOOL_BY_NAME.get(name);
|
|
67
|
+
if (!entry) return err(`Unknown tool: ${name}`);
|
|
36
68
|
try {
|
|
37
|
-
|
|
38
|
-
case "validate_form_definition":
|
|
39
|
-
return ok(validateFormDefinition(args));
|
|
40
|
-
case "generate_from_json_schema":
|
|
41
|
-
return ok(generateFromJsonSchema(args));
|
|
42
|
-
case "generate_from_openapi":
|
|
43
|
-
return ok(await generateFromOpenapi(args));
|
|
44
|
-
case "get_widget_spec":
|
|
45
|
-
return ok(getWidgetSpec(args));
|
|
46
|
-
case "get_concept":
|
|
47
|
-
return ok(getConcept(args));
|
|
48
|
-
default:
|
|
49
|
-
return err(`Unknown tool: ${name}`);
|
|
50
|
-
}
|
|
69
|
+
return ok(await entry.run(args));
|
|
51
70
|
} catch (e) {
|
|
52
71
|
return err(e.message);
|
|
53
72
|
}
|
|
54
73
|
});
|
|
55
|
-
function ok(payload) {
|
|
56
|
-
return {
|
|
57
|
-
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }]
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
function err(message) {
|
|
61
|
-
return {
|
|
62
|
-
isError: true,
|
|
63
|
-
content: [{ type: "text", text: message }]
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
74
|
async function main() {
|
|
67
75
|
const transport = new StdioServerTransport();
|
|
68
76
|
await server.connect(transport);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DxCheckResult } from './typecheck';
|
|
2
|
+
export type CheckDxCodeInput = {
|
|
3
|
+
/** A `gui.*` DX snippet (TypeScript). May be a bare array of `gui.inputs.*` items. */
|
|
4
|
+
code: string;
|
|
5
|
+
};
|
|
6
|
+
export type CheckDxCodeResult = DxCheckResult;
|
|
7
|
+
/**
|
|
8
|
+
* Type-check GolemUI DX code against the real `@golemui` declarations and return
|
|
9
|
+
* compiler diagnostics. Async because the TypeScript compiler is loaded lazily.
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkDxCode(input: CheckDxCodeInput): Promise<CheckDxCodeResult>;
|
|
12
|
+
export declare const DX_CHECK_CODE_TOOL: {
|
|
13
|
+
readonly name: "dx_check_code";
|
|
14
|
+
readonly description: string;
|
|
15
|
+
readonly inputSchema: {
|
|
16
|
+
readonly type: "object";
|
|
17
|
+
readonly properties: {
|
|
18
|
+
readonly code: {
|
|
19
|
+
readonly type: "string";
|
|
20
|
+
readonly description: "The GolemUI `gui.*` DX snippet to type-check (TypeScript).";
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
readonly required: readonly ["code"];
|
|
24
|
+
};
|
|
25
|
+
};
|
package/dx/dx-lint.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ExpressionFinding } from '../shared/lint/reactive-expressions';
|
|
2
|
+
import { DxDiagnostic } from './typecheck';
|
|
3
|
+
import type * as TS from 'typescript';
|
|
4
|
+
/**
|
|
5
|
+
* Static lints over a `gui.*` DX snippet that the TypeScript compiler cannot catch.
|
|
6
|
+
*
|
|
7
|
+
* The compiler is the truthful gate for *type* errors, but two real defects slip past
|
|
8
|
+
* it because the code is structurally valid TypeScript:
|
|
9
|
+
*
|
|
10
|
+
* 1. **Misplaced `include`/`exclude` (the silent no-op).** Spreading a factory result
|
|
11
|
+
* and attaching `include`/`exclude`/`disabled`/`readonly` as a SIBLING
|
|
12
|
+
* (`{ ...gui.inputs.x(...), include: { when } }`) compiles — TS suppresses excess-property
|
|
13
|
+
* checks on object literals containing a spread — but the field never sees the
|
|
14
|
+
* condition, so it renders/behaves unconditionally. The arena caught this on a real
|
|
15
|
+
* "hide when" task. Reported as a blocking `diagnostic`.
|
|
16
|
+
*
|
|
17
|
+
* 2. **Reactive-expression quality.** The `when` strings inside `include`/`exclude`/etc.
|
|
18
|
+
* are opaque to the type-checker. We funnel each through the SAME engine the JSON
|
|
19
|
+
* `json_validate_form_definition` path uses ({@link checkReactiveExpression}), so the two
|
|
20
|
+
* surfaces share one set of rules. Reported as non-blocking `expressionWarnings`,
|
|
21
|
+
* mirroring the JSON path.
|
|
22
|
+
*/
|
|
23
|
+
export interface DxLintResult {
|
|
24
|
+
diagnostics: DxDiagnostic[];
|
|
25
|
+
expressionWarnings: ExpressionFinding[];
|
|
26
|
+
}
|
|
27
|
+
export declare function lintDxSnippet(ts: typeof TS, sourceText: string, lineOffset: number): DxLintResult;
|
package/dx/dx-specs.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DX grounding registry — the real `gui.*` builder surface, one entry per factory.
|
|
3
|
+
*
|
|
4
|
+
* GolemUI is not in any model's training data, so a cold model fabricates the
|
|
5
|
+
* `gui.*` API wholesale. This registry is what `dx_get_spec` serves so the model
|
|
6
|
+
* writes the real thing. Every `example` here is **compile-verified against the
|
|
7
|
+
* real `@golemui` types** by `dx-specs.spec.ts` — if an example is wrong, the test
|
|
8
|
+
* suite fails. (Hand-written references are unreliable even with repo access; the
|
|
9
|
+
* compile gate is the cure.)
|
|
10
|
+
*/
|
|
11
|
+
export type DxNamespace = 'inputs' | 'actions' | 'displays' | 'layouts';
|
|
12
|
+
export interface DxSpec {
|
|
13
|
+
/** Factory name, e.g. `textInput`. */
|
|
14
|
+
factory: string;
|
|
15
|
+
namespace: DxNamespace;
|
|
16
|
+
/** Human-readable calling convention. */
|
|
17
|
+
call: string;
|
|
18
|
+
/** A compiling `gui.*` snippet (verified by the suite). */
|
|
19
|
+
example: string;
|
|
20
|
+
/** Authoring notes and gotchas. */
|
|
21
|
+
notes: string[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A cross-cutting authoring pattern that is NOT a single factory — e.g. conditional
|
|
25
|
+
* visibility, which is a common field available on every `gui.*` item. Same compile
|
|
26
|
+
* guarantee as `DxSpec`: every `example` is verified by `dx-specs.spec.ts`.
|
|
27
|
+
*/
|
|
28
|
+
export interface DxPattern {
|
|
29
|
+
/** Short identifier, e.g. `conditionalVisibility`. */
|
|
30
|
+
name: string;
|
|
31
|
+
/** One-line title. */
|
|
32
|
+
title: string;
|
|
33
|
+
/** A compiling `gui.*` snippet (verified by the suite). */
|
|
34
|
+
example: string;
|
|
35
|
+
notes: string[];
|
|
36
|
+
}
|
|
37
|
+
export type DxFramework = 'react' | 'angular' | 'vue' | 'lit' | 'vanilla';
|
|
38
|
+
export declare function resolveDxFramework(): DxFramework;
|
|
39
|
+
export declare const DX_SPECS: Record<string, DxSpec>;
|
|
40
|
+
export declare function listDxFactories(): string[];
|
|
41
|
+
/**
|
|
42
|
+
* One catalog row — enough to WRITE the factory without a follow-up lookup: name, namespace,
|
|
43
|
+
* signature, a compile-verified example, and the authoring gotchas.
|
|
44
|
+
*/
|
|
45
|
+
export interface DxCatalogEntry {
|
|
46
|
+
factory: string;
|
|
47
|
+
namespace: DxNamespace;
|
|
48
|
+
call: string;
|
|
49
|
+
example: string;
|
|
50
|
+
notes: string[];
|
|
51
|
+
}
|
|
52
|
+
export interface DxCatalog {
|
|
53
|
+
/** Every factory, in `inputs → actions → displays → layouts` order — call + example + notes. */
|
|
54
|
+
factories: DxCatalogEntry[];
|
|
55
|
+
/** Cross-cutting patterns (e.g. conditional visibility) — full example + notes, resident once. */
|
|
56
|
+
patterns: DxPattern[];
|
|
57
|
+
/** The cross-cutting authoring note shared by all factories (incl. the validator `type` rule). */
|
|
58
|
+
common: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The whole `gui.*` surface as a SELF-SUFFICIENT reference in one payload: every factory's
|
|
62
|
+
* signature, a compile-verified example, and its gotchas, plus the cross-cutting patterns and the
|
|
63
|
+
* common note. Serves `dx_list_factories`. The agentic intent: the model fetches this ONCE, keeps
|
|
64
|
+
* it resident, and writes most forms from it directly — `dx_get_spec` becomes the rare deep-dive,
|
|
65
|
+
* not a per-factory round-trip. (Richer than a name-only index by design: in a resumed session
|
|
66
|
+
* this is paid once and reused, so front-loading the examples removes mid-task lookups and turns.)
|
|
67
|
+
*/
|
|
68
|
+
export declare function dxCatalog(framework?: DxFramework): DxCatalog;
|
|
69
|
+
export declare function dxCommonNote(framework?: DxFramework): string;
|
|
70
|
+
export declare function dxPatterns(): DxPattern[];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { DxSpec } from './dx-specs';
|
|
2
|
+
export type GetDxSpecInput = {
|
|
3
|
+
/** The `gui.*` factory name, e.g. `textInput`, `dropdown`, `button`. */
|
|
4
|
+
factory: string;
|
|
5
|
+
};
|
|
6
|
+
export type GetDxSpecResult = DxSpec;
|
|
7
|
+
/**
|
|
8
|
+
* Return the real `gui.*` builder signature, a compile-verified example, and authoring notes
|
|
9
|
+
* for a SINGLE factory — the deep-dive lookup. Lean by design: the cross-cutting common note
|
|
10
|
+
* and patterns are NOT re-shipped here (they ride in `dx_list_factories`, fetched once), so a
|
|
11
|
+
* follow-up lookup adds only the factory's own payload to the agent's context.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getDxSpec(input: GetDxSpecInput): GetDxSpecResult;
|
|
14
|
+
export declare const DX_GET_SPEC_TOOL: {
|
|
15
|
+
readonly name: "dx_get_spec";
|
|
16
|
+
readonly description: string;
|
|
17
|
+
readonly inputSchema: {
|
|
18
|
+
readonly type: "object";
|
|
19
|
+
readonly properties: {
|
|
20
|
+
readonly factory: {
|
|
21
|
+
readonly type: "string";
|
|
22
|
+
readonly description: "The gui.* factory name, e.g. \"textInput\", \"dropdown\", \"button\".";
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
readonly required: readonly ["factory"];
|
|
26
|
+
};
|
|
27
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `gui.*` DX half of the server's connect-time guidance (the MCP
|
|
3
|
+
* `initialize.instructions` field). Composed with the JSON half in `cli.ts`. The target
|
|
4
|
+
* framework name is interpolated from the environment at module load, the same as the
|
|
5
|
+
* `dx_list_factories` catalog, so the agent is steered to the correct host wiring.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DX_INSTRUCTIONS: string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { DxCatalog, DxFramework } from './dx-specs';
|
|
2
|
+
export type ListDxFactoriesResult = DxCatalog;
|
|
3
|
+
/**
|
|
4
|
+
* Return the entire `gui.*` DX surface in one payload: every factory name + one-line
|
|
5
|
+
* signature, the cross-cutting pattern names, and the common note. The catalog the agent
|
|
6
|
+
* fetches ONCE before authoring, instead of paying a `dx_get_spec` round-trip per factory.
|
|
7
|
+
*
|
|
8
|
+
* The common note's imports + render snippet are tailored to `framework` (defaults to the
|
|
9
|
+
* `GOLEMUI_FRAMEWORK` env, else react) so the agent is shown the correct host wiring.
|
|
10
|
+
*/
|
|
11
|
+
export declare function listDxFactoriesCatalog(framework?: DxFramework): ListDxFactoriesResult;
|
|
12
|
+
export declare const DX_LIST_FACTORIES_TOOL: {
|
|
13
|
+
readonly name: "dx_list_factories";
|
|
14
|
+
readonly description: string;
|
|
15
|
+
readonly inputSchema: {
|
|
16
|
+
readonly type: "object";
|
|
17
|
+
readonly properties: {};
|
|
18
|
+
};
|
|
19
|
+
};
|
package/dx/tools.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type * as TS from 'typescript';
|
|
2
|
+
/** Build the compiler options that resolve `gui.*` against the real `@golemui` types. */
|
|
3
|
+
export declare function resolveTypeCheckOptions(ts: typeof TS): TS.CompilerOptions;
|
|
4
|
+
/**
|
|
5
|
+
* Compile a single in-memory file against the type graph and return ONLY that file's
|
|
6
|
+
* diagnostics (the host serves {@link SNIPPET_FILE} from memory; every other file is read
|
|
7
|
+
* from disk as usual).
|
|
8
|
+
*/
|
|
9
|
+
export declare function diagnose(ts: typeof TS, code: string, options: TS.CompilerOptions): readonly TS.Diagnostic[];
|
|
10
|
+
export declare function assertTypesAreLive(ts: typeof TS, options: TS.CompilerOptions): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ExpressionFinding } from '../shared/lint/reactive-expressions';
|
|
2
|
+
/**
|
|
3
|
+
* In-process TypeScript type-check of a `gui.*` DX snippet against the real `@golemui`
|
|
4
|
+
* type graph. This is the *truthful* gate: the arena spike proved that regex and even
|
|
5
|
+
* careful human inspection score hallucinated GolemUI code as "valid" — only the compiler
|
|
6
|
+
* tells the truth.
|
|
7
|
+
*
|
|
8
|
+
* `typescript` is imported lazily (see {@link loadTs}) so this module — and the heavy
|
|
9
|
+
* compiler dependency — is only ever loaded when a DX tool is actually called; the JSON
|
|
10
|
+
* validation path never touches it. The fragile part — locating and compiling against the
|
|
11
|
+
* `@golemui` declarations — lives in `./type-graph`; this file only orchestrates a check
|
|
12
|
+
* and turns compiler output into GolemUI-flavored diagnostics.
|
|
13
|
+
*/
|
|
14
|
+
export interface DxDiagnostic {
|
|
15
|
+
/** TypeScript diagnostic code, e.g. 2769. */
|
|
16
|
+
code: number;
|
|
17
|
+
/** Flattened, single-line diagnostic message. */
|
|
18
|
+
message: string;
|
|
19
|
+
/** 1-based line within the submitted snippet (0 if unknown). */
|
|
20
|
+
line: number;
|
|
21
|
+
/** 1-based column within the submitted snippet (0 if unknown). */
|
|
22
|
+
column: number;
|
|
23
|
+
/** A GolemUI-specific fix suggestion, when we recognize the error. */
|
|
24
|
+
hint?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface DxCheckResult {
|
|
27
|
+
/** True when the snippet type-checks clean AND carries no blocking lint diagnostics. */
|
|
28
|
+
ok: boolean;
|
|
29
|
+
diagnostics: DxDiagnostic[];
|
|
30
|
+
/**
|
|
31
|
+
* Non-blocking reactive-expression findings (the `when` strings inside `include`/`exclude`/
|
|
32
|
+
* etc.), linted by the same engine as the JSON path. Advisory — they do not flip `ok`.
|
|
33
|
+
*/
|
|
34
|
+
expressionWarnings: ExpressionFinding[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Type-check a `gui.*` DX snippet against the real `@golemui` types.
|
|
38
|
+
* If the snippet does not import `gui`, a `@golemui/gui-shared` import is prepended,
|
|
39
|
+
* so a bare array of `gui.inputs.*` items can be checked directly.
|
|
40
|
+
*/
|
|
41
|
+
export declare function typeCheckDx(code: string): Promise<DxCheckResult>;
|
|
@@ -1081,6 +1081,11 @@ function lintReactiveExpressions(formDefinition) {
|
|
|
1081
1081
|
walk$1(formDefinition, "", findings);
|
|
1082
1082
|
return findings;
|
|
1083
1083
|
}
|
|
1084
|
+
function checkReactiveExpression(expression, path = "") {
|
|
1085
|
+
const out = [];
|
|
1086
|
+
checkExpression(expression, path, out);
|
|
1087
|
+
return out;
|
|
1088
|
+
}
|
|
1084
1089
|
function walk$1(node, path, out) {
|
|
1085
1090
|
if (node === null || typeof node !== "object") return;
|
|
1086
1091
|
if (Array.isArray(node)) {
|
|
@@ -1370,7 +1375,7 @@ function validateFormDefinition(input) {
|
|
|
1370
1375
|
errors.push({
|
|
1371
1376
|
path: "/",
|
|
1372
1377
|
keyword: "oneOf",
|
|
1373
|
-
message: "Form failed schema validation but no specific error could be localized. The form may contain a widget at a position the form schema does not allow, or a structural shape that our targeted validator missed. Verify each widget against its `
|
|
1378
|
+
message: "Form failed schema validation but no specific error could be localized. The form may contain a widget at a position the form schema does not allow, or a structural shape that our targeted validator missed. Verify each widget against its `json_get_widget_spec` entry."
|
|
1374
1379
|
});
|
|
1375
1380
|
}
|
|
1376
1381
|
return {
|
|
@@ -1381,8 +1386,8 @@ function validateFormDefinition(input) {
|
|
|
1381
1386
|
interpolationWarnings
|
|
1382
1387
|
};
|
|
1383
1388
|
}
|
|
1384
|
-
const
|
|
1385
|
-
name: "
|
|
1389
|
+
const JSON_VALIDATE_FORM_DEFINITION_TOOL = {
|
|
1390
|
+
name: "json_validate_form_definition",
|
|
1386
1391
|
description: "Validate a GolemUI form definition against the bundled JSON Schemas. Use this AFTER generating or modifying a form definition to guarantee it is correct before the user pastes it into their codebase. Returns `{ valid, errors, warnings, expressionWarnings, interpolationWarnings }`. Hard mistakes (typos in widget `type`, missing required props, invalid validator shapes) show up in `errors` and flip `valid` to false. Likely-custom widgets (a `type` value that isn't a built-in and isn't close to one) show up in `warnings` instead — they don't affect `valid`. Reactive expressions (`include.when`, `disabled.when`, etc.) are linted separately into `expressionWarnings`. String interpolation templates (`{{$form.x}}`, `{{$meta.y}}`, expressions like `{{$form.count + 1}}`, etc.) in widget props, and bare expressions inside i18n `params` objects, are linted into `interpolationWarnings`.",
|
|
1387
1392
|
inputSchema: {
|
|
1388
1393
|
type: "object",
|
|
@@ -1765,8 +1770,8 @@ function generateFromJsonSchema(input) {
|
|
|
1765
1770
|
const validation = validateFormDefinition({ formDefinition });
|
|
1766
1771
|
return { formDefinition, unmapped, validation };
|
|
1767
1772
|
}
|
|
1768
|
-
const
|
|
1769
|
-
name: "
|
|
1773
|
+
const JSON_GENERATE_FROM_SCHEMA_TOOL = {
|
|
1774
|
+
name: "json_generate_from_schema",
|
|
1770
1775
|
description: "Generate a GolemUI form definition from a JSON Schema describing the form data shape (typically an API request body or a Zod-derived schema). The result is validated against the GolemUI JSON Schemas before being returned, so it is guaranteed to be syntactically correct. Anything the mapper cannot handle is reported in `unmapped` rather than silently dropped — use that list to surface remaining work to the user.",
|
|
1771
1776
|
inputSchema: {
|
|
1772
1777
|
type: "object",
|
|
@@ -1920,8 +1925,8 @@ function resolveLocalRef(ref, doc) {
|
|
|
1920
1925
|
}
|
|
1921
1926
|
return cur ?? null;
|
|
1922
1927
|
}
|
|
1923
|
-
const
|
|
1924
|
-
name: "
|
|
1928
|
+
const JSON_GENERATE_FROM_OPENAPI_TOOL = {
|
|
1929
|
+
name: "json_generate_from_openapi",
|
|
1925
1930
|
description: 'Generate a GolemUI form for a specific OpenAPI 3.x operation (e.g. "POST /users"). Resolves the operation\'s JSON request body, dereferences `$ref`s, then maps it to a form definition that is validated against the GolemUI JSON Schemas before being returned, so it is guaranteed syntactically correct. Falls back to operation parameters when no request body is present. Anything the mapper cannot handle is reported in `unmapped` rather than silently dropped — use that list to surface remaining work to the user. Pass either a parsed `document` or a `documentUrl` to fetch.',
|
|
1926
1931
|
inputSchema: {
|
|
1927
1932
|
type: "object",
|
|
@@ -2257,9 +2262,9 @@ function getWidgetSpec(input) {
|
|
|
2257
2262
|
notes: NOTES[input.widgetType] ?? []
|
|
2258
2263
|
};
|
|
2259
2264
|
}
|
|
2260
|
-
const
|
|
2261
|
-
name: "
|
|
2262
|
-
description: "Look up the JSON Schema and a minimal working example for a single GolemUI widget. Use this when you need to know which `props` a widget accepts, what `kind` value it uses, or what shape its `validator` takes. Cheaper than dumping the whole API into context.",
|
|
2265
|
+
const JSON_GET_WIDGET_SPEC_TOOL = {
|
|
2266
|
+
name: "json_get_widget_spec",
|
|
2267
|
+
description: "Look up the JSON Schema and a minimal working example for a single GolemUI widget on the **JSON form-definition** surface. Use this when you need to know which `props` a widget accepts, what `kind` value it uses, or what shape its `validator` takes. **If you are writing `gui.*` DX code (TypeScript), you do NOT need this** — use `dx_list_factories` + `dx_get_spec` instead; fetching both surfaces for the same widget is redundant. Cheaper than dumping the whole API into context.",
|
|
2263
2268
|
inputSchema: {
|
|
2264
2269
|
type: "object",
|
|
2265
2270
|
properties: {
|
|
@@ -2749,7 +2754,7 @@ const ICONS_CONCEPT = {
|
|
|
2749
2754
|
"Widgets that support `props.icon`: `button`, `textinput`, `password`, `select`, `currency`, `tags`, `dateInput`, `datePicker`, `rangeCalendar`, `rangedateinput`, `rangedatepicker`.",
|
|
2750
2755
|
'`button` is the only widget with `props.iconPosition`. Allowed values: `"left"` (default) and `"right"`.',
|
|
2751
2756
|
'All icon props support state suffixes: `"icon.<stateName>": "check"` swaps the icon when that state is active. Call `get_concept({ concept: "states" })` for the full state-suffix pattern.',
|
|
2752
|
-
"Do not set `props.icon` on widgets that do not support it — the schema will reject it and `
|
|
2757
|
+
"Do not set `props.icon` on widgets that do not support it — the schema will reject it and `json_validate_form_definition` will report an error."
|
|
2753
2758
|
]
|
|
2754
2759
|
};
|
|
2755
2760
|
const CONCEPTS = {
|
|
@@ -2782,14 +2787,15 @@ const GET_CONCEPT_TOOL = {
|
|
|
2782
2787
|
}
|
|
2783
2788
|
};
|
|
2784
2789
|
export {
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
+
GET_CONCEPT_TOOL as G,
|
|
2791
|
+
JSON_GENERATE_FROM_OPENAPI_TOOL as J,
|
|
2792
|
+
JSON_GENERATE_FROM_SCHEMA_TOOL as a,
|
|
2793
|
+
JSON_GET_WIDGET_SPEC_TOOL as b,
|
|
2794
|
+
JSON_VALIDATE_FORM_DEFINITION_TOOL as c,
|
|
2790
2795
|
generateFromOpenapi as d,
|
|
2791
2796
|
getConcept as e,
|
|
2792
2797
|
getWidgetSpec as f,
|
|
2793
2798
|
generateFromJsonSchema as g,
|
|
2799
|
+
checkReactiveExpression as h,
|
|
2794
2800
|
validateFormDefinition as v
|
|
2795
2801
|
};
|