feat: stop generating answers

This commit is contained in:
josc146
2023-03-16 11:20:21 +08:00
parent 91d47a2970
commit 0f97840d23
7 changed files with 79 additions and 9 deletions
+17 -2
View File
@@ -53,13 +53,24 @@ export async function generateAnswersWithChatgptWebApi(port, question, session,
}
const controller = new AbortController()
const stopListener = (msg) => {
if (msg.stop) {
console.debug('stop generating')
port.postMessage({ done: true })
controller.abort()
port.onMessage.removeListener(stopListener)
}
}
port.onMessage.addListener(stopListener)
port.onDisconnect.addListener(() => {
console.debug('port disconnected')
controller.abort()
deleteConversation()
})
const models = await getModels(accessToken).catch(() => {})
const models = await getModels(accessToken).catch(() => {
port.onMessage.removeListener(stopListener)
})
const config = await getUserConfig()
let answer = ''
@@ -112,8 +123,12 @@ export async function generateAnswersWithChatgptWebApi(port, question, session,
async onStart() {
// sendModerations(accessToken, question, session.conversationId, session.messageId)
},
async onEnd() {},
async onEnd() {
port.onMessage.removeListener(stopListener)
},
async onError(resp) {
if (resp instanceof Error) throw resp
port.onMessage.removeListener(stopListener)
if (resp.status === 403) {
throw new Error('CLOUDFLARE')
}
+28 -2
View File
@@ -35,6 +35,15 @@ export async function generateAnswersWithGptCompletionApi(
modelName,
) {
const controller = new AbortController()
const stopListener = (msg) => {
if (msg.stop) {
console.debug('stop generating')
port.postMessage({ done: true })
controller.abort()
port.onMessage.removeListener(stopListener)
}
}
port.onMessage.addListener(stopListener)
port.onDisconnect.addListener(() => {
console.debug('port disconnected')
controller.abort()
@@ -79,8 +88,12 @@ export async function generateAnswersWithGptCompletionApi(
port.postMessage({ answer: answer, done: false, session: null })
},
async onStart() {},
async onEnd() {},
async onEnd() {
port.onMessage.removeListener(stopListener)
},
async onError(resp) {
if (resp instanceof Error) throw resp
port.onMessage.removeListener(stopListener)
if (resp.status === 403) {
throw new Error('CLOUDFLARE')
}
@@ -99,6 +112,15 @@ export async function generateAnswersWithGptCompletionApi(
*/
export async function generateAnswersWithChatgptApi(port, question, session, apiKey, modelName) {
const controller = new AbortController()
const stopListener = (msg) => {
if (msg.stop) {
console.debug('stop generating')
port.postMessage({ done: true })
controller.abort()
port.onMessage.removeListener(stopListener)
}
}
port.onMessage.addListener(stopListener)
port.onDisconnect.addListener(() => {
console.debug('port disconnected')
controller.abort()
@@ -142,8 +164,12 @@ export async function generateAnswersWithChatgptApi(port, question, session, api
port.postMessage({ answer: answer, done: false, session: null })
},
async onStart() {},
async onEnd() {},
async onEnd() {
port.onMessage.removeListener(stopListener)
},
async onError(resp) {
if (resp instanceof Error) throw resp
port.onMessage.removeListener(stopListener)
if (resp.status === 403) {
throw new Error('CLOUDFLARE')
}
+6 -3
View File
@@ -51,8 +51,9 @@ Browser.runtime.onConnect.addListener((port) => {
console.debug('connected')
port.onMessage.addListener(async (msg) => {
console.debug('received msg', msg)
const config = await getUserConfig()
const session = msg.session
if (!session) return
const config = await getUserConfig()
if (session.useApiKey == null) {
session.useApiKey = isUsingApiKey(config)
}
@@ -84,8 +85,10 @@ Browser.runtime.onConnect.addListener((port) => {
}
} catch (err) {
console.error(err)
port.postMessage({ error: err.message })
cache.delete(KEY_ACCESS_TOKEN)
if (!err.message.includes('aborted')) {
port.postMessage({ error: err.message })
cache.delete(KEY_ACCESS_TOKEN)
}
}
})
})
@@ -223,6 +223,7 @@ function ConversationCard(props) {
type={data.type}
session={data.session}
done={data.done}
port={port}
/>
))}
</div>
+13 -1
View File
@@ -5,7 +5,7 @@ import CopyButton from '../CopyButton'
import PropTypes from 'prop-types'
import MarkdownRender from '../MarkdownRender/markdown.jsx'
export function ConversationItem({ type, content, session, done }) {
export function ConversationItem({ type, content, session, done, port }) {
const [collapsed, setCollapsed] = useState(false)
switch (type) {
@@ -36,6 +36,17 @@ export function ConversationItem({ type, content, session, done }) {
<div className="gpt-header">
<p>{session ? 'ChatGPT:' : 'Loading...'}</p>
<div style="display: flex; gap: 15px;">
{!done && (
<button
type="button"
className="normal-button"
onClick={() => {
port.postMessage({ stop: true })
}}
>
Stop
</button>
)}
{done && session && session.conversationId && (
<FeedbackForChatGPTWeb
messageId={session.messageId}
@@ -97,6 +108,7 @@ ConversationItem.propTypes = {
content: PropTypes.string.isRequired,
session: PropTypes.object.isRequired,
done: PropTypes.bool.isRequired,
port: PropTypes.object.isRequired,
}
export default ConversationItem
+9
View File
@@ -167,6 +167,15 @@
.gpt-util-icon {
cursor: pointer;
}
.normal-button {
border: 1px solid;
border-color: var(--theme-border-color);
background-color: var(--theme-color);
color: var(--font-color);
border-radius: 5px;
cursor: pointer;
}
}
.error {
+5 -1
View File
@@ -3,9 +3,13 @@ import { streamAsyncIterable } from './stream-async-iterable'
export async function fetchSSE(resource, options) {
const { onMessage, onStart, onEnd, onError, ...fetchOptions } = options
const resp = await fetch(resource, fetchOptions)
const resp = await fetch(resource, fetchOptions).catch(async (err) => {
await onError(err)
})
if (!resp) return
if (!resp.ok) {
await onError(resp)
return
}
const parser = createParser((event) => {
if (event.type === 'event') {