@ai-matrx/content-ir-react 0.18.0 → 0.19.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.d.cts CHANGED
@@ -428,6 +428,15 @@ interface RecordValues {
428
428
  status: RecordValuesStatus;
429
429
  }
430
430
  type RecordReader = (ref: DirectiveRecordRef) => Promise<Record<string, unknown> | null>;
431
+ /** How many times this page has changed record `id` (0 = never). */
432
+ declare function recordRevision(id: string): number;
433
+ /**
434
+ * Record `id` just changed (an apply wrote it, or any other writer on the page).
435
+ * Every `useRecordValues` naming it reads it again.
436
+ */
437
+ declare function noteRecordChanged(id: string): void;
438
+ /** The live revision of record `id`, re-rendering when it changes. */
439
+ declare function useRecordRevision(id: string): number;
431
440
  declare function useRecordValues(read: RecordReader | undefined, ref: DirectiveRecordRef | null): RecordValues;
432
441
 
433
442
  /**
@@ -693,4 +702,4 @@ declare class DbKindComponentErrorBoundary extends react.Component<DbKindCompone
693
702
  render(): react.ReactNode;
694
703
  }
695
704
 
696
- export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, createDbKindComponentCache, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemRecordId, kindIsRoutable, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordValues };
705
+ export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, createDbKindComponentCache, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemRecordId, kindIsRoutable, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordRevision, useRecordValues };
package/dist/index.d.ts CHANGED
@@ -428,6 +428,15 @@ interface RecordValues {
428
428
  status: RecordValuesStatus;
429
429
  }
430
430
  type RecordReader = (ref: DirectiveRecordRef) => Promise<Record<string, unknown> | null>;
431
+ /** How many times this page has changed record `id` (0 = never). */
432
+ declare function recordRevision(id: string): number;
433
+ /**
434
+ * Record `id` just changed (an apply wrote it, or any other writer on the page).
435
+ * Every `useRecordValues` naming it reads it again.
436
+ */
437
+ declare function noteRecordChanged(id: string): void;
438
+ /** The live revision of record `id`, re-rendering when it changes. */
439
+ declare function useRecordRevision(id: string): number;
431
440
  declare function useRecordValues(read: RecordReader | undefined, ref: DirectiveRecordRef | null): RecordValues;
432
441
 
