@wallarm-org/gen-ui 0.0.0-stage → 0.1.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 (118) hide show
  1. package/README.md +153 -2
  2. package/dist/a2ui/A2uiSurfaces.d.ts +16 -0
  3. package/dist/a2ui/A2uiSurfaces.js +61 -0
  4. package/dist/a2ui/catalog.d.ts +16 -0
  5. package/dist/a2ui/catalog.js +66 -0
  6. package/dist/a2ui/check.d.ts +4 -0
  7. package/dist/a2ui/check.js +34 -0
  8. package/dist/a2ui/express.d.ts +38 -0
  9. package/dist/a2ui/express.js +64 -0
  10. package/dist/a2ui/index.d.ts +8 -0
  11. package/dist/a2ui/index.js +4 -0
  12. package/dist/a2ui/prompt.d.ts +16 -0
  13. package/dist/a2ui/prompt.js +17 -0
  14. package/dist/a2ui/toA2uiSchema.d.ts +19 -0
  15. package/dist/a2ui/toA2uiSchema.js +61 -0
  16. package/dist/components/Alert.d.ts +11 -0
  17. package/dist/components/Alert.js +43 -0
  18. package/dist/components/AreaChart.d.ts +36 -0
  19. package/dist/components/AreaChart.js +90 -0
  20. package/dist/components/Badge.d.ts +11 -0
  21. package/dist/components/Badge.js +30 -0
  22. package/dist/components/BarList.d.ts +26 -0
  23. package/dist/components/BarList.js +66 -0
  24. package/dist/components/Button.d.ts +10 -0
  25. package/dist/components/Button.js +40 -0
  26. package/dist/components/Card.d.ts +2 -0
  27. package/dist/components/Card.js +17 -0
  28. package/dist/components/ColumnChart.d.ts +32 -0
  29. package/dist/components/ColumnChart.js +114 -0
  30. package/dist/components/Grid.d.ts +29 -0
  31. package/dist/components/Grid.js +72 -0
  32. package/dist/components/Heading.d.ts +10 -0
  33. package/dist/components/Heading.js +29 -0
  34. package/dist/components/HorizontalBarStack.d.ts +39 -0
  35. package/dist/components/HorizontalBarStack.js +67 -0
  36. package/dist/components/LineChart.d.ts +36 -0
  37. package/dist/components/LineChart.js +101 -0
  38. package/dist/components/Metric.d.ts +35 -0
  39. package/dist/components/Metric.js +85 -0
  40. package/dist/components/PieChart.d.ts +25 -0
  41. package/dist/components/PieChart.js +83 -0
  42. package/dist/components/Section.d.ts +5 -0
  43. package/dist/components/Section.js +39 -0
  44. package/dist/components/Stack.d.ts +18 -0
  45. package/dist/components/Stack.js +41 -0
  46. package/dist/components/Table.d.ts +30 -0
  47. package/dist/components/Table.js +128 -0
  48. package/dist/components/Text.d.ts +9 -0
  49. package/dist/components/Text.js +27 -0
  50. package/dist/components/index.d.ts +20 -0
  51. package/dist/components/index.js +55 -0
  52. package/dist/core/check.d.ts +35 -0
  53. package/dist/core/check.js +63 -0
  54. package/dist/core/define.d.ts +64 -0
  55. package/dist/core/define.js +7 -0
  56. package/dist/core/format.d.ts +24 -0
  57. package/dist/core/format.js +74 -0
  58. package/dist/core/guards.d.ts +2 -0
  59. package/dist/core/guards.js +2 -0
  60. package/dist/fixtures/apiInventory.d.ts +36 -0
  61. package/dist/fixtures/apiInventory.js +287 -0
  62. package/dist/fixtures/attackSummary.d.ts +13 -0
  63. package/dist/fixtures/attackSummary.js +329 -0
  64. package/dist/fixtures/dashboard.d.ts +119 -0
  65. package/dist/fixtures/dashboard.js +428 -0
  66. package/dist/fixtures/incident.d.ts +44 -0
  67. package/dist/fixtures/incident.js +331 -0
  68. package/dist/fixtures/index.d.ts +13 -0
  69. package/dist/fixtures/index.js +9 -0
  70. package/dist/fixtures/liveMonitor.d.ts +9 -0
  71. package/dist/fixtures/liveMonitor.js +180 -0
  72. package/dist/fixtures/openui.d.ts +16 -0
  73. package/dist/fixtures/openui.js +74 -0
  74. package/dist/fixtures/scenarios.d.ts +13 -0
  75. package/dist/fixtures/scenarios.js +39 -0
  76. package/dist/fixtures/stream.d.ts +79 -0
  77. package/dist/fixtures/stream.js +147 -0
  78. package/dist/fixtures/weeklyReport.d.ts +46 -0
  79. package/dist/fixtures/weeklyReport.js +266 -0
  80. package/dist/index.d.ts +8 -0
  81. package/dist/index.js +4 -0
  82. package/dist/json-render/JsonRenderSurface.d.ts +13 -0
  83. package/dist/json-render/JsonRenderSurface.js +63 -0
  84. package/dist/json-render/catalog.d.ts +64 -0
  85. package/dist/json-render/catalog.js +50 -0
  86. package/dist/json-render/check.d.ts +4 -0
  87. package/dist/json-render/check.js +13 -0
  88. package/dist/json-render/index.d.ts +6 -0
  89. package/dist/json-render/index.js +4 -0
  90. package/dist/json-render/spec.d.ts +23 -0
  91. package/dist/json-render/spec.js +77 -0
  92. package/dist/openui/OpenUiSurface.d.ts +24 -0
  93. package/dist/openui/OpenUiSurface.js +30 -0
  94. package/dist/openui/catalog.d.ts +23 -0
  95. package/dist/openui/catalog.js +65 -0
  96. package/dist/openui/check.d.ts +4 -0
  97. package/dist/openui/check.js +68 -0
  98. package/dist/openui/index.d.ts +5 -0
  99. package/dist/openui/index.js +3 -0
  100. package/dist/playground/GenUiChatDemo.d.ts +11 -0
  101. package/dist/playground/GenUiChatDemo.js +148 -0
  102. package/dist/playground/GenUiPlayground.d.ts +15 -0
  103. package/dist/playground/GenUiPlayground.js +413 -0
  104. package/dist/playground/index.d.ts +3 -0
  105. package/dist/playground/index.js +2 -0
  106. package/dist/playground/useEmulatedAgent.d.ts +37 -0
  107. package/dist/playground/useEmulatedAgent.js +221 -0
  108. package/dist/render/ChartSkeleton.d.ts +6 -0
  109. package/dist/render/ChartSkeleton.js +26 -0
  110. package/dist/render/GuardedView.d.ts +18 -0
  111. package/dist/render/GuardedView.js +24 -0
  112. package/dist/render/Placeholder.d.ts +16 -0
  113. package/dist/render/Placeholder.js +15 -0
  114. package/dist/render/SurfaceBoundary.d.ts +15 -0
  115. package/dist/render/SurfaceBoundary.js +15 -0
  116. package/dist/render/warn.d.ts +1 -0
  117. package/dist/render/warn.js +2 -0
  118. package/package.json +94 -4
