@sanity/assist 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  import {JSX as JSX_2} from 'react/jsx-runtime'
2
2
  import {Path} from 'sanity'
3
3
  import {Plugin as Plugin_2} from 'sanity'
4
+ import {PortableTextBlock} from '@portabletext/types'
5
+ import {PortableTextMarkDefinition} from '@portabletext/types'
6
+ import {PortableTextSpan} from '@portabletext/types'
4
7
  import {SanityClient} from 'sanity'
5
8
  import {SanityClient as SanityClient_2} from '@sanity/client'
6
9
  import {SchemaType} from 'sanity'
@@ -25,6 +28,22 @@ declare interface AssistPluginConfig {
25
28
  * @internal
26
29
  */
27
30
  __customApiClient?: (defaultClient: SanityClient_2) => SanityClient_2
31
+ /**
32
+ * @internal
33
+ */
34
+ __presets?: Record<string, AssistPreset>
35
+ }
36
+
37
+ declare interface AssistPreset {
38
+ fields?: PresetField[]
39
+ }
40
+
41
+ declare interface ContextBlock {
42
+ _type: typeof instructionContextTypeName
43
+ reference?: {
44
+ _type: 'reference'
45
+ _ref?: string
46
+ }
28
47
  }
29
48
 
30
49
  export declare const contextDocumentTypeName: 'assist.instruction.context'
@@ -65,6 +84,13 @@ export declare interface DocumentTranslationConfig {
65
84
  documentTypes?: string[]
66
85
  }
67
86
 
87
+ declare interface FieldRef extends PortableTextMarkDefinition {
88
+ _type: typeof fieldReferenceTypeName
89
+ path?: string
90
+ }
91
+
92
+ declare const fieldReferenceTypeName: 'sanity.assist.instruction.fieldRef'
93
+
68
94
  export declare interface FieldTranslationConfig {
69
95
  /**
70
96
  * `documentTypes` should be an array of strings where each entry must match a name from your document schemas.
@@ -156,6 +182,10 @@ export declare interface FieldTranslationConfig {
156
182
  translationOutputs?: TranslationOutputsFunction
157
183
  }
158
184
 
185
+ declare type InlinePromptBlock = PortableTextSpan | FieldRef | UserInputBlock | ContextBlock
186
+
187
+ declare const instructionContextTypeName: 'sanity.assist.instruction.context'
188
+
159
189
  export declare interface Language {
160
190
  id: string
161
191
  title?: string
@@ -166,6 +196,49 @@ export declare type LanguageCallback = (
166
196
  selectedLanguageParams: Record<string, unknown>,
167
197
  ) => Promise<Language[]>
168
198
 
199
+ declare interface OutputFieldItem {
200
+ _type: typeof outputFieldTypeName
201
+ _key: string
202
+ relativePath?: string
203
+ }
204
+
205
+ declare const outputFieldTypeName: 'sanity.assist.output.field'
206
+
207
+ declare interface OutputTypeItem {
208
+ _type: typeof outputTypeTypeName
209
+ _key: string
210
+ type?: string
211
+ relativePath?: string
212
+ }
213
+
214
+ declare const outputTypeTypeName: 'sanity.assist.output.type'
215
+
216
+ declare interface PresetField {
217
+ path?: string
218
+ instructions?: PresetInstruction[]
219
+ }
220
+
221
+ declare interface PresetInstruction {
222
+ _key: string
223
+ prompt?: PromptTextBlock[]
224
+ title?: string
225
+ /**
226
+ * String key from @sanity/icons IconMap
227
+ */
228
+ icon?: string
229
+ /**
230
+ * Type/field filter
231
+ */
232
+ output?: (OutputFieldItem | OutputTypeItem)[]
233
+ }
234
+
235
+ declare type PromptTextBlock = Omit<
236
+ PortableTextBlock<never, InlinePromptBlock, 'normal', never>,
237
+ '_type'
238
+ > & {
239
+ _type: 'block'
240
+ }
241
+
169
242
  export declare function SchemaTypeTool(): JSX_2.Element
170
243
 
