@ai-matrx/content-ir-react 0.13.18 → 0.15.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
@@ -1,7 +1,7 @@
1
1
  import { C as ComponentResolutionSource, a as ComponentResolution, b as ContentIrErrorReporter } from './component-resolution.types-DLO2w-0n.cjs';
2
2
  export { c as ComponentRole, d as ContentIrErrorReport, J as JsonObject, K as KindComponentRow, S as SystemComponentEntry, e as consoleErrorReporter } from './component-resolution.types-DLO2w-0n.cjs';
3
- import { C as ContentIrHost, K as KindRouteEnv, a as KindDefinitionSource } from './route-DxK1SoPh.cjs';
4
- export { b as ContentIrRenderSeams, D as DB_KIND_COMPONENT_KEY, c as DIRECTIVE_BLOCK_TYPE, d as DirectiveApplyResult, e as DirectiveAskRequest, f as DirectiveCopyProps, g as DirectiveHost, h as DirectiveHostProvider, i as DirectiveHostProviderProps, j as DirectiveOpenItemOptions, k as DirectiveRecordProps, l as DirectiveRecordRef, G as GENERIC_STRUCTURED_COMPONENT_KEY, m as GenericFallbackReason, I as IR_PROVISIONAL_KEY, n as IR_ROUTE_KEY, o as IrRenderBlock, p as IrRoutableBlock, q as IrRouteMarker, r as KindRouteBinding, s as KindRouteOptions, P as PartialRenderOptions, t as ProvisionalKindRender, S as StructuredValueRenderProps, u as SupersededKindRender, v as applyIrKindRoute, w as createKindRouteBinding, x as envelopeFromPartialKind, y as isPartialReadyKind, z as isProvisionalBlock, A as kindServerDataFromStoredValue, B as markKindPartialUnsafe, E as readIrRouteMarker, F as resetPartialUnsafeKinds, H as resetSourcelessDbRowReports, J as resolveAnnouncedKindLoading, L as resolveProvisionalKindRender, M as resolveSupersededKindRender, N as routeEnvOf, O as useDirectiveHost } from './route-DxK1SoPh.cjs';
3
+ import { C as ContentIrHost, K as KindRouteEnv, a as KindDefinitionSource } from './route-BCtPhF7W.cjs';
4
+ export { b as ContentIrRenderSeams, D as DB_KIND_COMPONENT_KEY, c as DIRECTIVE_BLOCK_TYPE, d as DirectiveApplyResult, e as DirectiveApplyState, f as DirectiveAskRequest, g as DirectiveCopyProps, h as DirectiveHost, i as DirectiveHostProvider, j as DirectiveHostProviderProps, k as DirectiveOpenItemOptions, l as DirectiveRecordProps, m as DirectiveRecordRef, n as DirectiveScope, o as DirectiveScopeProvider, p as DirectiveShell, G as GENERIC_STRUCTURED_COMPONENT_KEY, q as GenericFallbackReason, I as IR_PROVISIONAL_KEY, r as IR_ROUTE_KEY, s as IrRenderBlock, t as IrRoutableBlock, u as IrRouteMarker, v as KindRouteBinding, w as KindRouteOptions, P as PartialRenderOptions, x as ProvisionalKindRender, S as StructuredValueRenderProps, y as SupersededKindRender, z as applyIrKindRoute, A as createKindRouteBinding, B as envelopeFromPartialKind, E as isPartialReadyKind, F as isProvisionalBlock, H as kindServerDataFromStoredValue, J as markKindPartialUnsafe, L as readIrRouteMarker, M as resetPartialUnsafeKinds, N as resetSourcelessDbRowReports, O as resolveAnnouncedKindLoading, Q as resolveProvisionalKindRender, R as resolveSupersededKindRender, T as routeEnvOf, U as useDirectiveHost, V as useDirectiveScope } from './route-BCtPhF7W.cjs';
5
5
  import * as react from 'react';
6
6
  import react__default, { ReactNode, ComponentType } from 'react';
7
7
  export { ComponentResolver, ComponentResolverOptions } from './resolver.cjs';
