mirror of
https://github.com/leon-ai/leon.git
synced 2024-12-25 01:31:47 +03:00
feat(bridge/nodejs): answers
This commit is contained in:
parent
759e67ac40
commit
8349e41205
@ -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)
|
||||
}
|
||||
})()
|
||||
|
84
bridges/nodejs/src/sdk/answer.ts
Normal file
84
bridges/nodejs/src/sdk/answer.ts
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export function rand(): number {
|
||||
return Math.random()
|
||||
}
|
3
bridges/nodejs/src/sdk/types.ts
Normal file
3
bridges/nodejs/src/sdk/types.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import type { AnswerObject } from '@bridge/types'
|
||||
|
||||
export type ActionResponse = AnswerObject | null
|
28
bridges/nodejs/src/types.ts
Normal file
28
bridges/nodejs/src/types.ts
Normal 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
|
||||
}
|
||||
}
|
17
bridges/nodejs/src/utils.ts
Normal file
17
bridges/nodejs/src/utils.ts
Normal 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')
|
||||
)
|
||||
}
|
@ -3,7 +3,10 @@
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist/bin",
|
||||
"baseUrl": "."
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@bridge/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"ts-node": {
|
||||
"swc": true,
|
||||
|
@ -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')
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
"extends": "@tsconfig/node16-strictest/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@bridge/*": ["../bridges/nodejs/src/*"],
|
||||
"@sdk/*": ["../bridges/nodejs/src/sdk/*"]
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
"paths": {
|
||||
"@@/*": ["./*"],
|
||||
"@/*": ["./server/src/*"],
|
||||
"@bridge/*": ["./bridges/nodejs/src/*"],
|
||||
"@sdk/*": ["./bridges/nodejs/src/sdk/*"]
|
||||
},
|
||||
"ignoreDeprecations": "5.0",
|
||||
|
Loading…
Reference in New Issue
Block a user