171
244
  export declare interface TranslationConfig {
@@ -192,6 +265,15 @@ export declare type TranslationOutputsFunction = (
192
265
  translateToLanguageIds: string[],
193
266
  ) => TranslationOutput[] | undefined
194
267
 
268
+ declare interface UserInputBlock {
269
+ _type: typeof userInputTypeName
270
+ _key: string
271
+ message?: string
272
+ description?: string
273
+ }
274
+
275
+ declare const userInputTypeName: 'sanity.assist.instruction.userInput'
276
+
195
277
  export {}
196
278
 
197
279
  declare module 'sanity' {
package/dist/index.esm.js CHANGED
@@ -885,12 +885,15 @@ function TimeAgo(_ref3) {
885
885
  }
886
886
  function usePathKey(path) {
887
887
  return useMemo(() => {
888
- if (path.length) {
889
- return Array.isArray(path) ? pathToString(path) : path;
890
- }
891
- return documentRootKey;
888
+ return getPathKey(path);
892
889
  }, [path]);
893
890
  }
891
+ function getPathKey(path) {
892
+ if (path.length) {
893
+ return Array.isArray(path) ? pathToString(path) : path;
894
+ }
895
+ return documentRootKey;
896
+ }
894
897
  function getInstructionTitle(instruction) {
895
898
  var _a;
896
899
  return (_a = instruction == null ? void 0 : instruction.title) != null ? _a : "Untitled";
@@ -1099,6 +1102,9 @@ function TaskItem(props) {
1099
1102
  });
1100
1103
  }
1101
1104
  const basePath = "/assist/tasks/instruction";
1105
+ function canUseAssist(status) {
1106
+ return (status == null ? void 0 : status.enabled) && status.initialized && status.validToken;
1107
+ }
1102
1108
  function useApiClient(customApiClient) {
1103
1109
  const client = useClient({
1104
1110
  apiVersion: "2023-06-05"
@@ -1757,7 +1763,6 @@ function AssistDocumentFormEditable(props) {
1757
1763
  onChange(set((_a = documentSchema.title) != null ? _a : documentSchema.name, ["title"]));
1758
1764
  }
1759
1765
  }, [title, documentSchema, onChange, id]);
1760
- const fieldExists = !!(fields == null ? void 0 : fields.some(f => f._key === typePath));
1761
1766
  const {
1762
1767
  onPathOpen,
1763
1768
  ...formCallbacks
@@ -1789,7 +1794,8 @@ function AssistDocumentFormEditable(props) {
1789
1794
  children: [/* @__PURE__ */jsx(FieldsInitializer, {
1790
1795
  pathKey: typePath,
1791
1796
  activePath,
1792
- fieldExists,
1797
+ fields,
1798
+ documentSchema,
1793
1799
  onChange
1794
1800
  }, typePath), instruction && /* @__PURE__ */jsx(BackToInstructionListLink, {}), activePath && /* @__PURE__ */jsx(FormCallbacksProvider, {
1795
1801
  ...newCallbacks,
@@ -1837,21 +1843,60 @@ function FieldsInitializer(_ref9) {
1837
1843
  let {
1838
1844
  pathKey,
1839
1845
  activePath,
1840
- fieldExists,
1846
+ fields,
1847
+ documentSchema,
1841
1848
  onChange
1842
1849
  } = _ref9;
1850
+ const {
1851
+ config: {
1852
+ __presets: presets
1853
+ }
1854
+ } = useAiAssistanceConfig();
1855
+ const existingField = fields == null ? void 0 : fields.find(f => f._key === pathKey);
1856
+ const documentPresets = !!(documentSchema == null ? void 0 : documentSchema.name) && (presets == null ? void 0 : presets[documentSchema == null ? void 0 : documentSchema.name]);
1857
+ const missingPresetInstructions = useMemo(() => {
1858
+ var _a, _b;
1859
+ if (!documentPresets || !pathKey) {
1860
+ return void 0;
1861
+ }
1862
+ const existingInstructions = existingField == null ? void 0 : existingField.instructions;
1863
+ const presetField = (_a = documentPresets.fields) == null ? void 0 : _a.find(f => f.path === pathKey);
1864
+ return (_b = presetField == null ? void 0 : presetField.instructions) == null ? void 0 : _b.filter(i => !(existingInstructions == null ? void 0 : existingInstructions.some(ei => ei._key === i._key)));
1865
+ }, [documentPresets, pathKey, existingField]);
1843
1866
  const initialized = useRef(false);
1844
1867
  useEffect(() => {
1845
- if (initialized.current || fieldExists || activePath || !pathKey) {
1868
+ if (initialized.current || !pathKey) {
1846
1869
  return;
1847
1870
  }
1848
- onChange([setIfMissing([], ["fields"]), insert([typed({
1849
- _key: pathKey,
1850
- _type: assistFieldTypeName,
1851
- path: pathKey
1852
- })], "after", ["fields", -1])]);
1871
+ if (existingField && !(missingPresetInstructions == null ? void 0 : missingPresetInstructions.length)) {
1872
+ return;
1873
+ }
1874
+ let event = PatchEvent.from([setIfMissing([], ["fields"])]);
1875
+ if (!existingField) {
1876
+ event = event.append(insert([typed({
1877
+ _key: pathKey,
1878
+ _type: assistFieldTypeName,
1879
+ path: pathKey
1880
+ })], "after", ["fields", -1]));
1881
+ }
1882
+ if (missingPresetInstructions == null ? void 0 : missingPresetInstructions.length) {
1883
+ event = event.append(insert(missingPresetInstructions.map(preset => {
1884
+ var _a;
1885
+ return {
1886
+ ...preset,
1887
+ _type: "sanity.assist.instruction",
1888
+ prompt: (_a = preset.prompt) == null ? void 0 : _a.map(p => ({
1889
+ markDefs: [],
1890
+ ...p
1891
+ }))
1892
+ };
1893
+ }), "after", ["fields", {
1894
+ _key: pathKey
1895
+ }, "instructions", -1]));
1896
+ }
1897
+ onChange(event);
1853
1898
  initialized.current = true;
1854
- }, [activePath, onChange, pathKey, fieldExists]);
1899
+ }, [activePath, onChange, pathKey, existingField, missingPresetInstructions]);
1855
1900
  return null;
1856
1901
  }
1857
1902
  function FieldAutocomplete(props) {
@@ -5310,7 +5355,11 @@ const contextDocumentSchema = defineType({
5310
5355
  // Strict ESM env, designed to run outside Node.js in envs that provide WebCrypto (deno, browsers, etc)
5311
5356
 
5312
5357
  function getRandomValues(typedArray) {
5313
- return window.crypto.getRandomValues(typedArray);
5358
+ const crypto = typeof window !== 'undefined' && 'crypto' in window ? window.crypto : globalThis.crypto;
5359
+ if (!crypto || !crypto.getRandomValues) {
5360
+ throw new Error('WebCrypto not available in this environment');
5361
+ }
5362
+ return crypto.getRandomValues(typedArray);
5314
5363
  }
5315
5364
  function whatwgRNG() {
5316
5365
  let length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 16;
@@ -5318,7 +5367,7 @@ function whatwgRNG() {
5318
5367
  getRandomValues(rnds8);
5319
5368
  return rnds8;
5320
5369
  }
5321
- const getByteHexTable = (() => {
5370
+ const getByteHexTable = /* @__PURE__ */(() => {
5322
5371
  let table;
5323
5372
  return () => {
5324
5373
  if (table) {
@@ -6130,7 +6179,8 @@ function ImageContextProvider(props) {
6130
6179
  documentSchemaType
6131
6180
  } = useAssistDocumentContext();
6132
6181
  const {
6133
- config
6182
+ config,
6183
+ status
6134
6184
  } = useAiAssistanceConfig();
6135
6185
  const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
6136
6186
  const {
@@ -6141,14 +6191,14 @@ function ImageContextProvider(props) {
6141
6191
  } = useSyncState(publicId(documentId), documentSchemaType.name);
6142
6192
  useEffect(() => {
6143
6193
  const descriptionField = getDescriptionFieldOption(schemaType);
6144
- if (assetRef && documentId && descriptionField && assetRef !== assetRefState && !isSyncing) {
6194
+ if (assetRef && documentId && descriptionField && assetRef !== assetRefState && !isSyncing && canUseAssist(status)) {
6145
6195
  setAssetRefState(assetRef);
6146
6196
  generateCaption({
6147
6197
  path: pathToString([...path, descriptionField]),
6148
6198
  documentId
6149
6199
  });
6150
6200
  }
6151
- }, [schemaType, path, assetRef, assetRefState, documentId, generateCaption, isSyncing]);
6201
+ }, [schemaType, path, assetRef, assetRefState, documentId, generateCaption, isSyncing, status]);
6152
6202
  const context = useMemo(() => {
6153
6203
  const descriptionField = getDescriptionFieldOption(schemaType);
6154
6204
  const imageInstructionField = getImageInstructionFieldOption(schemaType);
@@ -6171,7 +6221,11 @@ const generateCaptionsActions = {
6171
6221
  useAction(props) {
6172
6222
  const pathKey = usePathKey(props.path);
6173
6223
  const {
6174
- config
6224
+ openInspector
6225
+ } = useDocumentPane();
6226
+ const {
6227
+ config,
6228
+ status
6175
6229
  } = useAiAssistanceConfig();
6176
6230
  const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
6177
6231
  const {
@@ -6201,6 +6255,13 @@ const generateCaptionsActions = {
6201
6255
  if (loading) {
6202
6256
  return;
6203
6257
  }
6258
+ if (!canUseAssist(status)) {
6259
+ openInspector(aiInspectorId, {
6260
+ [fieldPathParam]: pathKey,
6261
+ [instructionParam]: void 0
6262
+ });
6263
+ return;
6264
+ }
6204
6265
  generateCaption({
6205
6266
  path: pathKey,
6206
6267
  documentId: documentId != null ? documentId : ""
@@ -6210,7 +6271,7 @@ const generateCaptionsActions = {
6210
6271
  disabled: loading,
6211
6272
  hidden: !imageContext.assetRef
6212
6273
  });
6213
- }, [generateCaption, pathKey, documentId, loading, imageContext]);
6274
+ }, [generateCaption, pathKey, documentId, loading, imageContext, status, openInspector]);
6214
6275
  }
6215
6276
  return void 0;
6216
6277
  }