@@ -292,8 +292,15 @@ interface DirectiveRenderProps {
292
292
  * OFF rather than "writing…" forever. Omitted = it may still be arriving.
293
293
  */
294
294
  streaming?: boolean;
295
+ /**
296
+ * The conversation this directive renders in (a chat message). Applies and
297
+ * ledger reads key on it — the same namespace an agent proposal's Approve
298
+ * uses — so one action can never apply twice through two doors. Omit in a
299
+ * person's own content. Overrides any enclosing `DirectiveScopeProvider`.
300
+ */
301
+ conversationId?: string | null;
295
302
  }
296
- declare function DirectiveRender({ content, className, streaming }: DirectiveRenderProps): react.JSX.Element;
303
+ declare function DirectiveRender({ conversationId, ...props }: DirectiveRenderProps): react.JSX.Element;
297
304
 
298
305
  /**
299
306
  * WHAT A DIRECTIVE ITEM WILL DO TO AN EXISTING RECORD — for the card, the
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { C as ComponentResolutionSource, a as ComponentResolution, b as ContentIrErrorReporter } from './component-resolution.types-DLO2w-0n.js';
2
2
  export { c as ComponentRole, d as ContentIrErrorReport, J as JsonObject, K as KindComponentRow, S as SystemComponentEntry, e as consoleErrorReporter } from './component-resolution.types-DLO2w-0n.js';
3
- import { C as ContentIrHost, K as KindRouteEnv, a as KindDefinitionSource } from './route-JGZfl2nL.js';
4
- export { b as ContentIrRenderSeams, D as DB_KIND_COMPONENT_KEY, c as DIRECTIVE_BLOCK_TYPE, d as DirectiveApplyResult, e as DirectiveAskRequest, f as DirectiveCopyProps, g as DirectiveHost, h as DirectiveHostProvider, i as DirectiveHostProviderProps, j as DirectiveOpenItemOptions, k as DirectiveRecordProps, l as DirectiveRecordRef, G as GENERIC_STRUCTURED_COMPONENT_KEY, m as GenericFallbackReason, I as IR_PROVISIONAL_KEY, n as IR_ROUTE_KEY, o as IrRenderBlock, p as IrRoutableBlock, q as IrRouteMarker, r as KindRouteBinding, s as KindRouteOptions, P as PartialRenderOptions, t as ProvisionalKindRender, S as StructuredValueRenderProps, u as SupersededKindRender, v as applyIrKindRoute, w as createKindRouteBinding, x as envelopeFromPartialKind, y as isPartialReadyKind, z as isProvisionalBlock, A as kindServerDataFromStoredValue, B as markKindPartialUnsafe, E as readIrRouteMarker, F as resetPartialUnsafeKinds, H as resetSourcelessDbRowReports, J as resolveAnnouncedKindLoading, L as resolveProvisionalKindRender, M as resolveSupersededKindRender, N as routeEnvOf, O as useDirectiveHost } from './route-JGZfl2nL.js';
3
+ import { C as ContentIrHost, K as KindRouteEnv, a as KindDefinitionSource } from './route-DDbgc-ID.js';
4
+ export { b as ContentIrRenderSeams, D as DB_KIND_COMPONENT_KEY, c as DIRECTIVE_BLOCK_TYPE, d as DirectiveApplyResult, e as DirectiveApplyState, f as DirectiveAskRequest, g as DirectiveCopyProps, h as DirectiveHost, i as DirectiveHostProvider, j as DirectiveHostProviderProps, k as DirectiveOpenItemOptions, l as DirectiveRecordProps, m as DirectiveRecordRef, n as DirectiveScope, o as DirectiveScopeProvider, p as DirectiveShell, G as GENERIC_STRUCTURED_COMPONENT_KEY, q as GenericFallbackReason, I as IR_PROVISIONAL_KEY, r as IR_ROUTE_KEY, s as IrRenderBlock, t as IrRoutableBlock, u as IrRouteMarker, v as KindRouteBinding, w as KindRouteOptions, P as PartialRenderOptions, x as ProvisionalKindRender, S as StructuredValueRenderProps, y as SupersededKindRender, z as applyIrKindRoute, A as createKindRouteBinding, B as envelopeFromPartialKind, E as isPartialReadyKind, F as isProvisionalBlock, H as kindServerDataFromStoredValue, J as markKindPartialUnsafe, L as readIrRouteMarker, M as resetPartialUnsafeKinds, N as resetSourcelessDbRowReports, O as resolveAnnouncedKindLoading, Q as resolveProvisionalKindRender, R as resolveSupersededKindRender, T as routeEnvOf, U as useDirectiveHost, V as useDirectiveScope } from './route-DDbgc-ID.js';
5
5
  import * as react from 'react';
6
6
  import react__default, { ReactNode, ComponentType } from 'react';
7
7
  export { ComponentResolver, ComponentResolverOptions } from './resolver.js';
@@ -292,8 +292,15 @@ interface DirectiveRenderProps {
292
292
  * OFF rather than "writing…" forever. Omitted = it may still be arriving.
293
293
  */
