UNPKG

@coze/taro-api

Version:

Official Coze Taro SDK for seamless AI integration into your applications | 扣子官方 Taro SDK,助您轻松集成 AI 能力到应用中

108 lines (107 loc) 3.56 kB
/* eslint-disable @typescript-eslint/no-magic-numbers -- ignore */ /* eslint-disable security/detect-object-injection -- ignore */ import Taro from '@tarojs/taro'; import { TextDecoder } from '../helpers/decoder'; import { EventName } from './types'; import { BaseEventSource } from './base'; /** * Process streaming requests for WeChat Mini Program */ export class EventSource extends BaseEventSource { options; task; isAborted = false; cacheChunk = ''; constructor(options) { super(); this.options = options; } start() { const { url, method, headers, data, timeout } = this.options; this.task = Taro.request({ url, method, header: headers, data, enableChunked: true, enableCookie: true, timeout, fail: err => { this.trigger(EventName.Fail, { errMsg: err.errMsg }); }, success: res => { if (res.statusCode !== 200) { this.trigger(EventName.Fail, { errMsg: res.errMsg, data: res }); } else { this.trigger(EventName.Success, { data: res }); } }, }); this.onHeadersReceived(); this.onChunkReceived(); } abort() { if (!this.isAborted) { this.task?.abort(); this.isAborted = true; } } onHeadersReceived() { this.task?.onHeadersReceived(res => { this.trigger(EventName.Open, { data: res }); }); } onChunkReceived() { this.task?.onChunkReceived(res => { const octets = new Uint8Array(res.data); const decoder = new TextDecoder(); const chunk = decoder.decode(octets); // The request may be failed, so we need to check the chunk if (!this.cacheChunk) { const chunkJson = this.safeParseJSON(chunk); if (chunkJson && chunkJson.code) { this.trigger(EventName.Fail, { errMsg: chunkJson.msg, data: chunkJson, }); // Abort the request this.abort(); return; } } this.cacheChunk += chunk; if (this.cacheChunk.endsWith('\n\n')) { const chunkStr = this.cacheChunk; this.cacheChunk = ''; const messages = []; let message = {}; const lines = chunkStr.split('\n'); for (let i = 0; i < lines.length - 1; i++) { const line = lines[i]; const index = line.indexOf(':'); if (index !== -1) { const field = line.substring(0, index).trim(); const content = line.substring(index + 1).trim(); message[field] = content; if (field === 'data') { messages.push(message); message = {}; } } } messages.map(msg => { this.trigger(EventName.Chunk, { data: msg }); }); } }); } safeParseJSON(str) { try { return JSON.parse(str); } catch (e) { return null; } } }