@sanity/assist 4.3.1 → 4.4.0
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/README.md +181 -175
- package/dist/index.d.mts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.esm.js +31 -10
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +31 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/assistDocument/AssistDocumentContext.tsx +4 -0
- package/src/assistDocument/hooks/useAssistDocumentContextValue.tsx +7 -1
- package/src/assistInspector/helpers.ts +8 -0
- package/src/assistLayout/RunInstructionProvider.tsx +1 -0
- package/src/fieldActions/assistFieldActions.tsx +15 -1
- package/src/fieldActions/customFieldActions.tsx +38 -10
- package/src/helpers/misc.ts +4 -0
- package/src/plugin.tsx +4 -1
- package/src/types.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/assist",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
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.13.4",
|
|
67
67
|
"@sanity/plugin-kit": "^3.1.10",
|
|
68
|
-
"@sanity/schema": "^3.
|
|
68
|
+
"@sanity/schema": "^3.93.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,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.
|
|
86
|
+
"sanity": "^3.93.0",
|
|
87
87
|
"semantic-release": "^23.0.8",
|
|
88
88
|
"styled-components": "^6.1.16",
|
|
89
89
|
"typescript": "^5.7.2",
|
|
@@ -2,6 +2,7 @@ import {createContext, useContext} from 'react'
|
|
|
2
2
|
import {DocumentInspector, ObjectSchemaType, PatchEvent} from 'sanity'
|
|
3
3
|
|
|
4
4
|
import {InstructionTask, StudioAssistDocument} from '../types'
|
|
5
|
+
import {FieldRef} from '../assistInspector/helpers'
|
|
5
6
|
|
|
6
7
|
export type AssistDocumentContextValue = (
|
|
7
8
|
| {assistDocument: StudioAssistDocument; loading: false}
|
|
@@ -32,6 +33,9 @@ export type AssistDocumentContextValue = (
|
|
|
32
33
|
syntheticTasks?: InstructionTask[]
|
|
33
34
|
addSyntheticTask: (syntheticTask: InstructionTask) => void
|
|
34
35
|
removeSyntheticTask: (syntheticTask: InstructionTask) => void
|
|
36
|
+
|
|
37
|
+
fieldRefs: FieldRef[]
|
|
38
|
+
fieldRefsByTypePath: Record<string, FieldRef | undefined>
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
export const AssistDocumentContext = createContext<AssistDocumentContextValue | undefined>(
|
|
@@ -2,7 +2,7 @@ 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
4
|
|
|
5
|
-
import {useAiPaneRouter} from '../../assistInspector/helpers'
|
|
5
|
+
import {asFieldRefsByTypePath, getFieldRefs, useAiPaneRouter} from '../../assistInspector/helpers'
|
|
6
6
|
import {fieldPathParam, InstructionTask} from '../../types'
|
|
7
7
|
import type {AssistDocumentContextValue} from '../AssistDocumentContext'
|
|
8
8
|
import {isDocAssistable} from '../RequestRunInstructionProvider'
|
|
@@ -53,6 +53,10 @@ export function useAssistDocumentContextValue(documentId: string, documentType:
|
|
|
53
53
|
})
|
|
54
54
|
const {syntheticTasks, addSyntheticTask, removeSyntheticTask} =
|
|
55
55
|
useSyntheticTasks(assistableDocumentId)
|
|
56
|
+
|
|
57
|
+
const fieldRefs = getFieldRefs(documentSchemaType)
|
|
58
|
+
const fieldRefsByTypePath = asFieldRefsByTypePath(fieldRefs)
|
|
59
|
+
|
|
56
60
|
const value: AssistDocumentContextValue = useMemo(() => {
|
|
57
61
|
const base = {
|
|
58
62
|
assistableDocumentId,
|
|
@@ -67,6 +71,8 @@ export function useAssistDocumentContextValue(documentId: string, documentType:
|
|
|
67
71
|
syntheticTasks,
|
|
68
72
|
addSyntheticTask,
|
|
69
73
|
removeSyntheticTask,
|
|
74
|
+
fieldRefs,
|
|
75
|
+
fieldRefsByTypePath,
|
|
70
76
|
}
|
|
71
77
|
if (!assistDocument) {
|
|
72
78
|
return {...base, loading: true, assistDocument: undefined}
|
|
@@ -57,6 +57,14 @@ export function getTypeIcon(schemaType: SchemaType) {
|
|
|
57
57
|
return DocumentIcon
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
export function asFieldRefsByTypePath(fieldRefs: FieldRef[]): Record<string, FieldRef | undefined> {
|
|
61
|
+
const lookup: Record<string, FieldRef | undefined> = fieldRefs.reduce(
|
|
62
|
+
(acc, ref) => ({...acc, [ref.key]: ref}),
|
|
63
|
+
{},
|
|
64
|
+
)
|
|
65
|
+
return lookup
|
|
66
|
+
}
|
|
67
|
+
|
|
60
68
|
export function getFieldRefsWithDocument(schemaType: ObjectSchemaType): FieldRef[] {
|
|
61
69
|
const fields = getFieldRefs(schemaType)
|
|
62
70
|
return [
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type DocumentFieldAction,
|
|
5
5
|
type DocumentFieldActionGroup,
|
|
6
6
|
type DocumentFieldActionItem,
|
|
7
|
+
pathToString,
|
|
7
8
|
stringToPath,
|
|
8
9
|
typed,
|
|
9
10
|
useCurrentUser,
|
|
@@ -14,7 +15,7 @@ import {useAssistDocumentContext} from '../assistDocument/AssistDocumentContext'
|
|
|
14
15
|
import {getIcon} from '../assistDocument/components/instruction/appearance/IconInput'
|
|
15
16
|
import {useRequestRunInstruction} from '../assistDocument/RequestRunInstructionProvider'
|
|
16
17
|
import {aiInspectorId} from '../assistInspector/constants'
|
|
17
|
-
import {useSelectedField, useTypePath} from '../assistInspector/helpers'
|
|
18
|
+
import {getTypePath, useSelectedField, useTypePath} from '../assistInspector/helpers'
|
|
18
19
|
import {pluginTitleShort} from '../constants'
|
|
19
20
|
import {isSchemaAssistEnabled} from '../helpers/assistSupported'
|
|
20
21
|
import {getConditionalMembers} from '../helpers/conditionalMembers'
|
|
@@ -48,6 +49,7 @@ export const assistFieldActions: DocumentFieldAction = {
|
|
|
48
49
|
documentSchemaType,
|
|
49
50
|
selectedPath,
|
|
50
51
|
assistableDocumentId,
|
|
52
|
+
fieldRefsByTypePath,
|
|
51
53
|
} = useAssistDocumentContext()
|
|
52
54
|
|
|
53
55
|
const {value: docValue, formState} = useDocumentPane()
|
|
@@ -204,6 +206,17 @@ export const assistFieldActions: DocumentFieldAction = {
|
|
|
204
206
|
)
|
|
205
207
|
}, [])
|
|
206
208
|
|
|
209
|
+
const parentSchemaType = useMemo(() => {
|
|
210
|
+
if (!props.path.length) {
|
|
211
|
+
return undefined
|
|
212
|
+
} else if (props.path.length === 1) {
|
|
213
|
+
return documentSchemaType
|
|
214
|
+
}
|
|
215
|
+
const parentPath = props.path.slice(0, -1)
|
|
216
|
+
const typePath = getTypePath(docValueRef.current, pathToString(parentPath))
|
|
217
|
+
return typePath ? fieldRefsByTypePath[typePath]?.schemaType : undefined
|
|
218
|
+
}, [fieldRefsByTypePath, props.path, documentSchemaType])
|
|
219
|
+
|
|
207
220
|
const customActions = useCustomFieldActions({
|
|
208
221
|
actionType: props.path.length ? 'field' : 'document',
|
|
209
222
|
documentIdForAction: assistableDocumentId,
|
|
@@ -212,6 +225,7 @@ export const assistFieldActions: DocumentFieldAction = {
|
|
|
212
225
|
path: props.path,
|
|
213
226
|
getDocumentValue,
|
|
214
227
|
getConditionalPaths,
|
|
228
|
+
parentSchemaType,
|
|
215
229
|
})
|
|
216
230
|
|
|
217
231
|
const manageInstructionsItem = useMemo(
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
instructionTaskTypeName,
|
|
21
21
|
} from '../types'
|
|
22
22
|
import {randomKey} from '../_lib/randomKey'
|
|
23
|
+
import {isDefined} from '../helpers/misc'
|
|
23
24
|
|
|
24
25
|
export interface AgentActionConditionalPath {
|
|
25
26
|
path: AgentActionPath
|
|
@@ -91,6 +92,8 @@ export interface AssistFieldActionProps {
|
|
|
91
92
|
* },
|
|
92
93
|
* //...
|
|
93
94
|
* })
|
|
95
|
+
*
|
|
96
|
+
* ```
|
|
94
97
|
*/
|
|
95
98
|
schemaId: string
|
|
96
99
|
|
|
@@ -141,6 +144,16 @@ export interface AssistFieldActionProps {
|
|
|
141
144
|
* ```
|
|
142
145
|
*/
|
|
143
146
|
schemaType: SchemaType
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Schema type of the parent field or array item holding this field.
|
|
150
|
+
*
|
|
151
|
+
* This can be undefined if the action was unable to resolve the parent type is excluded from AI Assist.
|
|
152
|
+
*
|
|
153
|
+
* @see schemaType
|
|
154
|
+
* @see documentSchemaType
|
|
155
|
+
*/
|
|
156
|
+
parentSchemaType?: SchemaType
|
|
144
157
|
}
|
|
145
158
|
|
|
146
159
|
export type AssistFieldActionNode =
|
|
@@ -159,7 +172,11 @@ export type AssistFieldActionGroup = Omit<
|
|
|
159
172
|
DocumentFieldActionGroup,
|
|
160
173
|
'renderAsButton' | 'expanded' | 'children'
|
|
161
174
|
> & {
|
|
162
|
-
|
|
175
|
+
/**
|
|
176
|
+
* `children` can include undefined entries in the action array. These will be filtered out.
|
|
177
|
+
* If the group has no defined children, the group will also be filtered out.
|
|
178
|
+
*/
|
|
179
|
+
children: (AssistFieldActionNode | undefined)[]
|
|
163
180
|
}
|
|
164
181
|
|
|
165
182
|
type PushToast = (params: ToastParams) => string
|
|
@@ -206,14 +223,17 @@ export function useCustomFieldActions(
|
|
|
206
223
|
|
|
207
224
|
return useMemo(() => {
|
|
208
225
|
const title = fieldActions?.title
|
|
209
|
-
const customActions = configActions
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
226
|
+
const customActions = configActions
|
|
227
|
+
?.filter(isDefined)
|
|
228
|
+
.map((node) => {
|
|
229
|
+
return createSafeNode({
|
|
230
|
+
node,
|
|
231
|
+
pushToast,
|
|
232
|
+
addSyntheticTask,
|
|
233
|
+
removeSyntheticTask,
|
|
234
|
+
})
|
|
215
235
|
})
|
|
216
|
-
|
|
236
|
+
.filter(isDefined)
|
|
217
237
|
const onlyGroups =
|
|
218
238
|
customActions?.length && customActions?.every((node) => node.type === 'group')
|
|
219
239
|
const groups = customActions?.length
|
|
@@ -237,17 +257,25 @@ function createSafeNode(args: {
|
|
|
237
257
|
pushToast: PushToast
|
|
238
258
|
addSyntheticTask: (task: InstructionTask) => void
|
|
239
259
|
removeSyntheticTask: (task: InstructionTask) => void
|
|
240
|
-
}): DocumentFieldActionNode {
|
|
260
|
+
}): DocumentFieldActionNode | undefined {
|
|
241
261
|
const {node} = args
|
|
242
262
|
switch (node.type) {
|
|
243
263
|
case 'action':
|
|
244
264
|
return createSafeAction({...args, action: node})
|
|
245
265
|
case 'group':
|
|
266
|
+
// eslint-disable-next-line no-case-declarations
|
|
267
|
+
const children = node.children
|
|
268
|
+
?.filter(isDefined)
|
|
269
|
+
.map((child) => createSafeNode({...args, node: child}))
|
|
270
|
+
.filter(isDefined)
|
|
271
|
+
if (!children?.length) {
|
|
272
|
+
return undefined
|
|
273
|
+
}
|
|
246
274
|
return {
|
|
247
275
|
...node,
|
|
248
276
|
renderAsButton: false,
|
|
249
277
|
expanded: true,
|
|
250
|
-
children
|
|
278
|
+
children,
|
|
251
279
|
}
|
|
252
280
|
case 'divider':
|
|
253
281
|
default:
|
package/src/helpers/misc.ts
CHANGED
|
@@ -19,3 +19,7 @@ export function getPathKey(path: Path | string) {
|
|
|
19
19
|
export function getInstructionTitle(instruction?: StudioInstruction) {
|
|
20
20
|
return instruction?.title ?? 'Untitled'
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
export function isDefined<T>(t: T | undefined | null): t is T {
|
|
24
|
+
return t !== undefined && t !== null
|
|
25
|
+
}
|
package/src/plugin.tsx
CHANGED
|
@@ -33,7 +33,10 @@ export interface AssistPluginConfig {
|
|
|
33
33
|
|
|
34
34
|
fieldActions?: {
|
|
35
35
|
title?: string
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* The returned array can include `undefined` entries in the action array. These will be filtered out.
|
|
38
|
+
*/
|
|
39
|
+
useFieldActions?: (props: AssistFieldActionProps) => (AssistFieldActionNode | undefined)[]
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
/**
|