mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 13:27:08 +00:00
* fix: 2.7 dev start * feat: 初步支持function call(WIP) * fix: syntax error * fix: syntax error * feat: 群聊上下文 * fix: 暂时阉割掉全员禁言功能 * fix: 修改禁言时间范围 * fix: 修复一些功能易用性 * fix: 只有管理员和群主才能用jinyan和kickout * fix: 加回来禁言和踢出 * fix: 修复管理员权限判断问题(可能吧) * fix: 试图优化逻辑 * fix: fuck openai documents * fix: 删掉认主不然一直禁言我烦死了 * fix: 哔哩哔哩封面损坏问题 * fix: 加个天气小工具 * fix: 天气不存在城市 * fix: website工具用浏览器 * feat: serp tool * feat: 增加一个google搜索源 * fix: 加一句描述 * feat: 增加搜索来源选项 * feat: 搜图和发图 * fix: groupId format error * fix: add a image caption tool * fix: 修改一些提示。tool太多机器人开始混乱了 * fix: 一些极端的措施 * fix: 增加一些提示和一个暂时的公共接口 * fix: 收拾一下 * fix: 修改命令正则 * fix: 修改一些提示 * fix: move send avatar into send picture tool * fix: 修复解除禁言的bug
89 lines
No EOL
2.5 KiB
TypeScript
89 lines
No EOL
2.5 KiB
TypeScript
import { createParser } from 'eventsource-parser'
|
|
|
|
import * as types from './types'
|
|
import { fetch as nodefetch } from 'node-fetch'
|
|
import { streamAsyncIterable } from './stream-async-iterable'
|
|
|
|
export async function fetchSSE(
|
|
url: string,
|
|
options: Parameters<typeof fetch>[1] & {
|
|
onMessage: (data: string) => void
|
|
onError?: (error: any) => void
|
|
},
|
|
fetch: types.FetchFn = nodefetch
|
|
) {
|
|
const { onMessage, onError, ...fetchOptions } = options
|
|
const res = await fetch(url, fetchOptions)
|
|
if (!res.ok) {
|
|
let reason: string
|
|
|
|
try {
|
|
reason = await res.text()
|
|
} catch (err) {
|
|
reason = res.statusText
|
|
}
|
|
|
|
const msg = `ChatGPT error ${res.status}: ${reason}`
|
|
const error = new types.ChatGPTError(msg, { cause: res })
|
|
error.statusCode = res.status
|
|
error.statusText = res.statusText
|
|
throw error
|
|
}
|
|
|
|
const parser = createParser((event) => {
|
|
if (event.type === 'event') {
|
|
onMessage(event.data)
|
|
}
|
|
})
|
|
|
|
// handle special response errors
|
|
const feed = (chunk: string) => {
|
|
let response = null
|
|
|
|
try {
|
|
response = JSON.parse(chunk)
|
|
} catch {
|
|
// ignore
|
|
}
|
|
|
|
if (response?.detail?.type === 'invalid_request_error') {
|
|
const msg = `ChatGPT error ${response.detail.message}: ${response.detail.code} (${response.detail.type})`
|
|
const error = new types.ChatGPTError(msg, { cause: response })
|
|
error.statusCode = response.detail.code
|
|
error.statusText = response.detail.message
|
|
|
|
if (onError) {
|
|
onError(error)
|
|
} else {
|
|
console.error(error)
|
|
}
|
|
|
|
// don't feed to the event parser
|
|
return
|
|
}
|
|
|
|
parser.feed(chunk)
|
|
}
|
|
|
|
if (!res.body.getReader) {
|
|
// Vercel polyfills `fetch` with `node-fetch`, which doesn't conform to
|
|
// web standards, so this is a workaround...
|
|
const body: NodeJS.ReadableStream = res.body as any
|
|
|
|
if (!body.on || !body.read) {
|
|
throw new types.ChatGPTError('unsupported "fetch" implementation')
|
|
}
|
|
|
|
body.on('readable', () => {
|
|
let chunk: string | Buffer
|
|
while (null !== (chunk = body.read())) {
|
|
feed(chunk.toString())
|
|
}
|
|
})
|
|
} else {
|
|
for await (const chunk of streamAsyncIterable(res.body)) {
|
|
const str = new TextDecoder().decode(chunk)
|
|
feed(str)
|
|
}
|
|
}
|
|
} |