@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.mjs 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, isObjectSchemaType, stringToPath, isKeySegment, FormFieldHeaderText, PatchEvent, unset, isArraySchemaType, useSchema, getVersionId, getDraftId, useColorSchemeValue, 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";
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, 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";
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 AiAssistanceConfigProvider(props) {
496
- const [status, setStatus] = useState(), [error, setError] = useState(), apiClient = useApiClient(props.config?.__customApiClient), { getInstructStatus, loading: statusLoading } = useGetInstructStatus(apiClient), { initInstruct, loading: initLoading } = useInitInstruct(apiClient);
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 hiddenTypes = [
900
- "any",
901
- "array",
902
- "block",
903
- "boolean",
904
- "crossDatasetReference",
905
- "date",
906
- "datetime",
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 getSchemaStub(schemaType, schema, options2) {
939
- if (!schemaType.type?.name)
940
- throw console.error("Missing type name", schemaType.type), new Error("Type is missing name!");
941
- const baseSchema = {
942
- // we dont need type or id when we send using POST, so leave these out to save bandwidth
943
- ...options2?.leanFormat ? {} : { _id: `${assistSchemaIdPrefix}${schemaType.name}`, _type: assistSerializedTypeName },
944
- name: schemaType.name,
945
- title: schemaType.title,
946
- type: schemaType.type.name,
947
- ...getBaseFields(schema, schemaType, schemaType.type.name, options2)
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 getBaseFields(schema, type, typeName, options2) {
952
- const schemaOptions = removeUndef({
953
- imagePromptField: type.options?.aiAssist?.imageInstructionField,
954
- embeddingsIndex: type.options?.aiAssist?.embeddingsIndex
955
- });
956
- return removeUndef({
957
- options: Object.keys(schemaOptions).length ? schemaOptions : void 0,
958
- values: Array.isArray(type?.options?.list) ? type?.options?.list.map(
959
- (v) => typeof v == "string" ? v : v.value ?? `${v.title}`
960
- ) : void 0,
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 serializeFields(schema, schemaType, options2) {
971
- return (schemaType.fieldsets ? schemaType.fieldsets.flatMap(
972
- (fs) => fs.single ? fs.field : fs.fields.map((f) => ({
973
- ...f,
974
- type: {
975
- ...f.type,
976
- // if fieldset is (conditionally) hidden, the field must be considered the same way
977
- // ie, if the field does not show up in conditionalMembers, it is hidden
978
- // regardless of weather or not it is the field function or the fieldset function that hides it
979
- hidden: typeof fs.hidden == "function" ? fs.hidden : fs.hidden ? !0 : f.type.hidden
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 serializeInlineOf(blockSchemaType, schema, options2) {
995
- const childrenType = blockSchemaType.fields.find((f) => f.name === "children")?.type;
996
- if (!(!childrenType || !isArraySchemaType(childrenType)))
997
- return arrayOf(
998
- {
999
- of: childrenType.of.filter((t) => !isType(t, "span"))
1000
- },
1001
- schema,
1002
- options2
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 serializeAnnotations(blockSchemaType, schema, options2) {
1006
- const marksType = blockSchemaType.fields.find((f) => f.name === "markDefs")?.type;
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 arrayOf(arrayType, schema, options2) {
1011
- return arrayType.of.filter((type) => isAssistSupported(type)).map((t) => serializeMember(schema, t, t.name, options2));
851
+ function useTypePath(doc, pathString) {
852
+ return useMemo(() => getTypePath(doc, pathString), [doc, pathString]);
1012
853
  }
1013
- function refToTypeNames(type) {
1014
- return type.to.map((t) => ({
1015
- type: typed(t.name)
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 removeUndef(obj) {
1019
- return Object.keys(obj).forEach((key) => obj[key] === void 0 ? delete obj[key] : {}), obj;
861
+ function getFieldTitle(field) {
862
+ const schemaType = field?.schemaType;
863
+ return field?.title ?? schemaType?.title ?? schemaType?.name ?? "Untitled";
1020
864
  }
1021
- function useSerializedTypes() {
1022
- return useAssistDocumentContext().serializedTypes;
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]), serializedTypes = useMemo(() => serializeSchema(schema, { leanFormat: !0 }), [schema]), { fieldRefs, fieldRefsByTypePath } = useMemo(() => {
1031
- const fieldRefs2 = getFieldRefs(documentSchemaType), fieldRefsByTypePath2 = asFieldRefsByTypePath(fieldRefs2);
1032
- return {
1033
- fieldRefs: fieldRefs2,
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, fieldRefs = useMemo(() => includeDocument ? getFieldRefsWithDocument(schemaType) : getFieldRefs(schemaType), [schemaType, includeDocument]), currentField = useMemo(
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) => rule.custom((value, context) => {
3692
- if (!value)
3693
- return "Please select a field";
3694
- try {
3695
- const docId = context.document?._id;
3696
- if (!docId)
3697
- return "Field reference cannot be used outside document inspector context. Could not resolve document id.";
3698
- const targetDocType = docId.replace(new RegExp(`^${assistDocumentIdPrefix}`), ""), schema = context.schema.get(targetDocType);
3699
- return schema ? getFieldRefsWithDocument(schema).find((r) => r.key === value) ? !0 : `Field with path "${value}" does not exist in the schema.` : `Field reference cannot be used outside document inspector context. Could not resolve schema: ${targetDocType}`;
3700
- } catch (e) {
3701
- return console.error("Failed to resolve field reference", e), "Invalid field reference.";
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: {