@sanity/assist 4.4.6 → 4.4.8

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, isArraySchemaType, useSchema, FormFieldHeaderText, PatchEvent, unset, 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,221 +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
- const hiddenTypes = [
489
- "any",
490
- "array",
491
- "block",
492
- "boolean",
493
- "crossDatasetReference",
494
- "date",
495
- "datetime",
496
- "document",
497
- "email",
498
- "file",
499
- "globalDocumentReference",
500
- "image",
501
- "number",
502
- "object",
503
- "reference",
504
- "span",
505
- "string",
506
- "text",
507
- "url",
508
- "slug",
509
- "geopoint",
510
- "sanity.assetSourceData",
511
- "sanity.imageAsset",
512
- "sanity.fileAsset",
513
- "sanity.imageCrop",
514
- "sanity.imageHotspot",
515
- "sanity.imageMetadata",
516
- "sanity.imageDimensions",
517
- "sanity.imagePalette",
518
- "sanity.imagePaletteSwatch",
519
- assistSerializedTypeName,
520
- assistSerializedFieldTypeName,
521
- "sanity-agent.job.document"
522
- ], inlineTypes = ["document", "object", "image", "file"];
523
- function serializeSchema(schema, options2) {
524
- 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));
525
- return list.sort((a, b) => (a?.name ?? "").localeCompare(b?.name ?? "")), list;
526
- }
527
- function getSchemaStub(schemaType, schema, options2) {
528
- if (!schemaType.type?.name)
529
- throw console.error("Missing type name", schemaType.type), new Error("Type is missing name!");
530
- const baseSchema = {
531
- // we dont need type or id when we send using POST, so leave these out to save bandwidth
532
- ...options2?.leanFormat ? {} : { _id: `${assistSchemaIdPrefix}${schemaType.name}`, _type: assistSerializedTypeName },
533
- name: schemaType.name,
534
- title: schemaType.title,
535
- type: schemaType.type.name,
536
- ...getBaseFields(schema, schemaType, schemaType.type.name, options2)
537
- };
538
- return removeUndef(baseSchema);
539
- }
540
- function getBaseFields(schema, type, typeName, options2) {
541
- const schemaOptions = removeUndef({
542
- imagePromptField: type.options?.aiAssist?.imageInstructionField,
543
- embeddingsIndex: type.options?.aiAssist?.embeddingsIndex
544
- });
545
- return removeUndef({
546
- options: Object.keys(schemaOptions).length ? schemaOptions : void 0,
547
- values: Array.isArray(type?.options?.list) ? type?.options?.list.map(
548
- (v) => typeof v == "string" ? v : v.value ?? `${v.title}`
549
- ) : void 0,
550
- of: "of" in type && typeName === "array" ? arrayOf(type, schema, options2) : void 0,
551
- to: "to" in type && typeName === "reference" ? refToTypeNames(type) : void 0,
552
- fields: "fields" in type && inlineTypes.includes(typeName) ? serializeFields(schema, type, options2) : void 0,
553
- annotations: typeName === "block" && "fields" in type ? serializeAnnotations(type, schema, options2) : void 0,
554
- inlineOf: typeName === "block" && "fields" in type ? serializeInlineOf(type, schema, options2) : void 0,
555
- hidden: typeof type.hidden == "function" ? "function" : type.hidden ? !0 : void 0,
556
- readOnly: typeof type.readOnly == "function" ? "function" : type.readOnly ? !0 : void 0
557
- });
558
- }
559
- function serializeFields(schema, schemaType, options2) {
560
- return (schemaType.fieldsets ? schemaType.fieldsets.flatMap(
561
- (fs) => fs.single ? fs.field : fs.fields.map((f) => ({
562
- ...f,
563
- type: {
564
- ...f.type,
565
- // if fieldset is (conditionally) hidden, the field must be considered the same way
566
- // ie, if the field does not show up in conditionalMembers, it is hidden
567
- // regardless of weather or not it is the field function or the fieldset function that hides it
568
- hidden: typeof fs.hidden == "function" ? fs.hidden : fs.hidden ? !0 : f.type.hidden
569
- }
570
- }))
571
- ) : 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));
572
- }
573
- function serializeMember(schema, type, name, options2) {
574
- const typeName = schema.get(type?.name) ? type.name : type.type?.name ?? "";
575
- return removeUndef({
576
- ...options2?.leanFormat ? {} : { _type: assistSerializedFieldTypeName },
577
- name,
578
- type: typeName,
579
- title: type.title,
580
- ...getBaseFields(schema, type, typeName, options2)
581
- });
582
- }
583
- function serializeInlineOf(blockSchemaType, schema, options2) {
584
- const childrenType = blockSchemaType.fields.find((f) => f.name === "children")?.type;
585
- if (!(!childrenType || !isArraySchemaType(childrenType)))
586
- return arrayOf(
587
- {
588
- of: childrenType.of.filter((t) => !isType(t, "span"))
589
- },
590
- schema,
591
- options2
592
- );
593
- }
594
- function serializeAnnotations(blockSchemaType, schema, options2) {
595
- const marksType = blockSchemaType.fields.find((f) => f.name === "markDefs")?.type;
596
- if (!(!marksType || !isArraySchemaType(marksType)))
597
- return arrayOf(marksType, schema, options2);
598
- }
599
- function arrayOf(arrayType, schema, options2) {
600
- return arrayType.of.filter((type) => isAssistSupported(type)).map((t) => serializeMember(schema, t, t.name, options2));
601
- }
602
- function refToTypeNames(type) {
603
- return type.to.map((t) => ({
604
- type: typed(t.name)
605
- }));
606
- }
607
- function removeUndef(obj) {
608
- return Object.keys(obj).forEach((key) => obj[key] === void 0 ? delete obj[key] : {}), obj;
609
- }
610
395
  const AiAssistanceConfigContext = createContext({});