433
442
  /**
@@ -693,4 +702,4 @@ declare class DbKindComponentErrorBoundary extends react.Component<DbKindCompone
693
702
  render(): react.ReactNode;
694
703
  }
695
704
 
696
- export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, createDbKindComponentCache, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemRecordId, kindIsRoutable, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordValues };
705
+ export { ApplyDirectiveButton, type ApplyDirectiveButtonProps, CHANGE_VALUE_MAX, type ChangeValue, type CompiledDbKindComponent, ComponentResolution, ComponentResolutionSource, ContentIrErrorReporter, ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type DbKindActionResult, type DbKindCompileResult, type DbKindComponentCache, type DbKindComponentCachePorts, type DbKindComponentCompiler, DbKindComponentErrorBoundary, type DbKindComponentErrorBoundaryProps, type DbKindComponentIncident, type DbKindComponentIncidentSink, type DbKindComponentIncidentType, type DbKindComponentRenderProps, DelegatedOutput, type DelegatedOutputProps, type DirectiveApplyPhase, DirectiveChangeList, DirectiveFailure, DirectiveFailureWords, DirectiveFallbackCard, type DirectiveFallbackCardProps, DirectiveProvisionalCard, type DirectiveProvisionalCardProps, DirectiveRecordRef, DirectiveRender, type DirectiveRenderProps, type DirectiveRenderer, type DirectiveRendererProps, GenericStructuredView, type GenericStructuredViewProps, type ItemChange, type ItemChangesOptions, type KindComponentUiOptions, KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, KindRouteEnv, type KindVersionSources, NodeOutcomeView, type NodeOutcomeViewProps, ProvisionalKindBoundary, ProvisionalKindFrame, type RecordReader, type RecordValues, type RecordValuesStatus, type ResolveKindValue, type RunDbKindAction, RunResultView, type RunResultViewProps, SideEffectDirectiveCard, type SideEffectDirectiveCardProps, TARGETING_CLASSES, createDbKindComponentCache, defaultFailureWords, describeChangeValue, failureWords, fieldLabel, getDirectiveRenderer, isDbKindComponentBodyPending, isRecordValue, itemChanges, itemRecordId, kindIsRoutable, noteRecordChanged, provisionalDirectiveSlug, readsApplyLedger, recordFallbackName, recordRevision, registerDirectiveRenderer, resetDirectiveRenderers, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv, useRecordRevision, useRecordValues };
package/dist/index.js CHANGED
@@ -268,8 +268,8 @@ var ComponentResolver = class {
268
268
  }
269
269
  bumpKind(kind) {
270
270
  this.kindVersions.set(kind, (this.kindVersions.get(kind) ?? 0) + 1);
271
- const listeners = this.kindListeners.get(kind);
272
- if (listeners) for (const listener of listeners) listener();
271
+ const listeners2 = this.kindListeners.get(kind);
272
+ if (listeners2) for (const listener of listeners2) listener();
273
273
  }
274
274
  notifyChanged() {
275
275
  this.version += 1;
@@ -753,7 +753,7 @@ import { looksLikeDirectiveHead, tryDecodeDirectiveContent } from "@ai-matrx/con
753
753
  import { directiveDisplay } from "@ai-matrx/content-ir";
754
754
 
755
755
  // directives/ApplyDirectiveButton.tsx
756
- import { useEffect, useRef, useState } from "react";
756
+ import { useEffect as useEffect2, useRef, useState as useState2, useSyncExternalStore as useSyncExternalStore3 } from "react";
757
757
  import { nounLabel } from "@ai-matrx/content-ir";
758
758
 
759
759
  // directives/item-changes.ts
@@ -832,6 +832,64 @@ function itemChanges(item, current, options = {}) {
832
832
  return out;
833
833
  }
834
834
 
835
+ // directives/record-values.ts
836
+ import { useEffect, useState, useSyncExternalStore as useSyncExternalStore2 } from "react";
837
+ var revisions = /* @__PURE__ */ new Map();
838
+ var listeners = /* @__PURE__ */ new Set();
839
+ function recordRevision(id) {
840
+ return revisions.get(id) ?? 0;
841
+ }
842
+ function noteRecordChanged(id) {
843
+ if (!id) return;
844
+ revisions.set(id, recordRevision(id) + 1);
845
+ for (const listener of listeners) listener();
846
+ }
847
+ function subscribeRevisions(listener) {
848
+ listeners.add(listener);
849
+ return () => {
850
+ listeners.delete(listener);
851
+ };
852
+ }
853
+ function useRecordRevision(id) {
854
+ return useSyncExternalStore2(
855
+ subscribeRevisions,
856
+ () => recordRevision(id),
857
+ () => 0
858
+ );
859
+ }
860
+ function useRecordValues(read, ref) {
861
+ const revision = useRecordRevision(ref?.id ?? "");
862
+ const key = ref && read ? `${ref.noun}:${ref.id}#${revision}` : "";
863
+ const [result, setResult] = useState({
864
+ key: "",
865
+ values: null,
866
+ status: "idle"
867
+ });
868
+ useEffect(() => {
869
+ if (!key || !read) return;
870
+ const split = key.indexOf(":");
871
+ const target = {
872
+ noun: key.slice(0, split),
873
+ id: key.slice(split + 1, key.lastIndexOf("#"))
874
+ };
875
+ let live = true;
876
+ setResult({ key, values: null, status: "loading" });
877
+ read(target).then((values) => {
878
+ if (!live) return;
879
+ setResult({ key, values, status: values ? "ready" : "unavailable" });
880
+ }).catch(() => {
881
+ if (!live) return;
882
+ setResult({ key, values: null, status: "unavailable" });
883
+ });
884
+ return () => {
885
+ live = false;
886
+ };
887
+ }, [key, read]);
888
+ if (!key) return { values: null, status: "idle" };
889
+ if (result.key !== key) return { values: null, status: "loading" };
890
+ return { values: result.values, status: result.status };
891
+ }
892
+
835
893
  // directives/failure-words.ts
