Spaces:
Runtime error
Runtime error
import React, { useState, useCallback, memo, ReactNode } from 'react'; | |
import { Spinner } from '~/components'; | |
import { useRecoilValue } from 'recoil'; | |
import CodeBlock from './Content/CodeBlock.jsx'; | |
import { Disclosure } from '@headlessui/react'; | |
import { ChevronDownIcon, LucideProps } from 'lucide-react'; | |
import { cn } from '~/utils/'; | |
import store from '~/store'; | |
interface Input { | |
inputStr: string; | |
} | |
interface PluginProps { | |
plugin: { | |
plugin: string; | |
input: string; | |
thought: string; | |
loading?: boolean; | |
outputs?: string; | |
latest?: string; | |
inputs?: Input[]; | |
}; | |
} | |
type PluginsMap = { | |
[pluginKey: string]: string; | |
}; | |
type PluginIconProps = LucideProps & { | |
className?: string; | |
}; | |
function formatInputs(inputs: Input[]) { | |
let output = ''; | |
for (let i = 0; i < inputs.length; i++) { | |
output += `${inputs[i].inputStr}`; | |
if (inputs.length > 1 && i !== inputs.length - 1) { | |
output += ',\n'; | |
} | |
} | |
return output; | |
} | |
const Plugin: React.FC<PluginProps> = ({ plugin }) => { | |
const [loading, setLoading] = useState(plugin.loading); | |
const finished = plugin.outputs && plugin.outputs.length > 0; | |
const plugins: PluginsMap = useRecoilValue(store.plugins); | |
const getPluginName = useCallback( | |
(pluginKey: string) => { | |
if (!pluginKey) { | |
return null; | |
} | |
if (pluginKey === 'n/a' || pluginKey === 'self reflection') { | |
return pluginKey; | |
} | |
return plugins[pluginKey] ?? 'self reflection'; | |
}, | |
[plugins], | |
); | |
if (!plugin || !plugin.latest) { | |
return null; | |
} | |
const latestPlugin = getPluginName(plugin.latest); | |
if (!latestPlugin || (latestPlugin && latestPlugin === 'n/a')) { | |
return null; | |
} | |
if (finished && loading) { | |
setLoading(false); | |
} | |
const generateStatus = (): ReactNode => { | |
if (!loading && latestPlugin === 'self reflection') { | |
return 'Finished'; | |
} else if (latestPlugin === 'self reflection') { | |
return 'I\'m thinking...'; | |
} else { | |
return ( | |
<> | |
{loading ? 'Using' : 'Used'} <b>{latestPlugin}</b> | |
{loading ? '...' : ''} | |
</> | |
); | |
} | |
}; | |
return ( | |
<div className="flex flex-col items-start"> | |
<Disclosure> | |
{({ open }) => { | |
const iconProps: PluginIconProps = { | |
className: cn(open ? 'rotate-180 transform' : '', 'h-4 w-4'), | |
}; | |
return ( | |
<> | |
<div | |
className={cn( | |
loading ? 'bg-green-100' : 'bg-[#ECECF1]', | |
'flex items-center rounded p-3 text-sm text-gray-900', | |
)} | |
> | |
<div> | |
<div className="flex items-center gap-3"> | |
<div>{generateStatus()}</div> | |
</div> | |
</div> | |
{loading && <Spinner className="ml-1" />} | |
<Disclosure.Button className="ml-12 flex items-center gap-2"> | |
<ChevronDownIcon {...iconProps} /> | |
</Disclosure.Button> | |
</div> | |
<Disclosure.Panel className="my-3 flex max-w-full flex-col gap-3"> | |
<CodeBlock | |
lang={latestPlugin?.toUpperCase() || 'INPUTS'} | |
codeChildren={formatInputs(plugin.inputs ?? [])} | |
plugin={true} | |
classProp="max-h-[450px]" | |
/> | |
{finished && ( | |
<CodeBlock | |
lang="OUTPUTS" | |
codeChildren={plugin.outputs ?? ''} | |
plugin={true} | |
classProp="max-h-[450px]" | |
/> | |
)} | |
</Disclosure.Panel> | |
</> | |
); | |
}} | |
</Disclosure> | |
</div> | |
); | |
}; | |
export default memo(Plugin); | |