1
1
mirror of https://github.com/leon-ai/leon.git synced 2024-11-28 04:04:58 +03:00

feat(bridge/nodejs): answers

This commit is contained in:
louistiti 2023-05-03 23:28:12 +08:00
parent 759e67ac40
commit 8349e41205
No known key found for this signature in database
GPG Key ID: 92CD6A2E497E1669
10 changed files with 180 additions and 69 deletions

View File

@ -1,71 +1,45 @@
import fs from 'node:fs'
import path from 'node:path'
const {
argv: [, , INTENT_OBJ_FILE_PATH]
} = process
import { getIntentObject } from '@bridge/utils'
;(async (): Promise<void> => {
if (INTENT_OBJ_FILE_PATH) {
const {
domain,
skill,
action,
lang,
utterance,
current_entities: currentEntities,
entities,
current_resolvers: currentResolvers,
resolvers,
slots
} = JSON.parse(await fs.promises.readFile(INTENT_OBJ_FILE_PATH, 'utf8'))
const {
domain,
skill,
action,
lang,
utterance,
current_entities: currentEntities,
entities,
current_resolvers: currentResolvers,
resolvers,
slots
} = await getIntentObject()
const params = {
lang,
utterance,
currentEntities,
entities,
currentResolvers,
resolvers,
slots
}
const params = {
lang,
utterance,
currentEntities,
entities,
currentResolvers,
resolvers,
slots
}
try {
const { [action]: actionFunction } = await import(
path.join(
process.cwd(),
'skills',
domain,
skill,
'src',
'actions',
`${action}.ts`
)
try {
const { [action]: actionFunction } = await import(
path.join(
process.cwd(),
'skills',
domain,
skill,
'src',
'actions',
`${action}.ts`
)
)
const speech = actionFunction(params)
console.log(
JSON.stringify({
domain,
skill,
action,
lang,
utterance,
entities,
slots,
// TODO
output: {
type: 'end',
codes: '',
speech,
core: {},
options: {}
}
})
)
} catch (e) {
console.error('Error while running action:', e)
}
actionFunction(params)
} catch (e) {
console.error('Error while running action:', e)
}
})()

View File

@ -0,0 +1,84 @@
import type { ActionResponse } from '@bridge/sdk/types'
import { getIntentObject } from '@bridge/utils'
import { AnswerTypes } from '@bridge/types'
/**
* Holds methods to communicate data from the skill to the core
*/
abstract class Answer {
/**
* Send an answer to the core
* @param text
*/
protected abstract text(text: string): Promise<ActionResponse>
/**
* Create an answer object to send an answer to the core
* @param type The type of the answer
* @param text The text to send
*/
protected async createAnswerObject(
type: AnswerTypes,
text: string
): Promise<ActionResponse> {
try {
const answer = {
...(await getIntentObject()),
output: {
type,
codes: '', // TODO
speech: text,
core: {}, // TODO
options: {} // TODO
}
}
process.stdout.write(JSON.stringify(answer))
return answer
} catch (e) {
console.error('Error creating answer object:', e)
return null
}
}
}
export class IntermediateAnswer extends Answer {
/**
* Create an answer object with the intermediate type
* to send an intermediate answer to the core.
* Used to send an answer before the final answer
* @param text The text to send
* @example await new IntermediateAnswer().text('intermediate answer')
*/
public async text(text: string): Promise<ActionResponse> {
try {
return await this.createAnswerObject(AnswerTypes.Intermediate, text)
} catch (e) {
console.error('Error creating intermediate answer:', e)
return null
}
}
}
export class FinalAnswer extends Answer {
/**
* Create an answer object with the final type
* to send a final answer to the core.
* Used to send an answer before the end of the skill action
* @param text The text to send
* @example await new FinalAnswer().text('final answer')
*/
public async text(text: string): Promise<ActionResponse> {
try {
return await this.createAnswerObject(AnswerTypes.Final, text)
} catch (e) {
console.error('Error creating final answer:', e)
return null
}
}
}

View File

@ -1,3 +0,0 @@
export function rand(): number {
return Math.random()
}

View File

@ -0,0 +1,3 @@
import type { AnswerObject } from '@bridge/types'
export type ActionResponse = AnswerObject | null

View File

@ -0,0 +1,28 @@
export enum AnswerTypes {
Intermediate = 'inter',
Final = 'end'
}
export interface IntentObject {
id: string
domain: string
skill: string
action: string
lang: string
utterance: string
current_entities: unknown[] // TODO
entities: unknown[] // TODO
current_resolvers: unknown[] // TODO
resolvers: unknown[] // TODO
slots: Record<string, unknown>[] // TODO
}
export interface AnswerObject extends IntentObject {
output: {
type: AnswerTypes
codes: string
speech: string
core: unknown // TODO
options: unknown // TODO
}
}

View File

@ -0,0 +1,17 @@
import fs from 'node:fs'
import type { IntentObject } from '@bridge/types'
const {
argv: [, , INTENT_OBJ_FILE_PATH]
} = process
/**
* Get the intent object from the temporary intent file
* @example await getIntentObject() // { ... }
*/
export async function getIntentObject(): Promise<IntentObject> {
return JSON.parse(
await fs.promises.readFile(INTENT_OBJ_FILE_PATH as string, 'utf8')
)
}

View File

@ -3,7 +3,10 @@
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist/bin",
"baseUrl": "."
"baseUrl": ".",
"paths": {
"@bridge/*": ["./src/*"]
}
},
"ts-node": {
"swc": true,

View File

@ -1,5 +1,8 @@
import { rand } from '@sdk/testo'
import type { ActionResponse } from '@sdk/types'
import { IntermediateAnswer, FinalAnswer } from '@sdk/answer'
export function run(): string {
return `hello ${rand()}`
export async function run(): Promise<ActionResponse> {
await new IntermediateAnswer().text('intermediate answer')
return await new FinalAnswer().text('final answer')
}

View File

@ -2,6 +2,7 @@
"extends": "@tsconfig/node16-strictest/tsconfig.json",
"compilerOptions": {
"paths": {
"@bridge/*": ["../bridges/nodejs/src/*"],
"@sdk/*": ["../bridges/nodejs/src/sdk/*"]
}
}

View File

@ -7,6 +7,7 @@
"paths": {
"@@/*": ["./*"],
"@/*": ["./server/src/*"],
"@bridge/*": ["./bridges/nodejs/src/*"],
"@sdk/*": ["./bridges/nodejs/src/sdk/*"]
},
"ignoreDeprecations": "5.0",