@sanity/assist 3.2.2 → 4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/assist",
3
- "version": "3.2.2",
3
+ "version": "4.0.1",
4
4
  "description": "You create the instructions; Sanity AI Assist does the rest.",
5
5
  "keywords": [
6
6
  "sanity",
@@ -65,7 +65,7 @@
65
65
  "@rollup/plugin-image": "^3.0.3",
66
66
  "@sanity/pkg-utils": "^6.1.0",
67
67
  "@sanity/plugin-kit": "^3.1.10",
68
- "@sanity/schema": "^3.80.0",
68
+ "@sanity/schema": "^3.81.0",
69
69
  "@sanity/semantic-release-preset": "^4.1.7",
70
70
  "@types/lodash": "^4.17.0",
71
71
  "@types/lodash-es": "^4.17.12",
@@ -83,9 +83,9 @@
83
83
  "react": "^18.2.0",
84
84
  "react-dom": "^18.2.0",
85
85
  "rimraf": "^5.0.5",
86
- "sanity": "^3.80.0",
86
+ "sanity": "^3.81.0",
87
87
  "semantic-release": "^23.0.8",
88
- "styled-components": "^6.1.8",
88
+ "styled-components": "^6.1.16",
89
89
  "typescript": "^5.7.2",
90
90
  "vitest": "^1.4.0"
91
91
  },
