@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.
Files changed (55) hide show
  1. package/.xpertai-plugin/plugin.json +1 -1
  2. package/README.md +4 -0
  3. package/dist/lib/agent.schema.d.ts +179 -25
  4. package/dist/lib/agent.schema.js +10 -9
  5. package/dist/lib/archive.service.d.ts +145 -0
  6. package/dist/lib/archive.service.js +133 -0
  7. package/dist/lib/content.provider.d.ts +1 -1
  8. package/dist/lib/dashboard-archive.d.ts +70 -0
  9. package/dist/lib/dashboard-archive.js +118 -0
  10. package/dist/lib/dashboard-sources.d.ts +69 -0
  11. package/dist/lib/dashboard-sources.js +37 -0
  12. package/dist/lib/dashboard-view.schema.d.ts +503 -88
  13. package/dist/lib/dashboard-view.schema.js +2 -1
  14. package/dist/lib/dashboard.schema.d.ts +379 -58
  15. package/dist/lib/dashboard.schema.js +18 -1
  16. package/dist/lib/dashboard.service.d.ts +72 -17
  17. package/dist/lib/dashboard.service.js +21 -3
  18. package/dist/lib/document-package.d.ts +19 -4
  19. package/dist/lib/editing-patch.d.ts +3 -0
  20. package/dist/lib/editing-patch.js +2 -1
  21. package/dist/lib/editing-session.d.ts +4 -4
  22. package/dist/lib/editing.d.ts +202 -19
  23. package/dist/lib/editing.js +5 -2
  24. package/dist/lib/html-validation-feedback.d.ts +7 -0
  25. package/dist/lib/html-validation-feedback.js +19 -0
  26. package/dist/lib/html-validation.js +2 -1
  27. package/dist/lib/inspection-host.d.ts +7 -0
  28. package/dist/lib/inspection-host.js +48 -0
  29. package/dist/lib/inspection-runtime.d.ts +2 -0
  30. package/dist/lib/inspection-runtime.js +77 -0
  31. package/dist/lib/json-input.d.ts +4 -0
  32. package/dist/lib/json-input.js +21 -0
  33. package/dist/lib/middleware.js +3 -2
  34. package/dist/lib/plugin.js +2 -1
  35. package/dist/lib/presentation.provider.d.ts +24 -9
  36. package/dist/lib/presentation.provider.js +2 -1
  37. package/dist/lib/projects.schema.d.ts +14 -0
  38. package/dist/lib/projects.schema.js +2 -1
  39. package/dist/lib/projects.service.d.ts +2 -0
  40. package/dist/lib/projects.service.js +10 -0
  41. package/dist/lib/source-executions.d.ts +196 -0
  42. package/dist/lib/source-executions.js +25 -0
  43. package/dist/lib/source-validation.d.ts +2 -0
  44. package/dist/lib/source-validation.js +21 -0
  45. package/dist/lib/view.provider.d.ts +211 -12
  46. package/dist/lib/view.provider.js +43 -9
  47. package/dist/remote/app.css +1 -1
  48. package/dist/remote/app.js +99 -26
  49. package/dist/remote/build-manifest.json +42 -27
  50. package/docs/docs.json +3 -1
  51. package/docs/sources-inspect-portability-acceptance.mdx +67 -0
  52. package/docs/sources-inspect-portability.mdx +115 -0
  53. package/package.json +6 -5
  54. package/skills/live-dashboard/SKILL.md +5 -4
  55. package/skills/live-dashboard/references/source-inspection.md +17 -0
@@ -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>)[];
@@ -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 changes instead of dropping title. 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.' } : {}) });
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 new common_1.BadRequestException(`DASHBOARD_HTML_PREFLIGHT_FAILED: ${JSON.stringify(report.errors)}. Repair the Workspace HTML or include every required previewId, then retry. No dashboard was saved.`);
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
+ }
@@ -0,0 +1,2 @@
1
+ /** Injected into the isolated dashboard only; it never reads or executes query definitions. */
2
+ export declare const DASHBOARD_INSPECTION_RUNTIME: string;