@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/README.md +302 -0
- package/dist/index.d.mts +269 -1
- package/dist/index.d.ts +269 -1
- package/dist/index.esm.js +244 -103
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +239 -98
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +244 -103
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -8
- package/src/assistDocument/AssistDocumentContext.tsx +14 -1
- package/src/assistDocument/hooks/useAssistDocumentContextValue.tsx +30 -3
- package/src/assistLayout/RunInstructionProvider.tsx +75 -23
- package/src/components/ImageContext.tsx +4 -4
- package/src/fieldActions/assistFieldActions.tsx +42 -2
- package/src/fieldActions/customFieldActions.tsx +304 -0
- package/src/fieldActions/useUserInput.ts +107 -0
- package/src/helpers/typeUtils.ts +13 -3
- package/src/index.ts +17 -0
- package/src/plugin.tsx +6 -0
- package/src/presence/AssistDocumentPresence.tsx +3 -3
- package/src/schemas/typeDefExtensions.ts +12 -1
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { pathToString,
|
|
3
|
-
import { useToast, useLayer, Dialog, Flex, Tooltip, Text,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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(),
|
|
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
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
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
|
-
]),
|
|
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
|
|
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
|
|
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
|
-
|
|
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.mjs.map
|