@sanity/assist 4.4.5 → 4.4.7
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.mts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.esm.js +300 -259
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +298 -257
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +300 -259
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/assistDocument/AssistDocumentContext.tsx +1 -3
- package/src/assistDocument/hooks/useAssistDocumentContextValue.tsx +7 -17
- package/src/assistInspector/FieldAutocomplete.tsx +9 -4
- package/src/assistInspector/helpers.ts +15 -26
- package/src/assistLayout/AiAssistanceConfigContext.tsx +9 -59
- package/src/assistLayout/AiAssistanceConfigProvider.tsx +98 -0
- package/src/assistLayout/AssistLayout.tsx +1 -1
- package/src/assistLayout/fieldRefCache.tsx +34 -0
- package/src/fieldActions/customFieldActions.tsx +2 -1
- package/src/schemas/assistDocumentSchema.tsx +9 -6
- package/src/schemas/typeDefExtensions.ts +1 -0
- package/src/useApiClient.ts +1 -2
package/dist/index.esm.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { pathToString, getVersionFromId, getPublishedId, isVersionId, useEditState, useCurrentUser, useClient, typed,
|
|
2
|
+
import { pathToString, getVersionFromId, getPublishedId, isVersionId, useEditState, useCurrentUser, useClient, typed, FormFieldHeaderText, PatchEvent, unset, isObjectSchemaType, stringToPath, isKeySegment, useSchema, getVersionId, getDraftId, useColorSchemeValue, isArraySchemaType, useFormCallbacks, useDocumentStore, useDocumentPresence, createPatchChannel, FormBuilder, fromMutationPatches, StatusButton, PresenceOverlay, VirtualizerScrollInstanceProvider, isDocumentSchemaType, useSyncState, set, useWorkspaceSchemaId, MemberFieldError, FormCallbacksProvider, FormInput, setIfMissing, insert, ObjectInputMember, isArrayOfObjectsSchemaType, defineType, defineField, defineArrayMember, definePlugin } from "sanity";
|
|
3
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,
|
|
7
|
+
import { PlayIcon, DocumentIcon, LinkIcon, ImageIcon, BlockContentIcon, OlistIcon, BlockquoteIcon, StringIcon, 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";
|
|
@@ -392,99 +392,6 @@ function useAssistDocumentContext() {
|
|
|
392
392
|
throw new Error("AssistDocumentContext value is missing");
|
|
393
393
|
return context;
|
|
394
394
|
}
|
|
395
|
-
const SelectedFieldContext = createContext(void 0), SelectedFieldContextProvider = SelectedFieldContext.Provider, maxDepth = 6;
|
|
396
|
-
function getTypeIcon(schemaType) {
|
|
397
|
-
let t = schemaType;
|
|
398
|
-
for (; t; ) {
|
|
399
|
-
if (t.icon) return t.icon;
|
|
400
|
-
t = t.type;
|
|
401
|
-
}
|
|
402
|
-
return isType(schemaType, "slug") ? LinkIcon : isType(schemaType, "image") ? ImageIcon : schemaType.jsonType === "array" && isPortableTextArray(schemaType) ? BlockContentIcon : schemaType.jsonType === "array" ? OlistIcon : schemaType.jsonType === "object" ? BlockquoteIcon : schemaType.jsonType === "string" ? StringIcon : DocumentIcon;
|
|
403
|
-
}
|
|
404
|
-
function asFieldRefsByTypePath(fieldRefs) {
|
|
405
|
-
return fieldRefs.reduce(
|
|
406
|
-
(acc, ref) => ({ ...acc, [ref.key]: ref }),
|
|
407
|
-
{}
|
|
408
|
-
);
|
|
409
|
-
}
|
|
410
|
-
function getFieldRefsWithDocument(schemaType) {
|
|
411
|
-
const fields = getFieldRefs(schemaType);
|
|
412
|
-
return [
|
|
413
|
-
{
|
|
414
|
-
key: documentRootKey,
|
|
415
|
-
icon: schemaType.icon ?? DocumentIcon,
|
|
416
|
-
title: "The entire document",
|
|
417
|
-
path: [],
|
|
418
|
-
schemaType
|
|
419
|
-
},
|
|
420
|
-
...fields
|
|
421
|
-
];
|
|
422
|
-
}
|
|
423
|
-
function getFieldRefs(schemaType, parent, depth = 0) {
|
|
424
|
-
return depth >= maxDepth ? [] : schemaType.fields.filter((f) => !f.name.startsWith("_")).flatMap((field) => {
|
|
425
|
-
const path = parent ? [...parent.path, field.name] : [field.name], title = field.type.title ?? field.name, fieldRef = {
|
|
426
|
-
key: patchableKey(pathToString(path)),
|
|
427
|
-
path,
|
|
428
|
-
title: parent ? [parent.title, title].join(" / ") : title,
|
|
429
|
-
schemaType: field.type,
|
|
430
|
-
icon: getTypeIcon(field.type)
|
|
431
|
-
}, fields = field.type.jsonType === "object" ? getFieldRefs(field.type, fieldRef, depth + 1) : [], syntheticFields = field.type.jsonType === "array" ? getSyntheticFields(field.type, fieldRef, depth + 1) : [];
|
|
432
|
-
return isAssistSupported(field.type) ? [fieldRef, ...fields, ...syntheticFields] : [...fields, ...syntheticFields];
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
function getSyntheticFields(schemaType, parent, depth = 0) {
|
|
436
|
-
return depth >= maxDepth ? [] : schemaType.of.filter((itemType) => !isType(itemType, "block")).flatMap((itemType) => {
|
|
437
|
-
const segment = { _key: itemType.name }, title = itemType.title ?? itemType.name, path = parent ? [...parent.path, segment] : [segment], fieldRef = {
|
|
438
|
-
key: patchableKey(pathToString(path)),
|
|
439
|
-
path,
|
|
440
|
-
title: parent ? [parent.title, title].join(" / ") : title,
|
|
441
|
-
schemaType: itemType,
|
|
442
|
-
icon: getTypeIcon(itemType),
|
|
443
|
-
synthetic: !0
|
|
444
|
-
}, fields = itemType.jsonType === "object" ? getFieldRefs(itemType, fieldRef, depth + 1) : [];
|
|
445
|
-
return isAssistSupported(itemType) ? [fieldRef, ...fields] : fields;
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
function getTypePath(doc, pathString) {
|
|
449
|
-
if (!pathString)
|
|
450
|
-
return;
|
|
451
|
-
const path = stringToPath(pathString), currentPath = [];
|
|
452
|
-
let valid = !0;
|
|
453
|
-
const syntheticPath = path.map((segment) => {
|
|
454
|
-
if (currentPath.push(segment), isKeySegment(segment)) {
|
|
455
|
-
const match = extractWithPath(pathToString(currentPath), doc)[0], value = match?.value;
|
|
456
|
-
if (match && value && typeof value == "object" && "_type" in value)
|
|
457
|
-
return { _key: value._type };
|
|
458
|
-
valid = !1;
|
|
459
|
-
}
|
|
460
|
-
return segment;
|
|
461
|
-
});
|
|
462
|
-
return valid ? patchableKey(pathToString(syntheticPath)) : void 0;
|
|
463
|
-
}
|
|
464
|
-
function patchableKey(pathKey) {
|
|
465
|
-
return pathKey.replace(/[=]=/g, ":").replace(/[[\]]/g, "|").replace(/"/g, "");
|
|
466
|
-
}
|
|
467
|
-
function useTypePath(doc, pathString) {
|
|
468
|
-
return useMemo(() => getTypePath(doc, pathString), [doc, pathString]);
|
|
469
|
-
}
|
|
470
|
-
function useSelectedField(documentSchemaType, path) {
|
|
471
|
-
const selectableFields = useMemo(
|
|
472
|
-
() => documentSchemaType && isObjectSchemaType(documentSchemaType) ? getFieldRefsWithDocument(documentSchemaType) : [],
|
|
473
|
-
[documentSchemaType]
|
|
474
|
-
);
|
|
475
|
-
return useMemo(() => path ? selectableFields?.find((f) => f.key === path) : void 0, [selectableFields, path]);
|
|
476
|
-
}
|
|
477
|
-
function getFieldTitle(field) {
|
|
478
|
-
const schemaType = field?.schemaType;
|
|
479
|
-
return field?.title ?? schemaType?.title ?? schemaType?.name ?? "Untitled";
|
|
480
|
-
}
|
|
481
|
-
function useAiPaneRouter() {
|
|
482
|
-
const paneRouter = usePaneRouter();
|
|
483
|
-
return useMemo(
|
|
484
|
-
() => ({ ...paneRouter, params: paneRouter.params ?? {} }),
|
|
485
|
-
[paneRouter]
|
|
486
|
-
);
|
|
487
|
-
}
|
|
488
395
|
const AiAssistanceConfigContext = createContext({});
|
|
489
396
|
function useAiAssistanceConfig() {
|
|
490
397
|
const context = useContext(AiAssistanceConfigContext);
|
|
@@ -492,31 +399,8 @@ function useAiAssistanceConfig() {
|
|
|
492
399
|
throw new Error("Missing AiAssistanceConfigContext");
|
|
493
400
|
return context;
|
|
494
401
|
}
|
|
495
|
-
function
|
|
496
|
-
|
|
497
|
-
useEffect(() => {
|
|
498
|
-
getInstructStatus().then((s) => setStatus(s)).catch((e) => {
|
|
499
|
-
console.error(e), setError(e);
|
|
500
|
-
});
|
|
501
|
-
}, [getInstructStatus]);
|
|
502
|
-
const init = useCallback(async () => {
|
|
503
|
-
setError(void 0);
|
|
504
|
-
try {
|
|
505
|
-
await initInstruct();
|
|
506
|
-
const status2 = await getInstructStatus();
|
|
507
|
-
setStatus(status2);
|
|
508
|
-
} catch (e) {
|
|
509
|
-
console.error("Failed to init ai assistance", e), setError(e);
|
|
510
|
-
}
|
|
511
|
-
}, [initInstruct, getInstructStatus, setStatus]), { config, children } = props, context = useMemo(() => ({
|
|
512
|
-
config,
|
|
513
|
-
status,
|
|
514
|
-
statusLoading,
|
|
515
|
-
init,
|
|
516
|
-
initLoading,
|
|
517
|
-
error
|
|
518
|
-
}), [config, status, init, statusLoading, initLoading, error]);
|
|
519
|
-
return /* @__PURE__ */ jsx(AiAssistanceConfigContext.Provider, { value: context, children });
|
|
402
|
+
function useSerializedTypes() {
|
|
403
|
+
return useAiAssistanceConfig().serializedTypes;
|
|
520
404
|
}
|
|
521
405
|
const basePath = "/assist/tasks/instruction", API_VERSION_WITH_EXTENDED_TYPES = "2025-04-01";
|
|
522
406
|
function canUseAssist(status) {
|
|
@@ -896,144 +780,105 @@ function useDraftDelayedTask(args) {
|
|
|
896
780
|
[setQueuedArgs, documentOnChange]
|
|
897
781
|
);
|
|
898
782
|
}
|
|
899
|
-
const
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
"
|
|
907
|
-
"document",
|
|
908
|
-
"email",
|
|
909
|
-
"file",
|
|
910
|
-
"globalDocumentReference",
|
|
911
|
-
"image",
|
|
912
|
-
"number",
|
|
913
|
-
"object",
|
|
914
|
-
"reference",
|
|
915
|
-
"span",
|
|
916
|
-
"string",
|
|
917
|
-
"text",
|
|
918
|
-
"url",
|
|
919
|
-
"slug",
|
|
920
|
-
"geopoint",
|
|
921
|
-
"sanity.assetSourceData",
|
|
922
|
-
"sanity.imageAsset",
|
|
923
|
-
"sanity.fileAsset",
|
|
924
|
-
"sanity.imageCrop",
|
|
925
|
-
"sanity.imageHotspot",
|
|
926
|
-
"sanity.imageMetadata",
|
|
927
|
-
"sanity.imageDimensions",
|
|
928
|
-
"sanity.imagePalette",
|
|
929
|
-
"sanity.imagePaletteSwatch",
|
|
930
|
-
assistSerializedTypeName,
|
|
931
|
-
assistSerializedFieldTypeName,
|
|
932
|
-
"sanity-agent.job.document"
|
|
933
|
-
], inlineTypes = ["document", "object", "image", "file"];
|
|
934
|
-
function serializeSchema(schema, options2) {
|
|
935
|
-
const list = schema.getTypeNames().filter((t) => !(hiddenTypes.includes(t) || t.startsWith("sanity."))).map((t) => schema.get(t)).filter((t) => !!t).map((t) => getSchemaStub(t, schema, options2)).filter((t) => !("to" in t && t.to && !t.to.length || "of" in t && t.of && !t.of.length || "fields" in t && t.fields && !t.fields.length));
|
|
936
|
-
return list.sort((a, b) => (a?.name ?? "").localeCompare(b?.name ?? "")), list;
|
|
783
|
+
const maxDepth = 6;
|
|
784
|
+
function getTypeIcon(schemaType) {
|
|
785
|
+
let t = schemaType;
|
|
786
|
+
for (; t; ) {
|
|
787
|
+
if (t.icon) return t.icon;
|
|
788
|
+
t = t.type;
|
|
789
|
+
}
|
|
790
|
+
return isType(schemaType, "slug") ? LinkIcon : isType(schemaType, "image") ? ImageIcon : schemaType.jsonType === "array" && isPortableTextArray(schemaType) ? BlockContentIcon : schemaType.jsonType === "array" ? OlistIcon : schemaType.jsonType === "object" ? BlockquoteIcon : schemaType.jsonType === "string" ? StringIcon : DocumentIcon;
|
|
937
791
|
}
|
|
938
|
-
function
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
792
|
+
function asFieldRefsByTypePath(fieldRefs) {
|
|
793
|
+
return fieldRefs.reduce(
|
|
794
|
+
(acc, ref) => ({ ...acc, [ref.key]: ref }),
|
|
795
|
+
{}
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
function getDocumentFieldRef(schemaType) {
|
|
799
|
+
return {
|
|
800
|
+
key: documentRootKey,
|
|
801
|
+
icon: schemaType.icon ?? DocumentIcon,
|
|
802
|
+
title: "The entire document",
|
|
803
|
+
path: [],
|
|
804
|
+
schemaType
|
|
948
805
|
};
|
|
949
|
-
return removeUndef(baseSchema);
|
|
950
806
|
}
|
|
951
|
-
function
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
) :
|
|
961
|
-
of: "of" in type && typeName === "array" ? arrayOf(type, schema, options2) : void 0,
|
|
962
|
-
to: "to" in type && typeName === "reference" ? refToTypeNames(type) : void 0,
|
|
963
|
-
fields: "fields" in type && inlineTypes.includes(typeName) ? serializeFields(schema, type, options2) : void 0,
|
|
964
|
-
annotations: typeName === "block" && "fields" in type ? serializeAnnotations(type, schema, options2) : void 0,
|
|
965
|
-
inlineOf: typeName === "block" && "fields" in type ? serializeInlineOf(type, schema, options2) : void 0,
|
|
966
|
-
hidden: typeof type.hidden == "function" ? "function" : type.hidden ? !0 : void 0,
|
|
967
|
-
readOnly: typeof type.readOnly == "function" ? "function" : type.readOnly ? !0 : void 0
|
|
807
|
+
function getFieldRefs(schemaType, parent, depth = 0) {
|
|
808
|
+
return depth >= maxDepth ? [] : schemaType.fields.filter((f) => !f.name.startsWith("_")).flatMap((field) => {
|
|
809
|
+
const path = parent ? [...parent.path, field.name] : [field.name], title = field.type.title ?? field.name, fieldRef = {
|
|
810
|
+
key: patchableKey(pathToString(path)),
|
|
811
|
+
path,
|
|
812
|
+
title: parent ? [parent.title, title].join(" / ") : title,
|
|
813
|
+
schemaType: field.type,
|
|
814
|
+
icon: getTypeIcon(field.type)
|
|
815
|
+
}, fields = field.type.jsonType === "object" ? getFieldRefs(field.type, fieldRef, depth + 1) : [], syntheticFields = field.type.jsonType === "array" ? getSyntheticFields(field.type, fieldRef, depth + 1) : [];
|
|
816
|
+
return isAssistSupported(field.type) ? [fieldRef, ...fields, ...syntheticFields] : [...fields, ...syntheticFields];
|
|
968
817
|
});
|
|
969
818
|
}
|
|
970
|
-
function
|
|
971
|
-
return
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
}))
|
|
982
|
-
) : schemaType.fields).filter((f) => !["sanity.imageHotspot", "sanity.imageCrop"].includes(f.type?.name ?? "")).filter((f) => isAssistSupported(f.type)).map((field) => serializeMember(schema, field.type, field.name, options2));
|
|
983
|
-
}
|
|
984
|
-
function serializeMember(schema, type, name, options2) {
|
|
985
|
-
const typeName = schema.get(type?.name) ? type.name : type.type?.name ?? "";
|
|
986
|
-
return removeUndef({
|
|
987
|
-
...options2?.leanFormat ? {} : { _type: assistSerializedFieldTypeName },
|
|
988
|
-
name,
|
|
989
|
-
type: typeName,
|
|
990
|
-
title: type.title,
|
|
991
|
-
...getBaseFields(schema, type, typeName, options2)
|
|
819
|
+
function getSyntheticFields(schemaType, parent, depth = 0) {
|
|
820
|
+
return depth >= maxDepth ? [] : schemaType.of.filter((itemType) => !isType(itemType, "block")).flatMap((itemType) => {
|
|
821
|
+
const segment = { _key: itemType.name }, title = itemType.title ?? itemType.name, path = parent ? [...parent.path, segment] : [segment], fieldRef = {
|
|
822
|
+
key: patchableKey(pathToString(path)),
|
|
823
|
+
path,
|
|
824
|
+
title: parent ? [parent.title, title].join(" / ") : title,
|
|
825
|
+
schemaType: itemType,
|
|
826
|
+
icon: getTypeIcon(itemType),
|
|
827
|
+
synthetic: !0
|
|
828
|
+
}, fields = itemType.jsonType === "object" ? getFieldRefs(itemType, fieldRef, depth + 1) : [];
|
|
829
|
+
return isAssistSupported(itemType) ? [fieldRef, ...fields] : fields;
|
|
992
830
|
});
|
|
993
831
|
}
|
|
994
|
-
function
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
832
|
+
function getTypePath(doc, pathString) {
|
|
833
|
+
if (!pathString)
|
|
834
|
+
return;
|
|
835
|
+
const path = stringToPath(pathString), currentPath = [];
|
|
836
|
+
let valid = !0;
|
|
837
|
+
const syntheticPath = path.map((segment) => {
|
|
838
|
+
if (currentPath.push(segment), isKeySegment(segment)) {
|
|
839
|
+
const match = extractWithPath(pathToString(currentPath), doc)[0], value = match?.value;
|
|
840
|
+
if (match && value && typeof value == "object" && "_type" in value)
|
|
841
|
+
return { _key: value._type };
|
|
842
|
+
valid = !1;
|
|
843
|
+
}
|
|
844
|
+
return segment;
|
|
845
|
+
});
|
|
846
|
+
return valid ? patchableKey(pathToString(syntheticPath)) : void 0;
|
|
1004
847
|
}
|
|
1005
|
-
function
|
|
1006
|
-
|
|
1007
|
-
if (!(!marksType || !isArraySchemaType(marksType)))
|
|
1008
|
-
return arrayOf(marksType, schema, options2);
|
|
848
|
+
function patchableKey(pathKey) {
|
|
849
|
+
return pathKey.replace(/[=]=/g, ":").replace(/[[\]]/g, "|").replace(/"/g, "");
|
|
1009
850
|
}
|
|
1010
|
-
function
|
|
1011
|
-
return
|
|
851
|
+
function useTypePath(doc, pathString) {
|
|
852
|
+
return useMemo(() => getTypePath(doc, pathString), [doc, pathString]);
|
|
1012
853
|
}
|
|
1013
|
-
function
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
854
|
+
function useSelectedField(documentSchemaType, path) {
|
|
855
|
+
const { getFieldRefs: getFieldRefs2 } = useAiAssistanceConfig(), selectableFields = useMemo(
|
|
856
|
+
() => documentSchemaType && isObjectSchemaType(documentSchemaType) ? [getDocumentFieldRef(documentSchemaType), ...getFieldRefs2(documentSchemaType.name)] : [],
|
|
857
|
+
[documentSchemaType, getFieldRefs2]
|
|
858
|
+
);
|
|
859
|
+
return useMemo(() => path ? selectableFields?.find((f) => f.key === path) : void 0, [selectableFields, path]);
|
|
1017
860
|
}
|
|
1018
|
-
function
|
|
1019
|
-
|
|
861
|
+
function getFieldTitle(field) {
|
|
862
|
+
const schemaType = field?.schemaType;
|
|
863
|
+
return field?.title ?? schemaType?.title ?? schemaType?.name ?? "Untitled";
|
|
1020
864
|
}
|
|
1021
|
-
function
|
|
1022
|
-
|
|
865
|
+
function useAiPaneRouter() {
|
|
866
|
+
const paneRouter = usePaneRouter();
|
|
867
|
+
return useMemo(
|
|
868
|
+
() => ({ ...paneRouter, params: paneRouter.params ?? {} }),
|
|
869
|
+
[paneRouter]
|
|
870
|
+
);
|
|
1023
871
|
}
|
|
1024
872
|
function useAssistDocumentContextValue(documentId, documentType) {
|
|
1025
|
-
const schema = useSchema(), documentSchemaType = useMemo(() => {
|
|
873
|
+
const schema = useSchema(), { getFieldRefs: getFieldRefs2, getFieldRefsByTypePath } = useAiAssistanceConfig(), documentSchemaType = useMemo(() => {
|
|
1026
874
|
const schemaType = schema.get(documentType);
|
|
1027
875
|
if (!schemaType)
|
|
1028
876
|
throw new Error(`Schema type "${documentType}" not found`);
|
|
1029
877
|
return schemaType;
|
|
1030
|
-
}, [documentType, schema]),
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
fieldRefsByTypePath: fieldRefsByTypePath2
|
|
1035
|
-
};
|
|
1036
|
-
}, [documentSchemaType]), {
|
|
878
|
+
}, [documentType, schema]), { fieldRefs, fieldRefsByTypePath } = useMemo(() => ({
|
|
879
|
+
fieldRefs: getFieldRefs2(documentType),
|
|
880
|
+
fieldRefsByTypePath: getFieldRefsByTypePath(documentType)
|
|
881
|
+
}), [getFieldRefs2, getFieldRefsByTypePath, documentType]), {
|
|
1037
882
|
openInspector,
|
|
1038
883
|
closeInspector,
|
|
1039
884
|
inspector,
|
|
@@ -1061,8 +906,7 @@ function useAssistDocumentContextValue(documentId, documentType) {
|
|
|
1061
906
|
addSyntheticTask,
|
|
1062
907
|
removeSyntheticTask,
|
|
1063
908
|
fieldRefs,
|
|
1064
|
-
fieldRefsByTypePath
|
|
1065
|
-
serializedTypes
|
|
909
|
+
fieldRefsByTypePath
|
|
1066
910
|
};
|
|
1067
911
|
return assistDocument ? {
|
|
1068
912
|
...base,
|
|
@@ -1084,8 +928,7 @@ function useAssistDocumentContextValue(documentId, documentType) {
|
|
|
1084
928
|
addSyntheticTask,
|
|
1085
929
|
removeSyntheticTask,
|
|
1086
930
|
fieldRefs,
|
|
1087
|
-
fieldRefsByTypePath
|
|
1088
|
-
serializedTypes
|
|
931
|
+
fieldRefsByTypePath
|
|
1089
932
|
]);
|
|
1090
933
|
}
|
|
1091
934
|
function useSyntheticTasks(assistableDocumentId) {
|
|
@@ -1602,7 +1445,10 @@ function InspectorOnboarding(props) {
|
|
|
1602
1445
|
] }) }) });
|
|
1603
1446
|
}
|
|
1604
1447
|
function FieldAutocomplete(props) {
|
|
1605
|
-
const { id, schemaType, fieldPath, onSelect, includeDocument, filter: filter2 } = props,
|
|
1448
|
+
const { id, schemaType, fieldPath, onSelect, includeDocument, filter: filter2 } = props, { getFieldRefs: getFieldRefs2 } = useAiAssistanceConfig(), fieldRefs = useMemo(() => {
|
|
1449
|
+
const refs = getFieldRefs2(schemaType.name);
|
|
1450
|
+
return includeDocument ? [getDocumentFieldRef(schemaType), ...refs] : refs;
|
|
1451
|
+
}, [schemaType, includeDocument, getFieldRefs2]), currentField = useMemo(
|
|
1606
1452
|
() => fieldRefs.find((f) => f.key === fieldPath),
|
|
1607
1453
|
[fieldPath, fieldRefs]
|
|
1608
1454
|
), autocompleteOptions = useMemo(
|
|
@@ -2603,6 +2449,195 @@ function FromLanguageRadio(props) {
|
|
|
2603
2449
|
/* @__PURE__ */ jsx(Text, { children: radioLanguage.title ?? radioLanguage.id })
|
|
2604
2450
|
] }, langId);
|
|
2605
2451
|
}
|
|
2452
|
+
const hiddenTypes = [
|
|
2453
|
+
"any",
|
|
2454
|
+
"array",
|
|
2455
|
+
"block",
|
|
2456
|
+
"boolean",
|
|
2457
|
+
"crossDatasetReference",
|
|
2458
|
+
"date",
|
|
2459
|
+
"datetime",
|
|
2460
|
+
"document",
|
|
2461
|
+
"email",
|
|
2462
|
+
"file",
|
|
2463
|
+
"globalDocumentReference",
|
|
2464
|
+
"image",
|
|
2465
|
+
"number",
|
|
2466
|
+
"object",
|
|
2467
|
+
"reference",
|
|
2468
|
+
"span",
|
|
2469
|
+
"string",
|
|
2470
|
+
"text",
|
|
2471
|
+
"url",
|
|
2472
|
+
"slug",
|
|
2473
|
+
"geopoint",
|
|
2474
|
+
"sanity.assetSourceData",
|
|
2475
|
+
"sanity.imageAsset",
|
|
2476
|
+
"sanity.fileAsset",
|
|
2477
|
+
"sanity.imageCrop",
|
|
2478
|
+
"sanity.imageHotspot",
|
|
2479
|
+
"sanity.imageMetadata",
|
|
2480
|
+
"sanity.imageDimensions",
|
|
2481
|
+
"sanity.imagePalette",
|
|
2482
|
+
"sanity.imagePaletteSwatch",
|
|
2483
|
+
assistSerializedTypeName,
|
|
2484
|
+
assistSerializedFieldTypeName,
|
|
2485
|
+
"sanity-agent.job.document"
|
|
2486
|
+
], inlineTypes = ["document", "object", "image", "file"];
|
|
2487
|
+
function serializeSchema(schema, options2) {
|
|
2488
|
+
const list = schema.getTypeNames().filter((t) => !(hiddenTypes.includes(t) || t.startsWith("sanity."))).map((t) => schema.get(t)).filter((t) => !!t).map((t) => getSchemaStub(t, schema, options2)).filter((t) => !("to" in t && t.to && !t.to.length || "of" in t && t.of && !t.of.length || "fields" in t && t.fields && !t.fields.length));
|
|
2489
|
+
return list.sort((a, b) => (a?.name ?? "").localeCompare(b?.name ?? "")), list;
|
|
2490
|
+
}
|
|
2491
|
+
function getSchemaStub(schemaType, schema, options2) {
|
|
2492
|
+
if (!schemaType.type?.name)
|
|
2493
|
+
throw console.error("Missing type name", schemaType.type), new Error("Type is missing name!");
|
|
2494
|
+
const baseSchema = {
|
|
2495
|
+
// we dont need type or id when we send using POST, so leave these out to save bandwidth
|
|
2496
|
+
...options2?.leanFormat ? {} : { _id: `${assistSchemaIdPrefix}${schemaType.name}`, _type: assistSerializedTypeName },
|
|
2497
|
+
name: schemaType.name,
|
|
2498
|
+
title: schemaType.title,
|
|
2499
|
+
type: schemaType.type.name,
|
|
2500
|
+
...getBaseFields(schema, schemaType, schemaType.type.name, options2)
|
|
2501
|
+
};
|
|
2502
|
+
return removeUndef(baseSchema);
|
|
2503
|
+
}
|
|
2504
|
+
function getBaseFields(schema, type, typeName, options2) {
|
|
2505
|
+
const schemaOptions = removeUndef({
|
|
2506
|
+
imagePromptField: type.options?.aiAssist?.imageInstructionField,
|
|
2507
|
+
embeddingsIndex: type.options?.aiAssist?.embeddingsIndex
|
|
2508
|
+
});
|
|
2509
|
+
return removeUndef({
|
|
2510
|
+
options: Object.keys(schemaOptions).length ? schemaOptions : void 0,
|
|
2511
|
+
values: Array.isArray(type?.options?.list) ? type?.options?.list.map(
|
|
2512
|
+
(v) => typeof v == "string" ? v : v.value ?? `${v.title}`
|
|
2513
|
+
) : void 0,
|
|
2514
|
+
of: "of" in type && typeName === "array" ? arrayOf(type, schema, options2) : void 0,
|
|
2515
|
+
to: "to" in type && typeName === "reference" ? refToTypeNames(type) : void 0,
|
|
2516
|
+
fields: "fields" in type && inlineTypes.includes(typeName) ? serializeFields(schema, type, options2) : void 0,
|
|
2517
|
+
annotations: typeName === "block" && "fields" in type ? serializeAnnotations(type, schema, options2) : void 0,
|
|
2518
|
+
inlineOf: typeName === "block" && "fields" in type ? serializeInlineOf(type, schema, options2) : void 0,
|
|
2519
|
+
hidden: typeof type.hidden == "function" ? "function" : type.hidden ? !0 : void 0,
|
|
2520
|
+
readOnly: typeof type.readOnly == "function" ? "function" : type.readOnly ? !0 : void 0
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
2523
|
+
function serializeFields(schema, schemaType, options2) {
|
|
2524
|
+
return (schemaType.fieldsets ? schemaType.fieldsets.flatMap(
|
|
2525
|
+
(fs) => fs.single ? fs.field : fs.fields.map((f) => ({
|
|
2526
|
+
...f,
|
|
2527
|
+
type: {
|
|
2528
|
+
...f.type,
|
|
2529
|
+
// if fieldset is (conditionally) hidden, the field must be considered the same way
|
|
2530
|
+
// ie, if the field does not show up in conditionalMembers, it is hidden
|
|
2531
|
+
// regardless of weather or not it is the field function or the fieldset function that hides it
|
|
2532
|
+
hidden: typeof fs.hidden == "function" ? fs.hidden : fs.hidden ? !0 : f.type.hidden
|
|
2533
|
+
}
|
|
2534
|
+
}))
|
|
2535
|
+
) : schemaType.fields).filter((f) => !["sanity.imageHotspot", "sanity.imageCrop"].includes(f.type?.name ?? "")).filter((f) => isAssistSupported(f.type)).map((field) => serializeMember(schema, field.type, field.name, options2));
|
|
2536
|
+
}
|
|
2537
|
+
function serializeMember(schema, type, name, options2) {
|
|
2538
|
+
const typeName = schema.get(type?.name) ? type.name : type.type?.name ?? "";
|
|
2539
|
+
return removeUndef({
|
|
2540
|
+
...options2?.leanFormat ? {} : { _type: assistSerializedFieldTypeName },
|
|
2541
|
+
name,
|
|
2542
|
+
type: typeName,
|
|
2543
|
+
title: type.title,
|
|
2544
|
+
...getBaseFields(schema, type, typeName, options2)
|
|
2545
|
+
});
|
|
2546
|
+
}
|
|
2547
|
+
function serializeInlineOf(blockSchemaType, schema, options2) {
|
|
2548
|
+
const childrenType = blockSchemaType.fields.find((f) => f.name === "children")?.type;
|
|
2549
|
+
if (!(!childrenType || !isArraySchemaType(childrenType)))
|
|
2550
|
+
return arrayOf(
|
|
2551
|
+
{
|
|
2552
|
+
of: childrenType.of.filter((t) => !isType(t, "span"))
|
|
2553
|
+
},
|
|
2554
|
+
schema,
|
|
2555
|
+
options2
|
|
2556
|
+
);
|
|
2557
|
+
}
|
|
2558
|
+
function serializeAnnotations(blockSchemaType, schema, options2) {
|
|
2559
|
+
const marksType = blockSchemaType.fields.find((f) => f.name === "markDefs")?.type;
|
|
2560
|
+
if (!(!marksType || !isArraySchemaType(marksType)))
|
|
2561
|
+
return arrayOf(marksType, schema, options2);
|
|
2562
|
+
}
|
|
2563
|
+
function arrayOf(arrayType, schema, options2) {
|
|
2564
|
+
return arrayType.of.filter((type) => isAssistSupported(type)).map((t) => serializeMember(schema, t, t.name, options2));
|
|
2565
|
+
}
|
|
2566
|
+
function refToTypeNames(type) {
|
|
2567
|
+
return type.to.map((t) => ({
|
|
2568
|
+
type: typed(t.name)
|
|
2569
|
+
}));
|
|
2570
|
+
}
|
|
2571
|
+
function removeUndef(obj) {
|
|
2572
|
+
return Object.keys(obj).forEach((key) => obj[key] === void 0 ? delete obj[key] : {}), obj;
|
|
2573
|
+
}
|
|
2574
|
+
function createFieldRefCache() {
|
|
2575
|
+
const byType = {};
|
|
2576
|
+
function getRefsForType(schemaType) {
|
|
2577
|
+
const documentType = schemaType.name, cached = byType[documentType];
|
|
2578
|
+
if (cached) return cached;
|
|
2579
|
+
const fieldRefs = getFieldRefs(schemaType), fieldRefsByTypePath = asFieldRefsByTypePath(fieldRefs), refs = {
|
|
2580
|
+
fieldRefs,
|
|
2581
|
+
fieldRefsByTypePath
|
|
2582
|
+
};
|
|
2583
|
+
return byType[documentType] = refs, refs;
|
|
2584
|
+
}
|
|
2585
|
+
return getRefsForType;
|
|
2586
|
+
}
|
|
2587
|
+
function AiAssistanceConfigProvider(props) {
|
|
2588
|
+
const [status, setStatus] = useState(), [error, setError] = useState(), apiClient = useApiClient(props.config?.__customApiClient), { getInstructStatus, loading: statusLoading } = useGetInstructStatus(apiClient), { initInstruct, loading: initLoading } = useInitInstruct(apiClient), schema = useSchema(), serializedTypes = useMemo(() => serializeSchema(schema, { leanFormat: !0 }), [schema]), { getFieldRefs: getFieldRefs2, getFieldRefsByTypePath } = useFieldRefGetters(schema);
|
|
2589
|
+
useEffect(() => {
|
|
2590
|
+
getInstructStatus().then((s) => setStatus(s)).catch((e) => {
|
|
2591
|
+
console.error(e), setError(e);
|
|
2592
|
+
});
|
|
2593
|
+
}, [getInstructStatus]);
|
|
2594
|
+
const init = useCallback(async () => {
|
|
2595
|
+
setError(void 0);
|
|
2596
|
+
try {
|
|
2597
|
+
await initInstruct();
|
|
2598
|
+
const status2 = await getInstructStatus();
|
|
2599
|
+
setStatus(status2);
|
|
2600
|
+
} catch (e) {
|
|
2601
|
+
console.error("Failed to init ai assistance", e), setError(e);
|
|
2602
|
+
}
|
|
2603
|
+
}, [initInstruct, getInstructStatus, setStatus]), { config, children } = props, context = useMemo(() => ({
|
|
2604
|
+
config,
|
|
2605
|
+
status,
|
|
2606
|
+
statusLoading,
|
|
2607
|
+
init,
|
|
2608
|
+
initLoading,
|
|
2609
|
+
error,
|
|
2610
|
+
serializedTypes,
|
|
2611
|
+
getFieldRefs: getFieldRefs2,
|
|
2612
|
+
getFieldRefsByTypePath
|
|
2613
|
+
}), [
|
|
2614
|
+
config,
|
|
2615
|
+
status,
|
|
2616
|
+
init,
|
|
2617
|
+
statusLoading,
|
|
2618
|
+
initLoading,
|
|
2619
|
+
error,
|
|
2620
|
+
serializedTypes,
|
|
2621
|
+
getFieldRefs2,
|
|
2622
|
+
getFieldRefsByTypePath
|
|
2623
|
+
]);
|
|
2624
|
+
return /* @__PURE__ */ jsx(AiAssistanceConfigContext.Provider, { value: context, children });
|
|
2625
|
+
}
|
|
2626
|
+
function useFieldRefGetters(schema) {
|
|
2627
|
+
return useMemo(() => {
|
|
2628
|
+
const getForSchemaType = createFieldRefCache();
|
|
2629
|
+
function getRefsForType(documentType) {
|
|
2630
|
+
const schemaType = schema.get(documentType);
|
|
2631
|
+
if (!schemaType)
|
|
2632
|
+
throw new Error(`Schema type "${documentType}" not found`);
|
|
2633
|
+
return getForSchemaType(schemaType);
|
|
2634
|
+
}
|
|
2635
|
+
return {
|
|
2636
|
+
getFieldRefs: (documentType) => getRefsForType(documentType).fieldRefs,
|
|
2637
|
+
getFieldRefsByTypePath: (documentType) => getRefsForType(documentType).fieldRefsByTypePath
|
|
2638
|
+
};
|
|
2639
|
+
}, [schema]);
|
|
2640
|
+
}
|
|
2606
2641
|
function AssistLayout(props) {
|
|
2607
2642
|
const [connectors, setConnectors] = useState([]);
|
|
2608
2643
|
return /* @__PURE__ */ jsx(AiAssistanceConfigProvider, { config: props.config, children: /* @__PURE__ */ jsx(RunInstructionProvider, { children: /* @__PURE__ */ jsx(FieldTranslationProvider, { children: /* @__PURE__ */ jsxs(ConnectorsProvider, { onConnectorsChange: setConnectors, children: [
|
|
@@ -3188,7 +3223,7 @@ function BackToInstructionListLink() {
|
|
|
3188
3223
|
}
|
|
3189
3224
|
) });
|
|
3190
3225
|
}
|
|
3191
|
-
const EMPTY_FIELDS = [];
|
|
3226
|
+
const SelectedFieldContext = createContext(void 0), SelectedFieldContextProvider = SelectedFieldContext.Provider, EMPTY_FIELDS = [];
|
|
3192
3227
|
function AssistDocumentForm(props) {
|
|
3193
3228
|
return props.readOnly ? /* @__PURE__ */ jsx(Card, { border: !0, tone: "caution", padding: 2, children: /* @__PURE__ */ jsx(Text, { size: 1, children: " You do not have sufficient permissions to manage instructions." }) }) : /* @__PURE__ */ jsx(AssistDocumentFormEditable, { ...props });
|
|
3194
3229
|
}
|
|
@@ -3688,19 +3723,25 @@ const contextDocumentSchema = defineType({
|
|
|
3688
3723
|
components: {
|
|
3689
3724
|
input: FieldRefPathInput
|
|
3690
3725
|
},
|
|
3691
|
-
validation: (rule) =>
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3726
|
+
validation: (rule) => {
|
|
3727
|
+
const getForSchemaType = createFieldRefCache();
|
|
3728
|
+
return rule.custom((value, context) => {
|
|
3729
|
+
if (!value)
|
|
3730
|
+
return "Please select a field";
|
|
3731
|
+
try {
|
|
3732
|
+
const docId = context.document?._id;
|
|
3733
|
+
if (!docId)
|
|
3734
|
+
return "Field reference cannot be used outside document inspector context. Could not resolve document id.";
|
|
3735
|
+
const targetDocType = docId.replace(new RegExp(`^${assistDocumentIdPrefix}`), ""), schema = context.schema.get(targetDocType);
|
|
3736
|
+
if (!schema)
|
|
3737
|
+
return `Field reference cannot be used outside document inspector context. Could not resolve schema: ${targetDocType}`;
|
|
3738
|
+
const { fieldRefs } = getForSchemaType(schema);
|
|
3739
|
+
return fieldRefs.find((r) => r.key === value) ? !0 : `Field with path "${value}" does not exist in the schema.`;
|
|
3740
|
+
} catch (e) {
|
|
3741
|
+
return console.error("Failed to resolve field reference", e), "Invalid field reference.";
|
|
3742
|
+
}
|
|
3743
|
+
});
|
|
3744
|
+
}
|
|
3704
3745
|
})
|
|
3705
3746
|
],
|
|
3706
3747
|
preview: {
|