-
Notifications
You must be signed in to change notification settings - Fork 282
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Code node generator built in to Rivet
- Loading branch information
Showing
11 changed files
with
670 additions
and
10 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { type CustomEditorDefinition, type ChartNode } from '@ironclad/rivet-core'; | ||
import { type FC } from 'react'; | ||
import { type SharedEditorProps } from './SharedEditorProps'; | ||
import { match } from 'ts-pattern'; | ||
import { CodeNodeAIAssistEditor } from './custom/CodeNodeAIAssistEditor'; | ||
|
||
export const CustomEditor: FC< | ||
SharedEditorProps & { | ||
editor: CustomEditorDefinition<ChartNode>; | ||
} | ||
> = ({ editor, ...props }) => { | ||
return match(editor.customEditorId) | ||
.with('CodeNodeAIAssist', () => <CodeNodeAIAssistEditor {...props} editor={editor} />) | ||
.otherwise(() => null); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
packages/app/src/components/editors/custom/CodeNodeAIAssistEditor.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import { useState, type FC, useMemo } from 'react'; | ||
import { type SharedEditorProps } from '../SharedEditorProps'; | ||
import { | ||
getError, | ||
type ChartNode, | ||
type CustomEditorDefinition, | ||
coreCreateProcessor, | ||
deserializeProject, | ||
type CodeNodeData, | ||
coerceType, | ||
coerceTypeOptional, | ||
} from '@ironclad/rivet-core'; | ||
import { Field } from '@atlaskit/form'; | ||
import TextField from '@atlaskit/textfield'; | ||
import Button from '@atlaskit/button'; | ||
import { css } from '@emotion/react'; | ||
import Select from '@atlaskit/select'; | ||
import { toast } from 'react-toastify'; | ||
import codeGeneratorProject from '../../../../graphs/code-node-generator.rivet-project?raw'; | ||
import { useRecoilValue } from 'recoil'; | ||
import { settingsState } from '../../../state/settings'; | ||
import { fillMissingSettingsFromEnvironmentVariables } from '../../../utils/tauri'; | ||
import { useDependsOnPlugins } from '../../../hooks/useDependsOnPlugins'; | ||
import { marked } from 'marked'; | ||
|
||
const styles = css` | ||
display: flex; | ||
align-items: center; | ||
gap: 8px; | ||
.model-selector { | ||
width: 200px; | ||
} | ||
`; | ||
|
||
export const CodeNodeAIAssistEditor: FC< | ||
SharedEditorProps & { | ||
editor: CustomEditorDefinition<ChartNode>; | ||
} | ||
> = ({ node, isReadonly, isDisabled, onChange, editor }) => { | ||
const [prompt, setPrompt] = useState(''); | ||
const [working, setWorking] = useState(false); | ||
const [model, setModel] = useState('gpt-3.5-turbo'); | ||
|
||
const settings = useRecoilValue(settingsState); | ||
const plugins = useDependsOnPlugins(); | ||
|
||
const data = node.data as CodeNodeData; | ||
|
||
const generateCode = async () => { | ||
try { | ||
const [project] = deserializeProject(codeGeneratorProject); | ||
const processor = coreCreateProcessor(project, { | ||
inputs: { | ||
prompt, | ||
model, | ||
}, | ||
...(await fillMissingSettingsFromEnvironmentVariables(settings, plugins)), | ||
}); | ||
|
||
setWorking(true); | ||
|
||
const outputs = await processor.run(); | ||
const code = coerceTypeOptional(outputs.code, 'string'); | ||
|
||
if (code) { | ||
onChange({ | ||
...node, | ||
data: { | ||
...data, | ||
code, | ||
} satisfies CodeNodeData, | ||
}); | ||
} else { | ||
const markdownResponse = marked(coerceType(outputs.response, 'string')); | ||
toast.info(<div dangerouslySetInnerHTML={{ __html: markdownResponse }}></div>, { | ||
autoClose: false, | ||
containerId: 'wide', | ||
toastId: 'ai-assist-response', | ||
}); | ||
} | ||
} catch (err) { | ||
toast.error(`Failed to generate code: ${getError(err).message}`); | ||
} finally { | ||
setWorking(false); | ||
} | ||
}; | ||
|
||
const modelOptions = useMemo( | ||
() => [ | ||
{ label: 'GPT-4', value: 'gpt-4' }, | ||
{ label: 'GPT-3.5 Turbo', value: 'gpt-3.5-turbo' }, | ||
], | ||
[], | ||
); | ||
|
||
const selectedModel = modelOptions.find((option) => option.value === model); | ||
|
||
return ( | ||
<Field name="aiAssist" label="Generate Using AI"> | ||
{() => ( | ||
<div css={styles}> | ||
<TextField | ||
isDisabled={isDisabled || working} | ||
isReadOnly={isReadonly} | ||
value={prompt} | ||
onChange={(e) => setPrompt((e.target as HTMLInputElement).value)} | ||
placeholder="What would you like your code node to do?" | ||
onKeyDown={(e) => { | ||
if (e.key === 'Enter') { | ||
generateCode(); | ||
} | ||
}} | ||
/> | ||
<Select | ||
options={modelOptions} | ||
value={selectedModel} | ||
onChange={(option) => setModel(option!.value)} | ||
isDisabled={isDisabled || working} | ||
className="model-selector" | ||
/> | ||
<Button appearance="primary" onClick={generateCode} isDisabled={isDisabled || working}> | ||
Generate | ||
</Button> | ||
</div> | ||
)} | ||
</Field> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters