@sanity/assist 4.1.0 → 4.3.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.esm.js CHANGED
@@ -1,16 +1,16 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { pathToString, isVersionId, getVersionFromId, getPublishedId, useEditState, useCurrentUser, useClient, typed, isObjectSchemaType, stringToPath, isKeySegment, isArraySchemaType, useSchema, FormFieldHeaderText, PatchEvent, unset, getVersionId, getDraftId, useColorSchemeValue, useFormCallbacks, useDocumentStore, useDocumentPresence, createPatchChannel, FormBuilder, fromMutationPatches, StatusButton, PresenceOverlay, VirtualizerScrollInstanceProvider, isDocumentSchemaType, useSyncState, set, FormCallbacksProvider, FormInput, setIfMissing, insert, ObjectInputMember, isArrayOfObjectsSchemaType, defineType, defineField, defineArrayMember, definePlugin } from "sanity";
3
- import { useToast, useLayer, Dialog, Flex, Tooltip, Text, Stack, TextArea, Button, Badge, Popover, Card, Box, ErrorBoundary, focusFirstDescendant, Spinner, Container, Autocomplete, Breadcrumbs, useClickOutside, useGlobalKeyDown, useTheme, rgba, Checkbox, Radio, ThemeProvider, MenuButton, Menu, MenuItem, Switch, Label } from "@sanity/ui";
2
+ import { pathToString, getVersionFromId, getPublishedId, isVersionId, useEditState, useCurrentUser, useClient, typed, isObjectSchemaType, stringToPath, isKeySegment, isArraySchemaType, useSchema, FormFieldHeaderText, PatchEvent, unset, getVersionId, getDraftId, useColorSchemeValue, useFormCallbacks, useDocumentStore, useDocumentPresence, createPatchChannel, FormBuilder, fromMutationPatches, StatusButton, PresenceOverlay, VirtualizerScrollInstanceProvider, isDocumentSchemaType, useSyncState, set, useWorkspaceSchemaId, FormCallbacksProvider, FormInput, setIfMissing, insert, ObjectInputMember, isArrayOfObjectsSchemaType, defineType, defineField, defineArrayMember, definePlugin } from "sanity";
3
+ import { useToast, useLayer, Dialog, Stack, Flex, Tooltip, Text, TextArea, Button, Badge, Popover, Card, Box, ErrorBoundary, focusFirstDescendant, Spinner, Container, Autocomplete, Breadcrumbs, useClickOutside, useGlobalKeyDown, useTheme, rgba, Radio, Checkbox, ThemeProvider, MenuButton, Menu, MenuItem, Switch, Label } from "@sanity/ui";
4
4
  import { useRef, useState, useEffect, useMemo, createContext, useContext, useCallback, useId, forwardRef, createElement, useReducer } from "react";
5
5
  import { useDocumentPane, usePaneRouter, DocumentInspectorHeader, DocumentPaneProvider } from "sanity/structure";
6
6
  import { minutesToMilliseconds, isAfter, addSeconds, formatDistanceToNow } from "date-fns";
7
- import { DocumentIcon, LinkIcon, ImageIcon, BlockContentIcon, OlistIcon, BlockquoteIcon, StringIcon, PlayIcon, SparklesIcon, ArrowRightIcon, CheckmarkIcon, SearchIcon, SyncIcon, ErrorOutlineIcon, CheckmarkCircleIcon, CloseCircleIcon, ClockIcon, RetryIcon, CloseIcon, icons, TranslateIcon, LockIcon, ControlsIcon, ArrowLeftIcon, TokenIcon, DocumentTextIcon, ThListIcon, CodeIcon, ComposeIcon } from "@sanity/icons";
7
+ import { DocumentIcon, LinkIcon, ImageIcon, BlockContentIcon, OlistIcon, BlockquoteIcon, StringIcon, PlayIcon, SparklesIcon, ArrowRightIcon, CheckmarkIcon, SearchIcon, SyncIcon, ErrorOutlineIcon, CheckmarkCircleIcon, ClockIcon, CloseCircleIcon, RetryIcon, CloseIcon, icons, TranslateIcon, LockIcon, ControlsIcon, ArrowLeftIcon, TokenIcon, DocumentTextIcon, ThListIcon, CodeIcon, ComposeIcon } from "@sanity/icons";
8
8
  import { extractWithPath } from "@sanity/mutator";
