@wwlocal/aibot-plugin-node 20260409.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +489 -0
- package/config.example.json +169 -0
- package/dist/cjs/index.js +76 -0
- package/dist/cjs/src/adapters/anthropic-adapter.js +534 -0
- package/dist/cjs/src/adapters/base-adapter.js +176 -0
- package/dist/cjs/src/adapters/deepseek-adapter.js +328 -0
- package/dist/cjs/src/adapters/dify-adapter.js +636 -0
- package/dist/cjs/src/adapters/index.js +131 -0
- package/dist/cjs/src/adapters/openai-adapter.js +361 -0
- package/dist/cjs/src/adapters/webhook-adapter.js +260 -0
- package/dist/cjs/src/agent-forwarder.js +87 -0
- package/dist/cjs/src/ca-cert.js +162 -0
- package/dist/cjs/src/config.js +169 -0
- package/dist/cjs/src/const.js +124 -0
- package/dist/cjs/src/conversation-manager.js +147 -0
- package/dist/cjs/src/dm-policy.js +46 -0
- package/dist/cjs/src/group-policy.js +95 -0
- package/dist/cjs/src/media-handler.js +136 -0
- package/dist/cjs/src/media-loader.js +271 -0
- package/dist/cjs/src/media-storage.js +165 -0
- package/dist/cjs/src/media-uploader.js +203 -0
- package/dist/cjs/src/message-parser.js +133 -0
- package/dist/cjs/src/message-sender.js +87 -0
- package/dist/cjs/src/monitor.js +849 -0
- package/dist/cjs/src/reqid-store.js +87 -0
- package/dist/cjs/src/server.js +72 -0
- package/dist/cjs/src/service-manager.js +135 -0
- package/dist/cjs/src/state-manager.js +143 -0
- package/dist/cjs/src/template-card-parser.js +498 -0
- package/dist/cjs/src/timeout.js +41 -0
- package/dist/cjs/src/version.js +25 -0
- package/dist/esm/index.js +74 -0
- package/dist/esm/src/adapters/anthropic-adapter.js +512 -0
- package/dist/esm/src/adapters/base-adapter.js +174 -0
- package/dist/esm/src/adapters/deepseek-adapter.js +326 -0
- package/dist/esm/src/adapters/dify-adapter.js +634 -0
- package/dist/esm/src/adapters/index.js +123 -0
- package/dist/esm/src/adapters/openai-adapter.js +339 -0
- package/dist/esm/src/adapters/webhook-adapter.js +258 -0
- package/dist/esm/src/agent-forwarder.js +84 -0
- package/dist/esm/src/ca-cert.js +136 -0
- package/dist/esm/src/config.js +145 -0
- package/dist/esm/src/const.js +100 -0
- package/dist/esm/src/conversation-manager.js +144 -0
- package/dist/esm/src/dm-policy.js +44 -0
- package/dist/esm/src/group-policy.js +92 -0
- package/dist/esm/src/media-handler.js +133 -0
- package/dist/esm/src/media-loader.js +246 -0
- package/dist/esm/src/media-storage.js +143 -0
- package/dist/esm/src/media-uploader.js +198 -0
- package/dist/esm/src/message-parser.js +131 -0
- package/dist/esm/src/message-sender.js +83 -0
- package/dist/esm/src/monitor.js +841 -0
- package/dist/esm/src/reqid-store.js +85 -0
- package/dist/esm/src/server.js +69 -0
- package/dist/esm/src/service-manager.js +133 -0
- package/dist/esm/src/state-manager.js +134 -0
- package/dist/esm/src/template-card-parser.js +495 -0
- package/dist/esm/src/timeout.js +38 -0
- package/dist/esm/src/version.js +22 -0
- package/dist/esm/types/index.d.ts +14 -0
- package/dist/esm/types/src/adapters/anthropic-adapter.d.ts +93 -0
- package/dist/esm/types/src/adapters/base-adapter.d.ts +76 -0
- package/dist/esm/types/src/adapters/deepseek-adapter.d.ts +87 -0
- package/dist/esm/types/src/adapters/dify-adapter.d.ts +100 -0
- package/dist/esm/types/src/adapters/index.d.ts +60 -0
- package/dist/esm/types/src/adapters/openai-adapter.d.ts +82 -0
- package/dist/esm/types/src/adapters/types.d.ts +373 -0
- package/dist/esm/types/src/adapters/webhook-adapter.d.ts +54 -0
- package/dist/esm/types/src/agent-forwarder.d.ts +32 -0
- package/dist/esm/types/src/ca-cert.d.ts +53 -0
- package/dist/esm/types/src/config.d.ts +29 -0
- package/dist/esm/types/src/const.d.ts +74 -0
- package/dist/esm/types/src/conversation-manager.d.ts +81 -0
- package/dist/esm/types/src/dm-policy.d.ts +27 -0
- package/dist/esm/types/src/group-policy.d.ts +28 -0
- package/dist/esm/types/src/interface.d.ts +332 -0
- package/dist/esm/types/src/media-handler.d.ts +36 -0
- package/dist/esm/types/src/media-loader.d.ts +47 -0
- package/dist/esm/types/src/media-storage.d.ts +35 -0
- package/dist/esm/types/src/media-uploader.d.ts +65 -0
- package/dist/esm/types/src/message-parser.d.ts +89 -0
- package/dist/esm/types/src/message-sender.d.ts +34 -0
- package/dist/esm/types/src/monitor.d.ts +30 -0
- package/dist/esm/types/src/reqid-store.d.ts +23 -0
- package/dist/esm/types/src/server.d.ts +23 -0
- package/dist/esm/types/src/service-manager.d.ts +52 -0
- package/dist/esm/types/src/state-manager.d.ts +76 -0
- package/dist/esm/types/src/template-card-parser.d.ts +18 -0
- package/dist/esm/types/src/timeout.d.ts +20 -0
- package/dist/esm/types/src/version.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/package.json +51 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 可插拔智能体适配器 - 类型定义
|
|
3
|
+
*
|
|
4
|
+
* 定义适配器接口规范和相关类型,所有适配器必须实现 AgentAdapter 接口
|
|
5
|
+
*/
|
|
6
|
+
import type { RuntimeLogger, DeliverPayload, DeliverInfo, AgentEndpoint } from "../interface.js";
|
|
7
|
+
/**
|
|
8
|
+
* 适配器接口 — 所有智能体平台适配器必须实现
|
|
9
|
+
*/
|
|
10
|
+
export interface AgentAdapter {
|
|
11
|
+
/** 适配器唯一标识(对应配置中的 provider 字段) */
|
|
12
|
+
readonly name: string;
|
|
13
|
+
/** 人类可读的显示名称 */
|
|
14
|
+
readonly displayName: string;
|
|
15
|
+
/**
|
|
16
|
+
* 将统一的转发请求转换为平台特定的 HTTP 请求并执行
|
|
17
|
+
*
|
|
18
|
+
* @param request - 标准化的转发请求(文本、媒体、引用等)
|
|
19
|
+
* @param endpoint - 智能体端点配置(URL、认证、模型等)
|
|
20
|
+
* @param callbacks - 回调函数集(deliver、onReplyStart、onError)
|
|
21
|
+
* @returns 最终的完整回复文本
|
|
22
|
+
*/
|
|
23
|
+
forward(request: AdapterRequest, endpoint: AgentEndpoint, callbacks: AdapterCallbacks): Promise<string>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 标准化的适配器请求
|
|
27
|
+
*/
|
|
28
|
+
export interface AdapterRequest {
|
|
29
|
+
/** 用户消息文本 */
|
|
30
|
+
text: string;
|
|
31
|
+
/** 媒体文件列表 */
|
|
32
|
+
mediaPaths?: Array<{
|
|
33
|
+
path: string;
|
|
34
|
+
contentType?: string;
|
|
35
|
+
}>;
|
|
36
|
+
/** 引用内容 */
|
|
37
|
+
quoteContent?: string;
|
|
38
|
+
/** 中止信号 */
|
|
39
|
+
abortSignal?: AbortSignal;
|
|
40
|
+
/** 运行时日志 */
|
|
41
|
+
runtime?: RuntimeLogger;
|
|
42
|
+
/** 扩展上下文(适配器可按需使用) */
|
|
43
|
+
context?: AdapterContext;
|
|
44
|
+
/** 对话历史消息(用于多轮对话) */
|
|
45
|
+
historyMessages?: Array<{
|
|
46
|
+
role: "user" | "assistant";
|
|
47
|
+
content: string;
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 适配器扩展上下文
|
|
52
|
+
*/
|
|
53
|
+
export interface AdapterContext {
|
|
54
|
+
/** 账号 ID(用于会话隔离,防止多账号历史串联) */
|
|
55
|
+
accountId?: string;
|
|
56
|
+
/** 企微用户 ID(用于 Dify 的 user 字段等场景) */
|
|
57
|
+
userId?: string;
|
|
58
|
+
/** 企微聊天 ID(用于 Dify 会话管理等场景) */
|
|
59
|
+
chatId?: string;
|
|
60
|
+
/** 聊天类型 */
|
|
61
|
+
chatType?: "single" | "group";
|
|
62
|
+
/** 其他自定义字段 */
|
|
63
|
+
[key: string]: unknown;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 适配器回调集
|
|
67
|
+
*/
|
|
68
|
+
export interface AdapterCallbacks {
|
|
69
|
+
/** 内容投递回调(中间帧/最终帧) */
|
|
70
|
+
deliver: (payload: DeliverPayload, info: DeliverInfo) => Promise<void>;
|
|
71
|
+
/** 首次收到回复时触发 */
|
|
72
|
+
onReplyStart?: () => Promise<void>;
|
|
73
|
+
/** 错误回调 */
|
|
74
|
+
onError?: (err: Error, info: {
|
|
75
|
+
kind: string;
|
|
76
|
+
}) => void;
|
|
77
|
+
}
|
|
78
|
+
/** OpenAI 消息格式 */
|
|
79
|
+
export interface ChatMessage {
|
|
80
|
+
role: "system" | "user" | "assistant";
|
|
81
|
+
content: string | ChatContentPart[];
|
|
82
|
+
}
|
|
83
|
+
/** 多模态内容部分 */
|
|
84
|
+
export type ChatContentPart = {
|
|
85
|
+
type: "text";
|
|
86
|
+
text: string;
|
|
87
|
+
} | {
|
|
88
|
+
type: "image_url";
|
|
89
|
+
image_url: {
|
|
90
|
+
url: string;
|
|
91
|
+
detail?: string;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
/** OpenAI Chat Completions 请求体 */
|
|
95
|
+
export interface ChatCompletionsRequest {
|
|
96
|
+
model?: string;
|
|
97
|
+
messages: ChatMessage[];
|
|
98
|
+
stream?: boolean;
|
|
99
|
+
[key: string]: unknown;
|
|
100
|
+
}
|
|
101
|
+
/** SSE 流式响应中的 delta 片段 */
|
|
102
|
+
export interface StreamDelta {
|
|
103
|
+
choices?: Array<{
|
|
104
|
+
delta?: {
|
|
105
|
+
content?: string;
|
|
106
|
+
role?: string;
|
|
107
|
+
reasoning_content?: string;
|
|
108
|
+
};
|
|
109
|
+
finish_reason?: string | null;
|
|
110
|
+
}>;
|
|
111
|
+
}
|
|
112
|
+
/** 非流式响应 */
|
|
113
|
+
export interface ChatCompletionsResponse {
|
|
114
|
+
choices?: Array<{
|
|
115
|
+
message?: {
|
|
116
|
+
content?: string;
|
|
117
|
+
role?: string;
|
|
118
|
+
reasoning_content?: string;
|
|
119
|
+
};
|
|
120
|
+
finish_reason?: string;
|
|
121
|
+
}>;
|
|
122
|
+
usage?: {
|
|
123
|
+
prompt_tokens?: number;
|
|
124
|
+
completion_tokens?: number;
|
|
125
|
+
total_tokens?: number;
|
|
126
|
+
completion_tokens_details?: {
|
|
127
|
+
reasoning_tokens?: number;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** DeepSeek 推理内容展示策略 */
|
|
132
|
+
export type ReasoningDisplayMode = "show" | "hide" | "collapse";
|
|
133
|
+
/** DeepSeek 适配器扩展配置 */
|
|
134
|
+
export interface DeepSeekProviderOptions {
|
|
135
|
+
/** 推理过程展示策略(默认 collapse) */
|
|
136
|
+
reasoningDisplay?: ReasoningDisplayMode;
|
|
137
|
+
}
|
|
138
|
+
/** Dify 应用类型 */
|
|
139
|
+
export type DifyAppType = "chat" | "completion" | "workflow";
|
|
140
|
+
/** Dify 适配器扩展配置 */
|
|
141
|
+
export interface DifyProviderOptions {
|
|
142
|
+
/** Dify 应用类型(默认 chat) */
|
|
143
|
+
difyAppType?: DifyAppType;
|
|
144
|
+
/** Dify 应用变量(对应 inputs 参数) */
|
|
145
|
+
difyInputs?: Record<string, string>;
|
|
146
|
+
/** 固定用户标识(为空时使用企微 userid) */
|
|
147
|
+
difyUser?: string;
|
|
148
|
+
/** 是否在流式中展示 Workflow 节点执行进度(默认 false) */
|
|
149
|
+
showWorkflowProgress?: boolean;
|
|
150
|
+
}
|
|
151
|
+
/** Dify Chat Messages 请求体 */
|
|
152
|
+
export interface DifyChatRequest {
|
|
153
|
+
/** 用户输入内容 */
|
|
154
|
+
query: string;
|
|
155
|
+
/** 用户标识 */
|
|
156
|
+
user: string;
|
|
157
|
+
/** 响应模式:streaming 或 blocking */
|
|
158
|
+
response_mode: "streaming" | "blocking";
|
|
159
|
+
/** 会话 ID(多轮对话) */
|
|
160
|
+
conversation_id?: string;
|
|
161
|
+
/** 应用变量 */
|
|
162
|
+
inputs?: Record<string, string>;
|
|
163
|
+
/** 文件列表 */
|
|
164
|
+
files?: DifyFile[];
|
|
165
|
+
}
|
|
166
|
+
/** Dify 文件类型 */
|
|
167
|
+
export interface DifyFile {
|
|
168
|
+
type: "image" | "document" | "audio" | "video" | "custom";
|
|
169
|
+
transfer_method: "remote_url" | "local_file";
|
|
170
|
+
url?: string;
|
|
171
|
+
upload_file_id?: string;
|
|
172
|
+
}
|
|
173
|
+
/** Dify 文件上传响应 */
|
|
174
|
+
export interface DifyFileUploadResponse {
|
|
175
|
+
id: string;
|
|
176
|
+
name: string;
|
|
177
|
+
size: number;
|
|
178
|
+
extension: string;
|
|
179
|
+
mime_type: string;
|
|
180
|
+
created_by: string;
|
|
181
|
+
created_at: number;
|
|
182
|
+
}
|
|
183
|
+
/** Dify SSE 事件类型 */
|
|
184
|
+
export type DifyEventType = "message" | "message_end" | "message_file" | "message_replace" | "text_chunk" | "text_replace" | "workflow_started" | "workflow_finished" | "node_started" | "node_finished" | "node_retry" | "iteration_started" | "iteration_next" | "iteration_completed" | "loop_started" | "loop_next" | "loop_completed" | "workflow_paused" | "agent_log" | "error" | "ping";
|
|
185
|
+
/** Dify SSE 事件数据 */
|
|
186
|
+
export interface DifySSEEvent {
|
|
187
|
+
event: DifyEventType;
|
|
188
|
+
task_id?: string;
|
|
189
|
+
message_id?: string;
|
|
190
|
+
conversation_id?: string;
|
|
191
|
+
/** ChatBot 模式下的文本增量(message / message_replace 事件) */
|
|
192
|
+
answer?: string;
|
|
193
|
+
/** Chatflow 模式下的文本片段(text_chunk 事件) */
|
|
194
|
+
text?: string;
|
|
195
|
+
created_at?: number;
|
|
196
|
+
metadata?: {
|
|
197
|
+
usage?: {
|
|
198
|
+
prompt_tokens?: number;
|
|
199
|
+
completion_tokens?: number;
|
|
200
|
+
total_tokens?: number;
|
|
201
|
+
};
|
|
202
|
+
};
|
|
203
|
+
id?: string;
|
|
204
|
+
type?: string;
|
|
205
|
+
belongs_to?: string;
|
|
206
|
+
url?: string;
|
|
207
|
+
workflow_run_id?: string;
|
|
208
|
+
data?: {
|
|
209
|
+
id?: string;
|
|
210
|
+
workflow_id?: string;
|
|
211
|
+
status?: string;
|
|
212
|
+
outputs?: Record<string, unknown>;
|
|
213
|
+
error?: string;
|
|
214
|
+
node_id?: string;
|
|
215
|
+
node_type?: string;
|
|
216
|
+
title?: string;
|
|
217
|
+
index?: number;
|
|
218
|
+
inputs?: Record<string, unknown>;
|
|
219
|
+
iteration_id?: string;
|
|
220
|
+
loop_id?: string;
|
|
221
|
+
sequence_number?: number;
|
|
222
|
+
retry_index?: number;
|
|
223
|
+
};
|
|
224
|
+
status?: number;
|
|
225
|
+
code?: string;
|
|
226
|
+
message?: string;
|
|
227
|
+
}
|
|
228
|
+
/** Anthropic 适配器扩展配置 */
|
|
229
|
+
export interface AnthropicProviderOptions {
|
|
230
|
+
/** 思维链展示策略(默认 collapse) */
|
|
231
|
+
reasoningDisplay?: ReasoningDisplayMode;
|
|
232
|
+
/** Anthropic API 要求必传的 max_tokens(默认 4096) */
|
|
233
|
+
maxTokens?: number;
|
|
234
|
+
/** Anthropic API 版本头 anthropic-version(默认 "2023-06-01") */
|
|
235
|
+
anthropicVersion?: string;
|
|
236
|
+
/** 是否使用 x-api-key 头认证(false 时用 Bearer Token,默认 true) */
|
|
237
|
+
useXApiKey?: boolean;
|
|
238
|
+
}
|
|
239
|
+
/** Anthropic Messages API 请求体 */
|
|
240
|
+
export interface AnthropicMessagesRequest {
|
|
241
|
+
model: string;
|
|
242
|
+
messages: AnthropicMessage[];
|
|
243
|
+
max_tokens: number;
|
|
244
|
+
stream?: boolean;
|
|
245
|
+
system?: string;
|
|
246
|
+
[key: string]: unknown;
|
|
247
|
+
}
|
|
248
|
+
/** Anthropic 消息格式 */
|
|
249
|
+
export interface AnthropicMessage {
|
|
250
|
+
role: "user" | "assistant";
|
|
251
|
+
content: string | AnthropicContentBlock[];
|
|
252
|
+
}
|
|
253
|
+
/** Anthropic 内容块 */
|
|
254
|
+
export type AnthropicContentBlock = {
|
|
255
|
+
type: "text";
|
|
256
|
+
text: string;
|
|
257
|
+
} | {
|
|
258
|
+
type: "image";
|
|
259
|
+
source: {
|
|
260
|
+
type: "base64";
|
|
261
|
+
media_type: string;
|
|
262
|
+
data: string;
|
|
263
|
+
};
|
|
264
|
+
} | {
|
|
265
|
+
type: "thinking";
|
|
266
|
+
thinking: string;
|
|
267
|
+
} | {
|
|
268
|
+
type: "tool_use";
|
|
269
|
+
id: string;
|
|
270
|
+
name: string;
|
|
271
|
+
input: unknown;
|
|
272
|
+
};
|
|
273
|
+
/** Anthropic 非流式响应 */
|
|
274
|
+
export interface AnthropicMessagesResponse {
|
|
275
|
+
id: string;
|
|
276
|
+
type: "message";
|
|
277
|
+
role: "assistant";
|
|
278
|
+
content: AnthropicResponseContentBlock[];
|
|
279
|
+
model: string;
|
|
280
|
+
stop_reason: string | null;
|
|
281
|
+
stop_sequence: string | null;
|
|
282
|
+
usage: {
|
|
283
|
+
input_tokens: number;
|
|
284
|
+
output_tokens: number;
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
/** Anthropic 响应内容块 */
|
|
288
|
+
export type AnthropicResponseContentBlock = {
|
|
289
|
+
type: "text";
|
|
290
|
+
text: string;
|
|
291
|
+
} | {
|
|
292
|
+
type: "thinking";
|
|
293
|
+
thinking: string;
|
|
294
|
+
} | {
|
|
295
|
+
type: "tool_use";
|
|
296
|
+
id: string;
|
|
297
|
+
name: string;
|
|
298
|
+
input: unknown;
|
|
299
|
+
};
|
|
300
|
+
/** Anthropic SSE 事件类型 */
|
|
301
|
+
export type AnthropicSSEEventType = "message_start" | "content_block_start" | "content_block_delta" | "content_block_stop" | "message_delta" | "message_stop" | "ping" | "error";
|
|
302
|
+
/** Anthropic SSE 事件数据 */
|
|
303
|
+
export interface AnthropicSSEEvent {
|
|
304
|
+
type: AnthropicSSEEventType;
|
|
305
|
+
/** message_start 事件中的 message 信息 */
|
|
306
|
+
message?: {
|
|
307
|
+
id: string;
|
|
308
|
+
type: string;
|
|
309
|
+
role: string;
|
|
310
|
+
model: string;
|
|
311
|
+
usage?: {
|
|
312
|
+
input_tokens: number;
|
|
313
|
+
output_tokens: number;
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
/** content_block_start 事件的内容块序号 */
|
|
317
|
+
index?: number;
|
|
318
|
+
/** content_block_start 事件的内容块信息 */
|
|
319
|
+
content_block?: {
|
|
320
|
+
type: string;
|
|
321
|
+
text?: string;
|
|
322
|
+
thinking?: string;
|
|
323
|
+
};
|
|
324
|
+
/** content_block_delta 事件的增量 */
|
|
325
|
+
delta?: {
|
|
326
|
+
type: string;
|
|
327
|
+
text?: string;
|
|
328
|
+
thinking?: string;
|
|
329
|
+
partial_json?: string;
|
|
330
|
+
stop_reason?: string;
|
|
331
|
+
stop_sequence?: string | null;
|
|
332
|
+
};
|
|
333
|
+
/** message_delta 事件的 usage */
|
|
334
|
+
usage?: {
|
|
335
|
+
output_tokens: number;
|
|
336
|
+
};
|
|
337
|
+
/** error 事件 */
|
|
338
|
+
error?: {
|
|
339
|
+
type: string;
|
|
340
|
+
message: string;
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/** Webhook 适配器扩展配置 */
|
|
344
|
+
export interface WebhookProviderOptions {
|
|
345
|
+
/** 请求体模板,支持变量替换 */
|
|
346
|
+
requestTemplate?: Record<string, unknown>;
|
|
347
|
+
/** 响应 JSON 中文本内容的字段路径(支持点号嵌套) */
|
|
348
|
+
responseTextField?: string;
|
|
349
|
+
/** 流式 SSE 中文本增量的字段路径 */
|
|
350
|
+
streamEventField?: string;
|
|
351
|
+
/** 流式结束标记(默认 "[DONE]") */
|
|
352
|
+
streamEndMarker?: string;
|
|
353
|
+
/** HTTP 方法(默认 "POST") */
|
|
354
|
+
method?: string;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* 适配器注册表接口
|
|
358
|
+
*/
|
|
359
|
+
export interface IAdapterRegistry {
|
|
360
|
+
/** 注册适配器 */
|
|
361
|
+
register(adapter: AgentAdapter): void;
|
|
362
|
+
/** 按 provider 名称获取适配器 */
|
|
363
|
+
get(provider: string): AgentAdapter | undefined;
|
|
364
|
+
/** 列出所有已注册适配器 */
|
|
365
|
+
list(): AgentAdapter[];
|
|
366
|
+
/**
|
|
367
|
+
* 解析并返回适配器
|
|
368
|
+
* 1. 优先使用 endpoint.provider 指定的适配器
|
|
369
|
+
* 2. 若 provider 未配置,尝试从 url 自动推断
|
|
370
|
+
* 3. 兜底使用 openai 适配器
|
|
371
|
+
*/
|
|
372
|
+
resolve(endpoint: AgentEndpoint): AgentAdapter;
|
|
373
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook 适配器
|
|
3
|
+
*
|
|
4
|
+
* 适用于:企业自建的非标准 HTTP API
|
|
5
|
+
*
|
|
6
|
+
* 核心机制:通过配置定义请求和响应的字段映射模板,无需编写代码
|
|
7
|
+
*
|
|
8
|
+
* 支持的模板变量:
|
|
9
|
+
* - {{text}} - 用户消息文本
|
|
10
|
+
* - {{user}} - 用户 ID
|
|
11
|
+
* - {{chatId}} - 聊天 ID
|
|
12
|
+
* - {{chatType}} - 聊天类型(single/group)
|
|
13
|
+
*/
|
|
14
|
+
import type { AgentEndpoint } from "../interface.js";
|
|
15
|
+
import { BaseAdapter } from "./base-adapter.js";
|
|
16
|
+
import type { AdapterRequest, AdapterCallbacks } from "./types.js";
|
|
17
|
+
/**
|
|
18
|
+
* Webhook 适配器
|
|
19
|
+
*/
|
|
20
|
+
export declare class WebhookAdapter extends BaseAdapter {
|
|
21
|
+
readonly name = "webhook";
|
|
22
|
+
readonly displayName = "Custom Webhook";
|
|
23
|
+
/**
|
|
24
|
+
* 获取 Webhook 配置选项
|
|
25
|
+
*/
|
|
26
|
+
private getOptions;
|
|
27
|
+
/**
|
|
28
|
+
* 转发请求到 Webhook API
|
|
29
|
+
*/
|
|
30
|
+
forward(request: AdapterRequest, endpoint: AgentEndpoint, callbacks: AdapterCallbacks): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* 构建请求体(应用模板变量替换)
|
|
33
|
+
*/
|
|
34
|
+
private buildRequestBody;
|
|
35
|
+
/**
|
|
36
|
+
* 递归应用模板变量替换
|
|
37
|
+
*/
|
|
38
|
+
private applyTemplate;
|
|
39
|
+
/**
|
|
40
|
+
* 从对象中按路径获取值
|
|
41
|
+
*
|
|
42
|
+
* @param obj 源对象
|
|
43
|
+
* @param path 字段路径(如 "data.reply.text")
|
|
44
|
+
*/
|
|
45
|
+
private getValueByPath;
|
|
46
|
+
/**
|
|
47
|
+
* 处理流式响应
|
|
48
|
+
*/
|
|
49
|
+
private handleStreamResponse;
|
|
50
|
+
/**
|
|
51
|
+
* 处理非流式响应
|
|
52
|
+
*/
|
|
53
|
+
private handleNonStreamResponse;
|
|
54
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 智能体转发器(适配器调度层)
|
|
3
|
+
*
|
|
4
|
+
* 核心模块,负责:
|
|
5
|
+
* 1. 根据端点配置解析对应的适配器
|
|
6
|
+
* 2. 读取对话历史,注入到适配器请求中
|
|
7
|
+
* 3. 调用适配器执行转发
|
|
8
|
+
* 4. AI 回复后,将用户消息和 AI 回复保存到对话历史
|
|
9
|
+
* 5. 通过 deliver 回调驱动 monitor 的流式回复逻辑
|
|
10
|
+
*
|
|
11
|
+
* v1.1.0 重构:从 OpenAI 专用转发器改为可插拔适配器调度层
|
|
12
|
+
* v1.1.1 新增:多轮对话上下文记忆
|
|
13
|
+
*/
|
|
14
|
+
import type { AgentEndpoint, ForwardOptions } from "./interface.js";
|
|
15
|
+
/**
|
|
16
|
+
* 将企微消息转发到外部智能体
|
|
17
|
+
*
|
|
18
|
+
* 完整流程:
|
|
19
|
+
* 1. 根据 endpoint.provider 解析适配器
|
|
20
|
+
* 2. 读取对话历史(如果 maxHistoryRounds > 0)
|
|
21
|
+
* 3. 构建适配器请求(含对话历史)
|
|
22
|
+
* 4. 调用 adapter.forward() 执行转发
|
|
23
|
+
* 5. 通过 deliver 回调驱动 monitor 的流式回复
|
|
24
|
+
* 6. AI 回复完成后,保存本轮对话到历史
|
|
25
|
+
*/
|
|
26
|
+
export declare function forwardToAgent(options: ForwardOptions): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* 查找并返回匹配的智能体端点
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveAgentEndpoint(agents: AgentEndpoint[], agentName?: string): AgentEndpoint | undefined;
|
|
31
|
+
export { resolveAdapter, getRegisteredAdapters, adapterRegistry, } from "./adapters/index.js";
|
|
32
|
+
export type { AgentAdapter, AdapterRequest, AdapterCallbacks, AdapterContext, } from "./adapters/index.js";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自签名 CA 证书运行时注入模块
|
|
3
|
+
*
|
|
4
|
+
* 背景:
|
|
5
|
+
* NODE_EXTRA_CA_CERTS 环境变量只在 Node.js 进程启动时读取一次,
|
|
6
|
+
* 但用户配置 caCert 可能在运行时加载,此时进程已在运行,
|
|
7
|
+
* 所以不能依赖 NODE_EXTRA_CA_CERTS。
|
|
8
|
+
*
|
|
9
|
+
* 原理:
|
|
10
|
+
* Node.js 所有 TLS 连接最终都会调用 tls.createSecureContext(),
|
|
11
|
+
* 我们在这一层做拦截(monkey-patch),将自签名 CA 证书追加到
|
|
12
|
+
* 每次创建的 TLS 上下文中,从而覆盖全部网络出口。
|
|
13
|
+
*
|
|
14
|
+
* 安全性说明:
|
|
15
|
+
* - 仅追加 CA 证书,不禁用证书验证
|
|
16
|
+
* - 不覆盖系统默认 CA 列表,只在默认列表基础上追加
|
|
17
|
+
* - patch 是幂等的,多次调用只生效一次
|
|
18
|
+
* - 调用 removeCaCertPatch() 可还原到原始状态
|
|
19
|
+
*
|
|
20
|
+
* 副作用:
|
|
21
|
+
* patch 是进程全局的,会影响同一进程中所有 TLS 连接。
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* 校验证书文件是否存在且为有效 PEM 格式
|
|
25
|
+
*
|
|
26
|
+
* @param certPath - 证书文件的绝对路径
|
|
27
|
+
* @returns 校验结果
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateCaCertFile(certPath: string): {
|
|
30
|
+
ok: true;
|
|
31
|
+
content: string;
|
|
32
|
+
fullPath: string;
|
|
33
|
+
} | {
|
|
34
|
+
ok: false;
|
|
35
|
+
error: string;
|
|
36
|
+
fullPath: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* 将自签名 CA 证书注入到 Node.js 全局 TLS 层
|
|
40
|
+
*
|
|
41
|
+
* @param certPath - 证书文件的绝对路径(PEM 格式)
|
|
42
|
+
* @param logger - 可选的日志函数
|
|
43
|
+
* @returns true 表示注入成功,false 表示跳过或失败
|
|
44
|
+
*/
|
|
45
|
+
export declare function injectCaCert(certPath: string, logger?: (...args: any[]) => void): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* 移除 CA 证书的 monkey-patch,还原到 Node.js 原始行为
|
|
48
|
+
*/
|
|
49
|
+
export declare function removeCaCertPatch(logger?: (...args: any[]) => void): void;
|
|
50
|
+
/**
|
|
51
|
+
* 检查当前是否已注入 CA 证书
|
|
52
|
+
*/
|
|
53
|
+
export declare function isCaCertInjected(): boolean;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 插件配置加载模块
|
|
3
|
+
*
|
|
4
|
+
* 从 JSON 配置文件加载插件配置,校验必填字段,提供合理默认值
|
|
5
|
+
*/
|
|
6
|
+
import type { PluginConfig, AccountConfig, ResolvedAccount } from "./interface.js";
|
|
7
|
+
/**
|
|
8
|
+
* 从 JSON 文件加载插件配置
|
|
9
|
+
*
|
|
10
|
+
* @param configPath - 配置文件路径
|
|
11
|
+
* @returns 解析后的配置
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadConfig(configPath: string): PluginConfig;
|
|
14
|
+
/**
|
|
15
|
+
* 解析账号配置,填充默认值,关联智能体端点
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveAccount(account: AccountConfig, config: PluginConfig): ResolvedAccount;
|
|
18
|
+
/**
|
|
19
|
+
* 解析所有启用的账号配置
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveAllAccounts(config: PluginConfig): ResolvedAccount[];
|
|
22
|
+
/**
|
|
23
|
+
* 打印已加载的适配器列表(启动日志)
|
|
24
|
+
*/
|
|
25
|
+
export declare function logRegisteredAdapters(): void;
|
|
26
|
+
/**
|
|
27
|
+
* 打印配置的智能体端点信息(启动日志)
|
|
28
|
+
*/
|
|
29
|
+
export declare function logAgentEndpoints(config: PluginConfig): void;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 企业微信私有部署渠道常量定义
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 渠道 ID
|
|
6
|
+
*/
|
|
7
|
+
export declare const CHANNEL_ID: "wecomserver";
|
|
8
|
+
/**
|
|
9
|
+
* 企业微信私有部署 WebSocket 命令枚举
|
|
10
|
+
*/
|
|
11
|
+
export declare enum WeComCommand {
|
|
12
|
+
/** 认证订阅 */
|
|
13
|
+
SUBSCRIBE = "aibot_subscribe",
|
|
14
|
+
/** 心跳 */
|
|
15
|
+
PING = "ping",
|
|
16
|
+
/** 企业微信推送消息 */
|
|
17
|
+
AIBOT_CALLBACK = "aibot_callback",
|
|
18
|
+
/** 响应消息 */
|
|
19
|
+
AIBOT_RESPONSE = "aibot_response"
|
|
20
|
+
}
|
|
21
|
+
/** 图片下载超时时间(毫秒) */
|
|
22
|
+
export declare const IMAGE_DOWNLOAD_TIMEOUT_MS = 30000;
|
|
23
|
+
/** 文件下载超时时间(毫秒) */
|
|
24
|
+
export declare const FILE_DOWNLOAD_TIMEOUT_MS = 60000;
|
|
25
|
+
/** 消息发送超时时间(毫秒) */
|
|
26
|
+
export declare const REPLY_SEND_TIMEOUT_MS = 15000;
|
|
27
|
+
/** 消息处理总超时时间(毫秒) */
|
|
28
|
+
export declare const MESSAGE_PROCESS_TIMEOUT_MS: number;
|
|
29
|
+
/** WebSocket 心跳间隔(毫秒) */
|
|
30
|
+
export declare const WS_HEARTBEAT_INTERVAL_MS = 30000;
|
|
31
|
+
/** WebSocket 连接断开时的最大重连次数 */
|
|
32
|
+
export declare const WS_MAX_RECONNECT_ATTEMPTS = 10;
|
|
33
|
+
/** WebSocket 认证失败时的最大重试次数 */
|
|
34
|
+
export declare const WS_MAX_AUTH_FAILURE_ATTEMPTS = 5;
|
|
35
|
+
/** messageStates Map 条目的最大 TTL(毫秒),防止内存泄漏 */
|
|
36
|
+
export declare const MESSAGE_STATE_TTL_MS: number;
|
|
37
|
+
/** messageStates Map 清理间隔(毫秒) */
|
|
38
|
+
export declare const MESSAGE_STATE_CLEANUP_INTERVAL_MS = 60000;
|
|
39
|
+
/** messageStates Map 最大条目数 */
|
|
40
|
+
export declare const MESSAGE_STATE_MAX_SIZE = 500;
|
|
41
|
+
/** "思考中"流式消息占位内容 */
|
|
42
|
+
export declare const THINKING_MESSAGE = "<think></think>";
|
|
43
|
+
/** 仅包含图片时的消息占位符 */
|
|
44
|
+
export declare const MEDIA_IMAGE_PLACEHOLDER = "<media:image>";
|
|
45
|
+
/** 仅包含文件时的消息占位符 */
|
|
46
|
+
export declare const MEDIA_DOCUMENT_PLACEHOLDER = "<media:document>";
|
|
47
|
+
/** monitor 层中间帧 deliver 节流:最小发送间隔(毫秒) */
|
|
48
|
+
export declare const MONITOR_DELIVER_THROTTLE_MS = 1000;
|
|
49
|
+
/** monitor 层中间帧 deliver 节流:最少新增字符数才触发 deliver */
|
|
50
|
+
export declare const MONITOR_DELIVER_MIN_DELTA = 30;
|
|
51
|
+
/** 默认媒体大小上限(MB) */
|
|
52
|
+
export declare const DEFAULT_MEDIA_MAX_MB = 5;
|
|
53
|
+
/** 文本分块大小上限 */
|
|
54
|
+
export declare const TEXT_CHUNK_LIMIT = 4000;
|
|
55
|
+
/** 图片大小上限(字节):10MB */
|
|
56
|
+
export declare const IMAGE_MAX_BYTES: number;
|
|
57
|
+
/** 视频大小上限(字节):10MB */
|
|
58
|
+
export declare const VIDEO_MAX_BYTES: number;
|
|
59
|
+
/** 语音大小上限(字节):2MB */
|
|
60
|
+
export declare const VOICE_MAX_BYTES: number;
|
|
61
|
+
/** 文件大小上限(字节):20MB */
|
|
62
|
+
export declare const FILE_MAX_BYTES: number;
|
|
63
|
+
/** 文件绝对上限(字节):超过此值无法发送,等于 FILE_MAX_BYTES */
|
|
64
|
+
export declare const ABSOLUTE_MAX_BYTES: number;
|
|
65
|
+
/** 上传分片大小(字节,Base64 编码前):512KB */
|
|
66
|
+
export declare const UPLOAD_CHUNK_SIZE: number;
|
|
67
|
+
/** 版本检查事件名称(SDK 事件监听用) */
|
|
68
|
+
export declare const EVENT_ENTER_CHECK_UPDATE = "event.enter_check_update";
|
|
69
|
+
/** 版本检查事件回复命令名称 */
|
|
70
|
+
export declare const CMD_ENTER_EVENT_REPLY = "ww_ai_robot_enter_event";
|
|
71
|
+
/** WSClient scene 参数:企微 AI 机器人场景 */
|
|
72
|
+
export declare const SCENE_WECOM_AIBOT = 1;
|
|
73
|
+
/** 合法的模板卡片 card_type 列表 */
|
|
74
|
+
export declare const VALID_CARD_TYPES: string[];
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 对话历史管理器
|
|
3
|
+
*
|
|
4
|
+
* 按 chatId 维护多轮对话的 messages 数组(内存缓存)
|
|
5
|
+
* - 支持配置最大保留轮数(maxRounds)
|
|
6
|
+
* - 带 TTL 自动过期(默认 2 小时)
|
|
7
|
+
* - 带容量上限防止内存泄漏
|
|
8
|
+
*
|
|
9
|
+
* 一轮对话 = 一条 user 消息 + 一条 assistant 消息
|
|
10
|
+
*/
|
|
11
|
+
/** 对话历史中的消息 */
|
|
12
|
+
export interface HistoryMessage {
|
|
13
|
+
role: "user" | "assistant";
|
|
14
|
+
content: string;
|
|
15
|
+
}
|
|
16
|
+
/** 对话管理器配置 */
|
|
17
|
+
export interface ConversationManagerOptions {
|
|
18
|
+
/** 每个对话最大保留轮数(默认 20 轮 = 40 条消息) */
|
|
19
|
+
maxRounds?: number;
|
|
20
|
+
/** 对话过期时间(毫秒,默认 7200000 即 2 小时) */
|
|
21
|
+
ttlMs?: number;
|
|
22
|
+
/** 最大缓存对话数(默认 500) */
|
|
23
|
+
maxConversations?: number;
|
|
24
|
+
}
|
|
25
|
+
export declare class ConversationManager {
|
|
26
|
+
private cache;
|
|
27
|
+
private readonly maxRounds;
|
|
28
|
+
private readonly ttlMs;
|
|
29
|
+
private readonly maxConversations;
|
|
30
|
+
constructor(options?: ConversationManagerOptions);
|
|
31
|
+
/**
|
|
32
|
+
* 获取指定对话的历史消息
|
|
33
|
+
*
|
|
34
|
+
* 返回按时间排列的 user/assistant 消息数组
|
|
35
|
+
* 如果对话已过期或不存在,返回空数组
|
|
36
|
+
*/
|
|
37
|
+
getHistory(chatId: string): HistoryMessage[];
|
|
38
|
+
/**
|
|
39
|
+
* 添加一条用户消息到对话历史
|
|
40
|
+
*/
|
|
41
|
+
addUserMessage(chatId: string, content: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* 添加一条 AI 回复消息到对话历史
|
|
44
|
+
*/
|
|
45
|
+
addAssistantMessage(chatId: string, content: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* 清除指定对话的历史
|
|
48
|
+
*/
|
|
49
|
+
clearHistory(chatId: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* 清除所有对话历史
|
|
52
|
+
*/
|
|
53
|
+
clearAll(): void;
|
|
54
|
+
/**
|
|
55
|
+
* 获取当前缓存的对话数量(用于调试/监控)
|
|
56
|
+
*/
|
|
57
|
+
get size(): number;
|
|
58
|
+
/**
|
|
59
|
+
* 确保 chatId 对应的条目存在
|
|
60
|
+
*/
|
|
61
|
+
private ensureEntry;
|
|
62
|
+
/**
|
|
63
|
+
* 裁剪消息数量,保留最近 maxRounds 轮
|
|
64
|
+
*
|
|
65
|
+
* 一轮 = user + assistant = 2 条消息
|
|
66
|
+
* 最多保留 maxRounds * 2 条消息
|
|
67
|
+
*/
|
|
68
|
+
private trimMessages;
|
|
69
|
+
/**
|
|
70
|
+
* 淘汰最旧的对话(LRU 策略)
|
|
71
|
+
*/
|
|
72
|
+
private evictOldest;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 获取全局对话管理器(懒初始化)
|
|
76
|
+
*/
|
|
77
|
+
export declare function getConversationManager(options?: ConversationManagerOptions): ConversationManager;
|
|
78
|
+
/**
|
|
79
|
+
* 重置全局对话管理器(用于测试或重新配置)
|
|
80
|
+
*/
|
|
81
|
+
export declare function resetConversationManager(options?: ConversationManagerOptions): ConversationManager;
|