611
396
  function useAiAssistanceConfig() {
612
397
  const context = useContext(AiAssistanceConfigContext);
@@ -617,33 +402,6 @@ function useAiAssistanceConfig() {
617
402
  function useSerializedTypes() {
618
403
  return useAiAssistanceConfig().serializedTypes;
619
404
  }
620
- function AiAssistanceConfigProvider(props) {
621
- 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]);
622
- useEffect(() => {
623
- getInstructStatus().then((s) => setStatus(s)).catch((e) => {
624
- console.error(e), setError(e);
625
- });
626
- }, [getInstructStatus]);
627
- const init = useCallback(async () => {
628
- setError(void 0);
629
- try {
630
- await initInstruct();
631
- const status2 = await getInstructStatus();
632
- setStatus(status2);
633
- } catch (e) {
634
- console.error("Failed to init ai assistance", e), setError(e);
635
- }
636
- }, [initInstruct, getInstructStatus, setStatus]), { config, children } = props, context = useMemo(() => ({
637
- config,
638
- status,
639
- statusLoading,
640
- init,
641
- initLoading,
642
- error,
643
- serializedTypes
644
- }), [config, status, init, statusLoading, initLoading, error, serializedTypes]);
645
- return /* @__PURE__ */ jsx(AiAssistanceConfigContext.Provider, { value: context, children });
646
- }
647
405
  const basePath = "/assist/tasks/instruction", API_VERSION_WITH_EXTENDED_TYPES = "2025-04-01";
