@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/index.js CHANGED
@@ -708,13 +708,70 @@ import {
708
708
  } from "@ai-matrx/content-ir";
709
709
 
710
710
  // directives/DirectiveRender.tsx
711
- import { tryDecodeDirectiveContent } from "@ai-matrx/content-ir";
711
+ import { looksLikeDirectiveHead, tryDecodeDirectiveContent } from "@ai-matrx/content-ir";
712
712
 
713
713
  // directives/DirectiveFallbackCard.tsx
714
714
  import { directiveDisplay } from "@ai-matrx/content-ir";
715
715
 
716
716
  // directives/ApplyDirectiveButton.tsx
717
717
  import { useEffect, useRef, useState } from "react";
718
+ import { nounLabel } from "@ai-matrx/content-ir";
719
+
720
+ // directives/item-changes.ts
721
+ var TARGETING_CLASSES = /* @__PURE__ */ new Set(["update", "delete"]);
722
+ var NOT_A_CHANGE = /* @__PURE__ */ new Set(["__kind", "id"]);
723
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
724
+ var CHANGE_VALUE_MAX = 60;
725
+ function itemRecordId(item) {
726
+ const id = item.id;
727
+ if (typeof id === "string" && id.trim()) return id.trim();
728
+ if (typeof id === "number") return String(id);
729
+ return null;
730
+ }
731
+ function fieldLabel(key) {
732
+ const spaced = key.replace(/_/g, " ").trim();
733
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
734
+ }
735
+ function recordFallbackName(nounLabel3, id) {
736
+ const short = UUID_RE.test(id) ? id.slice(0, 8) : id.length > 12 ? `${id.slice(0, 12)}\u2026` : id;
737
+ return `${nounLabel3} ${short}`;
738
+ }
739
+ function describeValue(value) {
740
+ if (value === null || value === void 0) return { value: "cleared", full: "cleared", clears: true };
741
+ if (typeof value === "string") {
742
+ const trimmed = value.trim();
743
+ if (!trimmed) return { value: "cleared", full: "cleared", clears: true };
744
+ const oneLine = trimmed.replace(/\s+/g, " ");
745
+ const shown = oneLine.length > CHANGE_VALUE_MAX ? `${oneLine.slice(0, CHANGE_VALUE_MAX - 1)}\u2026` : oneLine;
746
+ return { value: shown, full: trimmed, clears: false };
747
+ }
748
+ if (typeof value === "number" || typeof value === "boolean") {
749
+ return { value: String(value), full: String(value), clears: false };
750
+ }
751
+ if (Array.isArray(value)) {
752
+ const n2 = value.length;
753
+ const text2 = n2 === 0 ? "cleared" : `${n2} ${n2 === 1 ? "entry" : "entries"}`;
754
+ return { value: text2, full: safeJson(value), clears: n2 === 0 };
755
+ }
756
+ const n = Object.keys(value).length;
757
+ const text = n === 0 ? "cleared" : `${n} ${n === 1 ? "field" : "fields"}`;
758
+ return { value: text, full: safeJson(value), clears: n === 0 };
759
+ }
760
+ function safeJson(value) {
761
+ try {
762
+ return JSON.stringify(value, null, 2);
763
+ } catch {
764
+ return String(value);
765
+ }
766
+ }
767
+ function itemChanges(item) {
768
+ const out = [];
769
+ for (const [key, raw] of Object.entries(item)) {
770
+ if (NOT_A_CHANGE.has(key)) continue;
771
+ out.push({ key, label: fieldLabel(key), ...describeValue(raw) });
772
+ }
773
+ return out;
774
+ }
718
775
 
719
776
  // directives/icons.tsx
