@sanity/assist 1.0.11 → 1.1.0

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.esm.js CHANGED
@@ -1,5 +1,3 @@
1
- var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9, _templateObject10, _templateObject11, _templateObject12;
2
- function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
3
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
2
  import { useClient, typed, useSchema, useDocumentStore, useDocumentPresence, createPatchChannel, FormBuilder, fromMutationPatches, pathToString, isObjectSchemaType, useEditState, useCurrentUser, useValidationStatus, StatusButton, FormFieldHeaderText, PatchEvent, unset, PresenceOverlay, VirtualizerScrollInstanceProvider, stringToPath, isKeySegment, useColorSchemeValue, isArraySchemaType, useFormCallbacks, set, FormCallbacksProvider, FormInput, setIfMissing, insert, ObjectInputMember, defineType, defineField, defineArrayMember, getPublishedId, definePlugin } from 'sanity';
5
3
  import { Card, Stack, Box, Button, Spinner, Flex, Label, focusFirstDescendant, Text, useClickOutside, Popover, useLayer, useGlobalKeyDown, useToast, Dialog, Tooltip, TextArea, Container, Badge, useTheme, rgba, ThemeProvider, ErrorBoundary, Switch, MenuButton, Menu, MenuItem, Breadcrumbs, Autocomplete } from '@sanity/ui';
@@ -58,7 +56,7 @@ const listenQuery = function (client, query) {
58
56
  const events$ = listen(client, listenerQuery, params, options).pipe(mergeMap((ev, i) => {
59
57
  const isFirst = i === 0;
60
58
  if (isFirst && !isWelcomeEvent(ev)) {
61
- return throwError(new Error(ev.type === "reconnect" ? "Could not establish EventSource connection" : "Received unexpected type of first event \"".concat(ev.type, "\"")));
59
+ return throwError(new Error(ev.type === "reconnect" ? "Could not establish EventSource connection" : 'Received unexpected type of first event "'.concat(ev.type, '"')));
62
60
  }
63
61
  return of(ev);
64
62
  }), share());
@@ -122,6 +120,20 @@ function isType(schemaType, typeName) {
122
120
  }
123
121
  return isType(schemaType.type, typeName);
124
122
  }
123
+ function isImage(schemaType) {
124
+ return isType(schemaType, "image");
125
+ }
126
+ function getCaptionFieldOption(schemaType) {
127
+ var _a;
128
+ if (!schemaType) {
129
+ return void 0;
130
+ }
131
+ const captionField = (_a = schemaType.options) == null ? void 0 : _a.captionField;
132
+ if (captionField) {
133
+ return captionField;
134
+ }
135
+ return getCaptionFieldOption(schemaType.type);
136
+ }
125
137
  function isSchemaAssistEnabled(type) {
126
138
  var _a, _b;
127
139
  return !((_b = (_a = type.options) == null ? void 0 : _a.aiWritingAssistance) == null ? void 0 : _b.exclude);
@@ -684,8 +696,14 @@ function getInstructionTitle(instruction) {
684
696
  var _a;
685
697
  return (_a = instruction == null ? void 0 : instruction.title) != null ? _a : "Untitled";
686
698
  }
687
- const rotate = keyframes(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n 0% {\n transform: rotate(0);\n }\n 100% {\n transform: rotate(360deg);\n }\n"])));
688
- const SyncSpinningIcon = styled(SyncIcon)(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n animation: ", " 1s linear infinite;\n"])), rotate);
699
+ var __freeze$5 = Object.freeze;
700
+ var __defProp$5 = Object.defineProperty;
701
+ var __template$5 = (cooked, raw) => __freeze$5(__defProp$5(cooked, "raw", {
702
+ value: __freeze$5(raw || cooked.slice())
703
+ }));
704
+ var _a$5, _b$3;
705
+ const rotate = keyframes(_a$5 || (_a$5 = __template$5(["\n 0% {\n transform: rotate(0);\n }\n 100% {\n transform: rotate(360deg);\n }\n"])));
706
+ const SyncSpinningIcon = styled(SyncIcon)(_b$3 || (_b$3 = __template$5(["\n animation: ", " 1s linear infinite;\n"])), rotate);
689
707
  const TASK_CONFIG = {
690
708
  aborted: {
691
709
  title: "Canceled",
@@ -723,25 +741,26 @@ function InstructionTaskHistoryButton(props) {
723
741
  return;
724
742
  }
725
743
  const statusDocId = assistTasksStatusId(documentId);
726
- const basePath = "".concat(typed("tasks"), "[_key==\"").concat(taskKey, "\"]");
744
+ const basePath = "".concat(typed("tasks"), '[_key=="').concat(taskKey, '"]');
727
745
  client.patch(statusDocId).set({
728
746
  ["".concat(basePath, ".").concat(typed("ended"))]: /* @__PURE__ */new Date().toISOString(),
729
747
  ["".concat(basePath, ".").concat(typed("reason"))]: typed("aborted")
730
748
  }).commit().catch(console.error);
731
749
  }, [client, documentId]);
732
750
  const titledTasks = useMemo(() => {
733
- var _a;
734
- const t = (_a = tasks == null ? void 0 : tasks.filter(task => task.started && /* @__PURE__ */new Date().getTime() - new Date(task.started).getTime() < maxHistoryVisibilityMs).map(task => {
751
+ var _a2;
752
+ const t = (_a2 = tasks == null ? void 0 : tasks.filter(task => task.started && /* @__PURE__ */new Date().getTime() - new Date(task.started).getTime() < maxHistoryVisibilityMs).map(task => {
753
+ var _a3;
735
754
  const instruction = instructions == null ? void 0 : instructions.find(i => i._key === task.instructionKey);
736
755
  return {
737
756
  ...task,
738
- title: showTitles ? getInstructionTitle(instruction) : void 0,
757
+ title: showTitles ? (_a3 = task.title) != null ? _a3 : getInstructionTitle(instruction) : void 0,
739
758
  cancel: () => cancelRun(task._key)
740
759
  };
741
- })) != null ? _a : [];
760
+ })) != null ? _a2 : [];
742
761
  t.sort((a, b) => {
743
- var _a2, _b;
744
- return new Date((_a2 = b.started) != null ? _a2 : "").getTime() - new Date((_b = a.started) != null ? _b : "").getTime();
762
+ var _a3, _b2;
763
+ return new Date((_a3 = b.started) != null ? _a3 : "").getTime() - new Date((_b2 = a.started) != null ? _b2 : "").getTime();
745
764
  });
746
765
  return t;
747
766
  }, [tasks, instructions, cancelRun, showTitles]);
@@ -826,7 +845,7 @@ function TaskList(props) {
826
845
  });
827
846
  }
828
847
  function TaskItem(props) {
829
- var _a;
848
+ var _a2;
830
849
  const {
831
850
  task
832
851
  } = props;
@@ -864,7 +883,7 @@ function TaskItem(props) {
864
883
  muted: true,
865
884
  size: 1,
866
885
  children: /* @__PURE__ */jsx(TimeAgo, {
867
- date: (_a = task.ended) != null ? _a : task.started
886
+ date: (_a2 = task.ended) != null ? _a2 : task.started
868
887
  })
869
888
  })]
