@ai-matrx/content-ir-react 0.11.10 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.d.cts CHANGED
@@ -1,9 +1,9 @@
1
- import { c as KindDefinitionSource, C as ContentIrHost } from './host-types-C8jR31Wk.cjs';
1
+ import { c as KindDefinitionSource, C as ContentIrHost } from './host-types-BgROpyjE.cjs';
2
2
  import { d as ComponentResolutionSource } from './component-resolution.types-C1MzCf2s.cjs';
3
3
  import * as react from 'react';
4
4
  import react__default, { ReactNode } from 'react';
5
5
  import '@ai-matrx/content-ir';
6
- import './directive-host-DAb7Keg8.cjs';
6
+ import './directive-host-Bl-ZgJWp.cjs';
7
7
 
8
8
  /**
9
9
  * The two registries this hook watches. Passed explicitly by a host whose
package/dist/react.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { c as KindDefinitionSource, C as ContentIrHost } from './host-types-IUEDmso7.js';
1
+ import { c as KindDefinitionSource, C as ContentIrHost } from './host-types-Cz-1pGHz.js';
2
2
  import { d as ComponentResolutionSource } from './component-resolution.types-C1MzCf2s.js';
3
3
  import * as react from 'react';
4
4
  import react__default, { ReactNode } from 'react';
5
5
  import '@ai-matrx/content-ir';
6
- import './directive-host-DAb7Keg8.js';
6
+ import './directive-host-Bl-ZgJWp.js';
7
7
 
8
8
  /**
9
9
  * The two registries this hook watches. Passed explicitly by a host whose
package/dist/react.js CHANGED
@@ -78,13 +78,70 @@ import {
78
78
  } from "@ai-matrx/content-ir";
79
79
 
80
80
  // directives/DirectiveRender.tsx
81
- import { tryDecodeDirectiveContent } from "@ai-matrx/content-ir";
81
+ import { looksLikeDirectiveHead, tryDecodeDirectiveContent } from "@ai-matrx/content-ir";
82
82
 
83
83
  // directives/DirectiveFallbackCard.tsx
84
84
  import { directiveDisplay } from "@ai-matrx/content-ir";
85
85
 
86
86
  // directives/ApplyDirectiveButton.tsx
87
87
  import { useEffect, useRef, useState } from "react";
88
+ import { nounLabel } from "@ai-matrx/content-ir";
89
+
90
+ // directives/item-changes.ts
91
+ var TARGETING_CLASSES = /* @__PURE__ */ new Set(["update", "delete"]);
92
+ var NOT_A_CHANGE = /* @__PURE__ */ new Set(["__kind", "id"]);
93
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
94
+ var CHANGE_VALUE_MAX = 60;
95
+ function itemRecordId(item) {
96
+ const id = item.id;
97
+ if (typeof id === "string" && id.trim()) return id.trim();
98
+ if (typeof id === "number") return String(id);
99
+ return null;
100
+ }
101
+ function fieldLabel(key) {
102
+ const spaced = key.replace(/_/g, " ").trim();
103
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
104
+ }
105
+ function recordFallbackName(nounLabel3, id) {
106
+ const short = UUID_RE.test(id) ? id.slice(0, 8) : id.length > 12 ? `${id.slice(0, 12)}\u2026` : id;
107
+ return `${nounLabel3} ${short}`;
108
+ }
109
+ function describeValue(value) {
110
+ if (value === null || value === void 0) return { value: "cleared", full: "cleared", clears: true };
111
+ if (typeof value === "string") {
112
+ const trimmed = value.trim();
113
+ if (!trimmed) return { value: "cleared", full: "cleared", clears: true };
114
+ const oneLine = trimmed.replace(/\s+/g, " ");
115
+ const shown = oneLine.length > CHANGE_VALUE_MAX ? `${oneLine.slice(0, CHANGE_VALUE_MAX - 1)}\u2026` : oneLine;
116
+ return { value: shown, full: trimmed, clears: false };
117
+ }
118
+ if (typeof value === "number" || typeof value === "boolean") {
119
+ return { value: String(value), full: String(value), clears: false };
120
+ }
121
+ if (Array.isArray(value)) {
122
+ const n2 = value.length;
123
+ const text2 = n2 === 0 ? "cleared" : `${n2} ${n2 === 1 ? "entry" : "entries"}`;
124
+ return { value: text2, full: safeJson(value), clears: n2 === 0 };
125
+ }
126
+ const n = Object.keys(value).length;
127
+ const text = n === 0 ? "cleared" : `${n} ${n === 1 ? "field" : "fields"}`;
128
+ return { value: text, full: safeJson(value), clears: n === 0 };
129
+ }
130
+ function safeJson(value) {
131
+ try {
132
+ return JSON.stringify(value, null, 2);
133
+ } catch {
134
+ return String(value);
135
+ }
136
+ }
137
+ function itemChanges(item) {
138
+ const out = [];
139
+ for (const [key, raw] of Object.entries(item)) {
140
+ if (NOT_A_CHANGE.has(key)) continue;
141
+ out.push({ key, label: fieldLabel(key), ...describeValue(raw) });
142
+ }
143
+ return out;
144
+ }
88
145
 