720
777
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
@@ -832,10 +889,38 @@ function ApplyDirectiveButton({
832
889
  const items = directive.items;
833
890
  async function handleApply() {
834
891
  if (!confirm) return;
892
+ if (host.ask) {
893
+ setState({ status: "asking" });
894
+ let ok = false;
895
+ try {
896
+ ok = await host.ask({
897
+ directive,
898
+ items,
899
+ nounLabel: nounLabel(directive.noun, host.nouns)
900
+ });
901
+ } catch (error) {
902
+ setState({
903
+ status: "error",
904
+ message: error instanceof Error && error.message ? error.message : "We could not ask you to confirm this, so nothing was done."
905
+ });
906
+ return;
907
+ }
908
+ if (!ok) {
909
+ setState({ status: "idle" });
910
+ return;
911
+ }
912
+ }
913
+ setElapsed(0);
835
914
  setState({ status: "applying" });
836
915
  try {
837
916
  const result = await confirm({ __kind: directive.slug, items });
838
- setState({ status: "applied", applied: result.applied, failed: result.failed });
917
+ setState({
918
+ status: "applied",
919
+ applied: result.applied,
920
+ failed: result.failed,
921
+ message: result.message?.trim() ? result.message.trim() : null,
922
+ records: result.records ?? []
923
+ });
839
924
  onApplied?.();
840
925
  } catch (error) {
841
926
  setState({
@@ -846,15 +931,26 @@ function ApplyDirectiveButton({
846
931
  }
847
932
  if (state.status === "applied") {
848
933
  const bad = state.failed > 0;
934
+ const trashed = directive.directiveClass === "delete";
935
+ const label2 = nounLabel(directive.noun, host.nouns);
936
+ const records = host.renderRecord ? state.records : [];
849
937
  return /* @__PURE__ */ jsxs2(
850
938
  "span",
851
939
  {
852
- className: `inline-flex items-center gap-1 text-xs ${bad ? "text-destructive" : "text-primary"}`,
940
+ className: `inline-flex min-w-0 flex-wrap items-center gap-1 text-xs ${bad ? "text-destructive" : "text-primary"}`,
941
+ "data-apply-state": "applied",
853
942
  children: [
854
- bad ? /* @__PURE__ */ jsx4(AlertIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx4(CheckCircleIcon, { className: "h-3.5 w-3.5" }),
855
- "Applied ",
856
- state.applied,
857
- bad ? ` \xB7 ${state.failed} failed` : ""
943
+ 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" }),
944
+ /* @__PURE__ */ jsxs2("span", { children: [
945
+ state.message ?? `Applied ${state.applied}`,
946
+ bad && !state.message ? ` \xB7 ${state.failed} failed` : ""
947
+ ] }),
948
+ records.map((record) => /* @__PURE__ */ jsx4("span", { className: "inline-flex min-w-0 items-center", children: host.renderRecord?.({
949
+ ...record,
950
+ fallback: recordFallbackName(label2, record.id),
951
+ context: "applied",
952
+ trashed
953
+ }) }, `${record.noun}:${record.id}`))
858
954
  ]
859
955
  }
860
956
  );
@@ -865,7 +961,7 @@ function ApplyDirectiveButton({
865
961
  {
866
962
  type: "button",
867
963
  onClick: () => void handleApply(),
868
- disabled: state.status === "applying" || items.length === 0,
964
+ disabled: state.status === "applying" || state.status === "asking" || items.length === 0,
869
965
  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",
870
966
  children: [
871
967
  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" }),
@@ -907,6 +1003,46 @@ function DirectiveFallbackCard({ directive, reason }) {
907
1003
  ] });
908
1004
  }
909
1005
 
1006
+ // directives/DirectiveProvisionalCard.tsx
1007
+ import { directiveDisplay as directiveDisplay2, parseDirectiveSlug } from "@ai-matrx/content-ir";
1008
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1009
+ var COMPLETE_SLUG_RE = /^\{\s*"__kind"\s*:\s*"([^"]+)"/;
1010
+ function provisionalDirectiveSlug(content) {
1011
+ const match = content.trimStart().match(COMPLETE_SLUG_RE);
1012
+ return match?.[1] ?? null;
1013
+ }
1014
+ function DirectiveProvisionalCard({ content, streaming, className }) {
1015
+ const host = useDirectiveHost();
1016
+ const slug = provisionalDirectiveSlug(content);
1017
+ const known = slug ? parseDirectiveSlug(slug) : null;
1018
+ const display = known ? directiveDisplay2(known.directiveClass, known.noun, host.nouns) : null;
1019
+ const Icon = known ? classIcon(known.directiveClass, known.noun) : BoxesIcon;
1020
+ const title = display?.title ?? "Structured action";
1021
+ return /* @__PURE__ */ jsxs4(
1022
+ "div",
1023
+ {
1024
+ className: `my-3 rounded-md border border-border bg-card px-2.5 py-1.5${className ? ` ${className}` : ""}`,
1025
+ "data-directive": slug ?? void 0,
1026
+ "data-directive-state": streaming ? "streaming" : "incomplete",
1027
+ children: [
1028
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: [
1029
+ /* @__PURE__ */ jsx6(Icon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
1030
+ /* @__PURE__ */ jsx6("span", { className: "text-sm font-medium text-foreground", children: title }),
1031
+ display?.family ? /* @__PURE__ */ jsx6("span", { className: "text-xs text-muted-foreground", children: display.family }) : null,
1032
+ streaming ? /* @__PURE__ */ jsxs4("span", { className: "inline-flex items-center gap-1.5 text-xs text-muted-foreground", role: "status", children: [
1033
+ /* @__PURE__ */ jsx6("span", { className: "h-1.5 w-1.5 animate-pulse rounded-full bg-primary", "aria-hidden": true }),
1034
+ "Writing\u2026"
1035
+ ] }) : /* @__PURE__ */ jsx6("span", { className: "text-xs text-destructive", role: "status", children: "Cut off before it finished \u2014 nothing can be applied." })
1036
+ ] }),
1037
+ streaming ? null : /* @__PURE__ */ jsxs4("details", { className: "mt-1 text-xs text-muted-foreground", children: [
1038
+ /* @__PURE__ */ jsx6("summary", { className: "cursor-pointer select-none hover:text-foreground", children: "Show what arrived" }),
1039
+ /* @__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 })
1040
+ ] })
1041
+ ]
1042
+ }
1043
+ );
1044
+ }
1045
+
910
1046
  // directives/registry.ts
911
1047
  import {
912
1048
  buildDirectiveSlug
@@ -932,13 +1068,14 @@ function resetDirectiveRenderers() {
932
1068
  import { useState as useState2 } from "react";
933
1069
  import {
934
1070
  asKindInstance,
935
- directiveDisplay as directiveDisplay2,
1071
+ directiveDisplay as directiveDisplay3,
936
1072
  itemFacts,
937
1073
  itemSubtitle,
938
1074
  itemTitle,
1075
+ nounLabel as nounLabel2,
939
1076
  nounTitleColumn
940
1077
  } from "@ai-matrx/content-ir";
941
- import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1078
+ import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
942
1079
  var ROWS_BEFORE_FOLD = 3;
943
1080
  function ItemRow({
944
1081
  directive,
@@ -947,25 +1084,29 @@ function ItemRow({
947
1084
  total
948
1085
  }) {
949
1086
  const host = useDirectiveHost();
1087
+ const recordId = TARGETING_CLASSES.has(directive.directiveClass) ? itemRecordId(item) : null;
1088
+ if (recordId) {
1089
+ return /* @__PURE__ */ jsx7(TargetRow, { directive, item, recordId });
1090
+ }
950
1091
  const titleColumn = nounTitleColumn(directive.noun, host.nouns);
951
1092
  const title = itemTitle(item, titleColumn, index, total);
952
1093
  const subtitle = itemSubtitle(item);
953
1094
  const facts = itemFacts(item);
954
1095
  const kind = host.itemKind?.(directive.slug) ?? null;
955
- const display = directiveDisplay2(directive.directiveClass, directive.noun, host.nouns);
1096
+ const display = directiveDisplay3(directive.directiveClass, directive.noun, host.nouns);
956
1097
  const openItem = host.openItem;
957
- const body = /* @__PURE__ */ jsxs4(Fragment, { children: [
958
- /* @__PURE__ */ jsx6("span", { className: "min-w-0 shrink-0 truncate font-medium text-foreground", children: title }),
959
- /* @__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: [
1098
+ const body = /* @__PURE__ */ jsxs5(Fragment, { children: [
1099
+ /* @__PURE__ */ jsx7("span", { className: "min-w-0 shrink-0 truncate font-medium text-foreground", children: title }),
1100
+ /* @__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: [
960
1101
  fact.value,
961
1102
  " ",
962
1103
  fact.label
963
1104
  ] }, fact.key)) }),
964
- subtitle && facts.length === 0 ? /* @__PURE__ */ jsx6("span", { className: "hidden truncate text-[11px] text-muted-foreground sm:inline", children: subtitle }) : null,
965
- openItem ? /* @__PURE__ */ jsx6(MaximizeIcon, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground" }) : null
1105
+ subtitle && facts.length === 0 ? /* @__PURE__ */ jsx7("span", { className: "hidden truncate text-[11px] text-muted-foreground sm:inline", children: subtitle }) : null,
1106
+ openItem ? /* @__PURE__ */ jsx7(MaximizeIcon, { className: "ml-auto h-3 w-3 shrink-0 text-muted-foreground" }) : null
966
1107
  ] });
967
- return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 py-1 text-xs", children: [
968
- openItem ? /* @__PURE__ */ jsx6(
1108
+ return /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 py-1 text-xs", children: [
1109
+ openItem ? /* @__PURE__ */ jsx7(
969
1110
  "button",
970
1111
  {
971
1112
  type: "button",
@@ -983,46 +1124,81 @@ function ItemRow({
983
1124
  title: "Open to read it",
984
1125
  children: body
985
1126
  }
986
- ) : /* @__PURE__ */ jsx6("span", { className: "flex min-w-0 flex-1 items-center gap-2 px-1 py-0.5", children: body }),
1127
+ ) : /* @__PURE__ */ jsx7("span", { className: "flex min-w-0 flex-1 items-center gap-2 px-1 py-0.5", children: body }),
987
1128
  host.renderCopy?.({ label: title, value: item, kind, size: "xs" })
988
1129
  ] });
989
1130
  }
1131
+ function TargetRow({
1132
+ directive,
1133
+ item,
1134
+ recordId
1135
+ }) {
1136
+ const host = useDirectiveHost();
1137
+ const fallback = recordFallbackName(nounLabel2(directive.noun, host.nouns), recordId);
1138
+ const changes = directive.directiveClass === "update" ? itemChanges(item) : [];
1139
+ 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 });
1140
+ return /* @__PURE__ */ jsxs5("div", { className: "py-1 text-xs", "data-directive-target": recordId, children: [
1141
+ /* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 items-center gap-2", children: [
1142
+ /* @__PURE__ */ jsx7("span", { className: "flex min-w-0 flex-1 items-center gap-1 px-1", children: name }),
1143
+ host.renderCopy?.({ label: fallback, value: item, size: "xs" })
1144
+ ] }),
1145
+ 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(
1146
+ "li",
1147
+ {
1148
+ className: "flex min-w-0 items-baseline gap-1.5 text-[11px]",
1149
+ title: `${change.label} \u2192 ${change.full}`,
1150
+ children: [
1151
+ /* @__PURE__ */ jsx7("span", { className: "shrink-0 text-muted-foreground", children: change.label }),
1152
+ /* @__PURE__ */ jsx7("span", { "aria-hidden": true, className: "shrink-0 text-muted-foreground", children: "\u2192" }),
1153
+ /* @__PURE__ */ jsx7(
1154
+ "span",
1155
+ {
1156
+ className: `min-w-0 truncate ${change.clears ? "italic text-muted-foreground" : "text-foreground"}`,
1157
+ children: change.value
1158
+ }
1159
+ )
1160
+ ]
1161
+ },
1162
+ change.key
1163
+ )) }) : null
1164
+ ] });
1165
+ }
990
1166
  function SideEffectDirectiveCard({ directive }) {
991
1167
  const host = useDirectiveHost();
992
1168
  const [expanded, setExpanded] = useState2(false);
993
1169
  const items = directive.items;
994
1170
  const total = items.length;
995
- const display = directiveDisplay2(directive.directiveClass, directive.noun, host.nouns);
1171
+ const display = directiveDisplay3(directive.directiveClass, directive.noun, host.nouns);
996
1172
  const Icon = classIcon(directive.directiveClass, directive.noun);
997
1173
  const shown = expanded ? items : items.slice(0, ROWS_BEFORE_FOLD);
998
1174
  const hidden = total - shown.length;
999
- 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: [
1000
- /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: [
1001
- /* @__PURE__ */ jsx6(Icon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
1002
- /* @__PURE__ */ jsx6("span", { className: "text-sm font-medium text-foreground", children: display.title }),
1003
- display.family ? /* @__PURE__ */ jsx6("span", { className: "text-xs text-muted-foreground", children: display.family }) : null,
1004
- /* @__PURE__ */ jsxs4("span", { className: "text-xs tabular-nums text-muted-foreground", children: [
1175
+ 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: [
1176
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: [
1177
+ /* @__PURE__ */ jsx7(Icon, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
1178
+ /* @__PURE__ */ jsx7("span", { className: "text-sm font-medium text-foreground", children: display.title }),
1179
+ display.family ? /* @__PURE__ */ jsx7("span", { className: "text-xs text-muted-foreground", children: display.family }) : null,
1180
+ /* @__PURE__ */ jsxs5("span", { className: "text-xs tabular-nums text-muted-foreground", children: [
1005
1181
  total,
1006
1182
  " ",
1007
1183
  total === 1 ? "item" : "items"
1008
1184
  ] }),
1009
- /* @__PURE__ */ jsxs4("div", { className: "ml-auto flex items-center gap-1", children: [
1185
+ /* @__PURE__ */ jsxs5("div", { className: "ml-auto flex items-center gap-1", children: [
1010
1186
  host.renderCopy?.({ label: display.title, value: directive.shell, size: "icon" }),
1011
- /* @__PURE__ */ jsx6(ApplyDirectiveButton, { directive, itemCount: total })
1187
+ /* @__PURE__ */ jsx7(ApplyDirectiveButton, { directive, itemCount: total })
1012
1188
  ] })
1013
1189
  ] }),
1014
1190
  total === 0 ? (
1015
1191
  // Stated, never silent: an empty batch is a real (and suspicious) state.
1016
- /* @__PURE__ */ jsx6("p", { className: "mt-1 text-xs text-muted-foreground", children: "No items \u2014 nothing would be written." })
1017
- ) : /* @__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)) }),
1018
- hidden > 0 || expanded ? /* @__PURE__ */ jsxs4(
1192
+ /* @__PURE__ */ jsx7("p", { className: "mt-1 text-xs text-muted-foreground", children: "No items \u2014 nothing would be written." })
1193
+ ) : /* @__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)) }),
1194
+ hidden > 0 || expanded ? /* @__PURE__ */ jsxs5(
1019
1195
  "button",
1020
1196
  {
1021
1197
  type: "button",
1022
1198
  onClick: () => setExpanded((v) => !v),
1023
1199
  className: "mt-0.5 inline-flex items-center gap-1 rounded px-1 py-0.5 text-[11px] text-muted-foreground hover:text-foreground",
1024
1200
  children: [
1025
- expanded ? /* @__PURE__ */ jsx6(ChevronDownIcon, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx6(ChevronRightIcon, { className: "h-3 w-3" }),
1201
+ expanded ? /* @__PURE__ */ jsx7(ChevronDownIcon, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx7(ChevronRightIcon, { className: "h-3 w-3" }),
1026
1202
  expanded ? "Show less" : `Show ${hidden} more`
1027
1203
  ]
1028
1204
  }
@@ -1031,8 +1207,16 @@ function SideEffectDirectiveCard({ directive }) {
1031
1207
  }
1032
1208
 
1033
1209
  // directives/DirectiveRender.tsx
1034
- import { jsx as jsx7 } from "react/jsx-runtime";
1035
- function DirectiveRender({ content, className }) {
1210
+ import { jsx as jsx8 } from "react/jsx-runtime";
1211
+ function isWholeJson(content) {
1212
+ try {
1213
+ JSON.parse(content);
1214
+ return true;
1215
+ } catch {
1216
+ return false;
1217
+ }
1218
+ }
1219
+ function DirectiveRender({ content, className, streaming }) {
1036
1220
  const host = useDirectiveHost();
1037
1221
  const directive = tryDecodeDirectiveContent(content, (message) => {
1038
1222
  const line = `[kind-directives] ${message}`;
@@ -1040,8 +1224,11 @@ function DirectiveRender({ content, className }) {
1040
1224
  else console.error(line);
1041
1225
  });
1042
1226
  if (!directive) {
1227
+ if (typeof content === "string" && looksLikeDirectiveHead(content) && !isWholeJson(content)) {
1228
+ return /* @__PURE__ */ jsx8(DirectiveProvisionalCard, { content, streaming: streaming !== false, className });
1229
+ }
1043
1230
  const raw = typeof content === "string" ? content : JSON.stringify(content, null, 2);
1044
- return /* @__PURE__ */ jsx7(
1231
+ return /* @__PURE__ */ jsx8(
1045
1232
  "pre",
1046
1233
  {
1047
1234
  className: `my-3 overflow-x-auto rounded-md border border-border bg-muted px-3 py-2 text-xs text-muted-foreground${className ? ` ${className}` : ""}`,
@@ -1050,13 +1237,13 @@ function DirectiveRender({ content, className }) {
1050
1237
  );
1051
1238
  }
1052
1239
  const Renderer = getDirectiveRenderer(directive);
1053
- if (Renderer) return /* @__PURE__ */ jsx7(Renderer, { directive });
1054
- if (directive.parsed.executes) return /* @__PURE__ */ jsx7(SideEffectDirectiveCard, { directive });
1055
- return /* @__PURE__ */ jsx7(DirectiveFallbackCard, { directive });
1240
+ if (Renderer) return /* @__PURE__ */ jsx8(Renderer, { directive });
1241
+ if (directive.parsed.executes) return /* @__PURE__ */ jsx8(SideEffectDirectiveCard, { directive });
1242
+ return /* @__PURE__ */ jsx8(DirectiveFallbackCard, { directive });
1056
1243
  }
1057
1244
 
1058
1245
  // react/KindInstanceRender.tsx
1059
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1246
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1060
1247
  function isRecordValue(value) {
1061
1248
  return typeof value === "object" && value !== null && !Array.isArray(value);
1062
1249
  }
@@ -1069,7 +1256,7 @@ function kindIsRoutable(kind, host) {
1069
1256
  }
1070
1257
  function KindInstanceRender(props) {
1071
1258
  if (isReservedDirectiveSlug2(props.kind)) {
1072
- return /* @__PURE__ */ jsx8(
1259
+ return /* @__PURE__ */ jsx9(
1073
1260
  DirectiveRender,
1074
1261
  {
1075
1262
  content: props.value,
@@ -1077,7 +1264,7 @@ function KindInstanceRender(props) {
1077
1264
  }
1078
1265
  );
1079
1266
  }
1080
- return /* @__PURE__ */ jsx8(KindInstanceRenderInner, { ...props });
1267
+ return /* @__PURE__ */ jsx9(KindInstanceRenderInner, { ...props });
1081
1268
  }
1082
1269
  function KindInstanceRenderInner({
1083
1270
  kind,
@@ -1128,19 +1315,19 @@ function KindInstanceRenderInner({
1128
1315
  } : null;
1129
1316
  const frameClass = variant === "bare" ? void 0 : "rounded-md border border-border bg-card p-3";
1130
1317
  if (routingStatus === "unroutable" && unroutableFallback !== void 0) {
1131
- return /* @__PURE__ */ jsx8(Fragment2, { children: unroutableFallback });
1318
+ return /* @__PURE__ */ jsx9(Fragment2, { children: unroutableFallback });
1132
1319
  }
1133
1320
  const onTheFloor = block === null || routingStatus === "unroutable";
1134
1321
  const notice = "This shape has no custom component yet, so it renders through the universal viewer \u2014 exactly what production shows today.";
1135
- return /* @__PURE__ */ jsxs5("div", { className: className ? `space-y-3 ${className}` : "space-y-3", children: [
1136
- 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,
1137
- /* @__PURE__ */ jsx8("div", { className: frameClass, children: onTheFloor ? host.renderValue({ value, kind }) : host.renderBlock(block) })
1322
+ return /* @__PURE__ */ jsxs6("div", { className: className ? `space-y-3 ${className}` : "space-y-3", children: [
1323
+ 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,
1324
+ /* @__PURE__ */ jsx9("div", { className: frameClass, children: onTheFloor ? host.renderValue({ value, kind }) : host.renderBlock(block) })
1138
1325
  ] });
1139
1326
  }
1140
1327
 
1141
1328
  // react/ProvisionalKindBoundary.tsx
1142
1329
  import React from "react";
1143
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1330
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1144
1331
  var ProvisionalKindBoundaryInner = class extends React.Component {
1145
1332
  state = { failed: false };
1146
1333
  static getDerivedStateFromError() {
@@ -1165,14 +1352,14 @@ var ProvisionalKindBoundaryInner = class extends React.Component {
1165
1352
  };
1166
1353
  function ProvisionalKindBoundary(props) {
1167
1354
  const host = useContentIrHost();
1168
- return /* @__PURE__ */ jsx9(ProvisionalKindBoundaryInner, { ...props, reportError: host.reportError });
1355
+ return /* @__PURE__ */ jsx10(ProvisionalKindBoundaryInner, { ...props, reportError: host.reportError });
1169
1356
  }
1170
1357
  function ProvisionalKindFrame({ children }) {
1171
1358
  const host = useContentIrHost();
1172
1359
  const label = "Still arriving";
1173
- return /* @__PURE__ */ jsxs6("div", { className: "relative", "aria-busy": "true", children: [
1360
+ return /* @__PURE__ */ jsxs7("div", { className: "relative", "aria-busy": "true", children: [
1174
1361
  children,
1175
- /* @__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 }) })
1362
+ /* @__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 }) })
1176
1363
  ] });
1177
1364
  }
1178
1365
 
@@ -1183,7 +1370,7 @@ import {
1183
1370
  readObjectKind as readObjectKind3,
1184
1371
  reconstructRegionValue
1185
1372
  } from "@ai-matrx/content-ir";
1186
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1373
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1187
1374
  function readStructuredValue(content, metadata) {
1188
1375
  const envelope = readEnvelope3(metadata);
1189
1376
  if (envelope) {
@@ -1208,19 +1395,19 @@ function GenericStructuredView({
1208
1395
  const kind = envelope?.root.kind ?? (typeof value === "object" && value !== null && !Array.isArray(value) ? readObjectKind3(value) : null) ?? "";
1209
1396
  const marker = readIrRouteMarker(metadata);
1210
1397
  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";
1211
- return /* @__PURE__ */ jsxs7("div", { className: className ? `my-2 min-w-0 ${className}` : "my-2 min-w-0", children: [
1212
- status === "streaming" ? streamingIndicator ?? /* @__PURE__ */ jsx10("div", { className: "mb-2 text-xs text-muted-foreground", children: "Still arriving\u2026" }) : null,
1398
+ return /* @__PURE__ */ jsxs8("div", { className: className ? `my-2 min-w-0 ${className}` : "my-2 min-w-0", children: [
1399
+ status === "streaming" ? streamingIndicator ?? /* @__PURE__ */ jsx11("div", { className: "mb-2 text-xs text-muted-foreground", children: "Still arriving\u2026" }) : null,
1213
1400
  recovered ? host.renderValue({ value, ...kind ? { kind } : {}, note }) : (
1214
1401
  // Zero-data-loss backstop: the region never parsed, so show the source
1215
1402
  // verbatim rather than swallowing it.
1216
- /* @__PURE__ */ jsx10("pre", { className: "max-h-96 overflow-auto font-mono text-xs leading-relaxed text-muted-foreground", children: content })
1403
+ /* @__PURE__ */ jsx11("pre", { className: "max-h-96 overflow-auto font-mono text-xs leading-relaxed text-muted-foreground", children: content })
1217
1404
  )
1218
1405
  ] });
1219
1406
  }
1220
1407
 
1221
1408
  // react/RuntimeWrapperViews.tsx
1222
1409
  import { readNodeOutcomeValue, readObjectKind as readObjectKind4, readRunResultValue } from "@ai-matrx/content-ir";
1223
- import { Fragment as Fragment3, jsx as jsx11 } from "react/jsx-runtime";
1410
+ import { Fragment as Fragment3, jsx as jsx12 } from "react/jsx-runtime";
1224
1411
  function isRecord2(value) {
1225
1412
  return typeof value === "object" && value !== null && !Array.isArray(value);
1226
1413
  }
@@ -1236,16 +1423,16 @@ function DelegatedOutput({
1236
1423
  }) {
1237
1424
  const host = useContentIrHost();
1238
1425
  if (output === null || output === void 0) {
1239
- return /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground", children: emptyLabel });
1426
+ return /* @__PURE__ */ jsx12("p", { className: "text-xs text-muted-foreground", children: emptyLabel });
1240
1427
  }
1241
1428
  if (!isRecord2(output)) {
1242
- return /* @__PURE__ */ jsx11(Fragment3, { children: host.renderValue({ value: output }) });
1429
+ return /* @__PURE__ */ jsx12(Fragment3, { children: host.renderValue({ value: output }) });
1243
1430
  }
1244
1431
  const kind = readObjectKind4(output) ?? declaredKind;
1245
1432
  if (!kind) {
1246
- return /* @__PURE__ */ jsx11(Fragment3, { children: fallback?.(output) ?? host.renderValue({ value: output }) });
1433
+ return /* @__PURE__ */ jsx12(Fragment3, { children: fallback?.(output) ?? host.renderValue({ value: output }) });
1247
1434
  }
1248
- return /* @__PURE__ */ jsx11(
1435
+ return /* @__PURE__ */ jsx12(
1249
1436
  KindInstanceRender,
1250
1437
  {
1251
1438
  kind,
@@ -1262,7 +1449,7 @@ function NodeOutcomeView({ serverData, fallback }) {
1262
1449
  readNodeOutcomeValue
1263
1450
  );
1264
1451
  if (!wrapper) return null;
1265
- return /* @__PURE__ */ jsx11(
1452
+ return /* @__PURE__ */ jsx12(
1266
1453
  DelegatedOutput,
1267
1454
  {
1268
1455
  output: wrapper.output,
@@ -1277,14 +1464,14 @@ function RunResultView({ serverData, fallback }) {
1277
1464
  readRunResultValue
1278
1465
  );
1279
1466
  if (!wrapper) return null;
1280
- return /* @__PURE__ */ jsx11("div", { className: "space-y-2", children: wrapper.outputs.length > 0 ? wrapper.outputs.map((outcome) => /* @__PURE__ */ jsx11(
1467
+ return /* @__PURE__ */ jsx12("div", { className: "space-y-2", children: wrapper.outputs.length > 0 ? wrapper.outputs.map((outcome) => /* @__PURE__ */ jsx12(
1281
1468
  NodeOutcomeView,
1282
1469
  {
1283
1470
  serverData: { wrapper: outcome },
1284
1471
  ...fallback === void 0 ? {} : { fallback }
1285
1472
  },
1286
1473
  `${outcome.node_id}:${outcome.attempt}`
1287
- )) : /* @__PURE__ */ jsx11(
1474
+ )) : /* @__PURE__ */ jsx12(
1288
1475
  DelegatedOutput,
1289
1476
  {
1290
1477
  output: wrapper.output,
@@ -1482,6 +1669,7 @@ var DbKindComponentErrorBoundary = class extends React2.Component {
1482
1669
  };
1483
1670
  export {
1484
1671
  ApplyDirectiveButton,
1672
+ CHANGE_VALUE_MAX,
1485
1673
  ComponentResolver,
1486
1674
  ContentIrRenderProvider,
1487
1675
  DB_KIND_COMPONENT_KEY,
@@ -1490,6 +1678,7 @@ export {
1490
1678
  DelegatedOutput,
1491
1679
  DirectiveFallbackCard,
1492
1680
  DirectiveHostProvider,
1681
+ DirectiveProvisionalCard,
1493
1682
  DirectiveRender,
1494
1683
  GENERIC_STRUCTURED_COMPONENT_KEY,
1495
1684
  GenericStructuredView,
@@ -1501,20 +1690,26 @@ export {
1501
1690
  ProvisionalKindFrame,
1502
1691
  RunResultView,
1503
1692
  SideEffectDirectiveCard,
1693
+ TARGETING_CLASSES,
1504
1694
  applyIrKindRoute,
1505
1695
  consoleErrorReporter,
1506
1696
  createDbKindComponentCache,
1507
1697
  createKindRouteBinding,
1508
1698
  envelopeFromPartialKind,
1699
+ fieldLabel,
1509
1700
  getDirectiveRenderer,
1510
1701
  isDbKindComponentBodyPending,
1511
1702
  isPartialReadyKind,
1512
1703
  isProvisionalBlock,
1513
1704
  isRecordValue,
1705
+ itemChanges,
1706
+ itemRecordId,
1514
1707
  kindIsRoutable,
1515
1708
  kindServerDataFromStoredValue,
1516
1709
  markKindPartialUnsafe,
1710
+ provisionalDirectiveSlug,
1517
1711
  readIrRouteMarker,
1712
+ recordFallbackName,
1518
1713
  registerDirectiveRenderer,
1519
1714
  resetDirectiveRenderers,
1520
1715
  resetPartialUnsafeKinds,