@@ -0,0 +1,128 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Badge } from "@wallarm-org/design-system/Badge";
3
+ import { Code } from "@wallarm-org/design-system/Code";
4
+ import { FormatDateTime } from "@wallarm-org/design-system/FormatDateTime";
5
+ import { Heading } from "@wallarm-org/design-system/Heading";
6
+ import { HttpMethod } from "@wallarm-org/design-system/HttpMethod";
7
+ import { Ip, IpAddress } from "@wallarm-org/design-system/Ip";
8
+ import { ResponseCode } from "@wallarm-org/design-system/ResponseCode";
9
+ import { Skeleton } from "@wallarm-org/design-system/Skeleton";
10
+ import { Table, createTableColumnHelper } from "@wallarm-org/design-system/Table";
11
+ import { cn } from "@wallarm-org/design-system/utils/cn";
12
+ import { allOf, defineComponent } from "../core/define.js";
13
+ import { NUMBER_FORMATS, formatNumber } from "../core/format.js";
14
+ import * as __rspack_external_zod from "zod";
15
+ const DATE_FORMATS = allOf()([
16
+ 'relative',
17
+ 'date',
18
+ 'datetime'
19
+ ]);
20
+ const CELL_TYPES = [
21
+ 'text',
22
+ 'number',
23
+ 'badge',
24
+ 'datetime',
25
+ 'code',
26
+ 'ip',
27
+ 'method',
28
+ 'status'
29
+ ];
30
+ const isNumberFormat = (f)=>NUMBER_FORMATS.some((n)=>n === f);
31
+ const isDateFormat = (f)=>DATE_FORMATS.some((d)=>d === f);
32
+ const scalar = (value)=>{
33
+ if ('string' == typeof value || 'number' == typeof value) return value;
34
+ if ('boolean' == typeof value) return String(value);
35
+ };
36
+ const CELLS = {
37
+ text: (value)=>value,
38
+ number: (value, format)=>'number' == typeof value ? formatNumber(value, isNumberFormat(format) ? format : 'number') : value,
39
+ badge: (value)=>/*#__PURE__*/ jsx(Badge, {
40
+ type: "secondary",
41
+ color: "slate",
42
+ children: value
43
+ }),
44
+ datetime: (value, format)=>/*#__PURE__*/ jsx(FormatDateTime, {
45
+ value: value,
46
+ format: isDateFormat(format) ? format : 'datetime',
47
+ layout: "inline"
48
+ }),
49
+ code: (value)=>/*#__PURE__*/ jsx(Code, {
50
+ size: "s",
51
+ truncate: true,
52
+ children: value
53
+ }),
54
+ ip: (value)=>/*#__PURE__*/ jsx(Ip, {
55
+ children: /*#__PURE__*/ jsx(IpAddress, {
56
+ children: value
57
+ })
58
+ }),
59
+ method: (value)=>/*#__PURE__*/ jsx(HttpMethod, {
60
+ method: String(value)
61
+ }),
62
+ status: (value)=>/*#__PURE__*/ jsx(ResponseCode, {
63
+ code: value
64
+ })
65
+ };
66
+ const column = createTableColumnHelper();
67
+ const TableComponent = defineComponent({
68
+ name: 'Table',
69
+ description: 'A read-only table of records: requests, events, IPs, rules. Use it when the user needs to compare rows across several fields; for a ranked top-N of one number prefer BarList. Each row is a flat object of strings and numbers keyed by the column keys; rowKey names the field that is unique per row. Column types: datetime takes an ISO time or epoch ms, ip an IP string, method an HTTP verb, status an HTTP response code, code a short literal (path, payload, rule id), badge a short label. Send rows in display order: there is no sorting, paging or selection.',
70
+ props: __rspack_external_zod.object({
71
+ title: __rspack_external_zod.string().optional(),
72
+ rowKey: __rspack_external_zod.string().describe('The row field that is unique per row, e.g. "requestId"'),
73
+ columns: __rspack_external_zod.array(__rspack_external_zod.object({
74
+ key: __rspack_external_zod.string().describe('The row field this column shows'),
75
+ header: __rspack_external_zod.string(),
76
+ type: __rspack_external_zod["enum"](CELL_TYPES).optional().describe('Default text'),
77
+ format: __rspack_external_zod["enum"]([
78
+ ...NUMBER_FORMATS,
79
+ ...DATE_FORMATS
80
+ ]).optional().describe('number columns: number, compact, percent (0-100), bytes, ms; datetime columns: relative, date, datetime')
81
+ })),
82
+ rows: __rspack_external_zod.array(__rspack_external_zod.looseObject({})).describe('One object per row, keyed by the column keys')
83
+ }),
84
+ Skeleton: ()=>/*#__PURE__*/ jsx(Skeleton, {
85
+ width: "100%",
86
+ height: "240px",
87
+ rounded: 8,
88
+ transparent: false
89
+ }),
90
+ View: ({ props })=>{
91
+ const columns = props.columns.map(({ key, header, type = 'text', format })=>column.accessor(key, {
92
+ header: header ?? key,
93
+ meta: {
94
+ align: 'number' === type ? 'right' : 'left'
95
+ },
96
+ cell: ({ row })=>{
97
+ const value = scalar(row.original[key]);
98
+ return void 0 === value || '' === value ? '—' : CELLS[type](value, format);
99
+ }
100
+ }));
101
+ const { rows } = props;
102
+ const seen = new Set();
103
+ const rowIds = rows.map((row, index)=>{
104
+ const base = String(scalar(row[props.rowKey]) ?? `#${index}`);
105
+ const rowId = seen.has(base) ? `${base}#${index}` : base;
106
+ seen.add(rowId);
107
+ return rowId;
108
+ });
109
+ const getRowId = (_row, index)=>rowIds[index] ?? String(index);
110
+ return /*#__PURE__*/ jsxs("div", {
111
+ className: cn('flex min-w-0 flex-col gap-8'),
112
+ children: [
113
+ props.title && /*#__PURE__*/ jsx(Heading, {
114
+ size: "md",
115
+ weight: "medium",
116
+ children: props.title
117
+ }),
118
+ /*#__PURE__*/ jsx(Table, {
119
+ data: rows,
120
+ columns: columns,
121
+ getRowId: getRowId,
122
+ "aria-label": props.title
123
+ })
124
+ ]
125
+ });
126
+ }
127
+ });
128
+ export { TableComponent };
@@ -0,0 +1,9 @@
1
+ import * as z from 'zod';
2
+ export declare const TextComponent: import("../index.js").GenUiComponent<z.ZodObject<{
3
+ text: z.ZodString;
4
+ tone: z.ZodOptional<z.ZodEnum<{
5
+ danger: "danger";
6
+ primary: "primary";
7
+ secondary: "secondary";
8
+ }>>;
9
+ }, z.core.$strip>>;
@@ -0,0 +1,27 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Skeleton } from "@wallarm-org/design-system/Skeleton";
3
+ import { Text } from "@wallarm-org/design-system/Text";
4
+ import { defineComponent, subsetOf } from "../core/define.js";
5
+ import * as __rspack_external_zod from "zod";
6
+ const TextComponent = defineComponent({
7
+ name: 'Text',
8
+ description: 'A paragraph of plain text (no markdown).',
9
+ props: __rspack_external_zod.object({
10
+ text: __rspack_external_zod.string(),
11
+ tone: __rspack_external_zod["enum"](subsetOf()([
12
+ 'primary',
13
+ 'secondary',
14
+ 'danger'
15
+ ])).optional()
16
+ }),
17
+ Skeleton: ()=>/*#__PURE__*/ jsx(Skeleton, {
18
+ width: "100%",
19
+ height: "16px",
20
+ transparent: false
21
+ }),
22
+ View: ({ props })=>/*#__PURE__*/ jsx(Text, {
23
+ color: props.tone ?? 'primary',
24
+ children: props.text
25
+ })
26
+ });
27
+ export { TextComponent };
@@ -0,0 +1,20 @@
1
+ import type { GenUiComponent } from '../core/define.js';
2
+ export * from './Alert.js';
3
+ export * from './AreaChart.js';
4
+ export * from './Badge.js';
5
+ export * from './BarList.js';
6
+ export * from './Button.js';
7
+ export * from './Card.js';
8
+ export * from './ColumnChart.js';
9
+ export * from './Grid.js';
10
+ export * from './Heading.js';
11
+ export * from './HorizontalBarStack.js';
12
+ export * from './LineChart.js';
13
+ export * from './Metric.js';
14
+ export * from './PieChart.js';
15
+ export * from './Section.js';
16
+ export * from './Stack.js';
17
+ export * from './Table.js';
18
+ export * from './Text.js';
19
+ /** The catalog: layout (Section, Grid, Stack, Card), text, status, actions, charts and Table. */
20
+ export declare const wallarmComponents: readonly GenUiComponent[];
@@ -0,0 +1,55 @@
1
+ import { AlertComponent } from "./Alert.js";
2
+ import { AreaChartComponent } from "./AreaChart.js";
3
+ import { BadgeComponent } from "./Badge.js";
4
+ import { BarListComponent } from "./BarList.js";
5
+ import { ButtonComponent } from "./Button.js";
6
+ import { CardComponent } from "./Card.js";
7
+ import { ColumnChartComponent } from "./ColumnChart.js";
8
+ import { GridComponent, GridItemComponent } from "./Grid.js";
9
+ import { HeadingComponent } from "./Heading.js";
10
+ import { HorizontalBarStackComponent } from "./HorizontalBarStack.js";
11
+ import { LineChartComponent } from "./LineChart.js";
12
+ import { MetricComponent } from "./Metric.js";
13
+ import { PieChartComponent } from "./PieChart.js";
14
+ import { SectionComponent } from "./Section.js";
15
+ import { StackComponent } from "./Stack.js";
16
+ import { TableComponent } from "./Table.js";
17
+ import { TextComponent } from "./Text.js";
18
+ export * from "./Alert.js";
19
+ export * from "./AreaChart.js";
20
+ export * from "./Badge.js";
21
+ export * from "./BarList.js";
22
+ export * from "./Button.js";
23
+ export * from "./Card.js";
24
+ export * from "./ColumnChart.js";
25
+ export * from "./Grid.js";
26
+ export * from "./Heading.js";
27
+ export * from "./HorizontalBarStack.js";
28
+ export * from "./LineChart.js";
29
+ export * from "./Metric.js";
30
+ export * from "./PieChart.js";
31
+ export * from "./Section.js";
32
+ export * from "./Stack.js";
33
+ export * from "./Table.js";
34
+ export * from "./Text.js";
35
+ const wallarmComponents = [
36
+ SectionComponent,
37
+ GridComponent,
38
+ GridItemComponent,
39
+ StackComponent,
40
+ CardComponent,
41
+ HeadingComponent,
42
+ TextComponent,
43
+ BadgeComponent,
44
+ AlertComponent,
45
+ ButtonComponent,
46
+ MetricComponent,
47
+ BarListComponent,
48
+ HorizontalBarStackComponent,
49
+ PieChartComponent,
50
+ LineChartComponent,
51
+ AreaChartComponent,
52
+ ColumnChartComponent,
53
+ TableComponent
54
+ ];
55
+ export { wallarmComponents };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Checks a finished answer for the agent's own mistakes, the ones that would leave a skeleton on
3
+ * the page for good: an unknown component, a prop its schema rejects, a child that was never
4
+ * sent, an action outside the allowlist. A bound prop is never an issue: its value is the app's.
5
+ * Each format reads its answer into nodes (`checkA2uiAnswer`, `checkJsonRenderAnswer`); the result
6
+ * goes back to the model as a "fix these" message (`describeIssues`) or into an eval.
7
+ */
8
+ import type { GenUiAction, GenUiComponent } from './define.js';
9
+ /** One component of an answer, as both formats describe it. */
10
+ export interface AnswerNode {
11
+ id: string;
12
+ type: string;
13
+ /** Data props only: no children, no action props. */
14
+ props: Record<string, unknown>;
15
+ children: readonly string[];
16
+ /** Names of the actions the component fires. */
17
+ actions: readonly string[];
18
+ }
19
+ export interface GenUiIssue {
20
+ /** The agent's component id; the root's id for an issue with the answer as a whole. */
21
+ id: string;
22
+ component?: string;
23
+ /** The prop, dot-separated, when the issue is in one. */
24
+ prop?: string;
25
+ message: string;
26
+ }
27
+ export interface CheckOptions {
28
+ components: readonly GenUiComponent[];
29
+ actions: readonly GenUiAction[];
30
+ /** Report a number written into a prop instead of bound: a figure the model may have made up. */
31
+ boundFigures?: boolean;
32
+ }
33
+ export declare const checkNodes: (nodes: readonly AnswerNode[], rootId: string | undefined, isBinding: (value: unknown) => boolean, { components, actions, boundFigures }: CheckOptions) => GenUiIssue[];
34
+ /** The issues as one message to send the model, asking it to resend only those components. */
35
+ export declare const describeIssues: (issues: readonly GenUiIssue[]) => string;
@@ -0,0 +1,63 @@
1
+ import { isRecord } from "./guards.js";
2
+ const checkNodes = (nodes, rootId, isBinding, { components, actions, boundFigures = false })=>{
3
+ const issues = [];
4
+ const ids = new Set(nodes.map((node)=>node.id));
5
+ if (!rootId || !ids.has(rootId)) issues.push({
6
+ id: rootId ?? 'root',
7
+ message: 'The answer has no root component.'
8
+ });
9
+ for (const node of nodes){
10
+ const at = {
11
+ id: node.id,
12
+ component: node.type
13
+ };
14
+ const entry = components.find((c)=>c.name === node.type);
15
+ if (!entry) {
16
+ issues.push({
17
+ ...at,
18
+ message: `Unknown component "${node.type}".`
19
+ });
20
+ continue;
21
+ }
22
+ const parsed = entry.props.safeParse(node.props);
23
+ for (const issue of parsed.success ? [] : parsed.error.issues)if (!boundOnPath(node.props, issue.path, isBinding)) issues.push({
24
+ ...at,
25
+ prop: issue.path.join('.') || void 0,
26
+ message: issue.message
27
+ });
28
+ for (const child of node.children)if (!ids.has(child)) issues.push({
29
+ ...at,
30
+ message: `Child "${child}" was never sent.`
31
+ });
32
+ for (const action of node.actions)if (!actions.some((a)=>a.name === action)) issues.push({
33
+ ...at,
34
+ message: `Action "${action}" is not allowed.`
35
+ });
36
+ if (boundFigures) for (const prop of literalNumbers(node.props, isBinding))issues.push({
37
+ ...at,
38
+ prop,
39
+ message: 'A figure is written in; bind it to the app data.'
40
+ });
41
+ }
42
+ return issues;
43
+ };
44
+ const describeIssues = (issues)=>[
45
+ 'Some components in your answer cannot render. Fix them and resend only these components:',
46
+ ...issues.map((i)=>`- ${i.id}${i.component ? ` (${i.component})` : ''}${i.prop ? `, ${i.prop}` : ''}: ${i.message}`)
47
+ ].join('\n');
48
+ const boundOnPath = (props, path, isBinding)=>{
49
+ let value = props;
50
+ for (const key of path){
51
+ if (isBinding(value)) return true;
52
+ value = 'object' == typeof value && null !== value ? Reflect.get(value, key) : void 0;
53
+ }
54
+ return isBinding(value);
55
+ };
56
+ const literalNumbers = (value, isBinding, prefix = '')=>{
57
+ if ('number' == typeof value) return [
58
+ prefix
59
+ ];
60
+ if (isBinding(value) || !(isRecord(value) || Array.isArray(value))) return [];
61
+ return Object.entries(value).flatMap(([key, v])=>literalNumbers(v, isBinding, prefix ? `${prefix}.${key}` : key));
62
+ };
63
+ export { checkNodes, describeIssues };
@@ -0,0 +1,64 @@
1
+ import type { FC, ReactNode } from 'react';
2
+ import * as z from 'zod';
3
+ /** What a component's View receives from either format's renderer. */
4
+ export interface GenUiViewProps<P> {
5
+ /** Props with every binding already resolved to a value. */
6
+ props: P;
7
+ /** Fires one of the component's `events`; the format decides what reaches the agent. */
8
+ emit: (event: string) => void;
9
+ /** Rendered children, when the component `hasChildren`. */
10
+ children?: ReactNode;
11
+ }
12
+ /**
13
+ * One catalog entry, written once and rendered by both formats.
14
+ *
15
+ * Constraints that keep it portable:
16
+ * - `props` is a plain zod object of strings, numbers, booleans, enums, arrays and objects:
17
+ * no functions, no ReactNode.
18
+ * - No prop named `id`, `component`, `children` or `child`: A2UI puts props flat next to them.
19
+ * - Events carry no arguments: the spec, not the component, decides what an action sends.
20
+ */
21
+ export interface GenUiComponent<S extends z.ZodObject = z.ZodObject> {
22
+ name: string;
23
+ /** Read by the model: say when to use it, not how it looks. */
24
+ description: string;
25
+ props: S;
26
+ events?: readonly string[];
27
+ hasChildren?: boolean;
28
+ View: FC<GenUiViewProps<z.infer<S>>>;
29
+ /**
30
+ * Drawn while the props don't match the schema yet (mid-stream: data still on its way), shaped
31
+ * like the loaded component so the layout doesn't jump. Gets the title once it has streamed in.
32
+ * Default: a plain block.
33
+ */
34
+ Skeleton?: FC<{
35
+ title?: string;
36
+ }>;
37
+ }
38
+ /** An app action a spec may bind a component event to, e.g. `block_ip`. */
39
+ export interface GenUiAction {
40
+ name: string;
41
+ description: string;
42
+ }
43
+ /** Where both formats deliver a fired action; `params` comes from the spec, never from the View. */
44
+ export type GenUiActionHandler = (name: string, params: Record<string, unknown>) => void;
45
+ export declare const defineComponent: <S extends z.ZodObject>(c: GenUiComponent<S>) => GenUiComponent<S>;
46
+ /** The string values of a DS prop type: `Values<BadgeProps['color']>`. */
47
+ export type Values<T> = Extract<NonNullable<T>, string>;
48
+ /**
49
+ * The enum values a catalog entry offers, checked against the DS union they come from, so the two
50
+ * can't drift: `z.enum(subsetOf<BadgeColor>()(['slate', 'red']))`. A value the DS renames or removes
51
+ * fails typecheck. Use it where the catalog deliberately offers fewer values than the DS has.
52
+ */
53
+ export declare const subsetOf: <T extends string>() => <const A extends readonly [T, ...T[]]>(values: A) => A;
54
+ /**
55
+ * Like `subsetOf`, for a DS union the catalog offers in full (a meaning, not a palette). It also
56
+ * fails typecheck with `{ missing: '<value>' }` when the DS adds a value the list lacks.
57
+ */
58
+ export declare const allOf: <T extends string>() => <const A extends readonly [T, ...T[]]>(values: A & ([Exclude<T, A[number]>] extends [never] ? unknown : {
59
+ missing: Exclude<T, A[number]>;
60
+ })) => A;
61
+ /** A series' field in each point. `x` is the axis, and `__`-prefixed keys are the Views' own. */
62
+ export declare const seriesKey: z.ZodString;
63
+ /** For `.refine` on an array of items keyed by `field`: React keys and the DS join on it. */
64
+ export declare const unique: <K extends string>(field: K) => (items: readonly Partial<Record<K, unknown>>[]) => boolean;
@@ -0,0 +1,7 @@
1
+ import * as __rspack_external_zod from "zod";
2
+ const defineComponent = (c)=>c;
3
+ const subsetOf = ()=>(values)=>values;
4
+ const allOf = ()=>(values)=>values;
5
+ const seriesKey = __rspack_external_zod.string().refine((key)=>'x' !== key && !key.startsWith('__'), 'x and __-prefixed keys are reserved');
6
+ const unique = (field)=>(items)=>new Set(items.map((item)=>item[field])).size === items.length;
7
+ export { allOf, defineComponent, seriesKey, subsetOf, unique };
@@ -0,0 +1,24 @@
1
+ import * as z from 'zod';
2
+ /**
3
+ * Named formats instead of formatter functions: a spec is data, so a chart axis or a table cell
4
+ * says `'percent'` and the View formats it. One registry for Metric, the charts and Table.
5
+ */
6
+ export declare const NUMBER_FORMATS: readonly ['number', 'compact', 'percent', 'bytes', 'ms'];
7
+ export declare const TIME_FORMATS: readonly ['time', 'date', 'datetime'];
8
+ export type NumberFormat = (typeof NUMBER_FORMATS)[number];
9
+ export type TimeFormat = (typeof TIME_FORMATS)[number];
10
+ export declare const numberFormat: z.ZodOptional<z.ZodEnum<{
11
+ bytes: "bytes";
12
+ compact: "compact";
13
+ ms: "ms";
14
+ number: "number";
15
+ percent: "percent";
16
+ }>>;
17
+ export declare const timeFormat: z.ZodOptional<z.ZodEnum<{
18
+ date: "date";
19
+ datetime: "datetime";
20
+ time: "time";
21
+ }>>;
22
+ export declare const formatNumber: (value: number, format?: NumberFormat) => string;
23
+ /** An ISO string or epoch ms; an unparseable value is printed as is. */
24
+ export declare const formatTime: (value: string | number, format?: TimeFormat) => string;
@@ -0,0 +1,74 @@
1
+ import * as __rspack_external_zod from "zod";
2
+ const NUMBER_FORMATS = [
3
+ 'number',
4
+ 'compact',
5
+ 'percent',
6
+ 'bytes',
7
+ 'ms'
8
+ ];
9
+ const TIME_FORMATS = [
10
+ 'time',
11
+ 'date',
12
+ 'datetime'
13
+ ];
14
+ const numberFormat = __rspack_external_zod["enum"](NUMBER_FORMATS).optional().describe('number 1,240 · compact 1.2K · percent 42% (value is 0-100) · bytes 1.2 MB · ms 340 ms');
15
+ const timeFormat = __rspack_external_zod["enum"](TIME_FORMATS).optional().describe('How to print ISO timestamps: time 14:05 · date 5 Nov · datetime 5 Nov, 14:05');
16
+ const BYTE_UNITS = [
17
+ 'B',
18
+ 'KB',
19
+ 'MB',
20
+ 'GB',
21
+ 'TB'
22
+ ];
23
+ const formatNumber = (value, format = 'number')=>{
24
+ switch(format){
25
+ case 'compact':
26
+ return new Intl.NumberFormat('en-US', {
27
+ notation: 'compact',
28
+ maximumFractionDigits: 1
29
+ }).format(value);
30
+ case 'percent':
31
+ return `${new Intl.NumberFormat('en-US', {
32
+ maximumFractionDigits: 1
33
+ }).format(value)}%`;
34
+ case 'bytes':
35
+ {
36
+ let unit = 0;
37
+ let n = Math.abs(value);
38
+ while(n >= 1024 && unit < BYTE_UNITS.length - 1){
39
+ n /= 1024;
40
+ unit++;
41
+ }
42
+ return `${Math.sign(value) < 0 ? '-' : ''}${n.toFixed(unit && n < 10 ? 1 : 0)} ${BYTE_UNITS[unit]}`;
43
+ }
44
+ case 'ms':
45
+ return `${new Intl.NumberFormat('en-US', {
46
+ maximumFractionDigits: 0
47
+ }).format(value)} ms`;
48
+ default:
49
+ return value.toLocaleString('en-US');
50
+ }
51
+ };
52
+ const TIME_OPTIONS = {
53
+ time: {
54
+ hour: '2-digit',
55
+ minute: '2-digit',
56
+ hourCycle: 'h23'
57
+ },
58
+ date: {
59
+ day: 'numeric',
60
+ month: 'short'
61
+ },
62
+ datetime: {
63
+ day: 'numeric',
64
+ month: 'short',
65
+ hour: '2-digit',
66
+ minute: '2-digit',
67
+ hourCycle: 'h23'
68
+ }
69
+ };
70
+ const formatTime = (value, format = 'datetime')=>{
71
+ const date = new Date(value);
72
+ return Number.isNaN(date.getTime()) ? String(value) : new Intl.DateTimeFormat('en-GB', TIME_OPTIONS[format]).format(date);
73
+ };
74
+ export { NUMBER_FORMATS, TIME_FORMATS, formatNumber, formatTime, numberFormat, timeFormat };
@@ -0,0 +1,2 @@
1
+ /** Agent output is untrusted: narrow before reading a field. */
2
+ export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
@@ -0,0 +1,2 @@
1
+ const isRecord = (value)=>'object' == typeof value && null !== value && !Array.isArray(value);
2
+ export { isRecord };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * An API inventory answer: the agent lays out where sensitive data is exposed, with every figure
3
+ * bound to a path, and the app fills those paths from its API Discovery data.
4
+ */
5
+ import type { GenUiAction } from '../core/define.js';
6
+ import { type Scenario } from './stream.js';
7
+ export declare const API_INVENTORY_DATA: {
8
+ kpi: {
9
+ endpoints: number;
10
+ sensitive: number;
11
+ unauthenticated: number;
12
+ newThisWeek: number;
13
+ };
14
+ dataTypes: {
15
+ label: string;
16
+ value: number;
17
+ color: string;
18
+ }[];
19
+ newEndpoints: {
20
+ x: string;
21
+ sensitive: number;
22
+ other: number;
23
+ }[];
24
+ endpoints: {
25
+ id: string;
26
+ method: string;
27
+ path: string;
28
+ status: number;
29
+ dataType: string;
30
+ hits: number;
31
+ last: string;
32
+ }[];
33
+ };
34
+ export declare const API_INVENTORY_ACTIONS: readonly GenUiAction[];
35
+ /** API inventory: KPI tiles, sensitive data types, new endpoints per day and an endpoints table. */
36
+ export declare const API_INVENTORY_SCENARIO: Scenario;