chore: replace all cn comments of fe to en version by volc api (#320)
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import Mock from 'mockjs';
|
||||
|
||||
import { ChatCoreUploadPlugin } from '@/plugins/upload-plugin';
|
||||
@@ -29,7 +29,7 @@ import ChatSDK from '@/chat-sdk';
|
||||
const random = Mock.Random;
|
||||
|
||||
describe('创建消息', () => {
|
||||
// 创建 ChatSDK 实例
|
||||
// Create a ChatSDK instance
|
||||
const sdkProps: CreateProps = {
|
||||
bot_id: random.string(),
|
||||
biz: 'third_part',
|
||||
@@ -41,15 +41,15 @@ describe('创建消息', () => {
|
||||
};
|
||||
const chat = new ChatSDK(sdkProps);
|
||||
|
||||
// 注册插件
|
||||
// @ts-expect-error -- 测试文件中不需要真实的插件
|
||||
// Register plugin
|
||||
// @ts-expect-error -- no real plugin is required in the test file
|
||||
chat.registerPlugin('upload-plugin', ChatCoreUploadPlugin, {
|
||||
userId: '123',
|
||||
appId: 123,
|
||||
});
|
||||
|
||||
it('createTextMessage', () => {
|
||||
// 标准输出的 Message
|
||||
// Standard Output Message
|
||||
const messageStand = {
|
||||
bot_id: sdkProps.bot_id,
|
||||
role: 'user',
|
||||
@@ -117,7 +117,7 @@ describe('创建消息', () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
// 标准输出的 Message
|
||||
// Standard Output Message
|
||||
const messageStand = {
|
||||
bot_id: sdkProps.bot_id,
|
||||
role: 'user',
|
||||
@@ -157,15 +157,15 @@ describe('创建消息', () => {
|
||||
};
|
||||
const options = { section_id: '123' };
|
||||
|
||||
// 注册插件
|
||||
// @ts-expect-error -- test文件忽略
|
||||
// Register plugin
|
||||
// @ts-expect-error -- test file ignored
|
||||
chat.registerPlugin('upload-plugin', ChatCoreUploadPlugin, {
|
||||
userId: '123',
|
||||
appId: 123,
|
||||
});
|
||||
|
||||
// Execute
|
||||
// @ts-expect-error -- 测试文件
|
||||
// @ts-expect-error -- test file
|
||||
const message = chat.createImageMessage(props, options);
|
||||
|
||||
// Assert
|
||||
@@ -185,7 +185,7 @@ describe('创建消息', () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
// 标准输出的 Message
|
||||
// Standard Output Message
|
||||
const messageStand = {
|
||||
bot_id: sdkProps.bot_id,
|
||||
role: 'user',
|
||||
@@ -230,7 +230,7 @@ describe('创建消息', () => {
|
||||
const options = { section_id: '123' };
|
||||
|
||||
// Execute
|
||||
// @ts-expect-error -- 测试文件
|
||||
// @ts-expect-error -- test file
|
||||
const message = chat.createFileMessage(props, options);
|
||||
|
||||
// Assert
|
||||
@@ -248,7 +248,7 @@ describe('创建消息', () => {
|
||||
},
|
||||
{
|
||||
type: ContentType.File,
|
||||
// @ts-expect-error -- 测试文件
|
||||
// @ts-expect-error -- test file
|
||||
file: {
|
||||
type: 'pdf',
|
||||
name: 'file.pdf',
|
||||
@@ -258,7 +258,7 @@ describe('创建消息', () => {
|
||||
},
|
||||
{
|
||||
type: ContentType.Image,
|
||||
// @ts-expect-error -- 测试文件
|
||||
// @ts-expect-error -- test file
|
||||
file: {
|
||||
type: 'png',
|
||||
name: 'image.png',
|
||||
@@ -310,7 +310,7 @@ describe('创建消息', () => {
|
||||
],
|
||||
};
|
||||
|
||||
// 标准输出的 Message
|
||||
// Standard Output Message
|
||||
const messageStand = {
|
||||
bot_id: sdkProps.bot_id,
|
||||
role: 'user',
|
||||
@@ -395,7 +395,7 @@ describe('创建消息', () => {
|
||||
],
|
||||
};
|
||||
|
||||
// 标准输出的 Message
|
||||
// Standard Output Message
|
||||
const messageStand = {
|
||||
bot_id: sdkProps.bot_id,
|
||||
role: 'user',
|
||||
|
||||
@@ -106,7 +106,7 @@ describe('SendMessageService', () => {
|
||||
extra_info: { local_message_id: '456' },
|
||||
};
|
||||
const options: SendMessageOptions = {};
|
||||
// 1s后上传成功
|
||||
// Upload successful after 1s
|
||||
setTimeout(() => {
|
||||
preSendLocalMessageEventsManager.emit(
|
||||
PreSendLocalMessageEventsEnum.FILE_UPLOAD_STATUS_CHANGE,
|
||||
@@ -119,7 +119,7 @@ describe('SendMessageService', () => {
|
||||
},
|
||||
);
|
||||
}, 1000);
|
||||
// 2s后发送成功
|
||||
// Sent successfully after 2s
|
||||
setTimeout(() => {
|
||||
preSendLocalMessageEventsManager.emit(
|
||||
PreSendLocalMessageEventsEnum.MESSAGE_SEND_SUCCESS,
|
||||
@@ -144,7 +144,7 @@ describe('SendMessageService', () => {
|
||||
extra_info: { local_message_id: '789' },
|
||||
};
|
||||
const options: SendMessageOptions = {};
|
||||
// 1s后上传成功
|
||||
// Upload successful after 1s
|
||||
setTimeout(() => {
|
||||
preSendLocalMessageEventsManager.emit(
|
||||
PreSendLocalMessageEventsEnum.FILE_UPLOAD_STATUS_CHANGE,
|
||||
|
||||
@@ -65,10 +65,10 @@ const randomChunkRawList: ChunkRaw[] = Mock.mock({
|
||||
content: '@string',
|
||||
reasoning_content: '@string',
|
||||
message_status: '@RANDOM_MESSAGE_STATUS',
|
||||
message_id: '@string', // 后端消息 id, 可能有多条回复
|
||||
reply_id: '999999999', // 回复 id,query的messageId
|
||||
message_id: '@string', // Backend message id, there may be multiple replies
|
||||
reply_id: '999999999', // Reply id, query messageId
|
||||
extra_info: {
|
||||
local_message_id: '88888888888', // 前端消息 id, 用于预发送消息体更新
|
||||
local_message_id: '88888888888', // Front-end message id, used to pre-send message body updates
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -113,16 +113,16 @@ describe('消息接收测试', () => {
|
||||
reasoning_content: 'I am the last!!!',
|
||||
reply_id: firstTextChunk?.message.reply_id ?? '',
|
||||
extra_info: {
|
||||
input_tokens: '', // 用户 query 消耗的 token
|
||||
output_tokens: '', // llm 输出消耗的 token
|
||||
token: '', // 总的 token 消耗
|
||||
input_tokens: '', // User query consumed token
|
||||
output_tokens: '', // LLM output consumed token
|
||||
token: '', // Total token consumption
|
||||
plugin_status: 'success', // "success" or "fail"
|
||||
time_cost: '', // 中间调用过程的时间
|
||||
time_cost: '', // Intermediate invocation time of procedure
|
||||
workflow_tokens: '',
|
||||
bot_state: '', // { bot_id?: string;agent_id?: string;agent_name?: string; }
|
||||
plugin_request: '', // plugin 请求的参数
|
||||
tool_name: '', // 调用的 plugin 下具体的 api 名称
|
||||
plugin: '', // 调用的 plugin 名称
|
||||
plugin_request: '', // Parameters of the plugin request
|
||||
tool_name: '', // Specific API name under the invoked plugin
|
||||
plugin: '', // Name of the plugin invoked
|
||||
local_message_id:
|
||||
firstTextChunk?.message.extra_info.local_message_id ?? '',
|
||||
},
|
||||
|
||||
@@ -54,7 +54,7 @@ export const testSetup = () => {
|
||||
}),
|
||||
})),
|
||||
}));
|
||||
// mock上传插件实现
|
||||
// Mock upload plugin implementation
|
||||
vi.mock('../src/plugins/upload-plugin', () => ({
|
||||
ChatCoreUploadPlugin: class {
|
||||
eventBus = new eventEmitter();
|
||||
|
||||
@@ -15,26 +15,26 @@
|
||||
*/
|
||||
|
||||
export enum HttpChunkEvents {
|
||||
// 收到消息
|
||||
// Received message
|
||||
MESSAGE_RECEIVED = 'http_chunk_message_received',
|
||||
// 收到消息异常
|
||||
// Abnormal message received
|
||||
MESSAGE_RECEIVED_INVALID = 'http_chunk_message_received_invalid',
|
||||
// 整体拉流超时
|
||||
// overall pull timeout
|
||||
TOTAL_FETCH_TIMEOUT = 'http_chunk_total_fetch_timeout',
|
||||
// 包间超时
|
||||
// Private room timeout
|
||||
BETWEEN_CHUNK_TIMEOUT = 'http_chunk_between_chunk_timeout',
|
||||
// 开始 fetch
|
||||
// Start fetching
|
||||
FETCH_START = 'http_chunk_fetch_start',
|
||||
// fetch 请求成功
|
||||
// Fetch request successful
|
||||
FETCH_SUCCESS = 'http_chunk_fetch_success',
|
||||
// fetch 请求异常
|
||||
// Fetch request exception
|
||||
FETCH_ERROR = 'http_chunk_fetch_error',
|
||||
// 无效的消息格式
|
||||
// Invalid message format
|
||||
INVALID_MESSAGE = 'http_chunk_invalid_message',
|
||||
// 拉流开始
|
||||
// Pull flow starts
|
||||
READ_STREAM_START = 'http_chunk_read_stream_start',
|
||||
// 拉流异常
|
||||
// Pull flow anomaly
|
||||
READ_STREAM_ERROR = 'http_chunk_read_stream_error',
|
||||
// 从 fetch 到 read stream 完整成功
|
||||
// Fetch to read stream full success
|
||||
ALL_SUCCESS = 'http_chunk_all_success',
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* http chunk 的 slardar 自定义事件
|
||||
* HTTP chunk slardar custom event
|
||||
*/
|
||||
export enum SlardarEvents {
|
||||
// 调用 controller.abort 的代码发生的报错 不在预期之内
|
||||
// The error occurred in the code calling controller.abort, which is not expected
|
||||
HTTP_CHUNK_UNEXPECTED_ABORT_ERROR = 'http_chunk_unexpected_abort_error',
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ export class HttpChunk extends CustomEventEmitter {
|
||||
}: HandleMessageParams) => {
|
||||
const { logID, replyID } = fetchDataHelper;
|
||||
|
||||
// 从 fetch 中抛出的数据类型由断言得到 这里运行时保卫一下类型
|
||||
// The data type thrown from fetch is obtained by assertions, here the runtime defends the type
|
||||
if (!inValidChunkRaw(data)) {
|
||||
this.customEmit(HttpChunkEvents.INVALID_MESSAGE, {
|
||||
logID,
|
||||
@@ -111,19 +111,19 @@ export class HttpChunk extends CustomEventEmitter {
|
||||
|
||||
private pullMessage = async ({
|
||||
value,
|
||||
// TODO: 本期没有做消息重试
|
||||
// TODO: There is no message retry in this issue
|
||||
isRePullMessage: _isRePullMessage,
|
||||
fetchDataHelper,
|
||||
fetchUrl,
|
||||
scene,
|
||||
}: {
|
||||
value: Record<string, unknown>; // 短链入参:直接透传body不做特化处理,在外层处理业务逻辑
|
||||
value: Record<string, unknown>; // Short URL imported parameters: direct pass-through body does not do specialized processing, external processing business logic
|
||||
isRePullMessage: boolean;
|
||||
fetchDataHelper: FetchDataHelper;
|
||||
fetchUrl: string; // 短链链接
|
||||
fetchUrl: string; // Short URL Link
|
||||
scene: RequestScene;
|
||||
}) => {
|
||||
// TODO: hzf,不使用三元表达式
|
||||
// TODO: hzf, does not use ternary expressions
|
||||
const headers: [string, string][] = [
|
||||
['content-type', 'application/json'],
|
||||
...((this.tokenManager?.getApiKeyAuthorizationValue()
|
||||
@@ -138,7 +138,7 @@ export class HttpChunk extends CustomEventEmitter {
|
||||
const { hooks } = this.requestManager.getSceneConfig?.(scene) || {};
|
||||
const { onBeforeSendMessage = [], onGetMessageStreamParser } = hooks || {};
|
||||
|
||||
// 如下参数可做修改
|
||||
// The following parameters can be modified
|
||||
let channelFetchInfo = {
|
||||
url: fetchUrl,
|
||||
body: JSON.stringify(value),
|
||||
@@ -241,10 +241,10 @@ export class HttpChunk extends CustomEventEmitter {
|
||||
|
||||
return;
|
||||
|
||||
// TODO: 下面应该是重新拉取 message 的逻辑 本期服务端没有来得及做
|
||||
// TODO: The following should be the logic to re-pull the message. The server level did not have time to do it in this issue.
|
||||
// if (dataClump.retryCounter.matchMaxRetryAttempts()) {
|
||||
// this.customOnError?.(errorInfo);
|
||||
// // 放弃尝试重试
|
||||
// //give up trying and try again
|
||||
// this.handleFinish();
|
||||
// return;
|
||||
// }
|
||||
@@ -252,12 +252,12 @@ export class HttpChunk extends CustomEventEmitter {
|
||||
// dataClump.retryCounter.add();
|
||||
};
|
||||
|
||||
// 调用chat、resume接口发送消息,已经在上层抹平差异
|
||||
// Call the chat and resume interfaces to send messages, which has smoothed the difference at the upper level.
|
||||
sendMessage = (value: SendMessage, config?: SendMessageConfig) => {
|
||||
const localMessageID = value.local_message_id;
|
||||
|
||||
if (!localMessageID) {
|
||||
// TODO: 用同一的异常类
|
||||
// TODO: Use the same exception class
|
||||
this.customEmit(HttpChunkEvents.FETCH_ERROR, {
|
||||
code: FetchStreamErrorCode.FetchException,
|
||||
msg: 'SendMessageError: SendMessage is Invalid',
|
||||
@@ -281,7 +281,7 @@ export class HttpChunk extends CustomEventEmitter {
|
||||
this.fetchDataHelperMap.set(localMessageID, fetchDataHelper);
|
||||
|
||||
const scene = config?.requestScene || RequestScene.SendMessage;
|
||||
// 获取消息短链请求链接
|
||||
// Get short URL request link
|
||||
const { url, baseURL } = this.requestManager.getSceneConfig?.(scene) || {};
|
||||
|
||||
const fetchUrl = baseURL ? `${baseURL}${url}` : url;
|
||||
|
||||
@@ -55,7 +55,7 @@ export interface MessageLifecycleCallbackParams
|
||||
|
||||
export type OnMessageCallback = (messageEvent: OnMessageCallbackParams) => void;
|
||||
/**
|
||||
* 收到的消息结构体异常响应此错误
|
||||
* The received message structure responded abnormally to this error
|
||||
*/
|
||||
export type OnMessageInvalidCallback = (
|
||||
error: HttpChunkMessageInvalidErrorInfo,
|
||||
@@ -68,7 +68,7 @@ export type OnMessageStartCallback = (
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* HttpChunk 未能建连、意外断开、Abort
|
||||
* HttpChunk failed to connect, accidentally disconnected, aborted
|
||||
*/
|
||||
export type OnErrorCallback = (errorInfo: ErrorInfo) => void;
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ export const streamParser: FetchSteamConfig<
|
||||
case ChunkEvent.DONE:
|
||||
terminate();
|
||||
return;
|
||||
// 对话过程中出现异常,例如:token 消耗完了
|
||||
// An exception occurs during the conversation, for example: the token is exhausted
|
||||
case ChunkEvent.ERROR:
|
||||
return { event, data };
|
||||
default:
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
export enum SdkEventsEnum {
|
||||
MESSAGE_RECEIVED_AND_UPDATE = 'message_received_and_update',
|
||||
/**
|
||||
* 监测拉取回复消息状态变化
|
||||
* Monitor pull reply message status changes
|
||||
*/
|
||||
MESSAGE_PULLING_STATUS = 'message_pulling_status',
|
||||
ERROR = 'error',
|
||||
|
||||
@@ -18,23 +18,23 @@ import { type ReportLog, type Tracer } from '../../report-log';
|
||||
import type { ChatCoreError } from '../../custom-error';
|
||||
|
||||
/**
|
||||
* 承接所有 sdk 的 slardar 自定义事件
|
||||
* Undertake all sdk slardar custom events
|
||||
*/
|
||||
export enum SlardarEvents {
|
||||
// sdk初始化,用于数据统计
|
||||
// SDK initialization for data statistics
|
||||
SDK_INIT = 'chat_sdk_init',
|
||||
// 上传失败
|
||||
// Upload failed.
|
||||
SDK_MESSAGE_UPLOAD_FAIL = 'chat_sdk_message_upload_fail',
|
||||
// 打断消息
|
||||
// interrupt message
|
||||
SDK_BREAK_MESSAGE = 'chat_sdk_break_message',
|
||||
// 消息发送链路监控
|
||||
// messaging link monitoring
|
||||
SDK_MESSAGE_SEND_TRACER = 'chat_sdk_message_send_tracer',
|
||||
// 拉流链路耗时监控
|
||||
// Pull link time monitoring
|
||||
SDK_PULL_STREAM_TRACER = 'chat_sdk_pull_stream_tracer',
|
||||
}
|
||||
|
||||
/**
|
||||
* slardar事件追踪
|
||||
* Slardar Event Tracking
|
||||
*/
|
||||
export class ReportEventsTracer {
|
||||
private reporter: ReportLog;
|
||||
@@ -52,7 +52,7 @@ export class ReportEventsTracer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息发送事件追踪
|
||||
* Messaging Event Tracking
|
||||
*/
|
||||
sendMessageTracer = {
|
||||
start: (local_message_id: string, meta?: Record<string, unknown>) => {
|
||||
@@ -111,7 +111,7 @@ export class ReportEventsTracer {
|
||||
};
|
||||
|
||||
/*
|
||||
* 拉取流事件追踪
|
||||
* Pull stream event tracking
|
||||
*/
|
||||
pullStreamTracer = {
|
||||
start: (local_message_id: string, meta?: Record<string, unknown>) => {
|
||||
@@ -139,7 +139,7 @@ export class ReportEventsTracer {
|
||||
local_message_id,
|
||||
SlardarEvents.SDK_PULL_STREAM_TRACER,
|
||||
);
|
||||
// 打断算成功
|
||||
// Interrupt is successful
|
||||
trace?.('success', {
|
||||
meta,
|
||||
});
|
||||
@@ -202,14 +202,14 @@ export class ReportEventsTracer {
|
||||
};
|
||||
|
||||
/**
|
||||
* 组装获取唯一key
|
||||
* Assemble to get unique key
|
||||
*/
|
||||
static getUniqueKey(local_message_id: string, event: SlardarEvents): string {
|
||||
return `${local_message_id}_${event}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据local_message_id、event获取trace
|
||||
* Get trace based on local_message_id, event
|
||||
*/
|
||||
getTracer(local_message_id: string, event: SlardarEvents) {
|
||||
return (
|
||||
@@ -222,7 +222,7 @@ export class ReportEventsTracer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据local_message_id、event新增trace
|
||||
* Add trace based on local_message_id and event
|
||||
*/
|
||||
setTracer(
|
||||
local_message_id: string,
|
||||
@@ -243,7 +243,7 @@ export class ReportEventsTracer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除trace
|
||||
* Delete trace
|
||||
*/
|
||||
deleteTracer(local_message_id: string, event: SlardarEvents) {
|
||||
this.eventTracers.delete(
|
||||
@@ -252,7 +252,7 @@ export class ReportEventsTracer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建trace
|
||||
* Create trace
|
||||
*/
|
||||
createTracer(eventName: SlardarEvents) {
|
||||
return this.reporter.slardarTracer({
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
/**
|
||||
* @module @coze-common/chat-core
|
||||
* 暴露所有对外接口
|
||||
* Expose all external interfaces
|
||||
*/
|
||||
import EventEmitter from 'eventemitter3';
|
||||
import { type InternalAxiosRequestConfig } from 'axios';
|
||||
@@ -74,19 +74,19 @@ import { ReportEventsTracer, SlardarEvents } from './events/slardar-events';
|
||||
export default class ChatSDK {
|
||||
private static instances: Map<string, ChatSDK> = new Map();
|
||||
/**
|
||||
* 预发送消息工厂: 创建预发送消息用于上屏
|
||||
* Pre-send Message Factory: Create pre-send messages for use on the screen
|
||||
*/
|
||||
private preSendLocalMessageFactory!: PreSendLocalMessageFactory;
|
||||
|
||||
/**
|
||||
* 处理接收到的 chunk 消息,处理成统一 Message 格式
|
||||
* Process received chunk messages into a unified message format
|
||||
*/
|
||||
private chunkProcessor!: ChunkProcessor;
|
||||
|
||||
private messageManager!: MessageManager;
|
||||
|
||||
/**
|
||||
* stream拉流
|
||||
* Streaming
|
||||
*/
|
||||
private httpChunk!: HttpChunk;
|
||||
|
||||
@@ -97,7 +97,7 @@ export default class ChatSDK {
|
||||
private requestManager!: RequestManager;
|
||||
|
||||
/**
|
||||
* 维护本地消息的发送事件:
|
||||
* Maintain local message sending events:
|
||||
*/
|
||||
|
||||
private preSendLocalMessageEventsManager!: PreSendLocalMessageEventsManager;
|
||||
@@ -113,15 +113,15 @@ export default class ChatSDK {
|
||||
preset_bot!: PresetBot;
|
||||
|
||||
/**
|
||||
* 目前chat-core生命周期内以一个 bot_id、user 为维度
|
||||
* 后续如果支持一个 user对应多个 conversation_id,需要调整
|
||||
* The current chat-core life cycle takes a bot_id and user as dimensions
|
||||
* If one user is supported for multiple conversation_id, it needs to be adjusted
|
||||
*/
|
||||
user!: string;
|
||||
|
||||
scene?: Scene;
|
||||
|
||||
/**
|
||||
* 使用环境
|
||||
* usage environment
|
||||
*/
|
||||
env!: ENV;
|
||||
|
||||
@@ -156,7 +156,7 @@ export default class ChatSDK {
|
||||
private pluginsService!: PluginsService;
|
||||
|
||||
constructor(props: CreateProps) {
|
||||
/** 初始化构造参数 */
|
||||
/** Initialize construction parameters */
|
||||
this.initProps(props);
|
||||
this.initModules(props);
|
||||
this.initServices();
|
||||
@@ -168,13 +168,13 @@ export default class ChatSDK {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建chatBot实例
|
||||
*1. 对于同一个 bot_id/preset_bot, 重复调用,sdk 只会创建一个实例
|
||||
*2. 多个 bot_id/presetBot,对应多个 sdk 实例,维护自己的events
|
||||
* Create a chatBot instance
|
||||
*1. For the same bot_id/preset_bot, repeated calls, sdk will only create one instance
|
||||
*2. Multiple bot_id/presetBot, corresponding to multiple SDK instances, maintaining its own events
|
||||
*/
|
||||
static create(props: CreateProps) {
|
||||
const { unique_key } = ChatSDK.getUniqueKey(props);
|
||||
// 对于同一个 bot_id/preset_bot, 重复调用,create只会创建一个实例
|
||||
// For the same bot_id/preset_bot, repeated calls, create will only create one instance
|
||||
if (ChatSDK.instances.has(unique_key)) {
|
||||
console.error('duplicate chat core instance error');
|
||||
return ChatSDK.instances.get(unique_key);
|
||||
@@ -186,7 +186,7 @@ export default class ChatSDK {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 sdk 唯一键 preset_bot > bot_id
|
||||
* Get sdk unique key preset_bot > bot_id
|
||||
* @param props
|
||||
* @returns
|
||||
*/
|
||||
@@ -240,7 +240,7 @@ export default class ChatSDK {
|
||||
this.draft_mode = draft_mode;
|
||||
}
|
||||
|
||||
/** 初始化依赖Module实例 */
|
||||
/** Initializing Dependency Module Instances */
|
||||
private initModules(props: CreateProps) {
|
||||
this.initReportLog();
|
||||
this.reportEventsTracer = new ReportEventsTracer(this.reportLogWithScope);
|
||||
@@ -250,7 +250,7 @@ export default class ChatSDK {
|
||||
new PreSendLocalMessageEventsManager({
|
||||
reportLog: this.reportLog,
|
||||
});
|
||||
/** 初始化预发送消息工厂 */
|
||||
/** Initialize the pre-sent message factory */
|
||||
this.preSendLocalMessageFactory = new PreSendLocalMessageFactory({
|
||||
bot_id: this.bot_id,
|
||||
preset_bot: this.preset_bot,
|
||||
@@ -260,7 +260,7 @@ export default class ChatSDK {
|
||||
bot_version: this.bot_version,
|
||||
draft_mode: this.draft_mode,
|
||||
});
|
||||
/** 初始化处理接收到的 chunk 消息,处理成统一 Message 格式 */
|
||||
/** Initialize processing of received chunk messages into a unified message format */
|
||||
this.chunkProcessor = new ChunkProcessor({
|
||||
bot_id: this.bot_id,
|
||||
preset_bot: this.preset_bot,
|
||||
@@ -272,7 +272,7 @@ export default class ChatSDK {
|
||||
reportLogWithScope: this.reportLogWithScope,
|
||||
});
|
||||
/**
|
||||
* 初始化消息管理器:消息删除/历史等
|
||||
* Initialize the message manager: message deletion/history, etc
|
||||
*/
|
||||
this.messageManager = new MessageManager({
|
||||
reportLog: this.reportLog,
|
||||
@@ -371,23 +371,23 @@ export default class ChatSDK {
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁 SDK 实例。
|
||||
* 清空所有监听事件
|
||||
* Destroy the SDK instance.
|
||||
* Clear all listening events
|
||||
*/
|
||||
destroy() {
|
||||
// 清空所有httpChunk监听事件
|
||||
// Clear all htpChunk listening events
|
||||
this.httpChunk.drop();
|
||||
// 清空sdk时间
|
||||
// Clear sdk time
|
||||
this.eventBus.removeAllListeners();
|
||||
// 清空所有缓存的 chunk 消息
|
||||
// Clear all cached chunks
|
||||
this.chunkProcessor.streamBuffer.clearMessageBuffer();
|
||||
// 清除对应的实例
|
||||
// Clear the corresponding instance
|
||||
const { unique_key } = ChatSDK.getUniqueKey({
|
||||
bot_id: this.bot_id,
|
||||
preset_bot: this.preset_bot,
|
||||
});
|
||||
ChatSDK.instances.delete(unique_key);
|
||||
// 清除预发送消息缓存
|
||||
// Clear pre-sent message cache
|
||||
this.preSendLocalMessageEventsManager.destroy();
|
||||
this.reportLogWithScope.info({
|
||||
message: 'SDK销毁',
|
||||
@@ -395,10 +395,10 @@ export default class ChatSDK {
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听sdk事件
|
||||
* Monitor sdk events
|
||||
*/
|
||||
on<T extends SdkEventsEnum>(event: T, fn: SdkEventsCallbackMap[T]) {
|
||||
// 重复监听,错误提示
|
||||
// Repeated listening, error message
|
||||
if (this.eventBus.eventNames().includes(event)) {
|
||||
this.reportLogWithScope.slardarError({
|
||||
message: '重复监听事件',
|
||||
|
||||
@@ -56,7 +56,7 @@ export class CreateMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文本消息
|
||||
* Create text message
|
||||
*/
|
||||
createTextMessage(
|
||||
props: TextMessageProps,
|
||||
@@ -70,7 +70,7 @@ export class CreateMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建图片消息
|
||||
* Create image message
|
||||
*/
|
||||
createImageMessage<M extends EventPayloadMaps = EventPayloadMaps>(
|
||||
props: ImageMessageProps<M>,
|
||||
@@ -94,7 +94,7 @@ export class CreateMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件消息
|
||||
* Create file message
|
||||
*/
|
||||
createFileMessage<M extends EventPayloadMaps = EventPayloadMaps>(
|
||||
props: FileMessageProps<M>,
|
||||
@@ -118,7 +118,7 @@ export class CreateMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建图文混合消息
|
||||
* Create a mixed message
|
||||
*/
|
||||
createTextAndFileMixMessage(
|
||||
props: TextAndFileMixMessageProps,
|
||||
@@ -132,7 +132,7 @@ export class CreateMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建标准化消息,已经处理好payload content结构的消息
|
||||
* Create standardized messages, messages with payload content structure already processed
|
||||
*/
|
||||
createNormalizedPayloadMessage<T extends ContentType>(
|
||||
props: NormalizedMessageProps<T>,
|
||||
|
||||
@@ -77,29 +77,29 @@ export class HttpChunkService {
|
||||
this.chatSdkEventBus = chatSdkEventBus;
|
||||
}
|
||||
/**
|
||||
* 处理channel监听到的事件
|
||||
* Handle events listened to by the channel
|
||||
*/
|
||||
onHttpChunkEvents() {
|
||||
this.httpChunk.on(
|
||||
HttpChunkEvents.FETCH_START,
|
||||
this.handleHttpChunkFetchStart,
|
||||
);
|
||||
// 读取流
|
||||
// read stream
|
||||
this.httpChunk.on(
|
||||
HttpChunkEvents.MESSAGE_RECEIVED,
|
||||
this.handleHttpChunkMessageReceived,
|
||||
);
|
||||
// 整体拉流成功
|
||||
// Overall flow success
|
||||
this.httpChunk.on(
|
||||
HttpChunkEvents.ALL_SUCCESS,
|
||||
this.handleHttpChunkStreamSuccess,
|
||||
);
|
||||
// 开始读取流
|
||||
// Start reading stream
|
||||
this.httpChunk.on(
|
||||
HttpChunkEvents.READ_STREAM_START,
|
||||
this.handleHttpChunkReadStreamStart,
|
||||
);
|
||||
// fetch阶段异常, 还没到读流阶段
|
||||
// Fetch phase exception, not yet reached the read stream phase
|
||||
this.httpChunk.on(
|
||||
HttpChunkEvents.FETCH_ERROR,
|
||||
this.handleHttpChunkFetchError,
|
||||
@@ -108,7 +108,7 @@ export class HttpChunkService {
|
||||
HttpChunkEvents.READ_STREAM_ERROR,
|
||||
this.handleReadStreamError,
|
||||
);
|
||||
// 包间超时
|
||||
// Private room timeout
|
||||
this.httpChunk.on(
|
||||
HttpChunkEvents.BETWEEN_CHUNK_TIMEOUT,
|
||||
this.handleHttpChunkTimeout,
|
||||
@@ -130,7 +130,7 @@ export class HttpChunkService {
|
||||
ackMessage?.extra_info || receiveMessage.chunk.message.extra_info;
|
||||
|
||||
let pullingStatus: PullingStatus = 'pulling';
|
||||
// 判断是否是final answer
|
||||
// Is it the final answer?
|
||||
if (this.chunkProcessor.isMessageAnswerEnd(chunk)) {
|
||||
pullingStatus = 'answerEnd';
|
||||
}
|
||||
@@ -148,7 +148,7 @@ export class HttpChunkService {
|
||||
.eventNames()
|
||||
.includes(SdkEventsEnum.MESSAGE_RECEIVED_AND_UPDATE);
|
||||
|
||||
// 判断接收到的消息是否已经存在
|
||||
// Determine whether the received message already exists
|
||||
if (this.chunkProcessor.isFirstReplyMessage(chunk)) {
|
||||
this.reportEventsTracer?.pullStreamTracer?.receiveFirstAnsChunk(
|
||||
local_message_id,
|
||||
@@ -189,7 +189,7 @@ export class HttpChunkService {
|
||||
});
|
||||
};
|
||||
|
||||
// 读取流异常
|
||||
// read stream exception
|
||||
private handleReadStreamError = (errorInfo: ErrorInfo) => {
|
||||
const {
|
||||
ext: {
|
||||
@@ -212,7 +212,7 @@ export class HttpChunkService {
|
||||
const stashedAckMessage =
|
||||
this.chunkProcessor.getAckMessageByLocalMessageId(local_message_id);
|
||||
|
||||
// 读取流异常,要区分在首包接受到了么
|
||||
// The read stream is abnormal, do you want to distinguish between receiving it in the first package?
|
||||
if (!stashedAckMessage) {
|
||||
this.preSendLocalMessageEventsManager.emit(
|
||||
PreSendLocalMessageEventsEnum.MESSAGE_SEND_FAIL,
|
||||
@@ -221,7 +221,7 @@ export class HttpChunkService {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果是发送消息成功,则表示是拉流阶段失败
|
||||
// If the message is sent successfully, it means that the pull phase failed.
|
||||
if (stashedAckMessage) {
|
||||
this.chatSdkEventEmit(SdkEventsEnum.MESSAGE_PULLING_STATUS, {
|
||||
name: SdkEventsEnum.MESSAGE_PULLING_STATUS,
|
||||
@@ -240,7 +240,7 @@ export class HttpChunkService {
|
||||
});
|
||||
};
|
||||
|
||||
// fetch异常,还没到拉流阶段
|
||||
// Fetch is abnormal, it has not yet reached the pull flow stage
|
||||
private handleHttpChunkFetchError = (errorInfo: ErrorInfo) => {
|
||||
const {
|
||||
ext: {
|
||||
|
||||
@@ -85,7 +85,7 @@ export class MessageManagerService {
|
||||
this.reportLogWithScope = reportLogWithScope;
|
||||
}
|
||||
/**
|
||||
* 获取历史消息
|
||||
* Get chat history
|
||||
*/
|
||||
async getHistoryMessage(props: GetHistoryMessageParams) {
|
||||
const params = filterEmptyField({
|
||||
@@ -103,7 +103,7 @@ export class MessageManagerService {
|
||||
MessageManager.convertMessageList(data);
|
||||
|
||||
/**
|
||||
* 清空对话上下文
|
||||
* Clear the conversation context
|
||||
*/
|
||||
async clearMessageContext(params: ClearMessageContextParams) {
|
||||
return await this.messageManager.clearMessageContextUrl({
|
||||
@@ -114,7 +114,7 @@ export class MessageManagerService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空历史
|
||||
* Clear history
|
||||
*/
|
||||
async clearHistory() {
|
||||
return await this.messageManager.clearHistory({
|
||||
@@ -125,7 +125,7 @@ export class MessageManagerService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除消息
|
||||
* delete message
|
||||
*/
|
||||
async deleteMessage(params: DeleteMessageParams) {
|
||||
return await this.messageManager.deleteMessage({
|
||||
@@ -137,7 +137,7 @@ export class MessageManagerService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞/点踩消息
|
||||
* Like/click on the message
|
||||
*/
|
||||
async reportMessage(params: ReportMessageParams) {
|
||||
return await this.messageManager.reportMessage({
|
||||
@@ -149,7 +149,7 @@ export class MessageManagerService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 打断消息
|
||||
* interrupt message
|
||||
*/
|
||||
async breakMessage(params: BreakMessageParams) {
|
||||
this.httpChunk.abort(params.local_message_id);
|
||||
@@ -173,7 +173,7 @@ export class MessageManagerService {
|
||||
}
|
||||
|
||||
/**
|
||||
* ASR 语音转文字
|
||||
* ASR speech-to-text
|
||||
*/
|
||||
async chatASR(params: ChatASRParams) {
|
||||
return await this.messageManager.chatASR(params);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import { exhaustiveCheckSimple } from '@coze-common/chat-area-utils';
|
||||
|
||||
import type { UploadPluginConstructor } from '@/plugins/upload-plugin/types/plugin-upload';
|
||||
@@ -21,12 +21,12 @@ import type { UploadPluginConstructor } from '@/plugins/upload-plugin/types/plug
|
||||
import type { PluginKey, PluginValue } from '../types/interface';
|
||||
|
||||
export class PluginsService {
|
||||
//eslint-disable-next-line @typescript-eslint/no-explicit-any -- 暂时没想到合适的类型体操, 先用 any,
|
||||
//eslint-disable-next-line @typescript-eslint/no-explicit-any -- I didn't think of a suitable type of gymnastics for the time being, use any first,
|
||||
UploadPlugin: UploadPluginConstructor<any> | null = null;
|
||||
uploadPluginConstructorOptions: Record<string, unknown> = {};
|
||||
|
||||
/**
|
||||
* 注册插件
|
||||
* Register plugin
|
||||
*/
|
||||
registerPlugin<T extends PluginKey, P extends Record<string, unknown>>(
|
||||
key: T,
|
||||
@@ -40,7 +40,7 @@ export class PluginsService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查插件是否已经注册过
|
||||
* Check if the plugin has been registered
|
||||
*/
|
||||
checkPluginIsRegistered(key: PluginKey): boolean {
|
||||
if (key === 'upload-plugin') {
|
||||
|
||||
@@ -66,7 +66,7 @@ export class SendMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送resume消息
|
||||
* Send resume message
|
||||
*/
|
||||
resumeMessage(message: Message<ContentType>, options?: SendMessageOptions) {
|
||||
const mergedOptions: SendMessageMergedOptions = {
|
||||
@@ -92,7 +92,7 @@ export class SendMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
* Send message
|
||||
*/
|
||||
async sendMessage(
|
||||
message: Message<ContentType>,
|
||||
@@ -134,7 +134,7 @@ export class SendMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送图片消息
|
||||
* Send picture message
|
||||
*/
|
||||
private async sendImageMessage(
|
||||
message: PreSendLocalMessage<ContentType.Image>,
|
||||
@@ -150,7 +150,7 @@ export class SendMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送文件消息
|
||||
* Send file message
|
||||
* @param message
|
||||
* @param options
|
||||
* @private
|
||||
@@ -169,7 +169,7 @@ export class SendMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送文本消息
|
||||
* Send a text message
|
||||
*/
|
||||
private async sendTextMessage(
|
||||
message: PreSendLocalMessage<ContentType.Text>,
|
||||
@@ -181,26 +181,26 @@ export class SendMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片&文件上传事件完成
|
||||
* Upload image & file upload event complete
|
||||
*/
|
||||
private onUploadEventFinish<T extends ContentType.Image | ContentType.File>(
|
||||
message: PreSendLocalMessage<T>,
|
||||
sendMessageOptions?: SendMessageOptions,
|
||||
): Promise<PreSendLocalMessage<T>> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 如果是重新生成消息,直接返回
|
||||
// If it is to regenerate the message, return it directly.
|
||||
if (sendMessageOptions?.isRegenMessage) {
|
||||
resolve(message);
|
||||
return;
|
||||
}
|
||||
// 根据 message_id 查询是否已经上传完成
|
||||
// According to message_id, check whether the upload has been completed
|
||||
const stashedLocalMessage =
|
||||
this.preSendLocalMessageEventsManager.getStashedLocalMessage(
|
||||
message.extra_info.local_message_id,
|
||||
) as PreSendLocalMessage<T>;
|
||||
if (stashedLocalMessage?.file_upload_result) {
|
||||
if (stashedLocalMessage?.file_upload_result === 'success') {
|
||||
// todo 改成直接 resolve message,stashed 不应存入全量 request,容易引起误会
|
||||
// Todo is changed to directly resolve message, stashed should not be stored in the full amount of requests, which is easy to cause misunderstandings
|
||||
resolve(message);
|
||||
return;
|
||||
}
|
||||
@@ -214,7 +214,7 @@ export class SendMessageService {
|
||||
return;
|
||||
}
|
||||
|
||||
// 消息上传完成
|
||||
// Message upload complete
|
||||
this.preSendLocalMessageEventsManager.on(
|
||||
PreSendLocalMessageEventsEnum.FILE_UPLOAD_STATUS_CHANGE,
|
||||
(preSendLocalMessage: Message<ContentType>) => {
|
||||
@@ -241,9 +241,9 @@ export class SendMessageService {
|
||||
}
|
||||
|
||||
/**
|
||||
* httpChunk 发送消息事件模式改为 await 模式
|
||||
* @param message 最终要发送给服务端的消息格式
|
||||
* @param options 发送消息配置
|
||||
* HttpChunk send message event mode changed to await mode
|
||||
* @Param message The final message format to be sent to the server
|
||||
* @Param options send message configuration
|
||||
*/
|
||||
private sendChannelMessage(
|
||||
message: SendMessage,
|
||||
@@ -282,7 +282,7 @@ export class SendMessageService {
|
||||
headers,
|
||||
requestScene: RequestScene.SendMessage,
|
||||
});
|
||||
// 监听消息发送成功
|
||||
// The monitor message was sent successfully.
|
||||
this.preSendLocalMessageEventsManager.once(
|
||||
PreSendLocalMessageEventsEnum.MESSAGE_SEND_SUCCESS,
|
||||
(receiveMessage: Message<ContentType>) => {
|
||||
@@ -307,7 +307,7 @@ export class SendMessageService {
|
||||
resolve(receiveMessage);
|
||||
},
|
||||
);
|
||||
// 监听消息发送失败
|
||||
// Listening message sending failed
|
||||
this.preSendLocalMessageEventsManager.once(
|
||||
PreSendLocalMessageEventsEnum.MESSAGE_SEND_FAIL,
|
||||
(error: ChatCoreError) => {
|
||||
|
||||
@@ -39,9 +39,9 @@ export type BotUnique =
|
||||
}
|
||||
| {
|
||||
/**
|
||||
* 使用的bot模版 代替bot_id bot_version draft_mode参数
|
||||
* 非安全考虑,仅不想暴露bot_id的情况下使用
|
||||
* botId、presetBot必传其一
|
||||
* Use the bot template instead of bot_id bot_version draft_mode parameters
|
||||
* For non-safety reasons, use only if you don't want to expose bot_id
|
||||
* botId, presetBot must pass one
|
||||
*/
|
||||
preset_bot: PresetBot;
|
||||
};
|
||||
@@ -53,66 +53,66 @@ export const isPresetBotUnique = <T extends BotUnique>(
|
||||
|
||||
export type CreateProps = BotUnique & {
|
||||
/**
|
||||
* 用于计算资源点消耗
|
||||
* For computing resource point consumption
|
||||
*/
|
||||
space_id?: string;
|
||||
/**
|
||||
* 业务方标识,用于埋点记录
|
||||
* Business party ID for event tracking
|
||||
*/
|
||||
biz: Biz;
|
||||
/**
|
||||
* bot 版本号
|
||||
* bot version number
|
||||
*/
|
||||
bot_version?: string;
|
||||
|
||||
/**
|
||||
* 草稿bot or 线上bot,
|
||||
* Draft bots or online bots,
|
||||
*/
|
||||
draft_mode?: boolean;
|
||||
|
||||
/**
|
||||
* 会话 id
|
||||
* session id
|
||||
*/
|
||||
conversation_id: string;
|
||||
|
||||
/**
|
||||
* 指定发送的唯一用户
|
||||
* Specify the unique user to send
|
||||
*/
|
||||
user?: string;
|
||||
|
||||
/**
|
||||
* 场景值,主要用于服务端鉴权, 默认 0 default
|
||||
* Scene value, mainly used for server level authentication, default 0 default
|
||||
*/
|
||||
scene?: Scene;
|
||||
|
||||
/**
|
||||
* 环境变量,区分测试环境和线上环境
|
||||
* 用于日志上报
|
||||
* Environment variables to distinguish between testing environment and online environment
|
||||
* For log reporting
|
||||
*/
|
||||
env: ENV;
|
||||
|
||||
/**
|
||||
* 区分部署版本
|
||||
* Differentiate deployment versions
|
||||
*/
|
||||
|
||||
deployVersion: DeployVersion;
|
||||
|
||||
/**
|
||||
* 是否开启 debug模式,目前主要给 bot editor 使用
|
||||
* 开启后,每条回复消息新增debug_messages字段,包含channel 吐出的所有 chunk消息
|
||||
* Whether to enable debug mode, currently mainly used by the bot editor
|
||||
* After opening, each reply message adds debug_messages field, including all chunk messages spat out by the channel
|
||||
**/
|
||||
enableDebug?: boolean;
|
||||
/**
|
||||
* sdk 控制台日志等级,默认error, 后面层级会包含前面层级
|
||||
* SDK console log level, default error, the following level will contain the previous level
|
||||
**/
|
||||
logLevel?: LogLevel;
|
||||
/**
|
||||
接口拦截器
|
||||
Interface blocker
|
||||
**/
|
||||
requestManagerOptions?: RequestManagerOptions;
|
||||
|
||||
/**
|
||||
* token 刷新机制
|
||||
* Token refresh mechanism
|
||||
*/
|
||||
tokenManager?: TokenManager;
|
||||
};
|
||||
@@ -142,15 +142,15 @@ export interface SdkPullingStatusEvent {
|
||||
name: SdkEventsEnum;
|
||||
data: {
|
||||
/**
|
||||
* 拉取回复消息状态
|
||||
* Pull reply message status
|
||||
*/
|
||||
pullingStatus: PullingStatus;
|
||||
/**
|
||||
* query 的本地 id
|
||||
* Local ID of the query
|
||||
*/
|
||||
local_message_id: string;
|
||||
/**
|
||||
* query 的服务端 message_id
|
||||
* The server level of the query message_id
|
||||
*/
|
||||
reply_id: string;
|
||||
};
|
||||
@@ -158,7 +158,7 @@ export interface SdkPullingStatusEvent {
|
||||
error?: ChatCoreError;
|
||||
|
||||
/**
|
||||
* timeout 状态下返回,用于终止拉取
|
||||
* Returns in timeout state to terminate the pull
|
||||
* @returns
|
||||
*/
|
||||
abort?: () => void;
|
||||
@@ -180,17 +180,17 @@ export type PluginValue<
|
||||
> = T extends 'upload-plugin' ? UploadPluginConstructor<P> : never;
|
||||
|
||||
/**
|
||||
* 接入的业务方向
|
||||
* 目前采用枚举接入,控制接入方向
|
||||
* third_part给open_api sdk使用,暴露给第三方
|
||||
* Access business direction
|
||||
* Currently, enumeration access is used to control the access direction
|
||||
* third_part used by open_api SDK, exposed to third parties
|
||||
*/
|
||||
export type Biz = 'coze_home' | 'bot_editor' | 'third_part';
|
||||
|
||||
export type PresetBot = 'coze_home' | 'prompt_optimize' | '';
|
||||
|
||||
/**
|
||||
* 接口也有这个定义 enum Scene.
|
||||
* 注意前端定义与接口完全对齐:
|
||||
* Interfaces also have this definition enum Scene.
|
||||
* Note that the front-end definition is fully aligned with the interface.
|
||||
* src/auto-generate/developer_api/namespaces/developer_api.ts
|
||||
*/
|
||||
export const enum Scene {
|
||||
@@ -198,18 +198,18 @@ export const enum Scene {
|
||||
Explore = 1,
|
||||
BotStore = 2,
|
||||
CozeHome = 3,
|
||||
// 调试区 命名和服务端对齐的
|
||||
// Debug area, named and server level aligned
|
||||
Playground = 4,
|
||||
AgentAPP = 6,
|
||||
PromptOptimize = 7,
|
||||
/**
|
||||
* TODO: 前端单独增加,需要和后端对齐固定一个枚举
|
||||
* TODO: The front end is increased separately, and an enumeration needs to be aligned with the back end.
|
||||
*/
|
||||
OpenAipSdk = 1000,
|
||||
}
|
||||
|
||||
/**
|
||||
* 对齐 developer_api/namespaces/developer_api.ts
|
||||
* Align developer_api/namespaces/developer_api
|
||||
*/
|
||||
export const enum LoadDirection {
|
||||
Unknown = 0,
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 负责 token 验权,自动刷新 token
|
||||
* 暴露给业务方,由业务方决定是否单例还是多例鉴权
|
||||
* Responsible for token verification, automatically refresh the token
|
||||
* Exposed to the service party, the service party decides whether to single-case or multiple-case authentication
|
||||
*/
|
||||
export interface TokenManagerProps {
|
||||
token?: string;
|
||||
@@ -39,10 +39,10 @@ export default class TokenManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 token
|
||||
* Get token
|
||||
*/
|
||||
getToken() {
|
||||
// TODO: 没有 token,获取最新 token
|
||||
// TODO: No token, get the latest token
|
||||
return this.token;
|
||||
}
|
||||
updateToken(token: string) {
|
||||
@@ -53,24 +53,24 @@ export default class TokenManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 apiKey
|
||||
* Get apiKey
|
||||
*/
|
||||
getApiKey() {
|
||||
return this.apiKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 apiKey 组装成的 Authorization 值
|
||||
* Get the Authorization value assembled by apiKey
|
||||
*/
|
||||
getApiKeyAuthorizationValue() {
|
||||
return `Bearer ${this?.getApiKey()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新 apiKey
|
||||
* Refresh apiKey
|
||||
*/
|
||||
refreshApiKey(apiKey: string) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
// TODO: 补充刷新机制
|
||||
// TODO: Supplementary refresh mechanism
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export class ChatCoreError extends Error {
|
||||
}
|
||||
|
||||
/**
|
||||
* 扁平化错误信息,方便在slardar中筛选错误信息
|
||||
* Flatten error messages for easy filtering of error messages in slardar
|
||||
*/
|
||||
flatten = () => {
|
||||
const { message, ext } = this;
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 处理接收到的Chunk消息
|
||||
* 1、预处理:反序列化
|
||||
* 2、增量消息拼接
|
||||
* Process received Chunk messages
|
||||
* 1. Pretreatment: Deserialization
|
||||
* 2. Incremental message splicing
|
||||
*/
|
||||
import { cloneDeep, flow } from 'lodash-es';
|
||||
|
||||
@@ -34,14 +34,14 @@ import {
|
||||
} from './types';
|
||||
|
||||
export class StreamBufferHelper {
|
||||
// 一次流式拉取的message消息缓存
|
||||
// One-time streaming pull message message cache
|
||||
streamMessageBuffer: Message<ContentType>[] = [];
|
||||
|
||||
// 一次流式拉取的Chunk消息缓存
|
||||
// Chunk message cache for one-time streaming pull
|
||||
streamChunkBuffer: ChunkRaw[] = [];
|
||||
|
||||
/**
|
||||
* 新增Chunk消息缓存
|
||||
* Added Chunk message cache
|
||||
*/
|
||||
pushChunk(chunk: ChunkRaw) {
|
||||
this.streamChunkBuffer.push(chunk);
|
||||
@@ -51,12 +51,12 @@ export class StreamBufferHelper {
|
||||
const previousIndex = this.streamMessageBuffer.findIndex(
|
||||
item => item.message_id === message.message_id,
|
||||
);
|
||||
// 新增
|
||||
// new
|
||||
if (previousIndex === -1) {
|
||||
this.streamMessageBuffer.push(message);
|
||||
return;
|
||||
}
|
||||
// 更新
|
||||
// update
|
||||
const previousMessage = this.streamMessageBuffer.at(previousIndex);
|
||||
message.content = (previousMessage?.content || '') + message.content;
|
||||
message.reasoning_content =
|
||||
@@ -68,7 +68,7 @@ export class StreamBufferHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空消息缓存
|
||||
* Clear message cache
|
||||
*/
|
||||
clearMessageBuffer() {
|
||||
this.streamMessageBuffer = [];
|
||||
@@ -76,9 +76,9 @@ export class StreamBufferHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 按reply_id清除相关消息缓存
|
||||
* 1、reply_id相等的回复
|
||||
* 2、reply_id为 message_id 的问题
|
||||
* Clear related message cache reply_id
|
||||
* 1. reply_id equal reply
|
||||
* 2, reply_id message_id problem
|
||||
*/
|
||||
clearMessageBufferByReplyId(reply_id: string) {
|
||||
this.streamMessageBuffer = this.streamMessageBuffer.filter(
|
||||
@@ -93,7 +93,7 @@ export class StreamBufferHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据message_id获取chunk buffer中的chunk
|
||||
* Get the chunk in the chunk buffer according to message_id
|
||||
*/
|
||||
getChunkByMessageId(message_id: string) {
|
||||
return this.streamChunkBuffer.filter(
|
||||
@@ -125,7 +125,7 @@ export class ChunkProcessor {
|
||||
this.enableDebug = enableDebug;
|
||||
}
|
||||
/**
|
||||
* 新增chunk, 统一处理后的Chunk消息
|
||||
* Added chunk, unified processing of chunk messages
|
||||
*/
|
||||
addChunkAndProcess(chunk: ChunkRaw, options?: AddChunkAndProcessOptions) {
|
||||
this.streamBuffer.pushChunk(chunk);
|
||||
@@ -137,7 +137,7 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据chunk获取处理后的消息
|
||||
* Get the processed message according to the chunk
|
||||
*/
|
||||
getProcessedMessageByChunk(chunk: ChunkRaw) {
|
||||
return this.streamBuffer.streamMessageBuffer.find(
|
||||
@@ -146,7 +146,7 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据message_id获取处理后的消息
|
||||
* Get processed messages according to message_id
|
||||
*/
|
||||
getProcessedMessageByMessageId(message_id: string) {
|
||||
return this.streamBuffer.streamMessageBuffer.find(
|
||||
@@ -155,7 +155,7 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据local_message_id获取接收到的ack消息
|
||||
* Get the received ack message according to the local_message_id
|
||||
*/
|
||||
getAckMessageByLocalMessageId(local_message_id: string) {
|
||||
return this.streamBuffer.streamMessageBuffer.find(
|
||||
@@ -166,7 +166,7 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据chunk获取到第一条回复
|
||||
* Got the first reply according to chunk
|
||||
*/
|
||||
getFirstReplyMessageByChunk(chunk: ChunkRaw) {
|
||||
const hasAck = this.streamBuffer.streamMessageBuffer.find(
|
||||
@@ -181,7 +181,7 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据chunk获取到ack
|
||||
* Get ack according to chunk.
|
||||
*/
|
||||
getAckMessageByChunk(chunk: ChunkRaw) {
|
||||
return this.streamBuffer.streamMessageBuffer.find(
|
||||
@@ -190,11 +190,11 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是第一条回复消息
|
||||
* 除ack外的第一条回复
|
||||
* Determine whether it is the first reply message.
|
||||
* First reply except ack
|
||||
*/
|
||||
isFirstReplyMessage(chunk: ChunkRaw) {
|
||||
// 还没有ack,肯定没有第一条回复
|
||||
// No ack yet, definitely no first reply.
|
||||
if (!this.getAckMessageByChunk(chunk)) {
|
||||
return false;
|
||||
}
|
||||
@@ -202,7 +202,7 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据reply_id获取所有回复消息
|
||||
* Get all reply messages according to reply_id
|
||||
*/
|
||||
getReplyMessagesByReplyId(reply_id: string) {
|
||||
return this.streamBuffer.streamMessageBuffer.filter(
|
||||
@@ -211,7 +211,7 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有回复消息的长度
|
||||
* Get the length of all reply messages
|
||||
*/
|
||||
getReplyMessagesLengthByReplyId(reply_id: string) {
|
||||
return `${this.getReplyMessagesByReplyId(reply_id).reduce(
|
||||
@@ -221,7 +221,7 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 给本地日志使用
|
||||
* Use for local logs
|
||||
* @param message
|
||||
* @returns
|
||||
*/
|
||||
@@ -236,13 +236,13 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取是否是final answer
|
||||
* Is getting the final answer?
|
||||
*/
|
||||
isMessageAnswerEnd(chunk: ChunkRaw): boolean {
|
||||
const { message } = chunk;
|
||||
// 找到对应的所有回复
|
||||
// Find all corresponding replies
|
||||
const replyMessages = this.getReplyMessagesByReplyId(message.reply_id);
|
||||
// 查找是否有verbose消息, 并且标识answer结束,并且过滤掉中断场景的finish
|
||||
// Find if there is a verbose message, and identify the end of the answer, and filter out the finish of the interrupt scene
|
||||
const finalAnswerVerboseMessage = replyMessages.find(replyMessage => {
|
||||
const { type, content } = replyMessage;
|
||||
if (type !== 'verbose') {
|
||||
@@ -258,7 +258,7 @@ export class ChunkProcessor {
|
||||
const { value: verboseContentData } =
|
||||
safeJSONParse<AnswerFinishVerboseData>(verboseContent.data, null);
|
||||
|
||||
// 目前一个group内可能会有finish包,需要通过finish_reason过滤掉中断场景的,拿到的就是回答全部结束的finish
|
||||
// At present, there may be a finish package in a group. If you need to filter out the interrupt scene through finish_reason, you will get the finish that answers all the ends.
|
||||
return (
|
||||
verboseContent.msg_type === VerboseMsgType.GENERATE_ANSWER_FINISH &&
|
||||
verboseContentData?.finish_reason !== FinishReasonType.INTERRUPT
|
||||
@@ -268,9 +268,9 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 预处理消息
|
||||
* 1、反序列化
|
||||
* 2、添加 bot_id、is_finish、index, logId
|
||||
* preprocess message
|
||||
* 1. Deserialization
|
||||
* 2. Add bot_id, is_finish, index, logId
|
||||
* @param chunk
|
||||
* @param options
|
||||
* @returns
|
||||
@@ -299,8 +299,8 @@ export class ChunkProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* 增量消息拼接
|
||||
* 1、对于增量消息,需要拼接上一次的消息
|
||||
* incremental message stitching
|
||||
* 1. For incremental messages, you need to splice the previous message
|
||||
*/
|
||||
private concatChunkMessage(
|
||||
message: Message<ContentType>,
|
||||
@@ -310,14 +310,14 @@ export class ChunkProcessor {
|
||||
return message;
|
||||
}
|
||||
|
||||
// debug_message 逻辑
|
||||
// debug_message logic
|
||||
private assembleDebugMessage(
|
||||
message: Message<ContentType>,
|
||||
): Message<ContentType> {
|
||||
if (!this.enableDebug) {
|
||||
return message;
|
||||
}
|
||||
// 一次 stream拉取的所有message_id一样的 chunk 消息一次返回
|
||||
// All message_id chunk messages pulled by a stream are returned at once
|
||||
message.debug_messages = this.streamBuffer.getChunkByMessageId(
|
||||
message.message_id,
|
||||
);
|
||||
|
||||
@@ -15,21 +15,21 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 承接所有 sdk 的 slardar 自定义事件
|
||||
* Undertake all sdk slardar custom events
|
||||
*/
|
||||
export enum SlardarEvents {
|
||||
// 拉取历史异常
|
||||
// pull historical exception
|
||||
MESSAGE_FETCH_HISTORY_ERROR = 'message_fetch_history_error',
|
||||
// 清空上下文异常
|
||||
// clear context exception
|
||||
MESSAGE_CLEAR_CONTEXT_ERROR = 'message_clear_context_error',
|
||||
// 清空历史异常
|
||||
// Clear historical anomalies
|
||||
MESSAGE_CLEAR_HISTORY_ERROR = 'message_clear_history_error',
|
||||
// 删除消息异常
|
||||
// Delete message exception
|
||||
MESSAGE_DELETE_ERROR = 'message_delete_error',
|
||||
// 打断消息
|
||||
// interrupt message
|
||||
MESSAGE_INTERRUPT_ERROR = 'message_interrupt_error',
|
||||
// 点赞/点踩消息
|
||||
// Like/click on the message
|
||||
MESSAGE_REPORT_ERROR = 'message_report_error',
|
||||
// 语音转文字
|
||||
// speech-to-text
|
||||
CHAT_ASR_ERROR = 'chat_asr_error',
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. 负责规范各种类型消息创建的入参出参,减少消息创建成本
|
||||
* 2. 对于接收到的消息,针对不同消息类型,吐出指定的消息格式
|
||||
* 1. Responsible for standardizing imported parameters exported parameters of various types of message creation to reduce message creation costs
|
||||
* 2. For the received message, spit out the specified message format for different message types
|
||||
*/
|
||||
|
||||
export { PreSendLocalMessageFactory } from './presend-local-message/presend-local-message-factory';
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 消息管理相关
|
||||
* 1、获取历史消息
|
||||
* 2、清空对话上下文
|
||||
* 3、清空历史
|
||||
* 4、删除消息
|
||||
* message management related
|
||||
* 1. Get chat history
|
||||
* 2. Clear the conversation context
|
||||
* 3. Clear history
|
||||
* 4. Delete messages
|
||||
*/
|
||||
|
||||
import { safeJSONParse } from '../shared/utils/safe-json-parse';
|
||||
@@ -70,7 +70,7 @@ export class MessageManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 将接口获取到的消息历史记录进行数据转换
|
||||
* Data conversion of the message history obtained by the interface
|
||||
*/
|
||||
static convertMessageList = (
|
||||
messageList: GetHistoryMessageResponse['message_list'],
|
||||
@@ -86,7 +86,7 @@ export class MessageManager {
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取历史消息
|
||||
* Get chat history
|
||||
*/
|
||||
async getHistoryMessage(props: GetHistoryMessageProps) {
|
||||
try {
|
||||
@@ -102,13 +102,13 @@ export class MessageManager {
|
||||
eventName: SlardarEvents.MESSAGE_FETCH_HISTORY_ERROR,
|
||||
error: error as Error,
|
||||
});
|
||||
// 此处不应省略异常抛出,上游逻辑分支已检查,无风险
|
||||
// Exception should not be omitted here, upstream logical branch checked, no risk
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空对话上下文
|
||||
* Clear the conversation context
|
||||
*/
|
||||
async clearMessageContextUrl(props: ClearMessageContextProps) {
|
||||
try {
|
||||
@@ -127,7 +127,7 @@ export class MessageManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空历史
|
||||
* Clear history
|
||||
*/
|
||||
async clearHistory(props: ClearHistoryProps) {
|
||||
try {
|
||||
@@ -145,7 +145,7 @@ export class MessageManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除消息
|
||||
* delete message
|
||||
*/
|
||||
async deleteMessage(props: DeleteMessageProps) {
|
||||
try {
|
||||
@@ -163,7 +163,7 @@ export class MessageManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 打断消息
|
||||
* interrupt message
|
||||
*/
|
||||
async breakMessage(props: BreakMessageProps) {
|
||||
try {
|
||||
@@ -181,7 +181,7 @@ export class MessageManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 点赞/点踩消息
|
||||
* Like/click on the message
|
||||
*/
|
||||
async reportMessage(props: ReportMessageProps) {
|
||||
try {
|
||||
@@ -199,7 +199,7 @@ export class MessageManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 语音转文字
|
||||
* speech-to-text
|
||||
*/
|
||||
async chatASR(props: ChatASRProps) {
|
||||
try {
|
||||
@@ -210,7 +210,7 @@ export class MessageManager {
|
||||
headers: {
|
||||
/**
|
||||
* https://developer.mozilla.org/zh-CN/docs/Web/API/FormData
|
||||
* 如果送出时的编码类型被设为 "multipart/form-data",它会使用和表单一样的格式。
|
||||
* If the encoding type for sending is set to "multipart/form-data", it will use the same format as the form.
|
||||
*/
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
|
||||
@@ -32,7 +32,7 @@ export interface PreSendLocalMessageEventsManagerProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* 主要处理预发送消息的状态管理
|
||||
* Mainly handles state management of pre-sent messages
|
||||
*/
|
||||
export class PreSendLocalMessageEventsManager {
|
||||
private reportLog: ReportLog;
|
||||
@@ -55,7 +55,7 @@ export class PreSendLocalMessageEventsManager {
|
||||
PreSendLocalMessage<ContentType>
|
||||
> = new Map();
|
||||
|
||||
// 新增需要缓存的本地消息
|
||||
// Add local messages that need to be cached
|
||||
add(message: Message<ContentType>) {
|
||||
this.preSendLocalMessageEventsMap.set(
|
||||
message.extra_info.local_message_id,
|
||||
@@ -87,7 +87,7 @@ export class PreSendLocalMessageEventsManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取缓存的本地消息
|
||||
// Get cached local messages
|
||||
getStashedLocalMessage(local_message_id: string) {
|
||||
return this.preSendLocalMessageEventsMap.get(local_message_id);
|
||||
}
|
||||
@@ -111,7 +111,7 @@ export class PreSendLocalMessageEventsManager {
|
||||
params: Parameters<PreSendLocalMessageEventsMap[T]>[0],
|
||||
) {
|
||||
this.preSendLocalMessageEvents.emit(event, params);
|
||||
// 发送成功, 清除
|
||||
// Sent successfully, clear
|
||||
if (event === PreSendLocalMessageEventsEnum.MESSAGE_SEND_SUCCESS) {
|
||||
const message = params as Message<ContentType>;
|
||||
this.preSendLocalMessageEventsMap.delete(
|
||||
@@ -126,7 +126,7 @@ export class PreSendLocalMessageEventsManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// 发送失败/超时, 清除
|
||||
// Send failed/timed out, clear
|
||||
if (
|
||||
[
|
||||
PreSendLocalMessageEventsEnum.MESSAGE_SEND_FAIL,
|
||||
@@ -145,7 +145,7 @@ export class PreSendLocalMessageEventsManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// 上传状态修改
|
||||
// Upload status modification
|
||||
if (event === PreSendLocalMessageEventsEnum.FILE_UPLOAD_STATUS_CHANGE) {
|
||||
const message = params as Message<ContentType>;
|
||||
this.preSendLocalMessageEventsMap.set(
|
||||
@@ -156,7 +156,7 @@ export class PreSendLocalMessageEventsManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁
|
||||
* destroy
|
||||
*/
|
||||
destroy() {
|
||||
this.preSendLocalMessageEvents.removeAllListeners();
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. 负责规范各种类型消息创建的入参出参,减少消息创建成本
|
||||
* 2. 对于接收到的消息,针对不同消息类型,吐出指定的消息格式
|
||||
* 1. Responsible for standardizing imported parameters exported parameters of various types of message creation to reduce message creation costs
|
||||
* 2. For the received message, spit out the specified message format for different message types
|
||||
*/
|
||||
|
||||
import { nanoid } from 'nanoid';
|
||||
@@ -51,7 +51,7 @@ import { type PreSendLocalMessageEventsManager } from './presend-local-message-e
|
||||
import { PreSendLocalMessage } from './presend-local-message';
|
||||
|
||||
/**
|
||||
* 创建预发送消息
|
||||
* Create a pre-sent message
|
||||
*/
|
||||
export interface PreSendLocalMessageFactoryProps {
|
||||
bot_id?: string;
|
||||
@@ -99,7 +99,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文本消息
|
||||
* Create text message
|
||||
*/
|
||||
createTextMessage(
|
||||
props: TextMessageProps,
|
||||
@@ -121,7 +121,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建图片消息
|
||||
* Create image message
|
||||
*/
|
||||
createImageMessage<M extends EventPayloadMaps>(props: {
|
||||
messageProps: ImageMessageProps<M>;
|
||||
@@ -151,7 +151,7 @@ export class PreSendLocalMessageFactory {
|
||||
}),
|
||||
);
|
||||
|
||||
// 预发送消息保存本地
|
||||
// Pre-sent messages are saved locally
|
||||
messageEventsManager.add(message);
|
||||
|
||||
const uploaderPluginInstance = new UploadPlugin({
|
||||
@@ -179,7 +179,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件消息
|
||||
* Create file message
|
||||
*/
|
||||
createFileMessage<M extends EventPayloadMaps>(props: {
|
||||
messageProps: ImageMessageProps<M>;
|
||||
@@ -208,7 +208,7 @@ export class PreSendLocalMessageFactory {
|
||||
mention_list,
|
||||
}),
|
||||
);
|
||||
// 预发送文件消息保存本地
|
||||
// Pre-send file messages saved locally
|
||||
messageEventsManager.add(message);
|
||||
|
||||
const uploaderPluginInstance = new UploadPlugin({
|
||||
@@ -241,7 +241,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建图文混合消息
|
||||
* Create a mixed message
|
||||
*/
|
||||
createTextAndFileMixMessage(
|
||||
props: TextAndFileMixMessageProps,
|
||||
@@ -267,7 +267,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建标准化过的消息
|
||||
* Create standardized messages
|
||||
*/
|
||||
createNormalizedMessage<T extends ContentType>(
|
||||
props: NormalizedMessageProps<T>,
|
||||
@@ -292,7 +292,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装图片消息content
|
||||
* Assemble image message content
|
||||
*/
|
||||
private assembleImageMessageContent(
|
||||
file: File,
|
||||
@@ -319,7 +319,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新图片消息content
|
||||
* Update image message content
|
||||
*/
|
||||
private updateImageMessageContent(
|
||||
message: PreSendLocalMessage<ContentType.Image>,
|
||||
@@ -352,7 +352,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新文件消息content
|
||||
* Update file message content
|
||||
*/
|
||||
private updateFileMessageContent(
|
||||
message: PreSendLocalMessage<ContentType.File>,
|
||||
@@ -365,7 +365,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新图片/文件消息上传状态:success | fail
|
||||
* Update image/file message Upload status: success | failed
|
||||
*/
|
||||
private updateMessageUploadResult(
|
||||
message: PreSendLocalMessage<ContentType.Image | ContentType.File>,
|
||||
@@ -376,7 +376,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装文件消息content
|
||||
* Assemble file message content
|
||||
*/
|
||||
private assembleFileMessageContent(
|
||||
file: File,
|
||||
@@ -399,7 +399,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装图文混合消息content
|
||||
* Assemble mixed message content
|
||||
*/
|
||||
private assembleTextAndFileMixMessageContent(
|
||||
mixList: TextAndFileMixMessagePropsPayload['mixList'],
|
||||
@@ -455,7 +455,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装消息通用字段
|
||||
* Assembly message common field
|
||||
*/
|
||||
private assembleMessageCommonProps<T extends ContentType>(
|
||||
props: Pick<
|
||||
@@ -479,16 +479,16 @@ export class PreSendLocalMessageFactory {
|
||||
// @ts-expect-error should be fixed
|
||||
extra_info: {
|
||||
local_message_id: nanoid(),
|
||||
input_tokens: '', // 用户 query 消耗的 token
|
||||
output_tokens: '', // llm 输出消耗的 token
|
||||
token: '', // 总的 token 消耗
|
||||
input_tokens: '', // User query consumed token
|
||||
output_tokens: '', // LLM output consumed token
|
||||
token: '', // Total token consumption
|
||||
plugin_status: 'success', // "success" or "fail"
|
||||
time_cost: '', // 中间调用过程的时间
|
||||
time_cost: '', // Intermediate invocation time of procedure
|
||||
workflow_tokens: '',
|
||||
bot_state: '', // { bot_id?: string;agent_id?: string;agent_name?: string; }
|
||||
plugin_request: '', // plugin 请求的参数
|
||||
tool_name: '', // 调用的 plugin 下具体的 api 名称
|
||||
plugin: '', // 调用的 plugin 名称
|
||||
plugin_request: '', // Parameters of the plugin request
|
||||
tool_name: '', // Specific API name under the invoked plugin
|
||||
plugin: '', // Name of the plugin invoked
|
||||
},
|
||||
role: 'user',
|
||||
type: 'question',
|
||||
@@ -504,7 +504,7 @@ export class PreSendLocalMessageFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理发送给服务端的消息结构
|
||||
* Process the message structure sent to the server
|
||||
*/
|
||||
getSendMessageStructure(
|
||||
message: PreSendLocalMessage<ContentType>,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 暴露预发送消息实例,预发送消息用于创建消息后上屏,消息格式和Message<T>一致
|
||||
* Expose the pre-sent message instance, the pre-sent message is used to be uploaded to the screen after the message is created, and the message format is consistent with Message < T >
|
||||
*/
|
||||
|
||||
import {
|
||||
@@ -37,25 +37,25 @@ export class PreSendLocalMessage<T extends ContentType> implements Message<T> {
|
||||
// @ts-expect-error should be fixed
|
||||
extra_info: Message<T>['extra_info'] = {
|
||||
local_message_id: '',
|
||||
input_tokens: '', // 用户 query 消耗的 token
|
||||
output_tokens: '', // llm 输出消耗的 token
|
||||
token: '', // 总的 token 消耗
|
||||
input_tokens: '', // User query consumed token
|
||||
output_tokens: '', // LLM output consumed token
|
||||
token: '', // Total token consumption
|
||||
plugin_status: 'success', // "success" or "fail"
|
||||
time_cost: '', // 中间调用过程的时间
|
||||
time_cost: '', // Intermediate invocation time of procedure
|
||||
workflow_tokens: '',
|
||||
bot_state: '', // { bot_id?: string;agent_id?: string;agent_name?: string; }
|
||||
plugin_request: '', // plugin 请求的参数
|
||||
tool_name: '', // 调用的 plugin 下具体的 api 名称
|
||||
plugin: '', // 调用的 plugin 名称
|
||||
plugin_request: '', // Parameters of the plugin request
|
||||
tool_name: '', // Specific API name under the invoked plugin
|
||||
plugin: '', // Name of the plugin invoked
|
||||
};
|
||||
index?: number; // message在一次 response 的排序
|
||||
is_finish?: boolean; // 消息状态
|
||||
section_id: string; // 消息属于的上下文id
|
||||
index?: number; // Order of messages in a response
|
||||
is_finish?: boolean; // message status
|
||||
section_id: string; // The context id to which the message belongs
|
||||
content_type: ContentType;
|
||||
debug_messages?: ChunkRaw[];
|
||||
content: string;
|
||||
content_obj: MessageContent<T>;
|
||||
file_upload_result?: 'success' | 'fail'; // 文件上传状态
|
||||
file_upload_result?: 'success' | 'fail'; // file upload status
|
||||
role: MessageInfoRole;
|
||||
type: MessageType;
|
||||
message_status?: MessageStatus;
|
||||
|
||||
@@ -27,20 +27,20 @@ import { type Scene } from '../../chat-sdk/types/interface';
|
||||
|
||||
type JSONstring<T = object> = T extends object ? string : never;
|
||||
|
||||
/** follow copilot 定义的枚举 */
|
||||
/** Enumeration following copilot definition */
|
||||
export enum ChatMessageMetaType {
|
||||
/** Compatible value */
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
Default_0,
|
||||
/** 端侧直接替换 */
|
||||
/** End-to-side direct replacement */
|
||||
Replaceable,
|
||||
/** 插入引用 */
|
||||
/** insert reference */
|
||||
Insertable,
|
||||
/** 文档引用 */
|
||||
/** document citation */
|
||||
DocumentRef,
|
||||
/** 知识库引用卡片 */
|
||||
/** Knowledge Base Reference Card */
|
||||
KnowledgeCard,
|
||||
/** 嵌入的多媒体信息,只是alice给端上用的,因为全链路复用这一个字段,所以在这儿改了 */
|
||||
/** The embedded multimedia information is only used by Alice for the end. Because full link multiplexing uses this field, it has been changed here. */
|
||||
EmbeddedMultimedia = 100,
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ export interface ChatMessageMetaInfo {
|
||||
info?: JSONstring;
|
||||
}
|
||||
|
||||
// 服务端返回的chunk
|
||||
// Server level returned chunks
|
||||
export interface ChunkRaw {
|
||||
index: number;
|
||||
seq_id: number;
|
||||
@@ -58,85 +58,85 @@ export interface ChunkRaw {
|
||||
}
|
||||
|
||||
export interface MessageExtraInfo {
|
||||
local_message_id: string; // 前端消息 id, 用于预发送消息体更新
|
||||
input_tokens: string; // 用户 query 消耗的 token
|
||||
output_tokens: string; // llm 输出消耗的 token
|
||||
token: string; // 总的 token 消耗
|
||||
local_message_id: string; // Front-end message id, used to pre-send message body updates
|
||||
input_tokens: string; // User query consumed token
|
||||
output_tokens: string; // LLM output consumed token
|
||||
token: string; // Total token consumption
|
||||
plugin_status: string; // "0" === success or "1" === fail
|
||||
time_cost: string; // 中间调用过程的时间
|
||||
time_cost: string; // Intermediate invocation time of procedure
|
||||
workflow_tokens: string;
|
||||
bot_state: string; // { bot_id?: string;agent_id?: string;agent_name?: string; }
|
||||
plugin_request: string; // plugin 请求的参数
|
||||
tool_name: string; // 调用的 plugin 下具体的 api 名称
|
||||
plugin: string; // 调用的 plugin 名称
|
||||
log_id?: string; // chat 的 logId
|
||||
mock_hit_info?: string; // plugin 命中 mockset 信息
|
||||
execute_display_name: string; // 展示名称
|
||||
/** 流式plugin返回的用于替换tool response内容的标识,普通plugin没有 */
|
||||
plugin_request: string; // Parameters of the plugin request
|
||||
tool_name: string; // Specific API name under the invoked plugin
|
||||
plugin: string; // Name of the plugin invoked
|
||||
log_id?: string; // Chat logId
|
||||
mock_hit_info?: string; // Plugin hit mockset info
|
||||
execute_display_name: string; // display name
|
||||
/** The identifier returned by the streaming plugin to replace the tool response content, which is not available in the normal plugin */
|
||||
stream_plugin_running?: string;
|
||||
/** 目前仅有中间消息返回*/
|
||||
/** Currently only intermediate messages are returned.*/
|
||||
message_title?: string;
|
||||
remove_query_id?: string; // 有此字段代表触发擦除用户 qeury 安全策略, 值为需要擦出的用户消息的 message_id
|
||||
new_section_id?: string; // 有此字段代表触发清除上下文安全策略
|
||||
/** 对应定时任务task_type,1-预设任务,2-用户任务,3-Plugin后台任务 */
|
||||
remove_query_id?: string; // This field represents the trigger to erase the user qeury security policy, and the value is the message_id of the user message that needs to be erased
|
||||
new_section_id?: string; // This field represents the trigger to clear the context security policy
|
||||
/** Corresponding to timed task task_type, 1-preset task, 2-user task, 3-Plugin background task */
|
||||
task_type?: string;
|
||||
call_id?: string; // function_call和tool_response匹配的id
|
||||
call_id?: string; // function_call and tool_response matching IDs
|
||||
}
|
||||
|
||||
// 服务端返回的原始Message结构
|
||||
// Message structure returned by server level
|
||||
export interface MessageRaw {
|
||||
role: MessageInfoRole; // 信息发出方的角色
|
||||
type: MessageType; // 主要用于区分role=assistant的bot返回信息类型
|
||||
role: MessageInfoRole; // The role of the sender of the message
|
||||
type: MessageType; // Mainly used to distinguish the type of bot return information for role = assistant
|
||||
section_id: string;
|
||||
content_type: ContentType;
|
||||
content: string;
|
||||
reasoning_content?: string;
|
||||
content_time?: number; // 消息发送时间,服务端是 Int64,接口拿到需要转一下
|
||||
user?: string; // 用户唯一标识
|
||||
content_time?: number; // Message sending time, server level is Int64, you need to transfer it when you get the interface.
|
||||
user?: string; // user unique identity
|
||||
/**
|
||||
* 仅拉取历史返回
|
||||
* Pull history only
|
||||
*/
|
||||
message_status?: MessageStatus;
|
||||
message_id: string; // 后端消息 id, 可能有多条回复
|
||||
reply_id: string; // 回复 id,query的messageId
|
||||
broken_pos?: number; // 打断位置,仅对type = 'answer'生效
|
||||
/** 拉流 ack 有, 后续没有 */
|
||||
message_id: string; // Backend message id, there may be multiple replies
|
||||
reply_id: string; // Reply id, query messageId
|
||||
broken_pos?: number; // Interrupt position, only valid for type = 'answer'
|
||||
/** LaLiu ack has it, no follow-up */
|
||||
mention_list?: MessageMentionListFields['mention_list'];
|
||||
/** 发送者 id */
|
||||
/** Sender ID */
|
||||
sender_id?: string;
|
||||
extra_info: MessageExtraInfo;
|
||||
source?: MessageSource;
|
||||
reply_message?: Message<ContentType>;
|
||||
meta_infos?: Array<ChatMessageMetaInfo>;
|
||||
/** 中断消息服务端透传中台的参数,获取中断场景、续聊id */
|
||||
/** Interrupt message server level pass through the parameters of the middle station, get the interrupt scene, continue chat id */
|
||||
required_action?: RequiredAction;
|
||||
/** 卡片状态 */
|
||||
/** Card Status */
|
||||
card_status?: Record<string, string>;
|
||||
}
|
||||
|
||||
export const messageSource = {
|
||||
/** 普通聊天消息 */
|
||||
/** normal chat message */
|
||||
Chat: 0,
|
||||
/** 定时任务 */
|
||||
/** timed task */
|
||||
TaskManualTrigger: 1,
|
||||
/** 通知 */
|
||||
/** notify */
|
||||
Notice: 2,
|
||||
/** 异步结果 */
|
||||
/** asynchronous result */
|
||||
AsyncResult: 3,
|
||||
} as const;
|
||||
|
||||
export const taskType = {
|
||||
/** 预设任务 */
|
||||
/** preset task */
|
||||
PresetTask: '1',
|
||||
/** 用户任务 */
|
||||
/** user task */
|
||||
CreatedByUserTask: '2',
|
||||
/** Plugin 后台任务 */
|
||||
/** Plugin background task */
|
||||
PluginTask: '3',
|
||||
} as const;
|
||||
|
||||
export type MessageSource = (typeof messageSource)[keyof typeof messageSource];
|
||||
|
||||
// 经过Processor处理后的chunk
|
||||
// Processor processed chunks
|
||||
export interface Chunk<T extends ContentType> {
|
||||
index: number;
|
||||
seq_id: number;
|
||||
@@ -144,45 +144,45 @@ export interface Chunk<T extends ContentType> {
|
||||
message: Message<T>;
|
||||
}
|
||||
|
||||
// 经过Processor处理后的Message
|
||||
// Message processed by Processor
|
||||
export type Message<T extends ContentType, V = unknown> = MessageRaw &
|
||||
MessageMentionListFields & {
|
||||
bot_id?: string;
|
||||
preset_bot?: string;
|
||||
index?: number; // 临时状态,message在一次 response 的排序
|
||||
is_finish?: boolean; // 临时状态,标识消息是否拉取完成
|
||||
index?: number; // Temporary state, ordering of messages in a response
|
||||
is_finish?: boolean; // Temporary state that identifies whether the message has been pulled
|
||||
/**
|
||||
* content 经过反序列化
|
||||
* Content is deserialized
|
||||
*/
|
||||
content_obj: MessageContent<T, V>;
|
||||
/**
|
||||
* sdk开启了enableDebug模式,每条回复消息新增debug_messages字段,包含channel 吐出的所有 chunk消息
|
||||
* SDK has enabled the enableDebug mode, and each reply message adds debug_messages field, including all chunk messages spit out by the channel
|
||||
*/
|
||||
debug_messages?: ChunkRaw[];
|
||||
stream_chunk_buffer?: ChunkRaw[];
|
||||
stream_message_buffer?: Message<ContentType>[];
|
||||
/**
|
||||
* 旧接口未必有该字段;仅 query、answer、notice 等常见显示类型会进行计数。
|
||||
* - int64 类型,计数从 "1" 开始。
|
||||
* - 尽管我不认为单聊会有超过 Number.MAX_SAFE_INTEGER 的数值,但是还是用了 big-integer 库来进行处理。
|
||||
* - 不刷旧数据,因此 ① 旧数据 ② 非常规消息 的值取 "0"
|
||||
* Older interfaces may not have this field; only common display types such as query, answer, notice, etc. are counted.
|
||||
* - int64 type, counting starts at "1".
|
||||
* - Although I don't think there will be more than Number. MAX_SAFE_INTEGER alone, I still use the big-integer library to handle it.
|
||||
* - Do not brush old data, so ① old data ② unconventional messages, the value is "0"
|
||||
*/
|
||||
message_index?: string;
|
||||
/**
|
||||
* 仅预发送消息返回
|
||||
* Pre-send message return only
|
||||
*/
|
||||
file_upload_result?: 'success' | 'fail'; // 文件上传状态
|
||||
file_upload_result?: 'success' | 'fail'; // file upload status
|
||||
/**
|
||||
* 本地消息状态, 仅预发送消息返回
|
||||
* Local message status, only pre-sent messages are returned
|
||||
*/
|
||||
local_message_status?: LocalMessageStatus;
|
||||
/**
|
||||
* 仅即使消息返回,拉取历史消息无
|
||||
* Only if the message returns, pull chat history None
|
||||
*/
|
||||
logId?: string; // chat 的 logId
|
||||
logId?: string; // Chat logId
|
||||
};
|
||||
|
||||
// 发送给服务端的消息结构
|
||||
// The structure of the message sent to the server
|
||||
export interface SendMessage
|
||||
extends MessageMentionListFields,
|
||||
ResumeMessage,
|
||||
@@ -194,21 +194,21 @@ export interface SendMessage
|
||||
user?: string;
|
||||
query: string;
|
||||
extra: Record<string, string>;
|
||||
draft_mode?: boolean; // 草稿bot or 线上bot
|
||||
content_type?: string; // 文件 file 图片 image 等
|
||||
regen_message_id?: string; // 重试消息id
|
||||
local_message_id: string; // 前端本地的message_id 在extra_info 里面透传返回
|
||||
chat_history?: Message<ContentType>[]; // 指定聊天上下文, 服务端不落库
|
||||
draft_mode?: boolean; // Draft bot or online bot
|
||||
content_type?: string; // Files files pictures images etc
|
||||
regen_message_id?: string; // Retry message id
|
||||
local_message_id: string; // The local message_id on the front end is passed back in the extra_info
|
||||
chat_history?: Message<ContentType>[]; // Specify the chat context, server level does not drop library
|
||||
}
|
||||
// 发送给服务端的resume结构体,chat类型本身有缺失,本期只补充resume相关
|
||||
// The resume structure sent to the server, the chat type itself is missing, and this issue only supplements resume-related
|
||||
export interface ResumeMessage {
|
||||
conversation_id: string;
|
||||
scene?: Scene; // 场景值
|
||||
resume_message_id?: string; // 续聊场景服务端所需id,即reply_id
|
||||
interrupt_message_id?: string; // 中断的verbose消息id
|
||||
scene?: Scene; // scene value
|
||||
resume_message_id?: string; // Continue chatting with the ID required for the scene server level, which is reply_id
|
||||
interrupt_message_id?: string; // Interrupted verbose message id
|
||||
tool_outputs?: {
|
||||
tool_call_id?: string; // 透传中断verbose消息中的tool_call.id
|
||||
output?: string; // 地理位置授权场景传经纬度
|
||||
tool_call_id?: string; // Password interrupt tool_call.id in verbose messages
|
||||
output?: string; // Geographical location authorization scene transmission longitude and latitude
|
||||
}[];
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ export interface MessageExtProps {
|
||||
}
|
||||
|
||||
export interface MessageMentionListFields {
|
||||
/** \@bot 功能,在输入时提及的 bot id */
|
||||
/** \ @bot function, the bot id mentioned when entering */
|
||||
mention_list: { id: string }[];
|
||||
}
|
||||
|
||||
@@ -426,11 +426,11 @@ export interface SendMessageOptions {
|
||||
betweenChunkTimeout?: number;
|
||||
stream?: boolean;
|
||||
chatHistory?: Message<ContentType>[];
|
||||
// 参数会透传给 chat 接口
|
||||
// Parameters will be passed through to the chat interface
|
||||
extendFiled?: Record<string, unknown>;
|
||||
// 透传的header
|
||||
// Password header
|
||||
headers?: HeadersInit;
|
||||
// 是否为重新生成消息, 默认false
|
||||
// Whether to regenerate the message, the default is false
|
||||
isRegenMessage?: boolean;
|
||||
}
|
||||
|
||||
@@ -444,28 +444,28 @@ export interface CreateMessageOptions {
|
||||
}
|
||||
|
||||
export enum VerboseMsgType {
|
||||
/** 跳转节点 */
|
||||
/** jump node */
|
||||
JUMP_TO = 'multi_agents_jump_to_agent',
|
||||
/** 回溯节点 */
|
||||
/** backtracking node */
|
||||
BACK_WORD = 'multi_agents_backwards',
|
||||
/** 长期记忆节点 */
|
||||
/** long-term memory node */
|
||||
LONG_TERM_MEMORY = 'time_capsule_recall',
|
||||
/** finish answer*/
|
||||
GENERATE_ANSWER_FINISH = 'generate_answer_finish',
|
||||
/** 流式插件调用状态 */
|
||||
/** Streaming plugin call status */
|
||||
STREAM_PLUGIN_FINISH = 'stream_plugin_finish',
|
||||
/** 知识库召回 */
|
||||
/** knowledge base recall */
|
||||
KNOWLEDGE_RECALL = 'knowledge_recall',
|
||||
/** 中断消息:目前用于地理位置授权 / workflow question 待回复 */
|
||||
/** Interrupt message: Currently used for geolocation authorization/workflow question pending reply */
|
||||
INTERRUPT = 'interrupt',
|
||||
/** hooks调用 */
|
||||
/** Hooks call */
|
||||
HOOK_CALL = 'hook_call',
|
||||
}
|
||||
|
||||
export enum InterruptToolCallsType {
|
||||
FunctionType = 'function', // tool 结果上报
|
||||
RequireInfoType = 'require_info', // 需要信息,如地理位置
|
||||
ReplyMessage = 'reply_message', // question 节点
|
||||
FunctionType = 'function', // Tool result reporting
|
||||
RequireInfoType = 'require_info', // Required information, such as geographical location
|
||||
ReplyMessage = 'reply_message', // Question Node
|
||||
}
|
||||
|
||||
export interface VerboseContent {
|
||||
@@ -474,9 +474,9 @@ export interface VerboseContent {
|
||||
}
|
||||
|
||||
export enum FinishReasonType {
|
||||
/** 正常回答全部结束 */
|
||||
/** Normal answer all over */
|
||||
ALL_FINISH = 0,
|
||||
/** 中断结束 */
|
||||
/** end of interrupt */
|
||||
INTERRUPT = 1,
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ export interface ParticipantInfo {
|
||||
user_name?: string;
|
||||
allow_mention: boolean;
|
||||
access_path: string | undefined;
|
||||
/** 是否允许被分享 */
|
||||
/** Is it allowed to be shared? */
|
||||
allow_share?: boolean;
|
||||
}
|
||||
|
||||
@@ -106,21 +106,21 @@ export interface DeleteMessageResponse {
|
||||
export interface BreakMessageProps {
|
||||
conversation_id: string;
|
||||
/**
|
||||
* 被打断问题的 local_message_id
|
||||
* local_message_id of interrupted questions
|
||||
*/
|
||||
local_message_id: string;
|
||||
/**
|
||||
* 被打断的问题id
|
||||
* Interrupted question id
|
||||
*/
|
||||
query_message_id: string;
|
||||
/**
|
||||
* 当前问题下哪一条回复被打断了
|
||||
* 仅但被打断的消息 type = 'answer' 时传递
|
||||
* Which reply was interrupted under the current question?
|
||||
* Only delivered if the interrupted message type = 'answer'
|
||||
*/
|
||||
answer_message_id?: string;
|
||||
/**
|
||||
* 打断位置
|
||||
* 仅但被打断的消息 type = 'answer' 时传递
|
||||
* interrupt position
|
||||
* Only delivered if the interrupted message type = 'answer'
|
||||
*/
|
||||
broken_pos?: number;
|
||||
|
||||
@@ -138,7 +138,7 @@ export type ClearMessageContextParams = Pick<
|
||||
>;
|
||||
|
||||
/*
|
||||
消息点赞/点踩接口类型定义
|
||||
Message Like/Click Interface Type Definition
|
||||
*/
|
||||
export enum MessageFeedbackType {
|
||||
Default = 0,
|
||||
@@ -148,16 +148,16 @@ export enum MessageFeedbackType {
|
||||
|
||||
export enum MessageFeedbackDetailType {
|
||||
UnlikeDefault = 0,
|
||||
UnlikeHarmful = 1, //有害信息
|
||||
UnlikeIncorrect = 2, //信息有误
|
||||
UnlikeNotFollowInstructions = 3, //未遵循指令
|
||||
UnlikeOthers = 4, //其他
|
||||
UnlikeHarmful = 1, //Harmful information
|
||||
UnlikeIncorrect = 2, //incorrect information
|
||||
UnlikeNotFollowInstructions = 3, //Did not follow instructions
|
||||
UnlikeOthers = 4, //other
|
||||
}
|
||||
|
||||
export interface MessageFeedback {
|
||||
feedback_type?: MessageFeedbackType; //反馈类型
|
||||
detail_types?: MessageFeedbackDetailType[]; //细分类型
|
||||
detail_content?: string; //负反馈自定义内容,对应用户选择Others
|
||||
feedback_type?: MessageFeedbackType; //feedback type
|
||||
detail_types?: MessageFeedbackDetailType[]; //segmentation type
|
||||
detail_content?: string; //Negative feedback custom content, corresponding to user selection Others
|
||||
}
|
||||
|
||||
export enum ReportMessageAction {
|
||||
@@ -168,12 +168,12 @@ export enum ReportMessageAction {
|
||||
|
||||
export interface ReportMessageProps {
|
||||
bot_id?: string; //bot_id
|
||||
biz_conversation_id: string; //会话ID
|
||||
message_id: string; //消息ID
|
||||
scene?: Scene; //当前会话所处场景
|
||||
action: ReportMessageAction; //动作
|
||||
biz_conversation_id: string; //Session ID
|
||||
message_id: string; //Message ID
|
||||
scene?: Scene; //The scene of the current session
|
||||
action: ReportMessageAction; //action
|
||||
message_feedback?: MessageFeedback;
|
||||
// 卡片状态
|
||||
// Card Status
|
||||
attributes?: {
|
||||
card_status?: Record<string, string>;
|
||||
};
|
||||
@@ -184,7 +184,7 @@ export interface ReportMessageResponse {
|
||||
msg: string;
|
||||
}
|
||||
|
||||
/* 消息点赞/点踩接口类型定义:end */
|
||||
/* Message Like/Click Interface Type Definition: end */
|
||||
|
||||
export type ChatASRProps = FormData;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ export class ChatCoreUploadPlugin implements UploadPluginInterface {
|
||||
try {
|
||||
const dataAuth = await requestInstance.post(GET_AUTH_URL, {
|
||||
data: {
|
||||
// TODO: 确认参数是否要支持传入配置
|
||||
// TODO: Confirm whether the parameter should support the incoming configuration
|
||||
scene: 'bot_task',
|
||||
},
|
||||
});
|
||||
@@ -65,9 +65,9 @@ export class ChatCoreUploadPlugin implements UploadPluginInterface {
|
||||
schema,
|
||||
useFileExtension: true,
|
||||
// cp-disable-next-line
|
||||
imageHost: `https://${upload_host}`, //imageX上传必填
|
||||
imageHost: `https://${upload_host}`, //imageX upload required
|
||||
imageConfig: {
|
||||
serviceId: service_id || '', // 在视频云中申请的服务id
|
||||
serviceId: service_id || '', // The service id applied for in the video cloud.
|
||||
},
|
||||
objectConfig: {
|
||||
serviceId: service_id || '',
|
||||
|
||||
@@ -16,16 +16,16 @@
|
||||
|
||||
export type UploadEventName = 'complete' | 'error' | 'progress';
|
||||
export interface UploadResult {
|
||||
// 图片 & 文件 uri资源标识,用于换取url·
|
||||
// Image & file URI resource ID, used in exchange for url ·
|
||||
|
||||
Uri?: string;
|
||||
// 图片 & 文件 url
|
||||
// Image & file url
|
||||
|
||||
Url?: string;
|
||||
// 图片宽度
|
||||
// image width
|
||||
|
||||
ImageWidth?: number;
|
||||
// 图片高度
|
||||
// image height
|
||||
|
||||
ImageHeight?: number;
|
||||
}
|
||||
@@ -33,8 +33,8 @@ export interface UploadResult {
|
||||
export type FileType = 'object' | 'image' | undefined;
|
||||
|
||||
export interface BaseEventInfo {
|
||||
type: 'success' | 'error'; // 当前任务状态,成功/失败
|
||||
// 当前状态的描述(随着生命周期不断变化)
|
||||
type: 'success' | 'error'; // Current task status, success/failure
|
||||
// Description of the current state (constantly changing with the lifecycle)
|
||||
extra: {
|
||||
error?: unknown;
|
||||
errorCode?: number;
|
||||
@@ -42,11 +42,11 @@ export interface BaseEventInfo {
|
||||
};
|
||||
}
|
||||
export interface CompleteEventInfo extends BaseEventInfo {
|
||||
// 上传结果,注意对于不同 type 来说结构不一样,
|
||||
// Upload the results, note that the structure is different for different types,
|
||||
uploadResult: UploadResult;
|
||||
}
|
||||
export interface ProgressEventInfo extends BaseEventInfo {
|
||||
// 当前上传总体进度百分比(%)
|
||||
// Current Upload Overall Progress Percentage (%)
|
||||
percent: number;
|
||||
}
|
||||
export interface EventPayloadMaps {
|
||||
@@ -65,14 +65,14 @@ export interface UploadPluginProps {
|
||||
type: FileType;
|
||||
}
|
||||
|
||||
// 上传插件构造函数
|
||||
// Upload plugin constructor
|
||||
export interface UploadPluginConstructor<
|
||||
P extends Record<string, unknown> = Record<string, unknown>,
|
||||
> {
|
||||
new (props: UploadPluginProps & P): UploadPluginInterface;
|
||||
}
|
||||
|
||||
// 上传插件接口实现
|
||||
// Upload plug-in interface implementation
|
||||
export interface UploadPluginInterface<
|
||||
M extends EventPayloadMaps = EventPayloadMaps,
|
||||
> {
|
||||
|
||||
@@ -26,22 +26,22 @@ import { type DeployVersion, type ENV } from '../shared/const';
|
||||
import { slardarInstance, createSlardarConfig } from './slardar';
|
||||
import { LogOptionsHelper } from './log-options-helper';
|
||||
|
||||
// 获取 ReportLog 类的实例类型
|
||||
// Get the instance type of the ReportLog class
|
||||
type ReportLogInstance = InstanceType<typeof ReportLog>;
|
||||
|
||||
// 获取 slardarTracer 方法的返回类型
|
||||
// Get the return type of the slardarTracer method
|
||||
type SlardarTracerReturnType = ReturnType<ReportLogInstance['slardarTracer']>;
|
||||
|
||||
// 获取 trace 方法的类型
|
||||
// Gets the type of the trace method
|
||||
export type Tracer = SlardarTracerReturnType['trace'];
|
||||
|
||||
export type ReportLogType = 'error' | 'info';
|
||||
/**
|
||||
* 日志上报
|
||||
* log report
|
||||
*/
|
||||
|
||||
export interface ReportLogProps {
|
||||
// 后面等级上报,包含前面等级日志
|
||||
// Back level report, including previous level log
|
||||
logLevel?: 'disable' | 'error' | 'info';
|
||||
env?: ENV;
|
||||
namespace?: string;
|
||||
@@ -61,7 +61,7 @@ const defaultReportLogProps: {
|
||||
};
|
||||
|
||||
/**
|
||||
* namespace不可覆盖
|
||||
* Namespace cannot be overridden
|
||||
*/
|
||||
const unChangeProps = {
|
||||
namespace: 'chat-core',
|
||||
@@ -85,7 +85,7 @@ export class ReportLog {
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例初始化,所有 scope 也只初始化一次
|
||||
* Instance initialization, all scopes are initialized only once
|
||||
*/
|
||||
init() {
|
||||
console.log('debugger slardar instance init', this.hasSlardarInitd);
|
||||
@@ -115,7 +115,7 @@ export class ReportLog {
|
||||
}
|
||||
|
||||
/**
|
||||
* slardar 初始化
|
||||
* slardar initialization
|
||||
*/
|
||||
private initReport(options?: ReportLogProps) {
|
||||
this.reportLogWithBaseInfo = reporter.createReporterWithPreset(
|
||||
@@ -125,7 +125,7 @@ export class ReportLog {
|
||||
}
|
||||
|
||||
/**
|
||||
* 控制台日志初始化
|
||||
* Console log initialization
|
||||
* @param options
|
||||
*/
|
||||
private initLog(options?: ReportLogProps) {
|
||||
@@ -134,7 +134,7 @@ export class ReportLog {
|
||||
});
|
||||
}
|
||||
|
||||
// 判断是否需要上报
|
||||
// Determine whether to report
|
||||
private isNeedReport(logType: ReportLogType) {
|
||||
const { logLevel } = this.ctx.get();
|
||||
if (logLevel === 'disable') {
|
||||
@@ -161,14 +161,14 @@ export class ReportLog {
|
||||
}
|
||||
|
||||
/**
|
||||
* slardar日志 info层级
|
||||
* Slardar log info hierarchy
|
||||
*/
|
||||
slardarInfo(...args: Parameters<typeof reporter.info>) {
|
||||
this.reportLogWithBaseInfo.info(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* slardar日志 success级别
|
||||
* Slardar log success level
|
||||
* @param args
|
||||
*/
|
||||
slardarSuccess(...args: Parameters<typeof reporter.success>) {
|
||||
@@ -176,35 +176,35 @@ export class ReportLog {
|
||||
}
|
||||
|
||||
/**
|
||||
* slardar日志, error级别
|
||||
* Slardar log, error level
|
||||
*/
|
||||
slardarError(...args: Parameters<typeof reporter.error>) {
|
||||
this.reportLogWithBaseInfo.error(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* slardar 自定义事件,用于事件统计
|
||||
* Slardar custom events for event statistics
|
||||
*/
|
||||
slardarEvent(...args: Parameters<typeof reporter.event>) {
|
||||
this.reportLogWithBaseInfo.event(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* slardar 自定义成功事件,用于事件统计
|
||||
* Slardar custom success events for event statistics
|
||||
*/
|
||||
slardarSuccessEvent(...args: Parameters<typeof reporter.event>) {
|
||||
this.reportLogWithBaseInfo.successEvent(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* slardar 自定义错误事件,用于事件统计, 有错误堆栈信息
|
||||
* Slardar custom error event, for event statistics, with error type information
|
||||
*/
|
||||
slardarErrorEvent(...args: Parameters<typeof reporter.errorEvent>) {
|
||||
this.reportLogWithBaseInfo.errorEvent(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件追踪, 用于链路性能统计
|
||||
* Event tracking for link performance statistics
|
||||
*/
|
||||
slardarTracer(...args: Parameters<typeof reporter.tracer>) {
|
||||
return this.reportLogWithBaseInfo.tracer(...args);
|
||||
|
||||
@@ -84,10 +84,10 @@ export class RequestManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入的request hooks, 可以对每个scene单独做拦截
|
||||
* Incoming request hooks can be intercepted separately for each scene
|
||||
*/
|
||||
private useRequestInterceptor() {
|
||||
// 执行传入的统一的hooks
|
||||
// Execute incoming unified hooks
|
||||
const onCommonBeforeRequest = async (
|
||||
config: InternalAxiosRequestConfig,
|
||||
) => {
|
||||
@@ -101,7 +101,7 @@ export class RequestManager {
|
||||
}
|
||||
return merge(config, rest);
|
||||
};
|
||||
// 执行每个scene的hooks
|
||||
// Execute hooks for each scene
|
||||
const onSceneBeforeRequest = async (config: InternalAxiosRequestConfig) => {
|
||||
const { scenes } = this.mergedBaseOptions;
|
||||
if (!scenes) {
|
||||
@@ -124,22 +124,22 @@ export class RequestManager {
|
||||
return merge({ ...rest }, config);
|
||||
};
|
||||
this.request.interceptors.request.use(async config => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- 临时变量, 挺正常的
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- temporary variable, quite normal
|
||||
const _config = await onCommonBeforeRequest(config);
|
||||
return await onSceneBeforeRequest(_config);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入的response hooks, 可以对每个scene单独做拦截
|
||||
* Incoming response hooks, can be intercepted individually for each scene
|
||||
*/
|
||||
private useResponseInterceptor() {
|
||||
// 执行传入的统一的hooks
|
||||
// Execute incoming unified hooks
|
||||
const onCommonAfterResponse = async (
|
||||
response: AxiosResponse,
|
||||
hooksName: 'onAfterResponse' | 'onErrrorResponse' = 'onAfterResponse',
|
||||
): Promise<AxiosResponse> => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- 临时变量, 挺正常的
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- temporary variable, quite normal
|
||||
let _response: AxiosResponse | Promise<AxiosResponse> = response;
|
||||
const { hooks } = this.mergedBaseOptions;
|
||||
if (!hooks) {
|
||||
@@ -151,13 +151,13 @@ export class RequestManager {
|
||||
}
|
||||
return _response;
|
||||
};
|
||||
// 执行每个scene的hooks
|
||||
// Execute hooks for each scene
|
||||
const onSceneAfterResponse = async (
|
||||
response: AxiosResponse,
|
||||
hooksName: 'onAfterResponse' | 'onErrrorResponse' = 'onAfterResponse',
|
||||
): Promise<AxiosResponse> => {
|
||||
const { scenes } = this.mergedBaseOptions;
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- 临时变量, 挺正常的
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- temporary variable, quite normal
|
||||
let _response: AxiosResponse | Promise<AxiosResponse> = response;
|
||||
if (!scenes) {
|
||||
return response;
|
||||
@@ -180,12 +180,12 @@ export class RequestManager {
|
||||
};
|
||||
this.request.interceptors.response.use(
|
||||
async response => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- 临时变量, 挺正常的
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- temporary variable, quite normal
|
||||
const _response = await onCommonAfterResponse(response);
|
||||
return await onSceneAfterResponse(_response);
|
||||
},
|
||||
async response => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- 临时变量, 挺正常的
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- temporary variable, quite normal
|
||||
const _response = await onCommonAfterResponse(
|
||||
response,
|
||||
'onErrrorResponse',
|
||||
@@ -196,7 +196,7 @@ export class RequestManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置信息
|
||||
* Get configuration information
|
||||
*/
|
||||
getSceneConfig(scene: RequestScene): PartiallyRequired<SceneConfig, 'url'> {
|
||||
const { hooks, scenes, ...rest } = this.mergedBaseOptions;
|
||||
|
||||
@@ -37,10 +37,10 @@ const useCsrfRequestHook = (config: InternalAxiosRequestConfig) => {
|
||||
config.method?.toLowerCase() === 'post' &&
|
||||
!config.headers.get('content-type')
|
||||
) {
|
||||
// 新的 csrf 防护需要 post 请求全部带上这个 header
|
||||
// The new CSRF protection requires all post requests to have this header.
|
||||
config.headers.set('content-type', 'application/json');
|
||||
if (!config.data) {
|
||||
// axios 会自动在 data 为空时清除 content-type,所以需要设置一个空对象
|
||||
// Axios will automatically clear the content-type when the data is empty, so you need to set an empty object
|
||||
config.data = {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ interface Hooks {
|
||||
| InternalChannelSendMessageConfig
|
||||
| Promise<InternalChannelSendMessageConfig>
|
||||
>;
|
||||
//为何这样,是由于OpenSdk 与 CozeSdk消息差异过大,缺少了Ack消息,需要构造出来。
|
||||
//The reason for this is that OpenSdk and CozeSdk messages are too different, missing Ack messages and need to be constructed.
|
||||
onGetMessageStreamParser?: (
|
||||
requestMessageRawBody: Record<string, unknown>,
|
||||
) => FetchSteamConfig<ParsedEvent>['streamParser'];
|
||||
|
||||
@@ -15,19 +15,19 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* sdk版本号
|
||||
* SDK version number
|
||||
*/
|
||||
export const CHAT_CORE_VERSION = '1.1.0';
|
||||
|
||||
/**
|
||||
* 使用环境
|
||||
* usage environment
|
||||
*/
|
||||
export type ENV = 'local' | 'boe' | 'production' | 'thirdPart';
|
||||
|
||||
/**
|
||||
* 部署版本
|
||||
* release: 正式版
|
||||
* inhouse: 内部测试版本
|
||||
* Deployment version
|
||||
* Release: Official Version
|
||||
* Inhouse: dogfooding version
|
||||
*/
|
||||
|
||||
export type DeployVersion = 'release' | 'inhouse';
|
||||
@@ -41,11 +41,11 @@ export const SECONDS_PER_SECOND = 1000;
|
||||
// 1min -> 60*1000ms
|
||||
export const MILLISECONDS_PER_MINUTE = SECONDS_PER_MINUTE * SECONDS_PER_SECOND;
|
||||
|
||||
// 拉流超时
|
||||
// eslint-disable-next-line @typescript-eslint/no-magic-numbers -- 5min更语义化
|
||||
// Pull stream timeout
|
||||
// eslint-disable-next-line @typescript-eslint/no-magic-numbers -- 5min more semantic
|
||||
export const BETWEEN_CHUNK_TIMEOUT = 5 * MILLISECONDS_PER_MINUTE;
|
||||
|
||||
// 发送消息超时
|
||||
// Send message timed out
|
||||
export const SEND_MESSAGE_TIMEOUT = MILLISECONDS_PER_MINUTE;
|
||||
|
||||
const MAX_RANDOM_NUMBER = 0x10000000;
|
||||
@@ -56,7 +56,7 @@ function getRandomDeviceID() {
|
||||
|
||||
export const randomDeviceID = getRandomDeviceID();
|
||||
|
||||
// ws 最大重试次数
|
||||
// WS maximum number of retries
|
||||
export const WS_MAX_RETRY_COUNT = 10;
|
||||
|
||||
export {
|
||||
|
||||
@@ -27,7 +27,7 @@ export const filterEmptyField = <T extends Record<string, unknown>>(
|
||||
export type PartiallyRequired<T, K extends keyof T> = Omit<T, K> &
|
||||
Required<Pick<T, K>>;
|
||||
|
||||
// enum转换为联合类型
|
||||
// Enum to union type
|
||||
export type EnumToUnion<T extends Record<string, string>> = T[keyof T];
|
||||
|
||||
export const muteMergeWithArray = (...args: Parameters<typeof merge>) =>
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
import { type ENV, type DeployVersion } from '../const';
|
||||
|
||||
/**
|
||||
* 获取 slardar 上报环境
|
||||
* 不同环境之间数据隔离
|
||||
* Get slardar report environment
|
||||
* Data isolation between different environments
|
||||
* @returns
|
||||
*/
|
||||
export const getSlardarEnv = ({
|
||||
|
||||
Reference in New Issue
Block a user