@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.js
CHANGED
|
@@ -385,221 +385,6 @@ function useAssistDocumentContext() {
|
|
|
385
385
|
throw new Error("AssistDocumentContext value is missing");
|
|
386
386
|
return context;
|
|
387
387
|
}
|
|
388
|
-
const SelectedFieldContext = react.createContext(void 0), SelectedFieldContextProvider = SelectedFieldContext.Provider, maxDepth = 6;
|
|
389
|
-
function getTypeIcon(schemaType) {
|
|
390
|
-
let t = schemaType;
|
|
391
|
-
for (; t; ) {
|
|
392
|
-
if (t.icon) return t.icon;
|
|
393
|
-
t = t.type;
|
|
394
|
-
}
|
|
395
|
-
return isType(schemaType, "slug") ? icons.LinkIcon : isType(schemaType, "image") ? icons.ImageIcon : schemaType.jsonType === "array" && isPortableTextArray(schemaType) ? icons.BlockContentIcon : schemaType.jsonType === "array" ? icons.OlistIcon : schemaType.jsonType === "object" ? icons.BlockquoteIcon : schemaType.jsonType === "string" ? icons.StringIcon : icons.DocumentIcon;
|
|
396
|
-
}
|
|
397
|
-
function asFieldRefsByTypePath(fieldRefs) {
|
|
398
|
-
return fieldRefs.reduce(
|
|
399
|
-
(acc, ref) => ({ ...acc, [ref.key]: ref }),
|
|
400
|
-
{}
|
|
401
|
-
);
|
|
402
|
-
}
|
|
403
|
-
function getFieldRefsWithDocument(schemaType) {
|
|
404
|
-
const fields = getFieldRefs(schemaType);
|
|
405
|
-
return [
|
|
406
|
-
{
|
|
407
|
-
key: documentRootKey,
|
|
408
|
-
icon: schemaType.icon ?? icons.DocumentIcon,
|
|
409
|
-
title: "The entire document",
|
|
410
|
-
path: [],
|
|
411
|
-
schemaType
|
|
412
|
-
},
|
|
413
|
-
...fields
|
|
414
|
-
];
|
|
415
|
-
}
|
|
416
|
-
function getFieldRefs(schemaType, parent, depth = 0) {
|
|
417
|
-
return depth >= maxDepth ? [] : schemaType.fields.filter((f) => !f.name.startsWith("_")).flatMap((field) => {
|
|
418
|
-
const path = parent ? [...parent.path, field.name] : [field.name], title = field.type.title ?? field.name, fieldRef = {
|
|
419
|
-
key: patchableKey(sanity.pathToString(path)),
|
|
420
|
-
path,
|
|
421
|
-
title: parent ? [parent.title, title].join(" / ") : title,
|
|
422
|
-
schemaType: field.type,
|
|
423
|
-
icon: getTypeIcon(field.type)
|
|
424
|
-
}, fields = field.type.jsonType === "object" ? getFieldRefs(field.type, fieldRef, depth + 1) : [], syntheticFields = field.type.jsonType === "array" ? getSyntheticFields(field.type, fieldRef, depth + 1) : [];
|
|
425
|
-
return isAssistSupported(field.type) ? [fieldRef, ...fields, ...syntheticFields] : [...fields, ...syntheticFields];
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
function getSyntheticFields(schemaType, parent, depth = 0) {
|
|
429
|
-
return depth >= maxDepth ? [] : schemaType.of.filter((itemType) => !isType(itemType, "block")).flatMap((itemType) => {
|
|
430
|
-
const segment = { _key: itemType.name }, title = itemType.title ?? itemType.name, path = parent ? [...parent.path, segment] : [segment], fieldRef = {
|
|
431
|
-
key: patchableKey(sanity.pathToString(path)),
|
|
432
|
-
path,
|
|
433
|
-
title: parent ? [parent.title, title].join(" / ") : title,
|
|
434
|
-
schemaType: itemType,
|
|
435
|
-
icon: getTypeIcon(itemType),
|
|
436
|
-
synthetic: !0
|
|
437
|
-
}, fields = itemType.jsonType === "object" ? getFieldRefs(itemType, fieldRef, depth + 1) : [];
|
|
438
|
-
return isAssistSupported(itemType) ? [fieldRef, ...fields] : fields;
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
function getTypePath(doc, pathString) {
|
|
442
|
-
if (!pathString)
|
|
443
|
-
return;
|
|
444
|
-
const path = sanity.stringToPath(pathString), currentPath = [];
|
|
445
|
-
let valid = !0;
|
|
446
|
-
const syntheticPath = path.map((segment) => {
|
|
447
|
-
if (currentPath.push(segment), sanity.isKeySegment(segment)) {
|
|
448
|
-
const match = mutator.extractWithPath(sanity.pathToString(currentPath), doc)[0], value = match?.value;
|
|
449
|
-
if (match && value && typeof value == "object" && "_type" in value)
|
|
450
|
-
return { _key: value._type };
|
|
451
|
-
valid = !1;
|
|
452
|
-
}
|
|
453
|
-
return segment;
|
|
454
|
-
});
|
|
455
|
-
return valid ? patchableKey(sanity.pathToString(syntheticPath)) : void 0;
|
|
456
|
-
}
|
|
457
|
-
function patchableKey(pathKey) {
|
|
458
|
-
return pathKey.replace(/[=]=/g, ":").replace(/[[\]]/g, "|").replace(/"/g, "");
|
|
459
|
-
}
|
|
460
|
-
function useTypePath(doc, pathString) {
|
|
461
|
-
return react.useMemo(() => getTypePath(doc, pathString), [doc, pathString]);
|
|
462
|
-
}
|
|
463
|
-
function useSelectedField(documentSchemaType, path) {
|
|
464
|
-
const selectableFields = react.useMemo(
|
|
465
|
-
() => documentSchemaType && sanity.isObjectSchemaType(documentSchemaType) ? getFieldRefsWithDocument(documentSchemaType) : [],
|
|
466
|
-
[documentSchemaType]
|
|
467
|
-
);
|
|
468
|
-
return react.useMemo(() => path ? selectableFields?.find((f) => f.key === path) : void 0, [selectableFields, path]);
|
|
469
|
-
}
|
|
470
|
-
function getFieldTitle(field) {
|
|
471
|
-
const schemaType = field?.schemaType;
|
|
472
|
-
return field?.title ?? schemaType?.title ?? schemaType?.name ?? "Untitled";
|
|
473
|
-
}
|
|
474
|
-
function useAiPaneRouter() {
|
|
475
|
-
const paneRouter = structure.usePaneRouter();
|
|
476
|
-
return react.useMemo(
|
|
477
|
-
() => ({ ...paneRouter, params: paneRouter.params ?? {} }),
|
|
478
|
-
[paneRouter]
|
|
479
|
-
);
|
|
480
|
-
}
|
|
481
|
-
const hiddenTypes = [
|
|
482
|
-
"any",
|
|
483
|
-
"array",
|
|
484
|
-
"block",
|
|
485
|
-
"boolean",
|
|
486
|
-
"crossDatasetReference",
|
|
487
|
-
"date",
|
|
488
|
-
"datetime",
|
|
489
|
-
"document",
|
|
490
|
-
"email",
|
|
491
|
-
"file",
|
|
492
|
-
"globalDocumentReference",
|
|
493
|
-
"image",
|
|
494
|
-
"number",
|
|
495
|
-
"object",
|
|
496
|
-
"reference",
|
|
497
|
-
"span",
|
|
498
|
-
"string",
|
|
499
|
-
"text",
|
|
500
|
-
"url",
|
|
501
|
-
"slug",
|
|
502
|
-
"geopoint",
|
|
503
|
-
"sanity.assetSourceData",
|
|
504
|
-
"sanity.imageAsset",
|
|
505
|
-
"sanity.fileAsset",
|
|
506
|
-
"sanity.imageCrop",
|
|
507
|
-
"sanity.imageHotspot",
|
|
508
|
-
"sanity.imageMetadata",
|
|
509
|
-
"sanity.imageDimensions",
|
|
510
|
-
"sanity.imagePalette",
|
|
511
|
-
"sanity.imagePaletteSwatch",
|
|
512
|
-
assistSerializedTypeName,
|
|
513
|
-
assistSerializedFieldTypeName,
|
|
514
|
-
"sanity-agent.job.document"
|
|
515
|
-
], inlineTypes = ["document", "object", "image", "file"];
|
|
516
|
-
function serializeSchema(schema, options2) {
|
|
517
|
-
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));
|
|
518
|
-
return list.sort((a, b) => (a?.name ?? "").localeCompare(b?.name ?? "")), list;
|
|
519
|
-
}
|
|
520
|
-
function getSchemaStub(schemaType, schema, options2) {
|
|
521
|
-
if (!schemaType.type?.name)
|
|
522
|
-
throw console.error("Missing type name", schemaType.type), new Error("Type is missing name!");
|
|
523
|
-
const baseSchema = {
|
|
524
|
-
// we dont need type or id when we send using POST, so leave these out to save bandwidth
|
|
525
|
-
...options2?.leanFormat ? {} : { _id: `${assistSchemaIdPrefix}${schemaType.name}`, _type: assistSerializedTypeName },
|
|
526
|
-
name: schemaType.name,
|
|
527
|
-
title: schemaType.title,
|
|
528
|
-
type: schemaType.type.name,
|
|
529
|
-
...getBaseFields(schema, schemaType, schemaType.type.name, options2)
|
|
530
|
-
};
|
|
531
|
-
return removeUndef(baseSchema);
|
|
532
|
-
}
|
|
533
|
-
function getBaseFields(schema, type, typeName, options2) {
|
|
534
|
-
const schemaOptions = removeUndef({
|
|
535
|
-
imagePromptField: type.options?.aiAssist?.imageInstructionField,
|
|
536
|
-
embeddingsIndex: type.options?.aiAssist?.embeddingsIndex
|
|
537
|
-
});
|
|
538
|
-
return removeUndef({
|
|
539
|
-
options: Object.keys(schemaOptions).length ? schemaOptions : void 0,
|
|
540
|
-
values: Array.isArray(type?.options?.list) ? type?.options?.list.map(
|
|
541
|
-
(v) => typeof v == "string" ? v : v.value ?? `${v.title}`
|
|
542
|
-
) : void 0,
|
|
543
|
-
of: "of" in type && typeName === "array" ? arrayOf(type, schema, options2) : void 0,
|
|
544
|
-
to: "to" in type && typeName === "reference" ? refToTypeNames(type) : void 0,
|
|
545
|
-
fields: "fields" in type && inlineTypes.includes(typeName) ? serializeFields(schema, type, options2) : void 0,
|
|
546
|
-
annotations: typeName === "block" && "fields" in type ? serializeAnnotations(type, schema, options2) : void 0,
|
|
547
|
-
inlineOf: typeName === "block" && "fields" in type ? serializeInlineOf(type, schema, options2) : void 0,
|
|
548
|
-
hidden: typeof type.hidden == "function" ? "function" : type.hidden ? !0 : void 0,
|
|
549
|
-
readOnly: typeof type.readOnly == "function" ? "function" : type.readOnly ? !0 : void 0
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
function serializeFields(schema, schemaType, options2) {
|
|
553
|
-
return (schemaType.fieldsets ? schemaType.fieldsets.flatMap(
|
|
554
|
-
(fs) => fs.single ? fs.field : fs.fields.map((f) => ({
|
|
555
|
-
...f,
|
|
556
|
-
type: {
|
|
557
|
-
...f.type,
|
|
558
|
-
// if fieldset is (conditionally) hidden, the field must be considered the same way
|
|
559
|
-
// ie, if the field does not show up in conditionalMembers, it is hidden
|
|
560
|
-
// regardless of weather or not it is the field function or the fieldset function that hides it
|
|
561
|
-
hidden: typeof fs.hidden == "function" ? fs.hidden : fs.hidden ? !0 : f.type.hidden
|
|
562
|
-
}
|
|
563
|
-
}))
|
|
564
|
-
) : 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));
|
|
565
|
-
}
|
|
566
|
-
function serializeMember(schema, type, name, options2) {
|
|
567
|
-
const typeName = schema.get(type?.name) ? type.name : type.type?.name ?? "";
|
|
568
|
-
return removeUndef({
|
|
569
|
-
...options2?.leanFormat ? {} : { _type: assistSerializedFieldTypeName },
|
|
570
|
-
name,
|
|
571
|
-
type: typeName,
|
|
572
|
-
title: type.title,
|
|
573
|
-
...getBaseFields(schema, type, typeName, options2)
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
|
-
function serializeInlineOf(blockSchemaType, schema, options2) {
|
|
577
|
-
const childrenType = blockSchemaType.fields.find((f) => f.name === "children")?.type;
|
|
578
|
-
if (!(!childrenType || !sanity.isArraySchemaType(childrenType)))
|
|
579
|
-
return arrayOf(
|
|
580
|
-
{
|
|
581
|
-
of: childrenType.of.filter((t) => !isType(t, "span"))
|
|
582
|
-
},
|
|
583
|
-
schema,
|
|
584
|
-
options2
|
|
585
|
-
);
|
|
586
|
-
}
|
|
587
|
-
function serializeAnnotations(blockSchemaType, schema, options2) {
|
|
588
|
-
const marksType = blockSchemaType.fields.find((f) => f.name === "markDefs")?.type;
|
|
589
|
-
if (!(!marksType || !sanity.isArraySchemaType(marksType)))
|
|
590
|
-
return arrayOf(marksType, schema, options2);
|
|
591
|
-
}
|
|
592
|
-
function arrayOf(arrayType, schema, options2) {
|
|
593
|
-
return arrayType.of.filter((type) => isAssistSupported(type)).map((t) => serializeMember(schema, t, t.name, options2));
|
|
594
|
-
}
|
|
595
|
-
function refToTypeNames(type) {
|
|
596
|
-
return type.to.map((t) => ({
|
|
597
|
-
type: sanity.typed(t.name)
|
|
598
|
-
}));
|
|
599
|
-
}
|
|
600
|
-
function removeUndef(obj) {
|
|
601
|
-
return Object.keys(obj).forEach((key) => obj[key] === void 0 ? delete obj[key] : {}), obj;
|
|
602
|
-
}
|
|
603
388
|
const AiAssistanceConfigContext = react.createContext({});
|
|
604
389
|
function useAiAssistanceConfig() {
|
|
605
390
|
const context = react.useContext(AiAssistanceConfigContext);
|
|
@@ -610,33 +395,6 @@ function useAiAssistanceConfig() {
|
|
|
610
395
|
function useSerializedTypes() {
|
|
611
396
|
return useAiAssistanceConfig().serializedTypes;
|
|
612
397
|
}
|
|
613
|
-
function AiAssistanceConfigProvider(props) {
|
|
614
|
-
const [status, setStatus] = react.useState(), [error, setError] = react.useState(), apiClient = useApiClient(props.config?.__customApiClient), { getInstructStatus, loading: statusLoading } = useGetInstructStatus(apiClient), { initInstruct, loading: initLoading } = useInitInstruct(apiClient), schema = sanity.useSchema(), serializedTypes = react.useMemo(() => serializeSchema(schema, { leanFormat: !0 }), [schema]);
|
|
615
|
-
react.useEffect(() => {
|
|
616
|
-
getInstructStatus().then((s) => setStatus(s)).catch((e) => {
|
|
617
|
-
console.error(e), setError(e);
|
|
618
|
-
});
|
|
619
|
-
}, [getInstructStatus]);
|
|
620
|
-
const init = react.useCallback(async () => {
|
|
621
|
-
setError(void 0);
|
|
622
|
-
try {
|
|
623
|
-
await initInstruct();
|
|
624
|
-
const status2 = await getInstructStatus();
|
|
625
|
-
setStatus(status2);
|
|
626
|
-
} catch (e) {
|
|
627
|
-
console.error("Failed to init ai assistance", e), setError(e);
|
|
628
|
-
}
|
|
629
|
-
}, [initInstruct, getInstructStatus, setStatus]), { config, children } = props, context = react.useMemo(() => ({
|
|
630
|
-
config,
|
|
631
|
-
status,
|
|
632
|
-
statusLoading,
|
|
633
|
-
init,
|
|
634
|
-
initLoading,
|
|
635
|
-
error,
|
|
636
|
-
serializedTypes
|
|
637
|
-
}), [config, status, init, statusLoading, initLoading, error, serializedTypes]);
|
|
638
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AiAssistanceConfigContext.Provider, { value: context, children });
|
|
639
|
-
}
|
|
640
398
|
const basePath = "/assist/tasks/instruction", API_VERSION_WITH_EXTENDED_TYPES = "2025-04-01";
|
|
641
399
|
function canUseAssist(status) {
|
|
642
400
|
return status?.enabled && status.initialized && status.validToken;
|
|
@@ -1015,19 +773,105 @@ function useDraftDelayedTask(args) {
|
|
|
1015
773
|
[setQueuedArgs, documentOnChange]
|
|
1016
774
|
);
|
|
1017
775
|
}
|
|
776
|
+
const maxDepth = 6;
|
|
777
|
+
function getTypeIcon(schemaType) {
|
|
778
|
+
let t = schemaType;
|
|
779
|
+
for (; t; ) {
|
|
780
|
+
if (t.icon) return t.icon;
|
|
781
|
+
t = t.type;
|
|
782
|
+
}
|
|
783
|
+
return isType(schemaType, "slug") ? icons.LinkIcon : isType(schemaType, "image") ? icons.ImageIcon : schemaType.jsonType === "array" && isPortableTextArray(schemaType) ? icons.BlockContentIcon : schemaType.jsonType === "array" ? icons.OlistIcon : schemaType.jsonType === "object" ? icons.BlockquoteIcon : schemaType.jsonType === "string" ? icons.StringIcon : icons.DocumentIcon;
|
|
784
|
+
}
|
|
785
|
+
function asFieldRefsByTypePath(fieldRefs) {
|
|
786
|
+
return fieldRefs.reduce(
|
|
787
|
+
(acc, ref) => ({ ...acc, [ref.key]: ref }),
|
|
788
|
+
{}
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
function getDocumentFieldRef(schemaType) {
|
|
792
|
+
return {
|
|
793
|
+
key: documentRootKey,
|
|
794
|
+
icon: schemaType.icon ?? icons.DocumentIcon,
|
|
795
|
+
title: "The entire document",
|
|
796
|
+
path: [],
|
|
797
|
+
schemaType
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
function getFieldRefs(schemaType, parent, depth = 0) {
|
|
801
|
+
return depth >= maxDepth ? [] : schemaType.fields.filter((f) => !f.name.startsWith("_")).flatMap((field) => {
|
|
802
|
+
const path = parent ? [...parent.path, field.name] : [field.name], title = field.type.title ?? field.name, fieldRef = {
|
|
803
|
+
key: patchableKey(sanity.pathToString(path)),
|
|
804
|
+
path,
|
|
805
|
+
title: parent ? [parent.title, title].join(" / ") : title,
|
|
806
|
+
schemaType: field.type,
|
|
807
|
+
icon: getTypeIcon(field.type)
|
|
808
|
+
}, fields = field.type.jsonType === "object" ? getFieldRefs(field.type, fieldRef, depth + 1) : [], syntheticFields = field.type.jsonType === "array" ? getSyntheticFields(field.type, fieldRef, depth + 1) : [];
|
|
809
|
+
return isAssistSupported(field.type) ? [fieldRef, ...fields, ...syntheticFields] : [...fields, ...syntheticFields];
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
function getSyntheticFields(schemaType, parent, depth = 0) {
|
|
813
|
+
return depth >= maxDepth ? [] : schemaType.of.filter((itemType) => !isType(itemType, "block")).flatMap((itemType) => {
|
|
814
|
+
const segment = { _key: itemType.name }, title = itemType.title ?? itemType.name, path = parent ? [...parent.path, segment] : [segment], fieldRef = {
|
|
815
|
+
key: patchableKey(sanity.pathToString(path)),
|
|
816
|
+
path,
|
|
817
|
+
title: parent ? [parent.title, title].join(" / ") : title,
|
|
818
|
+
schemaType: itemType,
|
|
819
|
+
icon: getTypeIcon(itemType),
|
|
820
|
+
synthetic: !0
|
|
821
|
+
}, fields = itemType.jsonType === "object" ? getFieldRefs(itemType, fieldRef, depth + 1) : [];
|
|
822
|
+
return isAssistSupported(itemType) ? [fieldRef, ...fields] : fields;
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
function getTypePath(doc, pathString) {
|
|
826
|
+
if (!pathString)
|
|
827
|
+
return;
|
|
828
|
+
const path = sanity.stringToPath(pathString), currentPath = [];
|
|
829
|
+
let valid = !0;
|
|
830
|
+
const syntheticPath = path.map((segment) => {
|
|
831
|
+
if (currentPath.push(segment), sanity.isKeySegment(segment)) {
|
|
832
|
+
const match = mutator.extractWithPath(sanity.pathToString(currentPath), doc)[0], value = match?.value;
|
|
833
|
+
if (match && value && typeof value == "object" && "_type" in value)
|
|
834
|
+
return { _key: value._type };
|
|
835
|
+
valid = !1;
|
|
836
|
+
}
|
|
837
|
+
return segment;
|
|
838
|
+
});
|
|
839
|
+
return valid ? patchableKey(sanity.pathToString(syntheticPath)) : void 0;
|
|
840
|
+
}
|
|
841
|
+
function patchableKey(pathKey) {
|
|
842
|
+
return pathKey.replace(/[=]=/g, ":").replace(/[[\]]/g, "|").replace(/"/g, "");
|
|
843
|
+
}
|
|
844
|
+
function useTypePath(doc, pathString) {
|
|
845
|
+
return react.useMemo(() => getTypePath(doc, pathString), [doc, pathString]);
|
|
846
|
+
}
|
|
847
|
+
function useSelectedField(documentSchemaType, path) {
|
|
848
|
+
const { getFieldRefs: getFieldRefs2 } = useAiAssistanceConfig(), selectableFields = react.useMemo(
|
|
849
|
+
() => documentSchemaType && sanity.isObjectSchemaType(documentSchemaType) ? [getDocumentFieldRef(documentSchemaType), ...getFieldRefs2(documentSchemaType.name)] : [],
|
|
850
|
+
[documentSchemaType, getFieldRefs2]
|
|
851
|
+
);
|
|
852
|
+
return react.useMemo(() => path ? selectableFields?.find((f) => f.key === path) : void 0, [selectableFields, path]);
|
|
853
|
+
}
|
|
854
|
+
function getFieldTitle(field) {
|
|
855
|
+
const schemaType = field?.schemaType;
|
|
856
|
+
return field?.title ?? schemaType?.title ?? schemaType?.name ?? "Untitled";
|
|
857
|
+
}
|
|
858
|
+
function useAiPaneRouter() {
|
|
859
|
+
const paneRouter = structure.usePaneRouter();
|
|
860
|
+
return react.useMemo(
|
|
861
|
+
() => ({ ...paneRouter, params: paneRouter.params ?? {} }),
|
|
862
|
+
[paneRouter]
|
|
863
|
+
);
|
|
864
|
+
}
|
|
1018
865
|
function useAssistDocumentContextValue(documentId, documentType) {
|
|
1019
|
-
const schema = sanity.useSchema(), documentSchemaType = react.useMemo(() => {
|
|
866
|
+
const schema = sanity.useSchema(), { getFieldRefs: getFieldRefs2, getFieldRefsByTypePath } = useAiAssistanceConfig(), documentSchemaType = react.useMemo(() => {
|
|
1020
867
|
const schemaType = schema.get(documentType);
|
|
1021
868
|
if (!schemaType)
|
|
1022
869
|
throw new Error(`Schema type "${documentType}" not found`);
|
|
1023
870
|
return schemaType;
|
|
1024
|
-
}, [documentType, schema]), { fieldRefs, fieldRefsByTypePath } = react.useMemo(() => {
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
fieldRefsByTypePath: fieldRefsByTypePath2
|
|
1029
|
-
};
|
|
1030
|
-
}, [documentSchemaType]), {
|
|
871
|
+
}, [documentType, schema]), { fieldRefs, fieldRefsByTypePath } = react.useMemo(() => ({
|
|
872
|
+
fieldRefs: getFieldRefs2(documentType),
|
|
873
|
+
fieldRefsByTypePath: getFieldRefsByTypePath(documentType)
|
|
874
|
+
}), [getFieldRefs2, getFieldRefsByTypePath, documentType]), {
|
|
1031
875
|
openInspector,
|
|
1032
876
|
closeInspector,
|
|
1033
877
|
inspector,
|
|
@@ -1519,8 +1363,9 @@ function conditionalState(memberState) {
|
|
|
1519
1363
|
return {
|
|
1520
1364
|
path: sanity.pathToString(memberState.path),
|
|
1521
1365
|
readOnly: !!memberState.readOnly,
|
|
1366
|
+
// Use actual form state readOnly value
|
|
1522
1367
|
hidden: !1,
|
|
1523
|
-
//
|
|
1368
|
+
// If it's in form state members, it's not hidden
|
|
1524
1369
|
conditional: isConditional(memberState.schemaType)
|
|
1525
1370
|
};
|
|
1526
1371
|
}
|
|
@@ -1555,7 +1400,7 @@ function extractConditionalPaths(node, maxDepth2) {
|
|
|
1555
1400
|
), innerFields = extractConditionalPaths(member.fieldSet, maxDepth2).map((f) => ({
|
|
1556
1401
|
...f,
|
|
1557
1402
|
// if fieldset is conditional, visible fields must also be considered conditional
|
|
1558
|
-
conditional: conditionalFieldset
|
|
1403
|
+
conditional: conditionalFieldset || f.conditional
|
|
1559
1404
|
}));
|
|
1560
1405
|
return [...acc, ...innerFields];
|
|
1561
1406
|
}
|
|
@@ -1594,7 +1439,10 @@ function InspectorOnboarding(props) {
|
|
|
1594
1439
|
] }) }) });
|
|
1595
1440
|
}
|
|
1596
1441
|
function FieldAutocomplete(props) {
|
|
1597
|
-
const { id, schemaType, fieldPath, onSelect, includeDocument, filter } = props,
|
|
1442
|
+
const { id, schemaType, fieldPath, onSelect, includeDocument, filter } = props, { getFieldRefs: getFieldRefs2 } = useAiAssistanceConfig(), fieldRefs = react.useMemo(() => {
|
|
1443
|
+
const refs = getFieldRefs2(schemaType.name);
|
|
1444
|
+
return includeDocument ? [getDocumentFieldRef(schemaType), ...refs] : refs;
|
|
1445
|
+
}, [schemaType, includeDocument, getFieldRefs2]), currentField = react.useMemo(
|
|
1598
1446
|
() => fieldRefs.find((f) => f.key === fieldPath),
|
|
1599
1447
|
[fieldPath, fieldRefs]
|
|
1600
1448
|
), autocompleteOptions = react.useMemo(
|
|
@@ -2595,6 +2443,195 @@ function FromLanguageRadio(props) {
|
|
|
2595
2443
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: radioLanguage.title ?? radioLanguage.id })
|
|
2596
2444
|
] }, langId);
|
|
2597
2445
|
}
|
|
2446
|
+
const hiddenTypes = [
|
|
2447
|
+
"any",
|
|
2448
|
+
"array",
|
|
2449
|
+
"block",
|
|
2450
|
+
"boolean",
|
|
2451
|
+
"crossDatasetReference",
|
|
2452
|
+
"date",
|
|
2453
|
+
"datetime",
|
|
2454
|
+
"document",
|
|
2455
|
+
"email",
|
|
2456
|
+
"file",
|
|
2457
|
+
"globalDocumentReference",
|
|
2458
|
+
"image",
|
|
2459
|
+
"number",
|
|
2460
|
+
"object",
|
|
2461
|
+
"reference",
|
|
2462
|
+
"span",
|
|
2463
|
+
"string",
|
|
2464
|
+
"text",
|
|
2465
|
+
"url",
|
|
2466
|
+
"slug",
|
|
2467
|
+
"geopoint",
|
|
2468
|
+
"sanity.assetSourceData",
|
|
2469
|
+
"sanity.imageAsset",
|
|
2470
|
+
"sanity.fileAsset",
|
|
2471
|
+
"sanity.imageCrop",
|
|
2472
|
+
"sanity.imageHotspot",
|
|
2473
|
+
"sanity.imageMetadata",
|
|
2474
|
+
"sanity.imageDimensions",
|
|
2475
|
+
"sanity.imagePalette",
|
|
2476
|
+
"sanity.imagePaletteSwatch",
|
|
2477
|
+
assistSerializedTypeName,
|
|
2478
|
+
assistSerializedFieldTypeName,
|
|
2479
|
+
"sanity-agent.job.document"
|
|
2480
|
+
], inlineTypes = ["document", "object", "image", "file"];
|
|
2481
|
+
function serializeSchema(schema, options2) {
|
|
2482
|
+
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));
|
|
2483
|
+
return list.sort((a, b) => (a?.name ?? "").localeCompare(b?.name ?? "")), list;
|
|
2484
|
+
}
|
|
2485
|
+
function getSchemaStub(schemaType, schema, options2) {
|
|
2486
|
+
if (!schemaType.type?.name)
|
|
2487
|
+
throw console.error("Missing type name", schemaType.type), new Error("Type is missing name!");
|
|
2488
|
+
const baseSchema = {
|
|
2489
|
+
// we dont need type or id when we send using POST, so leave these out to save bandwidth
|
|
2490
|
+
...options2?.leanFormat ? {} : { _id: `${assistSchemaIdPrefix}${schemaType.name}`, _type: assistSerializedTypeName },
|
|
2491
|
+
name: schemaType.name,
|
|
2492
|
+
title: schemaType.title,
|
|
2493
|
+
type: schemaType.type.name,
|
|
2494
|
+
...getBaseFields(schema, schemaType, schemaType.type.name, options2)
|
|
2495
|
+
};
|
|
2496
|
+
return removeUndef(baseSchema);
|
|
2497
|
+
}
|
|
2498
|
+
function getBaseFields(schema, type, typeName, options2) {
|
|
2499
|
+
const schemaOptions = removeUndef({
|
|
2500
|
+
imagePromptField: type.options?.aiAssist?.imageInstructionField,
|
|
2501
|
+
embeddingsIndex: type.options?.aiAssist?.embeddingsIndex
|
|
2502
|
+
});
|
|
2503
|
+
return removeUndef({
|
|
2504
|
+
options: Object.keys(schemaOptions).length ? schemaOptions : void 0,
|
|
2505
|
+
values: Array.isArray(type?.options?.list) ? type?.options?.list.map(
|
|
2506
|
+
(v) => typeof v == "string" ? v : v.value ?? `${v.title}`
|
|
2507
|
+
) : void 0,
|
|
2508
|
+
of: "of" in type && typeName === "array" ? arrayOf(type, schema, options2) : void 0,
|
|
2509
|
+
to: "to" in type && typeName === "reference" ? refToTypeNames(type) : void 0,
|
|
2510
|
+
fields: "fields" in type && inlineTypes.includes(typeName) ? serializeFields(schema, type, options2) : void 0,
|
|
2511
|
+
annotations: typeName === "block" && "fields" in type ? serializeAnnotations(type, schema, options2) : void 0,
|
|
2512
|
+
inlineOf: typeName === "block" && "fields" in type ? serializeInlineOf(type, schema, options2) : void 0,
|
|
2513
|
+
hidden: typeof type.hidden == "function" ? "function" : type.hidden ? !0 : void 0,
|
|
2514
|
+
readOnly: typeof type.readOnly == "function" ? "function" : type.readOnly ? !0 : void 0
|
|
2515
|
+
});
|
|
2516
|
+
}
|
|
2517
|
+
function serializeFields(schema, schemaType, options2) {
|
|
2518
|
+
return (schemaType.fieldsets ? schemaType.fieldsets.flatMap(
|
|
2519
|
+
(fs) => fs.single ? fs.field : fs.fields.map((f) => ({
|
|
2520
|
+
...f,
|
|
2521
|
+
type: {
|
|
2522
|
+
...f.type,
|
|
2523
|
+
// if fieldset is (conditionally) hidden, the field must be considered the same way
|
|
2524
|
+
// ie, if the field does not show up in conditionalMembers, it is hidden
|
|
2525
|
+
// regardless of weather or not it is the field function or the fieldset function that hides it
|
|
2526
|
+
hidden: typeof fs.hidden == "function" ? fs.hidden : fs.hidden ? !0 : f.type.hidden
|
|
2527
|
+
}
|
|
2528
|
+
}))
|
|
2529
|
+
) : 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));
|
|
2530
|
+
}
|
|
2531
|
+
function serializeMember(schema, type, name, options2) {
|
|
2532
|
+
const typeName = schema.get(type?.name) ? type.name : type.type?.name ?? "";
|
|
2533
|
+
return removeUndef({
|
|
2534
|
+
...options2?.leanFormat ? {} : { _type: assistSerializedFieldTypeName },
|
|
2535
|
+
name,
|
|
2536
|
+
type: typeName,
|
|
2537
|
+
title: type.title,
|
|
2538
|
+
...getBaseFields(schema, type, typeName, options2)
|
|
2539
|
+
});
|
|
2540
|
+
}
|
|
2541
|
+
function serializeInlineOf(blockSchemaType, schema, options2) {
|
|
2542
|
+
const childrenType = blockSchemaType.fields.find((f) => f.name === "children")?.type;
|
|
2543
|
+
if (!(!childrenType || !sanity.isArraySchemaType(childrenType)))
|
|
2544
|
+
return arrayOf(
|
|
2545
|
+
{
|
|
2546
|
+
of: childrenType.of.filter((t) => !isType(t, "span"))
|
|
2547
|
+
},
|
|
2548
|
+
schema,
|
|
2549
|
+
options2
|
|
2550
|
+
);
|
|
2551
|
+
}
|
|
2552
|
+
function serializeAnnotations(blockSchemaType, schema, options2) {
|
|
2553
|
+
const marksType = blockSchemaType.fields.find((f) => f.name === "markDefs")?.type;
|
|
2554
|
+
if (!(!marksType || !sanity.isArraySchemaType(marksType)))
|
|
2555
|
+
return arrayOf(marksType, schema, options2);
|
|
2556
|
+
}
|
|
2557
|
+
function arrayOf(arrayType, schema, options2) {
|
|
2558
|
+
return arrayType.of.filter((type) => isAssistSupported(type)).map((t) => serializeMember(schema, t, t.name, options2));
|
|
2559
|
+
}
|
|
2560
|
+
function refToTypeNames(type) {
|
|
2561
|
+
return type.to.map((t) => ({
|
|
2562
|
+
type: sanity.typed(t.name)
|
|
2563
|
+
}));
|
|
2564
|
+
}
|
|
2565
|
+
function removeUndef(obj) {
|
|
2566
|
+
return Object.keys(obj).forEach((key) => obj[key] === void 0 ? delete obj[key] : {}), obj;
|
|
2567
|
+
}
|
|
2568
|
+
function createFieldRefCache() {
|
|
2569
|
+
const byType = {};
|
|
2570
|
+
function getRefsForType(schemaType) {
|
|
2571
|
+
const documentType = schemaType.name, cached = byType[documentType];
|
|
2572
|
+
if (cached) return cached;
|
|
2573
|
+
const fieldRefs = getFieldRefs(schemaType), fieldRefsByTypePath = asFieldRefsByTypePath(fieldRefs), refs = {
|
|
2574
|
+
fieldRefs,
|
|
2575
|
+
fieldRefsByTypePath
|
|
2576
|
+
};
|
|
2577
|
+
return byType[documentType] = refs, refs;
|
|
2578
|
+
}
|
|
2579
|
+
return getRefsForType;
|
|
2580
|
+
}
|
|
2581
|
+
function AiAssistanceConfigProvider(props) {
|
|
2582
|
+
const [status, setStatus] = react.useState(), [error, setError] = react.useState(), apiClient = useApiClient(props.config?.__customApiClient), { getInstructStatus, loading: statusLoading } = useGetInstructStatus(apiClient), { initInstruct, loading: initLoading } = useInitInstruct(apiClient), schema = sanity.useSchema(), serializedTypes = react.useMemo(() => serializeSchema(schema, { leanFormat: !0 }), [schema]), { getFieldRefs: getFieldRefs2, getFieldRefsByTypePath } = useFieldRefGetters(schema);
|
|
2583
|
+
react.useEffect(() => {
|
|
2584
|
+
getInstructStatus().then((s) => setStatus(s)).catch((e) => {
|
|
2585
|
+
console.error(e), setError(e);
|
|
2586
|
+
});
|
|
2587
|
+
}, [getInstructStatus]);
|
|
2588
|
+
const init = react.useCallback(async () => {
|
|
2589
|
+
setError(void 0);
|
|
2590
|
+
try {
|
|
2591
|
+
await initInstruct();
|
|
2592
|
+
const status2 = await getInstructStatus();
|
|
2593
|
+
setStatus(status2);
|
|
2594
|
+
} catch (e) {
|
|
2595
|
+
console.error("Failed to init ai assistance", e), setError(e);
|
|
2596
|
+
}
|
|
2597
|
+
}, [initInstruct, getInstructStatus, setStatus]), { config, children } = props, context = react.useMemo(() => ({
|
|
2598
|
+
config,
|
|
2599
|
+
status,
|
|
2600
|
+
statusLoading,
|
|
2601
|
+
init,
|
|
2602
|
+
initLoading,
|
|
2603
|
+
error,
|
|
2604
|
+
serializedTypes,
|
|
2605
|
+
getFieldRefs: getFieldRefs2,
|
|
2606
|
+
getFieldRefsByTypePath
|
|
2607
|
+
}), [
|
|
2608
|
+
config,
|
|
2609
|
+
status,
|
|
2610
|
+
init,
|
|
2611
|
+
statusLoading,
|
|
2612
|
+
initLoading,
|
|
2613
|
+
error,
|
|
2614
|
+
serializedTypes,
|
|
2615
|
+
getFieldRefs2,
|
|
2616
|
+
getFieldRefsByTypePath
|
|
2617
|
+
]);
|
|
2618
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AiAssistanceConfigContext.Provider, { value: context, children });
|
|
2619
|
+
}
|
|
2620
|
+
function useFieldRefGetters(schema) {
|
|
2621
|
+
return react.useMemo(() => {
|
|
2622
|
+
const getForSchemaType = createFieldRefCache();
|
|
2623
|
+
function getRefsForType(documentType) {
|
|
2624
|
+
const schemaType = schema.get(documentType);
|
|
2625
|
+
if (!schemaType)
|
|
2626
|
+
throw new Error(`Schema type "${documentType}" not found`);
|
|
2627
|
+
return getForSchemaType(schemaType);
|
|
2628
|
+
}
|
|
2629
|
+
return {
|
|
2630
|
+
getFieldRefs: (documentType) => getRefsForType(documentType).fieldRefs,
|
|
2631
|
+
getFieldRefsByTypePath: (documentType) => getRefsForType(documentType).fieldRefsByTypePath
|
|
2632
|
+
};
|
|
2633
|
+
}, [schema]);
|
|
2634
|
+
}
|
|
2598
2635
|
function AssistLayout(props) {
|
|
2599
2636
|
const [connectors, setConnectors] = react.useState([]);
|
|
2600
2637
|
return /* @__PURE__ */ jsxRuntime.jsx(AiAssistanceConfigProvider, { config: props.config, children: /* @__PURE__ */ jsxRuntime.jsx(RunInstructionProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(FieldTranslationProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(ConnectorsProvider, { onConnectorsChange: setConnectors, children: [
|
|
@@ -3180,7 +3217,7 @@ function BackToInstructionListLink() {
|
|
|
3180
3217
|
}
|
|
3181
3218
|
) });
|
|
3182
3219
|
}
|
|
3183
|
-
const EMPTY_FIELDS = [];
|
|
3220
|
+
const SelectedFieldContext = react.createContext(void 0), SelectedFieldContextProvider = SelectedFieldContext.Provider, EMPTY_FIELDS = [];
|
|
3184
3221
|
function AssistDocumentForm(props) {
|
|
3185
3222
|
return props.readOnly ? /* @__PURE__ */ jsxRuntime.jsx(ui.Card, { border: !0, tone: "caution", padding: 2, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: 1, children: " You do not have sufficient permissions to manage instructions." }) }) : /* @__PURE__ */ jsxRuntime.jsx(AssistDocumentFormEditable, { ...props });
|
|
3186
3223
|
}
|
|
@@ -3680,19 +3717,25 @@ const contextDocumentSchema = sanity.defineType({
|
|
|
3680
3717
|
components: {
|
|
3681
3718
|
input: FieldRefPathInput
|
|
3682
3719
|
},
|
|
3683
|
-
validation: (rule) =>
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3720
|
+
validation: (rule) => {
|
|
3721
|
+
const getForSchemaType = createFieldRefCache();
|
|
3722
|
+
return rule.custom((value, context) => {
|
|
3723
|
+
if (!value)
|
|
3724
|
+
return "Please select a field";
|
|
3725
|
+
try {
|
|
3726
|
+
const docId = context.document?._id;
|
|
3727
|
+
if (!docId)
|
|
3728
|
+
return "Field reference cannot be used outside document inspector context. Could not resolve document id.";
|
|
3729
|
+
const targetDocType = docId.replace(new RegExp(`^${assistDocumentIdPrefix}`), ""), schema = context.schema.get(targetDocType);
|
|
3730
|
+
if (!schema)
|
|
3731
|
+
return `Field reference cannot be used outside document inspector context. Could not resolve schema: ${targetDocType}`;
|
|
3732
|
+
const { fieldRefs } = getForSchemaType(schema);
|
|
3733
|
+
return fieldRefs.find((r) => r.key === value) ? !0 : `Field with path "${value}" does not exist in the schema.`;
|
|
3734
|
+
} catch (e) {
|
|
3735
|
+
return console.error("Failed to resolve field reference", e), "Invalid field reference.";
|
|
3736
|
+
}
|
|
3737
|
+
});
|
|
3738
|
+
}
|
|
3696
3739
|
})
|
|
3697
3740
|
],
|
|
3698
3741
|
preview: {
|