648
406
  function canUseAssist(status) {
649
407
  return status?.enabled && status.initialized && status.validToken;
@@ -1022,19 +780,105 @@ function useDraftDelayedTask(args) {
1022
780
  [setQueuedArgs, documentOnChange]
1023
781
  );
1024
782
  }
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;
791
+ }
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
805
+ };
806
+ }
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];
817
+ });
818
+ }
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;
830
+ });
831
+ }
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;
847
+ }
848
+ function patchableKey(pathKey) {
849
+ return pathKey.replace(/[=]=/g, ":").replace(/[[\]]/g, "|").replace(/"/g, "");
850
+ }
851
+ function useTypePath(doc, pathString) {
852
+ return useMemo(() => getTypePath(doc, pathString), [doc, pathString]);
853
+ }
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]);
860
+ }
861
+ function getFieldTitle(field) {
862
+ const schemaType = field?.schemaType;
863
+ return field?.title ?? schemaType?.title ?? schemaType?.name ?? "Untitled";
864
+ }
865
+ function useAiPaneRouter() {
866
+ const paneRouter = usePaneRouter();
867
+ return useMemo(
868
+ () => ({ ...paneRouter, params: paneRouter.params ?? {} }),
869
+ [paneRouter]
870
+ );
871
+ }
1025
872
  function useAssistDocumentContextValue(documentId, documentType) {
1026
- const schema = useSchema(), documentSchemaType = useMemo(() => {
873
+ const schema = useSchema(), { getFieldRefs: getFieldRefs2, getFieldRefsByTypePath } = useAiAssistanceConfig(), documentSchemaType = useMemo(() => {
1027
874
  const schemaType = schema.get(documentType);
1028
875
  if (!schemaType)
1029
876
  throw new Error(`Schema type "${documentType}" not found`);
1030
877
  return schemaType;
1031
- }, [documentType, schema]), { fieldRefs, fieldRefsByTypePath } = useMemo(() => {
1032
- const fieldRefs2 = getFieldRefs(documentSchemaType), fieldRefsByTypePath2 = asFieldRefsByTypePath(fieldRefs2);
1033
- return {
1034
- fieldRefs: fieldRefs2,
1035
- fieldRefsByTypePath: fieldRefsByTypePath2
1036
- };
1037
- }, [documentSchemaType]), {
878
+ }, [documentType, schema]), { fieldRefs, fieldRefsByTypePath } = useMemo(() => ({
879
+ fieldRefs: getFieldRefs2(documentType),
880
+ fieldRefsByTypePath: getFieldRefsByTypePath(documentType)
881
+ }), [getFieldRefs2, getFieldRefsByTypePath, documentType]), {
1038
882
  openInspector,
1039
883
  closeInspector,
1040
884
  inspector,
@@ -1526,8 +1370,9 @@ function conditionalState(memberState) {
1526
1370
  return {
1527
1371
  path: pathToString(memberState.path),
1528
1372
  readOnly: !!memberState.readOnly,
1373
+ // Use actual form state readOnly value
1529
1374
  hidden: !1,
1530
- // if its in members, its not hidden
1375
+ // If it's in form state members, it's not hidden
1531
1376
  conditional: isConditional(memberState.schemaType)
1532
1377
  };
1533
1378
  }
@@ -1562,7 +1407,7 @@ function extractConditionalPaths(node, maxDepth2) {
1562
1407
  ), innerFields = extractConditionalPaths(member.fieldSet, maxDepth2).map((f) => ({
1563
1408
  ...f,
1564
1409
  // if fieldset is conditional, visible fields must also be considered conditional
1565
- conditional: conditionalFieldset ?? f.conditional
1410
+ conditional: conditionalFieldset || f.conditional
1566
1411
  }));
1567
1412
  return [...acc, ...innerFields];
1568
1413
  }
@@ -1601,7 +1446,10 @@ function InspectorOnboarding(props) {
1601
1446
  ] }) }) });
1602
1447
  }
1603
1448
  function FieldAutocomplete(props) {
1604
- const { id, schemaType, fieldPath, onSelect, includeDocument, filter: filter2 } = props, fieldRefs = useMemo(() => includeDocument ? getFieldRefsWithDocument(schemaType) : getFieldRefs(schemaType), [schemaType, includeDocument]), currentField = useMemo(
1449
+ const { id, schemaType, fieldPath, onSelect, includeDocument, filter: filter2 } = props, { getFieldRefs: getFieldRefs2 } = useAiAssistanceConfig(), fieldRefs = useMemo(() => {
1450
+ const refs = getFieldRefs2(schemaType.name);
1451
+ return includeDocument ? [getDocumentFieldRef(schemaType), ...refs] : refs;
1452
+ }, [schemaType, includeDocument, getFieldRefs2]), currentField = useMemo(
1605
1453
  () => fieldRefs.find((f) => f.key === fieldPath),
1606
1454
  [fieldPath, fieldRefs]
1607
1455
  ), autocompleteOptions = useMemo(
@@ -2602,6 +2450,195 @@ function FromLanguageRadio(props) {
2602
2450
  /* @__PURE__ */ jsx(Text, { children: radioLanguage.title ?? radioLanguage.id })
2603
2451
  ] }, langId);
2604
2452
  }