870
889
  })]
@@ -889,6 +908,48 @@ function useApiClient(customApiClient) {
889
908
  });
890
909
  return useMemo(() => customApiClient ? customApiClient(client) : client, [client, customApiClient]);
891
910
  }
911
+ function useGenerateCaption(apiClient) {
912
+ const [loading, setLoading] = useState(false);
913
+ const user = useCurrentUser();
914
+ const schema = useSchema();
915
+ const types = useMemo(() => serializeSchema(schema, {
916
+ leanFormat: true
917
+ }), [schema]);
918
+ const toast = useToast();
919
+ const generateCaption = useCallback(_ref4 => {
920
+ let {
921
+ path,
922
+ documentId
923
+ } = _ref4;
924
+ setLoading(true);
925
+ return apiClient.request({
926
+ method: "POST",
927
+ url: "/assist/tasks/generate-caption/".concat(apiClient.config().dataset, "?projectId=").concat(apiClient.config().projectId),
928
+ body: {
929
+ path,
930
+ documentId,
931
+ types,
932
+ userId: user == null ? void 0 : user.id
933
+ }
934
+ }).catch(e => {
935
+ toast.push({
936
+ status: "error",
937
+ title: "Generate caption failed",
938
+ description: e.message
939
+ });
940
+ setLoading(false);
941
+ throw e;
942
+ }).finally(() => {
943
+ setTimeout(() => {
944
+ setLoading(false);
945
+ }, 2e3);
946
+ });
947
+ }, [setLoading, apiClient, toast, user, types]);
948
+ return useMemo(() => ({
949
+ generateCaption,
950
+ loading
951
+ }), [generateCaption, loading]);
952
+ }
892
953
  function useGetInstructStatus(apiClient) {
893
954
  const [loading, setLoading] = useState(true);
894
955
  const projectClient = useClient({
@@ -1089,8 +1150,8 @@ function RunInstructionProvider(props) {
1089
1150
  runInstructionRequest({
1090
1151
  ...request,
1091
1152
  instructionKey: instruction._key,
1092
- userTexts: Object.entries(inputs).map(_ref4 => {
1093
- let [key, value] = _ref4;
1153
+ userTexts: Object.entries(inputs).map(_ref5 => {
1154
+ let [key, value] = _ref5;
1094
1155
  return {
1095
1156
  blockKey: key,
1096
1157
  userInput: value
@@ -1103,8 +1164,8 @@ function RunInstructionProvider(props) {
1103
1164
  const open = !!runRequest;
1104
1165
  const runDisabled = useMemo(() => {
1105
1166
  var _a2, _b;
1106
- return ((_b = (_a2 = runRequest == null ? void 0 : runRequest.userInputBlocks) == null ? void 0 : _a2.length) != null ? _b : 0) > Object.entries(inputs).filter(_ref5 => {
1107
- let [, value] = _ref5;
1167
+ return ((_b = (_a2 = runRequest == null ? void 0 : runRequest.userInputBlocks) == null ? void 0 : _a2.length) != null ? _b : 0) > Object.entries(inputs).filter(_ref6 => {
1168
+ let [, value] = _ref6;
1108
1169
  return !!value;
1109
1170
  }).length;
1110
1171
  }, [runRequest == null ? void 0 : runRequest.userInputBlocks, inputs]);
@@ -1316,8 +1377,14 @@ function useOnboardingFeature(featureKey) {
1316
1377
  dismissOnboarding
1317
1378
  };
1318
1379
  }
1319
- const CardWithShadowBelow = styled(Card)(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n position: relative;\n\n &:after {\n content: '';\n display: block;\n position: absolute;\n left: 0;\n right: 0;\n bottom: -1px;\n border-bottom: 1px solid var(--card-border-color);\n opacity: 0.5;\n z-index: 100;\n }\n"])));
1320
- const CardWithShadowAbove = styled(Card)(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n position: relative;\n\n &:after {\n content: '';\n display: block;\n position: absolute;\n left: 0;\n right: 0;\n top: -1px;\n border-top: 1px solid var(--card-border-color);\n opacity: 0.5;\n z-index: 100;\n }\n"])));
1380
+ var __freeze$4 = Object.freeze;
1381
+ var __defProp$4 = Object.defineProperty;
1382
+ var __template$4 = (cooked, raw) => __freeze$4(__defProp$4(cooked, "raw", {
1383
+ value: __freeze$4(raw || cooked.slice())
1384
+ }));
1385
+ var _a$4, _b$2;
1386
+ const CardWithShadowBelow = styled(Card)(_a$4 || (_a$4 = __template$4(["\n position: relative;\n\n &:after {\n content: '';\n display: block;\n position: absolute;\n left: 0;\n right: 0;\n bottom: -1px;\n border-bottom: 1px solid var(--card-border-color);\n opacity: 0.5;\n z-index: 100;\n }\n"])));
1387
+ const CardWithShadowAbove = styled(Card)(_b$2 || (_b$2 = __template$4(["\n position: relative;\n\n &:after {\n content: '';\n display: block;\n position: absolute;\n left: 0;\n right: 0;\n top: -1px;\n border-top: 1px solid var(--card-border-color);\n opacity: 0.5;\n z-index: 100;\n }\n"])));
1321
1388
  function AssistInspectorWrapper(props) {
1322
1389
  const context = useAiAssistanceConfig();
1323
1390
  if (context.statusLoading) {
@@ -1436,11 +1503,11 @@ function AssistInspectorWrapper(props) {
1436
1503
  });
1437
1504
  }
1438
1505
  function AssistInspector(props) {
1439
- var _a, _b;
1506
+ var _a2, _b2;
1440
1507
  const {
1441
1508
  params
1442
1509
  } = useAiPaneRouter();
1443
- const [boundary, setBoundary] = useState(null);
1510
+ const boundary = useRef(null);
1444
1511
  const pathKey = params == null ? void 0 : params[fieldPathParam];
1445
1512
  const instructionKey = params == null ? void 0 : params[instructionParam];
1446
1513
  const documentPane = useDocumentPane();
@@ -1468,28 +1535,28 @@ function AssistInspector(props) {
1468
1535
  documentId,
1469
1536
  schemaType
1470
1537
  });
1471
- const assistField = (_a = assistDocument == null ? void 0 : assistDocument.fields) == null ? void 0 : _a.find(f => f.path === pathKey);
1472
- const instruction = (_b = assistField == null ? void 0 : assistField.instructions) == null ? void 0 : _b.find(i => i._key === instructionKey);
1538
+ const assistField = (_a2 = assistDocument == null ? void 0 : assistDocument.fields) == null ? void 0 : _a2.find(f => f.path === pathKey);
1539
+ const instruction = (_b2 = assistField == null ? void 0 : assistField.instructions) == null ? void 0 : _b2.find(i => i._key === instructionKey);
1473
1540
  const tasks = useMemo(() => {
1474
- var _a2;
1475
- return (_a2 = assistDocument == null ? void 0 : assistDocument.tasks) == null ? void 0 : _a2.filter(i => !instructionKey || i.instructionKey === instructionKey);
1541
+ var _a3;
1542
+ return (_a3 = assistDocument == null ? void 0 : assistDocument.tasks) == null ? void 0 : _a3.filter(i => !instructionKey || i.instructionKey === instructionKey);
1476
1543
  }, [assistDocument == null ? void 0 : assistDocument.tasks, instructionKey]);
1477
1544
  const instructions = useMemo(() => {
1478
- var _a2;
1479
- return (_a2 = assistDocument == null ? void 0 : assistDocument.fields) == null ? void 0 : _a2.flatMap(f => {
1480
- var _a3;
1481
- return (_a3 = f.instructions) != null ? _a3 : [];
1545
+ var _a3;
1546
+ return (_a3 = assistDocument == null ? void 0 : assistDocument.fields) == null ? void 0 : _a3.flatMap(f => {
1547
+ var _a4;
1548
+ return (_a4 = f.instructions) != null ? _a4 : [];
1482
1549
  });
1483
1550
  }, [assistDocument == null ? void 0 : assistDocument.fields]);
1484
1551
  const promptValue = instruction == null ? void 0 : instruction.prompt;
1485
1552
  const isEmptyPrompt = useMemo(() => {
1486
- var _a2, _b2;
1553
+ var _a3, _b3;
1487
1554
  if (!(promptValue == null ? void 0 : promptValue.length)) {
1488
1555
  return true;
1489
1556
  }
1490
1557
  const firstBlock = promptValue[0];
1491
1558
  const children = firstBlock == null ? void 0 : firstBlock.children;
1492
- return promptValue.length == 1 && (children == null ? void 0 : children.length) === 1 && !((_b2 = (_a2 = children == null ? void 0 : children[0]) == null ? void 0 : _a2.text) == null ? void 0 : _b2.length);
1559
+ return promptValue.length == 1 && (children == null ? void 0 : children.length) === 1 && !((_b3 = (_a3 = children == null ? void 0 : children[0]) == null ? void 0 : _a3.text) == null ? void 0 : _b3.length);
1493
1560
  }, [promptValue]);
1494
1561
  const paneNode = useMemo(() => ({
1495
1562
  type: "document",
@@ -1526,7 +1593,7 @@ function AssistInspector(props) {
1526
1593
  });
1527
1594
  }
1528
1595
  return /* @__PURE__ */jsxs(Flex, {
1529
- ref: setBoundary,
1596
+ ref: boundary,
1530
1597
  direction: "column",
1531
1598
  height: "fill",
1532
1599
  overflow: "hidden",
@@ -1552,7 +1619,8 @@ function AssistInspector(props) {
1552
1619
  children: /* @__PURE__ */jsx(Box, {
1553
1620
  padding: 4,
1554
1621
  children: selectedField && /* @__PURE__ */jsx(VirtualizerScrollInstanceProvider, {
1555
- scrollElement: boundary,
1622
+ scrollElement: boundary.current,
1623
+ containerElement: boundary,
1556
1624
  children: /* @__PURE__ */jsx(DocumentPaneProvider, {
1557
1625
  paneKey: documentPane.paneKey,
1558
1626
  index: documentPane.index,
@@ -1677,10 +1745,10 @@ const assistInspector = {
1677
1745
  showAsAction: false
1678
1746
  }),
1679
1747
  component: AssistInspectorWrapper,
1680
- onClose(_ref6) {
1748
+ onClose(_ref7) {
1681
1749
  let {
1682
1750
  params
1683
- } = _ref6;
1751
+ } = _ref7;
1684
1752
  return {
1685
1753
  params: typed({
1686
1754
  ...params,
@@ -1745,20 +1813,27 @@ function aiPresence(presence, path, title) {
1745
1813
  lastActiveAt: (_a = presence == null ? void 0 : presence.started) != null ? _a : /* @__PURE__ */new Date().toISOString()
1746
1814
  };
1747
1815
  }
1748
- const fadeIn = keyframes(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n 0% {\n opacity: 0;\n transform: scale(0.75);\n }\n 40% {\n opacity: 0;\n transform: scale(0.75);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n"])));
1749
- const FadeInDiv = styled.div(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["\n animation-name: ", ";\n animation-timing-function: ease-in-out;\n"])), fadeIn);
1750
- function FadeInContent(_ref7) {
1816
+ var __freeze$3 = Object.freeze;
1817
+ var __defProp$3 = Object.defineProperty;
1818
+ var __template$3 = (cooked, raw) => __freeze$3(__defProp$3(cooked, "raw", {
1819
+ value: __freeze$3(raw || cooked.slice())
1820
+ }));
1821
+ var _a$3, _b$1;
1822
+ const fadeIn = keyframes(_a$3 || (_a$3 = __template$3(["\n 0% {\n opacity: 0;\n transform: scale(0.75);\n }\n 40% {\n opacity: 0;\n transform: scale(0.75);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n"])));
1823
+ const FadeInDiv = styled.div(_b$1 || (_b$1 = __template$3(["\n animation-name: ", ";\n animation-timing-function: ease-in-out;\n"])), fadeIn);
1824
+ const FadeInContent = forwardRef(function FadeInContent2(_ref8, ref) {
1751
1825
  let {
1752
1826
  children,
1753
1827
  durationMs = 250
1754
- } = _ref7;
1828
+ } = _ref8;
1755
1829
  return /* @__PURE__ */jsx(FadeInDiv, {
1830
+ ref,
1756
1831
  style: {
1757
1832
  animationDuration: "".concat(durationMs, "ms")
1758
1833
  },
1759
1834
  children
1760
1835
  });
1761
- }
1836
+ });
1762
1837
  const purple = {
1763
1838
  "50": {
1764
1839
  title: "Purple 50",
@@ -1805,10 +1880,16 @@ const purple = {
1805
1880
  hex: "#211229"
1806
1881
  }
1807
1882
  };
1808
- const Root = styled.span(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["\n display: block;\n width: 25px;\n height: 25px;\n position: relative;\n"])));
1809
- const dash = keyframes(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["\n 0% {\n transform: rotate(0);\n }\n 100% {\n transform: rotate(43deg);\n }\n"])));
1810
- const Outline = styled.svg(_templateObject9 || (_templateObject9 = _taggedTemplateLiteral(["\n display: block;\n position: absolute;\n top: 0;\n left: 0;\n\n & > circle {\n stroke: var(--ai-avatar-stroke-color);\n stroke-width: 1.5px;\n stroke-linecap: round;\n transform-origin: center;\n animation: ", " 500ms ease-in-out infinite;\n transition: stroke-dasharray 200ms ease-in-out;\n\n stroke-dasharray: 2.34px 0;\n\n [data-state='active'] > & {\n stroke-dasharray: 2px 2.34px;\n }\n }\n"])), dash);
1811
- const IconDisc = styled.span(_templateObject10 || (_templateObject10 = _taggedTemplateLiteral(["\n background: var(--ai-avatar-disc-color);\n color: white;\n width: 21px;\n height: 21px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10.5px;\n position: absolute;\n top: 2px;\n left: 2px;\n"])));
1883
+ var __freeze$2 = Object.freeze;
1884
+ var __defProp$2 = Object.defineProperty;
1885
+ var __template$2 = (cooked, raw) => __freeze$2(__defProp$2(cooked, "raw", {
1886
+ value: __freeze$2(raw || cooked.slice())
1887
+ }));
1888
+ var _a$2, _b, _c, _d;
1889
+ const Root = styled.span(_a$2 || (_a$2 = __template$2(["\n display: block;\n width: 25px;\n height: 25px;\n position: relative;\n"])));
1890
+ const dash = keyframes(_b || (_b = __template$2(["\n 0% {\n transform: rotate(0);\n }\n 100% {\n transform: rotate(43deg);\n }\n"])));
1891
+ const Outline = styled.svg(_c || (_c = __template$2(["\n display: block;\n position: absolute;\n top: 0;\n left: 0;\n\n & > circle {\n stroke: var(--ai-avatar-stroke-color);\n stroke-width: 1.5px;\n stroke-linecap: round;\n transform-origin: center;\n animation: ", " 500ms ease-in-out infinite;\n transition: stroke-dasharray 200ms ease-in-out;\n\n stroke-dasharray: 2.34px 0;\n\n [data-state='active'] > & {\n stroke-dasharray: 2px 2.34px;\n }\n }\n"])), dash);
1892
+ const IconDisc = styled.span(_d || (_d = __template$2(["\n background: var(--ai-avatar-disc-color);\n color: white;\n width: 21px;\n height: 21px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 10.5px;\n position: absolute;\n top: 2px;\n left: 2px;\n"])));
1812
1893
  function AssistAvatar(props) {
1813
1894
  const {
1814
1895
  state = "present"
@@ -2526,7 +2607,7 @@ function AlphaMigration() {
2526
2607
  });
2527
2608
  useEffect(() => {
2528
2609
  let canUpdate = true;
2529
- client.fetch("\n {\n \"assistDocs\": *[_type==\"".concat(legacyAssistDocumentTypeName, "\"],\n \"staleStatusDocIds\": *[_type==\"").concat(legacyAssistStatusDocumentTypeName, "\"]._id,\n \"contextDocs\": *[_type==\"").concat(legacyContextDocumentTypeName, "\"],\n }\n ")).then(result => {
2610
+ client.fetch('\n {\n "assistDocs": *[_type=="'.concat(legacyAssistDocumentTypeName, '"],\n "staleStatusDocIds": *[_type=="').concat(legacyAssistStatusDocumentTypeName, '"]._id,\n "contextDocs": *[_type=="').concat(legacyContextDocumentTypeName, '"],\n }\n ')).then(result => {
2530
2611
  var _a, _b, _c;
2531
2612
  if (!canUpdate || !result) {
2532
2613
  return;
@@ -2648,7 +2729,7 @@ async function convertDocs(client, docs, updateProgress) {
2648
2729
  const progressCount = Math.min(docs.length, i + chunkSize);
2649
2730
  const chunk = docs.slice(i, progressCount);
2650
2731
  const trans = client.transaction();
2651
- const contextDocs = await client.fetch("*[_type==\"".concat(contextDocumentTypeName, "\" && _alphaId != null]{_id, _alphaId}"));
2732
+ const contextDocs = await client.fetch('*[_type=="'.concat(contextDocumentTypeName, '" && _alphaId != null]{_id, _alphaId}'));
2652
2733
  chunk.forEach(oldDoc => {
2653
2734
  var _a;
2654
2735
  const documentType = oldDoc._id.replace(new RegExp("^(".concat(legacyAssistDocumentIdPrefix, "|").concat(assistDocumentIdPrefix, ")")), "");
@@ -2756,7 +2837,13 @@ function AssistLayout(props) {
2756
2837
  })]
2757
2838
  });
2758
2839
  }
2759
- const WrapPreCard = styled(Card)(_templateObject11 || (_templateObject11 = _taggedTemplateLiteral(["\n & pre {\n white-space: pre-wrap !important;\n }\n"])));
2840
+ var __freeze$1 = Object.freeze;
2841
+ var __defProp$1 = Object.defineProperty;
2842
+ var __template$1 = (cooked, raw) => __freeze$1(__defProp$1(cooked, "raw", {
2843
+ value: __freeze$1(raw || cooked.slice())
2844
+ }));
2845
+ var _a$1;
2846
+ const WrapPreCard = styled(Card)(_a$1 || (_a$1 = __template$1(["\n & pre {\n white-space: pre-wrap !important;\n }\n"])));
2760
2847
  function SafeValueInput(props) {
2761
2848
  return /* @__PURE__ */jsx(ErrorWrapper, {
2762
2849
  onChange: props.onChange,
@@ -3033,13 +3120,13 @@ function useSelectedSchema(fieldPath, documentSchema) {
3033
3120
  return currentSchema;
3034
3121
  }, [documentSchema, fieldPath]);
3035
3122
  }
3036
- function FieldsInitializer(_ref8) {
3123
+ function FieldsInitializer(_ref9) {
3037
3124
  let {
3038
3125
  pathKey,
3039
3126
  activePath,
3040
3127
  fieldExists,
3041
3128
  onChange
3042
- } = _ref8;
3129
+ } = _ref9;
3043
3130
  const initialized = useRef(false);
3044
3131
  useEffect(() => {
3045
3132
  if (initialized.current || fieldExists || activePath || !pathKey) {
@@ -3211,8 +3298,8 @@ function IconInput(props) {
3211
3298
  onChange
3212
3299
  } = props;
3213
3300
  const id = useId();
3214
- const items = useMemo(() => Object.entries(icons).map(_ref9 => {
3215
- let [key, icon] = _ref9;
3301
+ const items = useMemo(() => Object.entries(icons).map(_ref10 => {
3302
+ let [key, icon] = _ref10;
3216
3303
  return /* @__PURE__ */jsx(IconItem, {
3217
3304
  iconKey: key,
3218
3305
  icon,
@@ -3240,12 +3327,12 @@ function IconInput(props) {
3240
3327
  }
3241
3328
  });
3242
3329
  }
3243
- function IconItem(_ref10) {
3330
+ function IconItem(_ref11) {
3244
3331
  let {
3245
3332
  icon,
3246
3333
  iconKey: key,
3247
3334
  onChange
3248
- } = _ref10;
3335
+ } = _ref11;
3249
3336
  const onClick = useCallback(() => onChange(set(key)), [onChange, key]);
3250
3337
  return /* @__PURE__ */jsx(MenuItem, {
3251
3338
  icon,
@@ -3256,8 +3343,8 @@ function IconItem(_ref10) {
3256
3343
  }
3257
3344
  function getIcon(iconName) {
3258
3345
  var _a, _b;
3259
- return (_b = (_a = Object.entries(icons).find(_ref11 => {
3260
- let [key] = _ref11;
3346
+ return (_b = (_a = Object.entries(icons).find(_ref12 => {
3347
+ let [key] = _ref12;
3261
3348
  return key === iconName;
3262
3349
  })) == null ? void 0 : _a[1]) != null ? _b : icons.sparkles;
3263
3350
  }
@@ -3468,7 +3555,7 @@ function HideReferenceChangedBannerInput(props) {
3468
3555
  const style = document.createElement("style");
3469
3556
  const parentId = "id-".concat(Math.random()).replace(".", "-");
3470
3557
  parent.id = parentId;
3471
- style.innerText = "\n #".concat(parentId, " [data-testid=\"reference-changed-banner\"] { display: none; }\n ");
3558
+ style.innerText = "\n #".concat(parentId, ' [data-testid="reference-changed-banner"] { display: none; }\n ');
3472
3559
  parent.prepend(style);
3473
3560
  }, [ref]);
3474
3561
  return /* @__PURE__ */jsx(Box, {
@@ -3511,11 +3598,11 @@ const contextDocumentSchema = defineType({
3511
3598
  title: "title",
3512
3599
  context: "context"
3513
3600
  },
3514
- prepare(_ref12) {
3601
+ prepare(_ref13) {
3515
3602
  let {
3516
3603
  title,
3517
3604
  context
3518
- } = _ref12;
3605
+ } = _ref13;
3519
3606
  var _a;
3520
3607
  const text = context == null ? void 0 : context.flatMap(block => block == null ? void 0 : block.children).flatMap(child => {
3521
3608
  var _a2;
@@ -3559,7 +3646,13 @@ function randomKey(length) {
3559
3646
  const table = getByteHexTable();
3560
3647
  return whatwgRNG(length).reduce((str, n) => str + table[n], "").slice(0, length);
3561
3648
  }
3562
- const PteMods = styled(Box)(_templateObject12 || (_templateObject12 = _taggedTemplateLiteral(["\n & [data-testid='pt-editor__toolbar-card'] > div > div:last-child {\n display: none;\n }\n & [data-testid='pt-editor'] {\n min-height: 300px;\n }\n & [data-testid='pt-editor'] .pt-inline-object * {\n max-width: 400px;\n }\n"])));
3649
+ var __freeze = Object.freeze;
3650
+ var __defProp = Object.defineProperty;
3651
+ var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", {
3652
+ value: __freeze(raw || cooked.slice())
3653
+ }));
3654
+ var _a;
3655
+ const PteMods = styled(Box)(_a || (_a = __template(["\n & [data-testid='pt-editor__toolbar-card'] > div > div:last-child {\n display: none;\n }\n & [data-testid='pt-editor'] {\n min-height: 300px;\n }\n & [data-testid='pt-editor'] .pt-inline-object * {\n max-width: 400px;\n }\n"])));
3563
3656
  function PromptInput(props) {
3564
3657
  useOnlyInlineBlocks(props);
3565
3658
  return /* @__PURE__ */jsx(PteMods, {
@@ -3568,9 +3661,9 @@ function PromptInput(props) {
3568
3661
  }
3569
3662
  function useOnlyInlineBlocks(props) {
3570
3663
  useEffect(() => {
3571
- var _a;
3664
+ var _a2;
3572
3665
  let needsFix = false;
3573
- const val = ((_a = props.value) != null ? _a : []).map(block => {
3666
+ const val = ((_a2 = props.value) != null ? _a2 : []).map(block => {
3574
3667
  if (block._type === "block") {
3575
3668
  return block;
3576
3669
  }
@@ -3625,7 +3718,7 @@ const fieldReference = defineType({
3625
3718
  const refs = getFieldRefsWithDocument(schema);
3626
3719
  const fieldRef = refs.find(r => r.key === value);
3627
3720
  if (!fieldRef) {
3628
- return "Field with path \"".concat(value, "\" does not exist in the schema.");
3721
+ return 'Field with path "'.concat(value, '" does not exist in the schema.');
3629
3722
  }
3630
3723
  return true;
3631
3724
  } catch (e) {
@@ -3638,10 +3731,10 @@ const fieldReference = defineType({
3638
3731
  select: {
3639
3732
  path: "path"
3640
3733
  },
3641
- prepare(_ref13) {
3734
+ prepare(_ref14) {
3642
3735
  let {
3643
3736
  path
3644
- } = _ref13;
3737
+ } = _ref14;
3645
3738
  return {
3646
3739
  title: path,
3647
3740
  path,
@@ -3787,12 +3880,12 @@ const instruction = defineType({
3787
3880
  title: "title",
3788
3881
  userId: "userId"
3789
3882
  },
3790
- prepare: _ref14 => {
3883
+ prepare: _ref15 => {
3791
3884
  let {
3792
3885
  icon,
3793
3886
  title,
3794
3887
  userId
3795
- } = _ref14;
3888
+ } = _ref15;
3796
3889
  return {
3797
3890
  title,
3798
3891
  icon: icon ? icons[icon] : SparklesIcon,
@@ -4080,6 +4173,100 @@ function PrivateIcon() {
4080
4173
  children: /* @__PURE__ */jsx(LockIcon, {})
4081
4174
  });
4082
4175
  }
4176
+ const ImageContext = createContext(void 0);
4177
+ function ImageContextProvider(props) {
4178
+ var _a;
4179
+ const {
4180
+ schemaType,
4181
+ path,
4182
+ value
4183
+ } = props;
4184
+ const assetRef = (_a = value == null ? void 0 : value.asset) == null ? void 0 : _a._ref;
4185
+ const [assetRefState, setAssetRefState] = useState(assetRef);
4186
+ const {
4187
+ documentId
4188
+ } = useAssistDocumentContext();
4189
+ const {
4190
+ config
4191
+ } = useAiAssistanceConfig();
4192
+ const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
4193
+ const {
4194
+ generateCaption
4195
+ } = useGenerateCaption(apiClient);
4196
+ useEffect(() => {
4197
+ const captionField = getCaptionFieldOption(schemaType);
4198
+ if (assetRef && documentId && captionField && assetRef !== assetRefState) {
4199
+ setAssetRefState(assetRef);
4200
+ generateCaption({
4201
+ path: pathToString([...path, captionField]),
4202
+ documentId
4203
+ });
4204
+ }
4205
+ }, [schemaType, path, assetRef, assetRefState, documentId, generateCaption]);
4206
+ const context = useMemo(() => {
4207
+ const captionField = getCaptionFieldOption(schemaType);
4208
+ return captionField ? {
4209
+ captionPath: pathToString([...path, captionField]),
4210
+ assetRef
4211
+ } : void 0;
4212
+ }, [schemaType, path, assetRef]);
4213
+ return /* @__PURE__ */jsx(ImageContext.Provider, {
4214
+ value: context,
4215
+ children: props.renderDefault(props)
4216
+ });
4217
+ }
4218
+ function node$1(node2) {
4219
+ return node2;
4220
+ }
4221
+ const generateCaptionsActions = {
4222
+ name: "sanity-assist-generate-captions",
4223
+ useAction(props) {
4224
+ const pathKey = usePathKey(props.path);
4225
+ const {
4226
+ config
4227
+ } = useAiAssistanceConfig();
4228
+ const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
4229
+ const {
4230
+ generateCaption,
4231
+ loading
4232
+ } = useGenerateCaption(apiClient);
4233
+ const imageContext = useContext(ImageContext);
4234
+ if (imageContext && pathKey === (imageContext == null ? void 0 : imageContext.captionPath)) {
4235
+ const {
4236
+ documentId
4237
+ } = useAssistDocumentContext();
4238
+ return useMemo(() => {
4239
+ return node$1({
4240
+ type: "action",
4241
+ icon: loading ? () => /* @__PURE__ */jsx(Box, {
4242
+ style: {
4243
+ height: 17
4244
+ },
4245
+ children: /* @__PURE__ */jsx(Spinner, {
4246
+ style: {
4247
+ transform: "translateY(6px)"
4248
+ }
4249
+ })
4250
+ }) : ImageIcon,
4251
+ title: "Generate caption",
4252
+ onAction: () => {
4253
+ if (loading) {
4254
+ return;
4255
+ }
4256
+ generateCaption({
4257
+ path: pathKey,
4258
+ documentId: documentId != null ? documentId : ""
4259
+ });
4260
+ },
4261
+ renderAsButton: true,
4262
+ disabled: loading,
4263
+ hidden: !imageContext.assetRef
4264
+ });
4265
+ }, [generateCaption, pathKey, documentId, loading, imageContext]);
4266
+ }
4267
+ return void 0;
4268
+ }
4269
+ };
4083
4270
  function node(node2) {
4084
4271
  return node2;
4085
4272
  }
@@ -4129,6 +4316,7 @@ const assistFieldActions = {
4129
4316
  const isInspectorOpen = (inspector == null ? void 0 : inspector.name) === aiInspectorId;
4130
4317
  const isPathSelected = pathKey === selectedPath;
4131
4318
  const isSelected = isInspectorOpen && isPathSelected;
4319
+ const imageCaptionAction = generateCaptionsActions.useAction(props);
4132
4320
  const manageInstructions = useCallback(() => isSelected ? closeInspector(aiInspectorId) : openInspector(aiInspectorId, {
4133
4321
  [fieldPathParam]: pathKey,
4134
4322
  [instructionParam]: void 0
@@ -4158,17 +4346,17 @@ const assistFieldActions = {
4158
4346
  type: "group",
4159
4347
  icon: () => null,
4160
4348
  title: "Run instructions",
4161
- children: instructions.map(instruction => instructionItem({
4349
+ children: [...instructions.map(instruction => instructionItem({
4162
4350
  instruction,
4163
4351
  isPrivate: Boolean(instruction.userId && instruction.userId === (currentUser == null ? void 0 : currentUser.id)),
4164
4352
  onInstructionAction,
4165
4353
  hidden: isHidden,
4166
4354
  documentIsNew: !!documentIsNew,
4167
4355
  assistSupported
4168
- })),
4356
+ })), imageCaptionAction].filter(Boolean),
4169
4357
  expanded: true
4170
4358
  }) : void 0;
4171
- }, [instructions, currentUser == null ? void 0 : currentUser.id, onInstructionAction, isHidden, documentIsNew, assistSupported]);
4359
+ }, [instructions, currentUser == null ? void 0 : currentUser.id, onInstructionAction, isHidden, documentIsNew, assistSupported, imageCaptionAction]);
4172
4360
  const instructionsLength = (instructions == null ? void 0 : instructions.length) || 0;
4173
4361
  const manageInstructionsItem = useMemo(() => node({
4174
4362
  type: "action",
@@ -4207,7 +4395,7 @@ const assistFieldActions = {
4207
4395
  title: pluginTitleShort,
4208
4396
  selected: isSelected
4209
4397
  }), [assistSupported, manageInstructions, isSelected]);
4210
- if (instructionsLength === 0) {
4398
+ if (instructionsLength === 0 && !imageCaptionAction) {
4211
4399
  return emptyAction;
4212
4400
  }
4213
4401
  return group;
@@ -4267,13 +4455,13 @@ function useInstructionToaster(documentId, documentSchemaType) {
4267
4455
  return !prevTask && task.ended || !(prevTask == null ? void 0 : prevTask.ended) && task.ended;
4268
4456
  }).filter(task => task.ended && isAfter(addSeconds(new Date(task.ended), 30), /* @__PURE__ */new Date()));
4269
4457
  endedTasks == null ? void 0 : endedTasks.forEach(task => {
4270
- var _a2;
4271
- const title = getInstructionTitle(task.instruction);
4458
+ var _a2, _b;
4459
+ const title = (_a2 = task.title) != null ? _a2 : getInstructionTitle(task.instruction);
4272
4460
  if (task.reason === "error") {
4273
4461
  toast.push({
4274
4462
  title: "Failed: ".concat(title),
4275
4463
  status: "error",
4276
- description: "Instruction failed. ".concat((_a2 = task.message) != null ? _a2 : ""),
4464
+ description: "Instruction failed. ".concat((_b = task.message) != null ? _b : ""),
4277
4465
  closable: true,
4278
4466
  duration: 1e4
4279
4467
  });
@@ -4320,11 +4508,11 @@ function AssistDocumentInputWrapper(props) {
4320
4508
  documentId
4321
4509
  });
4322
4510
  }
4323
- function AssistDocumentInput(_ref15) {
4511
+ function AssistDocumentInput(_ref16) {
4324
4512
  let {
4325
4513
  documentId,
4326
4514
  ...props
4327
- } = _ref15;
4515
+ } = _ref16;
4328
4516
  useInstructionToaster(documentId, props.schemaType);
4329
4517
  return /* @__PURE__ */jsx(FirstAssistedPathProvider, {
4330
4518
  members: props.members,
@@ -4413,12 +4601,12 @@ const assist = definePlugin(config => {
4413
4601
  unstable_fieldActions: prev => {
4414
4602
  return [...prev, assistFieldActions];
4415
4603
  },
4416
- unstable_languageFilter: (prev, _ref16) => {
4604
+ unstable_languageFilter: (prev, _ref17) => {
4417
4605
  let {
4418
4606
  documentId,
4419
4607
  schema,
4420
4608
  schemaType
4421
- } = _ref16;
4609
+ } = _ref17;
4422
4610
  const docSchema = schema.get(schemaType);
4423
4611
  return [...prev, createAssistDocumentPresence(documentId, docSchema)];
4424
4612
  }
@@ -4449,6 +4637,23 @@ const assist = definePlugin(config => {
4449
4637
  input: SafeValueInput
4450
4638
  }
4451
4639
  }
4640
+ })(), definePlugin({
4641
+ name: "".concat(packageName, "/generate-caption"),
4642
+ form: {
4643
+ components: {
4644
+ input: props => {
4645
+ const {
4646
+ schemaType
4647
+ } = props;
4648
+ if (isImage(schemaType)) {
4649
+ return /* @__PURE__ */jsx(ImageContextProvider, {
4650
+ ...props
4651
+ });
4652
+ }
4653
+ return props.renderDefault(props);
4654
+ }
4655
+ }
4656
+ }
4452
4657
  })()]
4453
4658
  };
4454
4659
  });