Skip to content

Commit 4dea470

Browse files
authored
feat(chatbot): export type (#210)
1 parent da14a5a commit 4dea470

6 files changed

Lines changed: 296 additions & 286 deletions

File tree

server/data.js

Lines changed: 257 additions & 257 deletions
Large diffs are not rendered by default.

src/chatbot/_example/basic.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,8 @@ function handleStructuredData(chunk: SSEChunkData): AIMessageContent {
311311
const mockModels = {
312312
endpoint: 'http://localhost:3000/sse/normal',
313313
stream: true,
314-
onComplete: () => {
315-
console.log('onComplete');
314+
onComplete: (isAborted) => {
315+
console.log('onComplete', isAborted);
316316
},
317317
onError: (err) => {
318318
console.log('onError', err);

src/chatbot/_example/demo.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type { AIMessageContent, ChatMessagesData, SSEChunkData } from '../core/t
1010
// 天气扩展类型定义
1111
declare module '../core/type' {
1212
interface AIContentTypeOverrides {
13-
weather: BaseContent<
13+
weather: ChatBaseContent<
1414
'weather',
1515
{
1616
temp: number;

src/chatbot/core/server/sseClient.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export default class SSEClient {
1111

1212
private buffer = '';
1313

14+
private isClosed = false;
15+
1416
constructor(
1517
private url: string,
1618
private handlers: {
@@ -47,7 +49,6 @@ export default class SSEClient {
4749
this.handleError(response);
4850
return;
4951
}
50-
5152
this.reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
5253
// 直接开始读取流数据
5354
await this.readStream();
@@ -56,21 +57,31 @@ export default class SSEClient {
5657
}
5758
}
5859

59-
close() {
60-
this.reader?.cancel().catch(() => {});
61-
this.controller?.abort();
62-
this.reader = null;
63-
this.controller = null;
60+
async close() {
61+
if (this.isClosed) return;
62+
this.isClosed = true;
63+
// 先取消reader读取
64+
if (this.reader) {
65+
await this.reader.cancel().catch((err) => {
66+
this.handlers.onError?.(err);
67+
});
68+
this.reader = null;
69+
}
70+
71+
// 最后中止控制器
72+
if (this.controller && !this.controller.signal.aborted) {
73+
this.controller.abort();
74+
this.controller = null;
75+
}
6476
}
6577

6678
private async readStream() {
6779
try {
68-
while (true) {
80+
while (!this.isClosed) {
6981
// eslint-disable-next-line no-await-in-loop
7082
const { done, value } = await this.reader!.read();
7183
if (done) {
72-
const isAborted = this.reader === null;
73-
this.handlers.onComplete?.(isAborted);
84+
this.handlers.onComplete?.(this.isClosed);
7485
return;
7586
}
7687

src/chatbot/core/type.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@ export type ContentType =
1414
export type AttachmentType = 'image' | 'video' | 'audio' | 'pdf' | 'doc' | 'ppt' | 'txt';
1515

1616
// 基础类型
17-
export interface BaseContent<T extends string, TData> {
17+
export interface ChatBaseContent<T extends string, TData> {
1818
type: T;
1919
data: TData;
2020
status?: MessageStatus | ((currentStatus: MessageStatus | undefined) => MessageStatus);
2121
id?: string;
2222
}
2323

2424
// 内容类型
25-
export type TextContent = BaseContent<'text', string>;
25+
export type TextContent = ChatBaseContent<'text', string>;
2626

27-
export type MarkdownContent = BaseContent<'markdown', string>;
27+
export type MarkdownContent = ChatBaseContent<'markdown', string>;
2828

29-
export type ImageContent = BaseContent<
29+
export type ImageContent = ChatBaseContent<
3030
'image',
3131
{
3232
name?: string;
@@ -47,7 +47,7 @@ export type ReferenceItem = {
4747
site?: string;
4848
date?: string;
4949
};
50-
export type SearchContent = BaseContent<
50+
export type SearchContent = ChatBaseContent<
5151
'search',
5252
{
5353
title?: string;
@@ -59,7 +59,7 @@ export type SuggestionItem = {
5959
title: string;
6060
prompt?: string;
6161
};
62-
export type SuggestionContent = BaseContent<'suggestion', SuggestionItem[]>;
62+
export type SuggestionContent = ChatBaseContent<'suggestion', SuggestionItem[]>;
6363

6464
// 附件消息
6565
export type AttachmentItem = {
@@ -72,10 +72,10 @@ export type AttachmentItem = {
7272
height?: number;
7373
metadata?: Record<string, any>;
7474
};
75-
export type AttachmentContent = BaseContent<'attachment', AttachmentItem[]>;
75+
export type AttachmentContent = ChatBaseContent<'attachment', AttachmentItem[]>;
7676

7777
// 思考过程
78-
export type ThinkingContent = BaseContent<
78+
export type ThinkingContent = ChatBaseContent<
7979
'thinking',
8080
{
8181
text?: string;
@@ -195,12 +195,12 @@ export interface ChatState {
195195
model: ModelServiceState;
196196
}
197197

198-
export type AIContentHandler<T extends BaseContent<any, any>> = (chunk: T, existing?: T) => T;
198+
export type AIContentHandler<T extends ChatBaseContent<any, any>> = (chunk: T, existing?: T) => T;
199199

200200
export interface ContentTypeDefinition<T extends string = string, D = any> {
201201
type: T;
202-
handler?: AIContentHandler<BaseContent<T, D>>;
203-
renderer?: ContentRenderer<BaseContent<T, D>>;
202+
handler?: AIContentHandler<ChatBaseContent<T, D>>;
203+
renderer?: ContentRenderer<ChatBaseContent<T, D>>;
204204
}
205205

206-
export type ContentRenderer<T extends BaseContent<any, any>> = (content: T) => unknown;
206+
export type ContentRenderer<T extends ChatBaseContent<any, any>> = (content: T) => unknown;

src/chatbot/index.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import './style/index.js';
22

3-
import reactifyWebComponent from 'omi-reactify';
4-
53
import _Chat from './chat';
6-
import { TdChatProps } from './type';
74

85
export const Chat = _Chat;
96

107
export * from './core';
118
export * from './type';
129

1310
// 为方便如影测试,暂时从这里导出react组件
14-
const ChatBot = reactifyWebComponent<TdChatProps>('t-chatbot');
15-
export { ChatBot };
11+
// import reactifyWebComponent from 'omi-reactify';
12+
// import { TdChatProps } from './type';
13+
// const ChatBot = reactifyWebComponent<TdChatProps>('t-chatbot');
14+
// export { ChatBot };
1615
export default Chat;

0 commit comments

Comments
 (0)