@ai-matrx/content-ir-react 0.10.0 → 0.11.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 (40) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/dist/db-component.d.cts +8 -8
  3. package/dist/db-component.d.ts +8 -8
  4. package/dist/directive-host-DAb7Keg8.d.cts +63 -0
  5. package/dist/directive-host-DAb7Keg8.d.ts +63 -0
  6. package/dist/directives.cjs +382 -0
  7. package/dist/directives.cjs.map +1 -0
  8. package/dist/directives.d.cts +70 -0
  9. package/dist/directives.d.ts +70 -0
  10. package/dist/directives.js +369 -0
  11. package/dist/directives.js.map +1 -0
  12. package/dist/{host-types-CDcLW0TD.d.cts → host-types-C8jR31Wk.d.cts} +9 -0
  13. package/dist/{host-types-CpItjcYh.d.ts → host-types-IUEDmso7.d.ts} +9 -0
  14. package/dist/host.cjs +14 -4
  15. package/dist/host.cjs.map +1 -1
  16. package/dist/host.d.cts +5 -4
  17. package/dist/host.d.ts +5 -4
  18. package/dist/host.js +14 -4
  19. package/dist/host.js.map +1 -1
  20. package/dist/index.cjs +437 -46
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +85 -21
  23. package/dist/index.d.ts +85 -21
  24. package/dist/index.js +435 -30
  25. package/dist/index.js.map +1 -1
  26. package/dist/react.cjs +401 -46
  27. package/dist/react.cjs.map +1 -1
  28. package/dist/react.d.cts +11 -10
  29. package/dist/react.d.ts +11 -10
  30. package/dist/react.js +398 -29
  31. package/dist/react.js.map +1 -1
  32. package/dist/{route-QL2Vqf2e.d.cts → route-Bu85A41G.d.cts} +83 -3
  33. package/dist/{route-PUuEuEug.d.ts → route-DoFoDKBn.d.ts} +83 -3
  34. package/dist/route.cjs +14 -0
  35. package/dist/route.cjs.map +1 -1
  36. package/dist/route.d.cts +1 -1
  37. package/dist/route.d.ts +1 -1
  38. package/dist/route.js +15 -0
  39. package/dist/route.js.map +1 -1
  40. package/package.json +15 -2
package/dist/react.js CHANGED
@@ -4,11 +4,22 @@
4
4
  import { useCallback, useSyncExternalStore } from "react";
5
5
 
6
6
  // host/ContentIrProvider.tsx
7
- import { createContext, useContext, useMemo } from "react";
7
+ import { createContext as createContext2, useContext as useContext2, useMemo } from "react";
8
+
9
+ // directives/directive-host.tsx
10
+ import { createContext, useContext } from "react";
8
11
  import { jsx } from "react/jsx-runtime";
9
- var ContentIrHostContext = createContext(null);
12
+ var DirectiveHostContext = createContext(null);
13
+ var EMPTY_HOST = {};
14
+ function useDirectiveHost() {
15
+ return useContext(DirectiveHostContext) ?? EMPTY_HOST;
16
+ }
17
+
18
+ // host/ContentIrProvider.tsx
19
+ import { jsx as jsx2 } from "react/jsx-runtime";
20
+ var ContentIrHostContext = createContext2(null);
10
21
  function useContentIrHostOrNull() {
11
- return useContext(ContentIrHostContext);
22
+ return useContext2(ContentIrHostContext);
12
23
  }
