@sanity/assist 2.0.4-canary.0 → 2.0.5

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.
Files changed (91) hide show
  1. package/README.md +233 -214
  2. package/dist/index.esm.js +1769 -1769
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.js +1767 -1767
  5. package/dist/index.js.map +1 -1
  6. package/package.json +17 -18
  7. package/src/_lib/connector/ConnectFromRegion.tsx +4 -3
  8. package/src/_lib/connector/ConnectToRegion.tsx +1 -0
  9. package/src/_lib/connector/ConnectorRegion.tsx +2 -1
  10. package/src/_lib/connector/ConnectorsProvider.tsx +2 -1
  11. package/src/_lib/connector/ConnectorsStoreContext.ts +1 -0
  12. package/src/_lib/connector/index.ts +1 -1
  13. package/src/_lib/connector/mapConnectorToLine.ts +2 -2
  14. package/src/_lib/connector/useConnectorsStore.ts +2 -1
  15. package/src/_lib/connector/useRegionRects.ts +4 -3
  16. package/src/_lib/fixedListenQuery.ts +11 -11
  17. package/src/_lib/form/DocumentForm.tsx +4 -3
  18. package/src/_lib/form/helpers.ts +2 -1
  19. package/src/_lib/useListeningQuery.ts +4 -3
  20. package/src/assistConnectors/AssistConnectorsOverlay.tsx +1 -0
  21. package/src/assistConnectors/ConnectorPath.tsx +3 -2
  22. package/src/assistConnectors/draw/connectorPath.ts +13 -13
  23. package/src/assistDocument/AssistDocumentContext.tsx +3 -2
  24. package/src/assistDocument/AssistDocumentContextProvider.tsx +2 -1
  25. package/src/assistDocument/AssistDocumentInput.tsx +9 -8
  26. package/src/assistDocument/RequestRunInstructionProvider.tsx +4 -3
  27. package/src/assistDocument/components/AssistDocumentForm.tsx +25 -24
  28. package/src/assistDocument/components/FieldRefPreview.tsx +4 -3
  29. package/src/assistDocument/components/InstructionsArrayInput.tsx +4 -3
  30. package/src/assistDocument/components/SelectedFieldContext.tsx +1 -1
  31. package/src/assistDocument/components/helpers.ts +4 -4
  32. package/src/assistDocument/components/instruction/BackToInstructionsLink.tsx +3 -2
  33. package/src/assistDocument/components/instruction/FieldRefInput.tsx +5 -4
  34. package/src/assistDocument/components/instruction/InstructionInput.tsx +3 -2
  35. package/src/assistDocument/components/instruction/InstructionOutputField.tsx +2 -1
  36. package/src/assistDocument/components/instruction/InstructionOutputInput.tsx +14 -13
  37. package/src/assistDocument/components/instruction/PromptInput.tsx +4 -3
  38. package/src/assistDocument/components/instruction/appearance/IconInput.tsx +2 -2
  39. package/src/assistDocument/components/instruction/appearance/InstructionVisibility.tsx +1 -1
  40. package/src/assistDocument/hooks/useAssistDocumentContextValue.tsx +7 -6
  41. package/src/assistDocument/hooks/useInstructionToaster.tsx +6 -5
  42. package/src/assistDocument/hooks/useStudioAssistDocument.ts +14 -13
  43. package/src/assistFormComponents/AssistField.tsx +9 -8
  44. package/src/assistFormComponents/AssistFormBlock.tsx +5 -4
  45. package/src/assistFormComponents/AssistInlineFormBlock.tsx +1 -1
  46. package/src/assistFormComponents/AssistItem.tsx +3 -2
  47. package/src/assistFormComponents/validation/listItem.tsx +2 -2
  48. package/src/assistFormComponents/validation/validationList.tsx +3 -2
  49. package/src/assistInspector/AssistInspector.tsx +16 -15
  50. package/src/assistInspector/FieldAutocomplete.tsx +4 -3
  51. package/src/assistInspector/InstructionTaskHistoryButton.tsx +19 -18
  52. package/src/assistInspector/helpers.ts +10 -9
  53. package/src/assistInspector/index.ts +4 -3
  54. package/src/assistLayout/AiAssistanceConfigContext.tsx +1 -0
  55. package/src/assistLayout/AssistLayout.tsx +5 -4
  56. package/src/assistLayout/RunInstructionProvider.tsx +18 -15
  57. package/src/components/FadeInContent.tsx +1 -1
  58. package/src/components/HideReferenceChangedBannerInput.tsx +1 -1
  59. package/src/components/ImageContext.tsx +4 -3
  60. package/src/components/SafeValueInput.tsx +7 -6
  61. package/src/components/TimeAgo.tsx +1 -1
  62. package/src/fieldActions/assistFieldActions.tsx +31 -30
  63. package/src/fieldActions/generateCaptionActions.tsx +8 -7
  64. package/src/fieldActions/generateImageActions.tsx +6 -5
  65. package/src/helpers/assistSupported.ts +1 -0
  66. package/src/helpers/conditionalMembers.test.ts +2 -1
  67. package/src/helpers/conditionalMembers.ts +17 -14
  68. package/src/helpers/misc.ts +3 -2
  69. package/src/helpers/typeUtils.ts +1 -1
  70. package/src/helpers/useAssistSupported.ts +2 -1
  71. package/src/onboarding/FieldActionsOnboarding.tsx +2 -1
  72. package/src/onboarding/FirstAssistedPathProvider.tsx +4 -3
  73. package/src/onboarding/InspectorOnboarding.tsx +3 -2
  74. package/src/onboarding/onboardingStore.ts +1 -1
  75. package/src/presence/AiFieldPresence.tsx +3 -1
  76. package/src/presence/AssistDocumentPresence.tsx +7 -6
  77. package/src/presence/useAssistPresence.ts +6 -3
  78. package/src/schemas/assistDocumentSchema.tsx +21 -20
  79. package/src/schemas/contextDocumentSchema.tsx +3 -2
  80. package/src/schemas/index.ts +2 -1
  81. package/src/schemas/serialize/SchemTypeTool.tsx +4 -3
  82. package/src/schemas/serialize/serializeSchema.test.ts +3 -2
  83. package/src/schemas/serialize/serializeSchema.ts +15 -14
  84. package/src/schemas/serializedSchemaTypeSchema.ts +2 -1
  85. package/src/translate/FieldTranslationProvider.tsx +33 -25
  86. package/src/translate/getLanguageParams.ts +3 -3
  87. package/src/translate/paths.test.ts +11 -4
  88. package/src/translate/paths.ts +12 -11
  89. package/src/translate/translateActions.tsx +12 -11
  90. package/src/translate/types.ts +2 -2
  91. package/src/useApiClient.ts +9 -9
package/dist/index.esm.js CHANGED
@@ -1,38 +1,17 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { useClient, isArraySchemaType, typed, useSchema, isKeySegment, isDocumentSchemaType, pathToString, useDocumentStore, useDocumentPresence, createPatchChannel, FormBuilder, fromMutationPatches, isObjectSchemaType, stringToPath as stringToPath$2, useEditState, useCurrentUser, StatusButton, FormFieldHeaderText, PatchEvent, unset, set, useFormCallbacks, FormCallbacksProvider, FormInput, setIfMissing, insert, PresenceOverlay, VirtualizerScrollInstanceProvider, useColorSchemeValue, ObjectInputMember, defineType, defineField, defineArrayMember, isArrayOfObjectsSchemaType, getPublishedId, useSyncState, definePlugin } from 'sanity';
3
- import { Card, Stack, Box, Button, Spinner, Flex, Label, focusFirstDescendant, Text, useClickOutside, Popover, useLayer, useGlobalKeyDown, useToast, Dialog, Tooltip, TextArea, Container, Autocomplete, Breadcrumbs, Badge, useTheme, rgba, Checkbox, Radio, ThemeProvider, ErrorBoundary, Switch, MenuButton, Menu, MenuItem } from '@sanity/ui';
4
- import { useState, useRef, useEffect, useMemo, useCallback, createContext, useReducer, forwardRef, createElement, useContext, useId } from 'react';
5
- import { SyncIcon, DocumentIcon, LinkIcon, ImageIcon, BlockContentIcon, OlistIcon, BlockquoteIcon, StringIcon, ErrorOutlineIcon, CheckmarkCircleIcon, CloseCircleIcon, ClockIcon, PlayIcon, SparklesIcon, ArrowLeftIcon, SearchIcon, RetryIcon, ArrowRightIcon, CloseIcon, CheckmarkIcon, icons, TokenIcon, DocumentTextIcon, ThListIcon, CodeIcon, ComposeIcon, LockIcon, TranslateIcon, ControlsIcon } from '@sanity/icons';
6
- import { mergeMap, share, take, filter, distinctUntilChanged, catchError, tap } from 'rxjs/operators';
2
+ import { SyncIcon, DocumentIcon, LinkIcon, ImageIcon, BlockContentIcon, OlistIcon, BlockquoteIcon, StringIcon, ArrowLeftIcon, PlayIcon, SparklesIcon, SearchIcon, ErrorOutlineIcon, CheckmarkCircleIcon, CloseCircleIcon, ClockIcon, RetryIcon, ArrowRightIcon, CloseIcon, CheckmarkIcon, icons, TokenIcon, DocumentTextIcon, ThListIcon, CodeIcon, ComposeIcon, LockIcon, TranslateIcon, ControlsIcon } from '@sanity/icons';
3
+ import { Card, Stack, Box, Button, Spinner, Flex, Label, focusFirstDescendant, Text, useToast, Dialog, Tooltip, TextArea, Container, Autocomplete, Breadcrumbs, useClickOutside, Popover, useLayer, useGlobalKeyDown, Badge, useTheme, rgba, Checkbox, Radio, ThemeProvider, ErrorBoundary, MenuButton, Menu, MenuItem, Switch } from '@sanity/ui';
4
+ import { useState, useRef, useEffect, useMemo, useCallback, createContext, useContext, useId, createElement, useReducer, forwardRef } from 'react';
5
+ import { useClient, isArraySchemaType, typed, useSchema, isKeySegment, isDocumentSchemaType, pathToString, useDocumentStore, useDocumentPresence, createPatchChannel, FormBuilder, fromMutationPatches, isObjectSchemaType, stringToPath as stringToPath$2, useCurrentUser, set, useFormCallbacks, FormCallbacksProvider, FormInput, PatchEvent, setIfMissing, insert, useEditState, FormFieldHeaderText, unset, StatusButton, PresenceOverlay, VirtualizerScrollInstanceProvider, useColorSchemeValue, ObjectInputMember, isArrayOfObjectsSchemaType, defineType, defineField, defineArrayMember, getPublishedId, useSyncState, definePlugin } from 'sanity';
7
6
  import isEqual from 'react-fast-compare';
7
+ import { mergeMap, share, take, filter, distinctUntilChanged, catchError, tap } from 'rxjs/operators';
8
8
  import { throwError, of, partition, merge, switchMap, delay, defer } from 'rxjs';
9
9
  import { exhaustMapToWithTrailing } from 'rxjs-exhaustmap-with-trailing';
10
10
  import { extractWithPath } from '@sanity/mutator';
11
+ import { minutesToMilliseconds, isAfter, addSeconds } from 'date-fns';
11
12
  import { useDocumentPane, usePaneRouter, DocumentInspectorHeader, DocumentPaneProvider } from 'sanity/desk';
12
13
  import styled, { keyframes } from 'styled-components';
13
- import { minutesToMilliseconds, isAfter, addSeconds } from 'date-fns';
14
14
  import formatDistanceToNow from 'date-fns/formatDistanceToNow';
15
- const assistDocumentIdPrefix = "sanity.assist.schemaType.";
16
- const assistDocumentStatusIdPrefix = "sanity.assist.status.";
17
- const assistSchemaIdPrefix = "sanity.assist.schema.";
18
- const assistDocumentTypeName = "sanity.assist.schemaType.annotations";
19
- const assistFieldTypeName = "sanity.assist.schemaType.field";
20
- const instructionTypeName = "sanity.assist.instruction";
21
- const promptTypeName = "sanity.assist.instruction.prompt";
22
- const userInputTypeName = "sanity.assist.instruction.userInput";
23
- const instructionContextTypeName = "sanity.assist.instruction.context";
24
- const fieldReferenceTypeName = "sanity.assist.instruction.fieldRef";
25
- const contextDocumentTypeName = "assist.instruction.context";
26
- const assistTasksStatusTypeName = "sanity.assist.task.status";
27
- const instructionTaskTypeName = "sanity.assist.instructionTask";
28
- const fieldPresenceTypeName = "sanity.assist.instructionTask.presence";
29
- const assistSerializedTypeName = "sanity.assist.serialized.type";
30
- const assistSerializedFieldTypeName = "sanity.assist.serialized.field";
31
- const outputFieldTypeName = "sanity.assist.output.field";
32
- const outputTypeTypeName = "sanity.assist.output.type";
33
- const fieldPathParam = "pathKey";
34
- const instructionParam = "instruction";
35
- const documentRootKey = "<document>";
36
15
  const fetch = (client, query, params, options) => defer(() =>
37
16
  // getVersionedClient(options.apiVersion)
38
17
  client.observable.fetch(query, params, {
@@ -110,7 +89,27 @@ function useListeningQuery(query) {
110
89
  data
111
90
  };
112
91
  }
113
- const hiddenTypes = ["any", "array", "block", "boolean", "crossDatasetReference", "date", "datetime", "document", "email", "file", "image", "number", "object", "reference", "span", "string", "text", "url", "slug", "geopoint", "sanity.assetSourceData", "sanity.imageAsset", "sanity.fileAsset", "sanity.imageCrop", "sanity.imageHotspot", "sanity.imageMetadata", "sanity.imageDimensions", "sanity.imagePalette", "sanity.imagePaletteSwatch", assistSerializedTypeName, assistSerializedFieldTypeName, "sanity-agent.job.document"];
92
+ const assistDocumentIdPrefix = "sanity.assist.schemaType.";
93
+ const assistDocumentStatusIdPrefix = "sanity.assist.status.";
94
+ const assistSchemaIdPrefix = "sanity.assist.schema.";
95
+ const assistDocumentTypeName = "sanity.assist.schemaType.annotations";
96
+ const assistFieldTypeName = "sanity.assist.schemaType.field";
97
+ const instructionTypeName = "sanity.assist.instruction";
98
+ const promptTypeName = "sanity.assist.instruction.prompt";
99
+ const userInputTypeName = "sanity.assist.instruction.userInput";
100
+ const instructionContextTypeName = "sanity.assist.instruction.context";
101
+ const fieldReferenceTypeName = "sanity.assist.instruction.fieldRef";
102
+ const contextDocumentTypeName = "assist.instruction.context";
103
+ const assistTasksStatusTypeName = "sanity.assist.task.status";
104
+ const instructionTaskTypeName = "sanity.assist.instructionTask";
105
+ const fieldPresenceTypeName = "sanity.assist.instructionTask.presence";
106
+ const assistSerializedTypeName = "sanity.assist.serialized.type";
107
+ const assistSerializedFieldTypeName = "sanity.assist.serialized.field";
108
+ const outputFieldTypeName = "sanity.assist.output.field";
109
+ const outputTypeTypeName = "sanity.assist.output.type";
110
+ const fieldPathParam = "pathKey";
111
+ const instructionParam = "instruction";
112
+ const documentRootKey = "<document>";
114
113
  function isPortableTextArray(type) {
115
114
  return type.of.find(t => isType(t, "block"));
116
115
  }
@@ -176,6 +175,7 @@ function isUnsupportedType(type) {
176
175
  var _a, _b;
177
176
  return type.jsonType === "number" || type.name === "sanity.imageCrop" || type.name === "sanity.imageHotspot" || isType(type, "reference") && !((_b = (_a = type == null ? void 0 : type.options) == null ? void 0 : _a.aiAssist) == null ? void 0 : _b.embeddingsIndex) || isType(type, "crossDatasetReference") || isType(type, "slug") || isType(type, "url") || isType(type, "date") || isType(type, "datetime") || isType(type, "file");
178
177
  }
178
+ const hiddenTypes = ["any", "array", "block", "boolean", "crossDatasetReference", "date", "datetime", "document", "email", "file", "image", "number", "object", "reference", "span", "string", "text", "url", "slug", "geopoint", "sanity.assetSourceData", "sanity.imageAsset", "sanity.fileAsset", "sanity.imageCrop", "sanity.imageHotspot", "sanity.imageMetadata", "sanity.imageDimensions", "sanity.imagePalette", "sanity.imagePaletteSwatch", assistSerializedTypeName, assistSerializedFieldTypeName, "sanity-agent.job.document"];
179
179
  const inlineTypes = ["document", "object", "image", "file"];
180
180
  function serializeSchema(schema, options) {
181
181
  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, options)).filter(t => {
@@ -506,7 +506,14 @@ function getFieldLanguageMap(documentSchema, documentMembers, translateFromLangu
506
506
  }
507
507
  return translationMaps;
508
508
  }
509
- const aiInspectorId = "ai-assistance";
509
+ const releaseAnnouncementUrl = "https://www.sanity.io/blog/sanity-ai-assist-announcement?utm_source=sanity-assist-plugin&utm_medium=organic_social&utm_campaign=ai-assist&utm_content=";
510
+ const instructionGuideUrl = "https://sanity.io/guides/getting-started-with-ai-assist-instructions?utm_source=sanity-assist-plugin&utm_medium=organic_social&utm_campaign=ai-assist&utm_content=";
511
+ const giveFeedbackUrl = "https://forms.gle/Kwz7CThxGeA2GiEU8";
512
+ const salesUrl = "https://www.sanity.io/contact/sales?utm_source=sanity-assist-plugin&utm_medium=organic_social&utm_campaign=ai-assist&utm_content=";
513
+ const packageName = "@sanity/assist";
514
+ const pluginTitle = "Sanity AI Assist";
515
+ const pluginTitleShort = "AI Assist";
516
+ const maxHistoryVisibilityMs = minutesToMilliseconds(30);
510
517
  const assistFormId = "assist";
511
518
  const preventDefault = ev => ev.preventDefault();
512
519
  function DocumentForm(props) {
@@ -784,334 +791,107 @@ function useAiPaneRouter() {
784
791
  };
785
792
  }, [paneRouter]);
786
793
  }
