Skip to content

Commit c5baba3

Browse files
feat: add promptAI action
1 parent 280f6fc commit c5baba3

File tree

12 files changed

+187
-4
lines changed

12 files changed

+187
-4
lines changed

packages/demo/src/components/NonModalView.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { AssetSelector } from './AssetSelector'
66
import { ContextRequester } from './ContextRequester'
77
import { PluginComponent } from './FieldPluginDemo'
88
import { LanguageView } from './LanguageView'
9+
import { PromptAI } from './PromptAI'
910

1011
export const NonModalView: PluginComponent = (props) => (
1112
<Paper>
@@ -17,6 +18,7 @@ export const NonModalView: PluginComponent = (props) => (
1718
<ContextRequester {...props} />
1819
<HeightChangeDemo {...props} />
1920
<LanguageView {...props} />
21+
<PromptAI {...props} />
2022
</Stack>
2123
</Paper>
2224
)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import {
2+
Button,
3+
MenuItem,
4+
Select,
5+
Stack,
6+
TextField,
7+
Typography,
8+
} from '@mui/material'
9+
import { useState } from 'react'
10+
import {
11+
promptAIActionsList,
12+
type PromptAIAction,
13+
} from '@storyblok/field-plugin'
14+
import type { PluginComponent } from './FieldPluginDemo'
15+
16+
export const PromptAI: PluginComponent = (props) => {
17+
const { actions } = props
18+
19+
const [promptQuestion, setPromptQuestion] = useState<string>('')
20+
const [promptType, setPromptType] = useState<PromptAIAction>('prompt')
21+
const [promptOutput, setPromptOutput] = useState<string>('')
22+
23+
return (
24+
<Stack
25+
gap={2}
26+
direction={'column'}
27+
>
28+
<Typography variant="subtitle1">Prompt AI</Typography>
29+
<Stack gap={2}>
30+
<TextField
31+
label="Ask a question"
32+
onChange={(e) => setPromptQuestion(e.target.value)}
33+
required
34+
/>
35+
<Select
36+
value={promptType}
37+
onChange={(e) => setPromptType(e.target.value as PromptAIAction)}
38+
>
39+
{promptAIActionsList.map((promptAIAction) => (
40+
<MenuItem
41+
key={promptAIAction}
42+
value={promptAIAction}
43+
>
44+
{promptAIAction}
45+
</MenuItem>
46+
))}
47+
</Select>
48+
<Typography>Output: {promptOutput}</Typography>
49+
<Button
50+
variant="outlined"
51+
color="secondary"
52+
onClick={async () =>
53+
setPromptOutput(
54+
await actions.promptAI({
55+
action: promptType,
56+
text: promptQuestion,
57+
}),
58+
)
59+
}
60+
>
61+
Prompt
62+
</Button>
63+
</Stack>
64+
</Stack>
65+
)
66+
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Asset, StoryData } from '../messaging'
2-
import { FieldPluginData } from './FieldPluginData'
1+
import type { FieldPluginData } from './FieldPluginData'
2+
import type { Asset, PromptAIPayload, StoryData } from '../messaging'
33

44
export type SetContent<Content> = (
55
content: Content,
@@ -8,12 +8,14 @@ export type SetModalOpen<Content> = (
88
isModalOpen: boolean,
99
) => Promise<FieldPluginData<Content>>
1010
export type RequestContext = () => Promise<StoryData>
11+
export type PromptAI = (payload: PromptAIPayload) => Promise<string>
1112
export type SelectAsset = () => Promise<Asset>
1213
export type Initialize<Content> = () => Promise<FieldPluginData<Content>>
1314

1415
export type FieldPluginActions<Content> = {
1516
setContent: SetContent<Content>
1617
setModalOpen: SetModalOpen<Content>
1718
requestContext: RequestContext
19+
promptAI: PromptAI
1820
selectAsset: SelectAsset
1921
}

packages/field-plugin/src/createFieldPlugin/createPluginActions/callbackQueue.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import {
1+
import type {
2+
PromptAIResponseMessage,
23
AssetSelectedMessage,
34
ContextRequestMessage,
45
LoadedMessage,
@@ -14,6 +15,7 @@ type CallbackMap = {
1415
context: Record<CallbackId, OnMessage<ContextRequestMessage>>
1516
stateChanged: Record<CallbackId, OnMessage<StateChangedMessage>>
1617
loaded: Record<CallbackId, OnMessage<LoadedMessage>>
18+
promptAI: Record<CallbackId, OnMessage<PromptAIResponseMessage>>
1719
}
1820
type CallbackType = keyof CallbackMap
1921

@@ -23,7 +25,9 @@ export const callbackQueue = () => {
2325
context: {},
2426
stateChanged: {},
2527
loaded: {},
28+
promptAI: {},
2629
}
30+
2731
const pushCallback = <T extends CallbackType>(
2832
callbackType: T,
2933
callback: CallbackMap[T][CallbackId],

packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginActions.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
assetFromAssetSelectedMessage,
55
assetModalChangeMessage,
66
getContextMessage,
7+
getResponseFromPromptAIMessage,
78
heightChangeMessage,
89
modalChangeMessage,
910
OnAssetSelectMessage,
@@ -12,7 +13,10 @@ import {
1213
OnStateChangeMessage,
1314
OnUnknownPluginMessage,
1415
pluginLoadedMessage,
16+
type PromptAIPayload,
17+
getPromptAIMessage,
1518
valueChangeMessage,
19+
OnPromptAIMessage,
1620
} from '../../messaging'
1721
import { FieldPluginActions, Initialize } from '../FieldPluginActions'
1822
import { pluginStateFromStateChangeMessage } from './partialPluginStateFromStateChangeMessage'
@@ -55,16 +59,24 @@ export const createPluginActions: CreatePluginActions = ({
5559
popCallback('stateChanged', data.callbackId)?.(data)
5660
onUpdateState(pluginStateFromStateChangeMessage(data, validateContent))
5761
}
62+
5863
const onLoaded: OnLoadedMessage = (data) => {
5964
popCallback('loaded', data.callbackId)?.(data)
6065
onUpdateState(pluginStateFromStateChangeMessage(data, validateContent))
6166
}
67+
6268
const onContextRequest: OnContextRequestMessage = (data) => {
6369
popCallback('context', data.callbackId)?.(data)
6470
}
71+
6572
const onAssetSelect: OnAssetSelectMessage = (data) => {
6673
popCallback('asset', data.callbackId)?.(data)
6774
}
75+
76+
const onPromptAI: OnPromptAIMessage = (data) => {
77+
popCallback('promptAI', data.callbackId)?.(data)
78+
}
79+
6880
const onUnknownMessage: OnUnknownPluginMessage = (data) => {
6981
// TODO remove side-effect, making functions in this file pure.
7082
// perhaps only show this message in development mode?
@@ -82,6 +94,7 @@ export const createPluginActions: CreatePluginActions = ({
8294
onLoaded,
8395
onContextRequest,
8496
onAssetSelect,
97+
onPromptAI,
8598
onUnknownMessage,
8699
}
87100

@@ -135,6 +148,16 @@ export const createPluginActions: CreatePluginActions = ({
135148
postToContainer(getContextMessage({ uid, callbackId }))
136149
})
137150
},
151+
promptAI: (promptAIMessage: PromptAIPayload) => {
152+
return new Promise((resolve) => {
153+
const callbackId = pushCallback('promptAI', (message) =>
154+
resolve(getResponseFromPromptAIMessage(message)),
155+
)
156+
postToContainer(
157+
getPromptAIMessage(promptAIMessage, { uid, callbackId }),
158+
)
159+
})
160+
},
138161
},
139162
messageCallbacks,
140163
onHeightChange,

packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginMessageListener/createPluginMessageListener.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import {
1+
import type {
22
OnAssetSelectMessage,
33
OnContextRequestMessage,
44
OnLoadedMessage,
5+
OnPromptAIMessage,
56
OnStateChangeMessage,
67
OnUnknownPluginMessage,
78
} from '../../../messaging'
@@ -12,6 +13,7 @@ export type PluginMessageCallbacks = {
1213
onLoaded: OnLoadedMessage
1314
onContextRequest: OnContextRequestMessage
1415
onAssetSelect: OnAssetSelectMessage
16+
onPromptAI: OnPromptAIMessage
1517
onUnknownMessage: OnUnknownPluginMessage
1618
}
1719

packages/field-plugin/src/createFieldPlugin/createPluginActions/createPluginMessageListener/handlePluginMessage.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
isAssetSelectedMessage,
33
isMessageToPlugin,
44
isLoadedMessage,
5+
isPromptAIMessage,
56
} from '../../../messaging'
67
import { isContextRequestMessage } from '../../../messaging'
78
import { PluginMessageCallbacks } from './createPluginMessageListener'
@@ -32,6 +33,8 @@ export const handlePluginMessage = (
3233
callbacks.onContextRequest(data)
3334
} else if (isAssetSelectedMessage(data)) {
3435
callbacks.onAssetSelect(data)
36+
} else if (isPromptAIMessage(data)) {
37+
callbacks.onPromptAI(data)
3538
} else {
3639
callbacks.onUnknownMessage(data)
3740
}

packages/field-plugin/src/messaging/pluginMessage/containerToPluginMessage/ContainerToPlugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { AssetSelectedMessage } from './AssetSelectedMessage'
33
import { ContextRequestMessage } from './ContextRequestMessage'
44
import { MessageToPlugin } from './MessageToPlugin'
55
import { StateChangedMessage } from './StateChangedMessage'
6+
import { PromptAIResponseMessage } from './PromptAIResponseMessage'
67

78
/**
89
* The plugin container's sends it's state to the plugin
@@ -11,5 +12,6 @@ export type OnMessage<Message> = (message: Message) => void
1112
export type OnStateChangeMessage = (message: StateChangedMessage) => void
1213
export type OnLoadedMessage = (message: LoadedMessage) => void
1314
export type OnAssetSelectMessage = (message: AssetSelectedMessage) => void
15+
export type OnPromptAIMessage = (message: PromptAIResponseMessage) => void
1416
export type OnContextRequestMessage = (message: ContextRequestMessage) => void
1517
export type OnUnknownPluginMessage = (message: MessageToPlugin<string>) => void
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { hasKey } from '../../../utils'
2+
import { isMessageToPlugin, type MessageToPlugin } from './MessageToPlugin'
3+
4+
/**
5+
* The object returned when calling the "prompt-ai" action.
6+
*/
7+
export type PromptAIResponseMessage = MessageToPlugin<'prompt-ai'> & {
8+
output: string
9+
}
10+
11+
export const isPromptAIMessage = (
12+
data: unknown,
13+
): data is PromptAIResponseMessage =>
14+
isMessageToPlugin(data) &&
15+
hasKey(data, 'output') &&
16+
typeof data.output === 'string'
17+
18+
export const getResponseFromPromptAIMessage = (
19+
message: PromptAIResponseMessage,
20+
): string => {
21+
const { output } = message
22+
return output
23+
}

packages/field-plugin/src/messaging/pluginMessage/containerToPluginMessage/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export * from './ContextRequestMessage'
88
export * from './MessageToPlugin'
99
export * from './StoryData'
1010
export * from './Asset'
11+
export * from './PromptAIResponseMessage'

0 commit comments

Comments
 (0)