9
9
  import { keyframes, styled } from "styled-components";
10
10
  import { tap, mergeMap, share, take, filter, distinctUntilChanged, catchError } from "rxjs/operators";
11
11
  import { get } from "lodash-es";
12
12
  import isEqual from "react-fast-compare";
13
- import { throwError, of, partition, merge, switchMap, delay, defer } from "rxjs";
13
+ import { defer, throwError, of, partition, merge, switchMap, delay } from "rxjs";
14
14
  import { exhaustMapToWithTrailing } from "rxjs-exhaustmap-with-trailing";
15
15
  function hasOverflowScroll(el) {
16
16
  const overflow = getComputedStyle(el).overflow;
@@ -221,7 +221,16 @@ function isImage(schemaType) {
221
221
  return isType(schemaType, "image");
222
222
  }
223
223
  function getDescriptionFieldOption(schemaType) {
224
- return schemaType ? schemaType.options?.aiAssist?.imageDescriptionField || getDescriptionFieldOption(schemaType.type) : void 0;
224
+ if (!schemaType)
225
+ return;
226
+ const descriptionField = schemaType.options?.aiAssist?.imageDescriptionField;
227
+ return typeof descriptionField == "string" ? {
228
+ path: descriptionField,
229
+ updateOnImageChange: !0
230
+ } : descriptionField ? {
231
+ path: descriptionField.path,
232
+ updateOnImageChange: descriptionField.updateOnImageChange ?? !0
233
+ } : getDescriptionFieldOption(schemaType.type);
225
234
  }
226
235
  function getImageInstructionFieldOption(schemaType) {
227
236
  return schemaType ? schemaType.options?.aiAssist?.imageInstructionField || getImageInstructionFieldOption(schemaType.type) : void 0;
@@ -415,10 +424,10 @@ function getFieldRefs(schemaType, parent, depth = 0) {
415
424
  }
416
425
  function getSyntheticFields(schemaType, parent, depth = 0) {
417
426
  return depth >= maxDepth ? [] : schemaType.of.filter((itemType) => !isType(itemType, "block")).flatMap((itemType) => {
418
- const segment = { _key: itemType.name }, title = itemType.title ?? itemType.name, path = [...parent.path, segment], fieldRef = {
427
+ const segment = { _key: itemType.name }, title = itemType.title ?? itemType.name, path = parent ? [...parent.path, segment] : [segment], fieldRef = {
419
428
  key: patchableKey(pathToString(path)),
420
429
  path,
421
- title: [parent.title, title].join(" / "),
430
+ title: parent ? [parent.title, title].join(" / ") : title,
422
431
  schemaType: itemType,
423
432
  icon: getTypeIcon(itemType),
424
433
  synthetic: !0
@@ -599,7 +608,6 @@ function serializeInlineOf(blockSchemaType, schema, options2) {
599
608
  if (!(!childrenType || !isArraySchemaType(childrenType)))
600
609
  return arrayOf(
601
610
  {
602
- ...childrenType,
603
611
  of: childrenType.of.filter((t) => !isType(t, "span"))
604
612
  },
605
613
  schema,
@@ -823,6 +831,8 @@ function useRunInstructionApi(apiClient) {
823
831
  const NO_INPUT = {}, RunInstructionContext = createContext({
824
832
  runInstruction: () => {
825
833
  },
834
+ getUserInput: async () => {
835
+ },
826
836
  instructionLoading: !1
827
837
  });
828
838
  function useRunInstruction() {
@@ -832,7 +842,18 @@ function isUserInputBlock(block) {
832
842
  return block._type === userInputTypeName;
833
843
  }
834
844
  function RunInstructionProvider(props) {
835
- const { config } = useAiAssistanceConfig(), apiClient = useApiClient(config?.__customApiClient), { runInstruction: runInstructionRequest, loading } = useRunInstructionApi(apiClient), id = useId(), [inputs, setInputs] = useState(NO_INPUT), [runRequest, setRunRequest] = useState(), runInstruction = useCallback(
845
+ const { config } = useAiAssistanceConfig(), apiClient = useApiClient(config?.__customApiClient), { runInstruction: runInstructionRequest, loading } = useRunInstructionApi(apiClient), id = useId(), [inputs, setInputs] = useState(NO_INPUT), [runRequest, setRunRequest] = useState(), [resolveUserInput, setResolveUserInput] = useState(), getUserInput = useCallback(async ({ title, inputs: inputs2 }) => {
846
+ const userInputBlocks = inputs2.map((input, i) => ({
847
+ _type: userInputTypeName,
848
+ _key: input.id ?? `${i}`,
849
+ message: input.title,
850
+ description: input.description
851
+ }));
852
+ if (userInputBlocks.length)
853
+ return setRunRequest({ dialogTitle: title, userInputBlocks }), new Promise((resolve) => {
854
+ setResolveUserInput(() => resolve);
855
+ });
856
+ }, []), runInstruction = useCallback(
836
857
  (req) => {
837
858
  if (loading)
838
859
  return;
@@ -854,21 +875,35 @@ function RunInstructionProvider(props) {
854
875
  },
855
876
  [runInstructionRequest, loading]
856
877
  ), close = useCallback(() => {
857
- setRunRequest(void 0), setInputs(NO_INPUT);
858
- }, []), runWithInput = useCallback(() => {
859
- if (runRequest) {
860
- const { instruction: instruction2, userTexts, ...request } = runRequest;
861
- runInstructionRequest({
862
- ...request,
863
- instructionKey: instruction2._key,
864
- userTexts: Object.entries(inputs).map(([key, value]) => ({
865
- blockKey: key,
866
- userInput: value
867
- }))
868
- });
869
- }
878
+ setRunRequest(void 0), setInputs(NO_INPUT), resolveUserInput && resolveUserInput(void 0), setResolveUserInput(void 0);
879
+ }, [resolveUserInput]), runWithInput = useCallback(() => {
880
+ if (runRequest)
881
+ if ("instruction" in runRequest) {
882
+ const { instruction: instruction2, userTexts, ...request } = runRequest;
883
+ runInstructionRequest({
884
+ ...request,
885
+ instructionKey: instruction2._key,
886
+ userTexts: Object.entries(inputs).map(([key, value]) => ({
887
+ blockKey: key,
888
+ userInput: value
889
+ }))
890
+ });
891
+ } else {
892
+ const userInputs = Object.values(inputs).map((input, i) => {
893
+ const userInputBlock = runRequest.userInputBlocks[i];
894
+ return {
895
+ input: {
896
+ id: userInputBlock._key,
897
+ title: userInputBlock.message ?? "",
898
+ description: userInputBlock.description
899
+ },
900
+ result: input
901
+ };
902
+ });
903
+ resolveUserInput?.(userInputs), setResolveUserInput(void 0);
904
+ }
870
905
  close();
871
- }, [close, runInstructionRequest, runRequest, inputs]), open = !!runRequest, runDisabled = useMemo(
906
+ }, [close, runInstructionRequest, runRequest, inputs, resolveUserInput]), open = !!runRequest, runDisabled = useMemo(
872
907
  () => (runRequest?.userInputBlocks?.length ?? 0) > Object.entries(inputs).filter(([, value]) => !!value).length,
873
908
  [runRequest?.userInputBlocks, inputs]
874
909
  ), runButton = /* @__PURE__ */ jsx(
@@ -882,7 +917,7 @@ function RunInstructionProvider(props) {
882
917
  disabled: runDisabled
883
918
  }
884
919
  ), contextValue = useMemo(
885
- () => ({ runInstruction, instructionLoading: loading }),
920
+ () => ({ runInstruction, getUserInput, instructionLoading: loading }),
886
921
  [runInstruction, loading]
887
922
  );
888
923
  return /* @__PURE__ */ jsxs(RunInstructionContext.Provider, { value: contextValue, children: [
@@ -893,7 +928,7 @@ function RunInstructionProvider(props) {
893
928
  open,
894
929
  onClose: close,
895
930
  width: 1,
896
- header: getInstructionTitle(runRequest?.instruction),
931
+ header: "dialogTitle" in runRequest ? runRequest.dialogTitle : getInstructionTitle(runRequest?.instruction),
897
932
  footer: /* @__PURE__ */ jsx(Flex, { justify: "space-between", padding: 2, flex: 1, children: runDisabled ? /* @__PURE__ */ jsx(
898
933
  Tooltip,
899
934
  {
@@ -991,7 +1026,7 @@ function useAssistDocumentContextValue(documentId, documentType) {
991
1026
  } = useDocumentPane(), { draft, published, version } = editState || {}, assistableDocumentId = selectedReleaseId ? getVersionId(documentId, selectedReleaseId) : documentSchemaType.liveEdit ? documentId : getDraftId(documentId), documentIsNew = selectedReleaseId ? !version?._id : !draft?._id && !published?._id, documentIsAssistable = selectedReleaseId ? !!version : isDocAssistable(documentSchemaType, published, draft), { params } = useAiPaneRouter(), selectedPath = params[fieldPathParam], assistDocument = useStudioAssistDocument({
992
1027
  documentId: assistableDocumentId,
993
1028
  schemaType: documentSchemaType
994
- });
1029
+ }), { syntheticTasks, addSyntheticTask, removeSyntheticTask } = useSyntheticTasks(assistableDocumentId);
995
1030
  return useMemo(() => {
996
1031
  const base = {
997
1032
  assistableDocumentId,
@@ -1002,7 +1037,10 @@ function useAssistDocumentContextValue(documentId, documentType) {
1002
1037
  closeInspector,
1003
1038
  inspector,
1004
1039
  documentOnChange,
1005
- selectedPath
1040
+ selectedPath,
1041
+ syntheticTasks,
1042
+ addSyntheticTask,
1043
+ removeSyntheticTask
1006
1044
  };
1007
1045
  return assistDocument ? {
1008
1046
  ...base,
@@ -1019,9 +1057,26 @@ function useAssistDocumentContextValue(documentId, documentType) {
1019
1057
  closeInspector,
1020
1058
  inspector,
1021
1059
  documentOnChange,
1022
- selectedPath
1060
+ selectedPath,
1061
+ syntheticTasks,
1062
+ addSyntheticTask,
1063
+ removeSyntheticTask
1023
1064
  ]);
1024
1065
  }
1066
+ function useSyntheticTasks(assistableDocumentId) {
1067
+ const [syntheticTasks, setSyntheticTasks] = useState(() => []), addSyntheticTask = useCallback((task) => {
1068
+ setSyntheticTasks((current) => [...current, task]);
1069
+ }, []), removeSyntheticTask = useCallback((task) => {
1070
+ setSyntheticTasks((current) => current.filter((t) => task._key !== t._key));
1071
+ }, []);
1072
+ return useEffect(() => {
1073
+ setSyntheticTasks([]);
1074
+ }, [assistableDocumentId]), {
1075
+ syntheticTasks,
1076
+ addSyntheticTask,
1077
+ removeSyntheticTask
1078
+ };
1079
+ }
1025
1080
  function AssistDocumentContextProvider(props) {
1026
1081
  const { documentId, documentType } = props, value = useAssistDocumentContextValue(documentId, documentType);
1027
1082
  return /* @__PURE__ */ jsx(AssistDocumentContext.Provider, { value, children: props.children });
@@ -1116,49 +1171,14 @@ const fadeIn = keyframes`
1116
1171
  }, ref) {
1117
1172
  return /* @__PURE__ */ jsx(FadeInDiv, { ref, style: { animationDuration: `${durationMs}ms` }, children });
1118
1173
  }), purple = {
1119
- 50: {
1120
- title: "Purple 50",
1121
- hex: "#f8f5ff"
1122
- },
1123
- 100: {
1124
- title: "Purple 100",
1125
- hex: "#f1ebff"
1126
- },
1127
- 200: {
1128
- title: "Purple 200",
1129
- hex: "#ece1fe"
1130
- },
1131
- 300: {
1132
- title: "Purple 300",
1133
- hex: "#ccb1fc"
1134
- },
1135
1174
  400: {
1136
- title: "Purple 400",
1137
1175
  hex: "#b087f7"
1138
1176
  },
1139
1177
  500: {
1140
- title: "Purple 500",
1141
1178
  hex: "#8f57ef"
1142
1179
  },
1143
1180
  600: {
1144
- title: "Purple 600",
1145
1181
  hex: "#721fe5"
1146
- },
1147
- 700: {
1148
- title: "Purple 700",
1149
- hex: "#4c1a9e"
1150
- },
1151
- 800: {
1152
- title: "Purple 800",
1153
- hex: "#2f1862"
1154
- },
1155
- 900: {
1156
- title: "Purple 900",
1157
- hex: "#23173f"
1158
- },
1159
- 950: {
1160
- title: "Purple 950",
1161
- hex: "#181128"
1162
1182
  }
1163
1183
  }, Root = styled.span`
1164
1184
  display: block;
@@ -2574,8 +2594,8 @@ function ImageContextProvider(props) {
2574
2594
  ), isShowingOlderRevision = !!usePaneRouter().params?.rev;
2575
2595
  useEffect(() => {
2576
2596
  const descriptionField = getDescriptionFieldOption(schemaType);
2577
- assetRef && assistableDocumentId && descriptionField && assetRef !== assetRefState && !isSyncing && !isShowingOlderRevision && !readOnly && (setAssetRefState(assetRef), canUseAssist(status) && generateCaption({
2578
- path: pathToString([...path, descriptionField]),
2597
+ assetRef && assistableDocumentId && descriptionField?.updateOnImageChange && assetRef !== assetRefState && !isSyncing && !isShowingOlderRevision && !readOnly && (setAssetRefState(assetRef), canUseAssist(status) && generateCaption({
2598
+ path: pathToString([...path, descriptionField.path]),
2579
2599
  documentId: assistableDocumentId
2580
2600
  }));
2581
2601
  }, [
@@ -2593,7 +2613,7 @@ function ImageContextProvider(props) {
2593
2613
  const context = useMemo(() => {
2594
2614
  const descriptionField = getDescriptionFieldOption(schemaType), imageInstructionField = getImageInstructionFieldOption(schemaType);
2595
2615
  return {
2596
- imageDescriptionPath: descriptionField ? pathToString([...path, descriptionField]) : void 0,
2616
+ imageDescriptionPath: descriptionField?.path ? pathToString([...path, descriptionField.path]) : void 0,
2597
2617
  imageInstructionPath: imageInstructionField ? pathToString([...path, imageInstructionField]) : void 0,
2598
2618
  assetRef
2599
2619
  };
@@ -2799,6 +2819,129 @@ function PrivateIcon() {
2799
2819
  }
2800
2820
  );
2801
2821
  }
2822
+ function getRandomValues(typedArray) {
2823
+ const crypto = typeof window < "u" && "crypto" in window ? window.crypto : globalThis.crypto;
2824
+ if (!crypto || !crypto.getRandomValues)
2825
+ throw new Error("WebCrypto not available in this environment");
2826
+ return crypto.getRandomValues(typedArray);
2827
+ }
2828
+ function whatwgRNG(length = 16) {
2829
+ const rnds8 = new Uint8Array(length);
2830
+ return getRandomValues(rnds8), rnds8;
2831
+ }
2832
+ const getByteHexTable = /* @__PURE__ */ (() => {
2833
+ let table;
2834
+ return () => {
2835
+ if (table)
2836
+ return table;
2837
+ table = [];
2838
+ for (let i = 0; i < 256; ++i)
2839
+ table[i] = (i + 256).toString(16).substring(1);
2840
+ return table;
2841
+ };
2842
+ })();
2843
+ function randomKey(length) {
2844
+ const table = getByteHexTable();
2845
+ return whatwgRNG(length).reduce((str, n) => str + table[n], "").slice(0, length);
2846
+ }
2847
+ function defineAssistFieldAction(action) {
2848
+ return {
2849
+ ...action,
2850
+ type: "action"
2851
+ };
2852
+ }
2853
+ function defineFieldActionDivider() {
2854
+ return {
2855
+ type: "divider"
2856
+ };
2857
+ }
2858
+ function defineAssistFieldActionGroup(group) {
2859
+ return {
2860
+ ...group,
2861
+ type: "group"
2862
+ };
2863
+ }
2864
+ function useCustomFieldActions(props) {
2865
+ const {
2866
+ config: { fieldActions }
2867
+ } = useAiAssistanceConfig(), { addSyntheticTask, removeSyntheticTask } = useAssistDocumentContext(), schemaId = useWorkspaceSchemaId(), { push: pushToast } = useToast(), configActions = fieldActions?.useFieldActions?.({
2868
+ ...props,
2869
+ schemaId,
2870
+ path: props.path
2871
+ });
2872
+ return useMemo(() => {
2873
+ const title = fieldActions?.title, customActions = configActions?.map((node) => createSafeNode({
2874
+ node,
2875
+ pushToast,
2876
+ addSyntheticTask,
2877
+ removeSyntheticTask
2878
+ })), onlyGroups = customActions?.length && customActions?.every((node) => node.type === "group");
2879
+ return (customActions?.length ? onlyGroups ? customActions : [
2880
+ {
2881
+ type: "group",
2882
+ title: title || "Custom actions",
2883
+ children: customActions,
2884
+ expanded: !0
2885
+ }
2886
+ ] : []) ?? [];
2887
+ }, [configActions, fieldActions, pushToast]);
2888
+ }
2889
+ function createSafeNode(args) {
2890
+ const { node } = args;
2891
+ switch (node.type) {
2892
+ case "action":
2893
+ return createSafeAction({ ...args, action: node });
2894
+ case "group":
2895
+ return {
2896
+ ...node,
2897
+ renderAsButton: !1,
2898
+ expanded: !0,
2899
+ children: node.children?.map((child) => createSafeNode({ ...args, node: child }))
2900
+ };
2901
+ case "divider":
2902
+ default:
2903
+ return node;
2904
+ }
2905
+ }
2906
+ function createSafeAction(args) {
2907
+ const { action, pushToast, addSyntheticTask, removeSyntheticTask } = args;
2908
+ return {
2909
+ ...action,
2910
+ onAction: () => {
2911
+ async function runAction() {
2912
+ const task = {
2913
+ _type: instructionTaskTypeName,
2914
+ _key: randomKey(12),
2915
+ started: (/* @__PURE__ */ new Date()).toISOString(),
2916
+ presence: [
2917
+ {
2918
+ _type: fieldPresenceTypeName,
2919
+ _key: randomKey(12),
2920
+ path: documentRootKey,
2921
+ started: (/* @__PURE__ */ new Date()).toISOString()
2922
+ }
2923
+ ]
2924
+ };
2925
+ try {
2926
+ addSyntheticTask(task);
2927
+ const actionResult = action.onAction?.();
2928
+ actionResult instanceof Promise && await actionResult;
2929
+ } catch (err) {
2930
+ console.error("Failed to execute action", action, err), pushToast({
2931
+ title: "Failed to execute action",
2932
+ description: err?.message,
2933
+ status: "error"
2934
+ });
2935
+ } finally {
2936
+ removeSyntheticTask(task);
2937
+ }
2938
+ }
2939
+ runAction();
2940
+ },
2941
+ renderAsButton: !1,
2942
+ selected: !1
2943
+ };
2944
+ }
2802
2945
  const assistFieldActions = {
2803
2946
  name: "sanity-assist-actions",
2804
2947
  useAction(props) {
@@ -2813,7 +2956,7 @@ const assistFieldActions = {
2813
2956
  documentSchemaType,
2814
2957
  selectedPath,
2815
2958
  assistableDocumentId
2816
- } = useAssistDocumentContext(), { value: docValue, formState } = useDocumentPane(), formStateRef = useRef(formState);
2959
+ } = useAssistDocumentContext(), { value: docValue, formState } = useDocumentPane(), docValueRef = useRef(docValue), formStateRef = useRef(formState);
2817
2960
  formStateRef.current = formState;
2818
2961
  const currentUser = useCurrentUser(), isHidden = !assistDocument, pathKey = usePathKey(props.path), typePath = useTypePath(docValue, pathKey), assistDocumentId2 = assistDocument?._id, { requestRunInstruction } = useRequestRunInstruction({
2819
2962
  documentOnChange,
@@ -2875,7 +3018,6 @@ const assistFieldActions = {
2875
3018
  isPrivate: !!(instruction2.userId && instruction2.userId === currentUser?.id),
2876
3019
  onInstructionAction,
2877
3020
  hidden: isHidden,
2878
- documentIsNew: !!documentIsNew,
2879
3021
  assistSupported
2880
3022
  })
2881
3023
  ) || [],
@@ -2893,7 +3035,23 @@ const assistFieldActions = {
2893
3035
  imageCaptionAction,
2894
3036
  translateAction,
2895
3037
  imageGenAction
2896
- ]), instructionsLength = instructions?.length || 0, manageInstructionsItem = useMemo(
3038
+ ]), getDocumentValue = useCallback(() => docValueRef.current, []), getConditionalPaths = useCallback(() => (formStateRef.current ? getConditionalMembers(formStateRef.current) : []).flatMap(
3039
+ (cm) => {
3040
+ const path = stringToPath(cm.path);
3041
+ return path.some((s) => typeof s == "number") ? [] : {
3042
+ ...cm,
3043
+ path
3044
+ };
3045
+ }
3046
+ ), []), customActions = useCustomFieldActions({
3047
+ actionType: props.path.length ? "field" : "document",
3048
+ documentIdForAction: assistableDocumentId,
3049
+ schemaType,
3050
+ documentSchemaType,
3051
+ path: props.path,
3052
+ getDocumentValue,
3053
+ getConditionalPaths
3054
+ }), manageInstructionsItem = useMemo(
2897
3055
  () => ({
2898
3056
  type: "action",
2899
3057
  icon: ControlsIcon,
@@ -2910,6 +3068,7 @@ const assistFieldActions = {
2910
3068
  children: [
2911
3069
  runInstructionsGroup,
2912
3070
  translateAction,
3071
+ ...customActions,
2913
3072
  assistSupported && manageInstructionsItem
2914
3073
  ].filter((c) => !!c).filter((c) => c.type === "group" ? c.children.length : !0),
2915
3074
  expanded: !1,
@@ -2923,7 +3082,8 @@ const assistFieldActions = {
2923
3082
  assistSupported,
2924
3083
  imageCaptionAction,
2925
3084
  translateAction,
2926
- imageGenAction
3085
+ imageGenAction,
3086
+ customActions
2927
3087
  ]
2928
3088
  ), emptyAction = useMemo(
2929
3089
  () => ({
@@ -2937,7 +3097,7 @@ const assistFieldActions = {
2937
3097
  }),
2938
3098
  [assistSupported, manageInstructions, isSelected]
2939
3099
  );
2940
- return instructionsLength === 0 && !imageCaptionAction && !translateAction && !imageGenAction ? emptyAction : group;
3100
+ return !instructions?.length && !imageCaptionAction && !translateAction && !imageGenAction && !customActions.length ? emptyAction : group;
2941
3101
  }
2942
3102
  };
2943
3103
  function instructionItem(props) {
@@ -2958,21 +3118,19 @@ function createAssistDocumentPresence(documentId) {
2958
3118
  };
2959
3119
  }
2960
3120
  function AssistDocumentPresence() {
2961
- const { assistDocument } = useAssistDocumentContext(), anyPresence = useMemo(() => {
2962
- const anyPresence2 = assistDocument?.tasks?.filter((run) => !run.ended && !run.reason)?.flatMap((run) => run.presence ?? []).find((f) => f.started && (/* @__PURE__ */ new Date()).getTime() - new Date(f.started).getTime() < 3e4);
3121
+ const { assistDocument, syntheticTasks } = useAssistDocumentContext(), anyPresence = useMemo(() => {
3122
+ const anyPresence2 = [...assistDocument?.tasks ?? [], ...syntheticTasks ?? []].filter((run) => !run.ended && !run.reason)?.flatMap((run) => run.presence ?? []).find((f) => f.started && (/* @__PURE__ */ new Date()).getTime() - new Date(f.started).getTime() < 3e4);
2963
3123
  if (anyPresence2)
2964
3124
  return aiPresence(anyPresence2, []);
2965
3125
  const anyRun = assistDocument?.tasks?.filter((run) => !run.ended && !run.reason)?.find((f) => f.started && (/* @__PURE__ */ new Date()).getTime() - new Date(f.started).getTime() < 3e4);
2966
3126
  return anyRun ? aiPresence(
2967
3127
  {
2968
3128
  started: anyRun.started,
2969
- path: documentRootKey,
2970
- _key: anyRun._key,
2971
- _type: fieldPresenceTypeName
3129
+ _key: anyRun._key
2972
3130
  },
2973
3131
  []
2974
3132
  ) : void 0;
2975
- }, [assistDocument?.tasks]);
3133
+ }, [assistDocument?.tasks, syntheticTasks]);
2976
3134
  return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(Flex, { flex: 1, justify: "flex-end", children: /* @__PURE__ */ jsx(Flex, { gap: 2, align: "center", children: anyPresence && /* @__PURE__ */ jsx(AiFieldPresence, { presence: anyPresence }) }) }) });
2977
3135
  }
2978
3136
  function BackToInstructionListLink() {
@@ -3366,31 +3524,6 @@ function Selectable({
3366
3524
  /* @__PURE__ */ jsx(Card, { marginTop: 1, onClick: handleChange, children: /* @__PURE__ */ jsx(Text, { style: { cursor: "default" }, size: 1, children: title }) })
3367
3525
  ] });
3368
3526
  }
3369
- function getRandomValues(typedArray) {
3370
- const crypto = typeof window < "u" && "crypto" in window ? window.crypto : globalThis.crypto;
3371
- if (!crypto || !crypto.getRandomValues)
3372
- throw new Error("WebCrypto not available in this environment");
3373
- return crypto.getRandomValues(typedArray);
3374
- }
3375
- function whatwgRNG(length = 16) {
3376
- const rnds8 = new Uint8Array(length);
3377
- return getRandomValues(rnds8), rnds8;
3378
- }
3379
- const getByteHexTable = /* @__PURE__ */ (() => {
3380
- let table;
3381
- return () => {
3382
- if (table)
3383
- return table;
3384
- table = [];
3385
- for (let i = 0; i < 256; ++i)
3386
- table[i] = (i + 256).toString(16).substring(1);
3387
- return table;
3388
- };
3389
- })();
3390
- function randomKey(length) {
3391
- const table = getByteHexTable();
3392
- return whatwgRNG(length).reduce((str, n) => str + table[n], "").slice(0, length);
3393
- }
3394
3527
  const PteMods = styled(Box)`
3395
3528
  & [data-testid='pt-editor__toolbar-card'] > div > div:last-child {
3396
3529
  display: none;
@@ -4091,10 +4224,18 @@ function SchemaEntry({ schemaStub }) {
4091
4224
  const out = useMemo(() => JSON.stringify(schemaStub, null, 2), [schemaStub]);
4092
4225
  return /* @__PURE__ */ jsx("pre", { children: out });
4093
4226
  }
4227
+ function useUserInput() {
4228
+ const { getUserInput } = useRunInstruction();
4229
+ return getUserInput;
4230
+ }
4094
4231
  export {
4095
4232
  SchemaTypeTool,
4096
4233
  assist,
4097
4234
  contextDocumentTypeName,
4098
- defaultLanguageOutputs
4235
+ defaultLanguageOutputs,
4236
+ defineAssistFieldAction,
4237
+ defineAssistFieldActionGroup,
4238
+ defineFieldActionDivider,
4239
+ useUserInput
4099
4240
  };
4100
4241
  //# sourceMappingURL=index.esm.js.map