@sanity/assist 4.4.5 → 4.4.7

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": "4.4.5",
3
+ "version": "4.4.7",
4
4
  "description": "You create the instructions; Sanity AI Assist does the rest.",
5
5
  "keywords": [
6
6
  "sanity",
@@ -83,7 +83,7 @@
83
83
  "react": "^18.2.0",
84
84
  "react-dom": "^18.2.0",
85
85
  "rimraf": "^5.0.5",
86
- "sanity": "^3.93.0",
86
+ "sanity": "^4.0.0",
87
87
  "semantic-release": "^23.0.8",
88
88
  "styled-components": "^6.1.16",
89
89
  "typescript": "^5.7.2",
@@ -1,7 +1,7 @@
1
1
  import {createContext, useContext} from 'react'
2
2
  import {DocumentInspector, ObjectSchemaType, PatchEvent} from 'sanity'
3
3
 
4
- import {InstructionTask, SerializedSchemaType, StudioAssistDocument} from '../types'
4
+ import {InstructionTask, StudioAssistDocument} from '../types'
5
5
  import {FieldRef} from '../assistInspector/helpers'
6
6
 
7
7
  export type AssistDocumentContextValue = (
@@ -36,8 +36,6 @@ export type AssistDocumentContextValue = (
36
36
 
37
37
  fieldRefs: FieldRef[]
38
38
  fieldRefsByTypePath: Record<string, FieldRef | undefined>
39
-
40
- serializedTypes: SerializedSchemaType[]
41
39
  }
42
40
 
43
41
  export const AssistDocumentContext = createContext<AssistDocumentContextValue | undefined>(
@@ -1,21 +1,17 @@
1
1
  import {useCallback, useEffect, useMemo, useState} from 'react'
2
2
  import {getDraftId, getVersionId, type ObjectSchemaType, useSchema} from 'sanity'
3
3
  import {useDocumentPane} from 'sanity/structure'
4
-
5
- import {asFieldRefsByTypePath, getFieldRefs, useAiPaneRouter} from '../../assistInspector/helpers'
6
4
  import {fieldPathParam, InstructionTask} from '../../types'
7
- import {AssistDocumentContextValue, useAssistDocumentContext} from '../AssistDocumentContext'
5
+ import {AssistDocumentContextValue} from '../AssistDocumentContext'
8
6
  import {isDocAssistable} from '../RequestRunInstructionProvider'
9
7
  import {useStudioAssistDocument} from './useStudioAssistDocument'
10
- import {serializeSchema} from '../../schemas/serialize/serializeSchema'
11
-
12
- export function useSerializedTypes() {
13
- return useAssistDocumentContext().serializedTypes
14
- }
8
+ import {useAiAssistanceConfig} from '../../assistLayout/AiAssistanceConfigContext'
9
+ import {useAiPaneRouter} from '../../assistInspector/helpers'
15
10
 
16
11
  export function useAssistDocumentContextValue(documentId: string, documentType: string) {
17
12
  const schema = useSchema()
18
13
 
14
+ const {getFieldRefs, getFieldRefsByTypePath} = useAiAssistanceConfig()
19
15
  const documentSchemaType = useMemo(() => {
20
16
  const schemaType = schema.get(documentType) as ObjectSchemaType | undefined
21
17
  if (!schemaType) {
@@ -24,16 +20,12 @@ export function useAssistDocumentContextValue(documentId: string, documentType:
24
20
  return schemaType
25
21
  }, [documentType, schema])
26
22
 
27
- const serializedTypes = useMemo(() => serializeSchema(schema, {leanFormat: true}), [schema])
28
-
29
23
  const {fieldRefs, fieldRefsByTypePath} = useMemo(() => {
30
- const fieldRefs = getFieldRefs(documentSchemaType)
31
- const fieldRefsByTypePath = asFieldRefsByTypePath(fieldRefs)
32
24
  return {
33
- fieldRefs,
34
- fieldRefsByTypePath,
25
+ fieldRefs: getFieldRefs(documentType),
26
+ fieldRefsByTypePath: getFieldRefsByTypePath(documentType),
35
27
  }
36
- }, [documentSchemaType])
28
+ }, [getFieldRefs, getFieldRefsByTypePath, documentType])
37
29
 
38
30
  const {
39
31
  openInspector,
@@ -86,7 +78,6 @@ export function useAssistDocumentContextValue(documentId: string, documentType:
86
78
  removeSyntheticTask,
87
79
  fieldRefs,
88
80
  fieldRefsByTypePath,
89
- serializedTypes,
90
81
  }
91
82
  if (!assistDocument) {
92
83
  return {...base, loading: true, assistDocument: undefined}
@@ -112,7 +103,6 @@ export function useAssistDocumentContextValue(documentId: string, documentType:
112
103
  removeSyntheticTask,
113
104
  fieldRefs,
114
105
  fieldRefsByTypePath,
115
- serializedTypes,
116
106
  ])
117
107
 
118
108
  return value
@@ -4,7 +4,8 @@ import {createElement, useCallback, useMemo} from 'react'
4
4
  import {ObjectSchemaType} from 'sanity'
5
5
 
6
6
  import {isType} from '../helpers/typeUtils'
7
- import {FieldRef, getFieldRefs, getFieldRefsWithDocument} from './helpers'
7
+ import {FieldRef, getDocumentFieldRef} from './helpers'
8
+ import {useAiAssistanceConfig} from '../assistLayout/AiAssistanceConfigContext'
8
9
 
9
10
  interface FieldSelectorProps {
10
11
  id: string
@@ -18,12 +19,16 @@ interface FieldSelectorProps {
18
19
  export function FieldAutocomplete(props: FieldSelectorProps) {
19
20
  const {id, schemaType, fieldPath, onSelect, includeDocument, filter} = props
20
21
 
22
+ const {getFieldRefs} = useAiAssistanceConfig()
23
+
21
24
  const fieldRefs = useMemo(() => {
25
+ const refs = getFieldRefs(schemaType.name)
22
26
  if (includeDocument) {
23
- return getFieldRefsWithDocument(schemaType)
27
+ return [getDocumentFieldRef(schemaType), ...refs]
24
28
  }
25
- return getFieldRefs(schemaType)
26
- }, [schemaType, includeDocument])
29
+ return refs
30
+ }, [schemaType, includeDocument, getFieldRefs])
31
+
27
32
  const currentField = useMemo(
28
33
  () => fieldRefs.find((f) => f.key === fieldPath),
29
34
  [fieldPath, fieldRefs],
@@ -8,7 +8,7 @@ import {
8
8
  StringIcon,
9
9
  } from '@sanity/icons'
10
10
  import {extractWithPath} from '@sanity/mutator'
11
- import {type ComponentType, useContext, useMemo} from 'react'
11
+ import {type ComponentType, useMemo} from 'react'
12
12
  import {
13
13
  type ArraySchemaType,
14
14
  isKeySegment,
@@ -21,11 +21,10 @@ import {
21
21
  stringToPath,
22
22
  } from 'sanity'
23
23
  import {type PaneRouterContextValue, usePaneRouter} from 'sanity/structure'
24
-
25
- import {SelectedFieldContext} from '../assistDocument/components/SelectedFieldContext'
26
24
  import {isAssistSupported} from '../helpers/assistSupported'
27
25
  import {isPortableTextArray, isType} from '../helpers/typeUtils'
28
- import {type AssistInspectorRouteParams, documentRootKey, fieldPathParam} from '../types'
26
+ import {type AssistInspectorRouteParams, documentRootKey} from '../types'
27
+ import {useAiAssistanceConfig} from '../assistLayout/AiAssistanceConfigContext'
29
28
 
30
29
  export interface FieldRef {
31
30
  key: string
@@ -65,19 +64,14 @@ export function asFieldRefsByTypePath(fieldRefs: FieldRef[]): Record<string, Fie
65
64
  return lookup
66
65
  }
67
66
 
68
- export function getFieldRefsWithDocument(schemaType: ObjectSchemaType): FieldRef[] {
69
- const fields = getFieldRefs(schemaType)
70
- return [
71
- {
72
- key: documentRootKey,
73
- icon: schemaType.icon ?? DocumentIcon,
74
- title: `The entire document`,
75
- path: [],
76
- schemaType: schemaType,
77
- },
78
-
79
- ...fields,
80
- ]
67
+ export function getDocumentFieldRef(schemaType: ObjectSchemaType) {
68
+ return {
69
+ key: documentRootKey,
70
+ icon: schemaType.icon ?? DocumentIcon,
71
+ title: `The entire document`,
72
+ path: [],
73
+ schemaType: schemaType,
74
+ }
81
75
  }
82
76
 
83
77
  export function getFieldRefs(
@@ -182,12 +176,14 @@ export function useSelectedField(
182
176
  documentSchemaType?: SchemaType,
183
177
  path?: string,
184
178
  ): FieldRef | undefined {
179
+ const {getFieldRefs} = useAiAssistanceConfig()
180
+
185
181
  const selectableFields = useMemo(
186
182
  () =>
187
183
  documentSchemaType && isObjectSchemaType(documentSchemaType)
188
- ? getFieldRefsWithDocument(documentSchemaType)
184
+ ? [getDocumentFieldRef(documentSchemaType), ...getFieldRefs(documentSchemaType.name)]
189
185
  : [],
190
- [documentSchemaType],
186
+ [documentSchemaType, getFieldRefs],
191
187
  )
192
188
 
193
189
  return useMemo(() => {
@@ -195,13 +191,6 @@ export function useSelectedField(
195
191
  }, [selectableFields, path])
196
192
  }
197
193
 
198
- export function useSelectedFieldTitle() {
199
- const {params} = useAiPaneRouter()
200
- const {documentSchema} = useContext(SelectedFieldContext) ?? {}
201
- const selectedField = useSelectedField(documentSchema, params[fieldPathParam])
202
- return getFieldTitle(selectedField)
203
- }
204
-
205
194
  export function getFieldTitle(field?: FieldRef) {
206
195
  const schemaType = field?.schemaType
207
196
  return field?.title ?? schemaType?.title ?? schemaType?.name ?? 'Untitled'
@@ -1,15 +1,9 @@
1
- import {
2
- createContext,
3
- ReactNode,
4
- useCallback,
5
- useContext,
6
- useEffect,
7
- useMemo,
8
- useState,
9
- } from 'react'
1
+ import {createContext, useContext} from 'react'
10
2
 
11
3
  import {AssistPluginConfig} from '../plugin'
12
- import {InstructStatus, useApiClient, useGetInstructStatus, useInitInstruct} from '../useApiClient'
4
+ import {InstructStatus} from '../useApiClient'
5
+ import {SerializedSchemaType} from '../types'
6
+ import {FieldRef} from '../assistInspector/helpers'
13
7
 
14
8
  export interface AiAssistanceConfigContextValue {
15
9
  config: AssistPluginConfig
@@ -18,6 +12,9 @@ export interface AiAssistanceConfigContextValue {
18
12
  initLoading: boolean
19
13
  init: () => void
20
14
  error?: Error
15
+ serializedTypes: SerializedSchemaType[]
16
+ getFieldRefs: (documentType: string) => FieldRef[]
17
+ getFieldRefsByTypePath: (documentType: string) => Record<string, FieldRef | undefined>
21
18
  }
22
19
 
23
20
  export const AiAssistanceConfigContext = createContext<AiAssistanceConfigContextValue>({} as any)
@@ -30,53 +27,6 @@ export function useAiAssistanceConfig() {
30
27
  return context
31
28
  }
32
29
 
33
- export function AiAssistanceConfigProvider(props: {
34
- children?: ReactNode
35
- config: AssistPluginConfig
36
- }) {
37
- const [status, setStatus] = useState<InstructStatus | undefined>()
38
- const [error, setError] = useState<Error | undefined>()
39
-
40
- const apiClient = useApiClient(props.config?.__customApiClient)
41
- const {getInstructStatus, loading: statusLoading} = useGetInstructStatus(apiClient)
42
- const {initInstruct, loading: initLoading} = useInitInstruct(apiClient)
43
-
44
- useEffect(() => {
45
- getInstructStatus()
46
- .then((s) => setStatus(s))
47
- .catch((e) => {
48
- console.error(e)
49
- setError(e as Error)
50
- })
51
- }, [getInstructStatus])
52
-
53
- const init = useCallback(async () => {
54
- setError(undefined)
55
- try {
56
- await initInstruct()
57
- const status = await getInstructStatus()
58
- setStatus(status)
59
- } catch (e) {
60
- console.error('Failed to init ai assistance', e)
61
- setError(e as Error)
62
- }
63
- }, [initInstruct, getInstructStatus, setStatus])
64
-
65
- const {config, children} = props
66
- const context = useMemo<AiAssistanceConfigContextValue>(() => {
67
- return {
68
- config,
69
- status,
70
- statusLoading,
71
- init,
72
- initLoading,
73
- error,
74
- }
75
- }, [config, status, init, statusLoading, initLoading, error])
76
-
77
- return (
78
- <AiAssistanceConfigContext.Provider value={context}>
79
- {children}
80
- </AiAssistanceConfigContext.Provider>
81
- )
30
+ export function useSerializedTypes() {
31
+ return useAiAssistanceConfig().serializedTypes
82
32
  }
@@ -0,0 +1,98 @@
1
+ import {ReactNode, useCallback, useEffect, useMemo, useState} from 'react'
2
+ import {AssistPluginConfig} from '../plugin'
3
+ import {InstructStatus, useApiClient, useGetInstructStatus, useInitInstruct} from '../useApiClient'
4
+ import {type ObjectSchemaType, Schema, useSchema} from 'sanity'
5
+ import {serializeSchema} from '../schemas/serialize/serializeSchema'
6
+ import {
7
+ AiAssistanceConfigContext,
8
+ AiAssistanceConfigContextValue,
9
+ } from './AiAssistanceConfigContext'
10
+ import {createFieldRefCache} from './fieldRefCache'
11
+
12
+ export function AiAssistanceConfigProvider(props: {
13
+ children?: ReactNode
14
+ config: AssistPluginConfig
15
+ }) {
16
+ const [status, setStatus] = useState<InstructStatus | undefined>()
17
+ const [error, setError] = useState<Error | undefined>()
18
+
19
+ const apiClient = useApiClient(props.config?.__customApiClient)
20
+ const {getInstructStatus, loading: statusLoading} = useGetInstructStatus(apiClient)
21
+ const {initInstruct, loading: initLoading} = useInitInstruct(apiClient)
22
+
23
+ const schema = useSchema()
24
+ const serializedTypes = useMemo(() => serializeSchema(schema, {leanFormat: true}), [schema])
25
+ const {getFieldRefs, getFieldRefsByTypePath} = useFieldRefGetters(schema)
26
+
27
+ useEffect(() => {
28
+ getInstructStatus()
29
+ .then((s) => setStatus(s))
30
+ .catch((e) => {
31
+ console.error(e)
32
+ setError(e as Error)
33
+ })
34
+ }, [getInstructStatus])
35
+
36
+ const init = useCallback(async () => {
37
+ setError(undefined)
38
+ try {
39
+ await initInstruct()
40
+ const status = await getInstructStatus()
41
+ setStatus(status)
42
+ } catch (e) {
43
+ console.error('Failed to init ai assistance', e)
44
+ setError(e as Error)
45
+ }
46
+ }, [initInstruct, getInstructStatus, setStatus])
47
+
48
+ const {config, children} = props
49
+ const context = useMemo<AiAssistanceConfigContextValue>(() => {
50
+ return {
51
+ config,
52
+ status,
53
+ statusLoading,
54
+ init,
55
+ initLoading,
56
+ error,
57
+ serializedTypes,
58
+ getFieldRefs,
59
+ getFieldRefsByTypePath,
60
+ }
61
+ }, [
62
+ config,
63
+ status,
64
+ init,
65
+ statusLoading,
66
+ initLoading,
67
+ error,
68
+ serializedTypes,
69
+ getFieldRefs,
70
+ getFieldRefsByTypePath,
71
+ ])
72
+
73
+ return (
74
+ <AiAssistanceConfigContext.Provider value={context}>
75
+ {children}
76
+ </AiAssistanceConfigContext.Provider>
77
+ )
78
+ }
79
+
80
+ function useFieldRefGetters(schema: Schema) {
81
+ return useMemo(() => {
82
+ const getForSchemaType = createFieldRefCache()
83
+
84
+ function getRefsForType(documentType: string) {
85
+ const schemaType = schema.get(documentType) as ObjectSchemaType | undefined
86
+ if (!schemaType) {
87
+ throw new Error(`Schema type "${documentType}" not found`)
88
+ }
89
+ return getForSchemaType(schemaType)
90
+ }
91
+
92
+ return {
93
+ getFieldRefs: (documentType: string) => getRefsForType(documentType).fieldRefs,
94
+ getFieldRefsByTypePath: (documentType: string) =>
95
+ getRefsForType(documentType).fieldRefsByTypePath,
96
+ }
97
+ }, [schema])
98
+ }
@@ -8,8 +8,8 @@ import {AssistPluginConfig} from '../plugin'
8
8
  import {FieldTranslationProvider} from '../translate/FieldTranslationProvider'
9
9
  import {StudioInstruction} from '../types'
10
10
  import {RunInstructionRequest} from '../useApiClient'
11
- import {AiAssistanceConfigProvider} from './AiAssistanceConfigContext'
12
11
  import {RunInstructionProvider} from './RunInstructionProvider'
12
+ import {AiAssistanceConfigProvider} from './AiAssistanceConfigProvider'
13
13
 
14
14
  export interface AIStudioLayoutProps extends LayoutProps {
15
15
  config: AssistPluginConfig
@@ -0,0 +1,34 @@
1
+ import {
2
+ asFieldRefsByTypePath,
3
+ FieldRef,
4
+ getFieldRefs as createFieldRefs,
5
+ } from '../assistInspector/helpers'
6
+ import type {ObjectSchemaType} from 'sanity'
7
+
8
+ export function createFieldRefCache() {
9
+ const byType: Record<
10
+ string,
11
+ | {
12
+ fieldRefs: FieldRef[]
13
+ fieldRefsByTypePath: Record<string, FieldRef | undefined>
14
+ }
15
+ | undefined
16
+ > = {}
17
+
18
+ function getRefsForType(schemaType: ObjectSchemaType) {
19
+ const documentType = schemaType.name
20
+ const cached = byType[documentType]
21
+ if (cached) return cached
22
+
23
+ const fieldRefs = createFieldRefs(schemaType)
24
+ const fieldRefsByTypePath = asFieldRefsByTypePath(fieldRefs)
25
+ const refs = {
26
+ fieldRefs,
27
+ fieldRefsByTypePath,
28
+ }
29
+ byType[documentType] = refs
30
+ return refs
31
+ }
32
+
33
+ return getRefsForType
34
+ }
@@ -4,10 +4,11 @@ import {
4
4
  DocumentFieldActionItem,
5
5
  DocumentFieldActionNode,
6
6
  ObjectSchemaType,
7
+ Path,
7
8
  SanityDocumentLike,
9
+ SchemaType,
8
10
  useWorkspaceSchemaId,
9
11
  } from 'sanity'
10
- import {Path, SchemaType} from '@sanity/types'
11
12
  import {useMemo} from 'react'
12
13
  import {useAiAssistanceConfig} from '../assistLayout/AiAssistanceConfigContext'
13
14
  import {ToastParams, useToast} from '@sanity/ui'
@@ -24,7 +24,6 @@ import {InstructionOutputInput} from '../assistDocument/components/instruction/I
24
24
  import {PromptInput} from '../assistDocument/components/instruction/PromptInput'
25
25
  import {InstructionsArrayField} from '../assistDocument/components/InstructionsArrayField'
26
26
  import {InstructionsArrayInput} from '../assistDocument/components/InstructionsArrayInput'
27
- import {getFieldRefsWithDocument} from '../assistInspector/helpers'
28
27
  import {instructionGuideUrl} from '../constants'
29
28
  import {getInstructionTitle} from '../helpers/misc'
30
29
  import {
@@ -43,6 +42,8 @@ import {
43
42
  } from '../types'
44
43
  import {contextDocumentSchema} from './contextDocumentSchema'
45
44
 
45
+ import {createFieldRefCache} from '../assistLayout/fieldRefCache'
46
+
46
47
  export const fieldReference = defineType({
47
48
  type: 'object',
48
49
  name: fieldReferenceTypeName,
@@ -57,8 +58,9 @@ export const fieldReference = defineType({
57
58
  components: {
58
59
  input: FieldRefPathInput,
59
60
  },
60
- validation: (rule) =>
61
- rule.custom((value, context) => {
61
+ validation: (rule) => {
62
+ const getForSchemaType = createFieldRefCache()
63
+ return rule.custom((value, context) => {
62
64
  if (!value) {
63
65
  return 'Please select a field'
64
66
  }
@@ -72,8 +74,8 @@ export const fieldReference = defineType({
72
74
  if (!schema) {
73
75
  return `Field reference cannot be used outside document inspector context. Could not resolve schema: ${targetDocType}`
74
76
  }
75
- const refs = getFieldRefsWithDocument(schema as ObjectSchemaType)
76
- const fieldRef = refs.find((r) => r.key === value)
77
+ const {fieldRefs} = getForSchemaType(schema as ObjectSchemaType)
78
+ const fieldRef = fieldRefs.find((r) => r.key === value)
77
79
  if (!fieldRef) {
78
80
  return `Field with path "${value}" does not exist in the schema.`
79
81
  }
@@ -82,7 +84,8 @@ export const fieldReference = defineType({
82
84
  console.error('Failed to resolve field reference', e)
83
85
  return 'Invalid field reference.'
84
86
  }
85
- }),
87
+ })
88
+ },
86
89
  }),
87
90
  ],
88
91
  preview: {
@@ -1,3 +1,4 @@
1
+ import 'sanity'
1
2
  /* eslint-disable no-unused-vars */
2
3
  export interface AssistOptions {
3
4
  aiAssist?: {
@@ -3,11 +3,10 @@ import {useToast} from '@sanity/ui'
3
3
  import {useCallback, useMemo, useState} from 'react'
4
4
  import {Path, pathToString, useClient, useCurrentUser} from 'sanity'
5
5
 
6
- import {useAiAssistanceConfig} from './assistLayout/AiAssistanceConfigContext'
6
+ import {useAiAssistanceConfig, useSerializedTypes} from './assistLayout/AiAssistanceConfigContext'
7
7
  import {ConditionalMemberState} from './helpers/conditionalMembers'
8
8
  import {FieldLanguageMap} from './translate/paths'
9
9
  import {documentRootKey} from './types'
10
- import {useSerializedTypes} from './assistDocument/hooks/useAssistDocumentContextValue'
11
10
 
12
11
  export interface UserTextInstance {
13
12
  blockKey: string