kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: add support for stop signal and use do-while
rodzic
646398d2aa
commit
f823da15af
|
@ -116,6 +116,11 @@ export type TwilioSendAndWaitOptions = {
|
||||||
* A function to validate the reply message. If the function returns `true`, the reply is considered valid and the function will return the message. If the function returns `false`, the reply is considered invalid and the function will continue to wait for a reply until the timeout is reached.
|
* A function to validate the reply message. If the function returns `true`, the reply is considered valid and the function will return the message. If the function returns `false`, the reply is considered invalid and the function will continue to wait for a reply until the timeout is reached.
|
||||||
*/
|
*/
|
||||||
validate?: (message: TwilioConversationMessage) => boolean
|
validate?: (message: TwilioConversationMessage) => boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stop signal from an [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController), which can be used to abort retrying. More specifically, when `AbortController.abort(reason)` is called, the function will throw an error with the `reason` argument as the error message.
|
||||||
|
*/
|
||||||
|
stopSignal?: AbortSignal
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -242,14 +247,28 @@ export class TwilioConversationClient {
|
||||||
recipientPhoneNumber,
|
recipientPhoneNumber,
|
||||||
timeoutMs = DEFAULT_TWILIO_TIMEOUT_MS,
|
timeoutMs = DEFAULT_TWILIO_TIMEOUT_MS,
|
||||||
intervalMs = DEFAULT_TWILIO_INTERVAL_MS,
|
intervalMs = DEFAULT_TWILIO_INTERVAL_MS,
|
||||||
validate = () => true
|
validate = () => true,
|
||||||
|
stopSignal
|
||||||
}: TwilioSendAndWaitOptions) {
|
}: TwilioSendAndWaitOptions) {
|
||||||
|
let aborted = false
|
||||||
|
stopSignal?.addEventListener(
|
||||||
|
'abort',
|
||||||
|
() => {
|
||||||
|
aborted = true
|
||||||
|
},
|
||||||
|
{ once: true }
|
||||||
|
)
|
||||||
|
|
||||||
const { sid: conversationSid } = await this.createConversation(name)
|
const { sid: conversationSid } = await this.createConversation(name)
|
||||||
await this.addParticipant({ conversationSid, recipientPhoneNumber })
|
await this.addParticipant({ conversationSid, recipientPhoneNumber })
|
||||||
await this.sendMessage({ conversationSid, text })
|
await this.sendMessage({ conversationSid, text })
|
||||||
const start = Date.now()
|
const start = Date.now()
|
||||||
let nUserMessages = 0
|
let nUserMessages = 0
|
||||||
while (Date.now() - start < timeoutMs) {
|
do {
|
||||||
|
if (aborted) {
|
||||||
|
await this.deleteConversation(conversationSid)
|
||||||
|
throw new Error('Aborted waiting for reply')
|
||||||
|
}
|
||||||
const response = await this.fetchMessages(conversationSid)
|
const response = await this.fetchMessages(conversationSid)
|
||||||
if (response.messages.length > 1) {
|
if (response.messages.length > 1) {
|
||||||
const candidates = response.messages.filter(
|
const candidates = response.messages.filter(
|
||||||
|
@ -269,7 +288,8 @@ export class TwilioConversationClient {
|
||||||
nUserMessages = candidates.length
|
nUserMessages = candidates.length
|
||||||
}
|
}
|
||||||
await sleep(intervalMs)
|
await sleep(intervalMs)
|
||||||
}
|
} while (Date.now() - start < timeoutMs)
|
||||||
|
|
||||||
await this.deleteConversation(conversationSid)
|
await this.deleteConversation(conversationSid)
|
||||||
throw new Error('Reached timeout waiting for reply')
|
throw new Error('Reached timeout waiting for reply')
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,3 +101,38 @@ test('TwilioConversationClient.sendAndWaitForReply', async (t) => {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('TwilioConversationClient.sendAndWaitForReply.stopSignal', async (t) => {
|
||||||
|
if (
|
||||||
|
!process.env.TWILIO_ACCOUNT_SID ||
|
||||||
|
!process.env.TWILIO_AUTH_TOKEN ||
|
||||||
|
!process.env.TWILIO_TEST_PHONE_NUMBER
|
||||||
|
) {
|
||||||
|
return t.pass()
|
||||||
|
}
|
||||||
|
|
||||||
|
t.timeout(2 * 60 * 1000)
|
||||||
|
const client = new TwilioConversationClient()
|
||||||
|
|
||||||
|
await t.throwsAsync(
|
||||||
|
async () => {
|
||||||
|
const controller = new AbortController()
|
||||||
|
const promise = client.sendAndWaitForReply({
|
||||||
|
recipientPhoneNumber: process.env.TWILIO_TEST_PHONE_NUMBER as string,
|
||||||
|
text: 'Please confirm by replying with "yes" or "no".',
|
||||||
|
name: 'wait-for-reply-test',
|
||||||
|
validate: (message) =>
|
||||||
|
['yes', 'no'].includes(message.body.toLowerCase()),
|
||||||
|
timeoutMs: 10000, // 10 seconds
|
||||||
|
intervalMs: 5000, // 5 seconds
|
||||||
|
stopSignal: controller.signal
|
||||||
|
})
|
||||||
|
controller.abort()
|
||||||
|
return promise
|
||||||
|
},
|
||||||
|
{
|
||||||
|
instanceOf: Error,
|
||||||
|
message: 'Aborted waiting for reply'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
Ładowanie…
Reference in New Issue