13
24
  function useContentIrHost() {
14
25
  const host = useContentIrHostOrNull();
@@ -59,12 +70,357 @@ function useContentIrKindVersion(kind, sources) {
59
70
  }
60
71
 
61
72
  // react/KindInstanceRender.tsx
62
- import { useEffect, useState } from "react";
63
- import { envelopeFromCompleteValue as envelopeFromCompleteValue2, IR_ENVELOPE_KEY } from "@ai-matrx/content-ir";
73
+ import { useEffect as useEffect2, useState as useState3 } from "react";
74
+ import {
75
+ envelopeFromCompleteValue as envelopeFromCompleteValue2,
76
+ IR_ENVELOPE_KEY,
77
+ isReservedDirectiveSlug as isReservedDirectiveSlug2
78
+ } from "@ai-matrx/content-ir";
79
+
80
+ // directives/DirectiveRender.tsx
81
+ import { tryDecodeDirectiveContent } from "@ai-matrx/content-ir";
82
+
83
+ // directives/DirectiveFallbackCard.tsx
84
+ import { directiveDisplay } from "@ai-matrx/content-ir";
85
+
86
+ // directives/ApplyDirectiveButton.tsx
87
+ import { useEffect, useRef, useState } from "react";
88
+
89
+ // directives/icons.tsx
90
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
91
+ function Svg({ children, ...props }) {
92
+ return /* @__PURE__ */ jsx3(
93
+ "svg",
94
+ {
95
+ xmlns: "http://www.w3.org/2000/svg",
96
+ viewBox: "0 0 24 24",
97
+ fill: "none",
98
+ stroke: "currentColor",
99
+ strokeWidth: 2,
100
+ strokeLinecap: "round",
101
+ strokeLinejoin: "round",
102
+ "aria-hidden": "true",
103
+ ...props,
104
+ children
105
+ }
106
+ );
107
+ }
108
+ var FilePlusIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
109
+ /* @__PURE__ */ jsx3("path", { d: "M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4" }),
110
+ /* @__PURE__ */ jsx3("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" }),
111
+ /* @__PURE__ */ jsx3("path", { d: "M3 15h6" }),
112
+ /* @__PURE__ */ jsx3("path", { d: "M6 12v6" })
113
+ ] });
114
+ var PencilIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
115
+ /* @__PURE__ */ jsx3("path", { d: "M12 20h9" }),
116
+ /* @__PURE__ */ jsx3("path", { d: "M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z" })
117
+ ] });
118
+ var TrashIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
119
+ /* @__PURE__ */ jsx3("path", { d: "M3 6h18" }),
120
+ /* @__PURE__ */ jsx3("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }),
121
+ /* @__PURE__ */ jsx3("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" }),
122
+ /* @__PURE__ */ jsx3("line", { x1: "10", x2: "10", y1: "11", y2: "17" }),
123
+ /* @__PURE__ */ jsx3("line", { x1: "14", x2: "14", y1: "11", y2: "17" })
124
+ ] });
125
+ var PlayIcon = (p) => /* @__PURE__ */ jsx3(Svg, { ...p, children: /* @__PURE__ */ jsx3("polygon", { points: "6 3 20 12 6 21 6 3" }) });
126
+ var WebhookIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
127
+ /* @__PURE__ */ jsx3("path", { d: "M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2" }),
128
+ /* @__PURE__ */ jsx3("path", { d: "m6 17 3.13-5.78c.53-.97.1-2.01-.4-2.96A4 4 0 0 1 14 5.5c.63.42 1.13 1 1.44 1.66" }),
129
+ /* @__PURE__ */ jsx3("path", { d: "m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8" })
130
+ ] });
131
+ var BoxesIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
132
+ /* @__PURE__ */ jsx3("path", { d: "M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z" }),
133
+ /* @__PURE__ */ jsx3("path", { d: "m7 16.5-4.74-2.85" }),
134
+ /* @__PURE__ */ jsx3("path", { d: "m7 16.5 5-3" }),
135
+ /* @__PURE__ */ jsx3("path", { d: "M7 16.5v5.17" }),
136
+ /* @__PURE__ */ jsx3("path", { d: "M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z" }),
137
+ /* @__PURE__ */ jsx3("path", { d: "m17 16.5-5-3" }),
138
+ /* @__PURE__ */ jsx3("path", { d: "m17 16.5 4.74-2.85" }),
139
+ /* @__PURE__ */ jsx3("path", { d: "M17 16.5v5.17" }),
140
+ /* @__PURE__ */ jsx3("path", { d: "M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z" }),
141
+ /* @__PURE__ */ jsx3("path", { d: "M12 8 7.26 5.15" }),
142
+ /* @__PURE__ */ jsx3("path", { d: "m12 8 4.74-2.85" }),
143
+ /* @__PURE__ */ jsx3("path", { d: "M12 13.5V8" })
144
+ ] });
145
+ var ChevronDownIcon = (p) => /* @__PURE__ */ jsx3(Svg, { ...p, children: /* @__PURE__ */ jsx3("path", { d: "m6 9 6 6 6-6" }) });
146
+ var ChevronRightIcon = (p) => /* @__PURE__ */ jsx3(Svg, { ...p, children: /* @__PURE__ */ jsx3("path", { d: "m9 18 6-6-6-6" }) });
147
+ var MaximizeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
148
+ /* @__PURE__ */ jsx3("polyline", { points: "15 3 21 3 21 9" }),
149
+ /* @__PURE__ */ jsx3("polyline", { points: "9 21 3 21 3 15" }),
150
+ /* @__PURE__ */ jsx3("line", { x1: "21", x2: "14", y1: "3", y2: "10" }),
151
+ /* @__PURE__ */ jsx3("line", { x1: "3", x2: "10", y1: "21", y2: "14" })
152
+ ] });
153
+ var LoaderIcon = (p) => /* @__PURE__ */ jsx3(Svg, { ...p, children: /* @__PURE__ */ jsx3("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
154
+ var CheckCircleIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
155
+ /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10" }),
156
+ /* @__PURE__ */ jsx3("path", { d: "m9 12 2 2 4-4" })
157
+ ] });
158
+ var AlertIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
159
+ /* @__PURE__ */ jsx3("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }),
160
+ /* @__PURE__ */ jsx3("path", { d: "M12 9v4" }),
161
+ /* @__PURE__ */ jsx3("path", { d: "M12 17h.01" })
162
+ ] });
163
+ var AGENT_NOUNS = /* @__PURE__ */ new Set(["create_agent", "create_agent_definition", "agent"]);
164
+ function classIcon(directiveClass, noun) {
165
+ if (directiveClass === "action" && AGENT_NOUNS.has(noun)) return WebhookIcon;
166
+ switch (directiveClass) {
167
+ case "create":
168
+ return FilePlusIcon;
169
+ case "update":
170
+ return PencilIcon;
171
+ case "delete":
172
+ return TrashIcon;
173
+ default:
174
+ return PlayIcon;
175
+ }
176
+ }
177
+
178
+ // directives/ApplyDirectiveButton.tsx
179
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
180
+ function ApplyDirectiveButton({
181
+ directive,
182
+ label = "Apply",
183
+ itemCount,
184
+ onApplied
185
+ }) {
186
+ const host = useDirectiveHost();
187
+ const [state, setState] = useState({ status: "idle" });
188
+ const [elapsed, setElapsed] = useState(0);
189
+ const startedAt = useRef(null);
190
+ useEffect(() => {
191
+ if (state.status !== "applying") return;
192
+ startedAt.current = Date.now();
193
+ const id = setInterval(
194
+ () => setElapsed(Math.round((Date.now() - (startedAt.current ?? 0)) / 1e3)),
195
+ 1e3
196
+ );
197
+ return () => clearInterval(id);
198
+ }, [state.status]);
199
+ if (!directive.parsed.executes) return null;
200
+ const confirm = host.confirm;
201
+ if (!confirm) return null;
202
+ const items = directive.items;
203
+ async function handleApply() {
204
+ if (!confirm) return;
205
+ setState({ status: "applying" });
206
+ try {
207
+ const result = await confirm({ __kind: directive.slug, items });
208
+ setState({ status: "applied", applied: result.applied, failed: result.failed });
209
+ onApplied?.();
210
+ } catch (error) {
211
+ setState({
212
+ status: "error",
213
+ message: error instanceof Error && error.message ? error.message : "That couldn't be applied just now. Please try again."
214
+ });
215
+ }
216
+ }
217
+ if (state.status === "applied") {
218
+ const bad = state.failed > 0;
219
+ return /* @__PURE__ */ jsxs2(
220
+ "span",
221
+ {
222
+ className: `inline-flex items-center gap-1 text-xs ${bad ? "text-destructive" : "text-primary"}`,
223
+ children: [
224
+ bad ? /* @__PURE__ */ jsx4(AlertIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx4(CheckCircleIcon, { className: "h-3.5 w-3.5" }),
225
+ "Applied ",
226
+ state.applied,
227
+ bad ? ` \xB7 ${state.failed} failed` : ""
228
+ ]
229
+ }
230
+ );
231
+ }
232
+ return /* @__PURE__ */ jsxs2("span", { className: "inline-flex items-center gap-2", children: [
233
+ /* @__PURE__ */ jsxs2(
234
+ "button",
235
+ {
236
+ type: "button",
237
+ onClick: () => void handleApply(),
238
+ disabled: state.status === "applying" || items.length === 0,
239
+ className: "inline-flex items-center gap-1 rounded-md border border-border bg-background px-2 py-1 text-xs font-medium hover:bg-accent disabled:opacity-50",
240
+ children: [
241
+ state.status === "applying" ? /* @__PURE__ */ jsx4(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx4(PlayIcon, { className: "h-3.5 w-3.5" }),
242
+ state.status === "applying" ? `Applying${itemCount ? ` ${itemCount} ${itemCount === 1 ? "item" : "items"}` : ""}\u2026${elapsed ? ` ${elapsed}s` : ""}` : label
243
+ ]
244
+ }
245
+ ),
246
+ state.status === "error" ? /* @__PURE__ */ jsxs2("span", { className: "inline-flex max-w-sm items-start gap-1 text-xs text-destructive", children: [
247
+ /* @__PURE__ */ jsx4(AlertIcon, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
248
+ /* @__PURE__ */ jsx4("span", { children: state.message })
249
+ ] }) : null
250
+ ] });
251
+ }
252
+
253
+ // directives/DirectiveFallbackCard.tsx
254
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
255
+ function DirectiveFallbackCard({ directive, reason }) {
256
+ const host = useDirectiveHost();
257
+ const count = directive.items.length;
258
+ const display = directiveDisplay(directive.directiveClass, directive.noun, host.nouns);
259
+ return /* @__PURE__ */ jsxs3("div", { className: "my-3 inline-flex flex-wrap items-center gap-2 rounded-md border border-border bg-muted px-2.5 py-1 text-sm", children: [
260
+ /* @__PURE__ */ jsx5(BoxesIcon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
261
+ /* @__PURE__ */ jsx5("span", { className: "text-foreground", children: display.title }),
262
+ display.family ? /* @__PURE__ */ jsxs3("span", { className: "text-muted-foreground", children: [
263
+ "\xB7 ",
264
+ display.family
265
+ ] }) : null,
266
+ /* @__PURE__ */ jsxs3("span", { className: "text-muted-foreground", children: [
267
+ "\xB7 ",
268
+ count,
269
+ " ",
270
+ count === 1 ? "item" : "items"
271
+ ] }),
272
+ reason ? /* @__PURE__ */ jsxs3("span", { className: "text-muted-foreground", children: [
273
+ "\xB7 ",
274
+ reason
275
+ ] }) : null,
276
+ /* @__PURE__ */ jsx5(ApplyDirectiveButton, { directive })
277
+ ] });
278
+ }
279
+
280
+ // directives/registry.ts
281
+ import {
282
+ buildDirectiveSlug
283
+ } from "@ai-matrx/content-ir";
284
+ var REGISTRY_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.content-ir-react.directive-renderers");
285
+ var registry = globalThis[REGISTRY_SLOT] ??= {
286
+ bySlug: /* @__PURE__ */ new Map(),
287
+ byClass: /* @__PURE__ */ new Map()
288
+ };
289
+ function getDirectiveRenderer(directive) {
290
+ return registry.bySlug.get(directive.slug) ?? registry.byClass.get(directive.directiveClass) ?? null;
291
+ }
292
+
293
+ // directives/SideEffectDirectiveCard.tsx
294
+ import { useState as useState2 } from "react";
295
+ import {
296
+ asKindInstance,
297
+ directiveDisplay as directiveDisplay2,
298
+ itemFacts,
299
+ itemSubtitle,
300
+ itemTitle,
301
+ nounTitleColumn
302
+ } from "@ai-matrx/content-ir";
303
+ import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
304
+ var ROWS_BEFORE_FOLD = 3;
305
+ function ItemRow({
306
+ directive,
307
+ item,
308
+ index,
309
+ total
310
+ }) {
311
+ const host = useDirectiveHost();
312
+ const titleColumn = nounTitleColumn(directive.noun, host.nouns);
313
+ const title = itemTitle(item, titleColumn, index, total);
314
+ const subtitle = itemSubtitle(item);
315
+ const facts = itemFacts(item);
316
+ const kind = host.itemKind?.(directive.slug) ?? null;
317
+ const display = directiveDisplay2(directive.directiveClass, directive.noun, host.nouns);
318
+ const openItem = host.openItem;
319
+ const body = /* @__PURE__ */ jsxs4(Fragment, { children: [
320
+ /* @__PURE__ */ jsx6("span", { className: "min-w-0 shrink-0 truncate font-medium text-foreground", children: title }),
321
+ /* @__PURE__ */ jsx6("span", { className: "hidden min-w-0 flex-1 items-baseline gap-2 overflow-hidden sm:flex", children: facts.map((fact) => /* @__PURE__ */ jsxs4("span", { className: "truncate text-[11px] text-muted-foreground", children: [
322
+ fact.value,
323
+ " ",
324
+ fact.label
325
+ ] }, fact.key)) }),
326
+ subtitle && facts.length === 0 ? /* @__PURE__ */ jsx6("span", { className: "hidden truncate text-[11px] text-muted-foreground sm:inline", children: subtitle }) : null,
327
+ openItem ? /* @__PURE__ */ jsx6(MaximizeIcon, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground" }) : null
328
+ ] });
329
+ return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 py-1 text-xs", children: [
330
+ openItem ? /* @__PURE__ */ jsx6(
331
+ "button",
332
+ {
333
+ type: "button",
334
+ onClick: () => openItem({
335
+ // Stamped so the panel's kind pipeline types it from its own first key.
336
+ item: asKindInstance(item, kind) ?? item,
337
+ itemKind: kind,
338
+ title,
339
+ subtitle: `${display.title} \xB7 item ${index + 1} of ${total}`,
340
+ directive,
341
+ index,
342
+ total
343
+ }),
344
+ className: "flex min-w-0 flex-1 items-center gap-2 rounded px-1 py-0.5 text-left hover:bg-accent hover:text-accent-foreground",
345
+ title: "Open to read it",
346
+ children: body
347
+ }
348
+ ) : /* @__PURE__ */ jsx6("span", { className: "flex min-w-0 flex-1 items-center gap-2 px-1 py-0.5", children: body }),
349
+ host.renderCopy?.({ label: title, value: item, kind, size: "xs" })
350
+ ] });
351
+ }
352
+ function SideEffectDirectiveCard({ directive }) {
353
+ const host = useDirectiveHost();
354
+ const [expanded, setExpanded] = useState2(false);
355
+ const items = directive.items;
356
+ const total = items.length;
357
+ const display = directiveDisplay2(directive.directiveClass, directive.noun, host.nouns);
358
+ const Icon = classIcon(directive.directiveClass, directive.noun);
359
+ const shown = expanded ? items : items.slice(0, ROWS_BEFORE_FOLD);
360
+ const hidden = total - shown.length;
361
+ return /* @__PURE__ */ jsxs4("div", { className: "my-3 rounded-md border border-border bg-card px-2.5 py-1.5", "data-directive": directive.slug, children: [
362
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: [
363
+ /* @__PURE__ */ jsx6(Icon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
364
+ /* @__PURE__ */ jsx6("span", { className: "text-sm font-medium text-foreground", children: display.title }),
365
+ display.family ? /* @__PURE__ */ jsx6("span", { className: "text-xs text-muted-foreground", children: display.family }) : null,
366
+ /* @__PURE__ */ jsxs4("span", { className: "text-xs tabular-nums text-muted-foreground", children: [
367
+ total,
368
+ " ",
369
+ total === 1 ? "item" : "items"
370
+ ] }),
371
+ /* @__PURE__ */ jsxs4("div", { className: "ml-auto flex items-center gap-1", children: [
372
+ host.renderCopy?.({ label: display.title, value: directive.shell, size: "icon" }),
373
+ /* @__PURE__ */ jsx6(ApplyDirectiveButton, { directive, itemCount: total })
374
+ ] })
375
+ ] }),
376
+ total === 0 ? (
377
+ // Stated, never silent: an empty batch is a real (and suspicious) state.
378
+ /* @__PURE__ */ jsx6("p", { className: "mt-1 text-xs text-muted-foreground", children: "No items \u2014 nothing would be written." })
379
+ ) : /* @__PURE__ */ jsx6("div", { className: "mt-0.5 divide-y divide-border/60", children: shown.map((item, i) => /* @__PURE__ */ jsx6(ItemRow, { directive, item, index: i, total }, i)) }),
380
+ hidden > 0 || expanded ? /* @__PURE__ */ jsxs4(
381
+ "button",
382
+ {
383
+ type: "button",
384
+ onClick: () => setExpanded((v) => !v),
385
+ className: "mt-0.5 inline-flex items-center gap-1 rounded px-1 py-0.5 text-[11px] text-muted-foreground hover:text-foreground",
386
+ children: [
387
+ expanded ? /* @__PURE__ */ jsx6(ChevronDownIcon, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx6(ChevronRightIcon, { className: "h-3 w-3" }),
388
+ expanded ? "Show less" : `Show ${hidden} more`
389
+ ]
390
+ }
391
+ ) : null
392
+ ] });
393
+ }
394
+
395
+ // directives/DirectiveRender.tsx
396
+ import { jsx as jsx7 } from "react/jsx-runtime";
397
+ function DirectiveRender({ content, className }) {
398
+ const host = useDirectiveHost();
399
+ const directive = tryDecodeDirectiveContent(content, (message) => {
400
+ const line = `[kind-directives] ${message}`;
401
+ if (host.reportError) host.reportError(line);
402
+ else console.error(line);
403
+ });
404
+ if (!directive) {
405
+ const raw = typeof content === "string" ? content : JSON.stringify(content, null, 2);
406
+ return /* @__PURE__ */ jsx7(
407
+ "pre",
408
+ {
409
+ className: `my-3 overflow-x-auto rounded-md border border-border bg-muted px-3 py-2 text-xs text-muted-foreground${className ? ` ${className}` : ""}`,
410
+ children: raw
411
+ }
412
+ );
413
+ }
414
+ const Renderer = getDirectiveRenderer(directive);
415
+ if (Renderer) return /* @__PURE__ */ jsx7(Renderer, { directive });
416
+ if (directive.parsed.executes) return /* @__PURE__ */ jsx7(SideEffectDirectiveCard, { directive });
417
+ return /* @__PURE__ */ jsx7(DirectiveFallbackCard, { directive });
418
+ }
64
419
 
65
420
  // route/kind-route.ts
66
421
  import {
67
422
  envelopeFromCompleteValue,
423
+ isReservedDirectiveSlug,
68
424
  readEnvelope,
69
425
  readObjectKind
70
426
  } from "@ai-matrx/content-ir";
@@ -86,17 +442,30 @@ function readIrRouteMarker(metadata) {
86
442
  }
87
443
 
88
444
  // react/KindInstanceRender.tsx
89
- import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
445
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
90
446
  function isRecordValue(value) {
91
447
  return typeof value === "object" && value !== null && !Array.isArray(value);
92
448
  }
93
449
  function kindIsRoutable(kind, host) {
450
+ if (isReservedDirectiveSlug2(kind)) return true;
94
451
  if (host.kinds.getDefinition(kind)?.legacyBlockType) return true;
95
452
  const resolution = host.components.resolve(kind, host.platform, "output");
96
453
  if (!resolution?.isActive) return false;
97
454
  return resolution.componentKey !== GENERIC_STRUCTURED_COMPONENT_KEY;
98
455
  }
99
- function KindInstanceRender({
456
+ function KindInstanceRender(props) {
457
+ if (isReservedDirectiveSlug2(props.kind)) {
458
+ return /* @__PURE__ */ jsx8(
459
+ DirectiveRender,
460
+ {
461
+ content: props.value,
462
+ ...props.className === void 0 ? {} : { className: props.className }
463
+ }
464
+ );
465
+ }
466
+ return /* @__PURE__ */ jsx8(KindInstanceRenderInner, { ...props });
467
+ }
468
+ function KindInstanceRenderInner({
100
469
  kind,
101
470
  value,
102
471
  showRoutingNote = true,
@@ -105,10 +474,10 @@ function KindInstanceRender({
105
474
  className
106
475
  }) {
107
476
  const host = useContentIrHost();
108
- const [routingStatus, setRoutingStatus] = useState(
477
+ const [routingStatus, setRoutingStatus] = useState3(
109
478
  () => kindIsRoutable(kind, host) ? "routable" : "checking"
110
479
  );
111
- useEffect(() => {
480
+ useEffect2(() => {
112
481
  let cancelled = false;
113
482
  let warmed = false;
114
483
  const syncRoutingStatus = () => {
@@ -145,13 +514,13 @@ function KindInstanceRender({
145
514
  } : null;
146
515
  const frameClass = variant === "bare" ? void 0 : "rounded-md border border-border bg-card p-3";
147
516
  if (routingStatus === "unroutable" && unroutableFallback !== void 0) {
148
- return /* @__PURE__ */ jsx2(Fragment, { children: unroutableFallback });
517
+ return /* @__PURE__ */ jsx8(Fragment2, { children: unroutableFallback });
149
518
  }
150
519
  const onTheFloor = block === null || routingStatus === "unroutable";
151
520
  const notice = "This shape has no custom component yet, so it renders through the universal viewer \u2014 exactly what production shows today.";
152
- return /* @__PURE__ */ jsxs("div", { className: className ? `space-y-3 ${className}` : "space-y-3", children: [
153
- showRoutingNote && routingStatus === "unroutable" ? host.renderNotice?.(notice) ?? /* @__PURE__ */ jsx2("div", { className: "rounded-md border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-xs text-amber-800 dark:text-amber-200", children: notice }) : null,
154
- /* @__PURE__ */ jsx2("div", { className: frameClass, children: onTheFloor ? host.renderValue({ value, kind }) : host.renderBlock(block) })
521
+ return /* @__PURE__ */ jsxs5("div", { className: className ? `space-y-3 ${className}` : "space-y-3", children: [
522
+ showRoutingNote && routingStatus === "unroutable" ? host.renderNotice?.(notice) ?? /* @__PURE__ */ jsx8("div", { className: "rounded-md border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-xs text-amber-800 dark:text-amber-200", children: notice }) : null,
523
+ /* @__PURE__ */ jsx8("div", { className: frameClass, children: onTheFloor ? host.renderValue({ value, kind }) : host.renderBlock(block) })
155
524
  ] });
156
525
  }
157
526
 
@@ -176,7 +545,7 @@ function markKindPartialUnsafe(kind) {
176
545
  }
177
546
 
178
547
  // react/ProvisionalKindBoundary.tsx
179
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
548
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
180
549
  var ProvisionalKindBoundaryInner = class extends React.Component {
181
550
  state = { failed: false };
182
551
  static getDerivedStateFromError() {
@@ -201,14 +570,14 @@ var ProvisionalKindBoundaryInner = class extends React.Component {
201
570
  };
202
571
  function ProvisionalKindBoundary(props) {
203
572
  const host = useContentIrHost();
204
- return /* @__PURE__ */ jsx3(ProvisionalKindBoundaryInner, { ...props, reportError: host.reportError });
573
+ return /* @__PURE__ */ jsx9(ProvisionalKindBoundaryInner, { ...props, reportError: host.reportError });
205
574
  }
206
575
  function ProvisionalKindFrame({ children }) {
207
576
  const host = useContentIrHost();
208
577
  const label = "Still arriving";
209
- return /* @__PURE__ */ jsxs2("div", { className: "relative", "aria-busy": "true", children: [
578
+ return /* @__PURE__ */ jsxs6("div", { className: "relative", "aria-busy": "true", children: [
210
579
  children,
211
- /* @__PURE__ */ jsx3("span", { className: "pointer-events-none absolute -top-2 right-4 z-10 select-none rounded-full bg-background px-1.5 leading-4", children: host.renderShimmer?.(label) ?? /* @__PURE__ */ jsx3("span", { className: "text-[10px] text-muted-foreground", children: label }) })
580
+ /* @__PURE__ */ jsx9("span", { className: "pointer-events-none absolute -top-2 right-4 z-10 select-none rounded-full bg-background px-1.5 leading-4", children: host.renderShimmer?.(label) ?? /* @__PURE__ */ jsx9("span", { className: "text-[10px] text-muted-foreground", children: label }) })
212
581
  ] });
213
582
  }
214
583
 
@@ -219,7 +588,7 @@ import {
219
588
  readObjectKind as readObjectKind2,
220
589
  reconstructRegionValue
221
590
  } from "@ai-matrx/content-ir";
222
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
591
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
223
592
  function readStructuredValue(content, metadata) {
224
593
  const envelope = readEnvelope3(metadata);
225
594
  if (envelope) {
@@ -244,19 +613,19 @@ function GenericStructuredView({
244
613
  const kind = envelope?.root.kind ?? (typeof value === "object" && value !== null && !Array.isArray(value) ? readObjectKind2(value) : null) ?? "";
245
614
  const marker = readIrRouteMarker(metadata);
246
615
  const note = marker?.reason === "inactive" ? "a custom view is registered but held inactive" : marker?.reason === "broken-instance" ? "this instance did not match the shape's schema" : marker?.reason === "unregistered" ? "this shape isn't registered on this platform" : "no custom view yet";
247
- return /* @__PURE__ */ jsxs3("div", { className: className ? `my-2 min-w-0 ${className}` : "my-2 min-w-0", children: [
248
- status === "streaming" ? streamingIndicator ?? /* @__PURE__ */ jsx4("div", { className: "mb-2 text-xs text-muted-foreground", children: "Still arriving\u2026" }) : null,
616
+ return /* @__PURE__ */ jsxs7("div", { className: className ? `my-2 min-w-0 ${className}` : "my-2 min-w-0", children: [
617
+ status === "streaming" ? streamingIndicator ?? /* @__PURE__ */ jsx10("div", { className: "mb-2 text-xs text-muted-foreground", children: "Still arriving\u2026" }) : null,
249
618
  recovered ? host.renderValue({ value, ...kind ? { kind } : {}, note }) : (
250
619
  // Zero-data-loss backstop: the region never parsed, so show the source
251
620
  // verbatim rather than swallowing it.
252
- /* @__PURE__ */ jsx4("pre", { className: "max-h-96 overflow-auto font-mono text-xs leading-relaxed text-muted-foreground", children: content })
621
+ /* @__PURE__ */ jsx10("pre", { className: "max-h-96 overflow-auto font-mono text-xs leading-relaxed text-muted-foreground", children: content })
253
622
  )
254
623
  ] });
255
624
  }
256
625
 
257
626
  // react/RuntimeWrapperViews.tsx
258
627
  import { readNodeOutcomeValue, readObjectKind as readObjectKind3, readRunResultValue } from "@ai-matrx/content-ir";
259
- import { Fragment as Fragment2, jsx as jsx5 } from "react/jsx-runtime";
628
+ import { Fragment as Fragment3, jsx as jsx11 } from "react/jsx-runtime";
260
629
  function isRecord2(value) {
261
630
  return typeof value === "object" && value !== null && !Array.isArray(value);
262
631
  }
@@ -272,16 +641,16 @@ function DelegatedOutput({
272
641
  }) {
273
642
  const host = useContentIrHost();
274
643
  if (output === null || output === void 0) {
275
- return /* @__PURE__ */ jsx5("p", { className: "text-xs text-muted-foreground", children: emptyLabel });
644
+ return /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground", children: emptyLabel });
276
645
  }
277
646
  if (!isRecord2(output)) {
278
- return /* @__PURE__ */ jsx5(Fragment2, { children: host.renderValue({ value: output }) });
647
+ return /* @__PURE__ */ jsx11(Fragment3, { children: host.renderValue({ value: output }) });
279
648
  }
280
649
  const kind = readObjectKind3(output) ?? declaredKind;
281
650
  if (!kind) {
282
- return /* @__PURE__ */ jsx5(Fragment2, { children: fallback?.(output) ?? host.renderValue({ value: output }) });
651
+ return /* @__PURE__ */ jsx11(Fragment3, { children: fallback?.(output) ?? host.renderValue({ value: output }) });
283
652
  }
284
- return /* @__PURE__ */ jsx5(
653
+ return /* @__PURE__ */ jsx11(
285
654
  KindInstanceRender,
286
655
  {
287
656
  kind,
@@ -298,7 +667,7 @@ function NodeOutcomeView({ serverData, fallback }) {
298
667
  readNodeOutcomeValue
299
668
  );
300
669
  if (!wrapper) return null;
301
- return /* @__PURE__ */ jsx5(
670
+ return /* @__PURE__ */ jsx11(
302
671
  DelegatedOutput,
303
672
  {
304
673
  output: wrapper.output,
@@ -313,14 +682,14 @@ function RunResultView({ serverData, fallback }) {
313
682
  readRunResultValue
314
683
  );
315
684
  if (!wrapper) return null;
316
- return /* @__PURE__ */ jsx5("div", { className: "space-y-2", children: wrapper.outputs.length > 0 ? wrapper.outputs.map((outcome) => /* @__PURE__ */ jsx5(
685
+ return /* @__PURE__ */ jsx11("div", { className: "space-y-2", children: wrapper.outputs.length > 0 ? wrapper.outputs.map((outcome) => /* @__PURE__ */ jsx11(
317
686
  NodeOutcomeView,
318
687
  {
319
688
  serverData: { wrapper: outcome },
320
689
  ...fallback === void 0 ? {} : { fallback }
321
690
  },
322
691
  `${outcome.node_id}:${outcome.attempt}`
323
- )) : /* @__PURE__ */ jsx5(
692
+ )) : /* @__PURE__ */ jsx11(
324
693
  DelegatedOutput,
325
694
  {
326
695
  output: wrapper.output,