@xpert-ai/plugin-live-dashboard 0.4.0 → 0.5.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/.xpertai-plugin/plugin.json +1 -1
- package/README.md +4 -0
- package/dist/lib/agent.schema.d.ts +179 -25
- package/dist/lib/agent.schema.js +10 -9
- package/dist/lib/archive.service.d.ts +145 -0
- package/dist/lib/archive.service.js +133 -0
- package/dist/lib/content.provider.d.ts +1 -1
- package/dist/lib/dashboard-archive.d.ts +70 -0
- package/dist/lib/dashboard-archive.js +118 -0
- package/dist/lib/dashboard-sources.d.ts +69 -0
- package/dist/lib/dashboard-sources.js +37 -0
- package/dist/lib/dashboard-view.schema.d.ts +503 -88
- package/dist/lib/dashboard-view.schema.js +2 -1
- package/dist/lib/dashboard.schema.d.ts +379 -58
- package/dist/lib/dashboard.schema.js +18 -1
- package/dist/lib/dashboard.service.d.ts +72 -17
- package/dist/lib/dashboard.service.js +21 -3
- package/dist/lib/document-package.d.ts +19 -4
- package/dist/lib/editing-patch.d.ts +3 -0
- package/dist/lib/editing-patch.js +2 -1
- package/dist/lib/editing-session.d.ts +4 -4
- package/dist/lib/editing.d.ts +202 -19
- package/dist/lib/editing.js +5 -2
- package/dist/lib/html-validation-feedback.d.ts +7 -0
- package/dist/lib/html-validation-feedback.js +19 -0
- package/dist/lib/html-validation.js +2 -1
- package/dist/lib/inspection-host.d.ts +7 -0
- package/dist/lib/inspection-host.js +48 -0
- package/dist/lib/inspection-runtime.d.ts +2 -0
- package/dist/lib/inspection-runtime.js +77 -0
- package/dist/lib/json-input.d.ts +4 -0
- package/dist/lib/json-input.js +21 -0
- package/dist/lib/middleware.js +3 -2
- package/dist/lib/plugin.js +2 -1
- package/dist/lib/presentation.provider.d.ts +24 -9
- package/dist/lib/presentation.provider.js +2 -1
- package/dist/lib/projects.schema.d.ts +14 -0
- package/dist/lib/projects.schema.js +2 -1
- package/dist/lib/projects.service.d.ts +2 -0
- package/dist/lib/projects.service.js +10 -0
- package/dist/lib/source-executions.d.ts +196 -0
- package/dist/lib/source-executions.js +25 -0
- package/dist/lib/source-validation.d.ts +2 -0
- package/dist/lib/source-validation.js +21 -0
- package/dist/lib/view.provider.d.ts +211 -12
- package/dist/lib/view.provider.js +43 -9
- package/dist/remote/app.css +1 -1
- package/dist/remote/app.js +99 -26
- package/dist/remote/build-manifest.json +42 -27
- package/docs/docs.json +3 -1
- package/docs/sources-inspect-portability-acceptance.mdx +67 -0
- package/docs/sources-inspect-portability.mdx +115 -0
- package/package.json +6 -5
- package/skills/live-dashboard/SKILL.md +5 -4
- package/skills/live-dashboard/references/source-inspection.md +17 -0
package/dist/lib/editing.d.ts
CHANGED
|
@@ -6,6 +6,66 @@ import { DashboardService } from './dashboard.service';
|
|
|
6
6
|
import { type DashboardSelection } from './editing-session';
|
|
7
7
|
export { dashboardSelectionSchema, dashboardContextSchema } from './editing-session';
|
|
8
8
|
export declare const updateToolSchema: z.ZodObject<{
|
|
9
|
+
sourceMetadata: z.ZodOptional<z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
10
|
+
bindingId: z.ZodString;
|
|
11
|
+
title: z.ZodString;
|
|
12
|
+
description: z.ZodOptional<z.ZodString>;
|
|
13
|
+
}, "strict", z.ZodTypeAny, {
|
|
14
|
+
bindingId: string;
|
|
15
|
+
title: string;
|
|
16
|
+
description?: string | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
bindingId: string;
|
|
19
|
+
title: string;
|
|
20
|
+
description?: string | undefined;
|
|
21
|
+
}>, "many">, {
|
|
22
|
+
bindingId: string;
|
|
23
|
+
title: string;
|
|
24
|
+
description?: string | undefined;
|
|
25
|
+
}[], unknown>>>;
|
|
26
|
+
components: z.ZodOptional<z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
27
|
+
id: z.ZodString;
|
|
28
|
+
elementId: z.ZodString;
|
|
29
|
+
title: z.ZodString;
|
|
30
|
+
kind: z.ZodEnum<["metric", "chart", "table", "filter", "text"]>;
|
|
31
|
+
sources: z.ZodArray<z.ZodObject<{
|
|
32
|
+
bindingId: z.ZodString;
|
|
33
|
+
fieldIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
34
|
+
}, "strict", z.ZodTypeAny, {
|
|
35
|
+
bindingId: string;
|
|
36
|
+
fieldIds?: string[] | undefined;
|
|
37
|
+
}, {
|
|
38
|
+
bindingId: string;
|
|
39
|
+
fieldIds?: string[] | undefined;
|
|
40
|
+
}>, "many">;
|
|
41
|
+
}, "strict", z.ZodTypeAny, {
|
|
42
|
+
title: string;
|
|
43
|
+
id: string;
|
|
44
|
+
elementId: string;
|
|
45
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
46
|
+
sources: {
|
|
47
|
+
bindingId: string;
|
|
48
|
+
fieldIds?: string[] | undefined;
|
|
49
|
+
}[];
|
|
50
|
+
}, {
|
|
51
|
+
title: string;
|
|
52
|
+
id: string;
|
|
53
|
+
elementId: string;
|
|
54
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
55
|
+
sources: {
|
|
56
|
+
bindingId: string;
|
|
57
|
+
fieldIds?: string[] | undefined;
|
|
58
|
+
}[];
|
|
59
|
+
}>, "many">, {
|
|
60
|
+
title: string;
|
|
61
|
+
id: string;
|
|
62
|
+
elementId: string;
|
|
63
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
64
|
+
sources: {
|
|
65
|
+
bindingId: string;
|
|
66
|
+
fieldIds?: string[] | undefined;
|
|
67
|
+
}[];
|
|
68
|
+
}[], unknown>>>;
|
|
9
69
|
controls: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
10
70
|
controlId: z.ZodString;
|
|
11
71
|
type: z.ZodEnum<["string", "number", "boolean", "date"]>;
|
|
@@ -41,25 +101,25 @@ export declare const updateToolSchema: z.ZodObject<{
|
|
|
41
101
|
y: z.ZodString;
|
|
42
102
|
color: z.ZodOptional<z.ZodString>;
|
|
43
103
|
}, "strict", z.ZodTypeAny, {
|
|
104
|
+
title: string;
|
|
44
105
|
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
45
106
|
id: string;
|
|
46
|
-
title: string;
|
|
47
107
|
datasetId: string;
|
|
48
108
|
x: string;
|
|
49
109
|
y: string;
|
|
50
110
|
color?: string | undefined;
|
|
51
111
|
}, {
|
|
112
|
+
title: string;
|
|
52
113
|
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
53
114
|
id: string;
|
|
54
|
-
title: string;
|
|
55
115
|
datasetId: string;
|
|
56
116
|
x: string;
|
|
57
117
|
y: string;
|
|
58
118
|
color?: string | undefined;
|
|
59
119
|
}>, "many">, {
|
|
120
|
+
title: string;
|
|
60
121
|
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
61
122
|
id: string;
|
|
62
|
-
title: string;
|
|
63
123
|
datasetId: string;
|
|
64
124
|
x: string;
|
|
65
125
|
y: string;
|
|
@@ -71,18 +131,18 @@ export declare const updateToolSchema: z.ZodObject<{
|
|
|
71
131
|
datasetId: z.ZodString;
|
|
72
132
|
fields: z.ZodArray<z.ZodString, "many">;
|
|
73
133
|
}, "strict", z.ZodTypeAny, {
|
|
74
|
-
id: string;
|
|
75
134
|
title: string;
|
|
135
|
+
id: string;
|
|
76
136
|
datasetId: string;
|
|
77
137
|
fields: string[];
|
|
78
138
|
}, {
|
|
79
|
-
id: string;
|
|
80
139
|
title: string;
|
|
140
|
+
id: string;
|
|
81
141
|
datasetId: string;
|
|
82
142
|
fields: string[];
|
|
83
143
|
}>, "many">, {
|
|
84
|
-
id: string;
|
|
85
144
|
title: string;
|
|
145
|
+
id: string;
|
|
86
146
|
datasetId: string;
|
|
87
147
|
fields: string[];
|
|
88
148
|
}[], unknown>>;
|
|
@@ -94,16 +154,19 @@ export declare const updateToolSchema: z.ZodObject<{
|
|
|
94
154
|
controlIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
95
155
|
viewIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
96
156
|
htmlElementIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
157
|
+
componentIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
97
158
|
}, "strict", z.ZodTypeAny, {
|
|
98
159
|
bindingIds: string[];
|
|
99
160
|
controlIds: string[];
|
|
100
161
|
viewIds: string[];
|
|
101
162
|
htmlElementIds: string[];
|
|
163
|
+
componentIds: string[];
|
|
102
164
|
}, {
|
|
103
165
|
bindingIds?: string[] | undefined;
|
|
104
166
|
controlIds?: string[] | undefined;
|
|
105
167
|
viewIds?: string[] | undefined;
|
|
106
168
|
htmlElementIds?: string[] | undefined;
|
|
169
|
+
componentIds?: string[] | undefined;
|
|
107
170
|
}>>;
|
|
108
171
|
title: z.ZodString;
|
|
109
172
|
editId: z.ZodString;
|
|
@@ -116,6 +179,21 @@ export declare const updateToolSchema: z.ZodObject<{
|
|
|
116
179
|
expectedRevision: number;
|
|
117
180
|
expectedCurrentVersionId: string | null;
|
|
118
181
|
editId: string;
|
|
182
|
+
sourceMetadata?: {
|
|
183
|
+
bindingId: string;
|
|
184
|
+
title: string;
|
|
185
|
+
description?: string | undefined;
|
|
186
|
+
}[] | undefined;
|
|
187
|
+
components?: {
|
|
188
|
+
title: string;
|
|
189
|
+
id: string;
|
|
190
|
+
elementId: string;
|
|
191
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
192
|
+
sources: {
|
|
193
|
+
bindingId: string;
|
|
194
|
+
fieldIds?: string[] | undefined;
|
|
195
|
+
}[];
|
|
196
|
+
}[] | undefined;
|
|
119
197
|
controls?: {
|
|
120
198
|
type: "string" | "number" | "boolean" | "date";
|
|
121
199
|
controlId: string;
|
|
@@ -124,17 +202,17 @@ export declare const updateToolSchema: z.ZodObject<{
|
|
|
124
202
|
allowedValues?: (string | number | boolean | null)[] | undefined;
|
|
125
203
|
}[] | undefined;
|
|
126
204
|
charts?: {
|
|
205
|
+
title: string;
|
|
127
206
|
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
128
207
|
id: string;
|
|
129
|
-
title: string;
|
|
130
208
|
datasetId: string;
|
|
131
209
|
x: string;
|
|
132
210
|
y: string;
|
|
133
211
|
color?: string | undefined;
|
|
134
212
|
}[] | undefined;
|
|
135
213
|
tables?: {
|
|
136
|
-
id: string;
|
|
137
214
|
title: string;
|
|
215
|
+
id: string;
|
|
138
216
|
datasetId: string;
|
|
139
217
|
fields: string[];
|
|
140
218
|
}[] | undefined;
|
|
@@ -146,6 +224,7 @@ export declare const updateToolSchema: z.ZodObject<{
|
|
|
146
224
|
controlIds: string[];
|
|
147
225
|
viewIds: string[];
|
|
148
226
|
htmlElementIds: string[];
|
|
227
|
+
componentIds: string[];
|
|
149
228
|
} | undefined;
|
|
150
229
|
htmlPath?: string | undefined;
|
|
151
230
|
}, {
|
|
@@ -153,6 +232,8 @@ export declare const updateToolSchema: z.ZodObject<{
|
|
|
153
232
|
expectedRevision: number;
|
|
154
233
|
expectedCurrentVersionId: string | null;
|
|
155
234
|
editId: string;
|
|
235
|
+
sourceMetadata?: unknown;
|
|
236
|
+
components?: unknown;
|
|
156
237
|
controls?: unknown;
|
|
157
238
|
charts?: unknown;
|
|
158
239
|
tables?: unknown;
|
|
@@ -164,10 +245,11 @@ export declare const updateToolSchema: z.ZodObject<{
|
|
|
164
245
|
controlIds?: string[] | undefined;
|
|
165
246
|
viewIds?: string[] | undefined;
|
|
166
247
|
htmlElementIds?: string[] | undefined;
|
|
248
|
+
componentIds?: string[] | undefined;
|
|
167
249
|
} | undefined;
|
|
168
250
|
htmlPath?: string | undefined;
|
|
169
251
|
}>;
|
|
170
|
-
export declare const EDITING_GUIDANCE = "Opening or reading a dashboard does not modify it. A selection_required result is normal: show its message to the user and wait for an explicit selection; do not retry, infer a target from history, or create a replacement. Do not save an unchanged editing copy or reopen/update merely to confirm a successful save; use the mutation receipt. For existing dashboards, call dashboard_open first and inspect presentation.type. For standard dashboards, update definition fields directly: a rename needs only title, editId, expectedRevision and expectedCurrentVersionId. No HTML file exists; omit htmlPath and libraries. For HTML dashboards only, open prepares a unique editing copy at htmlPath. Read with sandbox_read_file. If a long HTML line is truncated, do not repeat the same read: use dashboard_read_html with editId and follow nextOffset until null to inspect the saved source, then apply exact replacements to htmlPath. Never replace a file with a truncated preview. Edit with sandbox_edit_file/multi_edit_file (sandbox_write_file is create-only), then call dashboard_update with that exact htmlPath and read revisions. If the user requests a rename, include the new title in this same update; editing the HTML heading alone does not rename the Artifact. Save each batch automatically without human confirmation. Files are not dashboard saves. Preserve Binding semantics, stable component IDs and dependency locks unless requested. Update arrays upsert by ID, preserving omitted components; removals must name explicitly requested deletions. HTML updates retain existing element IDs. For new HTML, assign stable IDs to every KPI, chart, detail table and filter. Read and patch the current file instead of rebuilding unrelated sections. On conflict retain the editing file, open the latest draft and reconcile; never silently overwrite. Historical versions are read-only references. All Agent saves are drafts; only the Workbench human publish action creates formal versions. Read the live-dashboard skill for the complete workflow.";
|
|
252
|
+
export declare const EDITING_GUIDANCE = "Opening or reading a dashboard does not modify it. A selection_required result is normal: show its message to the user and wait for an explicit selection; do not retry, infer a target from history, or create a replacement. Do not save an unchanged editing copy or reopen/update merely to confirm a successful save; use the mutation receipt. For existing dashboards, call dashboard_open first and inspect presentation.type. For standard dashboards, update definition fields directly: a rename needs only title, editId, expectedRevision and expectedCurrentVersionId. No HTML file exists; omit htmlPath and libraries. For HTML dashboards only, open prepares a unique editing copy at htmlPath. Read with sandbox_read_file. If a long HTML line is truncated, do not repeat the same read: use dashboard_read_html with editId and follow nextOffset until null to inspect the saved source, then apply exact replacements to htmlPath. Never replace a file with a truncated preview. Edit with sandbox_edit_file/multi_edit_file (sandbox_write_file is create-only), then call dashboard_update with that exact htmlPath and read revisions. If the user requests a rename, include the new title in this same update; editing the HTML heading alone does not rename the Artifact. Save each batch automatically without human confirmation. Files are not dashboard saves. Preserve Binding semantics, stable component IDs and dependency locks unless requested. To add filters to an existing Binding, copy its complete dashboard_open.bindings[] entry, retain binding.id and existing parameters[].controlId, and call dashboard_preview_binding after changing payload/parameters/defaults. Binding ID is independent of output.datasetId; simplified dashboard_preview derives the ID from datasetId and can accidentally add a new Binding instead of updating the old one. Use the stable Binding ID in HTML query/subscribe calls. Submit every intended changed/new Binding previewId and matching controls with htmlPath in the same dashboard_update. Update arrays upsert by ID, preserving omitted components; removals must name explicitly requested deletions. On preflight failure, compare expected/requested Binding IDs, repair the HTML or previews, and retain all intended previewIds, controls, title and htmlPath when retrying. Dropping previewIds does not register new HTML queries. Do not remove an existing Binding merely to suppress validation. HTML updates retain existing element IDs. For new HTML, assign stable IDs to every KPI, chart, detail table and filter. Read and patch the current file instead of rebuilding unrelated sections. On conflict retain the editing file, open the latest draft and reconcile; never silently overwrite. Historical versions are read-only references. All Agent saves are drafts; only the Workbench human publish action creates formal versions. Read the live-dashboard skill for the complete workflow.";
|
|
171
253
|
/** Run-local read receipts carry planning versions; authorization and CAS remain in the domain service. */
|
|
172
254
|
export declare function createEditingTools(service: DashboardService, scope: XpertResolvedViewHostContext, context: IAgentMiddlewareContext, resolvePreviews: (ids: string[]) => AnalyticsBinding[], validateFinal: (manifest: DashboardManifest, requirePreviews: boolean, changedBindingIds?: string[]) => void, onOpen?: (path: string, artifactId: string) => void, currentTarget?: (config: unknown) => DashboardSelection | null | undefined): (import("@langchain/core/tools").DynamicStructuredTool<z.ZodObject<{
|
|
173
255
|
page: z.ZodDefault<z.ZodNumber>;
|
|
@@ -217,6 +299,66 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
217
299
|
}, {
|
|
218
300
|
artifactId?: string | undefined;
|
|
219
301
|
}, string> | import("@langchain/core/tools").DynamicStructuredTool<z.ZodObject<{
|
|
302
|
+
sourceMetadata: z.ZodOptional<z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
303
|
+
bindingId: z.ZodString;
|
|
304
|
+
title: z.ZodString;
|
|
305
|
+
description: z.ZodOptional<z.ZodString>;
|
|
306
|
+
}, "strict", z.ZodTypeAny, {
|
|
307
|
+
bindingId: string;
|
|
308
|
+
title: string;
|
|
309
|
+
description?: string | undefined;
|
|
310
|
+
}, {
|
|
311
|
+
bindingId: string;
|
|
312
|
+
title: string;
|
|
313
|
+
description?: string | undefined;
|
|
314
|
+
}>, "many">, {
|
|
315
|
+
bindingId: string;
|
|
316
|
+
title: string;
|
|
317
|
+
description?: string | undefined;
|
|
318
|
+
}[], unknown>>>;
|
|
319
|
+
components: z.ZodOptional<z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
320
|
+
id: z.ZodString;
|
|
321
|
+
elementId: z.ZodString;
|
|
322
|
+
title: z.ZodString;
|
|
323
|
+
kind: z.ZodEnum<["metric", "chart", "table", "filter", "text"]>;
|
|
324
|
+
sources: z.ZodArray<z.ZodObject<{
|
|
325
|
+
bindingId: z.ZodString;
|
|
326
|
+
fieldIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
327
|
+
}, "strict", z.ZodTypeAny, {
|
|
328
|
+
bindingId: string;
|
|
329
|
+
fieldIds?: string[] | undefined;
|
|
330
|
+
}, {
|
|
331
|
+
bindingId: string;
|
|
332
|
+
fieldIds?: string[] | undefined;
|
|
333
|
+
}>, "many">;
|
|
334
|
+
}, "strict", z.ZodTypeAny, {
|
|
335
|
+
title: string;
|
|
336
|
+
id: string;
|
|
337
|
+
elementId: string;
|
|
338
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
339
|
+
sources: {
|
|
340
|
+
bindingId: string;
|
|
341
|
+
fieldIds?: string[] | undefined;
|
|
342
|
+
}[];
|
|
343
|
+
}, {
|
|
344
|
+
title: string;
|
|
345
|
+
id: string;
|
|
346
|
+
elementId: string;
|
|
347
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
348
|
+
sources: {
|
|
349
|
+
bindingId: string;
|
|
350
|
+
fieldIds?: string[] | undefined;
|
|
351
|
+
}[];
|
|
352
|
+
}>, "many">, {
|
|
353
|
+
title: string;
|
|
354
|
+
id: string;
|
|
355
|
+
elementId: string;
|
|
356
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
357
|
+
sources: {
|
|
358
|
+
bindingId: string;
|
|
359
|
+
fieldIds?: string[] | undefined;
|
|
360
|
+
}[];
|
|
361
|
+
}[], unknown>>>;
|
|
220
362
|
controls: z.ZodOptional<z.ZodEffects<z.ZodArray<z.ZodObject<{
|
|
221
363
|
controlId: z.ZodString;
|
|
222
364
|
type: z.ZodEnum<["string", "number", "boolean", "date"]>;
|
|
@@ -252,25 +394,25 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
252
394
|
y: z.ZodString;
|
|
253
395
|
color: z.ZodOptional<z.ZodString>;
|
|
254
396
|
}, "strict", z.ZodTypeAny, {
|
|
397
|
+
title: string;
|
|
255
398
|
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
256
399
|
id: string;
|
|
257
|
-
title: string;
|
|
258
400
|
datasetId: string;
|
|
259
401
|
x: string;
|
|
260
402
|
y: string;
|
|
261
403
|
color?: string | undefined;
|
|
262
404
|
}, {
|
|
405
|
+
title: string;
|
|
263
406
|
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
264
407
|
id: string;
|
|
265
|
-
title: string;
|
|
266
408
|
datasetId: string;
|
|
267
409
|
x: string;
|
|
268
410
|
y: string;
|
|
269
411
|
color?: string | undefined;
|
|
270
412
|
}>, "many">, {
|
|
413
|
+
title: string;
|
|
271
414
|
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
272
415
|
id: string;
|
|
273
|
-
title: string;
|
|
274
416
|
datasetId: string;
|
|
275
417
|
x: string;
|
|
276
418
|
y: string;
|
|
@@ -282,18 +424,18 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
282
424
|
datasetId: z.ZodString;
|
|
283
425
|
fields: z.ZodArray<z.ZodString, "many">;
|
|
284
426
|
}, "strict", z.ZodTypeAny, {
|
|
285
|
-
id: string;
|
|
286
427
|
title: string;
|
|
428
|
+
id: string;
|
|
287
429
|
datasetId: string;
|
|
288
430
|
fields: string[];
|
|
289
431
|
}, {
|
|
290
|
-
id: string;
|
|
291
432
|
title: string;
|
|
433
|
+
id: string;
|
|
292
434
|
datasetId: string;
|
|
293
435
|
fields: string[];
|
|
294
436
|
}>, "many">, {
|
|
295
|
-
id: string;
|
|
296
437
|
title: string;
|
|
438
|
+
id: string;
|
|
297
439
|
datasetId: string;
|
|
298
440
|
fields: string[];
|
|
299
441
|
}[], unknown>>;
|
|
@@ -305,16 +447,19 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
305
447
|
controlIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
306
448
|
viewIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
307
449
|
htmlElementIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
450
|
+
componentIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
308
451
|
}, "strict", z.ZodTypeAny, {
|
|
309
452
|
bindingIds: string[];
|
|
310
453
|
controlIds: string[];
|
|
311
454
|
viewIds: string[];
|
|
312
455
|
htmlElementIds: string[];
|
|
456
|
+
componentIds: string[];
|
|
313
457
|
}, {
|
|
314
458
|
bindingIds?: string[] | undefined;
|
|
315
459
|
controlIds?: string[] | undefined;
|
|
316
460
|
viewIds?: string[] | undefined;
|
|
317
461
|
htmlElementIds?: string[] | undefined;
|
|
462
|
+
componentIds?: string[] | undefined;
|
|
318
463
|
}>>;
|
|
319
464
|
title: z.ZodString;
|
|
320
465
|
editId: z.ZodString;
|
|
@@ -327,6 +472,21 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
327
472
|
expectedRevision: number;
|
|
328
473
|
expectedCurrentVersionId: string | null;
|
|
329
474
|
editId: string;
|
|
475
|
+
sourceMetadata?: {
|
|
476
|
+
bindingId: string;
|
|
477
|
+
title: string;
|
|
478
|
+
description?: string | undefined;
|
|
479
|
+
}[] | undefined;
|
|
480
|
+
components?: {
|
|
481
|
+
title: string;
|
|
482
|
+
id: string;
|
|
483
|
+
elementId: string;
|
|
484
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
485
|
+
sources: {
|
|
486
|
+
bindingId: string;
|
|
487
|
+
fieldIds?: string[] | undefined;
|
|
488
|
+
}[];
|
|
489
|
+
}[] | undefined;
|
|
330
490
|
controls?: {
|
|
331
491
|
type: "string" | "number" | "boolean" | "date";
|
|
332
492
|
controlId: string;
|
|
@@ -335,17 +495,17 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
335
495
|
allowedValues?: (string | number | boolean | null)[] | undefined;
|
|
336
496
|
}[] | undefined;
|
|
337
497
|
charts?: {
|
|
498
|
+
title: string;
|
|
338
499
|
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
339
500
|
id: string;
|
|
340
|
-
title: string;
|
|
341
501
|
datasetId: string;
|
|
342
502
|
x: string;
|
|
343
503
|
y: string;
|
|
344
504
|
color?: string | undefined;
|
|
345
505
|
}[] | undefined;
|
|
346
506
|
tables?: {
|
|
347
|
-
id: string;
|
|
348
507
|
title: string;
|
|
508
|
+
id: string;
|
|
349
509
|
datasetId: string;
|
|
350
510
|
fields: string[];
|
|
351
511
|
}[] | undefined;
|
|
@@ -357,6 +517,7 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
357
517
|
controlIds: string[];
|
|
358
518
|
viewIds: string[];
|
|
359
519
|
htmlElementIds: string[];
|
|
520
|
+
componentIds: string[];
|
|
360
521
|
} | undefined;
|
|
361
522
|
htmlPath?: string | undefined;
|
|
362
523
|
}, {
|
|
@@ -364,6 +525,8 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
364
525
|
expectedRevision: number;
|
|
365
526
|
expectedCurrentVersionId: string | null;
|
|
366
527
|
editId: string;
|
|
528
|
+
sourceMetadata?: unknown;
|
|
529
|
+
components?: unknown;
|
|
367
530
|
controls?: unknown;
|
|
368
531
|
charts?: unknown;
|
|
369
532
|
tables?: unknown;
|
|
@@ -375,6 +538,7 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
375
538
|
controlIds?: string[] | undefined;
|
|
376
539
|
viewIds?: string[] | undefined;
|
|
377
540
|
htmlElementIds?: string[] | undefined;
|
|
541
|
+
componentIds?: string[] | undefined;
|
|
378
542
|
} | undefined;
|
|
379
543
|
htmlPath?: string | undefined;
|
|
380
544
|
}>, {
|
|
@@ -382,6 +546,21 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
382
546
|
expectedRevision: number;
|
|
383
547
|
expectedCurrentVersionId: string | null;
|
|
384
548
|
editId: string;
|
|
549
|
+
sourceMetadata?: {
|
|
550
|
+
bindingId: string;
|
|
551
|
+
title: string;
|
|
552
|
+
description?: string | undefined;
|
|
553
|
+
}[] | undefined;
|
|
554
|
+
components?: {
|
|
555
|
+
title: string;
|
|
556
|
+
id: string;
|
|
557
|
+
elementId: string;
|
|
558
|
+
kind: "filter" | "metric" | "chart" | "table" | "text";
|
|
559
|
+
sources: {
|
|
560
|
+
bindingId: string;
|
|
561
|
+
fieldIds?: string[] | undefined;
|
|
562
|
+
}[];
|
|
563
|
+
}[] | undefined;
|
|
385
564
|
controls?: {
|
|
386
565
|
type: "string" | "number" | "boolean" | "date";
|
|
387
566
|
controlId: string;
|
|
@@ -390,17 +569,17 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
390
569
|
allowedValues?: (string | number | boolean | null)[] | undefined;
|
|
391
570
|
}[] | undefined;
|
|
392
571
|
charts?: {
|
|
572
|
+
title: string;
|
|
393
573
|
type: "bar" | "line" | "area" | "pie" | "scatter";
|
|
394
574
|
id: string;
|
|
395
|
-
title: string;
|
|
396
575
|
datasetId: string;
|
|
397
576
|
x: string;
|
|
398
577
|
y: string;
|
|
399
578
|
color?: string | undefined;
|
|
400
579
|
}[] | undefined;
|
|
401
580
|
tables?: {
|
|
402
|
-
id: string;
|
|
403
581
|
title: string;
|
|
582
|
+
id: string;
|
|
404
583
|
datasetId: string;
|
|
405
584
|
fields: string[];
|
|
406
585
|
}[] | undefined;
|
|
@@ -412,6 +591,7 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
412
591
|
controlIds: string[];
|
|
413
592
|
viewIds: string[];
|
|
414
593
|
htmlElementIds: string[];
|
|
594
|
+
componentIds: string[];
|
|
415
595
|
} | undefined;
|
|
416
596
|
htmlPath?: string | undefined;
|
|
417
597
|
}, {
|
|
@@ -419,6 +599,8 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
419
599
|
expectedRevision: number;
|
|
420
600
|
expectedCurrentVersionId: string | null;
|
|
421
601
|
editId: string;
|
|
602
|
+
sourceMetadata?: unknown;
|
|
603
|
+
components?: unknown;
|
|
422
604
|
controls?: unknown;
|
|
423
605
|
charts?: unknown;
|
|
424
606
|
tables?: unknown;
|
|
@@ -430,6 +612,7 @@ export declare function createEditingTools(service: DashboardService, scope: Xpe
|
|
|
430
612
|
controlIds?: string[] | undefined;
|
|
431
613
|
viewIds?: string[] | undefined;
|
|
432
614
|
htmlElementIds?: string[] | undefined;
|
|
615
|
+
componentIds?: string[] | undefined;
|
|
433
616
|
} | undefined;
|
|
434
617
|
htmlPath?: string | undefined;
|
|
435
618
|
}, string>)[];
|
package/dist/lib/editing.js
CHANGED
|
@@ -23,7 +23,7 @@ exports.updateToolSchema = agent_schema_1.createToolSchema.omit({ creationIntent
|
|
|
23
23
|
libraries: document_libraries_1.libraryRequestsSchema.optional().describe('Omit to preserve the saved dependency versions. Supply the complete desired library IDs to explicitly add, remove or upgrade bundled libraries.') }).strict();
|
|
24
24
|
const readHtmlSchema = v3_1.z.object({ editId: v3_1.z.string().uuid(), versionId: v3_1.z.string().uuid().optional().describe('Only for historical inspection; copy readVersionId from dashboard_open.'), offset: v3_1.z.number().int().min(0).max(300000).default(0),
|
|
25
25
|
length: v3_1.z.number().int().min(1).max(24000).default(16000) }).strict();
|
|
26
|
-
exports.EDITING_GUIDANCE = `Opening or reading a dashboard does not modify it. A selection_required result is normal: show its message to the user and wait for an explicit selection; do not retry, infer a target from history, or create a replacement. Do not save an unchanged editing copy or reopen/update merely to confirm a successful save; use the mutation receipt. For existing dashboards, call dashboard_open first and inspect presentation.type. For standard dashboards, update definition fields directly: a rename needs only title, editId, expectedRevision and expectedCurrentVersionId. No HTML file exists; omit htmlPath and libraries. For HTML dashboards only, open prepares a unique editing copy at htmlPath. Read with sandbox_read_file. If a long HTML line is truncated, do not repeat the same read: use dashboard_read_html with editId and follow nextOffset until null to inspect the saved source, then apply exact replacements to htmlPath. Never replace a file with a truncated preview. Edit with sandbox_edit_file/multi_edit_file (sandbox_write_file is create-only), then call dashboard_update with that exact htmlPath and read revisions. If the user requests a rename, include the new title in this same update; editing the HTML heading alone does not rename the Artifact. Save each batch automatically without human confirmation. Files are not dashboard saves. Preserve Binding semantics, stable component IDs and dependency locks unless requested. Update arrays upsert by ID, preserving omitted components; removals must name explicitly requested deletions. HTML updates retain existing element IDs. For new HTML, assign stable IDs to every KPI, chart, detail table and filter. Read and patch the current file instead of rebuilding unrelated sections. On conflict retain the editing file, open the latest draft and reconcile; never silently overwrite. Historical versions are read-only references. All Agent saves are drafts; only the Workbench human publish action creates formal versions. Read the live-dashboard skill for the complete workflow.`;
|
|
26
|
+
exports.EDITING_GUIDANCE = `Opening or reading a dashboard does not modify it. A selection_required result is normal: show its message to the user and wait for an explicit selection; do not retry, infer a target from history, or create a replacement. Do not save an unchanged editing copy or reopen/update merely to confirm a successful save; use the mutation receipt. For existing dashboards, call dashboard_open first and inspect presentation.type. For standard dashboards, update definition fields directly: a rename needs only title, editId, expectedRevision and expectedCurrentVersionId. No HTML file exists; omit htmlPath and libraries. For HTML dashboards only, open prepares a unique editing copy at htmlPath. Read with sandbox_read_file. If a long HTML line is truncated, do not repeat the same read: use dashboard_read_html with editId and follow nextOffset until null to inspect the saved source, then apply exact replacements to htmlPath. Never replace a file with a truncated preview. Edit with sandbox_edit_file/multi_edit_file (sandbox_write_file is create-only), then call dashboard_update with that exact htmlPath and read revisions. If the user requests a rename, include the new title in this same update; editing the HTML heading alone does not rename the Artifact. Save each batch automatically without human confirmation. Files are not dashboard saves. Preserve Binding semantics, stable component IDs and dependency locks unless requested. To add filters to an existing Binding, copy its complete dashboard_open.bindings[] entry, retain binding.id and existing parameters[].controlId, and call dashboard_preview_binding after changing payload/parameters/defaults. Binding ID is independent of output.datasetId; simplified dashboard_preview derives the ID from datasetId and can accidentally add a new Binding instead of updating the old one. Use the stable Binding ID in HTML query/subscribe calls. Submit every intended changed/new Binding previewId and matching controls with htmlPath in the same dashboard_update. Update arrays upsert by ID, preserving omitted components; removals must name explicitly requested deletions. On preflight failure, compare expected/requested Binding IDs, repair the HTML or previews, and retain all intended previewIds, controls, title and htmlPath when retrying. Dropping previewIds does not register new HTML queries. Do not remove an existing Binding merely to suppress validation. HTML updates retain existing element IDs. For new HTML, assign stable IDs to every KPI, chart, detail table and filter. Read and patch the current file instead of rebuilding unrelated sections. On conflict retain the editing file, open the latest draft and reconcile; never silently overwrite. Historical versions are read-only references. All Agent saves are drafts; only the Workbench human publish action creates formal versions. Read the live-dashboard skill for the complete workflow.`;
|
|
27
27
|
/** Run-local read receipts carry planning versions; authorization and CAS remain in the domain service. */
|
|
28
28
|
function createEditingTools(service, scope, context, resolvePreviews, validateFinal, onOpen = () => undefined, currentTarget = editing_session_1.selectionFromConfig) {
|
|
29
29
|
const target = (input, config) => {
|
|
@@ -61,7 +61,7 @@ function createEditingTools(service, scope, context, resolvePreviews, validateFi
|
|
|
61
61
|
: { state: 'published', versionNumber: saved.versionNumber ?? 0, versionId: resolved.versionId }) }, config);
|
|
62
62
|
return JSON.stringify({ resourceCard, editId, expectedCurrentVersionId: saved.baseVersionId ?? saved.versionId ?? null, ...(resolved.versionId ? { readVersionId: resolved.versionId } : {}), expectedRevision: saved.draftRevision ?? 0, state: saved.isDraft ? 'draft' : 'published', artifactId: saved.artifactId, versionId: saved.versionId, versionNumber: saved.versionNumber,
|
|
63
63
|
...definition, presentation: presentation ? { type: 'html', characters: presentation.html.length, dependencies: presentation.dependencies ?? [] } : { type: 'standard' },
|
|
64
|
-
...(resolved.versionId ? { next: 'Read-only published version. To edit, select the working draft in the Workbench version selector or explicitly open this Artifact without a versionId, then use its current draft revision. Publication requires a separate human action.' } : htmlPath ? { htmlPath, saveArguments: { editId, expectedRevision: saved.draftRevision ?? 0, expectedCurrentVersionId: saved.baseVersionId ?? saved.versionId ?? null, title: saved.manifest.title, htmlPath }, editingFile: { path: htmlPath, exists: true, hasUnsavedChanges: false, writeMode: 'edit_existing', read: { tool: 'sandbox_read_file', arguments: { file_path: htmlPath } } }, next: 'Opening only prepared a copy; it did not change the dashboard and requires no save. Call dashboard_update only after applying requested changes. Copy saveArguments, replacing title with the requested new name when renaming. expectedCurrentVersionId must remain actual JSON null or the returned UUID; never a string such as None. When repairing a failed update, retain all intended
|
|
64
|
+
...(resolved.versionId ? { next: 'Read-only published version. To edit, select the working draft in the Workbench version selector or explicitly open this Artifact without a versionId, then use its current draft revision. Publication requires a separate human action.' } : htmlPath ? { htmlPath, saveArguments: { editId, expectedRevision: saved.draftRevision ?? 0, expectedCurrentVersionId: saved.baseVersionId ?? saved.versionId ?? null, title: saved.manifest.title, htmlPath }, editingFile: { path: htmlPath, exists: true, hasUnsavedChanges: false, writeMode: 'edit_existing', read: { tool: 'sandbox_read_file', arguments: { file_path: htmlPath } } }, next: 'Opening only prepared a copy; it did not change the dashboard and requires no save. Call dashboard_update only after applying requested changes. Copy saveArguments, replacing title with the requested new name when renaming. expectedCurrentVersionId must remain actual JSON null or the returned UUID; never a string such as None. When repairing a failed update, retain all intended previewIds, controls, title and htmlPath. For changed bindings, copy bindings[] and preserve binding.id via dashboard_preview_binding; omitted bindings remain saved. The editing file already exists: do not use sandbox_write_file on it. When renaming, include title and htmlPath together in one dashboard_update. A private editing copy is ready. Read it with sandbox_read_file. If long lines are truncated, use dashboard_read_html with editId and follow nextOffset until null instead of retrying file reads. This fallback reads the saved source; apply changes to htmlPath and never write a truncated preview. Edit with sandbox_edit_file/multi_edit_file, then save using dashboard_update with this htmlPath and the returned revisions. File edits alone do not save the dashboard.' } : !presentation ? { next: 'Standard dashboard: update definition fields directly. A rename requires only title plus editId, expectedRevision and expectedCurrentVersionId. No HTML editing file exists; omit htmlPath and libraries unless intentionally converting to HTML.' } : {}) });
|
|
65
65
|
}, { name: 'dashboard_open', description: 'Read one authorized saved dashboard and obtain its stable editId and current draft revision. For a current HTML dashboard also prepares a unique Workspace editing copy without changing the Artifact. Historical versions remain read-only. Omit artifactId only for the selected Workbench dashboard.',
|
|
66
66
|
schema: targetSchema, verboseParsingErrors: true, metadata: { toolName: { en_US: 'Read dashboard for editing', zh_Hans: '读取看板以继续修改' } } }),
|
|
67
67
|
(0, tools_1.tool)(async (input) => {
|
|
@@ -89,6 +89,8 @@ function createEditingTools(service, scope, context, resolvePreviews, validateFi
|
|
|
89
89
|
const changedBindings = previewIds ? resolvePreviews(previewIds) : undefined;
|
|
90
90
|
const bindings = (0, editing_patch_1.upsertComponents)(saved.manifest.bindings, changedBindings, item => item.id, removals?.bindingIds);
|
|
91
91
|
const controls = (0, editing_patch_1.upsertComponents)(saved.manifest.controls, changes.controls, item => item.controlId, removals?.controlIds);
|
|
92
|
+
const sourceMetadata = (0, editing_patch_1.upsertComponents)(saved.manifest.sourceMetadata ?? [], changes.sourceMetadata, item => item.bindingId, removals?.bindingIds.filter(id => saved.manifest.sourceMetadata?.some(item => item.bindingId === id)));
|
|
93
|
+
const components = (0, editing_patch_1.upsertComponents)(saved.manifest.components ?? [], changes.components, item => item.id, removals?.componentIds);
|
|
92
94
|
if (removals?.viewIds.some(id => ![...saved.manifest.charts, ...saved.manifest.tables].some(view => view.id === id)))
|
|
93
95
|
throw new Error('DASHBOARD_REMOVAL_INVALID: copy existing view IDs');
|
|
94
96
|
const charts = (0, editing_patch_1.upsertComponents)(saved.manifest.charts, changes.charts, item => item.id, removals?.viewIds.filter(id => saved.manifest.charts.some(item => item.id === id)));
|
|
@@ -114,6 +116,7 @@ function createEditingTools(service, scope, context, resolvePreviews, validateFi
|
|
|
114
116
|
}
|
|
115
117
|
(0, editing_patch_1.assertHtmlPreserved)(saved.manifest.presentation, presentation, removals?.htmlElementIds);
|
|
116
118
|
const manifest = dashboard_schema_1.dashboardSchema.parse({ ...saved.manifest, ...changes, bindings, controls, charts, tables,
|
|
119
|
+
...(sourceMetadata.length || saved.manifest.sourceMetadata ? { sourceMetadata } : {}), ...(components.length || saved.manifest.components ? { components } : {}),
|
|
117
120
|
...(presentation ? { presentation } : {}) });
|
|
118
121
|
validateFinal(manifest, previewIds !== undefined, changedBindings?.map(item => item.id));
|
|
119
122
|
const { schema, id, ...update } = manifest;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BadRequestException } from '@nestjs/common';
|
|
2
|
+
import type { DashboardManifest } from './dashboard.schema';
|
|
3
|
+
/** Report only binding identities observed by validation, never query payloads or returned rows. */
|
|
4
|
+
export declare function htmlPreflightFailure(manifest: DashboardManifest, report: {
|
|
5
|
+
errors: string[];
|
|
6
|
+
requestedBindings: string[];
|
|
7
|
+
}): BadRequestException;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.htmlPreflightFailure = htmlPreflightFailure;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
/** Report only binding identities observed by validation, never query payloads or returned rows. */
|
|
6
|
+
function htmlPreflightFailure(manifest, report) {
|
|
7
|
+
const expectedBindingIds = manifest.bindings.map(binding => binding.id);
|
|
8
|
+
const requestedBindingIds = [...new Set(report.requestedBindings)];
|
|
9
|
+
const expected = new Set(expectedBindingIds), requested = new Set(requestedBindingIds);
|
|
10
|
+
const bindingDiagnostics = {
|
|
11
|
+
expectedBindingIds, requestedBindingIds,
|
|
12
|
+
missingQueryBindingIds: expectedBindingIds.filter(id => !requested.has(id)),
|
|
13
|
+
unexpectedQueryBindingIds: requestedBindingIds.filter(id => !expected.has(id))
|
|
14
|
+
};
|
|
15
|
+
const repair = 'Compare the candidate manifest Binding IDs with the HTML query/subscribe IDs. Requested IDs are observed calls, not a static list of every HTML reference. For an existing Binding, preserve dashboard_open.bindings[].id and preview its complete edited Binding with dashboard_preview_binding. Include all intended current-run previewIds, controls and htmlPath together in dashboard_update; omitted components remain saved. Add new Bindings only for new data needs; remove existing ones only for explicitly requested deletions. Repair other reported page errors before retrying. No dashboard was saved.';
|
|
16
|
+
// Some tool hosts retain only Error.message, so keep the bounded identity diagnostics there too.
|
|
17
|
+
return new common_1.BadRequestException({ code: 'DASHBOARD_HTML_PREFLIGHT_FAILED', errors: report.errors,
|
|
18
|
+
bindingDiagnostics, message: `DASHBOARD_HTML_PREFLIGHT_FAILED: ${JSON.stringify(report.errors)}. Binding diagnostics: ${JSON.stringify(bindingDiagnostics)}. ${repair}` });
|
|
19
|
+
}
|
|
@@ -19,6 +19,7 @@ const promises_1 = require("node:timers/promises");
|
|
|
19
19
|
const v3_1 = require("zod/v3");
|
|
20
20
|
const plugin_sdk_1 = require("@xpert-ai/plugin-sdk");
|
|
21
21
|
const artifact_document_1 = require("@xpert-ai/plugin-sdk/artifact-document");
|
|
22
|
+
const html_validation_feedback_1 = require("./html-validation-feedback");
|
|
22
23
|
const PLUGIN = '@xpert-ai/plugin-live-dashboard', ACTION = 'live_dashboard.validate-html', POOL = 'sandbox-browser';
|
|
23
24
|
const reportSchema = v3_1.z.object({ ok: v3_1.z.boolean(), errors: v3_1.z.array(v3_1.z.string().max(300)).max(16),
|
|
24
25
|
requestedBindings: v3_1.z.array(v3_1.z.string().max(80)).max(60), renderedTextLength: v3_1.z.number().int().nonnegative() }).strict();
|
|
@@ -70,7 +71,7 @@ let HtmlDashboardValidation = class HtmlDashboardValidation {
|
|
|
70
71
|
const report = reportSchema.parse(JSON.parse(await redis.get(`${key}:report`) ?? 'null'));
|
|
71
72
|
finished = true;
|
|
72
73
|
if (!report.ok)
|
|
73
|
-
throw
|
|
74
|
+
throw (0, html_validation_feedback_1.htmlPreflightFailure)(manifest, report);
|
|
74
75
|
return { jobId, requestedBindings: report.requestedBindings, status: 'passed' };
|
|
75
76
|
}
|
|
76
77
|
await (0, promises_1.setTimeout)(250);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type DashboardComponent } from './dashboard-sources';
|
|
2
|
+
/** One frame generation, one nonce; inspection is UI metadata and grants no query authority. */
|
|
3
|
+
export declare function createDashboardInspector(frame: HTMLIFrameElement, components: DashboardComponent[], onSelect: (id: string | null) => void, onExit: () => void, standard?: boolean): {
|
|
4
|
+
prefix: string;
|
|
5
|
+
setEnabled(value: boolean): void;
|
|
6
|
+
dispose(): void;
|
|
7
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDashboardInspector = createDashboardInspector;
|
|
4
|
+
const v3_1 = require("zod/v3");
|
|
5
|
+
const inspection_runtime_1 = require("./inspection-runtime");
|
|
6
|
+
const dashboard_sources_1 = require("./dashboard-sources");
|
|
7
|
+
const message = v3_1.z.discriminatedUnion('type', [
|
|
8
|
+
v3_1.z.object({ channel: v3_1.z.literal('live-dashboard.inspection'), key: v3_1.z.string(), type: v3_1.z.literal('ready') }).strict(),
|
|
9
|
+
v3_1.z.object({ channel: v3_1.z.literal('live-dashboard.inspection'), key: v3_1.z.string(), type: v3_1.z.literal('exit') }).strict(),
|
|
10
|
+
v3_1.z.object({ channel: v3_1.z.literal('live-dashboard.inspection'), key: v3_1.z.string(), type: v3_1.z.literal('selected'), componentId: dashboard_sources_1.componentId.nullable() }).strict()
|
|
11
|
+
]);
|
|
12
|
+
/** One frame generation, one nonce; inspection is UI metadata and grants no query authority. */
|
|
13
|
+
function createDashboardInspector(frame, components, onSelect, onExit, standard = false) {
|
|
14
|
+
const key = Array.from(crypto.getRandomValues(new Uint8Array(16)), byte => byte.toString(16).padStart(2, '0')).join('');
|
|
15
|
+
const host = frame.ownerDocument.defaultView;
|
|
16
|
+
let connected = false, enabled = false, disposed = false;
|
|
17
|
+
const send = () => {
|
|
18
|
+
if (connected && !disposed)
|
|
19
|
+
frame.contentWindow?.postMessage({ channel: 'live-dashboard.inspection', key, type: 'mode', enabled,
|
|
20
|
+
standard, components: components.map(({ id, elementId }) => ({ id, elementId })) }, '*');
|
|
21
|
+
};
|
|
22
|
+
const receive = (event) => {
|
|
23
|
+
if (disposed || event.source !== frame.contentWindow)
|
|
24
|
+
return;
|
|
25
|
+
const parsed = message.safeParse(event.data);
|
|
26
|
+
if (!parsed.success || parsed.data.key !== key)
|
|
27
|
+
return;
|
|
28
|
+
if (parsed.data.type === 'ready') {
|
|
29
|
+
connected = true;
|
|
30
|
+
send();
|
|
31
|
+
}
|
|
32
|
+
else if (parsed.data.type === 'exit') {
|
|
33
|
+
enabled = false;
|
|
34
|
+
onExit();
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const selected = parsed.data.componentId;
|
|
38
|
+
if (enabled && (selected === null || components.some(item => item.id === selected)))
|
|
39
|
+
onSelect(selected);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
host.addEventListener('message', receive);
|
|
43
|
+
return {
|
|
44
|
+
prefix: `<script>${inspection_runtime_1.DASHBOARD_INSPECTION_RUNTIME.replace('__INSPECTION_SESSION__', key)}</script>`,
|
|
45
|
+
setEnabled(value) { enabled = value; send(); },
|
|
46
|
+
dispose() { enabled = false; send(); disposed = true; host.removeEventListener('message', receive); }
|
|
47
|
+
};
|
|
48
|
+
}
|