294
294
  streaming?: boolean;
295
+ /**
296
+ * The conversation this directive renders in (a chat message). Applies and
297
+ * ledger reads key on it — the same namespace an agent proposal's Approve
298
+ * uses — so one action can never apply twice through two doors. Omit in a
299
+ * person's own content. Overrides any enclosing `DirectiveScopeProvider`.
300
+ */
301
+ conversationId?: string | null;
295
302
  }
296
- declare function DirectiveRender({ content, className, streaming }: DirectiveRenderProps): react.JSX.Element;
303
+ declare function DirectiveRender({ conversationId, ...props }: DirectiveRenderProps): react.JSX.Element;
297
304
 
298
305
  /**
299
306
  * WHAT A DIRECTIVE ITEM WILL DO TO AN EXISTING RECORD — for the card, the
package/dist/index.js CHANGED
@@ -20,6 +20,16 @@ import { createContext as createContext2, useContext as useContext2, useMemo } f
20
20
  import { createContext, useContext } from "react";
21
21
  import { jsx } from "react/jsx-runtime";
22
22
  var DirectiveHostContext = createContext(null);
23
+ var DirectiveScopeContext = createContext({});
24
+ function DirectiveScopeProvider({
25
+ conversationId,
26
+ children
27
+ }) {
28
+ return /* @__PURE__ */ jsx(DirectiveScopeContext.Provider, { value: { conversationId: conversationId ?? null }, children });
29
+ }
30
+ function useDirectiveScope() {
31
+ return useContext(DirectiveScopeContext);
32
+ }
23
33
  function DirectiveHostProvider({ host, children }) {
24
34
  return /* @__PURE__ */ jsx(DirectiveHostContext.Provider, { value: host, children });
25
35
  }
@@ -867,6 +877,10 @@ var MaximizeIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
867
877
  /* @__PURE__ */ jsx3("line", { x1: "3", x2: "10", y1: "21", y2: "14" })
868
878
  ] });
