@sanity/assist 5.0.3 → 6.0.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/LICENSE +1 -1
- package/README.md +28 -254
- package/dist/index.d.ts +322 -410
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3182 -2673
- package/dist/index.js.map +1 -1
- package/package.json +41 -77
- package/dist/index.cjs +0 -4264
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -791
- package/sanity.json +0 -8
- package/src/_lib/connector/ConnectFromRegion.tsx +0 -25
- package/src/_lib/connector/ConnectToRegion.tsx +0 -23
- package/src/_lib/connector/ConnectorRegion.tsx +0 -24
- package/src/_lib/connector/ConnectorsProvider.tsx +0 -20
- package/src/_lib/connector/ConnectorsStore.ts +0 -122
- package/src/_lib/connector/ConnectorsStoreContext.ts +0 -5
- package/src/_lib/connector/helpers.ts +0 -5
- package/src/_lib/connector/index.ts +0 -9
- package/src/_lib/connector/mapConnectorToLine.ts +0 -83
- package/src/_lib/connector/types.ts +0 -56
- package/src/_lib/connector/useConnectorsStore.ts +0 -14
- package/src/_lib/connector/useRegionRects.ts +0 -142
- package/src/_lib/fixedListenQuery.ts +0 -101
- package/src/_lib/form/DocumentForm.tsx +0 -201
- package/src/_lib/form/constants.ts +0 -1
- package/src/_lib/form/helpers.ts +0 -32
- package/src/_lib/form/index.ts +0 -1
- package/src/_lib/randomKey.ts +0 -29
- package/src/_lib/useListeningQuery.ts +0 -62
- package/src/_lib/usePrevious.ts +0 -9
- package/src/assistConnectors/AssistConnectorsOverlay.tsx +0 -133
- package/src/assistConnectors/ConnectorPath.tsx +0 -63
- package/src/assistConnectors/draw/arrowPath.ts +0 -9
- package/src/assistConnectors/draw/connectorPath.ts +0 -142
- package/src/assistConnectors/index.ts +0 -1
- package/src/assistDocument/AssistDocumentContext.tsx +0 -51
- package/src/assistDocument/AssistDocumentContextProvider.tsx +0 -17
- package/src/assistDocument/AssistDocumentInput.tsx +0 -61
- package/src/assistDocument/AssistDocumentLayout.tsx +0 -12
- package/src/assistDocument/RequestRunInstructionProvider.tsx +0 -61
- package/src/assistDocument/components/AssistDocumentForm.tsx +0 -286
- package/src/assistDocument/components/AssistTypeContext.tsx +0 -7
- package/src/assistDocument/components/FieldRefPreview.tsx +0 -26
- package/src/assistDocument/components/InstructionsArrayField.tsx +0 -8
- package/src/assistDocument/components/InstructionsArrayInput.tsx +0 -27
- package/src/assistDocument/components/SelectedFieldContext.tsx +0 -10
- package/src/assistDocument/components/generic/HiddenFieldTitle.tsx +0 -5
- package/src/assistDocument/components/helpers.ts +0 -21
- package/src/assistDocument/components/instruction/BackToInstructionsLink.tsx +0 -32
- package/src/assistDocument/components/instruction/FieldRefInput.tsx +0 -54
- package/src/assistDocument/components/instruction/InstructionInput.tsx +0 -89
- package/src/assistDocument/components/instruction/InstructionOutputField.tsx +0 -46
- package/src/assistDocument/components/instruction/InstructionOutputInput.tsx +0 -206
- package/src/assistDocument/components/instruction/PromptInput.tsx +0 -59
- package/src/assistDocument/components/instruction/appearance/IconInput.tsx +0 -46
- package/src/assistDocument/components/instruction/appearance/InstructionVisibility.tsx +0 -37
- package/src/assistDocument/hooks/useAssistDocumentContextValue.tsx +0 -129
- package/src/assistDocument/hooks/useDocumentState.ts +0 -6
- package/src/assistDocument/hooks/useInstructionToaster.tsx +0 -75
- package/src/assistDocument/hooks/useStudioAssistDocument.ts +0 -99
- package/src/assistDocument/index.ts +0 -1
- package/src/assistFormComponents/AssistField.tsx +0 -63
- package/src/assistFormComponents/AssistFormBlock.tsx +0 -31
- package/src/assistFormComponents/AssistInlineFormBlock.tsx +0 -13
- package/src/assistFormComponents/AssistItem.tsx +0 -21
- package/src/assistFormComponents/validation/listItem.tsx +0 -63
- package/src/assistFormComponents/validation/validationList.tsx +0 -90
- package/src/assistInspector/AssistInspector.tsx +0 -423
- package/src/assistInspector/FieldAutocomplete.tsx +0 -146
- package/src/assistInspector/InstructionTaskHistoryButton.tsx +0 -262
- package/src/assistInspector/constants.ts +0 -1
- package/src/assistInspector/helpers.ts +0 -211
- package/src/assistInspector/index.ts +0 -27
- package/src/assistLayout/AiAssistanceConfigContext.tsx +0 -32
- package/src/assistLayout/AiAssistanceConfigProvider.tsx +0 -98
- package/src/assistLayout/AssistLayout.tsx +0 -39
- package/src/assistLayout/RunInstructionProvider.tsx +0 -278
- package/src/assistLayout/fieldRefCache.tsx +0 -34
- package/src/assistTypes.ts +0 -83
- package/src/components/AssistFeatureBadge.tsx +0 -9
- package/src/components/FadeInContent.tsx +0 -40
- package/src/components/HideReferenceChangedBannerInput.tsx +0 -25
- package/src/components/ImageContext.tsx +0 -85
- package/src/components/SafeValueInput.tsx +0 -74
- package/src/components/TimeAgo.tsx +0 -18
- package/src/constants.ts +0 -20
- package/src/fieldActions/PrivateIcon.tsx +0 -20
- package/src/fieldActions/assistFieldActions.tsx +0 -320
- package/src/fieldActions/customFieldActions.tsx +0 -333
- package/src/fieldActions/generateCaptionActions.tsx +0 -77
- package/src/fieldActions/generateImageActions.tsx +0 -58
- package/src/fieldActions/useUserInput.ts +0 -107
- package/src/globals.d.ts +0 -4
- package/src/helpers/assistSupported.ts +0 -49
- package/src/helpers/conditionalMembers.test.ts +0 -319
- package/src/helpers/conditionalMembers.ts +0 -134
- package/src/helpers/ids.test.ts +0 -28
- package/src/helpers/ids.ts +0 -23
- package/src/helpers/misc.ts +0 -25
- package/src/helpers/styleguide.ts +0 -24
- package/src/helpers/typeUtils.ts +0 -60
- package/src/helpers/useAssistSupported.ts +0 -8
- package/src/index.ts +0 -26
- package/src/onboarding/FirstAssistedPathProvider.tsx +0 -30
- package/src/onboarding/InspectorOnboarding.tsx +0 -47
- package/src/onboarding/onboardingStore.ts +0 -32
- package/src/plugin.tsx +0 -162
- package/src/presence/AiFieldPresence.tsx +0 -28
- package/src/presence/AssistAvatar.tsx +0 -96
- package/src/presence/AssistDocumentPresence.tsx +0 -50
- package/src/presence/useAssistPresence.ts +0 -64
- package/src/schemas/assistDocumentSchema.tsx +0 -497
- package/src/schemas/contextDocumentSchema.tsx +0 -57
- package/src/schemas/index.ts +0 -69
- package/src/schemas/serialize/SchemTypeTool.tsx +0 -103
- package/src/schemas/serialize/schemaUtils.ts +0 -38
- package/src/schemas/serialize/serializeSchema.test.ts +0 -819
- package/src/schemas/serialize/serializeSchema.ts +0 -224
- package/src/schemas/serializedSchemaTypeSchema.ts +0 -60
- package/src/schemas/typeDefExtensions.ts +0 -127
- package/src/translate/FieldTranslationProvider.tsx +0 -382
- package/src/translate/getLanguageParams.ts +0 -26
- package/src/translate/languageStore.ts +0 -18
- package/src/translate/paths.test.ts +0 -181
- package/src/translate/paths.ts +0 -183
- package/src/translate/translateActions.tsx +0 -205
- package/src/translate/types.ts +0 -197
- package/src/types.ts +0 -220
- package/src/useApiClient.ts +0 -338
- package/v2-incompatible.js +0 -11
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
import {ControlsIcon, SparklesIcon} from '@sanity/icons'
|
|
2
|
-
import {useCallback, useMemo, useRef} from 'react'
|
|
3
|
-
import {
|
|
4
|
-
type DocumentFieldAction,
|
|
5
|
-
type DocumentFieldActionGroup,
|
|
6
|
-
type DocumentFieldActionItem,
|
|
7
|
-
pathToString,
|
|
8
|
-
stringToPath,
|
|
9
|
-
typed,
|
|
10
|
-
useCurrentUser,
|
|
11
|
-
} from 'sanity'
|
|
12
|
-
import {useDocumentPane} from 'sanity/structure'
|
|
13
|
-
|
|
14
|
-
import {useAssistDocumentContext} from '../assistDocument/AssistDocumentContext'
|
|
15
|
-
import {getIcon} from '../assistDocument/components/instruction/appearance/IconInput'
|
|
16
|
-
import {useRequestRunInstruction} from '../assistDocument/RequestRunInstructionProvider'
|
|
17
|
-
import {aiInspectorId} from '../assistInspector/constants'
|
|
18
|
-
import {getTypePath, useSelectedField, useTypePath} from '../assistInspector/helpers'
|
|
19
|
-
import {pluginTitleShort} from '../constants'
|
|
20
|
-
import {isSchemaAssistEnabled} from '../helpers/assistSupported'
|
|
21
|
-
import {getConditionalMembers} from '../helpers/conditionalMembers'
|
|
22
|
-
import {getInstructionTitle, usePathKey} from '../helpers/misc'
|
|
23
|
-
import {useAssistSupported} from '../helpers/useAssistSupported'
|
|
24
|
-
import {translateActions, type TranslateProps} from '../translate/translateActions'
|
|
25
|
-
import {documentRootKey, fieldPathParam, instructionParam, type StudioInstruction} from '../types'
|
|
26
|
-
import {generateCaptionsActions} from './generateCaptionActions'
|
|
27
|
-
import {generateImagActions} from './generateImageActions'
|
|
28
|
-
import {PrivateIcon} from './PrivateIcon'
|
|
29
|
-
import {AgentActionConditionalPath, useCustomFieldActions} from './customFieldActions'
|
|
30
|
-
import {AgentActionPath} from '@sanity/client/stega'
|
|
31
|
-
|
|
32
|
-
function node(node: DocumentFieldActionItem | DocumentFieldActionGroup) {
|
|
33
|
-
return node
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const assistFieldActions: DocumentFieldAction = {
|
|
37
|
-
name: 'sanity-assist-actions',
|
|
38
|
-
useAction(props) {
|
|
39
|
-
const {schemaType} = props
|
|
40
|
-
|
|
41
|
-
const {
|
|
42
|
-
assistDocument,
|
|
43
|
-
documentIsNew,
|
|
44
|
-
documentIsAssistable,
|
|
45
|
-
openInspector,
|
|
46
|
-
closeInspector,
|
|
47
|
-
inspector,
|
|
48
|
-
documentOnChange,
|
|
49
|
-
documentSchemaType,
|
|
50
|
-
selectedPath,
|
|
51
|
-
assistableDocumentId,
|
|
52
|
-
fieldRefsByTypePath,
|
|
53
|
-
} = useAssistDocumentContext()
|
|
54
|
-
|
|
55
|
-
const {value: docValue, formState} = useDocumentPane()
|
|
56
|
-
const docValueRef = useRef(docValue)
|
|
57
|
-
const formStateRef = useRef(formState)
|
|
58
|
-
formStateRef.current = formState
|
|
59
|
-
|
|
60
|
-
const currentUser = useCurrentUser()
|
|
61
|
-
const isHidden = !assistDocument
|
|
62
|
-
const pathKey = usePathKey(props.path)
|
|
63
|
-
const typePath = useTypePath(docValue, pathKey)
|
|
64
|
-
const assistDocumentId = assistDocument?._id
|
|
65
|
-
|
|
66
|
-
const {requestRunInstruction} = useRequestRunInstruction({
|
|
67
|
-
documentOnChange,
|
|
68
|
-
isDocAssistable: documentIsAssistable ?? false,
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
const isSelectable = !!useSelectedField(documentSchemaType, typePath)
|
|
72
|
-
const assistSupported =
|
|
73
|
-
useAssistSupported(props.path, schemaType) &&
|
|
74
|
-
isSelectable &&
|
|
75
|
-
isSchemaAssistEnabled(documentSchemaType) &&
|
|
76
|
-
schemaType.readOnly !== true
|
|
77
|
-
|
|
78
|
-
const fieldAssist = useMemo(
|
|
79
|
-
() =>
|
|
80
|
-
(assistDocument?.fields ?? []).find(
|
|
81
|
-
(f) => f.path === typePath || (pathKey === documentRootKey && f.path === pathKey),
|
|
82
|
-
),
|
|
83
|
-
[assistDocument?.fields, pathKey, typePath],
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
const fieldAssistKey = fieldAssist?._key
|
|
87
|
-
const isInspectorOpen = inspector?.name === aiInspectorId
|
|
88
|
-
const isPathSelected = pathKey === selectedPath
|
|
89
|
-
const isSelected = isInspectorOpen && isPathSelected
|
|
90
|
-
|
|
91
|
-
const imageCaptionAction = generateCaptionsActions.useAction(props)
|
|
92
|
-
const imageGenAction = generateImagActions.useAction(props)
|
|
93
|
-
const translateAction = translateActions.useAction(
|
|
94
|
-
typed<TranslateProps>({
|
|
95
|
-
...props,
|
|
96
|
-
documentId: assistableDocumentId,
|
|
97
|
-
documentIsAssistable,
|
|
98
|
-
documentSchemaType,
|
|
99
|
-
}),
|
|
100
|
-
)
|
|
101
|
-
const manageInstructions = useCallback(
|
|
102
|
-
() =>
|
|
103
|
-
isSelected
|
|
104
|
-
? closeInspector(aiInspectorId)
|
|
105
|
-
: openInspector(aiInspectorId, {
|
|
106
|
-
[fieldPathParam]: pathKey,
|
|
107
|
-
[instructionParam]: undefined as any,
|
|
108
|
-
}),
|
|
109
|
-
[openInspector, closeInspector, isSelected, pathKey],
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
const onInstructionAction = useCallback(
|
|
113
|
-
(instruction: StudioInstruction) => {
|
|
114
|
-
if (!pathKey || !fieldAssistKey || !assistDocumentId || !assistableDocumentId) {
|
|
115
|
-
return
|
|
116
|
-
}
|
|
117
|
-
requestRunInstruction({
|
|
118
|
-
documentId: assistableDocumentId,
|
|
119
|
-
assistDocumentId,
|
|
120
|
-
path: pathKey,
|
|
121
|
-
typePath,
|
|
122
|
-
instruction,
|
|
123
|
-
conditionalMembers: formStateRef.current
|
|
124
|
-
? getConditionalMembers(formStateRef.current)
|
|
125
|
-
: [],
|
|
126
|
-
})
|
|
127
|
-
},
|
|
128
|
-
[
|
|
129
|
-
requestRunInstruction,
|
|
130
|
-
assistableDocumentId,
|
|
131
|
-
pathKey,
|
|
132
|
-
typePath,
|
|
133
|
-
assistDocumentId,
|
|
134
|
-
fieldAssistKey,
|
|
135
|
-
],
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
const privateInstructions = useMemo(
|
|
139
|
-
() =>
|
|
140
|
-
fieldAssist?.instructions?.filter((i) => i.userId && i.userId === currentUser?.id) || [],
|
|
141
|
-
[fieldAssist?.instructions, currentUser],
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
const sharedInstructions = useMemo(
|
|
145
|
-
() => fieldAssist?.instructions?.filter((i) => !i.userId) || [],
|
|
146
|
-
[fieldAssist?.instructions],
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
const instructions = useMemo(
|
|
150
|
-
() => [...privateInstructions, ...sharedInstructions],
|
|
151
|
-
[privateInstructions, sharedInstructions],
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
const runInstructionsGroup = useMemo(() => {
|
|
155
|
-
return instructions?.length || imageCaptionAction || translateAction || imageGenAction
|
|
156
|
-
? node({
|
|
157
|
-
type: 'group',
|
|
158
|
-
icon: () => null,
|
|
159
|
-
title: 'Run instructions',
|
|
160
|
-
children: [
|
|
161
|
-
...(instructions?.map((instruction) =>
|
|
162
|
-
instructionItem({
|
|
163
|
-
instruction,
|
|
164
|
-
isPrivate: Boolean(instruction.userId && instruction.userId === currentUser?.id),
|
|
165
|
-
onInstructionAction,
|
|
166
|
-
hidden: isHidden,
|
|
167
|
-
documentIsNew: !!documentIsNew,
|
|
168
|
-
assistSupported,
|
|
169
|
-
}),
|
|
170
|
-
) || []),
|
|
171
|
-
imageCaptionAction,
|
|
172
|
-
imageGenAction,
|
|
173
|
-
].filter((a): a is DocumentFieldActionItem => !!a),
|
|
174
|
-
expanded: true,
|
|
175
|
-
})
|
|
176
|
-
: undefined
|
|
177
|
-
}, [
|
|
178
|
-
instructions,
|
|
179
|
-
currentUser?.id,
|
|
180
|
-
onInstructionAction,
|
|
181
|
-
isHidden,
|
|
182
|
-
documentIsNew,
|
|
183
|
-
assistSupported,
|
|
184
|
-
imageCaptionAction,
|
|
185
|
-
translateAction,
|
|
186
|
-
imageGenAction,
|
|
187
|
-
])
|
|
188
|
-
|
|
189
|
-
const getDocumentValue = useCallback(() => {
|
|
190
|
-
return docValueRef.current
|
|
191
|
-
}, [])
|
|
192
|
-
|
|
193
|
-
const getConditionalPaths: () => AgentActionConditionalPath[] = useCallback(() => {
|
|
194
|
-
return (formStateRef.current ? getConditionalMembers(formStateRef.current) : []).flatMap(
|
|
195
|
-
(cm) => {
|
|
196
|
-
const path = stringToPath(cm.path)
|
|
197
|
-
if (path.some((s) => typeof s === 'number')) {
|
|
198
|
-
//agent actions does not support indexed paths
|
|
199
|
-
return []
|
|
200
|
-
}
|
|
201
|
-
return {
|
|
202
|
-
...cm,
|
|
203
|
-
path: path as AgentActionPath,
|
|
204
|
-
}
|
|
205
|
-
},
|
|
206
|
-
)
|
|
207
|
-
}, [])
|
|
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
|
-
|
|
220
|
-
const customActions = useCustomFieldActions({
|
|
221
|
-
actionType: props.path.length ? 'field' : 'document',
|
|
222
|
-
documentIdForAction: assistableDocumentId,
|
|
223
|
-
schemaType,
|
|
224
|
-
documentSchemaType,
|
|
225
|
-
path: props.path,
|
|
226
|
-
getDocumentValue,
|
|
227
|
-
getConditionalPaths,
|
|
228
|
-
parentSchemaType,
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
const manageInstructionsItem = useMemo(
|
|
232
|
-
() =>
|
|
233
|
-
node({
|
|
234
|
-
type: 'action',
|
|
235
|
-
icon: ControlsIcon,
|
|
236
|
-
title: 'Manage instructions',
|
|
237
|
-
onAction: manageInstructions,
|
|
238
|
-
selected: isSelected,
|
|
239
|
-
}),
|
|
240
|
-
[manageInstructions, isSelected],
|
|
241
|
-
)
|
|
242
|
-
|
|
243
|
-
const group = useMemo(
|
|
244
|
-
() =>
|
|
245
|
-
node({
|
|
246
|
-
type: 'group',
|
|
247
|
-
icon: SparklesIcon,
|
|
248
|
-
title: pluginTitleShort,
|
|
249
|
-
children: [
|
|
250
|
-
runInstructionsGroup,
|
|
251
|
-
translateAction,
|
|
252
|
-
...customActions,
|
|
253
|
-
assistSupported && manageInstructionsItem,
|
|
254
|
-
]
|
|
255
|
-
.filter((c): c is DocumentFieldActionItem | DocumentFieldActionGroup => !!c)
|
|
256
|
-
.filter((c) => (c.type === 'group' ? c.children.length : true)),
|
|
257
|
-
expanded: false,
|
|
258
|
-
renderAsButton: true,
|
|
259
|
-
hidden: !assistSupported && !imageCaptionAction && !translateAction && !imageGenAction,
|
|
260
|
-
}),
|
|
261
|
-
[
|
|
262
|
-
//documentIsNew,
|
|
263
|
-
runInstructionsGroup,
|
|
264
|
-
manageInstructionsItem,
|
|
265
|
-
assistSupported,
|
|
266
|
-
imageCaptionAction,
|
|
267
|
-
translateAction,
|
|
268
|
-
imageGenAction,
|
|
269
|
-
customActions,
|
|
270
|
-
],
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
const emptyAction = useMemo(
|
|
274
|
-
() =>
|
|
275
|
-
node({
|
|
276
|
-
type: 'action',
|
|
277
|
-
hidden: !assistSupported,
|
|
278
|
-
icon: SparklesIcon,
|
|
279
|
-
onAction: manageInstructions,
|
|
280
|
-
renderAsButton: true,
|
|
281
|
-
title: pluginTitleShort,
|
|
282
|
-
selected: isSelected,
|
|
283
|
-
}),
|
|
284
|
-
[assistSupported, manageInstructions, isSelected],
|
|
285
|
-
)
|
|
286
|
-
|
|
287
|
-
// If there are no instructions, we don't want to render the group
|
|
288
|
-
if (
|
|
289
|
-
!instructions?.length &&
|
|
290
|
-
!imageCaptionAction &&
|
|
291
|
-
!translateAction &&
|
|
292
|
-
!imageGenAction &&
|
|
293
|
-
!customActions.length
|
|
294
|
-
) {
|
|
295
|
-
return emptyAction
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return group
|
|
299
|
-
},
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
function instructionItem(props: {
|
|
303
|
-
instruction: StudioInstruction
|
|
304
|
-
isPrivate: boolean
|
|
305
|
-
onInstructionAction: (ins: StudioInstruction) => void
|
|
306
|
-
assistSupported: boolean
|
|
307
|
-
documentIsNew: boolean
|
|
308
|
-
hidden: boolean
|
|
309
|
-
}) {
|
|
310
|
-
const {hidden, isPrivate, onInstructionAction, assistSupported, instruction} = props
|
|
311
|
-
return node({
|
|
312
|
-
type: 'action',
|
|
313
|
-
icon: getIcon(instruction.icon),
|
|
314
|
-
iconRight: isPrivate ? PrivateIcon : undefined,
|
|
315
|
-
title: getInstructionTitle(instruction),
|
|
316
|
-
onAction: () => onInstructionAction(instruction),
|
|
317
|
-
disabled: !assistSupported,
|
|
318
|
-
hidden,
|
|
319
|
-
})
|
|
320
|
-
}
|
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DocumentFieldActionDivider,
|
|
3
|
-
DocumentFieldActionGroup,
|
|
4
|
-
DocumentFieldActionItem,
|
|
5
|
-
DocumentFieldActionNode,
|
|
6
|
-
ObjectSchemaType,
|
|
7
|
-
Path,
|
|
8
|
-
SanityDocumentLike,
|
|
9
|
-
SchemaType,
|
|
10
|
-
useWorkspaceSchemaId,
|
|
11
|
-
} from 'sanity'
|
|
12
|
-
import {useMemo} from 'react'
|
|
13
|
-
import {useAiAssistanceConfig} from '../assistLayout/AiAssistanceConfigContext'
|
|
14
|
-
import {ToastParams, useToast} from '@sanity/ui'
|
|
15
|
-
import {AgentActionPath} from '@sanity/client/stega'
|
|
16
|
-
import {useAssistDocumentContext} from '../assistDocument/AssistDocumentContext'
|
|
17
|
-
import {
|
|
18
|
-
documentRootKey,
|
|
19
|
-
fieldPresenceTypeName,
|
|
20
|
-
InstructionTask,
|
|
21
|
-
instructionTaskTypeName,
|
|
22
|
-
} from '../types'
|
|
23
|
-
import {randomKey} from '../_lib/randomKey'
|
|
24
|
-
import {isDefined} from '../helpers/misc'
|
|
25
|
-
|
|
26
|
-
export interface AgentActionConditionalPath {
|
|
27
|
-
path: AgentActionPath
|
|
28
|
-
readOnly: boolean
|
|
29
|
-
hidden: boolean
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface AssistFieldActionProps {
|
|
33
|
-
/**
|
|
34
|
-
* `actionType` will be `document` for action invoked from the top right document action menu, and
|
|
35
|
-
* `field` when invoked from a field action menu.
|
|
36
|
-
*/
|
|
37
|
-
actionType: 'document' | 'field'
|
|
38
|
-
/**
|
|
39
|
-
* This is the id of the current document pane; it contains `drafts.`or `versions. prefix` ect depending on context.
|
|
40
|
-
* Use this for `documentId` when calling any `client.agent.action`.
|
|
41
|
-
*
|
|
42
|
-
* It is generally recommended to call actions from the studio like this:
|
|
43
|
-
* ```ts
|
|
44
|
-
* await client.agent.action.generate({
|
|
45
|
-
* targetDocument: {
|
|
46
|
-
* operation: 'createIfNotExists',
|
|
47
|
-
* _id: props.documentIdForAction,
|
|
48
|
-
* _type: props.documentSchemaType.name,
|
|
49
|
-
* initialValues: props.getDocumentValue()
|
|
50
|
-
* },
|
|
51
|
-
* //...
|
|
52
|
-
* })
|
|
53
|
-
* ```
|
|
54
|
-
*/
|
|
55
|
-
documentIdForAction: string
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Schema type of the current document.
|
|
59
|
-
* @see documentIdForAction
|
|
60
|
-
*/
|
|
61
|
-
documentSchemaType: ObjectSchemaType
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Returns the current document value.
|
|
65
|
-
*
|
|
66
|
-
* Prefer passing this function to your hooks instead of passing the document value directly to avoid unnecessary re-renders.
|
|
67
|
-
* @see documentIdForAction
|
|
68
|
-
*/
|
|
69
|
-
getDocumentValue: () => SanityDocumentLike
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Returns the current readOnly and hidden state of all conditional members in the current document form.
|
|
73
|
-
*
|
|
74
|
-
* Intended to be passed to agent actions `conditionalPaths.paths`.
|
|
75
|
-
*/
|
|
76
|
-
getConditionalPaths: () => AgentActionConditionalPath[]
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* `schemaId` for the current workspace.
|
|
80
|
-
*
|
|
81
|
-
* Note: the workspace schema has to be deployed using `sanity schema deploy` or `sanity deploy`.
|
|
82
|
-
*
|
|
83
|
-
* Use this for `schemaId` when calling any `client.agent.action`.
|
|
84
|
-
*
|
|
85
|
-
* It is generally recommended to call actions from the studio like this:
|
|
86
|
-
* ```ts
|
|
87
|
-
* await client.agent.action.generate({
|
|
88
|
-
* targetDocument: {
|
|
89
|
-
* operation: 'createIfNotExists',
|
|
90
|
-
* _id: props.documentIdForAction,
|
|
91
|
-
* _type: props.documentSchemaType.name,
|
|
92
|
-
* initialValues: props.getDocumentValue()
|
|
93
|
-
* },
|
|
94
|
-
* //...
|
|
95
|
-
* })
|
|
96
|
-
*
|
|
97
|
-
* ```
|
|
98
|
-
*/
|
|
99
|
-
schemaId: string
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* This is the schema type of the field the actions will be attached to (ie, schemaType for `path`)
|
|
103
|
-
*
|
|
104
|
-
* It can be used with agent actions using `target.path`, to scope the action to a specific field.
|
|
105
|
-
*
|
|
106
|
-
* It is generally recommended to call actions from the studio like this:
|
|
107
|
-
* ```ts
|
|
108
|
-
* await client.agent.action.generate({
|
|
109
|
-
* targetDocument: {
|
|
110
|
-
* operation: 'createIfNotExists',
|
|
111
|
-
* _id: props.documentIdForAction,
|
|
112
|
-
* _type: props.documentSchemaType.name,
|
|
113
|
-
* initialValues: props.getDocumentValue()
|
|
114
|
-
* },
|
|
115
|
-
* target: {
|
|
116
|
-
* path: props.path
|
|
117
|
-
* },
|
|
118
|
-
* })
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
|
-
path: AgentActionPath
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* This is the schema type of the field the actions will be attached to (ie, schemaType for `path`).
|
|
125
|
-
*
|
|
126
|
-
* Typically useful to dynamically return different actions based on the schema type of the field.
|
|
127
|
-
*
|
|
128
|
-
* ```ts
|
|
129
|
-
* if(isObjectSchemaType(schemaType)) {
|
|
130
|
-
* return [
|
|
131
|
-
* defineAssistFieldAction({
|
|
132
|
-
* title: 'Fill the object fields',
|
|
133
|
-
* icon: RobotIcon,
|
|
134
|
-
* onAction: () => {
|
|
135
|
-
* //...
|
|
136
|
-
* }
|
|
137
|
-
* })
|
|
138
|
-
* ]
|
|
139
|
-
* }
|
|
140
|
-
* return useMemo(() => {
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* }, [])
|
|
144
|
-
*
|
|
145
|
-
* ```
|
|
146
|
-
*/
|
|
147
|
-
schemaType: SchemaType
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Schema type of the parent field or array item holding this field.
|
|
151
|
-
*
|
|
152
|
-
* This can be undefined if the action was unable to resolve the parent type is excluded from AI Assist.
|
|
153
|
-
*
|
|
154
|
-
* @see schemaType
|
|
155
|
-
* @see documentSchemaType
|
|
156
|
-
*/
|
|
157
|
-
parentSchemaType?: SchemaType
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export type AssistFieldActionNode =
|
|
161
|
-
| AssistFieldActionItem
|
|
162
|
-
| AssistFieldActionGroup
|
|
163
|
-
| DocumentFieldActionDivider
|
|
164
|
-
|
|
165
|
-
export type AssistFieldActionItem = Omit<
|
|
166
|
-
DocumentFieldActionItem,
|
|
167
|
-
'renderAsButton' | 'selected' | 'onAction'
|
|
168
|
-
> & {
|
|
169
|
-
onAction: () => void | Promise<void>
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export type AssistFieldActionGroup = Omit<
|
|
173
|
-
DocumentFieldActionGroup,
|
|
174
|
-
'renderAsButton' | 'expanded' | 'children'
|
|
175
|
-
> & {
|
|
176
|
-
/**
|
|
177
|
-
* `children` can include undefined entries in the action array. These will be filtered out.
|
|
178
|
-
* If the group has no defined children, the group will also be filtered out.
|
|
179
|
-
*/
|
|
180
|
-
children: (AssistFieldActionNode | undefined)[]
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
type PushToast = (params: ToastParams) => string
|
|
184
|
-
|
|
185
|
-
export function defineAssistFieldAction(
|
|
186
|
-
action: Omit<AssistFieldActionItem, 'type'>,
|
|
187
|
-
): AssistFieldActionItem {
|
|
188
|
-
return {
|
|
189
|
-
...action,
|
|
190
|
-
type: 'action',
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export function defineFieldActionDivider(): DocumentFieldActionDivider {
|
|
195
|
-
return {
|
|
196
|
-
type: 'divider',
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export function defineAssistFieldActionGroup(
|
|
201
|
-
group: Omit<AssistFieldActionGroup, 'type'>,
|
|
202
|
-
): AssistFieldActionGroup {
|
|
203
|
-
return {
|
|
204
|
-
...group,
|
|
205
|
-
type: 'group',
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export function useCustomFieldActions(
|
|
210
|
-
props: Omit<AssistFieldActionProps, 'schemaId' | 'path'> & {path: Path},
|
|
211
|
-
) {
|
|
212
|
-
const {
|
|
213
|
-
config: {fieldActions},
|
|
214
|
-
} = useAiAssistanceConfig()
|
|
215
|
-
const {addSyntheticTask, removeSyntheticTask} = useAssistDocumentContext()
|
|
216
|
-
|
|
217
|
-
const schemaId = useWorkspaceSchemaId()
|
|
218
|
-
const {push: pushToast} = useToast()
|
|
219
|
-
const configActions = fieldActions?.useFieldActions?.({
|
|
220
|
-
...props,
|
|
221
|
-
schemaId,
|
|
222
|
-
path: props.path as AgentActionPath,
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
return useMemo(() => {
|
|
226
|
-
const title = fieldActions?.title
|
|
227
|
-
const customActions = configActions
|
|
228
|
-
?.filter(isDefined)
|
|
229
|
-
.map((node) => {
|
|
230
|
-
return createSafeNode({
|
|
231
|
-
node,
|
|
232
|
-
pushToast,
|
|
233
|
-
addSyntheticTask,
|
|
234
|
-
removeSyntheticTask,
|
|
235
|
-
})
|
|
236
|
-
})
|
|
237
|
-
.filter(isDefined)
|
|
238
|
-
const onlyGroups =
|
|
239
|
-
customActions?.length && customActions?.every((node) => node.type === 'group')
|
|
240
|
-
const groups = customActions?.length
|
|
241
|
-
? onlyGroups
|
|
242
|
-
? customActions
|
|
243
|
-
: [
|
|
244
|
-
{
|
|
245
|
-
type: 'group',
|
|
246
|
-
title: title || 'Custom actions',
|
|
247
|
-
children: customActions,
|
|
248
|
-
expanded: true,
|
|
249
|
-
} satisfies DocumentFieldActionGroup,
|
|
250
|
-
]
|
|
251
|
-
: []
|
|
252
|
-
return groups ?? []
|
|
253
|
-
}, [configActions, fieldActions, pushToast])
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function createSafeNode(args: {
|
|
257
|
-
node: AssistFieldActionNode
|
|
258
|
-
pushToast: PushToast
|
|
259
|
-
addSyntheticTask: (task: InstructionTask) => void
|
|
260
|
-
removeSyntheticTask: (task: InstructionTask) => void
|
|
261
|
-
}): DocumentFieldActionNode | undefined {
|
|
262
|
-
const {node} = args
|
|
263
|
-
switch (node.type) {
|
|
264
|
-
case 'action':
|
|
265
|
-
return createSafeAction({...args, action: node})
|
|
266
|
-
case 'group':
|
|
267
|
-
// eslint-disable-next-line no-case-declarations
|
|
268
|
-
const children = node.children
|
|
269
|
-
?.filter(isDefined)
|
|
270
|
-
.map((child) => createSafeNode({...args, node: child}))
|
|
271
|
-
.filter(isDefined)
|
|
272
|
-
if (!children?.length) {
|
|
273
|
-
return undefined
|
|
274
|
-
}
|
|
275
|
-
return {
|
|
276
|
-
...node,
|
|
277
|
-
renderAsButton: false,
|
|
278
|
-
expanded: true,
|
|
279
|
-
children,
|
|
280
|
-
}
|
|
281
|
-
case 'divider':
|
|
282
|
-
default:
|
|
283
|
-
return node
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function createSafeAction(args: {
|
|
288
|
-
action: AssistFieldActionItem
|
|
289
|
-
pushToast: PushToast
|
|
290
|
-
addSyntheticTask: (task: InstructionTask) => void
|
|
291
|
-
removeSyntheticTask: (task: InstructionTask) => void
|
|
292
|
-
}) {
|
|
293
|
-
const {action, pushToast, addSyntheticTask, removeSyntheticTask} = args
|
|
294
|
-
return {
|
|
295
|
-
...action,
|
|
296
|
-
onAction: () => {
|
|
297
|
-
async function runAction() {
|
|
298
|
-
const task: InstructionTask = {
|
|
299
|
-
_type: instructionTaskTypeName,
|
|
300
|
-
_key: randomKey(12),
|
|
301
|
-
started: new Date().toISOString(),
|
|
302
|
-
presence: [
|
|
303
|
-
{
|
|
304
|
-
_type: fieldPresenceTypeName,
|
|
305
|
-
_key: randomKey(12),
|
|
306
|
-
path: documentRootKey,
|
|
307
|
-
started: new Date().toISOString(),
|
|
308
|
-
},
|
|
309
|
-
],
|
|
310
|
-
}
|
|
311
|
-
try {
|
|
312
|
-
addSyntheticTask(task)
|
|
313
|
-
const actionResult = action.onAction?.()
|
|
314
|
-
if (actionResult instanceof Promise) {
|
|
315
|
-
await actionResult
|
|
316
|
-
}
|
|
317
|
-
} catch (err: any) {
|
|
318
|
-
console.error('Failed to execute action', action, err)
|
|
319
|
-
pushToast({
|
|
320
|
-
title: 'Failed to execute action',
|
|
321
|
-
description: err?.message,
|
|
322
|
-
status: 'error',
|
|
323
|
-
})
|
|
324
|
-
} finally {
|
|
325
|
-
removeSyntheticTask(task)
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
runAction()
|
|
329
|
-
},
|
|
330
|
-
renderAsButton: false,
|
|
331
|
-
selected: false,
|
|
332
|
-
}
|
|
333
|
-
}
|