@sanity/assist 2.0.0 → 2.0.2

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,67 @@ 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
+ var _a;
1869
+ if (initialized.current || !pathKey) {
1870
+ return;
1871
+ }
1872
+ if (existingField && !(missingPresetInstructions == null ? void 0 : missingPresetInstructions.length)) {
1846
1873
  return;
1847
1874
  }
1848
- onChange([setIfMissing([], ["fields"]), insert([typed({
1849
- _key: pathKey,
1850
- _type: assistFieldTypeName,
1851
- path: pathKey
1852
- })], "after", ["fields", -1])]);
1875
+ let event = PatchEvent.from([setIfMissing([], ["fields"])]);
1876
+ if (!existingField) {
1877
+ event = event.append(insert([typed({
1878
+ _key: pathKey,
1879
+ _type: assistFieldTypeName,
1880
+ path: pathKey,
1881
+ instructions: []
1882
+ })], "after", ["fields", -1]));
1883
+ }
1884
+ if (!((_a = existingField == null ? void 0 : existingField.instructions) == null ? void 0 : _a.length)) {
1885
+ event = event.append([setIfMissing([], ["fields", {
1886
+ _key: pathKey
1887
+ }, "instructions"])]);
1888
+ }
1889
+ if (missingPresetInstructions == null ? void 0 : missingPresetInstructions.length) {
1890
+ event = event.append(insert(missingPresetInstructions.map(preset => {
1891
+ var _a2;
1892
+ return {
1893
+ ...preset,
1894
+ _type: "sanity.assist.instruction",
1895
+ prompt: (_a2 = preset.prompt) == null ? void 0 : _a2.map(p => ({
1896
+ markDefs: [],
1897
+ ...p
1898
+ }))
1899
+ };
1900
+ }), "after", ["fields", {
1901
+ _key: pathKey
1902
+ }, "instructions", -1]));
1903
+ }
1904
+ onChange(event);
1853
1905
  initialized.current = true;
1854
- }, [activePath, onChange, pathKey, fieldExists]);
1906
+ }, [activePath, onChange, pathKey, existingField, missingPresetInstructions]);
1855
1907
  return null;
1856
1908
  }
1857
1909
  function FieldAutocomplete(props) {
@@ -5310,7 +5362,11 @@ const contextDocumentSchema = defineType({
5310
5362
  // Strict ESM env, designed to run outside Node.js in envs that provide WebCrypto (deno, browsers, etc)
5311
5363
 
5312
5364
  function getRandomValues(typedArray) {
5313
- return window.crypto.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);
5314
5370
  }
5315
5371
  function whatwgRNG() {
5316
5372
  let length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 16;
@@ -5318,7 +5374,7 @@ function whatwgRNG() {
5318
5374
  getRandomValues(rnds8);
5319
5375
  return rnds8;
5320
5376
  }
5321
- const getByteHexTable = (() => {
5377
+ const getByteHexTable = /* @__PURE__ */(() => {
5322
5378
  let table;
5323
5379
  return () => {
5324
5380
  if (table) {
@@ -6130,7 +6186,8 @@ function ImageContextProvider(props) {
6130
6186
  documentSchemaType
6131
6187
  } = useAssistDocumentContext();
6132
6188
  const {
6133
- config
6189
+ config,
6190
+ status
6134
6191
  } = useAiAssistanceConfig();
6135
6192
  const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
6136
6193
  const {
@@ -6143,12 +6200,14 @@ function ImageContextProvider(props) {
6143
6200
  const descriptionField = getDescriptionFieldOption(schemaType);
6144
6201
  if (assetRef && documentId && descriptionField && assetRef !== assetRefState && !isSyncing) {
6145
6202
  setAssetRefState(assetRef);
6146
- generateCaption({
6147
- path: pathToString([...path, descriptionField]),
6148
- documentId
6149
- });
6203
+ if (canUseAssist(status)) {
6204
+ generateCaption({
6205
+ path: pathToString([...path, descriptionField]),
6206
+ documentId
6207
+ });
6208
+ }
6150
6209
  }
6151
- }, [schemaType, path, assetRef, assetRefState, documentId, generateCaption, isSyncing]);
6210
+ }, [schemaType, path, assetRef, assetRefState, documentId, generateCaption, isSyncing, status]);
6152
6211
  const context = useMemo(() => {
6153
6212
  const descriptionField = getDescriptionFieldOption(schemaType);
6154
6213
  const imageInstructionField = getImageInstructionFieldOption(schemaType);
@@ -6171,7 +6230,11 @@ const generateCaptionsActions = {
6171
6230
  useAction(props) {
6172
6231
  const pathKey = usePathKey(props.path);
6173
6232
  const {
6174
- config
6233
+ openInspector
6234
+ } = useDocumentPane();
6235
+ const {
6236
+ config,
6237
+ status
6175
6238
  } = useAiAssistanceConfig();
6176
6239
  const apiClient = useApiClient(config == null ? void 0 : config.__customApiClient);
6177
6240
  const {
@@ -6201,6 +6264,13 @@ const generateCaptionsActions = {
6201
6264
  if (loading) {
6202
6265
  return;
6203
6266
  }
6267
+ if (!canUseAssist(status)) {
6268
+ openInspector(aiInspectorId, {
6269
+ [fieldPathParam]: pathKey,
6270
+ [instructionParam]: void 0
6271
+ });
6272
+ return;
6273
+ }
6204
6274
  generateCaption({
6205
6275
  path: pathKey,
6206
6276
  documentId: documentId != null ? documentId : ""
@@ -6210,7 +6280,7 @@ const generateCaptionsActions = {
6210
6280
  disabled: loading,
6211
6281
  hidden: !imageContext.assetRef
6212
6282
  });
6213
- }, [generateCaption, pathKey, documentId, loading, imageContext]);
6283
+ }, [generateCaption, pathKey, documentId, loading, imageContext, status, openInspector]);
6214
6284
  }
6215
6285
  return void 0;
6216
6286
  }