(credential)
| 80 | } |
| 81 | |
| 82 | async function enterConversation(credential) { |
| 83 | console.log('Start chatting with', credential.name + ':'); |
| 84 | const chat = new ChatService({ |
| 85 | name: credential.name, |
| 86 | api: apiManager.createAPIForCredential(credential) as ChatServiceSupportedAPIs, |
| 87 | }); |
| 88 | |
| 89 | // Create terminal chat interface. |
| 90 | let spinner; |
| 91 | const rl = readline.createInterface({ |
| 92 | input: process.stdin, |
| 93 | output: process.stdout, |
| 94 | }); |
| 95 | // Print ChatGPT answers with streaming interface. |
| 96 | let state = 'waitUser'; |
| 97 | chat.onMessageDelta.connect((message, info) => { |
| 98 | if (spinner) { |
| 99 | // Clear spinner and print bot name. |
| 100 | spinner.clear(); |
| 101 | spinner.reset(); |
| 102 | spinner = null; |
| 103 | process.stdout.write('\x1b[?25h'); // restore cursor |
| 104 | process.stdout.write(`${chat.name}> `); |
| 105 | } |
| 106 | if (state == 'waitAnswer') { |
| 107 | // Print content. |
| 108 | if (message.content) |
| 109 | process.stdout.write(message.content); |
| 110 | } |
| 111 | if (info.pending) // more messages coming. |
| 112 | return; |
| 113 | process.stdout.write('\n'); |
| 114 | state = 'waitUser'; |
| 115 | }); |
| 116 | // Quite on EOF. |
| 117 | rl.once('close', () => chat.abort()); |
| 118 | // Make user ask question infinitely. |
| 119 | while (!chat.isAborted()) { |
| 120 | if (state != 'waitUser') |
| 121 | throw new Error('Did not receive an answer.'); |
| 122 | try { |
| 123 | const content = await rl.question('You> ', {signal: chat.aborter.signal}); |
| 124 | state = 'waitAnswer'; |
| 125 | spinner = createSpinner().start(); |
| 126 | await chat.sendMessage({content}); |
| 127 | } catch (error) { |
| 128 | // Ignore abort error. |
| 129 | if (error.name != 'AbortError') |
| 130 | throw error; |
| 131 | } |
| 132 | } |
| 133 | } |
no test coverage detected