2453
+ const hiddenTypes = [
2454
+ "any",
2455
+ "array",
2456
+ "block",
2457
+ "boolean",
2458
+ "crossDatasetReference",
2459
+ "date",
2460
+ "datetime",
2461
+ "document",
2462
+ "email",
2463
+ "file",
2464
+ "globalDocumentReference",
2465
+ "image",
2466
+ "number",
2467
+ "object",
2468
+ "reference",
2469
+ "span",
2470
+ "string",
2471
+ "text",
2472
+ "url",
2473
+ "slug",
2474
+ "geopoint",
2475
+ "sanity.assetSourceData",
2476
+ "sanity.imageAsset",
2477
+ "sanity.fileAsset",
2478
+ "sanity.imageCrop",
2479
+ "sanity.imageHotspot",
2480
+ "sanity.imageMetadata",
2481
+ "sanity.imageDimensions",
2482
+ "sanity.imagePalette",
2483
+ "sanity.imagePaletteSwatch",
2484
+ assistSerializedTypeName,
2485
+ assistSerializedFieldTypeName,
2486
+ "sanity-agent.job.document"
2487
+ ], inlineTypes = ["document", "object", "image", "file"];
2488
+ function serializeSchema(schema, options2) {
2489
+ 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));
2490
+ return list.sort((a, b) => (a?.name ?? "").localeCompare(b?.name ?? "")), list;
2491
+ }
2492
+ function getSchemaStub(schemaType, schema, options2) {
2493
+ if (!schemaType.type?.name)
2494
+ throw console.error("Missing type name", schemaType.type), new Error("Type is missing name!");
2495
+ const baseSchema = {
2496
+ // we dont need type or id when we send using POST, so leave these out to save bandwidth
2497
+ ...options2?.leanFormat ? {} : { _id: `${assistSchemaIdPrefix}${schemaType.name}`, _type: assistSerializedTypeName },
2498
+ name: schemaType.name,
2499
+ title: schemaType.title,
2500
+ type: schemaType.type.name,
2501
+ ...getBaseFields(schema, schemaType, schemaType.type.name, options2)
2502
+ };
2503
+ return removeUndef(baseSchema);
2504
+ }
2505
+ function getBaseFields(schema, type, typeName, options2) {
2506
+ const schemaOptions = removeUndef({
2507
+ imagePromptField: type.options?.aiAssist?.imageInstructionField,
2508
+ embeddingsIndex: type.options?.aiAssist?.embeddingsIndex
2509
+ });
2510
+ return removeUndef({
2511
+ options: Object.keys(schemaOptions).length ? schemaOptions : void 0,
2512
+ values: Array.isArray(type?.options?.list) ? type?.options?.list.map(
2513
+ (v) => typeof v == "string" ? v : v.value ?? `${v.title}`
2514
+ ) : void 0,
2515
+ of: "of" in type && typeName === "array" ? arrayOf(type, schema, options2) : void 0,
2516
+ to: "to" in type && typeName === "reference" ? refToTypeNames(type) : void 0,
2517
+ fields: "fields" in type && inlineTypes.includes(typeName) ? serializeFields(schema, type, options2) : void 0,
2518
+ annotations: typeName === "block" && "fields" in type ? serializeAnnotations(type, schema, options2) : void 0,
2519
+ inlineOf: typeName === "block" && "fields" in type ? serializeInlineOf(type, schema, options2) : void 0,
2520
+ hidden: typeof type.hidden == "function" ? "function" : type.hidden ? !0 : void 0,
2521
+ readOnly: typeof type.readOnly == "function" ? "function" : type.readOnly ? !0 : void 0
2522
+ });
2523
+ }
2524
+ function serializeFields(schema, schemaType, options2) {
2525
+ return (schemaType.fieldsets ? schemaType.fieldsets.flatMap(
2526
+ (fs) => fs.single ? fs.field : fs.fields.map((f) => ({
2527
+ ...f,
2528
+ type: {
2529
+ ...f.type,
2530
+ // if fieldset is (conditionally) hidden, the field must be considered the same way
2531
+ // ie, if the field does not show up in conditionalMembers, it is hidden
2532
+ // regardless of weather or not it is the field function or the fieldset function that hides it
2533
+ hidden: typeof fs.hidden == "function" ? fs.hidden : fs.hidden ? !0 : f.type.hidden
2534
+ }
2535
+ }))
2536
+ ) : 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));
2537
+ }
2538
+ function serializeMember(schema, type, name, options2) {
2539
+ const typeName = schema.get(type?.name) ? type.name : type.type?.name ?? "";
2540
+ return removeUndef({
2541
+ ...options2?.leanFormat ? {} : { _type: assistSerializedFieldTypeName },
2542
+ name,
2543
+ type: typeName,
2544
+ title: type.title,
2545
+ ...getBaseFields(schema, type, typeName, options2)
2546
+ });
2547
+ }
2548
+ function serializeInlineOf(blockSchemaType, schema, options2) {
2549
+ const childrenType = blockSchemaType.fields.find((f) => f.name === "children")?.type;
2550
+ if (!(!childrenType || !isArraySchemaType(childrenType)))
2551
+ return arrayOf(
2552
+ {
2553
+ of: childrenType.of.filter((t) => !isType(t, "span"))
2554
+ },
2555
+ schema,
2556
+ options2
2557
+ );
2558
+ }
2559
+ function serializeAnnotations(blockSchemaType, schema, options2) {
2560
+ const marksType = blockSchemaType.fields.find((f) => f.name === "markDefs")?.type;
2561
+ if (!(!marksType || !isArraySchemaType(marksType)))
2562
+ return arrayOf(marksType, schema, options2);
2563
+ }
2564
+ function arrayOf(arrayType, schema, options2) {
2565
+ return arrayType.of.filter((type) => isAssistSupported(type)).map((t) => serializeMember(schema, t, t.name, options2));
2566
+ }
2567
+ function refToTypeNames(type) {
2568
+ return type.to.map((t) => ({
2569
+ type: typed(t.name)
2570
+ }));
2571
+ }
2572
+ function removeUndef(obj) {
2573
+ return Object.keys(obj).forEach((key) => obj[key] === void 0 ? delete obj[key] : {}), obj;
2574
+ }
2575
+ function createFieldRefCache() {
2576
+ const byType = {};
2577
+ function getRefsForType(schemaType) {
2578
+ const documentType = schemaType.name, cached = byType[documentType];
2579
+ if (cached) return cached;
2580
+ const fieldRefs = getFieldRefs(schemaType), fieldRefsByTypePath = asFieldRefsByTypePath(fieldRefs), refs = {
2581
+ fieldRefs,
2582
+ fieldRefsByTypePath
2583
+ };
2584
+ return byType[documentType] = refs, refs;
2585
+ }
2586
+ return getRefsForType;
2587
+ }
2588
+ function AiAssistanceConfigProvider(props) {
2589
+ 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);
2590
+ useEffect(() => {
2591
+ getInstructStatus().then((s) => setStatus(s)).catch((e) => {
2592
+ console.error(e), setError(e);
2593
+ });
2594
+ }, [getInstructStatus]);
2595
+ const init = useCallback(async () => {
2596
+ setError(void 0);
2597
+ try {
2598
+ await initInstruct();
2599
+ const status2 = await getInstructStatus();
2600
+ setStatus(status2);
2601
+ } catch (e) {
2602
+ console.error("Failed to init ai assistance", e), setError(e);
2603
+ }
2604
+ }, [initInstruct, getInstructStatus, setStatus]), { config, children } = props, context = useMemo(() => ({
2605
+ config,
2606
+ status,
2607
+ statusLoading,
2608
+ init,
2609
+ initLoading,
2610
+ error,
2611
+ serializedTypes,
2612
+ getFieldRefs: getFieldRefs2,
2613
+ getFieldRefsByTypePath
2614
+ }), [
2615
+ config,
2616
+ status,
2617
+ init,
2618
+ statusLoading,
2619
+ initLoading,
2620
+ error,
2621
+ serializedTypes,
2622
+ getFieldRefs2,
2623
+ getFieldRefsByTypePath
2624
+ ]);
2625
+ return /* @__PURE__ */ jsx(AiAssistanceConfigContext.Provider, { value: context, children });
2626
+ }
2627
+ function useFieldRefGetters(schema) {
2628
+ return useMemo(() => {
2629
+ const getForSchemaType = createFieldRefCache();
2630
+ function getRefsForType(documentType) {
2631
+ const schemaType = schema.get(documentType);
2632
+ if (!schemaType)
2633
+ throw new Error(`Schema type "${documentType}" not found`);
2634
+ return getForSchemaType(schemaType);
2635
+ }
2636
+ return {
2637
+ getFieldRefs: (documentType) => getRefsForType(documentType).fieldRefs,
2638
+ getFieldRefsByTypePath: (documentType) => getRefsForType(documentType).fieldRefsByTypePath
2639
+ };
2640
+ }, [schema]);
2641
+ }
2605
2642
  function AssistLayout(props) {
2606
2643
  const [connectors, setConnectors] = useState([]);
2607
2644
  return /* @__PURE__ */ jsx(AiAssistanceConfigProvider, { config: props.config, children: /* @__PURE__ */ jsx(RunInstructionProvider, { children: /* @__PURE__ */ jsx(FieldTranslationProvider, { children: /* @__PURE__ */ jsxs(ConnectorsProvider, { onConnectorsChange: setConnectors, children: [
@@ -3187,7 +3224,7 @@ function BackToInstructionListLink() {
3187
3224
  }
3188
3225
  ) });
3189
3226
  }
3190
- const EMPTY_FIELDS = [];
3227
+ const SelectedFieldContext = createContext(void 0), SelectedFieldContextProvider = SelectedFieldContext.Provider, EMPTY_FIELDS = [];
3191
3228
  function AssistDocumentForm(props) {
3192
3229
  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 });
3193
3230
  }
@@ -3687,19 +3724,25 @@ const contextDocumentSchema = defineType({
3687
3724
  components: {
3688
3725
  input: FieldRefPathInput
3689
3726
  },
3690
- validation: (rule) => rule.custom((value, context) => {
3691
- if (!value)
3692
- return "Please select a field";
3693
- try {
3694
- const docId = context.document?._id;
3695
- if (!docId)
3696
- return "Field reference cannot be used outside document inspector context. Could not resolve document id.";
3697
- const targetDocType = docId.replace(new RegExp(`^${assistDocumentIdPrefix}`), ""), schema = context.schema.get(targetDocType);
3698
- 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}`;
3699
- } catch (e) {
3700
- return console.error("Failed to resolve field reference", e), "Invalid field reference.";
3701
- }
3702
- })
3727
+ validation: (rule) => {
3728
+ const getForSchemaType = createFieldRefCache();
3729
+ return rule.custom((value, context) => {
3730
+ if (!value)
3731
+ return "Please select a field";
3732
+ try {
3733
+ const docId = context.document?._id;
3734
+ if (!docId)
3735
+ return "Field reference cannot be used outside document inspector context. Could not resolve document id.";
3736
+ const targetDocType = docId.replace(new RegExp(`^${assistDocumentIdPrefix}`), ""), schema = context.schema.get(targetDocType);
3737
+ if (!schema)
3738
+ return `Field reference cannot be used outside document inspector context. Could not resolve schema: ${targetDocType}`;
3739
+ const { fieldRefs } = getForSchemaType(schema);
3740
+ return fieldRefs.find((r) => r.key === value) ? !0 : `Field with path "${value}" does not exist in the schema.`;
3741
+ } catch (e) {
3742
+ return console.error("Failed to resolve field reference", e), "Invalid field reference.";
3743
+ }
3744
+ });
3745
+ }
3703
3746
  })
3704
3747
  ],
3705
3748
  preview: {