UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

128 lines (114 loc) 4.69 kB
import { buildSchema, SchemaValues } from '@sprucelabs/schema' import AbstractAction from '../../AbstractAction' import { FeatureActionResponse } from '../../features.types' const optionsSchema = buildSchema({ id: 'testConversationOptions', description: 'Test your conversation topics.', fields: { shouldReturnImmediately: { type: 'boolean', isPrivate: true, }, shouldRunSilently: { type: 'boolean', isPrivate: true, }, }, }) type OptionsSchema = typeof optionsSchema type Options = SchemaValues<OptionsSchema> export default class TestAction extends AbstractAction<OptionsSchema> { public optionsSchema = optionsSchema public commandAliases = ['test.conversation', 'chat'] public invocationMessage = "Let's test talking about topics... 🎙" private killHandler?: () => void public async execute(options: Options): Promise<FeatureActionResponse> { const { shouldReturnImmediately, shouldRunSilently } = this.validateAndNormalizeOptions(options) this.ui.startLoading('Booting skill...') try { const command = this.Service('command') let isWriting = false const promise = new Promise((resolve, reject) => { command .execute('yarn boot.local', { spawnOptions: shouldRunSilently ? undefined : { stdio: [process.stdin, 'pipe', 'pipe'], }, onData: shouldRunSilently ? undefined : async (data) => { if (!isWriting) { isWriting = data.search(':: Skill booted') > -1 if (isWriting) { this.ui.clear() this.ui.stopLoading() process.stdout?.write( '? Send your first message to kick-off the conversation: ' ) } } else if (isWriting) { process.stdout?.write( data.replace( 'Skill :: Skill booted', '' ) ) } }, onError: (data) => { if (!data.includes('warning package.json')) { // const err = new SpruceError({ // friendlyMessage: // `Testing conversations failed because of the following error:\n\n` + // data, // code: 'EXECUTING_COMMAND_FAILED', // cmd: 'ACTION=test.conversation yarn.boot.local', // stderr: data, // }) // reject(err) } }, env: { ACTION: 'test.conversation', }, }) .then(resolve) .catch(reject) }) this.killHandler = command.kill.bind(command) if (shouldReturnImmediately) { return { meta: { kill: this.killHandler, pid: command.pid() as number, promise, }, } } else { await promise } } catch (err: any) { if ( err.options?.stderr?.includes('SIGINT') || err.options?.code === 'CONVERSATION_ABORTED' ) { return { summaryLines: ['Conversation terminated. ✌️'], } } return { errors: [err], } } return { summaryLines: ['Talk soon! 👋'], } } public async kill() { this.killHandler?.() } }