836
894
  var PAST = {
837
895
  create: "created",
@@ -951,6 +1009,41 @@ function classIcon(directiveClass, noun) {
951
1009
 
952
1010
  // directives/ApplyDirectiveButton.tsx
953
1011
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
1012
+ function announceChangedRecords(directive, items) {
1013
+ if (!TARGETING_CLASSES.has(directive.directiveClass)) return;
1014
+ for (const item of items) {
1015
+ const id = itemRecordId(item);
1016
+ if (id) noteRecordChanged(id);
1017
+ }
1018
+ }
1019
+ var applyOutcomes = /* @__PURE__ */ new WeakMap();
1020
+ var EMPTY_AUTHORITY = {};
1021
+ var outcomeListeners = /* @__PURE__ */ new Set();
1022
+ function outcomesOf(host) {
1023
+ let held = applyOutcomes.get(host);
1024
+ if (!held) {
1025
+ held = /* @__PURE__ */ new Map();
1026
+ applyOutcomes.set(host, held);
1027
+ }
1028
+ return held;
1029
+ }
1030
+ function publishOutcome(host, identity, outcome) {
1031
+ outcomesOf(host).set(identity, outcome);
1032
+ for (const listener of outcomeListeners) listener();
1033
+ }
1034
+ function subscribeOutcomes(listener) {
1035
+ outcomeListeners.add(listener);
1036
+ return () => {
1037
+ outcomeListeners.delete(listener);
1038
+ };
1039
+ }
1040
+ function useApplyOutcome(host, identity) {
1041
+ return useSyncExternalStore3(
1042
+ subscribeOutcomes,
1043
+ () => applyOutcomes.get(host)?.get(identity) ?? null,
1044
+ () => null
1045
+ );
1046
+ }
954
1047
  var FINISH_POLL_MS = 2e3;
955
1048
  var FINISH_POLLS_MAX = 30;
956
1049
  function readsApplyLedger(host, directive) {
@@ -970,27 +1063,29 @@ function ApplyDirectiveButton({
970
1063
  const items = directive.items;
971
1064
  const readsLedger = readsApplyLedger(host, directive);
972
1065
  const initial = readsLedger ? { status: "checking" } : { status: "idle" };
973
- const [state, setState] = useState(initial);
974
- const [elapsed, setElapsed] = useState(0);
975
- const [askingAgain, setAskingAgain] = useState(false);
1066
+ const [state, setState] = useState2(initial);
1067
+ const [elapsed, setElapsed] = useState2(0);
1068
+ const [askingAgain, setAskingAgain] = useState2(false);
976
1069
  const startedAt = useRef(null);
977
1070
  const identity = JSON.stringify([directive.slug, items, conversationId ?? null]);
978
- const [stateFor, setStateFor] = useState(identity);
1071
+ const [stateFor, setStateFor] = useState2(identity);
979
1072
  if (stateFor !== identity) {
980
1073
  setStateFor(identity);
981
1074
  setState(initial);
982
1075
  setAskingAgain(false);
983
1076
  setElapsed(0);
984
1077
  }
1078
+ const shared = useApplyOutcome(host.confirm ?? EMPTY_AUTHORITY, identity);
1079
+ const view = state.status === "asking" || !shared ? state : shared;
985
1080
  const currentIdentity = useRef(identity);
986
- useEffect(() => {
1081
+ useEffect2(() => {
987
1082
  currentIdentity.current = identity;
988
1083
  }, [identity]);
989
1084
  const nounText = nounLabel(directive.noun, host.nouns);
990
1085
  const shellKey = readsLedger ? JSON.stringify([directive.slug, items, conversationId ?? null]) : "";
991
1086
  const read = host.applyState;
992
1087
  const report = host.reportError;
993
- useEffect(() => {
1088
+ useEffect2(() => {
994
1089
  if (!shellKey || !read) return;
995
1090
  const [slug, shellItems, inConversation] = JSON.parse(shellKey);
996
1091
  const shell = { __kind: slug, items: shellItems };
@@ -1035,33 +1130,34 @@ function ApplyDirectiveButton({
1035
1130
  if (timer) clearTimeout(timer);
1036
1131
  };
1037
1132
  }, [shellKey, read, report]);
1038
- const appliedClean = state.status === "applied" && state.failed === 0 ? state : null;
1133
+ const appliedClean = view.status === "applied" && view.failed === 0 ? view : null;
1039
1134
  const appliedBefore = appliedClean ? appliedClean.before : null;
1040
- const phaseKey = state.status === "checking" || state.status === "finishing" ? "pending" : appliedClean ? `applied:${JSON.stringify(appliedBefore)}` : "open";
1041
- useEffect(() => {
1135
+ const phaseKey = view.status === "checking" || view.status === "finishing" ? "pending" : appliedClean ? `applied:${JSON.stringify(appliedBefore)}` : "open";
1136
+ useEffect2(() => {
1042
1137
  if (!onPhase) return;
1043
1138
  if (phaseKey === "pending") onPhase({ phase: "pending" });
1044
1139
  else if (phaseKey === "open") onPhase({ phase: "open" });
1045
1140
  else onPhase({ phase: "applied", before: appliedBefore });
1046
1141
  }, [phaseKey, onPhase, appliedBefore]);
1047
- useEffect(() => {
1048
- if (state.status !== "applying") return;
1049
- startedAt.current = Date.now();
1142
+ const applyingSince = view.status === "applying" ? view.startedAt : null;
1143
+ useEffect2(() => {
1144
+ if (applyingSince === null) return;
1145
+ startedAt.current = applyingSince;
1050
1146
  const id = setInterval(
1051
1147
  () => setElapsed(Math.round((Date.now() - (startedAt.current ?? 0)) / 1e3)),
1052
1148
  1e3
1053
1149
  );
1054
1150
  return () => clearInterval(id);
1055
- }, [state.status]);
1151
+ }, [applyingSince]);
1056
1152
  if (!directive.parsed.executes) return null;
1057
1153
  const confirm = host.confirm;
1058
1154
  if (!confirm) return null;
1059
1155
  async function handleApply(again = false) {
1060
1156
  if (!confirm) return;
1061
- const prior = state;
1157
+ const prior = view;
1062
1158
  const askedFor = identity;
1063
1159
  const stillHere = () => currentIdentity.current === askedFor;
1064
- const priorCopies = state.status === "applied" ? state.copies : 0;
1160
+ const priorCopies = view.status === "applied" ? view.copies : 0;
1065
1161
  if (host.ask) {
1066
1162
  if (again) setAskingAgain(true);
1067
1163
  else setState({ status: "asking" });
@@ -1090,14 +1186,20 @@ function ApplyDirectiveButton({
1090
1186
  }
1091
1187
  }
1092
1188
  setElapsed(0);
1093
- setState({ status: "applying" });
1189
+ setState((prev) => prev.status === "asking" ? { status: "idle" } : prev);
1190
+ publishOutcome(confirm, askedFor, { status: "applying", startedAt: Date.now() });
1094
1191
  try {
1095
1192
  const shell = { __kind: directive.slug, items };
1096
1193
  if (conversationId) shell.conversationId = conversationId;
1097
1194
  if (again) shell.force = true;
1098
- const result = await confirm(shell);
1099
- if (!stillHere()) return;
1100
- setState({
1195
+ let result;
1196
+ try {
1197
+ result = await confirm(shell);
1198
+ } finally {
1199
+ announceChangedRecords(directive, items);
1200
+ }
1201
+ for (const record of result.records ?? []) noteRecordChanged(record.id);
1202
+ publishOutcome(confirm, askedFor, {
1101
1203
  status: "applied",
1102
1204
  applied: result.applied,
1103
1205
  failed: result.failed,
@@ -1109,20 +1211,19 @@ function ApplyDirectiveButton({
1109
1211
  // apply replaced is still the change this block made.
1110
1212
  before: again && prior.status === "applied" && prior.before ? prior.before : result.before ?? null
1111
1213
  });
1112
- onApplied?.();
1214
+ if (stillHere()) onApplied?.();
1113
1215
  } catch (error) {
1114
- if (!stillHere()) return;
1115
- setState({
1216
+ publishOutcome(confirm, askedFor, {
1116
1217
  status: "error",
1117
1218
  message: error instanceof Error && error.message ? error.message : "That couldn't be applied just now. Please try again."
1118
1219
  });
1119
1220
  }
1120
1221
  }
1121
- if (state.status === "applied") {
1122
- const bad = state.failed > 0;
1222
+ if (view.status === "applied") {
1223
+ const bad = view.failed > 0;
1123
1224
  const trashed = directive.directiveClass === "delete";
1124
1225
  const label2 = nounText;
1125
- const records = host.renderRecord ? state.records : [];
1226
+ const records = host.renderRecord ? view.records : [];
1126
1227
  return /* @__PURE__ */ jsxs2(
1127
1228
  "span",
1128
1229
  {
@@ -1136,26 +1237,26 @@ function ApplyDirectiveButton({
1136
1237
  {
1137
1238
  words: failureWords(
1138
1239
  {
1139
- raw: state.message ?? `${state.failed} failed`,
1240
+ raw: view.message ?? `${view.failed} failed`,
1140
1241
  directiveClass: directive.directiveClass,
1141
1242
  noun: directive.noun,
1142
1243
  nounLabel: nounText,
1143
- failed: state.failed,
1144
- total: state.applied + state.failed
1244
+ failed: view.failed,
1245
+ total: view.applied + view.failed
1145
1246
  },
1146
1247
  host.explainFailure
1147
1248
  ),
1148
- raw: state.message
1249
+ raw: view.message
1149
1250
  }
1150
- ) : /* @__PURE__ */ jsx4("span", { className: "min-w-0", children: state.message ?? `Applied ${state.applied}` })
1251
+ ) : /* @__PURE__ */ jsx4("span", { className: "min-w-0", children: view.message ?? `Applied ${view.applied}` })
1151
1252
  ] }),
1152
- state.copies > 1 ? /* @__PURE__ */ jsx4(
1253
+ view.copies > 1 ? /* @__PURE__ */ jsx4(
1153
1254
  "span",
1154
1255
  {
1155
1256
  className: "shrink-0 text-muted-foreground",
1156
- "data-apply-copies": state.copies,
1257
+ "data-apply-copies": view.copies,
1157
1258
  title: records.length > 0 ? directive.directiveClass === "create" ? "Links to the latest copy." : "Links to the latest run." : void 0,
1158
- children: directive.directiveClass === "create" ? `${state.copies} copies` : `Ran ${state.copies} times`
1259
+ children: directive.directiveClass === "create" ? `${view.copies} copies` : `Ran ${view.copies} times`
1159
1260
  }
1160
1261
  ) : null,
1161
1262
  records.map((record) => /* @__PURE__ */ jsx4("span", { className: "inline-flex min-w-0 items-center", children: host.renderRecord?.({
@@ -1182,7 +1283,7 @@ function ApplyDirectiveButton({
1182
1283
  }
1183
1284
  );
1184
1285
  }
1185
- if (state.status === "checking") {
1286
+ if (view.status === "checking") {
1186
1287
  return /* @__PURE__ */ jsx4(
1187
1288
  "span",
1188
1289
  {
@@ -1194,7 +1295,7 @@ function ApplyDirectiveButton({
1194
1295
  }
1195
1296
  );
1196
1297
  }
1197
- if (state.status === "finishing") {
1298
+ if (view.status === "finishing") {
1198
1299
  return /* @__PURE__ */ jsxs2(
1199
1300
  "span",
1200
1301
  {
@@ -1209,7 +1310,7 @@ function ApplyDirectiveButton({
1209
1310
  );
1210
1311
  }
1211
1312
  const destructive = directive.directiveClass === "delete";
1212
- const muted = nothingToChange && state.status === "idle";
1313
+ const muted = nothingToChange && view.status === "idle";
1213
1314
  return /* @__PURE__ */ jsxs2("span", { className: "inline-flex items-center gap-2", children: [
1214
1315
  muted ? /* @__PURE__ */ jsx4("span", { className: "text-xs text-muted-foreground", "data-apply-nothing": "", children: "Nothing to change" }) : null,
1215
1316
  /* @__PURE__ */ jsxs2(
@@ -1217,17 +1318,17 @@ function ApplyDirectiveButton({
1217
1318
  {
1218
1319
  type: "button",
1219
1320
  onClick: () => void handleApply(),
1220
- disabled: state.status === "applying" || state.status === "asking" || items.length === 0,
1321
+ disabled: view.status === "applying" || view.status === "asking" || items.length === 0,
1221
1322
  "data-apply-tone": muted ? "muted" : destructive ? "destructive" : "default",
1222
1323
  title: muted ? "It sets no fields, so applying it changes nothing." : void 0,
1223
1324
  className: `inline-flex items-center gap-1 rounded-md border px-2 py-1 text-xs font-medium disabled:opacity-50 ${muted ? "border-border/60 bg-background text-muted-foreground hover:bg-accent" : destructive ? "border-destructive/50 bg-background text-destructive hover:bg-destructive/10" : "border-border bg-background hover:bg-accent"}`,
1224
1325
  children: [
1225
- 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" }),
1226
- state.status === "applying" ? `Applying${itemCount ? ` ${itemCount} ${itemCount === 1 ? "item" : "items"}` : ""}\u2026${elapsed ? ` ${elapsed}s` : ""}` : label
1326
+ view.status === "applying" ? /* @__PURE__ */ jsx4(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx4(PlayIcon, { className: "h-3.5 w-3.5" }),
1327
+ view.status === "applying" ? `Applying${itemCount ? ` ${itemCount} ${itemCount === 1 ? "item" : "items"}` : ""}\u2026${elapsed ? ` ${elapsed}s` : ""}` : label
1227
1328
  ]
1228
1329
  }
1229
1330
  ),
1230
- state.status === "error" ? /* @__PURE__ */ jsxs2(
1331
+ view.status === "error" ? /* @__PURE__ */ jsxs2(
1231
1332
  "span",
1232
1333
  {
1233
1334
  className: "inline-flex max-w-sm items-start gap-1 text-xs text-destructive",
@@ -1239,14 +1340,14 @@ function ApplyDirectiveButton({
1239
1340
  {
1240
1341
  words: failureWords(
1241
1342
  {
1242
- raw: state.message,
1343
+ raw: view.message,
1243
1344
  directiveClass: directive.directiveClass,
1244
1345
  noun: directive.noun,
1245
1346
  nounLabel: nounText
1246
1347
  },
1247
1348
  host.explainFailure
1248
1349
  ),
1249
- raw: state.message
1350
+ raw: view.message
1250
1351
  }
1251
1352
  )
1252
1353
  ]
@@ -1258,7 +1359,7 @@ function FailureNotice({
1258
1359
  words,
1259
1360
  raw
1260
1361
  }) {
1261
- const [open, setOpen] = useState(false);
1362
+ const [open, setOpen] = useState2(false);
1262
1363
  const detail = raw?.trim() ?? "";
1263
1364
  return /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 flex-col gap-0.5", "data-apply-failure": true, children: [
1264
1365
  /* @__PURE__ */ jsxs2("span", { className: "min-w-0", children: [
@@ -1387,39 +1488,6 @@ import {
1387
1488
  nounLabel as nounLabel2,
1388
1489
  nounTitleColumn
1389
1490
  } from "@ai-matrx/content-ir";
1390
-
1391
- // directives/record-values.ts
1392
- import { useEffect as useEffect2, useState as useState2 } from "react";
1393
- function useRecordValues(read, ref) {
1394
- const key = ref && read ? `${ref.noun}:${ref.id}` : "";
1395
- const [result, setResult] = useState2({
1396
- key: "",
1397
- values: null,
1398
- status: "idle"
1399
- });
1400
- useEffect2(() => {
1401
- if (!key || !read) return;
1402
- const split = key.indexOf(":");
1403
- const target = { noun: key.slice(0, split), id: key.slice(split + 1) };
1404
- let live = true;
1405
- setResult({ key, values: null, status: "loading" });
1406
- read(target).then((values) => {
1407
- if (!live) return;
1408
- setResult({ key, values, status: values ? "ready" : "unavailable" });
1409
- }).catch(() => {
1410
- if (!live) return;
1411
- setResult({ key, values: null, status: "unavailable" });
1412
- });
1413
- return () => {
1414
- live = false;
1415
- };
1416
- }, [key, read]);
1417
- if (!key) return { values: null, status: "idle" };
1418
- if (result.key !== key) return { values: null, status: "loading" };
1419
- return { values: result.values, status: result.status };
1420
- }
1421
-
1422
- // directives/SideEffectDirectiveCard.tsx
1423
1491
  import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1424
1492
  var ROWS_BEFORE_FOLD = 3;
1425
1493
  function ItemRow({
@@ -2107,10 +2175,12 @@ export {
2107
2175
  kindIsRoutable,
2108
2176
  kindServerDataFromStoredValue,
2109
2177
  markKindPartialUnsafe,
2178
+ noteRecordChanged,
2110
2179
  provisionalDirectiveSlug,
2111
2180
  readIrRouteMarker,
2112
2181
  readsApplyLedger,
2113
2182
  recordFallbackName,
2183
+ recordRevision,
2114
2184
  registerDirectiveRenderer,
2115
2185
  resetDirectiveRenderers,
2116
2186
  resetPartialUnsafeKinds,
@@ -2125,6 +2195,7 @@ export {
2125
2195
  useDirectiveHost,
2126
2196
  useDirectiveScope,
2127
2197
  useKindRouteEnv,
2198
+ useRecordRevision,
2128
2199
  useRecordValues
2129
2200
  };
2130
2201
  //# sourceMappingURL=index.js.map