@@ -33,14 +33,11 @@ export function useAssistDocumentContextValue(documentId: string, documentType:
33
33
  // @ts-ignore this is a valid option available in `corel` - Remove after corel is merged to next
34
34
  const {draft, published, version} = editState || {}
35
35
 
36
- let assistableDocumentId = version?._id || draft?._id || published?._id
37
- if (!assistableDocumentId) {
38
- assistableDocumentId = selectedReleaseId
39
- ? getVersionId(documentId, selectedReleaseId)
40
- : documentSchemaType.liveEdit
41
- ? documentId
42
- : getDraftId(documentId)
43
- }
36
+ const assistableDocumentId = selectedReleaseId
37
+ ? getVersionId(documentId, selectedReleaseId)
38
+ : documentSchemaType.liveEdit
39
+ ? documentId
40
+ : getDraftId(documentId)
44
41
 
45
42
  const documentIsNew = selectedReleaseId ? !version?._id : !draft?._id && !published?._id
46
43
  const documentIsAssistable = selectedReleaseId
@@ -367,7 +367,7 @@ export function AssistInspector(props: DocumentInspectorProps) {
367
367
  mode="ghost"
368
368
  disabled={isEmptyPrompt || instructionLoading}
369
369
  fontSize={1}
370
- icon={instructionLoading ? <Spinner /> : PlayIcon}
370
+ icon={instructionLoading ? <Spinner style={{marginTop: 3}} /> : PlayIcon}
371
371
  onClick={runCurrentInstruction}
372
372
  padding={3}
373
373
  text={'Run instruction'}
@@ -0,0 +1,83 @@
1
+ import {CurrentUser} from 'sanity'
2
+
3
+ export interface AssistConfig {
4
+ /**
5
+ * As of v3.0 Assist can write to date and datetime fields.
6
+ *
7
+ * If this function is omitted from config, the plugin will use the default timeZone and locale
8
+ * in the browser:
9
+ *
10
+ * ```ts
11
+ * const {timeZone, locale} = Intl.DateTimeFormat().resolvedOptions()
12
+ * ```
13
+ *
14
+ * The function will be called any time an instruction runs.
15
+ *
16
+ * @see #LocaleSettings.locale
17
+ * @see #LocaleSettings.timeZone
18
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#getcanonicalocales
19
+ * @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
20
+ */
21
+ localeSettings?: (context: LocaleSettingsContext) => LocaleSettings
22
+
23
+ /**
24
+ * The max depth for document paths AI Assist will write to.
25
+ *
26
+ * Depth is based on field path segments:
27
+ * - `title` has depth 1
28
+ * - `array[_key="no"].title` has depth 3
29
+ *
30
+ * Be careful not to set this too high in studios with recursive document schemas, as it could have
31
+ * negative impact on performance.
32
+ *
33
+ * Depth will be counted from the field the instruction is run from. For example, if an instruction
34
+ * is attached to depth 6, the count starts from there (at 0, not at 6).
35
+ *
36
+ * Default: 4
37
+ */
38
+ maxPathDepth?: number
39
+
40
+ /**
41
+ * Influences how much the output of an instruction will vary.
42
+ *
43
+ * Min: 0 – re-running an instruction will often produce the same outcomes
44
+ * Max: 1 – re-running an instruction can produce wildly different outcomes
45
+ *
46
+ * This parameter applies to _all_ instructions in the studio.
47
+ *
48
+ * Prior to v3.0, this defaulted to 0
49
+ *
50
+ * Default: 0.3
51
+ */
52
+ temperature?: number
53
+ }
54
+
55
+ export interface LocaleSettingsContext {
56
+ user: CurrentUser
57
+ defaultSettings: LocaleSettings
58
+ }
59
+
60
+ export interface LocaleSettings {
61
+ /**
62
+ * A valid Unicode BCP 47 locale identifier used to interpret and format
63
+ * natural language inputs and date output. Examples include "en-US", "fr-FR", or "ja-JP".
64
+ *
65
+ * This affects how phrases like "next Friday" or "in two weeks" are parsed,
66
+ * and how resulting dates are presented (e.g., 12-hour vs 24-hour format).
67
+ *
68
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#getcanonicalocales
69
+ */
70
+ locale: string
71
+
72
+ /**
73
+ * A valid IANA time zone identifier used to resolve relative and absolute
74
+ * date expressions to a specific point in time. Examples include
75
+ * "America/New_York", "Europe/Paris", or "Asia/Tokyo".
76
+ *
77
+ * This ensures phrases like "tomorrow at 9am" are interpreted correctly
78
+ * based on the user's local time.
79
+ *
80
+ * @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
81
+ */
82
+ timeZone: string
83
+ }
@@ -34,17 +34,12 @@ function isDisabled(type: SchemaType) {
34
34
 
35
35
  function isUnsupportedType(type: SchemaType) {
36
36
  return (
37
- type.jsonType === 'number' ||
38
37
  type.name === 'sanity.imageCrop' ||
39
38
  type.name === 'sanity.imageHotspot' ||
40
39
  isType(type, 'globalDocumentReference') ||
41
40
  (isType(type, 'reference') &&
42
41
  !(type?.options as ReferenceOptions)?.aiAssist?.embeddingsIndex) ||
43
42
  isType(type, 'crossDatasetReference') ||
44
- isType(type, 'slug') ||
45
- isType(type, 'url') ||
46
- isType(type, 'date') ||
47
- isType(type, 'datetime') ||
48
43
  isType(type, 'file')
49
44
  )
50
45
  }
package/src/index.ts CHANGED
@@ -4,3 +4,4 @@ export * from './schemas/typeDefExtensions'
4
4
  export {defaultLanguageOutputs} from './translate/paths'
5
5
  export * from './translate/types'
6
6
  export {contextDocumentTypeName} from './types'
7
+ export * from './assistTypes'
package/src/plugin.tsx CHANGED
@@ -19,10 +19,16 @@ import {createAssistDocumentPresence} from './presence/AssistDocumentPresence'
19
19
  import {schemaTypes} from './schemas'
20
20
  import {TranslationConfig} from './translate/types'
21
21
  import {assistDocumentTypeName, AssistPreset} from './types'
22
+ import {AssistConfig} from './assistTypes'
22
23
 
23
24
  export interface AssistPluginConfig {
24
25
  translate?: TranslationConfig
25
26
 
27
+ /**
28
+ * Config that affects all instructions
29
+ */
30
+ assist?: AssistConfig
31
+
26
32
  /**
27
33
  * @internal
28
34
  */
@@ -37,6 +43,8 @@ export interface AssistPluginConfig {
37
43
  export const assist = definePlugin<AssistPluginConfig | void>((config) => {
38
44
  const configWithDefaults = config ?? {}
39
45
  const styleguide = configWithDefaults.translate?.styleguide || ''
46
+ const maxPathDepth = configWithDefaults.assist?.maxPathDepth
47
+ const temperature = configWithDefaults.assist?.temperature
40
48
 
41
49
  if (styleguide.length > 2000) {
42
50
  throw new Error(
@@ -44,6 +52,18 @@ export const assist = definePlugin<AssistPluginConfig | void>((config) => {
44
52
  )
45
53
  }
46
54
 
55
+ if (maxPathDepth !== undefined && (maxPathDepth < 1 || maxPathDepth > 12)) {
56
+ throw new Error(
57
+ `[${packageName}]: \`assist.maxPathDepth\` must be be in the range [1,12] inclusive, but was ${maxPathDepth}`,
58
+ )
59
+ }
60
+
61
+ if (temperature !== undefined && (temperature < 0 || temperature > 1)) {
62
+ throw new Error(
63
+ `[${packageName}]: \`assist.maxPathDepth\` must be be in the range [0,1] inclusive, but was ${temperature}`,
64
+ )
65
+ }
66
+
47
67
  return {
48
68
  name: packageName,
49
69
  // the addition of global references broke auto updating studios
@@ -150,11 +150,6 @@ describe('serializeSchema', () => {
150
150
  }),
151
151
  //image without extra fields should be excluded
152
152
  defineField({type: 'image', name: 'image'}),
153
- // unsupported types
154
- defineField({type: 'number', name: 'number'}),
155
- defineField({type: 'slug', name: 'slug'}),
156
- defineField({type: 'url', name: 'url'}),
157
- defineField({type: 'datetime', name: 'datetime'}),
158
153
  defineField({type: 'file', name: 'file'}),
159
154
  defineField({type: 'reference', name: 'reference', to: [{type: 'excluded'}]}),
160
155
  defineField({
@@ -717,7 +712,14 @@ describe('serializeSchema', () => {
717
712
  name: 'blockAlias',
718
713
  title: 'Block',
719
714
  type: 'block',
720
- annotations: [],
715
+ annotations: [
716
+ {
717
+ fields: [{name: 'href', title: 'Link', type: 'url'}],
718
+ name: 'link',
719
+ title: 'Link',
720
+ type: 'object',
721
+ },
722
+ ],
721
723
  inlineOf: [
722
724
  {
723
725
  name: 'inline-block',
@@ -3,6 +3,7 @@ import {useToast} from '@sanity/ui'
3
3
  import {useCallback, useMemo, useState} from 'react'
4
4
  import {Path, pathToString, useClient, useCurrentUser, useSchema} from 'sanity'
5
5
 
6
+ import {useAiAssistanceConfig} from './assistLayout/AiAssistanceConfigContext'
6
7
  import {ConditionalMemberState} from './helpers/conditionalMembers'
7
8
  import {serializeSchema} from './schemas/serialize/serializeSchema'
8
9
  import {FieldLanguageMap} from './translate/paths'
@@ -40,13 +41,14 @@ export interface TranslateRequest {
40
41
  }
41
42
 
42
43
  const basePath = '/assist/tasks/instruction'
44
+ const API_VERSION_WITH_EXTENDED_TYPES = '2025-04-01'
43
45
 
44
46
  export function canUseAssist(status: InstructStatus | undefined) {
45
47
  return status?.enabled && status.initialized && status.validToken
46
48
  }
47
49
 
48
50
  export function useApiClient(customApiClient?: (defaultClient: SanityClient) => SanityClient) {
49
- const client = useClient({apiVersion: '2023-06-05'})
51
+ const client = useClient({apiVersion: API_VERSION_WITH_EXTENDED_TYPES})
50
52
  return useMemo(
51
53
  () => (customApiClient ? customApiClient(client) : client),
52
54
  [client, customApiClient],
@@ -278,9 +280,27 @@ export function useRunInstructionApi(apiClient: SanityClient) {
278
280
  const schema = useSchema()
279
281
  const types = useMemo(() => serializeSchema(schema, {leanFormat: true}), [schema])
280
282
 
283
+ const {
284
+ config: {assist: assistConfig},
285
+ } = useAiAssistanceConfig()
286
+
281
287
  const runInstruction = useCallback(
282
288
  (request: RunInstructionRequest) => {
289
+ if (!user) {
290
+ toast.push({
291
+ status: 'error',
292
+ title: 'Unable to get user for instruction.',
293
+ })
294
+ return undefined
295
+ }
283
296
  setLoading(true)
297
+
298
+ const {timeZone, locale} = Intl.DateTimeFormat().resolvedOptions()
299
+ const defaultLocaleSettings = {timeZone, locale}
300
+ const localeSettings =
301
+ assistConfig?.localeSettings?.({user, defaultSettings: defaultLocaleSettings}) ??
302
+ defaultLocaleSettings
303
+
284
304
  return apiClient
285
305
  .request({
286
306
  method: 'POST',
@@ -291,6 +311,8 @@ export function useRunInstructionApi(apiClient: SanityClient) {
291
311
  ...request,
292
312
  types,
293
313
  userId: user?.id,
314
+ localeSettings,
315
+ maxPathDepth: assistConfig?.maxPathDepth,
294
316
  },
295
317
  })
296
318
  .catch((e) => {
@@ -305,7 +327,7 @@ export function useRunInstructionApi(apiClient: SanityClient) {
305
327
  setLoading(false)
306
328
  })
307
329
  },
308
- [apiClient, types, user, toast],
330
+ [apiClient, types, user, toast, assistConfig],
309
331
  )
310
332
 
311
333
  return useMemo(