869
879
  var LoaderIcon = (p) => /* @__PURE__ */ jsx3(Svg, { ...p, children: /* @__PURE__ */ jsx3("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
880
+ var RotateCcwIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
881
+ /* @__PURE__ */ jsx3("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
882
+ /* @__PURE__ */ jsx3("path", { d: "M3 3v5h5" })
883
+ ] });
870
884
  var CheckCircleIcon = (p) => /* @__PURE__ */ jsxs(Svg, { ...p, children: [
871
885
  /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10" }),
872
886
  /* @__PURE__ */ jsx3("path", { d: "m9 12 2 2 4-4" })
@@ -893,6 +907,8 @@ function classIcon(directiveClass, noun) {
893
907
 
894
908
  // directives/ApplyDirectiveButton.tsx
895
909
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
910
+ var FINISH_POLL_MS = 2e3;
911
+ var FINISH_POLLS_MAX = 30;
896
912
  function ApplyDirectiveButton({
897
913
  directive,
898
914
  label = "Apply",
@@ -900,9 +916,62 @@ function ApplyDirectiveButton({
900
916
  onApplied
901
917
  }) {
902
918
  const host = useDirectiveHost();
903
- const [state, setState] = useState({ status: "idle" });
919
+ const scope = useDirectiveScope();
920
+ const conversationId = scope.conversationId || void 0;
921
+ const items = directive.items;
922
+ const readsLedger = !!host.applyState && !!host.confirm && directive.parsed.executes && items.length > 0;
923
+ const [state, setState] = useState(
924
+ readsLedger ? { status: "checking" } : { status: "idle" }
925
+ );
904
926
  const [elapsed, setElapsed] = useState(0);
905
927
  const startedAt = useRef(null);
928
+ const nounText = nounLabel(directive.noun, host.nouns);
929
+ const shellKey = readsLedger ? JSON.stringify([directive.slug, items, conversationId ?? null]) : "";
930
+ const read = host.applyState;
931
+ const report = host.reportError;
932
+ useEffect(() => {
933
+ if (!shellKey || !read) return;
934
+ const [slug, shellItems, inConversation] = JSON.parse(shellKey);
935
+ const shell = { __kind: slug, items: shellItems };
936
+ if (inConversation) shell.conversationId = inConversation;
937
+ let live = true;
938
+ let polls = 0;
939
+ let timer = null;
940
+ const ask = () => {
941
+ read(shell).then((answer) => {
942
+ if (!live) return;
943
+ if (answer.state === "applied") {
944
+ setState(
945
+ (prev) => prev.status === "checking" || prev.status === "finishing" ? {
946
+ status: "applied",
947
+ applied: shellItems.length,
948
+ failed: 0,
949
+ message: answer.message?.trim() ? answer.message.trim() : null,
950
+ records: answer.records ?? []
951
+ } : prev
952
+ );
953
+ } else if (answer.state === "in_flight" && polls < FINISH_POLLS_MAX) {
954
+ polls += 1;
955
+ setState((prev) => prev.status === "checking" || prev.status === "finishing" ? { status: "finishing" } : prev);
956
+ timer = setTimeout(ask, FINISH_POLL_MS);
957
+ } else {
958
+ setState((prev) => prev.status === "checking" || prev.status === "finishing" ? { status: "idle" } : prev);
959
+ }
960
+ }).catch((error) => {
961
+ if (!live) return;
962
+ const why = error instanceof Error && error.message ? error.message : String(error);
963
+ (report ?? console.error)(
964
+ `[kind-directives] Could not read whether ${slug} was already applied: ${why}`
965
+ );
966
+ setState((prev) => prev.status === "checking" || prev.status === "finishing" ? { status: "idle" } : prev);
967
+ });
968
+ };
969
+ ask();
970
+ return () => {
971
+ live = false;
972
+ if (timer) clearTimeout(timer);
973
+ };
974
+ }, [shellKey, read, report]);
906
975
  useEffect(() => {
907
976
  if (state.status !== "applying") return;
908
977
  startedAt.current = Date.now();
@@ -915,9 +984,9 @@ function ApplyDirectiveButton({
915
984
  if (!directive.parsed.executes) return null;
916
985
  const confirm = host.confirm;
917
986
  if (!confirm) return null;
918
- const items = directive.items;
919
- async function handleApply() {
987
+ async function handleApply(again = false) {
920
988
  if (!confirm) return;
989
+ const before = state;
921
990
  if (host.ask) {
922
991
  setState({ status: "asking" });
923
992
  let ok = false;
@@ -925,7 +994,8 @@ function ApplyDirectiveButton({
925
994
  ok = await host.ask({
926
995
  directive,
927
996
  items,
928
- nounLabel: nounLabel(directive.noun, host.nouns)
997
+ nounLabel: nounText,
998
+ ...again ? { again: true } : {}
929
999
  });
930
1000
  } catch (error) {
931
1001
  setState({
@@ -935,14 +1005,17 @@ function ApplyDirectiveButton({
935
1005
  return;
936
1006
  }
937
1007
  if (!ok) {
938
- setState({ status: "idle" });
1008
+ setState(again ? before : { status: "idle" });
939
1009
  return;
940
1010
  }
941
1011
  }
942
1012
  setElapsed(0);
943
1013
  setState({ status: "applying" });
944
1014
  try {
945
- const result = await confirm({ __kind: directive.slug, items });
1015
+ const shell = { __kind: directive.slug, items };
1016
+ if (conversationId) shell.conversationId = conversationId;
1017
+ if (again) shell.force = true;
1018
+ const result = await confirm(shell);
946
1019
  setState({
947
1020
  status: "applied",
948
1021
  applied: result.applied,
@@ -961,7 +1034,7 @@ function ApplyDirectiveButton({
961
1034
  if (state.status === "applied") {
962
1035
  const bad = state.failed > 0;
963
1036
  const trashed = directive.directiveClass === "delete";
964
- const label2 = nounLabel(directive.noun, host.nouns);
1037
+ const label2 = nounText;
965
1038
  const records = host.renderRecord ? state.records : [];
966
1039
  return /* @__PURE__ */ jsxs2(
967
1040
  "span",
@@ -979,7 +1052,46 @@ function ApplyDirectiveButton({
979
1052
  fallback: recordFallbackName(label2, record.id),
980
1053
  context: "applied",
981
1054
  trashed
982
- }) }, `${record.noun}:${record.id}`))
1055
+ }) }, `${record.noun}:${record.id}`)),
1056
+ /* @__PURE__ */ jsxs2(
1057
+ "button",
1058
+ {
1059
+ type: "button",
1060
+ onClick: () => void handleApply(!bad),
1061
+ className: "inline-flex items-center gap-1 rounded px-1 py-0.5 text-muted-foreground hover:bg-accent hover:text-accent-foreground",
1062
+ "data-apply-action": bad ? "retry" : "run-again",
1063
+ children: [
1064
+ /* @__PURE__ */ jsx4(RotateCcwIcon, { className: "h-3 w-3" }),
1065
+ bad ? "Retry" : "Run again"
1066
+ ]
1067
+ }
1068
+ )
1069
+ ]
1070
+ }
1071
+ );
1072
+ }
1073
+ if (state.status === "checking") {
1074
+ return /* @__PURE__ */ jsx4(
1075
+ "span",
1076
+ {
1077
+ className: "inline-flex h-6 w-6 items-center justify-center text-muted-foreground",
1078
+ role: "status",
1079
+ "aria-label": "Checking whether this already ran",
1080
+ "data-apply-state": "checking",
1081
+ children: /* @__PURE__ */ jsx4(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" })
1082
+ }
1083
+ );
1084
+ }
1085
+ if (state.status === "finishing") {
1086
+ return /* @__PURE__ */ jsxs2(
1087
+ "span",
1088
+ {
1089
+ className: "inline-flex items-center gap-1 text-xs text-muted-foreground",
1090
+ role: "status",
1091
+ "data-apply-state": "finishing",
1092
+ children: [
1093
+ /* @__PURE__ */ jsx4(LoaderIcon, { className: "h-3.5 w-3.5 animate-spin" }),
1094
+ "Finishing\u2026"
983
1095
  ]
984
1096
  }
985
1097
  );
@@ -1245,7 +1357,11 @@ function isWholeJson(content) {
1245
1357
  return false;
1246
1358
  }
1247
1359
  }
1248
- function DirectiveRender({ content, className, streaming }) {
1360
+ function DirectiveRender({ conversationId, ...props }) {
1361
+ if (conversationId === void 0) return /* @__PURE__ */ jsx8(DirectiveRenderInner, { ...props });
1362
+ return /* @__PURE__ */ jsx8(DirectiveScopeProvider, { conversationId, children: /* @__PURE__ */ jsx8(DirectiveRenderInner, { ...props }) });
1363
+ }
1364
+ function DirectiveRenderInner({ content, className, streaming }) {
1249
1365
  const host = useDirectiveHost();
1250
1366
  const directive = tryDecodeDirectiveContent(content, (message) => {
1251
1367
  const line = `[kind-directives] ${message}`;
@@ -1709,6 +1825,7 @@ export {
1709
1825
  DirectiveHostProvider,
1710
1826
  DirectiveProvisionalCard,
1711
1827
  DirectiveRender,
1828
+ DirectiveScopeProvider,
1712
1829
  GENERIC_STRUCTURED_COMPONENT_KEY,
1713
1830
  GenericStructuredView,
1714
1831
  IR_PROVISIONAL_KEY,
@@ -1751,6 +1868,7 @@ export {
1751
1868
  useContentIrHostOrNull,
1752
1869
  useContentIrKindVersion,
1753
1870
  useDirectiveHost,
1871
+ useDirectiveScope,
1754
1872
  useKindRouteEnv
1755
1873
  };
1756
1874
  //# sourceMappingURL=index.js.map