787
- function useDocumentState(id, docType) {
788
- const state = useEditState(id, docType);
789
- return state.draft || state.published;
790
- }
791
- const aiDocPrefixPattern = new RegExp("^".concat(assistDocumentIdPrefix));
792
- function publicId(id) {
793
- return id.replace("drafts.", "");
794
- }
795
- function assistDocumentId(documentType) {
796
- return "".concat(assistDocumentIdPrefix).concat(documentType);
797
- }
798
- function documentTypeFromAiDocumentId(id) {
799
- return id.replace(aiDocPrefixPattern, "");
800
- }
801
- function assistTasksStatusId(documentId) {
802
- return "".concat(assistDocumentStatusIdPrefix).concat(publicId(documentId));
794
+ const basePath = "/assist/tasks/instruction";
795
+ function canUseAssist(status) {
796
+ return (status == null ? void 0 : status.enabled) && status.initialized && status.validToken;
803
797
  }
804
- const releaseAnnouncementUrl = "https://www.sanity.io/blog/sanity-ai-assist-announcement?utm_source=sanity-assist-plugin&utm_medium=organic_social&utm_campaign=ai-assist&utm_content=";
805
- const instructionGuideUrl = "https://sanity.io/guides/getting-started-with-ai-assist-instructions?utm_source=sanity-assist-plugin&utm_medium=organic_social&utm_campaign=ai-assist&utm_content=";
806
- const giveFeedbackUrl = "https://forms.gle/Kwz7CThxGeA2GiEU8";
807
- const salesUrl = "https://www.sanity.io/contact/sales?utm_source=sanity-assist-plugin&utm_medium=organic_social&utm_campaign=ai-assist&utm_content=";
808
- const packageName = "@sanity/assist";
809
- const pluginTitle = "Sanity AI Assist";
810
- const pluginTitleShort = "AI Assist";
811
- const maxHistoryVisibilityMs = minutesToMilliseconds(30);
812
- function useStudioAssistDocument(_ref2) {
813
- let {
814
- documentId,
815
- schemaType,
816
- initDoc
817
- } = _ref2;
818
- const documentTypeName = schemaType.name;
819
- const currentUser = useCurrentUser();
820
- const assistDocument = useDocumentState(assistDocumentId(documentTypeName), assistDocumentTypeName);
821
- const assistTasksStatus = useDocumentState(assistTasksStatusId(documentId != null ? documentId : ""), assistTasksStatusTypeName);
798
+ function useApiClient(customApiClient) {
822
799
  const client = useClient({
823
- apiVersion: "2023-01-01"
824
- });
825
- useEffect(() => {
826
- if (!assistDocument && initDoc) {
827
- client.createIfNotExists({
828
- _id: assistDocumentId(documentTypeName),
829
- _type: assistDocumentTypeName
830
- }).catch(e => {});
831
- }
832
- }, [client, assistDocument, documentTypeName, initDoc]);
833
- return useMemo(() => {
834
- var _a, _b;
835
- if (!assistDocument) {
836
- return void 0;
837
- }
838
- const tasks = (_a = assistTasksStatus == null ? void 0 : assistTasksStatus.tasks) != null ? _a : [];
839
- const fields = ((_b = assistDocument == null ? void 0 : assistDocument.fields) != null ? _b : []).map(assistField => {
840
- var _a2;
841
- return {
842
- ...assistField,
843
- tasks: tasks.filter(task => task.path === assistField.path),
844
- instructions: (_a2 = assistField.instructions) == null ? void 0 : _a2.filter(p => !p.userId || p.userId === (currentUser == null ? void 0 : currentUser.id)).map(instruction => asStudioInstruction(instruction, tasks))
845
- };
846
- });
847
- return typed({
848
- ...assistDocument,
849
- tasks: tasks == null ? void 0 : tasks.map(task => {
850
- var _a2, _b2;
851
- const instruction = (_b2 = (_a2 = fields.find(f => f.path === task.path)) == null ? void 0 : _a2.instructions) == null ? void 0 : _b2.find(i => i._key === task.instructionKey);
852
- return {
853
- ...task,
854
- instruction
855
- };
856
- }),
857
- fields
858
- });
859
- }, [assistDocument, assistTasksStatus, currentUser]);
860
- }
861
- function asStudioInstruction(instruction, run) {
862
- return {
863
- ...instruction,
864
- tasks: run.filter(task => task.instructionKey === instruction._key).filter(task => task.started && ( /* @__PURE__ */new Date()).getTime() - new Date(task.started).getTime() < maxHistoryVisibilityMs)
865
- };
866
- }
867
- function useInterval(ms) {
868
- const [tick, update] = useReducer(n => n + 1, 0);
869
- useEffect(() => {
870
- const i = setInterval(update, ms);
871
- return () => clearInterval(i);
872
- }, [ms]);
873
- return tick;
874
- }
875
- function TimeAgo(_ref3) {
876
- let {
877
- date
878
- } = _ref3;
879
- useInterval(1e3);
880
- const timeSince = formatDistanceToNow(date ? new Date(date) : /* @__PURE__ */new Date());
881
- return /* @__PURE__ */jsxs("span", {
882
- title: timeSince,
883
- children: [timeSince, " ago"]
800
+ apiVersion: "2023-06-05"
884
801
  });
802
+ return useMemo(() => customApiClient ? customApiClient(client) : client, [client, customApiClient]);
885
803
  }
886
- function usePathKey(path) {
887
- return useMemo(() => {
888
- return getPathKey(path);
889
- }, [path]);
890
- }
891
- function getPathKey(path) {
892
- if (path.length) {
893
- return Array.isArray(path) ? pathToString(path) : path;
894
- }
895
- return documentRootKey;
804
+ function useTranslate(apiClient) {
805
+ const [loading, setLoading] = useState(false);
806
+ const user = useCurrentUser();
807
+ const schema = useSchema();
808
+ const types = useMemo(() => serializeSchema(schema, {
809
+ leanFormat: true
810
+ }), [schema]);
811
+ const toast = useToast();
812
+ const translate = useCallback(_ref2 => {
813
+ let {
814
+ documentId,
815
+ languagePath,
816
+ translatePath,
817
+ fieldLanguageMap,
818
+ conditionalMembers
819
+ } = _ref2;
820
+ setLoading(true);
821
+ return apiClient.request({
822
+ method: "POST",
823
+ url: "/assist/tasks/translate/".concat(apiClient.config().dataset, "?projectId=").concat(apiClient.config().projectId),
824
+ body: {
825
+ documentId,
826
+ types,
827
+ languagePath,
828
+ fieldLanguageMap,
829
+ conditionalMembers,
830
+ translatePath: translatePath.length === 0 ? documentRootKey : pathToString(translatePath),
831
+ userId: user == null ? void 0 : user.id
832
+ }
833
+ }).catch(e => {
834
+ toast.push({
835
+ status: "error",
836
+ title: "Translate failed",
837
+ description: e.message
838
+ });
839
+ setLoading(false);
840
+ throw e;
841
+ }).finally(() => {
842
+ setTimeout(() => {
843
+ setLoading(false);
844
+ }, 2e3);
845
+ });
846
+ }, [setLoading, apiClient, toast, user, types]);
847
+ return useMemo(() => ({
848
+ translate,
849
+ loading
850
+ }), [translate, loading]);
896
851
  }
897
- function getInstructionTitle(instruction) {
898
- var _a;
899
- return (_a = instruction == null ? void 0 : instruction.title) != null ? _a : "Untitled";
852
+ function useGenerateCaption(apiClient) {
853
+ const [loading, setLoading] = useState(false);
854
+ const user = useCurrentUser();
855
+ const schema = useSchema();
856
+ const types = useMemo(() => serializeSchema(schema, {
857
+ leanFormat: true
858
+ }), [schema]);
859
+ const toast = useToast();
860
+ const generateCaption = useCallback(_ref3 => {
861
+ let {
862
+ path,
863
+ documentId
864
+ } = _ref3;
865
+ setLoading(true);
866
+ return apiClient.request({
867
+ method: "POST",
868
+ url: "/assist/tasks/generate-caption/".concat(apiClient.config().dataset, "?projectId=").concat(apiClient.config().projectId),
869
+ body: {
870
+ path,
871
+ documentId,
872
+ types,
873
+ userId: user == null ? void 0 : user.id
874
+ }
875
+ }).catch(e => {
876
+ toast.push({
877
+ status: "error",
878
+ title: "Generate image description failed",
879
+ description: e.message
880
+ });
881
+ setLoading(false);
882
+ throw e;
883
+ }).finally(() => {
884
+ setTimeout(() => {
885
+ setLoading(false);
886
+ }, 2e3);
887
+ });
888
+ }, [setLoading, apiClient, toast, user, types]);
889
+ return useMemo(() => ({
890
+ generateCaption,
891
+ loading
892
+ }), [generateCaption, loading]);
900
893
  }
901
- var __freeze$5 = Object.freeze;
902
- var __defProp$5 = Object.defineProperty;
903
- var __template$5 = (cooked, raw) => __freeze$5(__defProp$5(cooked, "raw", {
904
- value: __freeze$5(raw || cooked.slice())
905
- }));
906
- var _a$5, _b$3;
907
- const rotate = keyframes(_a$5 || (_a$5 = __template$5(["\n 0% {\n transform: rotate(0);\n }\n 100% {\n transform: rotate(360deg);\n }\n"])));
908
- const SyncSpinningIcon = styled(SyncIcon)(_b$3 || (_b$3 = __template$5(["\n animation: ", " 1s linear infinite;\n"])), rotate);
909
- const TASK_CONFIG = {
910
- aborted: {
911
- title: "Canceled",
912
- icon: CloseCircleIcon,
913
- tone: "transparent"
914
- },
915
- error: {
916
- title: "Error",
917
- icon: ErrorOutlineIcon,
918
- tone: "critical"
919
- },
920
- success: {
921
- title: "Completed",
922
- icon: CheckmarkCircleIcon,
923
- tone: "positive"
924
- },
925
- timeout: {
926
- title: "Timeout",
927
- icon: ClockIcon,
928
- tone: "caution"
929
- }
930
- };
931
- function InstructionTaskHistoryButton(props) {
932
- const {
933
- tasks,
934
- instructions,
935
- documentId,
936
- showTitles
937
- } = props;
938
- const client = useClient({
939
- apiVersion: "2023-01-01"
940
- });
941
- const cancelRun = useCallback(taskKey => {
942
- if (!documentId) {
943
- return;
944
- }
945
- const statusDocId = assistTasksStatusId(documentId);
946
- const basePath = "".concat(typed("tasks"), '[_key=="').concat(taskKey, '"]');
947
- client.patch(statusDocId).set({
948
- ["".concat(basePath, ".").concat(typed("ended"))]: ( /* @__PURE__ */new Date()).toISOString(),
949
- ["".concat(basePath, ".").concat(typed("reason"))]: typed("aborted")
950
- }).commit().catch(console.error);
951
- }, [client, documentId]);
952
- const titledTasks = useMemo(() => {
953
- var _a2;
954
- const t = (_a2 = tasks == null ? void 0 : tasks.filter(task => task.started && ( /* @__PURE__ */new Date()).getTime() - new Date(task.started).getTime() < maxHistoryVisibilityMs).map(task => {
955
- var _a3;
956
- const instruction = instructions == null ? void 0 : instructions.find(i => i._key === task.instructionKey);
957
- return {
958
- ...task,
959
- title: showTitles ? (_a3 = task.title) != null ? _a3 : getInstructionTitle(instruction) : void 0,
960
- cancel: () => cancelRun(task._key)
961
- };
962
- })) != null ? _a2 : [];
963
- t.sort((a, b) => {
964
- var _a3, _b2;
965
- return new Date((_a3 = b.started) != null ? _a3 : "").getTime() - new Date((_b2 = a.started) != null ? _b2 : "").getTime();
966
- });
967
- return t;
968
- }, [tasks, instructions, cancelRun, showTitles]);
969
- const isRunning = useMemo(() => titledTasks.some(r => !r.ended), [titledTasks]);
970
- const hasErrors = useMemo(() => titledTasks.some(r => r.reason === "error" || r.reason === "timeout"), [titledTasks]);
971
- const [open, setOpen] = useState(false);
972
- const toggleOpen = useCallback(() => setOpen(v => !v), []);
973
- const [button, setButton] = useState(null);
974
- const [popover, setPopover] = useState(null);
975
- const handleClickOutside = useCallback(() => {
976
- setOpen(false);
977
- }, []);
978
- useClickOutside(handleClickOutside, [button, popover]);
979
- const handleEscape = useCallback(() => {
980
- setOpen(false);
981
- button == null ? void 0 : button.focus();
982
- }, [button]);
983
- return /* @__PURE__ */jsx(Popover, {
984
- constrainSize: true,
985
- content: /* @__PURE__ */jsx(TaskList, {
986
- onEscape: handleEscape,
987
- tasks: titledTasks
988
- }),
989
- open: open && !!(titledTasks == null ? void 0 : titledTasks.length),
990
- placement: "top",
991
- portal: true,
992
- ref: setPopover,
993
- width: 0,
994
- children: /* @__PURE__ */jsx(TaskStatusButton, {
995
- disabled: !(titledTasks == null ? void 0 : titledTasks.length),
996
- hasErrors,
997
- isRunning,
998
- onClick: toggleOpen,
999
- ref: setButton,
1000
- selected: open
1001
- })
1002
- });
1003
- }
1004
- const TASK_STATUS_BUTTON_TOOLTIP_PROPS = {
1005
- placement: "top"
1006
- };
1007
- const TaskStatusButton = forwardRef(function TaskStatusButton2(props, ref) {
1008
- const {
1009
- disabled,
1010
- hasErrors,
1011
- isRunning,
1012
- onClick,
1013
- selected
1014
- } = props;
1015
- return /* @__PURE__ */jsx(StatusButton, {
1016
- label: "".concat(pluginTitle, " status"),
1017
- icon: isRunning ? SyncSpinningIcon : hasErrors ? ErrorOutlineIcon : CheckmarkCircleIcon,
1018
- mode: "bleed",
1019
- onClick,
1020
- tone: hasErrors ? "critical" : void 0,
1021
- disabled,
1022
- ref,
1023
- selected,
1024
- tooltipProps: TASK_STATUS_BUTTON_TOOLTIP_PROPS
1025
- });
1026
- });
1027
- function TaskList(props) {
1028
- const {
1029
- onEscape,
1030
- tasks
1031
- } = props;
1032
- const {
1033
- isTopLayer
1034
- } = useLayer();
1035
- useGlobalKeyDown(useCallback(event => {
1036
- if (isTopLayer && event.key === "Escape") {
1037
- onEscape();
1038
- }
1039
- }, [isTopLayer, onEscape]));
1040
- return /* @__PURE__ */jsx(Stack, {
1041
- padding: 1,
1042
- space: 1,
1043
- children: tasks.map(task => /* @__PURE__ */jsx(TaskItem, {
1044
- task
1045
- }, task._key))
1046
- });
1047
- }
1048
- function TaskItem(props) {
1049
- var _a2;
1050
- const {
1051
- task
1052
- } = props;
1053
- const taskType = task.reason && TASK_CONFIG[task.reason];
1054
- return /* @__PURE__ */jsx(Card, {
1055
- radius: 2,
1056
- tone: taskType && (taskType == null ? void 0 : taskType.tone),
1057
- children: /* @__PURE__ */jsxs(Flex, {
1058
- align: "center",
1059
- gap: 1,
1060
- children: [/* @__PURE__ */jsxs(Flex, {
1061
- align: "flex-start",
1062
- flex: 1,
1063
- gap: 3,
1064
- padding: 3,
1065
- children: [/* @__PURE__ */jsx(Box, {
1066
- flex: "none",
1067
- children: /* @__PURE__ */jsxs(Text, {
1068
- size: 1,
1069
- children: [taskType && createElement(taskType.icon), !task.reason && /* @__PURE__ */jsx(Spinner, {})]
1070
- })
1071
- }), /* @__PURE__ */jsxs(Stack, {
1072
- flex: 1,
1073
- space: 2,
1074
- children: [/* @__PURE__ */jsxs(Text, {
1075
- size: 1,
1076
- weight: "medium",
1077
- children: [taskType ? taskType.title : "Running", task.title && /* @__PURE__ */jsxs(Fragment, {
1078
- children: [": ", task.title]
1079
- })]
1080
- }), task.message ? /* @__PURE__ */jsx(Text, {
1081
- size: 1,
1082
- children: task.message
1083
- }) : null, /* @__PURE__ */jsx(Text, {
1084
- muted: true,
1085
- size: 1,
1086
- children: /* @__PURE__ */jsx(TimeAgo, {
1087
- date: (_a2 = task.ended) != null ? _a2 : task.started
1088
- })
1089
- })]
1090
- })]
1091
- }), !task.ended && /* @__PURE__ */jsx(Box, {
1092
- flex: "none",
1093
- padding: 1,
1094
- children: /* @__PURE__ */jsx(Button, {
1095
- fontSize: 1,
1096
- mode: "bleed",
1097
- onClick: task.cancel,
1098
- text: "Cancel"
1099
- })
1100
- })]
1101
- })
1102
- });
1103
- }
1104
- const basePath = "/assist/tasks/instruction";
1105
- function canUseAssist(status) {
1106
- return (status == null ? void 0 : status.enabled) && status.initialized && status.validToken;
1107
- }
1108
- function useApiClient(customApiClient) {
1109
- const client = useClient({
1110
- apiVersion: "2023-06-05"
1111
- });
1112
- return useMemo(() => customApiClient ? customApiClient(client) : client, [client, customApiClient]);
1113
- }
1114
- function useTranslate(apiClient) {
894
+ function useGenerateImage(apiClient) {
1115
895
  const [loading, setLoading] = useState(false);
1116
896
  const user = useCurrentUser();
1117
897
  const schema = useSchema();
@@ -1119,31 +899,25 @@ function useTranslate(apiClient) {
1119
899
  leanFormat: true
1120
900
  }), [schema]);
1121
901
  const toast = useToast();
1122
- const translate = useCallback(_ref4 => {
902
+ const generateImage = useCallback(_ref4 => {
1123
903
  let {
1124
- documentId,
1125
- languagePath,
1126
- translatePath,
1127
- fieldLanguageMap,
1128
- conditionalMembers
904
+ path,
905
+ documentId
1129
906
  } = _ref4;
1130
907
  setLoading(true);
1131
908
  return apiClient.request({
1132
909
  method: "POST",
1133
- url: "/assist/tasks/translate/".concat(apiClient.config().dataset, "?projectId=").concat(apiClient.config().projectId),
910
+ url: "/assist/tasks/generate-image/".concat(apiClient.config().dataset, "?projectId=").concat(apiClient.config().projectId),
1134
911
  body: {
912
+ path,
1135
913
  documentId,
1136
914
  types,
1137
- languagePath,
1138
- fieldLanguageMap,
1139
- conditionalMembers,
1140
- translatePath: translatePath.length === 0 ? documentRootKey : pathToString(translatePath),
1141
915
  userId: user == null ? void 0 : user.id
1142
916
  }
1143
917
  }).catch(e => {
1144
918
  toast.push({
1145
919
  status: "error",
1146
- title: "Translate failed",
920
+ title: "Generate image from prompt failed",
1147
921
  description: e.message
1148
922
  });
1149
923
  setLoading(false);
@@ -1155,97 +929,13 @@ function useTranslate(apiClient) {
1155
929
  });
1156
930
  }, [setLoading, apiClient, toast, user, types]);
1157
931
  return useMemo(() => ({
1158
- translate,
932
+ generateImage,
1159
933
  loading
1160
- }), [translate, loading]);
934
+ }), [generateImage, loading]);
1161
935
  }
1162
- function useGenerateCaption(apiClient) {
1163
- const [loading, setLoading] = useState(false);
1164
- const user = useCurrentUser();
1165
- const schema = useSchema();
1166
- const types = useMemo(() => serializeSchema(schema, {
1167
- leanFormat: true
1168
- }), [schema]);
1169
- const toast = useToast();
1170
- const generateCaption = useCallback(_ref5 => {
1171
- let {
1172
- path,
1173
- documentId
1174
- } = _ref5;
1175
- setLoading(true);
1176
- return apiClient.request({
1177
- method: "POST",
1178
- url: "/assist/tasks/generate-caption/".concat(apiClient.config().dataset, "?projectId=").concat(apiClient.config().projectId),
1179
- body: {
1180
- path,
1181
- documentId,
1182
- types,
1183
- userId: user == null ? void 0 : user.id
1184
- }
1185
- }).catch(e => {
1186
- toast.push({
1187
- status: "error",
1188
- title: "Generate image description failed",
1189
- description: e.message
1190
- });
1191
- setLoading(false);
1192
- throw e;
1193
- }).finally(() => {
1194
- setTimeout(() => {
1195
- setLoading(false);
1196
- }, 2e3);
1197
- });
1198
- }, [setLoading, apiClient, toast, user, types]);
1199
- return useMemo(() => ({
1200
- generateCaption,
1201
- loading
1202
- }), [generateCaption, loading]);
1203
- }
1204
- function useGenerateImage(apiClient) {
1205
- const [loading, setLoading] = useState(false);
1206
- const user = useCurrentUser();
1207
- const schema = useSchema();
1208
- const types = useMemo(() => serializeSchema(schema, {
1209
- leanFormat: true
1210
- }), [schema]);
1211
- const toast = useToast();
1212
- const generateImage = useCallback(_ref6 => {
1213
- let {
1214
- path,
1215
- documentId
1216
- } = _ref6;
1217
- setLoading(true);
1218
- return apiClient.request({
1219
- method: "POST",
1220
- url: "/assist/tasks/generate-image/".concat(apiClient.config().dataset, "?projectId=").concat(apiClient.config().projectId),
1221
- body: {
1222
- path,
1223
- documentId,
1224
- types,
1225
- userId: user == null ? void 0 : user.id
1226
- }
1227
- }).catch(e => {
1228
- toast.push({
1229
- status: "error",
1230
- title: "Generate image from prompt failed",
1231
- description: e.message
1232
- });
1233
- setLoading(false);
1234
- throw e;
1235
- }).finally(() => {
1236
- setTimeout(() => {
1237
- setLoading(false);
1238
- }, 2e3);
1239
- });
1240
- }, [setLoading, apiClient, toast, user, types]);
1241
- return useMemo(() => ({
1242
- generateImage,
1243
- loading
1244
- }), [generateImage, loading]);
1245
- }
1246
- function useGetInstructStatus(apiClient) {
1247
- const [loading, setLoading] = useState(true);
1248
- const getInstructStatus = useCallback(async () => {
936
+ function useGetInstructStatus(apiClient) {
937
+ const [loading, setLoading] = useState(true);
938
+ const getInstructStatus = useCallback(async () => {
1249
939
  setLoading(true);
1250
940
  const projectId = apiClient.config().projectId;
1251
941
  try {
@@ -1370,345 +1060,62 @@ function AiAssistanceConfigProvider(props) {
1370
1060
  children
1371
1061
  });
1372
1062
  }
1373
- const NO_INPUT = {};
1374
- const RunInstructionContext = createContext({
1375
- runInstruction: () => {},
1376
- instructionLoading: false
1377
- });
1378
- function useRunInstruction() {
1379
- return useContext(RunInstructionContext);
1063
+ const aiDocPrefixPattern = new RegExp("^".concat(assistDocumentIdPrefix));
1064
+ function publicId(id) {
1065
+ return id.replace("drafts.", "");
1380
1066
  }
1381
- function isUserInputBlock(block) {
1382
- return block._type === userInputTypeName;
1067
+ function assistDocumentId(documentType) {
1068
+ return "".concat(assistDocumentIdPrefix).concat(documentType);
1383
1069
  }
1384
- function RunInstructionProvider(props) {
1385
- var _a;
1386
- const {
1387
- config
1388
- } = useAiAssistanceConfig();
1389
- const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
1070
+ function documentTypeFromAiDocumentId(id) {
1071
+ return id.replace(aiDocPrefixPattern, "");
1072
+ }
1073
+ function assistTasksStatusId(documentId) {
1074
+ return "".concat(assistDocumentStatusIdPrefix).concat(publicId(documentId));
1075
+ }
1076
+ const aiInspectorId = "ai-assistance";
1077
+ function BackToInstructionListLink() {
1390
1078
  const {
1391
- runInstruction: runInstructionRequest,
1392
- loading
1393
- } = useRunInstructionApi(apiClient);
1394
- const id = useId();
1395
- const [inputs, setInputs] = useState(NO_INPUT);
1396
- const [runRequest, setRunRequest] = useState();
1397
- const runInstruction = useCallback(req => {
1398
- var _a2;
1399
- if (loading) {
1400
- return;
1401
- }
1402
- const {
1403
- instruction,
1404
- ...request
1405
- } = req;
1406
- const instructionKey = instruction._key;
1407
- const userInputBlocks = (_a2 = instruction == null ? void 0 : instruction.prompt) == null ? void 0 : _a2.flatMap(block => block._type === "block" ? block.children.filter(isUserInputBlock) : [block]).filter(isUserInputBlock);
1408
- if (!(userInputBlocks == null ? void 0 : userInputBlocks.length)) {
1409
- runInstructionRequest({
1410
- ...request,
1411
- instructionKey,
1412
- userTexts: void 0
1413
- });
1414
- return;
1415
- }
1416
- setRunRequest({
1417
- ...req,
1418
- userInputBlocks
1419
- });
1420
- }, [setRunRequest, runInstructionRequest, loading]);
1421
- const close = useCallback(() => {
1422
- setRunRequest(void 0);
1423
- setInputs(NO_INPUT);
1424
- }, [setRunRequest, setInputs]);
1425
- const runWithInput = useCallback(() => {
1426
- if (runRequest) {
1427
- const {
1428
- instruction,
1429
- userTexts,
1430
- ...request
1431
- } = runRequest;
1432
- runInstructionRequest({
1433
- ...request,
1434
- instructionKey: instruction._key,
1435
- userTexts: Object.entries(inputs).map(_ref7 => {
1436
- let [key, value] = _ref7;
1437
- return {
1438
- blockKey: key,
1439
- userInput: value
1440
- };
1441
- })
1442
- });
1443
- }
1444
- close();
1445
- }, [close, runInstructionRequest, runRequest, inputs]);
1446
- const open = !!runRequest;
1447
- const runDisabled = useMemo(() => {
1448
- var _a2, _b;
1449
- return ((_b = (_a2 = runRequest == null ? void 0 : runRequest.userInputBlocks) == null ? void 0 : _a2.length) != null ? _b : 0) > Object.entries(inputs).filter(_ref8 => {
1450
- let [, value] = _ref8;
1451
- return !!value;
1452
- }).length;
1453
- }, [runRequest == null ? void 0 : runRequest.userInputBlocks, inputs]);
1454
- const runButton = /* @__PURE__ */jsx(Button, {
1455
- text: "Run instruction",
1456
- onClick: runWithInput,
1457
- tone: "primary",
1458
- icon: PlayIcon,
1459
- style: {
1460
- width: "100%"
1461
- },
1462
- disabled: runDisabled
1079
+ openInspector
1080
+ } = useDocumentPane();
1081
+ const goBack = useCallback(() => openInspector(aiInspectorId, {
1082
+ [instructionParam]: void 0
1083
+ }), [openInspector]);
1084
+ return /* @__PURE__ */jsx("div", {
1085
+ children: /* @__PURE__ */jsx(Button, {
1086
+ as: "a",
1087
+ fontSize: 1,
1088
+ icon: ArrowLeftIcon,
1089
+ mode: "bleed",
1090
+ padding: 1,
1091
+ space: 2,
1092
+ onClick: goBack,
1093
+ text: " Instructions",
1094
+ textAlign: "left"
1095
+ })
1463
1096
  });
1464
- const contextValue = useMemo(() => ({
1465
- runInstruction,
1466
- instructionLoading: loading
1467
- }), [runInstruction, loading]);
1468
- return /* @__PURE__ */jsxs(RunInstructionContext.Provider, {
1469
- value: contextValue,
1470
- children: [open ? /* @__PURE__ */jsx(Dialog, {
1471
- id,
1472
- open,
1473
- onClose: close,
1474
- width: 1,
1475
- header: getInstructionTitle(runRequest == null ? void 0 : runRequest.instruction),
1476
- footer: /* @__PURE__ */jsx(Flex, {
1477
- justify: "space-between",
1478
- padding: 2,
1479
- flex: 1,
1480
- children: runDisabled ? /* @__PURE__ */jsx(Tooltip, {
1481
- content: /* @__PURE__ */jsx(Flex, {
1482
- padding: 2,
1483
- children: /* @__PURE__ */jsx(Text, {
1484
- children: "Unable to run instruction. All fields must have a value."
1485
- })
1486
- }),
1487
- placement: "top",
1488
- children: /* @__PURE__ */jsx(Flex, {
1489
- flex: 1,
1490
- children: runButton
1491
- })
1492
- }) : runButton
1493
- }),
1494
- children: /* @__PURE__ */jsx(Stack, {
1495
- padding: 4,
1496
- space: 2,
1497
- children: (_a = runRequest == null ? void 0 : runRequest.userInputBlocks) == null ? void 0 : _a.map((block, i) => /* @__PURE__ */jsx(UserInput, {
1498
- block,
1499
- autoFocus: i === 0,
1500
- inputs,
1501
- setInputs
1502
- }, block._key))
1097
+ }
1098
+ const EMPTY_FIELDS = [];
1099
+ const TypePathContext = createContext(void 0);
1100
+ function AssistDocumentForm(props) {
1101
+ if (props.readOnly) {
1102
+ return /* @__PURE__ */jsx(Card, {
1103
+ border: true,
1104
+ tone: "caution",
1105
+ padding: 2,
1106
+ children: /* @__PURE__ */jsx(Text, {
1107
+ size: 1,
1108
+ children: " You do not have sufficient permissions to manage instructions."
1503
1109
  })
1504
- }) : null, props.children]
1110
+ });
1111
+ }
1112
+ return /* @__PURE__ */jsx(AssistDocumentFormEditable, {
1113
+ ...props
1505
1114
  });
1506
1115
  }
1507
- function UserInput(props) {
1508
- var _a;
1116
+ function AssistDocumentFormEditable(props) {
1509
1117
  const {
1510
- block,
1511
- autoFocus,
1512
- setInputs,
1513
- inputs
1514
- } = props;
1515
- const key = block._key;
1516
- const textAreaRef = useRef(null);
1517
- const onChange = useCallback(e => {
1518
- setInputs(current => {
1519
- var _a2;
1520
- return {
1521
- ...current,
1522
- [key]: ((_a2 = e.currentTarget) != null ? _a2 : e.target).value
1523
- };
1524
- });
1525
- }, [key, setInputs]);
1526
- const value = useMemo(() => inputs[key], [inputs, key]);
1527
- useEffect(() => {
1528
- if (!autoFocus) {
1529
- return;
1530
- }
1531
- setTimeout(() => {
1532
- var _a2;
1533
- return (_a2 = textAreaRef.current) == null ? void 0 : _a2.focus();
1534
- }, 0);
1535
- }, [autoFocus]);
1536
- return /* @__PURE__ */jsxs(Stack, {
1537
- padding: 2,
1538
- space: 3,
1539
- children: [/* @__PURE__ */jsx(FormFieldHeaderText, {
1540
- title: (_a = block == null ? void 0 : block.message) != null ? _a : "Provide more context",
1541
- description: block.description
1542
- }), /* @__PURE__ */jsx(TextArea, {
1543
- ref: textAreaRef,
1544
- rows: 4,
1545
- value,
1546
- onChange,
1547
- style: {
1548
- resize: "vertical"
1549
- }
1550
- })]
1551
- });
1552
- }
1553
- function isDocAssistable(documentSchemaType, published, draft) {
1554
- return !!(documentSchemaType.liveEdit ? published : draft);
1555
- }
1556
- function getAssistableDocId(documentSchemaType, documentId) {
1557
- const baseId = publicId(documentId);
1558
- return documentSchemaType.liveEdit ? baseId : "drafts.".concat(baseId);
1559
- }
1560
- function useRequestRunInstruction(args) {
1561
- const {
1562
- runInstruction,
1563
- instructionLoading
1564
- } = useRunInstruction();
1565
- const requestRunInstruction = useDraftDelayedTask({
1566
- ...args,
1567
- task: runInstruction
1568
- });
1569
- return {
1570
- instructionLoading,
1571
- requestRunInstruction
1572
- };
1573
- }
1574
- function useDraftDelayedTask(args) {
1575
- const {
1576
- documentOnChange,
1577
- isDocAssistable: isDocAssistable2,
1578
- task
1579
- } = args;
1580
- const [queuedArgs, setQueuedArgs] = useState(void 0);
1581
- useEffect(() => {
1582
- if (queuedArgs && isDocAssistable2) {
1583
- task(queuedArgs);
1584
- setQueuedArgs(void 0);
1585
- }
1586
- }, [queuedArgs, isDocAssistable2, task]);
1587
- return useCallback(taskArgs => {
1588
- documentOnChange(PatchEvent.from([unset(["_force_document_creation"])]));
1589
- setQueuedArgs(taskArgs);
1590
- }, [setQueuedArgs, documentOnChange]);
1591
- }
1592
- const SparklesIllustration = styled(SparklesIcon)({
1593
- fontSize: "3.125em",
1594
- "& path": {
1595
- strokeWidth: "0.6px !important"
1596
- }
1597
- });
1598
- function InspectorOnboarding(props) {
1599
- const {
1600
- onDismiss
1601
- } = props;
1602
- return /* @__PURE__ */jsx(Box, {
1603
- padding: 4,
1604
- children: /* @__PURE__ */jsx(Container, {
1605
- width: 0,
1606
- children: /* @__PURE__ */jsxs(Stack, {
1607
- space: 4,
1608
- children: [/* @__PURE__ */jsx("div", {
1609
- style: {
1610
- textAlign: "center"
1611
- },
1612
- children: /* @__PURE__ */jsx(SparklesIllustration, {})
1613
- }), /* @__PURE__ */jsx(Text, {
1614
- align: "center",
1615
- size: 1,
1616
- children: "Create reusable AI instructions that can be applied across all documents of a certain type."
1617
- }), /* @__PURE__ */jsxs(Flex, {
1618
- align: "center",
1619
- gap: 2,
1620
- justify: "center",
1621
- children: [/* @__PURE__ */jsx(Button, {
1622
- as: "a",
1623
- href: releaseAnnouncementUrl,
1624
- rel: "noreferrer",
1625
- target: "_blank",
1626
- fontSize: 1,
1627
- mode: "default",
1628
- onClick: onDismiss,
1629
- padding: 2,
1630
- text: "Learn more",
1631
- tone: "primary"
1632
- }), /* @__PURE__ */jsx(Button, {
1633
- fontSize: 1,
1634
- mode: "bleed",
1635
- onClick: onDismiss,
1636
- padding: 2,
1637
- text: "Dismiss"
1638
- })]
1639
- })]
1640
- })
1641
- })
1642
- });
1643
- }
1644
- const inspectorOnboardingKey = "sanityStudio:assist:inspector:onboarding:dismissed";
1645
- const fieldOnboardingKey = "sanityStudio:assist:field:onboarding:dismissed";
1646
- function isFeatureOnboardingDismissed(featureKey) {
1647
- if (typeof localStorage === "undefined") {
1648
- return false;
1649
- }
1650
- const value = localStorage.getItem(featureKey);
1651
- return value === "true";
1652
- }
1653
- function dismissFeatureOnboarding(featureKey) {
1654
- if (typeof localStorage === "undefined") {
1655
- return;
1656
- }
1657
- localStorage.setItem(featureKey, "true");
1658
- }
1659
- function useOnboardingFeature(featureKey) {
1660
- const [showOnboarding, setShowOnboarding] = useState(() => !isFeatureOnboardingDismissed(featureKey));
1661
- const dismissOnboarding = useCallback(() => {
1662
- setShowOnboarding(false);
1663
- dismissFeatureOnboarding(featureKey);
1664
- }, [setShowOnboarding, featureKey]);
1665
- return {
1666
- showOnboarding,
1667
- dismissOnboarding
1668
- };
1669
- }
1670
- function BackToInstructionListLink() {
1671
- const {
1672
- openInspector
1673
- } = useDocumentPane();
1674
- const goBack = useCallback(() => openInspector(aiInspectorId, {
1675
- [instructionParam]: void 0
1676
- }), [openInspector]);
1677
- return /* @__PURE__ */jsx("div", {
1678
- children: /* @__PURE__ */jsx(Button, {
1679
- as: "a",
1680
- fontSize: 1,
1681
- icon: ArrowLeftIcon,
1682
- mode: "bleed",
1683
- padding: 1,
1684
- space: 2,
1685
- onClick: goBack,
1686
- text: " Instructions",
1687
- textAlign: "left"
1688
- })
1689
- });
1690
- }
1691
- const EMPTY_FIELDS = [];
1692
- const TypePathContext = createContext(void 0);
1693
- function AssistDocumentForm(props) {
1694
- if (props.readOnly) {
1695
- return /* @__PURE__ */jsx(Card, {
1696
- border: true,
1697
- tone: "caution",
1698
- padding: 2,
1699
- children: /* @__PURE__ */jsx(Text, {
1700
- size: 1,
1701
- children: " You do not have sufficient permissions to manage instructions."
1702
- })
1703
- });
1704
- }
1705
- return /* @__PURE__ */jsx(AssistDocumentFormEditable, {
1706
- ...props
1707
- });
1708
- }
1709
- function AssistDocumentFormEditable(props) {
1710
- const {
1711
- onChange
1118
+ onChange
1712
1119
  } = props;
1713
1120
  const value = props.value;
1714
1121
  const id = value == null ? void 0 : value._id;
@@ -1839,14 +1246,14 @@ function useSelectedSchema(fieldPath, documentSchema) {
1839
1246
  return currentSchema;
1840
1247
  }, [documentSchema, fieldPath]);
1841
1248
  }
1842
- function FieldsInitializer(_ref9) {
1249
+ function FieldsInitializer(_ref5) {
1843
1250
  let {
1844
1251
  pathKey,
1845
1252
  activePath,
1846
1253
  fields,
1847
1254
  documentSchema,
1848
1255
  onChange
1849
- } = _ref9;
1256
+ } = _ref5;
1850
1257
  const {
1851
1258
  config: {
1852
1259
  __presets: presets
@@ -1906,206 +1313,799 @@ function FieldsInitializer(_ref9) {
1906
1313
  }, [activePath, onChange, pathKey, existingField, missingPresetInstructions]);
1907
1314
  return null;
1908
1315
  }
1909
- function FieldAutocomplete(props) {
1910
- const {
1911
- id,
1316
+ function useDocumentState(id, docType) {
1317
+ const state = useEditState(id, docType);
1318
+ return state.draft || state.published;
1319
+ }
1320
+ function useStudioAssistDocument(_ref6) {
1321
+ let {
1322
+ documentId,
1912
1323
  schemaType,
1913
- fieldPath,
1914
- onSelect,
1915
- includeDocument,
1916
- filter
1917
- } = props;
1918
- const fieldRefs = useMemo(() => {
1919
- if (includeDocument) {
1920
- return getFieldRefsWithDocument(schemaType);
1921
- }
1922
- return getFieldRefs(schemaType);
1923
- }, [schemaType, includeDocument]);
1924
- const currentField = useMemo(() => fieldRefs.find(f => f.key === fieldPath), [fieldPath, fieldRefs]);
1925
- const autocompleteOptions = useMemo(() => fieldRefs.filter(field => filter ? filter(field) : true).filter(f => !isType(f.schemaType, "reference")).map(field => ({
1926
- value: field.key,
1927
- field
1928
- })), [fieldRefs, filter]);
1929
- const renderOption = useCallback(option => {
1930
- const {
1931
- value,
1932
- field
1933
- } = option;
1934
- if (!value) {
1935
- return /* @__PURE__ */jsx(Card, {
1936
- as: "button",
1937
- padding: 3,
1938
- radius: 1,
1939
- children: /* @__PURE__ */jsx(Text, {
1940
- accent: true,
1941
- size: 1,
1942
- children: option.value
1943
- })
1944
- });
1324
+ initDoc
1325
+ } = _ref6;
1326
+ const documentTypeName = schemaType.name;
1327
+ const currentUser = useCurrentUser();
1328
+ const assistDocument = useDocumentState(assistDocumentId(documentTypeName), assistDocumentTypeName);
1329
+ const assistTasksStatus = useDocumentState(assistTasksStatusId(documentId != null ? documentId : ""), assistTasksStatusTypeName);
1330
+ const client = useClient({
1331
+ apiVersion: "2023-01-01"
1332
+ });
1333
+ useEffect(() => {
1334
+ if (!assistDocument && initDoc) {
1335
+ client.createIfNotExists({
1336
+ _id: assistDocumentId(documentTypeName),
1337
+ _type: assistDocumentTypeName
1338
+ }).catch(() => {});
1945
1339
  }
1946
- if (isType(field.schemaType, "document")) {
1947
- return /* @__PURE__ */jsx(Card, {
1948
- as: "button",
1949
- padding: 3,
1950
- radius: 1,
1951
- children: /* @__PURE__ */jsx(Text, {
1952
- size: 1,
1953
- weight: "semibold",
1954
- children: "The entire document"
1955
- })
1956
- });
1340
+ }, [client, assistDocument, documentTypeName, initDoc]);
1341
+ return useMemo(() => {
1342
+ var _a, _b;
1343
+ if (!assistDocument) {
1344
+ return void 0;
1957
1345
  }
1958
- return /* @__PURE__ */jsx(Card, {
1959
- as: "button",
1960
- padding: 3,
1961
- radius: 1,
1962
- children: /* @__PURE__ */jsxs(Flex, {
1963
- gap: 3,
1964
- children: [/* @__PURE__ */jsx(Text, {
1965
- size: 1,
1966
- children: createElement(field.icon)
1967
- }), /* @__PURE__ */jsx(FieldTitle, {
1968
- field
1969
- })]
1970
- })
1346
+ const tasks = (_a = assistTasksStatus == null ? void 0 : assistTasksStatus.tasks) != null ? _a : [];
1347
+ const fields = ((_b = assistDocument == null ? void 0 : assistDocument.fields) != null ? _b : []).map(assistField => {
1348
+ var _a2;
1349
+ return {
1350
+ ...assistField,
1351
+ tasks: tasks.filter(task => task.path === assistField.path),
1352
+ instructions: (_a2 = assistField.instructions) == null ? void 0 : _a2.filter(p => !p.userId || p.userId === (currentUser == null ? void 0 : currentUser.id)).map(instruction => asStudioInstruction(instruction, tasks))
1353
+ };
1971
1354
  });
1972
- }, []);
1973
- const renderValue = useCallback((value, option) => {
1974
- var _a;
1975
- return (_a = option == null ? void 0 : option.field.title) != null ? _a : value;
1976
- }, []);
1977
- const filterOption = useCallback((query, option) => {
1978
- var _a, _b, _c;
1979
- const lQuery = query.toLowerCase();
1980
- return ((_a = option == null ? void 0 : option.value) == null ? void 0 : _a.toLowerCase().includes(lQuery)) || ((_c = (_b = option == null ? void 0 : option.field) == null ? void 0 : _b.title) == null ? void 0 : _c.toLowerCase().includes(lQuery));
1981
- }, []);
1982
- return /* @__PURE__ */jsx(Autocomplete, {
1983
- fontSize: 1,
1984
- icon: currentField ? currentField.icon : SearchIcon,
1985
- onChange: onSelect,
1986
- openButton: true,
1987
- id,
1988
- options: autocompleteOptions,
1989
- placeholder: "Search for a field",
1990
- radius: 2,
1991
- renderOption,
1992
- renderValue,
1993
- value: currentField == null ? void 0 : currentField.key,
1994
- filterOption
1995
- });
1996
- }
1997
- function FieldTitle(props) {
1998
- const splitTitle = props.field.title.split("/");
1999
- return /* @__PURE__ */jsx(Box, {
2000
- flex: "none",
2001
- children: /* @__PURE__ */jsxs(Breadcrumbs, {
2002
- style: {
2003
- display: "flex",
2004
- flexWrap: "wrap",
2005
- alignItems: "center",
2006
- marginTop: "-4px"
2007
- },
2008
- separator: /* @__PURE__ */jsx(Box, {
2009
- marginTop: 1,
2010
- children: /* @__PURE__ */jsx(Text, {
2011
- muted: true,
2012
- size: 1,
2013
- children: "/"
2014
- })
1355
+ return typed({
1356
+ ...assistDocument,
1357
+ tasks: tasks == null ? void 0 : tasks.map(task => {
1358
+ var _a2, _b2;
1359
+ const instruction = (_b2 = (_a2 = fields.find(f => f.path === task.path)) == null ? void 0 : _a2.instructions) == null ? void 0 : _b2.find(i => i._key === task.instructionKey);
1360
+ return {
1361
+ ...task,
1362
+ instruction
1363
+ };
2015
1364
  }),
2016
- space: 1,
2017
- children: [splitTitle.slice(0, splitTitle.length - 1).map((pt, i) =>
2018
- // eslint-disable-next-line react/no-array-index-key
2019
- /* @__PURE__ */
2020
- jsx(Box, {
2021
- marginTop: 1,
2022
- children: /* @__PURE__ */jsx(Text, {
2023
- muted: true,
2024
- size: 1,
2025
- children: pt.trim()
2026
- })
2027
- }, i)), /* @__PURE__ */jsx(Box, {
2028
- marginTop: 1,
2029
- children: /* @__PURE__ */jsx(Text, {
2030
- size: 1,
2031
- weight: "medium",
2032
- children: splitTitle[splitTitle.length - 1]
2033
- })
2034
- })]
2035
- })
2036
- });
2037
- }
2038
- const MAX_DEPTH = 8;
2039
- function getConditionalMembers(docState) {
2040
- const doc = {
2041
- path: "",
2042
- hidden: false,
2043
- readOnly: !!docState.readOnly,
2044
- conditional: typeof docState.schemaType.hidden === "function"
2045
- };
2046
- return [doc, ...extractConditionalPaths(docState, MAX_DEPTH)].filter(v => v.conditional).map(_ref10 => {
2047
- let {
2048
- conditional,
2049
- ...state
2050
- } = _ref10;
2051
- return {
2052
- ...state
2053
- };
2054
- });
2055
- }
2056
- function isConditional(schemaType) {
2057
- return typeof schemaType.hidden === "function" || typeof schemaType.readOnly === "function";
1365
+ fields
1366
+ });
1367
+ }, [assistDocument, assistTasksStatus, currentUser]);
2058
1368
  }
2059
- function conditionalState(memberState) {
1369
+ function asStudioInstruction(instruction, run) {
2060
1370
  return {
2061
- path: pathToString(memberState.path),
2062
- readOnly: !!memberState.readOnly,
2063
- hidden: false,
2064
- // if its in members, its not hidden
2065
- conditional: isConditional(memberState.schemaType)
1371
+ ...instruction,
1372
+ tasks: run.filter(task => task.instructionKey === instruction._key).filter(task => task.started && ( /* @__PURE__ */new Date()).getTime() - new Date(task.started).getTime() < maxHistoryVisibilityMs)
2066
1373
  };
2067
1374
  }
2068
- function extractConditionalPaths(node, maxDepth) {
2069
- if (node.path.length >= maxDepth) {
2070
- return [];
1375
+ function usePathKey(path) {
1376
+ return useMemo(() => {
1377
+ return getPathKey(path);
1378
+ }, [path]);
1379
+ }
1380
+ function getPathKey(path) {
1381
+ if (path.length) {
1382
+ return Array.isArray(path) ? pathToString(path) : path;
2071
1383
  }
2072
- return node.members.reduce((acc, member) => {
2073
- var _a, _b;
2074
- if (member.kind === "error") {
2075
- return acc;
1384
+ return documentRootKey;
1385
+ }
1386
+ function getInstructionTitle(instruction) {
1387
+ var _a;
1388
+ return (_a = instruction == null ? void 0 : instruction.title) != null ? _a : "Untitled";
1389
+ }
1390
+ const NO_INPUT = {};
1391
+ const RunInstructionContext = createContext({
1392
+ runInstruction: () => {},
1393
+ instructionLoading: false
1394
+ });
1395
+ function useRunInstruction() {
1396
+ return useContext(RunInstructionContext);
1397
+ }
1398
+ function isUserInputBlock(block) {
1399
+ return block._type === userInputTypeName;
1400
+ }
1401
+ function RunInstructionProvider(props) {
1402
+ var _a;
1403
+ const {
1404
+ config
1405
+ } = useAiAssistanceConfig();
1406
+ const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
1407
+ const {
1408
+ runInstruction: runInstructionRequest,
1409
+ loading
1410
+ } = useRunInstructionApi(apiClient);
1411
+ const id = useId();
1412
+ const [inputs, setInputs] = useState(NO_INPUT);
1413
+ const [runRequest, setRunRequest] = useState();
1414
+ const runInstruction = useCallback(req => {
1415
+ var _a2;
1416
+ if (loading) {
1417
+ return;
2076
1418
  }
2077
- if (member.kind === "field") {
2078
- const schemaType = member.field.schemaType;
2079
- if (schemaType.jsonType === "object") {
2080
- const innerFields = member.field.readOnly ? [] : extractConditionalPaths(member.field, maxDepth);
2081
- return [...acc, conditionalState(member.field), ...innerFields];
2082
- } else if (schemaType.jsonType === "array") {
2083
- const array = member.field;
2084
- let arrayPaths = [];
2085
- const isObjectsArray = array.members.some(m => m.kind === "item" && isObjectSchemaType(m.item.schemaType));
2086
- if (!array.readOnly) {
2087
- for (const arrayMember of array.members) {
2088
- if (arrayMember.kind === "error") {
2089
- continue;
2090
- }
2091
- const innerFields = isObjectsArray && !arrayMember.item.readOnly ? extractConditionalPaths(arrayMember.item, maxDepth) : [];
2092
- arrayPaths = [...arrayPaths, conditionalState(arrayMember.item), ...innerFields];
2093
- }
2094
- }
2095
- return [...acc, conditionalState(array), ...arrayPaths];
2096
- }
2097
- return [...acc, conditionalState(member.field)];
2098
- } else if (member.kind === "fieldSet") {
2099
- const conditionalFieldset = !!((_b = (_a = node.schemaType) == null ? void 0 : _a.fieldsets) == null ? void 0 : _b.some(f => !f.single && f.name === member.fieldSet.name && typeof f.hidden === "function"));
2100
- const innerFields = extractConditionalPaths(member.fieldSet, maxDepth).map(f => ({
2101
- ...f,
2102
- // if fieldset is conditional, visible fields must also be considered conditional
2103
- conditional: conditionalFieldset != null ? conditionalFieldset : f.conditional
2104
- }));
2105
- return [...acc, ...innerFields];
1419
+ const {
1420
+ instruction,
1421
+ ...request
1422
+ } = req;
1423
+ const instructionKey = instruction._key;
1424
+ const userInputBlocks = (_a2 = instruction == null ? void 0 : instruction.prompt) == null ? void 0 : _a2.flatMap(block => block._type === "block" ? block.children.filter(isUserInputBlock) : [block]).filter(isUserInputBlock);
1425
+ if (!(userInputBlocks == null ? void 0 : userInputBlocks.length)) {
1426
+ runInstructionRequest({
1427
+ ...request,
1428
+ instructionKey,
1429
+ userTexts: void 0
1430
+ });
1431
+ return;
2106
1432
  }
2107
- return acc;
1433
+ setRunRequest({
1434
+ ...req,
1435
+ userInputBlocks
1436
+ });
1437
+ }, [runInstructionRequest, loading]);
1438
+ const close = useCallback(() => {
1439
+ setRunRequest(void 0);
1440
+ setInputs(NO_INPUT);
2108
1441
  }, []);
1442
+ const runWithInput = useCallback(() => {
1443
+ if (runRequest) {
1444
+ const {
1445
+ instruction,
1446
+ userTexts,
1447
+ ...request
1448
+ } = runRequest;
1449
+ runInstructionRequest({
1450
+ ...request,
1451
+ instructionKey: instruction._key,
1452
+ userTexts: Object.entries(inputs).map(_ref7 => {
1453
+ let [key, value] = _ref7;
1454
+ return {
1455
+ blockKey: key,
1456
+ userInput: value
1457
+ };
1458
+ })
1459
+ });
1460
+ }
1461
+ close();
1462
+ }, [close, runInstructionRequest, runRequest, inputs]);
1463
+ const open = !!runRequest;
1464
+ const runDisabled = useMemo(() => {
1465
+ var _a2, _b;
1466
+ return ((_b = (_a2 = runRequest == null ? void 0 : runRequest.userInputBlocks) == null ? void 0 : _a2.length) != null ? _b : 0) > Object.entries(inputs).filter(_ref8 => {
1467
+ let [, value] = _ref8;
1468
+ return !!value;
1469
+ }).length;
1470
+ }, [runRequest == null ? void 0 : runRequest.userInputBlocks, inputs]);
1471
+ const runButton = /* @__PURE__ */jsx(Button, {
1472
+ text: "Run instruction",
1473
+ onClick: runWithInput,
1474
+ tone: "primary",
1475
+ icon: PlayIcon,
1476
+ style: {
1477
+ width: "100%"
1478
+ },
1479
+ disabled: runDisabled
1480
+ });
1481
+ const contextValue = useMemo(() => ({
1482
+ runInstruction,
1483
+ instructionLoading: loading
1484
+ }), [runInstruction, loading]);
1485
+ return /* @__PURE__ */jsxs(RunInstructionContext.Provider, {
1486
+ value: contextValue,
1487
+ children: [open ? /* @__PURE__ */jsx(Dialog, {
1488
+ id,
1489
+ open,
1490
+ onClose: close,
1491
+ width: 1,
1492
+ header: getInstructionTitle(runRequest == null ? void 0 : runRequest.instruction),
1493
+ footer: /* @__PURE__ */jsx(Flex, {
1494
+ justify: "space-between",
1495
+ padding: 2,
1496
+ flex: 1,
1497
+ children: runDisabled ? /* @__PURE__ */jsx(Tooltip, {
1498
+ content: /* @__PURE__ */jsx(Flex, {
1499
+ padding: 2,
1500
+ children: /* @__PURE__ */jsx(Text, {
1501
+ children: "Unable to run instruction. All fields must have a value."
1502
+ })
1503
+ }),
1504
+ placement: "top",
1505
+ children: /* @__PURE__ */jsx(Flex, {
1506
+ flex: 1,
1507
+ children: runButton
1508
+ })
1509
+ }) : runButton
1510
+ }),
1511
+ children: /* @__PURE__ */jsx(Stack, {
1512
+ padding: 4,
1513
+ space: 2,
1514
+ children: (_a = runRequest == null ? void 0 : runRequest.userInputBlocks) == null ? void 0 : _a.map((block, i) => /* @__PURE__ */jsx(UserInput, {
1515
+ block,
1516
+ autoFocus: i === 0,
1517
+ inputs,
1518
+ setInputs
1519
+ }, block._key))
1520
+ })
1521
+ }) : null, props.children]
1522
+ });
1523
+ }
1524
+ function UserInput(props) {
1525
+ var _a;
1526
+ const {
1527
+ block,
1528
+ autoFocus,
1529
+ setInputs,
1530
+ inputs
1531
+ } = props;
1532
+ const key = block._key;
1533
+ const textAreaRef = useRef(null);
1534
+ const onChange = useCallback(e => {
1535
+ setInputs(current => {
1536
+ var _a2;
1537
+ return {
1538
+ ...current,
1539
+ [key]: ((_a2 = e.currentTarget) != null ? _a2 : e.target).value
1540
+ };
1541
+ });
1542
+ }, [key, setInputs]);
1543
+ const value = useMemo(() => inputs[key], [inputs, key]);
1544
+ useEffect(() => {
1545
+ if (!autoFocus) {
1546
+ return;
1547
+ }
1548
+ setTimeout(() => {
1549
+ var _a2;
1550
+ return (_a2 = textAreaRef.current) == null ? void 0 : _a2.focus();
1551
+ }, 0);
1552
+ }, [autoFocus]);
1553
+ return /* @__PURE__ */jsxs(Stack, {
1554
+ padding: 2,
1555
+ space: 3,
1556
+ children: [/* @__PURE__ */jsx(FormFieldHeaderText, {
1557
+ title: (_a = block == null ? void 0 : block.message) != null ? _a : "Provide more context",
1558
+ description: block.description
1559
+ }), /* @__PURE__ */jsx(TextArea, {
1560
+ ref: textAreaRef,
1561
+ rows: 4,
1562
+ value,
1563
+ onChange,
1564
+ style: {
1565
+ resize: "vertical"
1566
+ }
1567
+ })]
1568
+ });
1569
+ }
1570
+ function isDocAssistable(documentSchemaType, published, draft) {
1571
+ return !!(documentSchemaType.liveEdit ? published : draft);
1572
+ }
1573
+ function getAssistableDocId(documentSchemaType, documentId) {
1574
+ const baseId = publicId(documentId);
1575
+ return documentSchemaType.liveEdit ? baseId : "drafts.".concat(baseId);
1576
+ }
1577
+ function useRequestRunInstruction(args) {
1578
+ const {
1579
+ runInstruction,
1580
+ instructionLoading
1581
+ } = useRunInstruction();
1582
+ const requestRunInstruction = useDraftDelayedTask({
1583
+ ...args,
1584
+ task: runInstruction
1585
+ });
1586
+ return {
1587
+ instructionLoading,
1588
+ requestRunInstruction
1589
+ };
1590
+ }
1591
+ function useDraftDelayedTask(args) {
1592
+ const {
1593
+ documentOnChange,
1594
+ isDocAssistable: isDocAssistable2,
1595
+ task
1596
+ } = args;
1597
+ const [queuedArgs, setQueuedArgs] = useState(void 0);
1598
+ useEffect(() => {
1599
+ if (queuedArgs && isDocAssistable2) {
1600
+ task(queuedArgs);
1601
+ setQueuedArgs(void 0);
1602
+ }
1603
+ }, [queuedArgs, isDocAssistable2, task]);
1604
+ return useCallback(taskArgs => {
1605
+ documentOnChange(PatchEvent.from([unset(["_force_document_creation"])]));
1606
+ setQueuedArgs(taskArgs);
1607
+ }, [setQueuedArgs, documentOnChange]);
1608
+ }
1609
+ const MAX_DEPTH = 8;
1610
+ function getConditionalMembers(docState) {
1611
+ const doc = {
1612
+ path: "",
1613
+ hidden: false,
1614
+ readOnly: !!docState.readOnly,
1615
+ conditional: typeof docState.schemaType.hidden === "function"
1616
+ };
1617
+ return [doc, ...extractConditionalPaths(docState, MAX_DEPTH)].filter(v => v.conditional).map(_ref9 => {
1618
+ let {
1619
+ conditional,
1620
+ ...state
1621
+ } = _ref9;
1622
+ return {
1623
+ ...state
1624
+ };
1625
+ });
1626
+ }
1627
+ function isConditional(schemaType) {
1628
+ return typeof schemaType.hidden === "function" || typeof schemaType.readOnly === "function";
1629
+ }
1630
+ function conditionalState(memberState) {
1631
+ return {
1632
+ path: pathToString(memberState.path),
1633
+ readOnly: !!memberState.readOnly,
1634
+ hidden: false,
1635
+ // if its in members, its not hidden
1636
+ conditional: isConditional(memberState.schemaType)
1637
+ };
1638
+ }
1639
+ function extractConditionalPaths(node, maxDepth) {
1640
+ if (node.path.length >= maxDepth) {
1641
+ return [];
1642
+ }
1643
+ return node.members.reduce((acc, member) => {
1644
+ var _a, _b;
1645
+ if (member.kind === "error") {
1646
+ return acc;
1647
+ }
1648
+ if (member.kind === "field") {
1649
+ const schemaType = member.field.schemaType;
1650
+ if (schemaType.jsonType === "object") {
1651
+ const innerFields = member.field.readOnly ? [] : extractConditionalPaths(member.field, maxDepth);
1652
+ return [...acc, conditionalState(member.field), ...innerFields];
1653
+ } else if (schemaType.jsonType === "array") {
1654
+ const array = member.field;
1655
+ let arrayPaths = [];
1656
+ const isObjectsArray = array.members.some(m => m.kind === "item" && isObjectSchemaType(m.item.schemaType));
1657
+ if (!array.readOnly) {
1658
+ for (const arrayMember of array.members) {
1659
+ if (arrayMember.kind === "error") {
1660
+ continue;
1661
+ }
1662
+ const innerFields = isObjectsArray && !arrayMember.item.readOnly ? extractConditionalPaths(arrayMember.item, maxDepth) : [];
1663
+ arrayPaths = [...arrayPaths, conditionalState(arrayMember.item), ...innerFields];
1664
+ }
1665
+ }
1666
+ return [...acc, conditionalState(array), ...arrayPaths];
1667
+ }
1668
+ return [...acc, conditionalState(member.field)];
1669
+ } else if (member.kind === "fieldSet") {
1670
+ const conditionalFieldset = !!((_b = (_a = node.schemaType) == null ? void 0 : _a.fieldsets) == null ? void 0 : _b.some(f => !f.single && f.name === member.fieldSet.name && typeof f.hidden === "function"));
1671
+ const innerFields = extractConditionalPaths(member.fieldSet, maxDepth).map(f => ({
1672
+ ...f,
1673
+ // if fieldset is conditional, visible fields must also be considered conditional
1674
+ conditional: conditionalFieldset != null ? conditionalFieldset : f.conditional
1675
+ }));
1676
+ return [...acc, ...innerFields];
1677
+ }
1678
+ return acc;
1679
+ }, []);
1680
+ }
1681
+ const SparklesIllustration = styled(SparklesIcon)({
1682
+ fontSize: "3.125em",
1683
+ "& path": {
1684
+ strokeWidth: "0.6px !important"
1685
+ }
1686
+ });
1687
+ function InspectorOnboarding(props) {
1688
+ const {
1689
+ onDismiss
1690
+ } = props;
1691
+ return /* @__PURE__ */jsx(Box, {
1692
+ padding: 4,
1693
+ children: /* @__PURE__ */jsx(Container, {
1694
+ width: 0,
1695
+ children: /* @__PURE__ */jsxs(Stack, {
1696
+ space: 4,
1697
+ children: [/* @__PURE__ */jsx("div", {
1698
+ style: {
1699
+ textAlign: "center"
1700
+ },
1701
+ children: /* @__PURE__ */jsx(SparklesIllustration, {})
1702
+ }), /* @__PURE__ */jsx(Text, {
1703
+ align: "center",
1704
+ size: 1,
1705
+ children: "Create reusable AI instructions that can be applied across all documents of a certain type."
1706
+ }), /* @__PURE__ */jsxs(Flex, {
1707
+ align: "center",
1708
+ gap: 2,
1709
+ justify: "center",
1710
+ children: [/* @__PURE__ */jsx(Button, {
1711
+ as: "a",
1712
+ href: releaseAnnouncementUrl,
1713
+ rel: "noreferrer",
1714
+ target: "_blank",
1715
+ fontSize: 1,
1716
+ mode: "default",
1717
+ onClick: onDismiss,
1718
+ padding: 2,
1719
+ text: "Learn more",
1720
+ tone: "primary"
1721
+ }), /* @__PURE__ */jsx(Button, {
1722
+ fontSize: 1,
1723
+ mode: "bleed",
1724
+ onClick: onDismiss,
1725
+ padding: 2,
1726
+ text: "Dismiss"
1727
+ })]
1728
+ })]
1729
+ })
1730
+ })
1731
+ });
1732
+ }
1733
+ const inspectorOnboardingKey = "sanityStudio:assist:inspector:onboarding:dismissed";
1734
+ const fieldOnboardingKey = "sanityStudio:assist:field:onboarding:dismissed";
1735
+ function isFeatureOnboardingDismissed(featureKey) {
1736
+ if (typeof localStorage === "undefined") {
1737
+ return false;
1738
+ }
1739
+ const value = localStorage.getItem(featureKey);
1740
+ return value === "true";
1741
+ }
1742
+ function dismissFeatureOnboarding(featureKey) {
1743
+ if (typeof localStorage === "undefined") {
1744
+ return;
1745
+ }
1746
+ localStorage.setItem(featureKey, "true");
1747
+ }
1748
+ function useOnboardingFeature(featureKey) {
1749
+ const [showOnboarding, setShowOnboarding] = useState(() => !isFeatureOnboardingDismissed(featureKey));
1750
+ const dismissOnboarding = useCallback(() => {
1751
+ setShowOnboarding(false);
1752
+ dismissFeatureOnboarding(featureKey);
1753
+ }, [setShowOnboarding, featureKey]);
1754
+ return {
1755
+ showOnboarding,
1756
+ dismissOnboarding
1757
+ };
1758
+ }
1759
+ function FieldAutocomplete(props) {
1760
+ const {
1761
+ id,
1762
+ schemaType,
1763
+ fieldPath,
1764
+ onSelect,
1765
+ includeDocument,
1766
+ filter
1767
+ } = props;
1768
+ const fieldRefs = useMemo(() => {
1769
+ if (includeDocument) {
1770
+ return getFieldRefsWithDocument(schemaType);
1771
+ }
1772
+ return getFieldRefs(schemaType);
1773
+ }, [schemaType, includeDocument]);
1774
+ const currentField = useMemo(() => fieldRefs.find(f => f.key === fieldPath), [fieldPath, fieldRefs]);
1775
+ const autocompleteOptions = useMemo(() => fieldRefs.filter(field => filter ? filter(field) : true).filter(f => !isType(f.schemaType, "reference")).map(field => ({
1776
+ value: field.key,
1777
+ field
1778
+ })), [fieldRefs, filter]);
1779
+ const renderOption = useCallback(option => {
1780
+ const {
1781
+ value,
1782
+ field
1783
+ } = option;
1784
+ if (!value) {
1785
+ return /* @__PURE__ */jsx(Card, {
1786
+ as: "button",
1787
+ padding: 3,
1788
+ radius: 1,
1789
+ children: /* @__PURE__ */jsx(Text, {
1790
+ accent: true,
1791
+ size: 1,
1792
+ children: option.value
1793
+ })
1794
+ });
1795
+ }
1796
+ if (isType(field.schemaType, "document")) {
1797
+ return /* @__PURE__ */jsx(Card, {
1798
+ as: "button",
1799
+ padding: 3,
1800
+ radius: 1,
1801
+ children: /* @__PURE__ */jsx(Text, {
1802
+ size: 1,
1803
+ weight: "semibold",
1804
+ children: "The entire document"
1805
+ })
1806
+ });
1807
+ }
1808
+ return /* @__PURE__ */jsx(Card, {
1809
+ as: "button",
1810
+ padding: 3,
1811
+ radius: 1,
1812
+ children: /* @__PURE__ */jsxs(Flex, {
1813
+ gap: 3,
1814
+ children: [/* @__PURE__ */jsx(Text, {
1815
+ size: 1,
1816
+ children: createElement(field.icon)
1817
+ }), /* @__PURE__ */jsx(FieldTitle, {
1818
+ field
1819
+ })]
1820
+ })
1821
+ });
1822
+ }, []);
1823
+ const renderValue = useCallback((value, option) => {
1824
+ var _a;
1825
+ return (_a = option == null ? void 0 : option.field.title) != null ? _a : value;
1826
+ }, []);
1827
+ const filterOption = useCallback((query, option) => {
1828
+ var _a, _b, _c;
1829
+ const lQuery = query.toLowerCase();
1830
+ return ((_a = option == null ? void 0 : option.value) == null ? void 0 : _a.toLowerCase().includes(lQuery)) || ((_c = (_b = option == null ? void 0 : option.field) == null ? void 0 : _b.title) == null ? void 0 : _c.toLowerCase().includes(lQuery));
1831
+ }, []);
1832
+ return /* @__PURE__ */jsx(Autocomplete, {
1833
+ fontSize: 1,
1834
+ icon: currentField ? currentField.icon : SearchIcon,
1835
+ onChange: onSelect,
1836
+ openButton: true,
1837
+ id,
1838
+ options: autocompleteOptions,
1839
+ placeholder: "Search for a field",
1840
+ radius: 2,
1841
+ renderOption,
1842
+ renderValue,
1843
+ value: currentField == null ? void 0 : currentField.key,
1844
+ filterOption
1845
+ });
1846
+ }
1847
+ function FieldTitle(props) {
1848
+ const splitTitle = props.field.title.split("/");
1849
+ return /* @__PURE__ */jsx(Box, {
1850
+ flex: "none",
1851
+ children: /* @__PURE__ */jsxs(Breadcrumbs, {
1852
+ style: {
1853
+ display: "flex",
1854
+ flexWrap: "wrap",
1855
+ alignItems: "center",
1856
+ marginTop: "-4px"
1857
+ },
1858
+ separator: /* @__PURE__ */jsx(Box, {
1859
+ marginTop: 1,
1860
+ children: /* @__PURE__ */jsx(Text, {
1861
+ muted: true,
1862
+ size: 1,
1863
+ children: "/"
1864
+ })
1865
+ }),
1866
+ space: 1,
1867
+ children: [splitTitle.slice(0, splitTitle.length - 1).map((pt, i) =>
1868
+ // eslint-disable-next-line react/no-array-index-key
1869
+ /* @__PURE__ */
1870
+ jsx(Box, {
1871
+ marginTop: 1,
1872
+ children: /* @__PURE__ */jsx(Text, {
1873
+ muted: true,
1874
+ size: 1,
1875
+ children: pt.trim()
1876
+ })
1877
+ }, i)), /* @__PURE__ */jsx(Box, {
1878
+ marginTop: 1,
1879
+ children: /* @__PURE__ */jsx(Text, {
1880
+ size: 1,
1881
+ weight: "medium",
1882
+ children: splitTitle[splitTitle.length - 1]
1883
+ })
1884
+ })]
1885
+ })
1886
+ });
1887
+ }
1888
+ function useInterval(ms) {
1889
+ const [tick, update] = useReducer(n => n + 1, 0);
1890
+ useEffect(() => {
1891
+ const i = setInterval(update, ms);
1892
+ return () => clearInterval(i);
1893
+ }, [ms]);
1894
+ return tick;
1895
+ }
1896
+ function TimeAgo(_ref10) {
1897
+ let {
1898
+ date
1899
+ } = _ref10;
1900
+ useInterval(1e3);
1901
+ const timeSince = formatDistanceToNow(date ? new Date(date) : /* @__PURE__ */new Date());
1902
+ return /* @__PURE__ */jsxs("span", {
1903
+ title: timeSince,
1904
+ children: [timeSince, " ago"]
1905
+ });
1906
+ }
1907
+ var __freeze$5 = Object.freeze;
1908
+ var __defProp$5 = Object.defineProperty;
1909
+ var __template$5 = (cooked, raw) => __freeze$5(__defProp$5(cooked, "raw", {
1910
+ value: __freeze$5(raw || cooked.slice())
1911
+ }));
1912
+ var _a$5, _b$3;
1913
+ const rotate = keyframes(_a$5 || (_a$5 = __template$5(["\n 0% {\n transform: rotate(0);\n }\n 100% {\n transform: rotate(360deg);\n }\n"])));
1914
+ const SyncSpinningIcon = styled(SyncIcon)(_b$3 || (_b$3 = __template$5(["\n animation: ", " 1s linear infinite;\n"])), rotate);
1915
+ const TASK_CONFIG = {
1916
+ aborted: {
1917
+ title: "Canceled",
1918
+ icon: CloseCircleIcon,
1919
+ tone: "transparent"
1920
+ },
1921
+ error: {
1922
+ title: "Error",
1923
+ icon: ErrorOutlineIcon,
1924
+ tone: "critical"
1925
+ },
1926
+ success: {
1927
+ title: "Completed",
1928
+ icon: CheckmarkCircleIcon,
1929
+ tone: "positive"
1930
+ },
1931
+ timeout: {
1932
+ title: "Timeout",
1933
+ icon: ClockIcon,
1934
+ tone: "caution"
1935
+ }
1936
+ };
1937
+ function InstructionTaskHistoryButton(props) {
1938
+ const {
1939
+ tasks,
1940
+ instructions,
1941
+ documentId,
1942
+ showTitles
1943
+ } = props;
1944
+ const client = useClient({
1945
+ apiVersion: "2023-01-01"
1946
+ });
1947
+ const cancelRun = useCallback(taskKey => {
1948
+ if (!documentId) {
1949
+ return;
1950
+ }
1951
+ const statusDocId = assistTasksStatusId(documentId);
1952
+ const basePath = "".concat(typed("tasks"), '[_key=="').concat(taskKey, '"]');
1953
+ client.patch(statusDocId).set({
1954
+ ["".concat(basePath, ".").concat(typed("ended"))]: ( /* @__PURE__ */new Date()).toISOString(),
1955
+ ["".concat(basePath, ".").concat(typed("reason"))]: typed("aborted")
1956
+ }).commit().catch(console.error);
1957
+ }, [client, documentId]);
1958
+ const titledTasks = useMemo(() => {
1959
+ var _a2;
1960
+ const t = (_a2 = tasks == null ? void 0 : tasks.filter(task => task.started && ( /* @__PURE__ */new Date()).getTime() - new Date(task.started).getTime() < maxHistoryVisibilityMs).map(task => {
1961
+ var _a3;
1962
+ const instruction = instructions == null ? void 0 : instructions.find(i => i._key === task.instructionKey);
1963
+ return {
1964
+ ...task,
1965
+ title: showTitles ? (_a3 = task.title) != null ? _a3 : getInstructionTitle(instruction) : void 0,
1966
+ cancel: () => cancelRun(task._key)
1967
+ };
1968
+ })) != null ? _a2 : [];
1969
+ t.sort((a, b) => {
1970
+ var _a3, _b2;
1971
+ return new Date((_a3 = b.started) != null ? _a3 : "").getTime() - new Date((_b2 = a.started) != null ? _b2 : "").getTime();
1972
+ });
1973
+ return t;
1974
+ }, [tasks, instructions, cancelRun, showTitles]);
1975
+ const isRunning = useMemo(() => titledTasks.some(r => !r.ended), [titledTasks]);
1976
+ const hasErrors = useMemo(() => titledTasks.some(r => r.reason === "error" || r.reason === "timeout"), [titledTasks]);
1977
+ const [open, setOpen] = useState(false);
1978
+ const toggleOpen = useCallback(() => setOpen(v => !v), []);
1979
+ const [button, setButton] = useState(null);
1980
+ const [popover, setPopover] = useState(null);
1981
+ const handleClickOutside = useCallback(() => {
1982
+ setOpen(false);
1983
+ }, []);
1984
+ useClickOutside(handleClickOutside, [button, popover]);
1985
+ const handleEscape = useCallback(() => {
1986
+ setOpen(false);
1987
+ button == null ? void 0 : button.focus();
1988
+ }, [button]);
1989
+ return /* @__PURE__ */jsx(Popover, {
1990
+ constrainSize: true,
1991
+ content: /* @__PURE__ */jsx(TaskList, {
1992
+ onEscape: handleEscape,
1993
+ tasks: titledTasks
1994
+ }),
1995
+ open: open && !!(titledTasks == null ? void 0 : titledTasks.length),
1996
+ placement: "top",
1997
+ portal: true,
1998
+ ref: setPopover,
1999
+ width: 0,
2000
+ children: /* @__PURE__ */jsx(TaskStatusButton, {
2001
+ disabled: !(titledTasks == null ? void 0 : titledTasks.length),
2002
+ hasErrors,
2003
+ isRunning,
2004
+ onClick: toggleOpen,
2005
+ ref: setButton,
2006
+ selected: open
2007
+ })
2008
+ });
2009
+ }
2010
+ const TASK_STATUS_BUTTON_TOOLTIP_PROPS = {
2011
+ placement: "top"
2012
+ };
2013
+ const TaskStatusButton = forwardRef(function TaskStatusButton2(props, ref) {
2014
+ const {
2015
+ disabled,
2016
+ hasErrors,
2017
+ isRunning,
2018
+ onClick,
2019
+ selected
2020
+ } = props;
2021
+ return /* @__PURE__ */jsx(StatusButton, {
2022
+ label: "".concat(pluginTitle, " status"),
2023
+ icon: isRunning ? SyncSpinningIcon : hasErrors ? ErrorOutlineIcon : CheckmarkCircleIcon,
2024
+ mode: "bleed",
2025
+ onClick,
2026
+ tone: hasErrors ? "critical" : void 0,
2027
+ disabled,
2028
+ ref,
2029
+ selected,
2030
+ tooltipProps: TASK_STATUS_BUTTON_TOOLTIP_PROPS
2031
+ });
2032
+ });
2033
+ function TaskList(props) {
2034
+ const {
2035
+ onEscape,
2036
+ tasks
2037
+ } = props;
2038
+ const {
2039
+ isTopLayer
2040
+ } = useLayer();
2041
+ useGlobalKeyDown(useCallback(event => {
2042
+ if (isTopLayer && event.key === "Escape") {
2043
+ onEscape();
2044
+ }
2045
+ }, [isTopLayer, onEscape]));
2046
+ return /* @__PURE__ */jsx(Stack, {
2047
+ padding: 1,
2048
+ space: 1,
2049
+ children: tasks.map(task => /* @__PURE__ */jsx(TaskItem, {
2050
+ task
2051
+ }, task._key))
2052
+ });
2053
+ }
2054
+ function TaskItem(props) {
2055
+ var _a2;
2056
+ const {
2057
+ task
2058
+ } = props;
2059
+ const taskType = task.reason && TASK_CONFIG[task.reason];
2060
+ return /* @__PURE__ */jsx(Card, {
2061
+ radius: 2,
2062
+ tone: taskType && (taskType == null ? void 0 : taskType.tone),
2063
+ children: /* @__PURE__ */jsxs(Flex, {
2064
+ align: "center",
2065
+ gap: 1,
2066
+ children: [/* @__PURE__ */jsxs(Flex, {
2067
+ align: "flex-start",
2068
+ flex: 1,
2069
+ gap: 3,
2070
+ padding: 3,
2071
+ children: [/* @__PURE__ */jsx(Box, {
2072
+ flex: "none",
2073
+ children: /* @__PURE__ */jsxs(Text, {
2074
+ size: 1,
2075
+ children: [taskType && createElement(taskType.icon), !task.reason && /* @__PURE__ */jsx(Spinner, {})]
2076
+ })
2077
+ }), /* @__PURE__ */jsxs(Stack, {
2078
+ flex: 1,
2079
+ space: 2,
2080
+ children: [/* @__PURE__ */jsxs(Text, {
2081
+ size: 1,
2082
+ weight: "medium",
2083
+ children: [taskType ? taskType.title : "Running", task.title && /* @__PURE__ */jsxs(Fragment, {
2084
+ children: [": ", task.title]
2085
+ })]
2086
+ }), task.message ? /* @__PURE__ */jsx(Text, {
2087
+ size: 1,
2088
+ children: task.message
2089
+ }) : null, /* @__PURE__ */jsx(Text, {
2090
+ muted: true,
2091
+ size: 1,
2092
+ children: /* @__PURE__ */jsx(TimeAgo, {
2093
+ date: (_a2 = task.ended) != null ? _a2 : task.started
2094
+ })
2095
+ })]
2096
+ })]
2097
+ }), !task.ended && /* @__PURE__ */jsx(Box, {
2098
+ flex: "none",
2099
+ padding: 1,
2100
+ children: /* @__PURE__ */jsx(Button, {
2101
+ fontSize: 1,
2102
+ mode: "bleed",
2103
+ onClick: task.cancel,
2104
+ text: "Cancel"
2105
+ })
2106
+ })]
2107
+ })
2108
+ });
2109
2109
  }
2110
2110
  var __freeze$4 = Object.freeze;
2111
2111
  var __defProp$4 = Object.defineProperty;
@@ -2508,60 +2508,109 @@ const assistInspector = {
2508
2508
  };
2509
2509
  }
2510
2510
  };
2511
- const AssistDocumentContext = createContext(void 0);
2512
- function useAssistDocumentContext() {
2513
- const context = useContext(AssistDocumentContext);
2514
- if (!context) {
2515
- throw new Error("AssistDocumentContext value is missing");
2516
- }
2517
- return context;
2511
+ function AssistFeatureBadge() {
2512
+ return /* @__PURE__ */jsx(Badge, {
2513
+ fontSize: 0,
2514
+ style: {
2515
+ margin: "-2px 0"
2516
+ },
2517
+ tone: "primary",
2518
+ children: "Beta"
2519
+ });
2518
2520
  }
2519
- const NO_PRESENCE = [];
2520
- function useAssistPresence(path, showFocusWithin) {
2521
- const context = useAssistDocumentContext();
2522
- const assistDocument = context && "assistDocument" in context ? context.assistDocument : void 0;
2523
- const tasks = assistDocument == null ? void 0 : assistDocument.tasks;
2524
- return useMemo(() => {
2525
- var _a, _b;
2526
- const activePresence = (_b = (_a = tasks == null ? void 0 : tasks.filter(task => !task.ended)) == null ? void 0 : _a.flatMap(task => {
2527
- var _a2;
2528
- return (_a2 = task.presence) != null ? _a2 : [];
2529
- })) == null ? void 0 : _b.filter(p => p.started && ( /* @__PURE__ */new Date()).getTime() - new Date(p.started).getTime() < maxHistoryVisibilityMs).filter(presence => {
2530
- if (!presence.path || !path.length) {
2531
- return false;
2532
- }
2533
- const statusPath = stringToPath$2(presence.path);
2534
- if (!showFocusWithin && statusPath.length !== path.length) {
2535
- return false;
2536
- }
2537
- return path.every((pathSegment, i) => {
2538
- const statusSegment = statusPath[i];
2539
- if (typeof pathSegment === "string") {
2540
- return pathSegment === statusSegment;
2541
- }
2542
- if (isKeySegment(pathSegment) && isKeySegment(statusSegment)) {
2543
- return pathSegment._key === statusSegment._key;
2544
- }
2545
- return false;
2546
- });
2547
- });
2548
- if (!(activePresence == null ? void 0 : activePresence.length)) {
2549
- return NO_PRESENCE;
2550
- }
2551
- return activePresence.map(status => aiPresence(status, path));
2552
- }, [showFocusWithin, tasks, path]);
2521
+ function AssistOnboardingPopover(props) {
2522
+ const {
2523
+ dismiss
2524
+ } = props;
2525
+ return /* @__PURE__ */jsx(Popover, {
2526
+ content: /* @__PURE__ */jsx(AssistIntroCard, {
2527
+ dismiss
2528
+ }),
2529
+ open: true,
2530
+ portal: true,
2531
+ placeholder: "bottom",
2532
+ tone: "default",
2533
+ width: 0,
2534
+ children: /* @__PURE__ */jsx(Card, {
2535
+ radius: 2,
2536
+ shadow: 2,
2537
+ style: {
2538
+ padding: 2,
2539
+ lineHeight: 0
2540
+ },
2541
+ children: /* @__PURE__ */jsx(Button, {
2542
+ disabled: true,
2543
+ fontSize: 1,
2544
+ icon: SparklesIcon,
2545
+ mode: "bleed",
2546
+ padding: 2
2547
+ })
2548
+ })
2549
+ });
2553
2550
  }
2554
- function aiPresence(presence, path, title) {
2555
- var _a;
2556
- return {
2557
- user: {
2558
- id: "sanity-assistant_".concat(presence._key),
2559
- displayName: pluginTitle
2560
- },
2561
- path,
2562
- sessionId: "not-available",
2563
- lastActiveAt: (_a = presence == null ? void 0 : presence.started) != null ? _a : ( /* @__PURE__ */new Date()).toISOString()
2564
- };
2551
+ function AssistIntroCard(props) {
2552
+ const buttonRef = useRef(null);
2553
+ return /* @__PURE__ */jsxs(Stack, {
2554
+ as: "section",
2555
+ padding: 3,
2556
+ space: 3,
2557
+ children: [/* @__PURE__ */jsxs(Stack, {
2558
+ padding: 2,
2559
+ space: 4,
2560
+ children: [/* @__PURE__ */jsxs(Flex, {
2561
+ gap: 2,
2562
+ align: "center",
2563
+ children: [/* @__PURE__ */jsx(Text, {
2564
+ as: "h1",
2565
+ size: 1,
2566
+ weight: "semibold",
2567
+ children: pluginTitle
2568
+ }), /* @__PURE__ */jsx("div", {
2569
+ "aria-hidden": true,
2570
+ style: {
2571
+ margin: "-3px 0",
2572
+ lineHeight: 0
2573
+ },
2574
+ children: /* @__PURE__ */jsx(AssistFeatureBadge, {})
2575
+ })]
2576
+ }), /* @__PURE__ */jsx(Stack, {
2577
+ space: 3,
2578
+ children: /* @__PURE__ */jsxs(Text, {
2579
+ as: "p",
2580
+ muted: true,
2581
+ size: 1,
2582
+ children: ["Manage reusable AI instructions to boost your content creation and reduce amount of repetitive chores.", " ", /* @__PURE__ */jsxs("a", {
2583
+ href: releaseAnnouncementUrl,
2584
+ target: "_blank",
2585
+ rel: "noreferrer",
2586
+ children: ["Learn more ", /* @__PURE__ */jsx(ArrowRightIcon, {})]
2587
+ })]
2588
+ })
2589
+ })]
2590
+ }), /* @__PURE__ */jsx(Button, {
2591
+ fontSize: 1,
2592
+ icon: CheckmarkIcon,
2593
+ onClick: props.dismiss,
2594
+ padding: 3,
2595
+ ref: buttonRef,
2596
+ text: "Ok, good to know!",
2597
+ tone: "primary"
2598
+ })]
2599
+ });
2600
+ }
2601
+ const FirstAssistedPathContext = createContext(void 0);
2602
+ function FirstAssistedPathProvider(props) {
2603
+ const {
2604
+ members
2605
+ } = props;
2606
+ const firstAssistedPath = useMemo(() => {
2607
+ const firstAssisted = members.find(member => member.kind === "field" && isAssistSupported(member.field.schemaType));
2608
+ return (firstAssisted == null ? void 0 : firstAssisted.field.path) ? pathToString(firstAssisted == null ? void 0 : firstAssisted.field.path) : void 0;
2609
+ }, [members]);
2610
+ return /* @__PURE__ */jsx(FirstAssistedPathContext.Provider, {
2611
+ value: firstAssistedPath,
2612
+ children: props.children
2613
+ });
2565
2614
  }
2566
2615
  var __freeze$3 = Object.freeze;
2567
2616
  var __defProp$3 = Object.defineProperty;
@@ -2585,47 +2634,47 @@ const FadeInContent = forwardRef(function FadeInContent2(_ref12, ref) {
2585
2634
  });
2586
2635
  });
2587
2636
  const purple = {
2588
- "50": {
2637
+ 50: {
2589
2638
  title: "Purple 50",
2590
2639
  hex: "#f8f5ff"
2591
2640
  },
2592
- "100": {
2641
+ 100: {
2593
2642
  title: "Purple 100",
2594
2643
  hex: "#f1ebff"
2595
2644
  },
2596
- "200": {
2645
+ 200: {
2597
2646
  title: "Purple 200",
2598
2647
  hex: "#ece1fe"
2599
2648
  },
2600
- "300": {
2649
+ 300: {
2601
2650
  title: "Purple 300",
2602
2651
  hex: "#ccb1fc"
2603
2652
  },
2604
- "400": {
2653
+ 400: {
2605
2654
  title: "Purple 400",
2606
2655
  hex: "#b087f7"
2607
2656
  },
2608
- "500": {
2657
+ 500: {
2609
2658
  title: "Purple 500",
2610
2659
  hex: "#8f57ef"
2611
2660
  },
2612
- "600": {
2661
+ 600: {
2613
2662
  title: "Purple 600",
2614
2663
  hex: "#721fe5"
2615
2664
  },
2616
- "700": {
2665
+ 700: {
2617
2666
  title: "Purple 700",
2618
2667
  hex: "#4c1a9e"
2619
2668
  },
2620
- "800": {
2669
+ 800: {
2621
2670
  title: "Purple 800",
2622
2671
  hex: "#2f1862"
2623
2672
  },
2624
- "900": {
2673
+ 900: {
2625
2674
  title: "Purple 900",
2626
2675
  hex: "#23173f"
2627
2676
  },
2628
- "950": {
2677
+ 950: {
2629
2678
  title: "Purple 950",
2630
2679
  hex: "#181128"
2631
2680
  }
@@ -2672,154 +2721,105 @@ function AssistAvatar(props) {
2672
2721
  r: "11.75"
2673
2722
  })
2674
2723
  }), /* @__PURE__ */jsx(IconDisc, {
2675
- children: /* @__PURE__ */jsx(Text, {
2676
- as: "span",
2677
- size: 0,
2678
- style: {
2679
- color: "inherit"
2680
- },
2681
- children: /* @__PURE__ */jsx(SparklesIcon, {
2682
- style: {
2683
- color: "inherit"
2684
- }
2685
- })
2686
- })
2687
- })]
2688
- });
2689
- }
2690
- function AiFieldPresence(props) {
2691
- return /* @__PURE__ */jsx(Card, {
2692
- style: {
2693
- position: "relative",
2694
- background: "transparent"
2695
- },
2696
- contentEditable: false,
2697
- children: /* @__PURE__ */jsx(Tooltip, {
2698
- placement: "left",
2699
- content: /* @__PURE__ */jsx(Card, {
2700
- padding: 3,
2701
- border: true,
2702
- children: /* @__PURE__ */jsx(Flex, {
2703
- align: "center",
2704
- children: /* @__PURE__ */jsx(Text, {
2705
- size: 1,
2706
- children: "Running instruction..."
2707
- })
2708
- })
2709
- }),
2710
- children: /* @__PURE__ */jsx(FadeInContent, {
2711
- durationMs: 300,
2712
- children: /* @__PURE__ */jsx(AssistAvatar, {
2713
- state: "active"
2714
- })
2715
- })
2716
- })
2717
- });
2718
- }
2719
- function AssistFeatureBadge() {
2720
- return /* @__PURE__ */jsx(Badge, {
2721
- fontSize: 0,
2722
- style: {
2723
- margin: "-2px 0"
2724
- },
2725
- tone: "primary",
2726
- children: "Beta"
2727
- });
2728
- }
2729
- function AssistOnboardingPopover(props) {
2730
- const {
2731
- dismiss
2732
- } = props;
2733
- return /* @__PURE__ */jsx(Popover, {
2734
- content: /* @__PURE__ */jsx(AssistIntroCard, {
2735
- dismiss
2736
- }),
2737
- open: true,
2738
- portal: true,
2739
- placeholder: "bottom",
2740
- tone: "default",
2741
- width: 0,
2742
- children: /* @__PURE__ */jsx(Card, {
2743
- radius: 2,
2744
- shadow: 2,
2745
- style: {
2746
- padding: 2,
2747
- lineHeight: 0
2748
- },
2749
- children: /* @__PURE__ */jsx(Button, {
2750
- disabled: true,
2751
- fontSize: 1,
2752
- icon: SparklesIcon,
2753
- mode: "bleed",
2754
- padding: 2
2755
- })
2756
- })
2757
- });
2758
- }
2759
- function AssistIntroCard(props) {
2760
- const buttonRef = useRef(null);
2761
- return /* @__PURE__ */jsxs(Stack, {
2762
- as: "section",
2763
- padding: 3,
2764
- space: 3,
2765
- children: [/* @__PURE__ */jsxs(Stack, {
2766
- padding: 2,
2767
- space: 4,
2768
- children: [/* @__PURE__ */jsxs(Flex, {
2769
- gap: 2,
2770
- align: "center",
2771
- children: [/* @__PURE__ */jsx(Text, {
2772
- as: "h1",
2773
- size: 1,
2774
- weight: "semibold",
2775
- children: pluginTitle
2776
- }), /* @__PURE__ */jsx("div", {
2777
- "aria-hidden": true,
2724
+ children: /* @__PURE__ */jsx(Text, {
2725
+ as: "span",
2726
+ size: 0,
2727
+ style: {
2728
+ color: "inherit"
2729
+ },
2730
+ children: /* @__PURE__ */jsx(SparklesIcon, {
2778
2731
  style: {
2779
- margin: "-3px 0",
2780
- lineHeight: 0
2781
- },
2782
- children: /* @__PURE__ */jsx(AssistFeatureBadge, {})
2783
- })]
2784
- }), /* @__PURE__ */jsx(Stack, {
2785
- space: 3,
2786
- children: /* @__PURE__ */jsxs(Text, {
2787
- as: "p",
2788
- muted: true,
2789
- size: 1,
2790
- children: ["Manage reusable AI instructions to boost your content creation and reduce amount of repetitive chores.", " ", /* @__PURE__ */jsxs("a", {
2791
- href: releaseAnnouncementUrl,
2792
- target: "_blank",
2793
- rel: "noreferrer",
2794
- children: ["Learn more ", /* @__PURE__ */jsx(ArrowRightIcon, {})]
2795
- })]
2732
+ color: "inherit"
2733
+ }
2796
2734
  })
2797
- })]
2798
- }), /* @__PURE__ */jsx(Button, {
2799
- fontSize: 1,
2800
- icon: CheckmarkIcon,
2801
- onClick: props.dismiss,
2802
- padding: 3,
2803
- ref: buttonRef,
2804
- text: "Ok, good to know!",
2805
- tone: "primary"
2735
+ })
2806
2736
  })]
2807
2737
  });
2808
2738
  }
2809
- const FirstAssistedPathContext = createContext(void 0);
2810
- function FirstAssistedPathProvider(props) {
2811
- const {
2812
- members
2813
- } = props;
2814
- const firstAssistedPath = useMemo(() => {
2815
- const firstAssisted = members.find(member => member.kind === "field" && isAssistSupported(member.field.schemaType));
2816
- return (firstAssisted == null ? void 0 : firstAssisted.field.path) ? pathToString(firstAssisted == null ? void 0 : firstAssisted.field.path) : void 0;
2817
- }, [members]);
2818
- return /* @__PURE__ */jsx(FirstAssistedPathContext.Provider, {
2819
- value: firstAssistedPath,
2820
- children: props.children
2739
+ function AiFieldPresence(props) {
2740
+ return /* @__PURE__ */jsx(Card, {
2741
+ style: {
2742
+ position: "relative",
2743
+ background: "transparent"
2744
+ },
2745
+ contentEditable: false,
2746
+ children: /* @__PURE__ */jsx(Tooltip, {
2747
+ placement: "left",
2748
+ content: /* @__PURE__ */jsx(Card, {
2749
+ padding: 3,
2750
+ border: true,
2751
+ children: /* @__PURE__ */jsx(Flex, {
2752
+ align: "center",
2753
+ children: /* @__PURE__ */jsx(Text, {
2754
+ size: 1,
2755
+ children: "Running instruction..."
2756
+ })
2757
+ })
2758
+ }),
2759
+ children: /* @__PURE__ */jsx(FadeInContent, {
2760
+ durationMs: 300,
2761
+ children: /* @__PURE__ */jsx(AssistAvatar, {
2762
+ state: "active"
2763
+ })
2764
+ })
2765
+ })
2821
2766
  });
2822
2767
  }
2768
+ const AssistDocumentContext = createContext(void 0);
2769
+ function useAssistDocumentContext() {
2770
+ const context = useContext(AssistDocumentContext);
2771
+ if (!context) {
2772
+ throw new Error("AssistDocumentContext value is missing");
2773
+ }
2774
+ return context;
2775
+ }
2776
+ const NO_PRESENCE = [];
2777
+ function useAssistPresence(path, showFocusWithin) {
2778
+ const context = useAssistDocumentContext();
2779
+ const assistDocument = context && "assistDocument" in context ? context.assistDocument : void 0;
2780
+ const tasks = assistDocument == null ? void 0 : assistDocument.tasks;
2781
+ return useMemo(() => {
2782
+ var _a, _b;
2783
+ const activePresence = (_b = (_a = tasks == null ? void 0 : tasks.filter(task => !task.ended)) == null ? void 0 : _a.flatMap(task => {
2784
+ var _a2;
2785
+ return (_a2 = task.presence) != null ? _a2 : [];
2786
+ })) == null ? void 0 : _b.filter(p => p.started && ( /* @__PURE__ */new Date()).getTime() - new Date(p.started).getTime() < maxHistoryVisibilityMs).filter(presence => {
2787
+ if (!presence.path || !path.length) {
2788
+ return false;
2789
+ }
2790
+ const statusPath = stringToPath$2(presence.path);
2791
+ if (!showFocusWithin && statusPath.length !== path.length) {
2792
+ return false;
2793
+ }
2794
+ return path.every((pathSegment, i) => {
2795
+ const statusSegment = statusPath[i];
2796
+ if (typeof pathSegment === "string") {
2797
+ return pathSegment === statusSegment;
2798
+ }
2799
+ if (isKeySegment(pathSegment) && isKeySegment(statusSegment)) {
2800
+ return pathSegment._key === statusSegment._key;
2801
+ }
2802
+ return false;
2803
+ });
2804
+ });
2805
+ if (!(activePresence == null ? void 0 : activePresence.length)) {
2806
+ return NO_PRESENCE;
2807
+ }
2808
+ return activePresence.map(status => aiPresence(status, path));
2809
+ }, [showFocusWithin, tasks, path]);
2810
+ }
2811
+ function aiPresence(presence, path, title) {
2812
+ var _a;
2813
+ return {
2814
+ user: {
2815
+ id: "sanity-assistant_".concat(presence._key),
2816
+ displayName: pluginTitle
2817
+ },
2818
+ path,
2819
+ sessionId: "not-available",
2820
+ lastActiveAt: (_a = presence == null ? void 0 : presence.started) != null ? _a : ( /* @__PURE__ */new Date()).toISOString()
2821
+ };
2822
+ }
2823
2823
  function AssistFieldWrapper(props) {
2824
2824
  const {
2825
2825
  schemaType
@@ -2870,14 +2870,6 @@ function AssistField(props) {
2870
2870
  __internal_slot: actions
2871
2871
  });
2872
2872
  }
2873
- const ConnectorsStoreContext = createContext(null);
2874
- function useConnectorsStore() {
2875
- const store = useContext(ConnectorsStoreContext);
2876
- if (!store) {
2877
- throw new Error("Missing connectors store context");
2878
- }
2879
- return store;
2880
- }
2881
2873
  function hasOverflowScroll(el) {
2882
2874
  const overflow = getComputedStyle(el).overflow;
2883
2875
  return overflow.includes("auto") || overflow.includes("hidden") || overflow.includes("scroll");
@@ -3015,6 +3007,14 @@ function ConnectorRegion(props) {
3015
3007
  children
3016
3008
  });
3017
3009
  }
3010
+ const ConnectorsStoreContext = createContext(null);
3011
+ function useConnectorsStore() {
3012
+ const store = useContext(ConnectorsStoreContext);
3013
+ if (!store) {
3014
+ throw new Error("Missing connectors store context");
3015
+ }
3016
+ return store;
3017
+ }
3018
3018
  function ConnectFromRegion(props) {
3019
3019
  const {
3020
3020
  children,
@@ -4969,117 +4969,44 @@ function AssistItem(props) {
4969
4969
  }, pre.user.id))]
4970
4970
  });
4971
4971
  }
4972
- function findFieldMember(members, fieldName) {
4973
- return members.find(m => m.kind === "field" && m.name === fieldName || m.kind === "error" && m.fieldName === fieldName);
4974
- }
4975
- function findFieldsetMember(members, fieldsetName) {
4976
- return members.find(m => m.kind === "fieldSet" && m.fieldSet.name === fieldsetName);
4977
- }
4978
- function InstructionInput(props) {
4979
- return /* @__PURE__ */jsxs(Stack, {
4980
- space: [4, 4, 4, 5],
4981
- children: [/* @__PURE__ */jsx(NameField, {
4982
- ...props
4983
- }), /* @__PURE__ */jsx(ShareField, {
4984
- ...props
4985
- }), /* @__PURE__ */jsx(ObjectMember, {
4986
- fieldName: "prompt",
4987
- ...props
4988
- }), /* @__PURE__ */jsx(ObjectMember, {
4989
- fieldName: "output",
4990
- ...props
4991
- })]
4992
- });
4993
- }
4994
- function ObjectMember(_ref13) {
4995
- let {
4996
- fieldName,
4997
- ...props
4998
- } = _ref13;
4999
- const member = findFieldMember(props.members, fieldName);
5000
- return member ? /* @__PURE__ */jsx(ObjectInputMember, {
5001
- ...props,
5002
- member
5003
- }) : null;
5004
- }
5005
- const NONE = [];
5006
- function NameField(props) {
5007
- var _a;
5008
- const fieldsetMember = findFieldsetMember(props.members, "appearance");
5009
- const titleId = useId();
5010
- const members = (_a = fieldsetMember == null ? void 0 : fieldsetMember.fieldSet.members) != null ? _a : NONE;
5011
- const iconMember = findFieldMember(members, "icon");
5012
- const titleMember = findFieldMember(members, "title");
5013
- const titlePlaceholder = "Untitled";
5014
- const moddedTitleMember = useMemo(() => {
5015
- if (!titleMember) {
5016
- return void 0;
5017
- }
5018
- if (titleMember.kind === "error") {
5019
- return titleMember;
5020
- }
5021
- return {
5022
- ...titleMember,
5023
- field: {
5024
- ...(titleMember == null ? void 0 : titleMember.field),
5025
- schemaType: {
5026
- ...(titleMember == null ? void 0 : titleMember.field.schemaType),
5027
- placeholder: titlePlaceholder
5028
- }
5029
- }
5030
- };
5031
- }, [titleMember, titlePlaceholder]);
5032
- return /* @__PURE__ */jsx(Stack, {
5033
- space: 5,
5034
- children: /* @__PURE__ */jsxs(Stack, {
5035
- space: 2,
5036
- children: [/* @__PURE__ */jsx(Flex, {
5037
- gap: 1,
5038
- children: /* @__PURE__ */jsx(Text, {
5039
- as: "label",
5040
- weight: "semibold",
5041
- size: 1,
5042
- htmlFor: titleId,
5043
- children: "Name"
5044
- })
5045
- }), /* @__PURE__ */jsx(Text, {
5046
- muted: true,
5047
- size: 1,
5048
- children: "How this instruction appears in menus"
5049
- }), /* @__PURE__ */jsxs(Flex, {
5050
- align: "center",
5051
- children: [iconMember && /* @__PURE__ */jsx(Box, {
5052
- flex: "none",
5053
- children: /* @__PURE__ */jsx(ObjectInputMember, {
5054
- ...props,
5055
- member: iconMember
5056
- })
5057
- }), moddedTitleMember && /* @__PURE__ */jsx(Box, {
5058
- flex: 1,
5059
- style: {
5060
- marginLeft: -1
5061
- },
5062
- children: /* @__PURE__ */jsx(ObjectInputMember, {
5063
- ...props,
5064
- member: moddedTitleMember
5065
- })
5066
- })]
5067
- })]
5068
- })
5069
- });
5070
- }
5071
- function ShareField(props) {
5072
- var _a;
5073
- const fieldsetMember = findFieldsetMember(props.members, "appearance");
5074
- const members = (_a = fieldsetMember == null ? void 0 : fieldsetMember.fieldSet.members) != null ? _a : NONE;
5075
- const visibilityMember = findFieldMember(members, "userId");
5076
- return /* @__PURE__ */jsx(Fragment, {
5077
- children: visibilityMember && /* @__PURE__ */jsx(ObjectInputMember, {
5078
- ...props,
5079
- member: visibilityMember
4972
+ const InlineBlockValueContext = createContext(void 0);
4973
+ function AssistInlineFormBlock(props) {
4974
+ return /* @__PURE__ */jsx(InlineBlockValueContext.Provider, {
4975
+ value: props.value,
4976
+ children: /* @__PURE__ */jsx(Fragment, {
4977
+ children: props.renderDefault(props)
5080
4978
  })
5081
4979
  });
5082
4980
  }
4981
+ function FieldRefPreview(props) {
4982
+ var _a, _b, _c, _d;
4983
+ const documentSchema = (_a = useContext(SelectedFieldContext)) == null ? void 0 : _a.documentSchema;
4984
+ const path = (_c = (_b = useContext(InlineBlockValueContext)) == null ? void 0 : _b.path) != null ? _c : props.path;
4985
+ const selectedField = useSelectedField(documentSchema, path);
4986
+ return /* @__PURE__ */jsxs(Flex, {
4987
+ gap: 2,
4988
+ align: "center",
4989
+ style: {
4990
+ width: "100%"
4991
+ },
4992
+ children: [/* @__PURE__ */jsx(Flex, {
4993
+ flex: 1,
4994
+ gap: 2,
4995
+ align: "center",
4996
+ paddingY: 3,
4997
+ paddingX: 1,
4998
+ children: /* @__PURE__ */jsx(Box, {
4999
+ children: /* @__PURE__ */jsx(Text, {
5000
+ size: 1,
5001
+ textOverflow: "ellipsis",
5002
+ children: (_d = selectedField == null ? void 0 : selectedField.title) != null ? _d : "Select field"
5003
+ })
5004
+ })
5005
+ }), /* @__PURE__ */jsx(Fragment, {
5006
+ children: props.actions
5007
+ })]
5008
+ });
5009
+ }
5083
5010
  function HiddenFieldTitle(props) {
5084
5011
  return props.renderDefault({
5085
5012
  ...props,
@@ -5088,54 +5015,14 @@ function HiddenFieldTitle(props) {
5088
5015
  changed: false
5089
5016
  });
5090
5017
  }
5091
- function InstructionVisibility(props) {
5092
- const {
5093
- value,
5094
- onChange
5095
- } = props;
5096
- const user = useCurrentUser();
5097
- const handleChange = useCallback(() => {
5098
- var _a;
5099
- const newValue = value ? "" : (_a = user == null ? void 0 : user.id) != null ? _a : "";
5100
- onChange(newValue ? set(newValue) : unset());
5101
- }, [onChange, user, value]);
5102
- const id = useId();
5103
- return /* @__PURE__ */jsx(Card, {
5104
- children: /* @__PURE__ */jsxs(Flex, {
5105
- gap: 2,
5106
- align: "flex-start",
5107
- children: [/* @__PURE__ */jsx("div", {
5108
- style: {
5109
- margin: "-3px 0"
5110
- },
5111
- children: /* @__PURE__ */jsx(Switch, {
5112
- ...props.elementProps,
5113
- id,
5114
- value: "".concat(!value),
5115
- checked: !value,
5116
- onChange: handleChange,
5117
- disabled: props.elementProps.readOnly
5118
- })
5119
- }), /* @__PURE__ */jsx(Text, {
5120
- muted: true,
5121
- size: 1,
5122
- weight: "medium",
5123
- children: /* @__PURE__ */jsx("label", {
5124
- htmlFor: id,
5125
- children: "Make visible to all Studio members"
5126
- })
5127
- })]
5128
- })
5129
- });
5130
- }
5131
5018
  function IconInput(props) {
5132
5019
  const {
5133
5020
  value,
5134
5021
  onChange
5135
5022
  } = props;
5136
5023
  const id = useId();
5137
- const items = useMemo(() => Object.entries(icons).map(_ref14 => {
5138
- let [key, icon] = _ref14;
5024
+ const items = useMemo(() => Object.entries(icons).map(_ref13 => {
5025
+ let [key, icon] = _ref13;
5139
5026
  return /* @__PURE__ */jsx(IconItem, {
5140
5027
  iconKey: key,
5141
5028
  icon,
@@ -5163,12 +5050,12 @@ function IconInput(props) {
5163
5050
  }
5164
5051
  });
5165
5052
  }
5166
- function IconItem(_ref15) {
5053
+ function IconItem(_ref14) {
5167
5054
  let {
5168
5055
  icon,
5169
5056
  iconKey: key,
5170
5057
  onChange
5171
- } = _ref15;
5058
+ } = _ref14;
5172
5059
  const onClick = useCallback(() => onChange(set(key)), [onChange, key]);
5173
5060
  return /* @__PURE__ */jsx(MenuItem, {
5174
5061
  icon,
@@ -5179,11 +5066,51 @@ function IconItem(_ref15) {
5179
5066
  }
5180
5067
  function getIcon(iconName) {
5181
5068
  var _a, _b;
5182
- return (_b = (_a = Object.entries(icons).find(_ref16 => {
5183
- let [key] = _ref16;
5069
+ return (_b = (_a = Object.entries(icons).find(_ref15 => {
5070
+ let [key] = _ref15;
5184
5071
  return key === iconName;
5185
5072
  })) == null ? void 0 : _a[1]) != null ? _b : icons.sparkles;
5186
5073
  }
5074
+ function InstructionVisibility(props) {
5075
+ const {
5076
+ value,
5077
+ onChange
5078
+ } = props;
5079
+ const user = useCurrentUser();
5080
+ const handleChange = useCallback(() => {
5081
+ var _a;
5082
+ const newValue = value ? "" : (_a = user == null ? void 0 : user.id) != null ? _a : "";
5083
+ onChange(newValue ? set(newValue) : unset());
5084
+ }, [onChange, user, value]);
5085
+ const id = useId();
5086
+ return /* @__PURE__ */jsx(Card, {
5087
+ children: /* @__PURE__ */jsxs(Flex, {
5088
+ gap: 2,
5089
+ align: "flex-start",
5090
+ children: [/* @__PURE__ */jsx("div", {
5091
+ style: {
5092
+ margin: "-3px 0"
5093
+ },
5094
+ children: /* @__PURE__ */jsx(Switch, {
5095
+ ...props.elementProps,
5096
+ id,
5097
+ value: "".concat(!value),
5098
+ checked: !value,
5099
+ onChange: handleChange,
5100
+ disabled: props.elementProps.readOnly
5101
+ })
5102
+ }), /* @__PURE__ */jsx(Text, {
5103
+ muted: true,
5104
+ size: 1,
5105
+ weight: "medium",
5106
+ children: /* @__PURE__ */jsx("label", {
5107
+ htmlFor: id,
5108
+ children: "Make visible to all Studio members"
5109
+ })
5110
+ })]
5111
+ })
5112
+ });
5113
+ }
5187
5114
  function FieldRefPathInput(props) {
5188
5115
  var _a;
5189
5116
  const documentSchema = (_a = useContext(SelectedFieldContext)) == null ? void 0 : _a.documentSchema;
@@ -5228,209 +5155,115 @@ function FieldRefPathInput(props) {
5228
5155
  })
5229
5156
  });
5230
5157
  }
5231
- function InstructionsArrayInput(props) {
5232
- const user = useCurrentUser();
5233
- const originalValue = props.value;
5234
- const originalMembers = props.members;
5235
- const value = useMemo(() => (originalValue != null ? originalValue : []).filter(v => !v.userId || v.userId === (user == null ? void 0 : user.id)), [originalValue, user]);
5236
- const members = useMemo(() => (originalMembers != null ? originalMembers : []).filter(v => {
5237
- var _a;
5238
- if (v.kind === "error") {
5239
- return true;
5240
- }
5241
- const value2 = (_a = v == null ? void 0 : v.item) == null ? void 0 : _a.value;
5242
- return !value2.userId || value2.userId === (user == null ? void 0 : user.id);
5243
- }), [originalMembers, user]);
5244
- return props.renderDefault({
5245
- ...props,
5246
- value,
5247
- members
5248
- });
5249
- }
5250
- const InlineBlockValueContext = createContext(void 0);
5251
- function AssistInlineFormBlock(props) {
5252
- return /* @__PURE__ */jsx(InlineBlockValueContext.Provider, {
5253
- value: props.value,
5254
- children: /* @__PURE__ */jsx(Fragment, {
5255
- children: props.renderDefault(props)
5256
- })
5257
- });
5258
- }
5259
- function FieldRefPreview(props) {
5260
- var _a, _b, _c, _d;
5261
- const documentSchema = (_a = useContext(SelectedFieldContext)) == null ? void 0 : _a.documentSchema;
5262
- const path = (_c = (_b = useContext(InlineBlockValueContext)) == null ? void 0 : _b.path) != null ? _c : props.path;
5263
- const selectedField = useSelectedField(documentSchema, path);
5264
- return /* @__PURE__ */jsxs(Flex, {
5265
- gap: 2,
5266
- align: "center",
5267
- style: {
5268
- width: "100%"
5269
- },
5270
- children: [/* @__PURE__ */jsx(Flex, {
5271
- flex: 1,
5272
- gap: 2,
5273
- align: "center",
5274
- paddingY: 3,
5275
- paddingX: 1,
5276
- children: /* @__PURE__ */jsx(Box, {
5277
- children: /* @__PURE__ */jsx(Text, {
5278
- size: 1,
5279
- textOverflow: "ellipsis",
5280
- children: (_d = selectedField == null ? void 0 : selectedField.title) != null ? _d : "Select field"
5281
- })
5282
- })
5283
- }), /* @__PURE__ */jsx(Fragment, {
5284
- children: props.actions
5285
- })]
5286
- });
5287
- }
5288
- function HideReferenceChangedBannerInput(props) {
5289
- const ref = useRef(null);
5290
- useEffect(() => {
5291
- var _a;
5292
- const parent = (_a = ref.current) == null ? void 0 : _a.closest('[data-testid="pane-content"]');
5293
- if (!parent) {
5294
- return;
5295
- }
5296
- const style = document.createElement("style");
5297
- const parentId = "id-".concat(Math.random()).replace(".", "-");
5298
- parent.id = parentId;
5299
- style.innerText = "\n #".concat(parentId, ' [data-testid="reference-changed-banner"] { display: none; }\n ');
5300
- parent.prepend(style);
5301
- }, [ref]);
5302
- return /* @__PURE__ */jsx(Box, {
5303
- ref,
5304
- children: props.renderDefault(props)
5305
- });
5306
- }
5307
- const contextDocumentSchema = defineType({
5308
- type: "document",
5309
- name: contextDocumentTypeName,
5310
- title: "AI context",
5311
- liveEdit: true,
5312
- icon: TokenIcon,
5313
- components: {
5314
- input: HideReferenceChangedBannerInput
5315
- },
5316
- fields: [defineField({
5317
- type: "string",
5318
- name: "title",
5319
- title: "Title"
5320
- }), defineField({
5321
- name: "context",
5322
- type: "array",
5323
- title: "Context",
5324
- of: [defineArrayMember({
5325
- type: "block",
5326
- styles: [{
5327
- title: "Normal",
5328
- value: "normal"
5329
- }],
5330
- lists: [],
5331
- marks: {
5332
- decorators: [],
5333
- annotations: []
5334
- }
5335
- })]
5336
- })],
5337
- preview: {
5338
- select: {
5339
- title: "title",
5340
- context: "context"
5341
- },
5342
- prepare(_ref17) {
5343
- let {
5344
- title,
5345
- context
5346
- } = _ref17;
5347
- var _a;
5348
- const text = context == null ? void 0 : context.flatMap(block => block == null ? void 0 : block.children).flatMap(child => {
5349
- var _a2;
5350
- return (_a2 = child == null ? void 0 : child.text) == null ? void 0 : _a2.split(" ");
5351
- }).filter(Boolean);
5352
- const words = (_a = text == null ? void 0 : text.length) != null ? _a : 0;
5353
- return {
5354
- title,
5355
- subtitle: "Words: ".concat(words),
5356
- media: DocumentTextIcon
5357
- };
5358
- }
5359
- }
5360
- });
5361
-
5362
- // Strict ESM env, designed to run outside Node.js in envs that provide WebCrypto (deno, browsers, etc)
5363
-
5364
- function getRandomValues(typedArray) {
5365
- const crypto = typeof window !== 'undefined' && 'crypto' in window ? window.crypto : globalThis.crypto;
5366
- if (!crypto || !crypto.getRandomValues) {
5367
- throw new Error('WebCrypto not available in this environment');
5368
- }
5369
- return crypto.getRandomValues(typedArray);
5370
- }
5371
- function whatwgRNG() {
5372
- let length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 16;
5373
- const rnds8 = new Uint8Array(length);
5374
- getRandomValues(rnds8);
5375
- return rnds8;
5158
+ function findFieldMember(members, fieldName) {
5159
+ return members.find(m => m.kind === "field" && m.name === fieldName || m.kind === "error" && m.fieldName === fieldName);
5376
5160
  }
5377
- const getByteHexTable = /* @__PURE__ */(() => {
5378
- let table;
5379
- return () => {
5380
- if (table) {
5381
- return table;
5382
- }
5383
- table = [];
5384
- for (let i = 0; i < 256; ++i) {
5385
- table[i] = (i + 256).toString(16).substring(1);
5386
- }
5387
- return table;
5388
- };
5389
- })();
5390
- function randomKey(length) {
5391
- const table = getByteHexTable();
5392
- return whatwgRNG(length).reduce((str, n) => str + table[n], "").slice(0, length);
5161
+ function findFieldsetMember(members, fieldsetName) {
5162
+ return members.find(m => m.kind === "fieldSet" && m.fieldSet.name === fieldsetName);
5393
5163
  }
5394
- var __freeze = Object.freeze;
5395
- var __defProp = Object.defineProperty;
5396
- var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", {
5397
- value: __freeze(raw || cooked.slice())
5398
- }));
5399
- var _a;
5400
- 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"])));
5401
- function PromptInput(props) {
5402
- useOnlyInlineBlocks(props);
5403
- return /* @__PURE__ */jsx(PteMods, {
5404
- children: props.renderDefault(props)
5164
+ function InstructionInput(props) {
5165
+ return /* @__PURE__ */jsxs(Stack, {
5166
+ space: [4, 4, 4, 5],
5167
+ children: [/* @__PURE__ */jsx(NameField, {
5168
+ ...props
5169
+ }), /* @__PURE__ */jsx(ShareField, {
5170
+ ...props
5171
+ }), /* @__PURE__ */jsx(ObjectMember, {
5172
+ fieldName: "prompt",
5173
+ ...props
5174
+ }), /* @__PURE__ */jsx(ObjectMember, {
5175
+ fieldName: "output",
5176
+ ...props
5177
+ })]
5405
5178
  });
5406
5179
  }
5407
- function useOnlyInlineBlocks(props) {
5408
- useEffect(() => {
5409
- var _a2;
5410
- let needsFix = false;
5411
- const val = ((_a2 = props.value) != null ? _a2 : []).map(block => {
5412
- if (block._type === "block") {
5413
- return block;
5414
- }
5415
- needsFix = true;
5416
- return typed({
5417
- _key: randomKey(12),
5418
- _type: "block",
5419
- level: 0,
5420
- markDefs: [],
5421
- style: "normal",
5422
- children: [block]
5423
- });
5424
- });
5425
- if (needsFix) {
5426
- props.onChange(set(val));
5180
+ function ObjectMember(_ref16) {
5181
+ let {
5182
+ fieldName,
5183
+ ...props
5184
+ } = _ref16;
5185
+ const member = findFieldMember(props.members, fieldName);
5186
+ return member ? /* @__PURE__ */jsx(ObjectInputMember, {
5187
+ ...props,
5188
+ member
5189
+ }) : null;
5190
+ }
5191
+ const NONE = [];
5192
+ function NameField(props) {
5193
+ var _a;
5194
+ const fieldsetMember = findFieldsetMember(props.members, "appearance");
5195
+ const titleId = useId();
5196
+ const members = (_a = fieldsetMember == null ? void 0 : fieldsetMember.fieldSet.members) != null ? _a : NONE;
5197
+ const iconMember = findFieldMember(members, "icon");
5198
+ const titleMember = findFieldMember(members, "title");
5199
+ const titlePlaceholder = "Untitled";
5200
+ const moddedTitleMember = useMemo(() => {
5201
+ if (!titleMember) {
5202
+ return void 0;
5427
5203
  }
5428
- }, []);
5204
+ if (titleMember.kind === "error") {
5205
+ return titleMember;
5206
+ }
5207
+ return {
5208
+ ...titleMember,
5209
+ field: {
5210
+ ...(titleMember == null ? void 0 : titleMember.field),
5211
+ schemaType: {
5212
+ ...(titleMember == null ? void 0 : titleMember.field.schemaType),
5213
+ placeholder: titlePlaceholder
5214
+ }
5215
+ }
5216
+ };
5217
+ }, [titleMember, titlePlaceholder]);
5218
+ return /* @__PURE__ */jsx(Stack, {
5219
+ space: 5,
5220
+ children: /* @__PURE__ */jsxs(Stack, {
5221
+ space: 2,
5222
+ children: [/* @__PURE__ */jsx(Flex, {
5223
+ gap: 1,
5224
+ children: /* @__PURE__ */jsx(Text, {
5225
+ as: "label",
5226
+ weight: "semibold",
5227
+ size: 1,
5228
+ htmlFor: titleId,
5229
+ children: "Name"
5230
+ })
5231
+ }), /* @__PURE__ */jsx(Text, {
5232
+ muted: true,
5233
+ size: 1,
5234
+ children: "How this instruction appears in menus"
5235
+ }), /* @__PURE__ */jsxs(Flex, {
5236
+ align: "center",
5237
+ children: [iconMember && /* @__PURE__ */jsx(Box, {
5238
+ flex: "none",
5239
+ children: /* @__PURE__ */jsx(ObjectInputMember, {
5240
+ ...props,
5241
+ member: iconMember
5242
+ })
5243
+ }), moddedTitleMember && /* @__PURE__ */jsx(Box, {
5244
+ flex: 1,
5245
+ style: {
5246
+ marginLeft: -1
5247
+ },
5248
+ children: /* @__PURE__ */jsx(ObjectInputMember, {
5249
+ ...props,
5250
+ member: moddedTitleMember
5251
+ })
5252
+ })]
5253
+ })]
5254
+ })
5255
+ });
5429
5256
  }
5430
- function InstructionsArrayField(props) {
5431
- return props.renderDefault({
5432
- ...props,
5433
- title: " "
5257
+ function ShareField(props) {
5258
+ var _a;
5259
+ const fieldsetMember = findFieldsetMember(props.members, "appearance");
5260
+ const members = (_a = fieldsetMember == null ? void 0 : fieldsetMember.fieldSet.members) != null ? _a : NONE;
5261
+ const visibilityMember = findFieldMember(members, "userId");
5262
+ return /* @__PURE__ */jsx(Fragment, {
5263
+ children: visibilityMember && /* @__PURE__ */jsx(ObjectInputMember, {
5264
+ ...props,
5265
+ member: visibilityMember
5266
+ })
5434
5267
  });
5435
5268
  }
5436
5269
  function InstructionOutputField(props) {
@@ -5447,11 +5280,11 @@ function InstructionOutputField(props) {
5447
5280
  children: props.children
5448
5281
  });
5449
5282
  }
5450
- function EnabledOutputField(_ref18) {
5283
+ function EnabledOutputField(_ref17) {
5451
5284
  let {
5452
5285
  fieldSchema,
5453
5286
  ...props
5454
- } = _ref18;
5287
+ } = _ref17;
5455
5288
  var _a;
5456
5289
  const [open, setOpen] = useState(!!((_a = props.value) == null ? void 0 : _a.length));
5457
5290
  const onExpand = useCallback(() => setOpen(true), []);
@@ -5499,11 +5332,11 @@ function useEmptySelectAllValue(value, allowedValues, onChange) {
5499
5332
  }
5500
5333
  }, [allowedValues, value, onChange]);
5501
5334
  }
5502
- function ObjectOutputInput(_ref19) {
5335
+ function ObjectOutputInput(_ref18) {
5503
5336
  let {
5504
5337
  fieldSchema,
5505
5338
  ...props
5506
- } = _ref19;
5339
+ } = _ref18;
5507
5340
  const {
5508
5341
  value,
5509
5342
  onChange
@@ -5550,11 +5383,11 @@ function ObjectOutputInput(_ref19) {
5550
5383
  })
5551
5384
  });
5552
5385
  }
5553
- function ArrayOutputInput(_ref20) {
5386
+ function ArrayOutputInput(_ref19) {
5554
5387
  let {
5555
5388
  fieldSchema,
5556
5389
  ...props
5557
- } = _ref20;
5390
+ } = _ref19;
5558
5391
  const {
5559
5392
  value,
5560
5393
  onChange
@@ -5575,58 +5408,225 @@ function ArrayOutputInput(_ref20) {
5575
5408
  }));
5576
5409
  onChange(PatchEvent.from([setIfMissing([]), insert(items, "after", [-1])]));
5577
5410
  }
5578
- } else {
5579
- const patchValue = {
5580
- _key: selectedValue,
5581
- _type: "sanity.assist.output.type",
5582
- type: selectedValue
5583
- };
5584
- onChange(PatchEvent.from([setIfMissing([]), insert([patchValue], "after", [-1])]));
5411
+ } else {
5412
+ const patchValue = {
5413
+ _key: selectedValue,
5414
+ _type: "sanity.assist.output.type",
5415
+ type: selectedValue
5416
+ };
5417
+ onChange(PatchEvent.from([setIfMissing([]), insert([patchValue], "after", [-1])]));
5418
+ }
5419
+ }, [onChange, value, ofItems]);
5420
+ return /* @__PURE__ */jsx(Stack, {
5421
+ space: 2,
5422
+ children: ofItems.map(itemType => {
5423
+ var _a;
5424
+ return /* @__PURE__ */jsx(Flex, {
5425
+ children: /* @__PURE__ */jsx(Selectable, {
5426
+ value: itemType.name,
5427
+ title: isType(itemType, "block") ? "Text" : (_a = itemType.title) != null ? _a : itemType.name,
5428
+ arrayValue: value,
5429
+ onChange: onSelectChange
5430
+ })
5431
+ }, itemType.name);
5432
+ })
5433
+ });
5434
+ }
5435
+ function Selectable(_ref20) {
5436
+ let {
5437
+ title,
5438
+ arrayValue,
5439
+ value,
5440
+ onChange
5441
+ } = _ref20;
5442
+ const checked = !(arrayValue == null ? void 0 : arrayValue.length) || !!(arrayValue == null ? void 0 : arrayValue.find(v => v._key === value));
5443
+ const handleChange = useCallback(() => onChange(checked, value), [onChange, checked, value]);
5444
+ return /* @__PURE__ */jsxs(Flex, {
5445
+ gap: 2,
5446
+ align: "flex-start",
5447
+ children: [/* @__PURE__ */jsx(Checkbox, {
5448
+ checked,
5449
+ onChange: handleChange
5450
+ }), /* @__PURE__ */jsx(Card, {
5451
+ marginTop: 1,
5452
+ onClick: handleChange,
5453
+ children: /* @__PURE__ */jsx(Text, {
5454
+ style: {
5455
+ cursor: "default"
5456
+ },
5457
+ size: 1,
5458
+ children: title
5459
+ })
5460
+ })]
5461
+ });
5462
+ }
5463
+
5464
+ // Strict ESM env, designed to run outside Node.js in envs that provide WebCrypto (deno, browsers, etc)
5465
+
5466
+ function getRandomValues(typedArray) {
5467
+ const crypto = typeof window !== 'undefined' && 'crypto' in window ? window.crypto : globalThis.crypto;
5468
+ if (!crypto || !crypto.getRandomValues) {
5469
+ throw new Error('WebCrypto not available in this environment');
5470
+ }
5471
+ return crypto.getRandomValues(typedArray);
5472
+ }
5473
+ function whatwgRNG() {
5474
+ let length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 16;
5475
+ const rnds8 = new Uint8Array(length);
5476
+ getRandomValues(rnds8);
5477
+ return rnds8;
5478
+ }
5479
+ const getByteHexTable = /* @__PURE__ */(() => {
5480
+ let table;
5481
+ return () => {
5482
+ if (table) {
5483
+ return table;
5484
+ }
5485
+ table = [];
5486
+ for (let i = 0; i < 256; ++i) {
5487
+ table[i] = (i + 256).toString(16).substring(1);
5488
+ }
5489
+ return table;
5490
+ };
5491
+ })();
5492
+ function randomKey(length) {
5493
+ const table = getByteHexTable();
5494
+ return whatwgRNG(length).reduce((str, n) => str + table[n], "").slice(0, length);
5495
+ }
5496
+ var __freeze = Object.freeze;
5497
+ var __defProp = Object.defineProperty;
5498
+ var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", {
5499
+ value: __freeze(raw || cooked.slice())
5500
+ }));
5501
+ var _a;
5502
+ 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"])));
5503
+ function PromptInput(props) {
5504
+ useOnlyInlineBlocks(props);
5505
+ return /* @__PURE__ */jsx(PteMods, {
5506
+ children: props.renderDefault(props)
5507
+ });
5508
+ }
5509
+ function useOnlyInlineBlocks(props) {
5510
+ useEffect(() => {
5511
+ var _a2;
5512
+ let needsFix = false;
5513
+ const val = ((_a2 = props.value) != null ? _a2 : []).map(block => {
5514
+ if (block._type === "block") {
5515
+ return block;
5516
+ }
5517
+ needsFix = true;
5518
+ return typed({
5519
+ _key: randomKey(12),
5520
+ _type: "block",
5521
+ level: 0,
5522
+ markDefs: [],
5523
+ style: "normal",
5524
+ children: [block]
5525
+ });
5526
+ });
5527
+ if (needsFix) {
5528
+ props.onChange(set(val));
5585
5529
  }
5586
- }, [onChange, value, ofItems]);
5587
- return /* @__PURE__ */jsx(Stack, {
5588
- space: 2,
5589
- children: ofItems.map(itemType => {
5590
- var _a;
5591
- return /* @__PURE__ */jsx(Flex, {
5592
- children: /* @__PURE__ */jsx(Selectable, {
5593
- value: itemType.name,
5594
- title: isType(itemType, "block") ? "Text" : (_a = itemType.title) != null ? _a : itemType.name,
5595
- arrayValue: value,
5596
- onChange: onSelectChange
5597
- })
5598
- }, itemType.name);
5599
- })
5530
+ }, []);
5531
+ }
5532
+ function InstructionsArrayField(props) {
5533
+ return props.renderDefault({
5534
+ ...props,
5535
+ title: " "
5600
5536
  });
5601
5537
  }
5602
- function Selectable(_ref21) {
5603
- let {
5604
- title,
5605
- arrayValue,
5538
+ function InstructionsArrayInput(props) {
5539
+ const user = useCurrentUser();
5540
+ const originalValue = props.value;
5541
+ const originalMembers = props.members;
5542
+ const value = useMemo(() => (originalValue != null ? originalValue : []).filter(v => !v.userId || v.userId === (user == null ? void 0 : user.id)), [originalValue, user]);
5543
+ const members = useMemo(() => (originalMembers != null ? originalMembers : []).filter(v => {
5544
+ var _a;
5545
+ if (v.kind === "error") {
5546
+ return true;
5547
+ }
5548
+ const value2 = (_a = v == null ? void 0 : v.item) == null ? void 0 : _a.value;
5549
+ return !value2.userId || value2.userId === (user == null ? void 0 : user.id);
5550
+ }), [originalMembers, user]);
5551
+ return props.renderDefault({
5552
+ ...props,
5606
5553
  value,
5607
- onChange
5608
- } = _ref21;
5609
- const checked = !(arrayValue == null ? void 0 : arrayValue.length) || !!(arrayValue == null ? void 0 : arrayValue.find(v => v._key === value));
5610
- const handleChange = useCallback(() => onChange(checked, value), [onChange, checked, value]);
5611
- return /* @__PURE__ */jsxs(Flex, {
5612
- gap: 2,
5613
- align: "flex-start",
5614
- children: [/* @__PURE__ */jsx(Checkbox, {
5615
- checked,
5616
- onChange: handleChange
5617
- }), /* @__PURE__ */jsx(Card, {
5618
- marginTop: 1,
5619
- onClick: handleChange,
5620
- children: /* @__PURE__ */jsx(Text, {
5621
- style: {
5622
- cursor: "default"
5623
- },
5624
- size: 1,
5625
- children: title
5626
- })
5627
- })]
5554
+ members
5555
+ });
5556
+ }
5557
+ function HideReferenceChangedBannerInput(props) {
5558
+ const ref = useRef(null);
5559
+ useEffect(() => {
5560
+ var _a;
5561
+ const parent = (_a = ref.current) == null ? void 0 : _a.closest('[data-testid="pane-content"]');
5562
+ if (!parent) {
5563
+ return;
5564
+ }
5565
+ const style = document.createElement("style");
5566
+ const parentId = "id-".concat(Math.random()).replace(".", "-");
5567
+ parent.id = parentId;
5568
+ style.innerText = "\n #".concat(parentId, ' [data-testid="reference-changed-banner"] { display: none; }\n ');
5569
+ parent.prepend(style);
5570
+ }, [ref]);
5571
+ return /* @__PURE__ */jsx(Box, {
5572
+ ref,
5573
+ children: props.renderDefault(props)
5628
5574
  });
5629
5575
  }
5576
+ const contextDocumentSchema = defineType({
5577
+ type: "document",
5578
+ name: contextDocumentTypeName,
5579
+ title: "AI context",
5580
+ liveEdit: true,
5581
+ icon: TokenIcon,
5582
+ components: {
5583
+ input: HideReferenceChangedBannerInput
5584
+ },
5585
+ fields: [defineField({
5586
+ type: "string",
5587
+ name: "title",
5588
+ title: "Title"
5589
+ }), defineField({
5590
+ name: "context",
5591
+ type: "array",
5592
+ title: "Context",
5593
+ of: [defineArrayMember({
5594
+ type: "block",
5595
+ styles: [{
5596
+ title: "Normal",
5597
+ value: "normal"
5598
+ }],
5599
+ lists: [],
5600
+ marks: {
5601
+ decorators: [],
5602
+ annotations: []
5603
+ }
5604
+ })]
5605
+ })],
5606
+ preview: {
5607
+ select: {
5608
+ title: "title",
5609
+ context: "context"
5610
+ },
5611
+ prepare(_ref21) {
5612
+ let {
5613
+ title,
5614
+ context
5615
+ } = _ref21;
5616
+ var _a;
5617
+ const text = context == null ? void 0 : context.flatMap(block => block == null ? void 0 : block.children).flatMap(child => {
5618
+ var _a2;
5619
+ return (_a2 = child == null ? void 0 : child.text) == null ? void 0 : _a2.split(" ");
5620
+ }).filter(Boolean);
5621
+ const words = (_a = text == null ? void 0 : text.length) != null ? _a : 0;
5622
+ return {
5623
+ title,
5624
+ subtitle: "Words: ".concat(words),
5625
+ media: DocumentTextIcon
5626
+ };
5627
+ }
5628
+ }
5629
+ });
5630
5630
  const fieldReference = defineType({
5631
5631
  type: "object",
5632
5632
  name: fieldReferenceTypeName,
@@ -6108,193 +6108,60 @@ function excludeComments(type) {
6108
6108
  }
6109
6109
  const instructionForm = [fieldInstructions, instruction, fieldReference, prompt, userInput, promptContext].map(excludeComments);
6110
6110
  const schemaTypes = [...instructionForm, outputFieldType, outputTypeType, assistDocumentSchema, documentInstructionStatus, instructionTask, contextDocumentSchema];
6111
- function useAssistSupported(path, schemaType) {
6112
- return useMemo(() => isAssistSupported(schemaType), [schemaType]);
6113
- }
6114
6111
  function useAssistDocumentContextValue(documentId, documentSchemaType) {
6115
6112
  const {
6116
6113
  published,
6117
6114
  draft
6118
6115
  } = useEditState(getPublishedId(documentId), documentSchemaType.name, "low");
6119
- const assistableDocumentId = (draft == null ? void 0 : draft._id) || (published == null ? void 0 : published._id) || documentId;
6120
- const documentIsNew = Boolean(!(draft == null ? void 0 : draft._id) && !(published == null ? void 0 : published._id));
6121
- const documentIsAssistable = isDocAssistable(documentSchemaType, published, draft);
6122
- const {
6123
- params
6124
- } = useAiPaneRouter();
6125
- const selectedPath = params[fieldPathParam];
6126
- const {
6127
- openInspector,
6128
- closeInspector,
6129
- inspector,
6130
- onChange: documentOnChange
6131
- } = useDocumentPane();
6132
- const assistDocument = useStudioAssistDocument({
6133
- documentId,
6134
- schemaType: documentSchemaType
6135
- });
6136
- const value = useMemo(() => {
6137
- const base = {
6138
- documentId,
6139
- assistableDocumentId,
6140
- documentSchemaType,
6141
- documentIsNew,
6142
- documentIsAssistable,
6143
- openInspector,
6144
- closeInspector,
6145
- inspector,
6146
- documentOnChange,
6147
- selectedPath
6148
- };
6149
- if (!assistDocument) {
6150
- return {
6151
- ...base,
6152
- loading: true,
6153
- assistDocument: void 0
6154
- };
6155
- }
6156
- return {
6157
- ...base,
6158
- loading: false,
6159
- assistDocument
6160
- };
6161
- }, [assistDocument, documentIsAssistable, documentId, assistableDocumentId, documentSchemaType, documentIsNew, openInspector, closeInspector, inspector, documentOnChange, selectedPath]);
6162
- return value;
6163
- }
6164
- function PrivateIcon() {
6165
- return /* @__PURE__ */jsx(Tooltip, {
6166
- content: /* @__PURE__ */jsx(Text, {
6167
- size: 1,
6168
- style: {
6169
- whiteSpace: "nowrap"
6170
- },
6171
- children: "Only visible to you"
6172
- }),
6173
- fallbackPlacements: ["bottom"],
6174
- padding: 2,
6175
- placement: "top",
6176
- portal: true,
6177
- children: /* @__PURE__ */jsx(LockIcon, {})
6178
- });
6179
- }
6180
- const ImageContext = createContext({});
6181
- function ImageContextProvider(props) {
6182
- var _a, _b;
6183
- const {
6184
- schemaType,
6185
- path,
6186
- value,
6187
- readOnly
6188
- } = props;
6189
- const assetRef = (_a = value == null ? void 0 : value.asset) == null ? void 0 : _a._ref;
6190
- const [assetRefState, setAssetRefState] = useState(assetRef);
6191
- const {
6192
- documentId,
6193
- documentSchemaType
6194
- } = useAssistDocumentContext();
6195
- const {
6196
- config,
6197
- status
6198
- } = useAiAssistanceConfig();
6199
- const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
6200
- const {
6201
- generateCaption
6202
- } = useGenerateCaption(apiClient);
6203
- const {
6204
- isSyncing
6205
- } = useSyncState(publicId(documentId), documentSchemaType.name);
6206
- const router = usePaneRouter();
6207
- const isShowingOlderRevision = !!((_b = router.params) == null ? void 0 : _b.rev);
6208
- useEffect(() => {
6209
- const descriptionField = getDescriptionFieldOption(schemaType);
6210
- if (assetRef && documentId && descriptionField && assetRef !== assetRefState && !isSyncing && !isShowingOlderRevision && !readOnly) {
6211
- setAssetRefState(assetRef);
6212
- if (canUseAssist(status)) {
6213
- generateCaption({
6214
- path: pathToString([...path, descriptionField]),
6215
- documentId
6216
- });
6217
- }
6116
+ const assistableDocumentId = (draft == null ? void 0 : draft._id) || (published == null ? void 0 : published._id) || documentId;
6117
+ const documentIsNew = Boolean(!(draft == null ? void 0 : draft._id) && !(published == null ? void 0 : published._id));
6118
+ const documentIsAssistable = isDocAssistable(documentSchemaType, published, draft);
6119
+ const {
6120
+ params
6121
+ } = useAiPaneRouter();
6122
+ const selectedPath = params[fieldPathParam];
6123
+ const {
6124
+ openInspector,
6125
+ closeInspector,
6126
+ inspector,
6127
+ onChange: documentOnChange
6128
+ } = useDocumentPane();
6129
+ const assistDocument = useStudioAssistDocument({
6130
+ documentId,
6131
+ schemaType: documentSchemaType
6132
+ });
6133
+ const value = useMemo(() => {
6134
+ const base = {
6135
+ documentId,
6136
+ assistableDocumentId,
6137
+ documentSchemaType,
6138
+ documentIsNew,
6139
+ documentIsAssistable,
6140
+ openInspector,
6141
+ closeInspector,
6142
+ inspector,
6143
+ documentOnChange,
6144
+ selectedPath
6145
+ };
6146
+ if (!assistDocument) {
6147
+ return {
6148
+ ...base,
6149
+ loading: true,
6150
+ assistDocument: void 0
6151
+ };
6218
6152
  }
6219
- }, [schemaType, path, assetRef, assetRefState, documentId, generateCaption, isSyncing, status, readOnly, isShowingOlderRevision]);
6220
- const context = useMemo(() => {
6221
- const descriptionField = getDescriptionFieldOption(schemaType);
6222
- const imageInstructionField = getImageInstructionFieldOption(schemaType);
6223
6153
  return {
6224
- imageDescriptionPath: descriptionField ? pathToString([...path, descriptionField]) : void 0,
6225
- imageInstructionPath: imageInstructionField ? pathToString([...path, imageInstructionField]) : void 0,
6226
- assetRef
6154
+ ...base,
6155
+ loading: false,
6156
+ assistDocument
6227
6157
  };
6228
- }, [schemaType, path, assetRef]);
6229
- return /* @__PURE__ */jsx(ImageContext.Provider, {
6230
- value: context,
6231
- children: props.renderDefault(props)
6232
- });
6158
+ }, [assistDocument, documentIsAssistable, documentId, assistableDocumentId, documentSchemaType, documentIsNew, openInspector, closeInspector, inspector, documentOnChange, selectedPath]);
6159
+ return value;
6233
6160
  }
6234
- function node$3(node2) {
6235
- return node2;
6161
+ function useAssistSupported(path, schemaType) {
6162
+ return useMemo(() => isAssistSupported(schemaType), [schemaType]);
6236
6163
  }
6237
- const generateCaptionsActions = {
6238
- name: "sanity-assist-generate-captions",
6239
- useAction(props) {
6240
- const pathKey = usePathKey(props.path);
6241
- const {
6242
- openInspector
6243
- } = useDocumentPane();
6244
- const {
6245
- config,
6246
- status
6247
- } = useAiAssistanceConfig();
6248
- const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
6249
- const {
6250
- generateCaption,
6251
- loading
6252
- } = useGenerateCaption(apiClient);
6253
- const imageContext = useContext(ImageContext);
6254
- if (imageContext && pathKey === (imageContext == null ? void 0 : imageContext.imageDescriptionPath)) {
6255
- const {
6256
- documentId
6257
- } = useAssistDocumentContext();
6258
- return useMemo(() => {
6259
- return node$3({
6260
- type: "action",
6261
- icon: loading ? () => /* @__PURE__ */jsx(Box, {
6262
- style: {
6263
- height: 17
6264
- },
6265
- children: /* @__PURE__ */jsx(Spinner, {
6266
- style: {
6267
- transform: "translateY(6px)"
6268
- }
6269
- })
6270
- }) : ImageIcon,
6271
- title: "Generate image description",
6272
- onAction: () => {
6273
- if (loading) {
6274
- return;
6275
- }
6276
- if (!canUseAssist(status)) {
6277
- openInspector(aiInspectorId, {
6278
- [fieldPathParam]: pathKey,
6279
- [instructionParam]: void 0
6280
- });
6281
- return;
6282
- }
6283
- generateCaption({
6284
- path: pathKey,
6285
- documentId: documentId != null ? documentId : ""
6286
- });
6287
- },
6288
- renderAsButton: true,
6289
- disabled: loading,
6290
- hidden: !imageContext.assetRef
6291
- });
6292
- }, [generateCaption, pathKey, documentId, loading, imageContext, status, openInspector]);
6293
- }
6294
- return void 0;
6295
- }
6296
- };
6297
- function node$2(node2) {
6164
+ function node$3(node2) {
6298
6165
  return node2;
6299
6166
  }
6300
6167
  const translateActions = {
@@ -6342,7 +6209,7 @@ const translateActions = {
6342
6209
  return void 0;
6343
6210
  }
6344
6211
  const title = path.length ? "Translate" : "Translate document";
6345
- return node$2({
6212
+ return node$3({
6346
6213
  type: "action",
6347
6214
  icon: translationApi.loading ? () => /* @__PURE__ */jsx(Box, {
6348
6215
  style: {
@@ -6376,7 +6243,7 @@ const translateActions = {
6376
6243
  isDocAssistable: documentIsAssistable != null ? documentIsAssistable : false,
6377
6244
  task: fieldTranslate.openFieldTranslation
6378
6245
  });
6379
- const translateFieldsAction = useMemo(() => fieldTransEnabled ? node$2({
6246
+ const translateFieldsAction = useMemo(() => fieldTransEnabled ? node$3({
6380
6247
  type: "action",
6381
6248
  icon: fieldTranslate.translationLoading ? () => /* @__PURE__ */jsx(Box, {
6382
6249
  style: {
@@ -6410,7 +6277,7 @@ const translateActions = {
6410
6277
  if (!(status == null ? void 0 : status.initialized)) {
6411
6278
  return void 0;
6412
6279
  }
6413
- return node$2({
6280
+ return node$3({
6414
6281
  type: "group",
6415
6282
  icon: () => null,
6416
6283
  title: "Translation",
@@ -6422,6 +6289,123 @@ const translateActions = {
6422
6289
  return void 0;
6423
6290
  }
6424
6291
  };
6292
+ const ImageContext = createContext({});
6293
+ function ImageContextProvider(props) {
6294
+ var _a, _b;
6295
+ const {
6296
+ schemaType,
6297
+ path,
6298
+ value,
6299
+ readOnly
6300
+ } = props;
6301
+ const assetRef = (_a = value == null ? void 0 : value.asset) == null ? void 0 : _a._ref;
6302
+ const [assetRefState, setAssetRefState] = useState(assetRef);
6303
+ const {
6304
+ documentId,
6305
+ documentSchemaType
6306
+ } = useAssistDocumentContext();
6307
+ const {
6308
+ config,
6309
+ status
6310
+ } = useAiAssistanceConfig();
6311
+ const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
6312
+ const {
6313
+ generateCaption
6314
+ } = useGenerateCaption(apiClient);
6315
+ const {
6316
+ isSyncing
6317
+ } = useSyncState(publicId(documentId), documentSchemaType.name);
6318
+ const router = usePaneRouter();
6319
+ const isShowingOlderRevision = !!((_b = router.params) == null ? void 0 : _b.rev);
6320
+ useEffect(() => {
6321
+ const descriptionField = getDescriptionFieldOption(schemaType);
6322
+ if (assetRef && documentId && descriptionField && assetRef !== assetRefState && !isSyncing && !isShowingOlderRevision && !readOnly) {
6323
+ setAssetRefState(assetRef);
6324
+ if (canUseAssist(status)) {
6325
+ generateCaption({
6326
+ path: pathToString([...path, descriptionField]),
6327
+ documentId
6328
+ });
6329
+ }
6330
+ }
6331
+ }, [schemaType, path, assetRef, assetRefState, documentId, generateCaption, isSyncing, status, readOnly, isShowingOlderRevision]);
6332
+ const context = useMemo(() => {
6333
+ const descriptionField = getDescriptionFieldOption(schemaType);
6334
+ const imageInstructionField = getImageInstructionFieldOption(schemaType);
6335
+ return {
6336
+ imageDescriptionPath: descriptionField ? pathToString([...path, descriptionField]) : void 0,
6337
+ imageInstructionPath: imageInstructionField ? pathToString([...path, imageInstructionField]) : void 0,
6338
+ assetRef
6339
+ };
6340
+ }, [schemaType, path, assetRef]);
6341
+ return /* @__PURE__ */jsx(ImageContext.Provider, {
6342
+ value: context,
6343
+ children: props.renderDefault(props)
6344
+ });
6345
+ }
6346
+ function node$2(node2) {
6347
+ return node2;
6348
+ }
6349
+ const generateCaptionsActions = {
6350
+ name: "sanity-assist-generate-captions",
6351
+ useAction(props) {
6352
+ const pathKey = usePathKey(props.path);
6353
+ const {
6354
+ openInspector
6355
+ } = useDocumentPane();
6356
+ const {
6357
+ config,
6358
+ status
6359
+ } = useAiAssistanceConfig();
6360
+ const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
6361
+ const {
6362
+ generateCaption,
6363
+ loading
6364
+ } = useGenerateCaption(apiClient);
6365
+ const imageContext = useContext(ImageContext);
6366
+ if (imageContext && pathKey === (imageContext == null ? void 0 : imageContext.imageDescriptionPath)) {
6367
+ const {
6368
+ documentId
6369
+ } = useAssistDocumentContext();
6370
+ return useMemo(() => {
6371
+ return node$2({
6372
+ type: "action",
6373
+ icon: loading ? () => /* @__PURE__ */jsx(Box, {
6374
+ style: {
6375
+ height: 17
6376
+ },
6377
+ children: /* @__PURE__ */jsx(Spinner, {
6378
+ style: {
6379
+ transform: "translateY(6px)"
6380
+ }
6381
+ })
6382
+ }) : ImageIcon,
6383
+ title: "Generate image description",
6384
+ onAction: () => {
6385
+ if (loading) {
6386
+ return;
6387
+ }
6388
+ if (!canUseAssist(status)) {
6389
+ openInspector(aiInspectorId, {
6390
+ [fieldPathParam]: pathKey,
6391
+ [instructionParam]: void 0
6392
+ });
6393
+ return;
6394
+ }
6395
+ generateCaption({
6396
+ path: pathKey,
6397
+ documentId: documentId != null ? documentId : ""
6398
+ });
6399
+ },
6400
+ renderAsButton: true,
6401
+ disabled: loading,
6402
+ hidden: !imageContext.assetRef
6403
+ });
6404
+ }, [generateCaption, pathKey, documentId, loading, imageContext, status, openInspector]);
6405
+ }
6406
+ return void 0;
6407
+ }
6408
+ };
6425
6409
  function node$1(node2) {
6426
6410
  return node2;
6427
6411
  }
@@ -6473,6 +6457,22 @@ const generateImagActions = {
6473
6457
  return void 0;
6474
6458
  }
6475
6459
  };
6460
+ function PrivateIcon() {
6461
+ return /* @__PURE__ */jsx(Tooltip, {
6462
+ content: /* @__PURE__ */jsx(Text, {
6463
+ size: 1,
6464
+ style: {
6465
+ whiteSpace: "nowrap"
6466
+ },
6467
+ children: "Only visible to you"
6468
+ }),
6469
+ fallbackPlacements: ["bottom"],
6470
+ padding: 2,
6471
+ placement: "top",
6472
+ portal: true,
6473
+ children: /* @__PURE__ */jsx(LockIcon, {})
6474
+ });
6475
+ }
6476
6476
  function node(node2) {
6477
6477
  return node2;
6478
6478
  }
@@ -6570,14 +6570,14 @@ const assistFieldActions = {
6570
6570
  type: "group",
6571
6571
  icon: () => null,
6572
6572
  title: "Run instructions",
6573
- children: [...(instructions == null ? void 0 : instructions.map(instruction => instructionItem({
6573
+ children: [...((instructions == null ? void 0 : instructions.map(instruction => instructionItem({
6574
6574
  instruction,
6575
6575
  isPrivate: Boolean(instruction.userId && instruction.userId === (currentUser == null ? void 0 : currentUser.id)),
6576
6576
  onInstructionAction,
6577
6577
  hidden: isHidden,
6578
6578
  documentIsNew: !!documentIsNew,
6579
6579
  assistSupported
6580
- }))), imageCaptionAction, imageGenAction].filter(a => !!a),
6580
+ }))) || []), imageCaptionAction, imageGenAction].filter(a => !!a),
6581
6581
  expanded: true
6582
6582
  }) : void 0;
6583
6583
  }, [instructions, currentUser == null ? void 0 : currentUser.id, onInstructionAction, isHidden, documentIsNew, assistSupported, imageCaptionAction, translateAction, imageGenAction]);