@femtomc/mu-core 26.2.106 → 26.2.108

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/README.md CHANGED
@@ -34,20 +34,27 @@ await runContext({ runId: newRunId() }, async () => {
34
34
  console.log(await jsonl.read());
35
35
  ```
36
36
 
37
- ## HUD contract helpers
37
+ ## UI contract helpers
38
38
 
39
- `@femtomc/mu-core` exports a versioned HUD contract, deterministic JSON helper, and shared runtime loop:
39
+ Interactive UI documents are modeled as first-class, versioned contracts that describe renderable components, actions, and revisions so any rendering surface can stay in sync with agents. `@femtomc/mu-core` exposes the following helpers:
40
40
 
41
- - `HudDocSchema`, `HUD_CONTRACT_VERSION`
42
- - `parseHudDoc(...)`, `normalizeHudDocs(...)`
43
- - `resolveHudStylePresetName(...)`, `applyHudStylePreset(...)`, `hudStylePresetWarnings(...)`
44
- - `serializeHudDocTextFallback(...)`, `serializeHudDocsTextFallback(...)`
45
- - `stableSerializeJson(...)`
46
- - `HudRuntime` + `HudProvider` for provider registration, reducer updates, ordered effect execution, and HUD snapshot emission
41
+ - `UI_CONTRACT_VERSION`, `UiDocSchema`, `UiRevisionSchema`, `UiComponentSchema`, and `UiActionSchema` for validating document payloads.
42
+ - `parseUiDoc(...)`, `normalizeUiDocs(...)`, and `uiDocRevisionConflict(...)` for deterministic selection, conflict detection, and safe merging of candidate documents.
43
+ - `resolveUiStatusProfileName(...)` and `uiStatusProfileWarnings(...)` for advisory validation of profile-scoped status docs (`planning`, `subagents`, `control-flow`, `model-routing`) carried in `metadata.profile`.
44
+ - `UiEventSchema` + `parseUiEvent(...)` for structured event payloads emitted by frontends (every event includes `ui_id`, `action_id`, the originating `revision`, optional `callback_token`, `payload`, and `created_at_ms`).
45
+ - `stableSerializeJson(...)` for deterministic metadata serialization and revision tie-breaking.
47
46
 
48
- `HudDoc` also supports optional presentation hints (`title_style`, `snapshot_style`, chip/item/section/action style objects) and metadata style presets (`metadata.style_preset` currently `planning|subagents`) so renderers can opt into richer emphasis while preserving deterministic plain-text fallbacks.
47
+ ### Field limits
49
48
 
50
- These are runtime-agnostic primitives intended for shared HUD capture/render pipelines.
49
+ The UI contract enforces strict bounds to keep cross-frontends renderable:
50
+
51
+ - titles are capped at 256 characters and summaries at 1024 characters.
52
+ - documents can contain at most 64 components, where text segments are limited to 2048 characters, lists can hold at most 32 items, and key/value rows are capped at 32 entries.
53
+ - actions are limited to 32 entries; labels are 128 characters, descriptions 512, and callback tokens 128.
54
+
55
+ ### Deterministic ordering
56
+
57
+ `normalizeUiDocs(...)` deduplicates by `ui_id`, chooses the highest `revision.version`, breaks ties with `updated_at_ms`, and falls back to a stable JSON comparison (`stableSerializeJson`) so every renderer observes the same ordering. Use `uiDocRevisionConflict(...)` to detect when two docs claim the same revision but differ, enabling agents to guard against race conditions.
51
58
 
52
59
  ## Tests / Typecheck
53
60
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export * from "./events.js";
2
- export * from "./hud.js";
3
- export * from "./hud_runtime.js";
4
2
  export * from "./ids.js";
5
3
  export * from "./persistence.js";
6
4
  export * from "./spec.js";
5
+ export * from "./ui.js";
7
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from "./events.js";
2
- export * from "./hud.js";
3
- export * from "./hud_runtime.js";
4
2
  export * from "./ids.js";
5
3
  export * from "./persistence.js";
6
4
  export * from "./spec.js";
5
+ export * from "./ui.js";
package/dist/ui.d.ts ADDED
@@ -0,0 +1,298 @@
1
+ import { z } from "zod";
2
+ export declare const UiToneSchema: z.ZodEnum<{
3
+ error: "error";
4
+ success: "success";
5
+ info: "info";
6
+ warning: "warning";
7
+ muted: "muted";
8
+ accent: "accent";
9
+ dim: "dim";
10
+ }>;
11
+ export type UiTone = z.infer<typeof UiToneSchema>;
12
+ export declare const UI_CONTRACT_VERSION: 1;
13
+ export declare const UiListItemSchema: z.ZodObject<{
14
+ id: z.ZodString;
15
+ label: z.ZodString;
16
+ detail: z.ZodOptional<z.ZodString>;
17
+ tone: z.ZodOptional<z.ZodEnum<{
18
+ error: "error";
19
+ success: "success";
20
+ info: "info";
21
+ warning: "warning";
22
+ muted: "muted";
23
+ accent: "accent";
24
+ dim: "dim";
25
+ }>>;
26
+ }, z.core.$strict>;
27
+ export type UiListItem = z.infer<typeof UiListItemSchema>;
28
+ export declare const UiKeyValueRowSchema: z.ZodObject<{
29
+ key: z.ZodString;
30
+ value: z.ZodString;
31
+ tone: z.ZodOptional<z.ZodEnum<{
32
+ error: "error";
33
+ success: "success";
34
+ info: "info";
35
+ warning: "warning";
36
+ muted: "muted";
37
+ accent: "accent";
38
+ dim: "dim";
39
+ }>>;
40
+ }, z.core.$strict>;
41
+ export type UiKeyValueRow = z.infer<typeof UiKeyValueRowSchema>;
42
+ export declare const UiComponentTextSchema: z.ZodObject<{
43
+ kind: z.ZodLiteral<"text">;
44
+ id: z.ZodString;
45
+ text: z.ZodString;
46
+ tone: z.ZodOptional<z.ZodEnum<{
47
+ error: "error";
48
+ success: "success";
49
+ info: "info";
50
+ warning: "warning";
51
+ muted: "muted";
52
+ accent: "accent";
53
+ dim: "dim";
54
+ }>>;
55
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
56
+ }, z.core.$strict>;
57
+ export type UiComponentText = z.infer<typeof UiComponentTextSchema>;
58
+ export declare const UiComponentListSchema: z.ZodObject<{
59
+ kind: z.ZodLiteral<"list">;
60
+ id: z.ZodString;
61
+ title: z.ZodOptional<z.ZodString>;
62
+ items: z.ZodArray<z.ZodObject<{
63
+ id: z.ZodString;
64
+ label: z.ZodString;
65
+ detail: z.ZodOptional<z.ZodString>;
66
+ tone: z.ZodOptional<z.ZodEnum<{
67
+ error: "error";
68
+ success: "success";
69
+ info: "info";
70
+ warning: "warning";
71
+ muted: "muted";
72
+ accent: "accent";
73
+ dim: "dim";
74
+ }>>;
75
+ }, z.core.$strict>>;
76
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
77
+ }, z.core.$strict>;
78
+ export declare const UiComponentKeyValueSchema: z.ZodObject<{
79
+ kind: z.ZodLiteral<"key_value">;
80
+ id: z.ZodString;
81
+ title: z.ZodOptional<z.ZodString>;
82
+ rows: z.ZodArray<z.ZodObject<{
83
+ key: z.ZodString;
84
+ value: z.ZodString;
85
+ tone: z.ZodOptional<z.ZodEnum<{
86
+ error: "error";
87
+ success: "success";
88
+ info: "info";
89
+ warning: "warning";
90
+ muted: "muted";
91
+ accent: "accent";
92
+ dim: "dim";
93
+ }>>;
94
+ }, z.core.$strict>>;
95
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
96
+ }, z.core.$strict>;
97
+ export declare const UiComponentDividerSchema: z.ZodObject<{
98
+ kind: z.ZodLiteral<"divider">;
99
+ id: z.ZodString;
100
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
101
+ }, z.core.$strict>;
102
+ export declare const UiComponentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
103
+ kind: z.ZodLiteral<"text">;
104
+ id: z.ZodString;
105
+ text: z.ZodString;
106
+ tone: z.ZodOptional<z.ZodEnum<{
107
+ error: "error";
108
+ success: "success";
109
+ info: "info";
110
+ warning: "warning";
111
+ muted: "muted";
112
+ accent: "accent";
113
+ dim: "dim";
114
+ }>>;
115
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
116
+ }, z.core.$strict>, z.ZodObject<{
117
+ kind: z.ZodLiteral<"list">;
118
+ id: z.ZodString;
119
+ title: z.ZodOptional<z.ZodString>;
120
+ items: z.ZodArray<z.ZodObject<{
121
+ id: z.ZodString;
122
+ label: z.ZodString;
123
+ detail: z.ZodOptional<z.ZodString>;
124
+ tone: z.ZodOptional<z.ZodEnum<{
125
+ error: "error";
126
+ success: "success";
127
+ info: "info";
128
+ warning: "warning";
129
+ muted: "muted";
130
+ accent: "accent";
131
+ dim: "dim";
132
+ }>>;
133
+ }, z.core.$strict>>;
134
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
135
+ }, z.core.$strict>, z.ZodObject<{
136
+ kind: z.ZodLiteral<"key_value">;
137
+ id: z.ZodString;
138
+ title: z.ZodOptional<z.ZodString>;
139
+ rows: z.ZodArray<z.ZodObject<{
140
+ key: z.ZodString;
141
+ value: z.ZodString;
142
+ tone: z.ZodOptional<z.ZodEnum<{
143
+ error: "error";
144
+ success: "success";
145
+ info: "info";
146
+ warning: "warning";
147
+ muted: "muted";
148
+ accent: "accent";
149
+ dim: "dim";
150
+ }>>;
151
+ }, z.core.$strict>>;
152
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
153
+ }, z.core.$strict>, z.ZodObject<{
154
+ kind: z.ZodLiteral<"divider">;
155
+ id: z.ZodString;
156
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
157
+ }, z.core.$strict>], "kind">;
158
+ export type UiComponent = z.infer<typeof UiComponentSchema>;
159
+ export declare const UiActionKindSchema: z.ZodEnum<{
160
+ primary: "primary";
161
+ secondary: "secondary";
162
+ danger: "danger";
163
+ link: "link";
164
+ }>;
165
+ export type UiActionKind = z.infer<typeof UiActionKindSchema>;
166
+ export declare const UiActionSchema: z.ZodObject<{
167
+ id: z.ZodString;
168
+ label: z.ZodString;
169
+ kind: z.ZodOptional<z.ZodEnum<{
170
+ primary: "primary";
171
+ secondary: "secondary";
172
+ danger: "danger";
173
+ link: "link";
174
+ }>>;
175
+ description: z.ZodOptional<z.ZodString>;
176
+ component_id: z.ZodOptional<z.ZodString>;
177
+ callback_token: z.ZodOptional<z.ZodString>;
178
+ payload: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
179
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
180
+ }, z.core.$strict>;
181
+ export type UiAction = z.infer<typeof UiActionSchema>;
182
+ export declare const UiRevisionSchema: z.ZodObject<{
183
+ id: z.ZodString;
184
+ version: z.ZodNumber;
185
+ }, z.core.$strict>;
186
+ export type UiRevision = z.infer<typeof UiRevisionSchema>;
187
+ export declare const UiDocSchema: z.ZodObject<{
188
+ v: z.ZodDefault<z.ZodLiteral<1>>;
189
+ ui_id: z.ZodString;
190
+ title: z.ZodString;
191
+ summary: z.ZodOptional<z.ZodString>;
192
+ components: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
193
+ kind: z.ZodLiteral<"text">;
194
+ id: z.ZodString;
195
+ text: z.ZodString;
196
+ tone: z.ZodOptional<z.ZodEnum<{
197
+ error: "error";
198
+ success: "success";
199
+ info: "info";
200
+ warning: "warning";
201
+ muted: "muted";
202
+ accent: "accent";
203
+ dim: "dim";
204
+ }>>;
205
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
206
+ }, z.core.$strict>, z.ZodObject<{
207
+ kind: z.ZodLiteral<"list">;
208
+ id: z.ZodString;
209
+ title: z.ZodOptional<z.ZodString>;
210
+ items: z.ZodArray<z.ZodObject<{
211
+ id: z.ZodString;
212
+ label: z.ZodString;
213
+ detail: z.ZodOptional<z.ZodString>;
214
+ tone: z.ZodOptional<z.ZodEnum<{
215
+ error: "error";
216
+ success: "success";
217
+ info: "info";
218
+ warning: "warning";
219
+ muted: "muted";
220
+ accent: "accent";
221
+ dim: "dim";
222
+ }>>;
223
+ }, z.core.$strict>>;
224
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
225
+ }, z.core.$strict>, z.ZodObject<{
226
+ kind: z.ZodLiteral<"key_value">;
227
+ id: z.ZodString;
228
+ title: z.ZodOptional<z.ZodString>;
229
+ rows: z.ZodArray<z.ZodObject<{
230
+ key: z.ZodString;
231
+ value: z.ZodString;
232
+ tone: z.ZodOptional<z.ZodEnum<{
233
+ error: "error";
234
+ success: "success";
235
+ info: "info";
236
+ warning: "warning";
237
+ muted: "muted";
238
+ accent: "accent";
239
+ dim: "dim";
240
+ }>>;
241
+ }, z.core.$strict>>;
242
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
243
+ }, z.core.$strict>, z.ZodObject<{
244
+ kind: z.ZodLiteral<"divider">;
245
+ id: z.ZodString;
246
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
247
+ }, z.core.$strict>], "kind">>;
248
+ actions: z.ZodDefault<z.ZodArray<z.ZodObject<{
249
+ id: z.ZodString;
250
+ label: z.ZodString;
251
+ kind: z.ZodOptional<z.ZodEnum<{
252
+ primary: "primary";
253
+ secondary: "secondary";
254
+ danger: "danger";
255
+ link: "link";
256
+ }>>;
257
+ description: z.ZodOptional<z.ZodString>;
258
+ component_id: z.ZodOptional<z.ZodString>;
259
+ callback_token: z.ZodOptional<z.ZodString>;
260
+ payload: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
261
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
262
+ }, z.core.$strict>>>;
263
+ revision: z.ZodObject<{
264
+ id: z.ZodString;
265
+ version: z.ZodNumber;
266
+ }, z.core.$strict>;
267
+ updated_at_ms: z.ZodNumber;
268
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
269
+ }, z.core.$strict>;
270
+ export type UiDoc = z.infer<typeof UiDocSchema>;
271
+ export declare const UI_STATUS_PROFILE_NAMES: readonly ["planning", "subagents", "control-flow", "model-routing"];
272
+ export type UiStatusProfileName = (typeof UI_STATUS_PROFILE_NAMES)[number];
273
+ export declare const UiEventSchema: z.ZodObject<{
274
+ ui_id: z.ZodString;
275
+ action_id: z.ZodString;
276
+ component_id: z.ZodNullable<z.ZodOptional<z.ZodString>>;
277
+ revision: z.ZodObject<{
278
+ id: z.ZodString;
279
+ version: z.ZodNumber;
280
+ }, z.core.$strict>;
281
+ callback_token: z.ZodOptional<z.ZodString>;
282
+ payload: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
283
+ created_at_ms: z.ZodNumber;
284
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
285
+ }, z.core.$strict>;
286
+ export type UiEvent = z.infer<typeof UiEventSchema>;
287
+ export declare function stableSerializeJson(value: unknown, opts?: {
288
+ pretty?: boolean;
289
+ }): string;
290
+ export declare function parseUiDoc(input: unknown): UiDoc | null;
291
+ export declare function resolveUiStatusProfileName(input: unknown): UiStatusProfileName | null;
292
+ export declare function uiStatusProfileWarnings(input: unknown): string[];
293
+ export declare function normalizeUiDocs(input: unknown, opts?: {
294
+ maxDocs?: number;
295
+ }): UiDoc[];
296
+ export declare function uiDocRevisionConflict(left: UiDoc, right: UiDoc): boolean;
297
+ export declare function parseUiEvent(input: unknown): UiEvent | null;
298
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}