@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.d.mts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.esm.js +312 -269
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +310 -267
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +312 -269
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/assistDocument/hooks/useAssistDocumentContextValue.tsx +6 -7
- package/src/assistInspector/FieldAutocomplete.tsx +9 -4
- package/src/assistInspector/helpers.ts +15 -26
- package/src/assistLayout/AiAssistanceConfigContext.tsx +5 -67
- 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/helpers/conditionalMembers.test.ts +43 -0
- package/src/helpers/conditionalMembers.ts +3 -3
- package/src/schemas/assistDocumentSchema.tsx +9 -6
- package/src/schemas/typeDefExtensions.ts +1 -0
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,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
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
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
|
-
//
|
|
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
|
|
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,
|
|
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) =>
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
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: {
|