2
0

(openai) Enable setVariable function in tools

Closes #1178
This commit is contained in:
Baptiste Arnaud
2024-01-22 09:22:28 +01:00
parent b438c174c4
commit 42008f8c18
24 changed files with 258 additions and 43 deletions

View File

@ -0,0 +1,109 @@
import { Variable } from '@typebot.io/schemas'
import { parseVariables } from './parseVariables'
import { extractVariablesFromText } from './extractVariablesFromText'
import { parseGuessedValueType } from './parseGuessedValueType'
import { isDefined } from '@typebot.io/lib'
import { defaultTimeout } from '@typebot.io/schemas/features/blocks/integrations/webhook/constants'
type Props = {
variables: Variable[]
body: string
args?: Record<string, unknown>
}
export const executeFunction = async ({
variables,
body,
args: initialArgs,
}: Props) => {
const parsedBody = parseVariables(variables, { fieldToParse: 'id' })(body)
const args = (
extractVariablesFromText(variables)(body).map((variable) => ({
id: variable.id,
value: parseGuessedValueType(variable.value),
})) as { id: string; value: unknown }[]
).concat(
initialArgs
? Object.entries(initialArgs).map(([id, value]) => ({ id, value }))
: []
)
const func = AsyncFunction(
...args.map(({ id }) => id),
'setVariable',
parsedBody
)
let updatedVariables: Record<string, any> = {}
const setVariable = (key: string, value: any) => {
updatedVariables[key] = value
}
const timeout = new Timeout()
try {
const output = await timeout.wrap(
func(...args.map(({ value }) => value), setVariable),
defaultTimeout * 1000
)
timeout.clear()
return {
output,
newVariables: Object.entries(updatedVariables)
.map(([name, value]) => {
const existingVariable = variables.find((v) => v.name === name)
if (!existingVariable) return
return {
id: existingVariable.id,
name: existingVariable.name,
value,
}
})
.filter(isDefined),
}
} catch (e) {
console.log('Error while executing script')
console.error(e)
return {
error:
typeof e === 'string'
? e
: e instanceof Error
? e.message
: JSON.stringify(e),
}
}
}
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
class Timeout {
private ids: NodeJS.Timeout[]
constructor() {
this.ids = []
}
private set = (delay: number) =>
new Promise((_, reject) => {
const id = setTimeout(() => {
reject(`Script ${defaultTimeout}s timeout reached`)
this.clear(id)
}, delay)
this.ids.push(id)
})
wrap = (promise: Promise<any>, delay: number) =>
Promise.race([promise, this.set(delay)])
clear = (...ids: NodeJS.Timeout[]) => {
this.ids = this.ids.filter((id) => {
if (ids.includes(id)) {
clearTimeout(id)
return false
}
return true
})
}
}