Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled
150 lines
4.3 KiB
TypeScript
150 lines
4.3 KiB
TypeScript
import { FormEventHandler, useState } from 'react'
|
|
import { Editor, useValue } from 'tldraw'
|
|
import { AtIcon } from '../../shared/icons/AtIcon'
|
|
import { BrainIcon } from '../../shared/icons/BrainIcon'
|
|
import { ChevronDownIcon } from '../../shared/icons/ChevronDownIcon'
|
|
import { AGENT_MODEL_DEFINITIONS, AgentModelName } from '../../shared/models'
|
|
import { useAgent } from '../agent/TldrawAgentAppProvider'
|
|
import { ContextItemTag } from './ContextItemTag'
|
|
import { SelectionTag } from './SelectionTag'
|
|
|
|
export function ChatInput({
|
|
handleSubmit,
|
|
inputRef,
|
|
}: {
|
|
handleSubmit: FormEventHandler<HTMLFormElement>
|
|
inputRef: React.RefObject<HTMLTextAreaElement | null>
|
|
}) {
|
|
const agent = useAgent()
|
|
const { editor } = agent
|
|
const [inputValue, setInputValue] = useState('')
|
|
const isGenerating = useValue('isGenerating', () => agent.requests.isGenerating(), [agent])
|
|
|
|
const isContextToolActive = useValue(
|
|
'isContextToolActive',
|
|
() => {
|
|
const tool = editor.getCurrentTool()
|
|
return tool.id === 'target-shape' || tool.id === 'target-area'
|
|
},
|
|
[editor]
|
|
)
|
|
|
|
const selectedShapes = useValue('selectedShapes', () => editor.getSelectedShapes(), [editor])
|
|
const contextItems = useValue('contextItems', () => agent.context.getItems(), [agent])
|
|
const modelName = useValue('modelName', () => agent.modelName.getModelName(), [agent])
|
|
|
|
return (
|
|
<div className="chat-input">
|
|
<form
|
|
onSubmit={(e) => {
|
|
e.preventDefault()
|
|
setInputValue('')
|
|
handleSubmit(e)
|
|
}}
|
|
>
|
|
<div className="prompt-tags">
|
|
<div className={'chat-context-select ' + (isContextToolActive ? 'active' : '')}>
|
|
<div className="chat-context-select-label">
|
|
<AtIcon /> Add Context
|
|
</div>
|
|
<select
|
|
id="chat-context-select"
|
|
value=" "
|
|
onChange={(e) => {
|
|
const action = ADD_CONTEXT_ACTIONS.find((action) => action.name === e.target.value)
|
|
if (action) action.onSelect(editor)
|
|
}}
|
|
>
|
|
{ADD_CONTEXT_ACTIONS.map((action) => {
|
|
return (
|
|
<option key={action.name} value={action.name}>
|
|
{action.name}
|
|
</option>
|
|
)
|
|
})}
|
|
</select>
|
|
</div>
|
|
{selectedShapes.length > 0 && <SelectionTag onClick={() => editor.selectNone()} />}
|
|
{contextItems.map((item, i) => (
|
|
<ContextItemTag
|
|
editor={editor}
|
|
onClick={() => agent.context.remove(item)}
|
|
key={'context-item-' + i}
|
|
item={item}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
<textarea
|
|
ref={inputRef}
|
|
name="input"
|
|
autoComplete="off"
|
|
placeholder="Ask, learn, brainstorm, draw"
|
|
value={inputValue}
|
|
onInput={(e) => setInputValue(e.currentTarget.value)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault()
|
|
//idk about this but it works oops -max
|
|
const form = e.currentTarget.closest('form')
|
|
if (form) {
|
|
const submitEvent = new Event('submit', { bubbles: true, cancelable: true })
|
|
form.dispatchEvent(submitEvent)
|
|
}
|
|
}
|
|
}}
|
|
/>
|
|
<span className="chat-actions">
|
|
<div className="chat-actions-left">
|
|
<div className="chat-model-select">
|
|
<div className="chat-model-select-label">
|
|
<BrainIcon /> {modelName}
|
|
</div>
|
|
<select
|
|
value={modelName}
|
|
onChange={(e) => agent.modelName.setModelName(e.target.value as AgentModelName)}
|
|
>
|
|
{Object.values(AGENT_MODEL_DEFINITIONS).map((model) => (
|
|
<option key={model.name} value={model.name}>
|
|
{model.name}
|
|
</option>
|
|
))}
|
|
</select>
|
|
<ChevronDownIcon />
|
|
</div>
|
|
</div>
|
|
<button className="chat-input-submit" disabled={inputValue === '' && !isGenerating}>
|
|
{isGenerating && inputValue === '' ? '◼' : '⬆'}
|
|
</button>
|
|
</span>
|
|
</form>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const ADD_CONTEXT_ACTIONS = [
|
|
{
|
|
name: 'Pick Shapes',
|
|
onSelect: (editor: Editor) => {
|
|
editor.setCurrentTool('target-shape')
|
|
editor.focus()
|
|
},
|
|
},
|
|
{
|
|
name: 'Pick Area',
|
|
onSelect: (editor: Editor) => {
|
|
editor.setCurrentTool('target-area')
|
|
editor.focus()
|
|
},
|
|
},
|
|
{
|
|
name: ' ',
|
|
onSelect: (editor: Editor) => {
|
|
const currentTool = editor.getCurrentTool()
|
|
if (currentTool.id === 'target-area' || currentTool.id === 'target-shape') {
|
|
editor.setCurrentTool('select')
|
|
}
|
|
},
|
|
},
|
|
]
|