@nuwax-ai/openui-mcp 0.1.11 → 0.2.0
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 +15 -0
- package/README.md +66 -289
- package/dist/server/artifact-store.d.ts +14 -6
- package/dist/server/artifact-store.d.ts.map +1 -1
- package/dist/server/artifact-store.js +73 -9
- package/dist/server/artifact-store.js.map +1 -1
- package/dist/server/contracts.d.ts +68 -0
- package/dist/server/contracts.d.ts.map +1 -1
- package/dist/server/contracts.js +46 -1
- package/dist/server/contracts.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +4 -6
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/server/project-root.d.ts +11 -0
- package/dist/server/project-root.d.ts.map +1 -0
- package/dist/server/project-root.js +51 -0
- package/dist/server/project-root.js.map +1 -0
- package/dist/server/render-service.d.ts +3 -8
- package/dist/server/render-service.d.ts.map +1 -1
- package/dist/server/render-service.js +21 -26
- package/dist/server/render-service.js.map +1 -1
- package/dist/server/runtime.d.ts +3 -4
- package/dist/server/runtime.d.ts.map +1 -1
- package/dist/server/runtime.js +4 -7
- package/dist/server/runtime.js.map +1 -1
- package/dist/server/stdio.js +8 -9
- package/dist/server/stdio.js.map +1 -1
- package/dist/server/version.d.ts +1 -1
- package/dist/server/version.js +1 -1
- package/dist/web/{sidecar.css → runtime.css} +1 -1
- package/dist/web/{sidecar.js → runtime.js} +7578 -7549
- package/package.json +6 -9
- package/dist/server/config.d.ts +0 -14
- package/dist/server/config.d.ts.map +0 -1
- package/dist/server/config.js +0 -50
- package/dist/server/config.js.map +0 -1
- package/dist/server/http-app.d.ts +0 -11
- package/dist/server/http-app.d.ts.map +0 -1
- package/dist/server/http-app.js +0 -88
- package/dist/server/http-app.js.map +0 -1
- package/dist/server/http-server.d.ts +0 -10
- package/dist/server/http-server.d.ts.map +0 -1
- package/dist/server/http-server.js +0 -30
- package/dist/server/http-server.js.map +0 -1
- package/dist/server/http.d.ts +0 -3
- package/dist/server/http.d.ts.map +0 -1
- package/dist/server/http.js +0 -18
- package/dist/server/http.js.map +0 -1
- package/dist/server/page-template.d.ts +0 -2
- package/dist/server/page-template.d.ts.map +0 -1
- package/dist/server/page-template.js +0 -32
- package/dist/server/page-template.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
- Persist OpenUI artifacts as `data/{artifactId}.openui.json`.
|
|
6
|
+
- Support atomic updates by reusing `artifactId`.
|
|
7
|
+
- Return lightweight `nuwax.openui-ref/v1` results.
|
|
8
|
+
- Replace the localhost page server with a frozen postMessage Runtime bundle.
|
|
9
|
+
- Remove Artifact TTL, sidecar page URLs, and HTTP server configuration.
|
|
10
|
+
|
|
11
|
+
## 0.1.12
|
|
12
|
+
|
|
13
|
+
- Treat sidecar `structuredContent.page.url` as an internal local Runtime
|
|
14
|
+
locator and explicitly prohibit Agents from showing it to users.
|
|
15
|
+
- Return only the Artifact ID in the sidecar tool text result. The Nuwax Host
|
|
16
|
+
derives the authenticated user-facing proxy URL from conversation context.
|
|
17
|
+
|
|
3
18
|
## 0.1.11
|
|
4
19
|
|
|
5
20
|
- Fix dashboard authoring guidance for reactive filters: empty input/select
|
package/README.md
CHANGED
|
@@ -1,179 +1,65 @@
|
|
|
1
1
|
# Nuwax OpenUI MCP
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
- **inline** — rendered directly by the host Renderer by default, with an
|
|
7
|
-
optional OpenUI Runtime iframe mode;
|
|
8
|
-
- **sidecar** — the same Runtime page opened in the preview area or a full page.
|
|
9
|
-
|
|
10
|
-
The project intentionally does not replace the host's chat transport, session
|
|
11
|
-
model, permission system, or tool status UI.
|
|
12
|
-
|
|
13
|
-
## Status
|
|
14
|
-
|
|
15
|
-
This repository contains the first executable foundation:
|
|
16
|
-
|
|
17
|
-
- `nuwax_render_openui` MCP tool;
|
|
18
|
-
- `nuwax.openui/v1` input and structured-result contract;
|
|
19
|
-
- stdio and Streamable HTTP transports;
|
|
20
|
-
- direct Renderer and page Runtime options for inline artifacts;
|
|
21
|
-
- one OpenUI React page Runtime shared by iframe-inline and sidecar artifacts;
|
|
22
|
-
- relative-path and desktop-query transports for proxied Runtime pages;
|
|
23
|
-
- `OPENUI_READY` / `OPENUI_RESIZE` page messages for iframe auto-sizing;
|
|
24
|
-
- localized required validation, including date and date-range values;
|
|
25
|
-
- isolated Runtime styles, independent from the Nuwax host reset stylesheet;
|
|
26
|
-
- source policy, artifact TTL, Host validation, CSP, and tests.
|
|
27
|
-
|
|
28
|
-
The default artifact store is in-memory. Production deployments should provide
|
|
29
|
-
a durable, tenant-aware `ArtifactStore` and authentication at the edge.
|
|
3
|
+
`@nuwax-ai/openui-mcp` provides OpenUI authoring guidance, schema resources,
|
|
4
|
+
validation, and durable artifact generation for Nuwax Agent sessions.
|
|
30
5
|
|
|
31
6
|
## Architecture
|
|
32
7
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
└─ MCP call: nuwax_render_openui
|
|
36
|
-
└─ validate + persist artifact
|
|
37
|
-
├─ structuredContent → host discovers the artifact
|
|
38
|
-
├─ inline → host Renderer (default)
|
|
39
|
-
└─ shared Runtime page
|
|
40
|
-
├─ inline iframe (optional)
|
|
41
|
-
└─ sidecar preview / full page
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
`presentation.mode` controls where the host presents the Artifact; it does not
|
|
45
|
-
force an inline rendering technology. PC hosts should default inline Artifacts
|
|
46
|
-
to the direct Renderer and may explicitly select the iframe Runtime for stronger
|
|
47
|
-
style isolation or cross-client page reuse. `GET /openui/pages/:id` is available
|
|
48
|
-
for both inline and sidecar artifacts. For backward compatibility, only sidecar
|
|
49
|
-
structured results currently contain `artifact.page.url`; an iframe-inline host
|
|
50
|
-
builds its trusted page URL from its configured proxy route and `artifactId`.
|
|
51
|
-
|
|
52
|
-
OpenUI runtime queries and mutations are intentionally not proxied in the first
|
|
53
|
-
release. They must be added behind a host-controlled MCP proxy with tenant,
|
|
54
|
-
conversation, artifact, allowlist, permission, and audit checks.
|
|
55
|
-
|
|
56
|
-
## Requirements
|
|
57
|
-
|
|
58
|
-
- Node.js 20+
|
|
59
|
-
- pnpm 10+
|
|
60
|
-
|
|
61
|
-
## Install and verify
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
pnpm install
|
|
65
|
-
pnpm verify
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Install the published package in a host project:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
npm install @nuwax-ai/openui-mcp
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Run over stdio
|
|
8
|
+
The MCP server does not host pages. It writes OpenUI data into the active
|
|
9
|
+
project and returns a lightweight reference:
|
|
75
10
|
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
|
|
11
|
+
```text
|
|
12
|
+
nuwax_render_openui
|
|
13
|
+
-> validate OpenUI Lang
|
|
14
|
+
-> data/{artifactId}.openui.json
|
|
15
|
+
-> nuwax.openui-ref/v1
|
|
79
16
|
```
|
|
80
17
|
|
|
81
|
-
|
|
18
|
+
Nuwax PC Web loads the data file and renders it with the frozen static runtime
|
|
19
|
+
at `/openui-runtime/index.html`. Inline, sidecar, and file preview all use that
|
|
20
|
+
same runtime.
|
|
82
21
|
|
|
83
|
-
|
|
84
|
-
{
|
|
85
|
-
"mcpServers": {
|
|
86
|
-
"nuwax-openui": {
|
|
87
|
-
"command": "node",
|
|
88
|
-
"args": ["/absolute/path/to/nuwax-openui-mcp/dist/server/stdio.js"],
|
|
89
|
-
"env": {
|
|
90
|
-
"NUWAX_OPENUI_BASE_URL": "http://127.0.0.1:8787"
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
The stdio process starts the sidecar HTTP server by default and both transports
|
|
98
|
-
share the same in-memory artifact store. Set
|
|
99
|
-
`NUWAX_OPENUI_SIDECAR_SERVER_ENABLED=false` only when another process owns the
|
|
100
|
-
page Runtime service. Page-based inline rendering also needs this service.
|
|
22
|
+
## Installation
|
|
101
23
|
|
|
102
|
-
|
|
103
|
-
|
|
24
|
+
Configure the server as a session-scoped stdio MCP so it inherits the current
|
|
25
|
+
project directory:
|
|
104
26
|
|
|
105
27
|
```json
|
|
106
28
|
{
|
|
107
29
|
"mcpServers": {
|
|
108
30
|
"nuwax-openui": {
|
|
109
31
|
"command": "npx",
|
|
110
|
-
"args": ["-y", "@nuwax-ai/openui-mcp@0.
|
|
111
|
-
"env": {
|
|
112
|
-
"NUWAX_OPENUI_HOST": "127.0.0.1",
|
|
113
|
-
"NUWAX_OPENUI_PORT": "8787",
|
|
114
|
-
"NUWAX_OPENUI_BASE_URL": "http://127.0.0.1:8787",
|
|
115
|
-
"NUWAX_OPENUI_ALLOWED_HOSTS": "127.0.0.1,localhost"
|
|
116
|
-
},
|
|
117
|
-
"enabled": true,
|
|
118
|
-
"persistent": true
|
|
32
|
+
"args": ["-y", "@nuwax-ai/openui-mcp@0.2.0"]
|
|
119
33
|
}
|
|
120
34
|
}
|
|
121
35
|
}
|
|
122
36
|
```
|
|
123
37
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
## Run over Streamable HTTP
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
cp .env.example .env
|
|
132
|
-
pnpm build
|
|
133
|
-
pnpm start
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
Endpoints:
|
|
137
|
-
|
|
138
|
-
| Endpoint | Purpose |
|
|
139
|
-
| --------------------------- | ---------------------------------- |
|
|
140
|
-
| `POST /mcp` | MCP Streamable HTTP |
|
|
141
|
-
| `GET /healthz` | Health check |
|
|
142
|
-
| `GET /openui/artifacts/:id` | Artifact document for the renderer |
|
|
143
|
-
| `GET /openui/pages/:id` | Shared inline/sidecar Runtime page |
|
|
144
|
-
| `GET /openui/assets/*` | Runtime JavaScript and CSS |
|
|
145
|
-
|
|
146
|
-
### Proxied page transports
|
|
147
|
-
|
|
148
|
-
The default page uses relative path assets and Artifact lookup:
|
|
38
|
+
Do not configure it as a persistent/global MCP. If the host cannot provide the
|
|
39
|
+
project as the process working directory or an MCP Root, set
|
|
40
|
+
`NUWAX_OPENUI_PROJECT_ROOT` explicitly.
|
|
149
41
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
├─ ../assets/sidecar.js
|
|
154
|
-
└─ ../artifacts/{artifactId}
|
|
155
|
-
```
|
|
42
|
+
The file repository is initialized lazily on the first render call. This avoids
|
|
43
|
+
creating a `data/` directory when a client starts the server only to discover
|
|
44
|
+
its tool list.
|
|
156
45
|
|
|
157
|
-
|
|
158
|
-
`?transport=desktop-query`. The generated page keeps all subsequent requests on
|
|
159
|
-
the same conversation-scoped URL and changes only the query:
|
|
46
|
+
## Tools and resources
|
|
160
47
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
48
|
+
- `nuwax_render_openui`: creates or updates an Artifact file.
|
|
49
|
+
- `nuwax_get_openui_reference`: returns the authoring guide or schema.
|
|
50
|
+
- `nuwax://openui/schema/v0.5`: renderer-generated component schema.
|
|
51
|
+
- `nuwax://openui/authoring-guide/v0.5`: syntax and examples.
|
|
52
|
+
- `nuwax_openui_authoring`: reusable authoring prompt.
|
|
166
53
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
authenticated context and must not accept an arbitrary upstream URL.
|
|
54
|
+
Call `nuwax_get_openui_reference` before producing complex forms, charts, or
|
|
55
|
+
dashboards.
|
|
170
56
|
|
|
171
|
-
##
|
|
57
|
+
## Creating an Artifact
|
|
172
58
|
|
|
173
59
|
```json
|
|
174
60
|
{
|
|
175
61
|
"schemaVersion": "nuwax.openui/v1",
|
|
176
|
-
"title": "
|
|
62
|
+
"title": "Deployment status",
|
|
177
63
|
"presentation": {
|
|
178
64
|
"mode": "inline",
|
|
179
65
|
"autoOpen": false
|
|
@@ -181,164 +67,55 @@ authenticated context and must not accept an arbitrary upstream URL.
|
|
|
181
67
|
"document": {
|
|
182
68
|
"language": "openui-lang",
|
|
183
69
|
"specVersion": "0.5",
|
|
184
|
-
"source": "root = Stack([title])\ntitle = TextContent(\"
|
|
185
|
-
},
|
|
186
|
-
"bindings": {
|
|
187
|
-
"tools": []
|
|
70
|
+
"source": "root = Stack([title])\ntitle = TextContent(\"Ready\", \"large-heavy\")"
|
|
188
71
|
},
|
|
189
|
-
"
|
|
190
|
-
|
|
191
|
-
}
|
|
72
|
+
"bindings": { "tools": [] },
|
|
73
|
+
"fallback": { "markdown": "Deployment is ready." }
|
|
192
74
|
}
|
|
193
75
|
```
|
|
194
76
|
|
|
195
|
-
The
|
|
196
|
-
`structuredContent`. Hosts must identify OpenUI results by all three fields:
|
|
77
|
+
The response is a `nuwax.openui-ref/v1` pointing to:
|
|
197
78
|
|
|
198
79
|
```text
|
|
199
|
-
|
|
200
|
-
type = nuwax.openui
|
|
201
|
-
schemaVersion = nuwax.openui/v1
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
Do not infer UI from arbitrary MCP tool results.
|
|
205
|
-
|
|
206
|
-
## Agent authoring guidance
|
|
207
|
-
|
|
208
|
-
The server publishes the DSL contract through multiple MCP capabilities so an
|
|
209
|
-
Agent does not need to guess syntax or inspect installed package files:
|
|
210
|
-
|
|
211
|
-
| Capability | Name / URI | Purpose |
|
|
212
|
-
| ---------- | ------------------------------------- | ---------------------------------------------------------------------------- |
|
|
213
|
-
| Tool | `nuwax_get_openui_reference` | Returns the generated authoring guide or complete DSL JSON Schema |
|
|
214
|
-
| Prompt | `nuwax_openui_authoring` | Starts an authoring flow with a `basic`, `dashboard`, `form`, or `all` focus |
|
|
215
|
-
| Resource | `nuwax://openui/schema/v0.5` | Complete JSON Schema generated from the renderer's current component library |
|
|
216
|
-
| Resource | `nuwax://openui/authoring-guide/v0.5` | Complete generated OpenUI Lang authoring guide |
|
|
217
|
-
|
|
218
|
-
`nuwax_render_openui` also includes trigger guidance and a minimal valid example
|
|
219
|
-
in its tool description and input schema. Agents should use it when the user
|
|
220
|
-
asks for a visual card, dashboard, chart, table, report, form, status panel, or
|
|
221
|
-
other structured interface even if the user does not explicitly mention
|
|
222
|
-
OpenUI.
|
|
223
|
-
|
|
224
|
-
For a complex interface, call `nuwax_get_openui_reference` with `format=guide`
|
|
225
|
-
and the closest profile before rendering. Clients that only expose MCP tools
|
|
226
|
-
can also retrieve the complete DSL schema with `format=schema`. OpenUI Lang is
|
|
227
|
-
assignment-based and is not XML, HTML, or JSX:
|
|
228
|
-
|
|
229
|
-
```text
|
|
230
|
-
root = Stack([title, status])
|
|
231
|
-
title = TextContent("Deployment", "large-heavy")
|
|
232
|
-
status = Callout("success", "Ready", "Deployment completed successfully.")
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
The JSON Schema and guide are generated from the exact OpenUI renderer library
|
|
236
|
-
used by this package, preventing the authoring contract from drifting away from
|
|
237
|
-
runtime behavior.
|
|
238
|
-
|
|
239
|
-
## Host integration
|
|
240
|
-
|
|
241
|
-
PC Web inline supports two rendering strategies. The direct Renderer is the
|
|
242
|
-
default because it has no local Runtime/network dependency and integrates with
|
|
243
|
-
the existing conversation lifecycle:
|
|
244
|
-
|
|
245
|
-
```tsx
|
|
246
|
-
<Renderer
|
|
247
|
-
library={openuiLibrary}
|
|
248
|
-
response={artifact.document.source}
|
|
249
|
-
isStreaming={false}
|
|
250
|
-
/>
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
The host may explicitly select iframe mode for isolation or page-runtime
|
|
254
|
-
testing:
|
|
255
|
-
|
|
256
|
-
```tsx
|
|
257
|
-
<ToolProcessShell header={existingToolBar}>
|
|
258
|
-
<iframe
|
|
259
|
-
src={resolveTrustedOpenUiPageUrl(artifact.artifactId)}
|
|
260
|
-
sandbox="allow-scripts"
|
|
261
|
-
title={artifact.title}
|
|
262
|
-
/>
|
|
263
|
-
</ToolProcessShell>
|
|
80
|
+
data/{artifactId}.openui.json
|
|
264
81
|
```
|
|
265
82
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
### Page bridge and automatic height
|
|
83
|
+
Pass the same `artifactId` on a later call to atomically replace the Artifact.
|
|
84
|
+
The original `createdAt` is retained while `updatedAt` and the document digest
|
|
85
|
+
are refreshed.
|
|
271
86
|
|
|
272
|
-
|
|
87
|
+
## File contract
|
|
273
88
|
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"type": "nuwax.openui-file",
|
|
92
|
+
"schemaVersion": "nuwax.openui-file/v1",
|
|
93
|
+
"artifactId": "550e8400-e29b-41d4-a716-446655440000",
|
|
94
|
+
"title": "Deployment status",
|
|
95
|
+
"presentation": { "mode": "inline", "autoOpen": false },
|
|
96
|
+
"document": {
|
|
97
|
+
"language": "openui-lang",
|
|
98
|
+
"specVersion": "0.5",
|
|
99
|
+
"source": "root = Stack([])",
|
|
100
|
+
"digest": "sha256:..."
|
|
101
|
+
},
|
|
102
|
+
"bindings": { "tools": [] },
|
|
103
|
+
"fallback": { "markdown": "" },
|
|
104
|
+
"createdAt": "2026-07-22T00:00:00.000Z",
|
|
105
|
+
"updatedAt": "2026-07-22T00:00:00.000Z"
|
|
106
|
+
}
|
|
287
107
|
```
|
|
288
108
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
can update the iframe height. The host must validate `event.source`, the trusted
|
|
292
|
-
Runtime origin, `protocolVersion`, and `artifactId` before applying the height.
|
|
293
|
-
It should also clamp the height and provide an expand/scroll fallback for large
|
|
294
|
-
documents.
|
|
295
|
-
|
|
296
|
-
The v1 bridge currently reports readiness and size only. Host context, actions,
|
|
297
|
-
nonce/sequence replay protection, and native/mobile WebView bridges are planned
|
|
298
|
-
extensions and must not be assumed by clients yet.
|
|
299
|
-
|
|
300
|
-
### Runtime styles, validation, and locale
|
|
301
|
-
|
|
302
|
-
The page Runtime imports the official `@openuidev/react-ui` stylesheet inside
|
|
303
|
-
its own document. This prevents host rules such as `button { color: inherit }`
|
|
304
|
-
from overriding iframe-rendered OpenUI button colors. A direct Renderer shares
|
|
305
|
-
the host document and must load the official layered stylesheet plus scoped,
|
|
306
|
-
unlayered compatibility overrides for host reset rules.
|
|
307
|
-
|
|
308
|
-
The page Runtime replaces the built-in `required` validator to correctly accept
|
|
309
|
-
`Date`, date-range objects, wrapped values, and selected checkbox maps. Required
|
|
310
|
-
messages follow `navigator.language` for English, Simplified Chinese,
|
|
311
|
-
Traditional Chinese, and Japanese. Unknown locales fall back to English. A host
|
|
312
|
-
using the direct Renderer must install the equivalent validator integration in
|
|
313
|
-
its own JavaScript context; Nuwax PC Web does this through its i18n runtime.
|
|
314
|
-
|
|
315
|
-
## Security model
|
|
316
|
-
|
|
317
|
-
- OpenUI document size and line count are bounded.
|
|
318
|
-
- Script-like source patterns are rejected before persistence.
|
|
319
|
-
- Sidecar URLs are generated by this service, never accepted from the model.
|
|
320
|
-
- The HTTP server validates `Host` to reduce DNS rebinding exposure.
|
|
321
|
-
- Sidecar responses use CSP and no-store caching. Set
|
|
322
|
-
`NUWAX_OPENUI_FRAME_ANCESTORS` to the exact Nuwax origins that may embed the
|
|
323
|
-
page; the default permits only same-origin framing.
|
|
324
|
-
- Runtime MCP bindings are explicit and cannot contain wildcards.
|
|
325
|
-
- Mutations are data only in this contract; execution requires a separate,
|
|
326
|
-
permission-aware host proxy.
|
|
327
|
-
|
|
328
|
-
This foundation is not a substitute for authentication. A production Nuwax
|
|
329
|
-
deployment must bind every artifact to user, tenant, conversation, message, and
|
|
330
|
-
tool-call context.
|
|
109
|
+
Artifacts have no TTL. Their lifetime follows the project files and they can be
|
|
110
|
+
reviewed and versioned with Git.
|
|
331
111
|
|
|
332
112
|
## Development
|
|
333
113
|
|
|
334
114
|
```bash
|
|
335
|
-
pnpm
|
|
336
|
-
pnpm
|
|
337
|
-
pnpm typecheck
|
|
338
|
-
pnpm test
|
|
339
|
-
pnpm build
|
|
115
|
+
pnpm install
|
|
116
|
+
pnpm verify
|
|
340
117
|
```
|
|
341
118
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
119
|
+
The web build produces `dist/web/runtime.js` and `dist/web/runtime.css`. In the
|
|
120
|
+
Nuwax repository, `scripts/sync-openui-runtime.sh` copies those assets into
|
|
121
|
+
`public/openui-runtime/`.
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type OpenUiFile } from './contracts.js';
|
|
2
2
|
export interface ArtifactStore {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
initialize(): Promise<void>;
|
|
4
|
+
get(artifactId: string): Promise<OpenUiFile | undefined>;
|
|
5
|
+
put(artifact: OpenUiFile): Promise<'created' | 'updated'>;
|
|
5
6
|
delete(artifactId: string): Promise<boolean>;
|
|
6
7
|
}
|
|
7
|
-
export
|
|
8
|
+
export type ProjectRootResolver = () => Promise<string>;
|
|
9
|
+
export declare class FileArtifactStore implements ArtifactStore {
|
|
10
|
+
private readonly resolveProjectRoot;
|
|
8
11
|
private readonly artifacts;
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
private initialization;
|
|
13
|
+
constructor(resolveProjectRoot: ProjectRootResolver);
|
|
14
|
+
initialize(): Promise<void>;
|
|
15
|
+
get(artifactId: string): Promise<OpenUiFile | undefined>;
|
|
16
|
+
put(artifact: OpenUiFile): Promise<'created' | 'updated'>;
|
|
11
17
|
delete(artifactId: string): Promise<boolean>;
|
|
18
|
+
private getDataDir;
|
|
19
|
+
private getArtifactPath;
|
|
12
20
|
}
|
|
13
21
|
//# sourceMappingURL=artifact-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-store.d.ts","sourceRoot":"","sources":["../../src/artifact-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"artifact-store.d.ts","sourceRoot":"","sources":["../../src/artifact-store.ts"],"names":[],"mappings":"AAWA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEnE,MAAM,WAAW,aAAa;IAC5B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACzD,GAAG,CAAC,QAAQ,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAC1D,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9C;AAED,MAAM,MAAM,mBAAmB,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;AAIxD,qBAAa,iBAAkB,YAAW,aAAa;IAIzC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAH/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAC3D,OAAO,CAAC,cAAc,CAA4B;gBAErB,kBAAkB,EAAE,mBAAmB;IAE9D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B3B,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAkBxD,GAAG,CAAC,QAAQ,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAmBzD,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YAOpC,UAAU;YAIV,eAAe;CAI9B"}
|
|
@@ -1,20 +1,84 @@
|
|
|
1
|
-
|
|
1
|
+
import { mkdir, readdir, readFile, rename, rm, writeFile, } from 'node:fs/promises';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { openUiFileSchema } from './contracts.js';
|
|
5
|
+
const ARTIFACT_FILE_PATTERN = /^([0-9a-f-]{36})\.openui\.json$/;
|
|
6
|
+
export class FileArtifactStore {
|
|
7
|
+
resolveProjectRoot;
|
|
2
8
|
artifacts = new Map();
|
|
9
|
+
initialization;
|
|
10
|
+
constructor(resolveProjectRoot) {
|
|
11
|
+
this.resolveProjectRoot = resolveProjectRoot;
|
|
12
|
+
}
|
|
13
|
+
async initialize() {
|
|
14
|
+
this.initialization ??= (async () => {
|
|
15
|
+
const dataDir = await this.getDataDir();
|
|
16
|
+
await mkdir(dataDir, { recursive: true });
|
|
17
|
+
const files = await readdir(dataDir, { withFileTypes: true });
|
|
18
|
+
await Promise.all(files.map(async (entry) => {
|
|
19
|
+
if (!entry.isFile() || !ARTIFACT_FILE_PATTERN.test(entry.name))
|
|
20
|
+
return;
|
|
21
|
+
try {
|
|
22
|
+
const value = JSON.parse(await readFile(path.join(dataDir, entry.name), 'utf8'));
|
|
23
|
+
const artifact = openUiFileSchema.parse(value);
|
|
24
|
+
if (entry.name !== `${artifact.artifactId}.openui.json`)
|
|
25
|
+
return;
|
|
26
|
+
this.artifacts.set(artifact.artifactId, artifact);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
process.stderr.write(`[nuwax-openui] Skipping invalid artifact ${entry.name}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
30
|
+
}
|
|
31
|
+
}));
|
|
32
|
+
})();
|
|
33
|
+
return this.initialization;
|
|
34
|
+
}
|
|
3
35
|
async get(artifactId) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
36
|
+
await this.initialize();
|
|
37
|
+
const cached = this.artifacts.get(artifactId);
|
|
38
|
+
if (cached)
|
|
39
|
+
return structuredClone(cached);
|
|
40
|
+
try {
|
|
41
|
+
const raw = await readFile(await this.getArtifactPath(artifactId), 'utf8');
|
|
42
|
+
const artifact = openUiFileSchema.parse(JSON.parse(raw));
|
|
43
|
+
this.artifacts.set(artifactId, artifact);
|
|
44
|
+
return structuredClone(artifact);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error.code === 'ENOENT')
|
|
48
|
+
return undefined;
|
|
49
|
+
throw error;
|
|
10
50
|
}
|
|
11
|
-
return structuredClone(artifact);
|
|
12
51
|
}
|
|
13
52
|
async put(artifact) {
|
|
53
|
+
await this.initialize();
|
|
54
|
+
const validated = openUiFileSchema.parse(artifact);
|
|
55
|
+
const destination = await this.getArtifactPath(validated.artifactId);
|
|
56
|
+
const existed = Boolean(await this.get(validated.artifactId));
|
|
57
|
+
const temporary = `${destination}.${process.pid}.${randomUUID()}.tmp`;
|
|
58
|
+
await mkdir(path.dirname(destination), { recursive: true });
|
|
59
|
+
await writeFile(temporary, `${JSON.stringify(validated, null, 2)}\n`, {
|
|
60
|
+
encoding: 'utf8',
|
|
61
|
+
flag: 'wx',
|
|
62
|
+
});
|
|
63
|
+
await rename(temporary, destination).catch(async (error) => {
|
|
64
|
+
await rm(temporary, { force: true });
|
|
65
|
+
throw error;
|
|
66
|
+
});
|
|
14
67
|
this.artifacts.set(artifact.artifactId, structuredClone(artifact));
|
|
68
|
+
return existed ? 'updated' : 'created';
|
|
15
69
|
}
|
|
16
70
|
async delete(artifactId) {
|
|
17
|
-
|
|
71
|
+
await this.initialize();
|
|
72
|
+
const existed = this.artifacts.delete(artifactId);
|
|
73
|
+
await rm(await this.getArtifactPath(artifactId), { force: true });
|
|
74
|
+
return existed;
|
|
75
|
+
}
|
|
76
|
+
async getDataDir() {
|
|
77
|
+
return path.join(await this.resolveProjectRoot(), 'data');
|
|
78
|
+
}
|
|
79
|
+
async getArtifactPath(artifactId) {
|
|
80
|
+
const parsedId = openUiFileSchema.shape.artifactId.parse(artifactId);
|
|
81
|
+
return path.join(await this.getDataDir(), `${parsedId}.openui.json`);
|
|
18
82
|
}
|
|
19
83
|
}
|
|
20
84
|
//# sourceMappingURL=artifact-store.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-store.js","sourceRoot":"","sources":["../../src/artifact-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"artifact-store.js","sourceRoot":"","sources":["../../src/artifact-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const OPENUI_SCHEMA_VERSION: "nuwax.openui/v1";
|
|
3
|
+
export declare const OPENUI_FILE_SCHEMA_VERSION: "nuwax.openui-file/v1";
|
|
4
|
+
export declare const OPENUI_REF_SCHEMA_VERSION: "nuwax.openui-ref/v1";
|
|
3
5
|
export declare const OPENUI_LANG_VERSION: "0.5";
|
|
4
6
|
export declare const OPENUI_TOOL_NAME: "nuwax_render_openui";
|
|
5
7
|
export declare const OPENUI_REFERENCE_TOOL_NAME: "nuwax_get_openui_reference";
|
|
@@ -27,6 +29,7 @@ declare const bindingSchema: z.ZodObject<{
|
|
|
27
29
|
}>;
|
|
28
30
|
}, z.core.$strip>;
|
|
29
31
|
export declare const renderOpenUiInputSchema: z.ZodObject<{
|
|
32
|
+
artifactId: z.ZodOptional<z.ZodString>;
|
|
30
33
|
schemaVersion: z.ZodLiteral<"nuwax.openui/v1">;
|
|
31
34
|
title: z.ZodString;
|
|
32
35
|
presentation: z.ZodObject<{
|
|
@@ -104,9 +107,74 @@ export declare const openUiArtifactSchema: z.ZodObject<{
|
|
|
104
107
|
createdAt: z.ZodString;
|
|
105
108
|
expiresAt: z.ZodString;
|
|
106
109
|
}, z.core.$strip>;
|
|
110
|
+
export declare const openUiFileSchema: z.ZodObject<{
|
|
111
|
+
type: z.ZodLiteral<"nuwax.openui-file">;
|
|
112
|
+
schemaVersion: z.ZodLiteral<"nuwax.openui-file/v1">;
|
|
113
|
+
artifactId: z.ZodString;
|
|
114
|
+
title: z.ZodString;
|
|
115
|
+
presentation: z.ZodObject<{
|
|
116
|
+
mode: z.ZodEnum<{
|
|
117
|
+
inline: "inline";
|
|
118
|
+
sidecar: "sidecar";
|
|
119
|
+
}>;
|
|
120
|
+
autoOpen: z.ZodBoolean;
|
|
121
|
+
preferredWidth: z.ZodOptional<z.ZodEnum<{
|
|
122
|
+
compact: "compact";
|
|
123
|
+
normal: "normal";
|
|
124
|
+
wide: "wide";
|
|
125
|
+
}>>;
|
|
126
|
+
}, z.core.$strip>;
|
|
127
|
+
document: z.ZodObject<{
|
|
128
|
+
language: z.ZodLiteral<"openui-lang">;
|
|
129
|
+
specVersion: z.ZodLiteral<"0.5">;
|
|
130
|
+
source: z.ZodString;
|
|
131
|
+
digest: z.ZodString;
|
|
132
|
+
}, z.core.$strip>;
|
|
133
|
+
bindings: z.ZodObject<{
|
|
134
|
+
tools: z.ZodArray<z.ZodObject<{
|
|
135
|
+
serverId: z.ZodString;
|
|
136
|
+
toolName: z.ZodString;
|
|
137
|
+
access: z.ZodEnum<{
|
|
138
|
+
query: "query";
|
|
139
|
+
mutation: "mutation";
|
|
140
|
+
}>;
|
|
141
|
+
}, z.core.$strip>>;
|
|
142
|
+
}, z.core.$strip>;
|
|
143
|
+
fallback: z.ZodObject<{
|
|
144
|
+
markdown: z.ZodString;
|
|
145
|
+
}, z.core.$strip>;
|
|
146
|
+
createdAt: z.ZodString;
|
|
147
|
+
updatedAt: z.ZodString;
|
|
148
|
+
}, z.core.$strip>;
|
|
149
|
+
export declare const openUiArtifactRefSchema: z.ZodObject<{
|
|
150
|
+
type: z.ZodLiteral<"nuwax.openui-ref">;
|
|
151
|
+
schemaVersion: z.ZodLiteral<"nuwax.openui-ref/v1">;
|
|
152
|
+
artifactId: z.ZodString;
|
|
153
|
+
path: z.ZodString;
|
|
154
|
+
title: z.ZodString;
|
|
155
|
+
presentation: z.ZodObject<{
|
|
156
|
+
mode: z.ZodEnum<{
|
|
157
|
+
inline: "inline";
|
|
158
|
+
sidecar: "sidecar";
|
|
159
|
+
}>;
|
|
160
|
+
autoOpen: z.ZodBoolean;
|
|
161
|
+
preferredWidth: z.ZodOptional<z.ZodEnum<{
|
|
162
|
+
compact: "compact";
|
|
163
|
+
normal: "normal";
|
|
164
|
+
wide: "wide";
|
|
165
|
+
}>>;
|
|
166
|
+
}, z.core.$strip>;
|
|
167
|
+
digest: z.ZodString;
|
|
168
|
+
operation: z.ZodEnum<{
|
|
169
|
+
created: "created";
|
|
170
|
+
updated: "updated";
|
|
171
|
+
}>;
|
|
172
|
+
}, z.core.$strip>;
|
|
107
173
|
export type RenderOpenUiInput = z.infer<typeof renderOpenUiInputSchema>;
|
|
108
174
|
export type OpenUiReferenceInput = z.infer<typeof openUiReferenceInputSchema>;
|
|
109
175
|
export type OpenUiArtifact = z.infer<typeof openUiArtifactSchema>;
|
|
176
|
+
export type OpenUiFile = z.infer<typeof openUiFileSchema>;
|
|
177
|
+
export type OpenUiArtifactRef = z.infer<typeof openUiArtifactRefSchema>;
|
|
110
178
|
export type OpenUiBinding = z.infer<typeof bindingSchema>;
|
|
111
179
|
export {};
|
|
112
180
|
//# sourceMappingURL=contracts.d.ts.map
|