89
146
  // directives/icons.tsx
90
147
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
@@ -202,10 +259,38 @@ function ApplyDirectiveButton({
202
259
  const items = directive.items;
203
260
  async function handleApply() {
204
261
  if (!confirm) return;
262
+ if (host.ask) {
263
+ setState({ status: "asking" });
264
+ let ok = false;
265
+ try {
266
+ ok = await host.ask({
267
+ directive,
268
+ items,
269
+ nounLabel: nounLabel(directive.noun, host.nouns)
270
+ });
271
+ } catch (error) {
272
+ setState({
273
+ status: "error",
274
+ message: error instanceof Error && error.message ? error.message : "We could not ask you to confirm this, so nothing was done."
275
+ });
276
+ return;
277
+ }
278
+ if (!ok) {
279
+ setState({ status: "idle" });
280
+ return;
281
+ }
282
+ }
283
+ setElapsed(0);
205
284
  setState({ status: "applying" });
206
285
  try {
207
286
  const result = await confirm({ __kind: directive.slug, items });
208
- setState({ status: "applied", applied: result.applied, failed: result.failed });
287
+ setState({
288
+ status: "applied",
289
+ applied: result.applied,
290
+ failed: result.failed,
291
+ message: result.message?.trim() ? result.message.trim() : null,
292
+ records: result.records ?? []
293
+ });
209
294
  onApplied?.();
210
295
  } catch (error) {
211
296
  setState({
@@ -216,15 +301,26 @@ function ApplyDirectiveButton({
216
301
  }
217
302
  if (state.status === "applied") {
218
303
  const bad = state.failed > 0;
304
+ const trashed = directive.directiveClass === "delete";
305
+ const label2 = nounLabel(directive.noun, host.nouns);
306
+ const records = host.renderRecord ? state.records : [];
219
307
  return /* @__PURE__ */ jsxs2(
220
308
  "span",
221
309
  {
222
- className: `inline-flex items-center gap-1 text-xs ${bad ? "text-destructive" : "text-primary"}`,
310
+ className: `inline-flex min-w-0 flex-wrap items-center gap-1 text-xs ${bad ? "text-destructive" : "text-primary"}`,
311
+ "data-apply-state": "applied",
223
312
  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` : ""
313
+ bad ? /* @__PURE__ */ jsx4(AlertIcon, { className: "h-3.5 w-3.5 shrink-0" }) : /* @__PURE__ */ jsx4(CheckCircleIcon, { className: "h-3.5 w-3.5 shrink-0" }),
314
+ /* @__PURE__ */ jsxs2("span", { children: [
315
+ state.message ?? `Applied ${state.applied}`,
316
+ bad && !state.message ? ` \xB7 ${state.failed} failed` : ""
317
+ ] }),
318
+ records.map((record) => /* @__PURE__ */ jsx4("span", { className: "inline-flex min-w-0 items-center", children: host.renderRecord?.({
319
+ ...record,
320
+ fallback: recordFallbackName(label2, record.id),
321
+ context: "applied",
322
+ trashed
323
+ }) }, `${record.noun}:${record.id}`))
228
324
  ]
229
325
  }
230
326
  );
@@ -235,7 +331,7 @@ function ApplyDirectiveButton({
235
331
  {
236
332
  type: "button",
237
333
  onClick: () => void handleApply(),
238
- disabled: state.status === "applying" || items.length === 0,
334
+ disabled: state.status === "applying" || state.status === "asking" || items.length === 0,
239
335
  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
336
  children: [
241
337
  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" }),
@@ -277,6 +373,46 @@ function DirectiveFallbackCard({ directive, reason }) {
277
373
  ] });
278
374
  }
279
375
 
376
+ // directives/DirectiveProvisionalCard.tsx
377
+ import { directiveDisplay as directiveDisplay2, parseDirectiveSlug } from "@ai-matrx/content-ir";
378
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
379
+ var COMPLETE_SLUG_RE = /^\{\s*"__kind"\s*:\s*"([^"]+)"/;
380
+ function provisionalDirectiveSlug(content) {
381
+ const match = content.trimStart().match(COMPLETE_SLUG_RE);
382
+ return match?.[1] ?? null;
383
+ }
384
+ function DirectiveProvisionalCard({ content, streaming, className }) {
385
+ const host = useDirectiveHost();
386
+ const slug = provisionalDirectiveSlug(content);
387
+ const known = slug ? parseDirectiveSlug(slug) : null;
388
+ const display = known ? directiveDisplay2(known.directiveClass, known.noun, host.nouns) : null;
389
+ const Icon = known ? classIcon(known.directiveClass, known.noun) : BoxesIcon;
390
+ const title = display?.title ?? "Structured action";
391
+ return /* @__PURE__ */ jsxs4(
392
+ "div",
393
+ {
394
+ className: `my-3 rounded-md border border-border bg-card px-2.5 py-1.5${className ? ` ${className}` : ""}`,
395
+ "data-directive": slug ?? void 0,
396
+ "data-directive-state": streaming ? "streaming" : "incomplete",
397
+ children: [
398
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: [
399
+ /* @__PURE__ */ jsx6(Icon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
400
+ /* @__PURE__ */ jsx6("span", { className: "text-sm font-medium text-foreground", children: title }),
401
+ display?.family ? /* @__PURE__ */ jsx6("span", { className: "text-xs text-muted-foreground", children: display.family }) : null,
402
+ streaming ? /* @__PURE__ */ jsxs4("span", { className: "inline-flex items-center gap-1.5 text-xs text-muted-foreground", role: "status", children: [
403
+ /* @__PURE__ */ jsx6("span", { className: "h-1.5 w-1.5 animate-pulse rounded-full bg-primary", "aria-hidden": true }),
404
+ "Writing\u2026"
405
+ ] }) : /* @__PURE__ */ jsx6("span", { className: "text-xs text-destructive", role: "status", children: "Cut off before it finished \u2014 nothing can be applied." })
406
+ ] }),
407
+ streaming ? null : /* @__PURE__ */ jsxs4("details", { className: "mt-1 text-xs text-muted-foreground", children: [
408
+ /* @__PURE__ */ jsx6("summary", { className: "cursor-pointer select-none hover:text-foreground", children: "Show what arrived" }),
409
+ /* @__PURE__ */ jsx6("pre", { className: "mt-1 max-h-64 overflow-auto whitespace-pre-wrap break-all rounded bg-muted px-2 py-1 text-[11px]", children: content })
410
+ ] })
411
+ ]
412
+ }
413
+ );
414
+ }
415
+
280
416
  // directives/registry.ts
281
417
  import {
282
418
  buildDirectiveSlug
@@ -294,13 +430,14 @@ function getDirectiveRenderer(directive) {
294
430
  import { useState as useState2 } from "react";
295
431
  import {
296
432
  asKindInstance,
297
- directiveDisplay as directiveDisplay2,
433
+ directiveDisplay as directiveDisplay3,
298
434
  itemFacts,
299
435
  itemSubtitle,
300
436
  itemTitle,
437
+ nounLabel as nounLabel2,
301
438
  nounTitleColumn
302
439
  } from "@ai-matrx/content-ir";
303
- import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
440
+ import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
304
441
  var ROWS_BEFORE_FOLD = 3;
305
442
  function ItemRow({
306
443
  directive,
@@ -309,25 +446,29 @@ function ItemRow({
309
446
  total
310
447
  }) {
311
448
  const host = useDirectiveHost();
449
+ const recordId = TARGETING_CLASSES.has(directive.directiveClass) ? itemRecordId(item) : null;
450
+ if (recordId) {
451
+ return /* @__PURE__ */ jsx7(TargetRow, { directive, item, recordId });
452
+ }
312
453
  const titleColumn = nounTitleColumn(directive.noun, host.nouns);
313
454
  const title = itemTitle(item, titleColumn, index, total);
314
455
  const subtitle = itemSubtitle(item);
315
456
  const facts = itemFacts(item);
316
457
  const kind = host.itemKind?.(directive.slug) ?? null;
317
- const display = directiveDisplay2(directive.directiveClass, directive.noun, host.nouns);
458
+ const display = directiveDisplay3(directive.directiveClass, directive.noun, host.nouns);
318
459
  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: [
460
+ const body = /* @__PURE__ */ jsxs5(Fragment, { children: [
461
+ /* @__PURE__ */ jsx7("span", { className: "min-w-0 shrink-0 truncate font-medium text-foreground", children: title }),
462
+ /* @__PURE__ */ jsx7("span", { className: "hidden min-w-0 flex-1 items-baseline gap-2 overflow-hidden sm:flex", children: facts.map((fact) => /* @__PURE__ */ jsxs5("span", { className: "truncate text-[11px] text-muted-foreground", children: [
322
463
  fact.value,
323
464
  " ",
324
465
  fact.label
325
466
  ] }, 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
467
+ subtitle && facts.length === 0 ? /* @__PURE__ */ jsx7("span", { className: "hidden truncate text-[11px] text-muted-foreground sm:inline", children: subtitle }) : null,
468
+ openItem ? /* @__PURE__ */ jsx7(MaximizeIcon, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground" }) : null
328
469
  ] });
329
- return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 py-1 text-xs", children: [
330
- openItem ? /* @__PURE__ */ jsx6(
470
+ return /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 py-1 text-xs", children: [
471
+ openItem ? /* @__PURE__ */ jsx7(
331
472
  "button",
332
473
  {
333
474
  type: "button",
@@ -345,46 +486,81 @@ function ItemRow({
345
486
  title: "Open to read it",
346
487
  children: body
347
488
  }
348
- ) : /* @__PURE__ */ jsx6("span", { className: "flex min-w-0 flex-1 items-center gap-2 px-1 py-0.5", children: body }),
489
+ ) : /* @__PURE__ */ jsx7("span", { className: "flex min-w-0 flex-1 items-center gap-2 px-1 py-0.5", children: body }),
349
490
  host.renderCopy?.({ label: title, value: item, kind, size: "xs" })
350
491
  ] });
351
492
  }
493
+ function TargetRow({
494
+ directive,
495
+ item,
496
+ recordId
497
+ }) {
498
+ const host = useDirectiveHost();
499
+ const fallback = recordFallbackName(nounLabel2(directive.noun, host.nouns), recordId);
500
+ const changes = directive.directiveClass === "update" ? itemChanges(item) : [];
501
+ const name = host.renderRecord ? host.renderRecord({ noun: directive.noun, id: recordId, fallback, context: "row" }) : /* @__PURE__ */ jsx7("span", { className: "truncate font-medium text-foreground", children: fallback });
502
+ return /* @__PURE__ */ jsxs5("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
503
+ /* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 items-center gap-2", children: [
504
+ /* @__PURE__ */ jsx7("span", { className: "flex min-w-0 flex-1 items-center gap-1 px-1", children: name }),
505
+ host.renderCopy?.({ label: fallback, value: item, size: "xs" })
506
+ ] }),
507
+ directive.directiveClass === "update" ? changes.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "px-1 text-[11px] text-muted-foreground", children: "Sets no fields \u2014 nothing would change." }) : /* @__PURE__ */ jsx7("ul", { className: "mt-0.5 space-y-0.5 px-1", children: changes.map((change) => /* @__PURE__ */ jsxs5(
508
+ "li",
509
+ {
510
+ className: "flex min-w-0 items-baseline gap-1.5 text-[11px]",
511
+ title: `${change.label} \u2192 ${change.full}`,
512
+ children: [
513
+ /* @__PURE__ */ jsx7("span", { className: "shrink-0 text-muted-foreground", children: change.label }),
514
+ /* @__PURE__ */ jsx7("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
515
+ /* @__PURE__ */ jsx7(
516
+ "span",
517
+ {
518
+ className: `min-w-0 truncate ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
519
+ children: change.value
520
+ }
521
+ )
522
+ ]
523
+ },
524
+ change.key
525
+ )) }) : null
526
+ ] });
527
+ }
352
528
  function SideEffectDirectiveCard({ directive }) {
353
529
  const host = useDirectiveHost();
354
530
  const [expanded, setExpanded] = useState2(false);
355
531
  const items = directive.items;
356
532
  const total = items.length;
357
- const display = directiveDisplay2(directive.directiveClass, directive.noun, host.nouns);
533
+ const display = directiveDisplay3(directive.directiveClass, directive.noun, host.nouns);
358
534
  const Icon = classIcon(directive.directiveClass, directive.noun);
359
535
  const shown = expanded ? items : items.slice(0, ROWS_BEFORE_FOLD);
360
536
  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: [
537
+ return /* @__PURE__ */ jsxs5("div", { className: "my-3 rounded-md border border-border bg-card px-2.5 py-1.5", "data-directive": directive.slug, children: [
538
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: [
539
+ /* @__PURE__ */ jsx7(Icon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
540
+ /* @__PURE__ */ jsx7("span", { className: "text-sm font-medium text-foreground", children: display.title }),
541
+ display.family ? /* @__PURE__ */ jsx7("span", { className: "text-xs text-muted-foreground", children: display.family }) : null,
542
+ /* @__PURE__ */ jsxs5("span", { className: "text-xs tabular-nums text-muted-foreground", children: [
367
543
  total,
368
544
  " ",
369
545
  total === 1 ? "item" : "items"
370
546
  ] }),
371
- /* @__PURE__ */ jsxs4("div", { className: "ml-auto flex items-center gap-1", children: [
547
+ /* @__PURE__ */ jsxs5("div", { className: "ml-auto flex items-center gap-1", children: [
372
548
  host.renderCopy?.({ label: display.title, value: directive.shell, size: "icon" }),
373
- /* @__PURE__ */ jsx6(ApplyDirectiveButton, { directive, itemCount: total })
549
+ /* @__PURE__ */ jsx7(ApplyDirectiveButton, { directive, itemCount: total })
374
550
  ] })
375
551
  ] }),
376
552
  total === 0 ? (
377
553
  // 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(
554
+ /* @__PURE__ */ jsx7("p", { className: "mt-1 text-xs text-muted-foreground", children: "No items \u2014 nothing would be written." })
555
+ ) : /* @__PURE__ */ jsx7("div", { className: "mt-0.5 divide-y divide-border/60", children: shown.map((item, i) => /* @__PURE__ */ jsx7(ItemRow, { directive, item, index: i, total }, i)) }),
556
+ hidden > 0 || expanded ? /* @__PURE__ */ jsxs5(
381
557
  "button",
382
558
  {
383
559
  type: "button",
384
560
  onClick: () => setExpanded((v) => !v),
385
561
  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
562
  children: [
387
- expanded ? /* @__PURE__ */ jsx6(ChevronDownIcon, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx6(ChevronRightIcon, { className: "h-3 w-3" }),
563
+ expanded ? /* @__PURE__ */ jsx7(ChevronDownIcon, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx7(ChevronRightIcon, { className: "h-3 w-3" }),
388
564
  expanded ? "Show less" : `Show ${hidden} more`
389
565
  ]
390
566
  }
@@ -393,8 +569,16 @@ function SideEffectDirectiveCard({ directive }) {
393
569
  }
394
570
 
395
571
  // directives/DirectiveRender.tsx
396
- import { jsx as jsx7 } from "react/jsx-runtime";
397
- function DirectiveRender({ content, className }) {
572
+ import { jsx as jsx8 } from "react/jsx-runtime";
573
+ function isWholeJson(content) {
574
+ try {
575
+ JSON.parse(content);
576
+ return true;
577
+ } catch {
578
+ return false;
579
+ }
580
+ }
581
+ function DirectiveRender({ content, className, streaming }) {
398
582
  const host = useDirectiveHost();
399
583
  const directive = tryDecodeDirectiveContent(content, (message) => {
400
584
  const line = `[kind-directives] ${message}`;
@@ -402,8 +586,11 @@ function DirectiveRender({ content, className }) {
402
586
  else console.error(line);
403
587
  });
404
588
  if (!directive) {
589
+ if (typeof content === "string" && looksLikeDirectiveHead(content) && !isWholeJson(content)) {
590
+ return /* @__PURE__ */ jsx8(DirectiveProvisionalCard, { content, streaming: streaming !== false, className });
591
+ }
405
592
  const raw = typeof content === "string" ? content : JSON.stringify(content, null, 2);
406
- return /* @__PURE__ */ jsx7(
593
+ return /* @__PURE__ */ jsx8(
407
594
  "pre",
408
595
  {
409
596
  className: `my-3 overflow-x-auto rounded-md border border-border bg-muted px-3 py-2 text-xs text-muted-foreground${className ? ` ${className}` : ""}`,
@@ -412,9 +599,9 @@ function DirectiveRender({ content, className }) {
412
599
  );
413
600
  }
414
601
  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 });
602
+ if (Renderer) return /* @__PURE__ */ jsx8(Renderer, { directive });
603
+ if (directive.parsed.executes) return /* @__PURE__ */ jsx8(SideEffectDirectiveCard, { directive });
604
+ return /* @__PURE__ */ jsx8(DirectiveFallbackCard, { directive });
418
605
  }
419
606
 
420
607
  // route/kind-route.ts
@@ -442,7 +629,7 @@ function readIrRouteMarker(metadata) {
442
629
  }
443
630
 
444
631
  // react/KindInstanceRender.tsx
445
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
632
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
446
633
  function isRecordValue(value) {
447
634
  return typeof value === "object" && value !== null && !Array.isArray(value);
448
635
  }
@@ -455,7 +642,7 @@ function kindIsRoutable(kind, host) {
455
642
  }
456
643
  function KindInstanceRender(props) {
457
644
  if (isReservedDirectiveSlug2(props.kind)) {
458
- return /* @__PURE__ */ jsx8(
645
+ return /* @__PURE__ */ jsx9(
459
646
  DirectiveRender,
460
647
  {
461
648
  content: props.value,
@@ -463,7 +650,7 @@ function KindInstanceRender(props) {
463
650
  }
464
651
  );
465
652
  }
466
- return /* @__PURE__ */ jsx8(KindInstanceRenderInner, { ...props });
653
+ return /* @__PURE__ */ jsx9(KindInstanceRenderInner, { ...props });
467
654
  }
468
655
  function KindInstanceRenderInner({
469
656
  kind,
@@ -514,13 +701,13 @@ function KindInstanceRenderInner({
514
701
  } : null;
515
702
  const frameClass = variant === "bare" ? void 0 : "rounded-md border border-border bg-card p-3";
516
703
  if (routingStatus === "unroutable" && unroutableFallback !== void 0) {
517
- return /* @__PURE__ */ jsx8(Fragment2, { children: unroutableFallback });
704
+ return /* @__PURE__ */ jsx9(Fragment2, { children: unroutableFallback });
518
705
  }
519
706
  const onTheFloor = block === null || routingStatus === "unroutable";
520
707
  const notice = "This shape has no custom component yet, so it renders through the universal viewer \u2014 exactly what production shows today.";
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) })
708
+ return /* @__PURE__ */ jsxs6("div", { className: className ? `space-y-3 ${className}` : "space-y-3", children: [
709
+ showRoutingNote && routingStatus === "unroutable" ? host.renderNotice?.(notice) ?? /* @__PURE__ */ jsx9("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,
710
+ /* @__PURE__ */ jsx9("div", { className: frameClass, children: onTheFloor ? host.renderValue({ value, kind }) : host.renderBlock(block) })
524
711
  ] });
525
712
  }
526
713
 
@@ -547,7 +734,7 @@ function markKindPartialUnsafe(kind) {
547
734
  }
548
735
 
549
736
  // react/ProvisionalKindBoundary.tsx
550
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
737
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
551
738
  var ProvisionalKindBoundaryInner = class extends React.Component {
552
739
  state = { failed: false };
553
740
  static getDerivedStateFromError() {
@@ -572,14 +759,14 @@ var ProvisionalKindBoundaryInner = class extends React.Component {
572
759
  };
573
760
  function ProvisionalKindBoundary(props) {
574
761
  const host = useContentIrHost();
575
- return /* @__PURE__ */ jsx9(ProvisionalKindBoundaryInner, { ...props, reportError: host.reportError });
762
+ return /* @__PURE__ */ jsx10(ProvisionalKindBoundaryInner, { ...props, reportError: host.reportError });
576
763
  }
577
764
  function ProvisionalKindFrame({ children }) {
578
765
  const host = useContentIrHost();
579
766
  const label = "Still arriving";
580
- return /* @__PURE__ */ jsxs6("div", { className: "relative", "aria-busy": "true", children: [
767
+ return /* @__PURE__ */ jsxs7("div", { className: "relative", "aria-busy": "true", children: [
581
768
  children,
582
- /* @__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 }) })
769
+ /* @__PURE__ */ jsx10("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__ */ jsx10("span", { className: "text-[10px] text-muted-foreground", children: label }) })
583
770
  ] });
584
771
  }
585
772
 
@@ -590,7 +777,7 @@ import {
590
777
  readObjectKind as readObjectKind3,
591
778
  reconstructRegionValue
592
779
  } from "@ai-matrx/content-ir";
593
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
780
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
594
781
  function readStructuredValue(content, metadata) {
595
782
  const envelope = readEnvelope3(metadata);
596
783
  if (envelope) {
@@ -615,19 +802,19 @@ function GenericStructuredView({
615
802
  const kind = envelope?.root.kind ?? (typeof value === "object" && value !== null && !Array.isArray(value) ? readObjectKind3(value) : null) ?? "";
616
803
  const marker = readIrRouteMarker(metadata);
617
804
  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";
618
- return /* @__PURE__ */ jsxs7("div", { className: className ? `my-2 min-w-0 ${className}` : "my-2 min-w-0", children: [
619
- status === "streaming" ? streamingIndicator ?? /* @__PURE__ */ jsx10("div", { className: "mb-2 text-xs text-muted-foreground", children: "Still arriving\u2026" }) : null,
805
+ return /* @__PURE__ */ jsxs8("div", { className: className ? `my-2 min-w-0 ${className}` : "my-2 min-w-0", children: [
806
+ status === "streaming" ? streamingIndicator ?? /* @__PURE__ */ jsx11("div", { className: "mb-2 text-xs text-muted-foreground", children: "Still arriving\u2026" }) : null,
620
807
  recovered ? host.renderValue({ value, ...kind ? { kind } : {}, note }) : (
621
808
  // Zero-data-loss backstop: the region never parsed, so show the source
622
809
  // verbatim rather than swallowing it.
623
- /* @__PURE__ */ jsx10("pre", { className: "max-h-96 overflow-auto font-mono text-xs leading-relaxed text-muted-foreground", children: content })
810
+ /* @__PURE__ */ jsx11("pre", { className: "max-h-96 overflow-auto font-mono text-xs leading-relaxed text-muted-foreground", children: content })
624
811
  )
625
812
  ] });
626
813
  }
627
814
 
628
815
  // react/RuntimeWrapperViews.tsx
629
816
  import { readNodeOutcomeValue, readObjectKind as readObjectKind4, readRunResultValue } from "@ai-matrx/content-ir";
630
- import { Fragment as Fragment3, jsx as jsx11 } from "react/jsx-runtime";
817
+ import { Fragment as Fragment3, jsx as jsx12 } from "react/jsx-runtime";
631
818
  function isRecord2(value) {
632
819
  return typeof value === "object" && value !== null && !Array.isArray(value);
633
820
  }
@@ -643,16 +830,16 @@ function DelegatedOutput({
643
830
  }) {
644
831
  const host = useContentIrHost();
645
832
  if (output === null || output === void 0) {
646
- return /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground", children: emptyLabel });
833
+ return /* @__PURE__ */ jsx12("p", { className: "text-xs text-muted-foreground", children: emptyLabel });
647
834
  }
648
835
  if (!isRecord2(output)) {
649
- return /* @__PURE__ */ jsx11(Fragment3, { children: host.renderValue({ value: output }) });
836
+ return /* @__PURE__ */ jsx12(Fragment3, { children: host.renderValue({ value: output }) });
650
837
  }
651
838
  const kind = readObjectKind4(output) ?? declaredKind;
652
839
  if (!kind) {
653
- return /* @__PURE__ */ jsx11(Fragment3, { children: fallback?.(output) ?? host.renderValue({ value: output }) });
840
+ return /* @__PURE__ */ jsx12(Fragment3, { children: fallback?.(output) ?? host.renderValue({ value: output }) });
654
841
  }
655
- return /* @__PURE__ */ jsx11(
842
+ return /* @__PURE__ */ jsx12(
656
843
  KindInstanceRender,
657
844
  {
658
845
  kind,
@@ -669,7 +856,7 @@ function NodeOutcomeView({ serverData, fallback }) {
669
856
  readNodeOutcomeValue
670
857
  );
671
858
  if (!wrapper) return null;
672
- return /* @__PURE__ */ jsx11(
859
+ return /* @__PURE__ */ jsx12(
673
860
  DelegatedOutput,
674
861
  {
675
862
  output: wrapper.output,
@@ -684,14 +871,14 @@ function RunResultView({ serverData, fallback }) {
684
871
  readRunResultValue
685
872
  );
686
873
  if (!wrapper) return null;
687
- return /* @__PURE__ */ jsx11("div", { className: "space-y-2", children: wrapper.outputs.length > 0 ? wrapper.outputs.map((outcome) => /* @__PURE__ */ jsx11(
874
+ return /* @__PURE__ */ jsx12("div", { className: "space-y-2", children: wrapper.outputs.length > 0 ? wrapper.outputs.map((outcome) => /* @__PURE__ */ jsx12(
688
875
  NodeOutcomeView,
689
876
  {
690
877
  serverData: { wrapper: outcome },
691
878
  ...fallback === void 0 ? {} : { fallback }
692
879
  },
693
880
  `${outcome.node_id}:${outcome.attempt}`
694
- )) : /* @__PURE__ */ jsx11(
881
+ )) : /* @__PURE__ */ jsx12(
695
882
  DelegatedOutput,
696
883
  {
697
884
  output: wrapper.output,