176 lines
5.4 KiB
TypeScript
176 lines
5.4 KiB
TypeScript
import { SidebarCreateItem } from "@/components/sidebar/items/all/sidebar-create-item"
|
|
import { Input } from "@/components/ui/input"
|
|
import { Label } from "@/components/ui/label"
|
|
import { TextareaAutosize } from "@/components/ui/textarea-autosize"
|
|
import { ChatbotUIContext } from "@/context/context"
|
|
import { TOOL_DESCRIPTION_MAX, TOOL_NAME_MAX } from "@/db/limits"
|
|
import { validateOpenAPI } from "@/lib/openapi-conversion"
|
|
import { TablesInsert } from "@/supabase/types"
|
|
import { FC, useContext, useState } from "react"
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
interface CreateToolProps {
|
|
isOpen: boolean
|
|
onOpenChange: (isOpen: boolean) => void
|
|
}
|
|
|
|
export const CreateTool: FC<CreateToolProps> = ({ isOpen, onOpenChange }) => {
|
|
const { t } = useTranslation()
|
|
|
|
const { profile, selectedWorkspace } = useContext(ChatbotUIContext)
|
|
|
|
const [name, setName] = useState("")
|
|
const [isTyping, setIsTyping] = useState(false)
|
|
const [description, setDescription] = useState("")
|
|
const [url, setUrl] = useState("")
|
|
const [customHeaders, setCustomHeaders] = useState("")
|
|
const [schema, setSchema] = useState("")
|
|
const [schemaError, setSchemaError] = useState("")
|
|
|
|
if (!profile || !selectedWorkspace) return null
|
|
|
|
return (
|
|
<SidebarCreateItem
|
|
contentType="tools"
|
|
createState={
|
|
{
|
|
user_id: profile.user_id,
|
|
name,
|
|
description,
|
|
url,
|
|
custom_headers: customHeaders,
|
|
schema
|
|
} as TablesInsert<"tools">
|
|
}
|
|
isOpen={isOpen}
|
|
isTyping={isTyping}
|
|
renderInputs={() => (
|
|
<>
|
|
<div className="space-y-1">
|
|
<Label>{t("side.name")}</Label>
|
|
|
|
<Input
|
|
placeholder={t("side.toolNamePlaceholder")}
|
|
value={name}
|
|
onChange={e => setName(e.target.value)}
|
|
maxLength={TOOL_NAME_MAX}
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-1">
|
|
<Label>{t("side.description")}</Label>
|
|
|
|
<Input
|
|
placeholder={t("side.toolDescriptionPlaceholder")}
|
|
value={description}
|
|
onChange={e => setDescription(e.target.value)}
|
|
maxLength={TOOL_DESCRIPTION_MAX}
|
|
/>
|
|
</div>
|
|
|
|
{/* <div className="space-y-1">
|
|
<Label>URL</Label>
|
|
|
|
<Input
|
|
placeholder="Tool url..."
|
|
value={url}
|
|
onChange={e => setUrl(e.target.value)}
|
|
/>
|
|
</div> */}
|
|
|
|
{/* <div className="space-y-3 pt-4 pb-3">
|
|
<div className="space-x-2 flex items-center">
|
|
<Checkbox />
|
|
|
|
<Label>Web Browsing</Label>
|
|
</div>
|
|
|
|
<div className="space-x-2 flex items-center">
|
|
<Checkbox />
|
|
|
|
<Label>Image Generation</Label>
|
|
</div>
|
|
|
|
<div className="space-x-2 flex items-center">
|
|
<Checkbox />
|
|
|
|
<Label>Code Interpreter</Label>
|
|
</div>
|
|
</div> */}
|
|
|
|
<div className="space-y-1">
|
|
<Label>{t("side.customHeadersLabel")}</Label>
|
|
|
|
<TextareaAutosize
|
|
placeholder={`{"X-api-key": "1234567890"}`}
|
|
value={customHeaders}
|
|
onValueChange={setCustomHeaders}
|
|
minRows={1}
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-1">
|
|
<Label>{t("side.schemaLabel")}</Label>
|
|
|
|
<TextareaAutosize
|
|
placeholder={`{
|
|
"openapi": "3.1.0",
|
|
"info": {
|
|
"title": "Get weather data",
|
|
"description": "Retrieves current weather data for a location.",
|
|
"version": "v1.0.0"
|
|
},
|
|
"servers": [
|
|
{
|
|
"url": "https://weather.example.com"
|
|
}
|
|
],
|
|
"paths": {
|
|
"/location": {
|
|
"get": {
|
|
"description": "Get temperature for a specific location",
|
|
"operationId": "GetCurrentWeather",
|
|
"parameters": [
|
|
{
|
|
"name": "location",
|
|
"in": "query",
|
|
"description": "The city and state to retrieve the weather for",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"deprecated": false
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"schemas": {}
|
|
}
|
|
}`}
|
|
value={schema}
|
|
onValueChange={value => {
|
|
setSchema(value)
|
|
|
|
try {
|
|
const parsedSchema = JSON.parse(value)
|
|
validateOpenAPI(parsedSchema)
|
|
.then(() => setSchemaError("")) // Clear error if validation is successful
|
|
.catch(error => setSchemaError(error.message)) // Set specific validation error message
|
|
} catch (error) {
|
|
setSchemaError("Invalid JSON format") // Set error for invalid JSON format
|
|
}
|
|
}}
|
|
minRows={15}
|
|
/>
|
|
|
|
<div className="text-xs text-red-500">{schemaError}</div>
|
|
</div>
|
|
</>
|
|
)}
|
|
onOpenChange={onOpenChange}
|
|
/>
|
|
)
|
|
}
|