@downcity/plugins 1.0.152 → 1.0.156
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/bin/chat/ChatPlugin.d.ts +2 -10
- package/bin/chat/ChatPlugin.d.ts.map +1 -1
- package/bin/chat/ChatPlugin.js +3 -13
- package/bin/chat/ChatPlugin.js.map +1 -1
- package/bin/chat/PROMPT.direct.d.ts +1 -1
- package/bin/chat/PROMPT.direct.d.ts.map +1 -1
- package/bin/chat/PROMPT.direct.js +1 -1
- package/bin/chat/PROMPT.direct.js.map +1 -1
- package/bin/chat/access/ChatAccessActions.d.ts +11 -0
- package/bin/chat/access/ChatAccessActions.d.ts.map +1 -0
- package/bin/chat/access/ChatAccessActions.js +137 -0
- package/bin/chat/access/ChatAccessActions.js.map +1 -0
- package/bin/chat/access/ChatAccessRuntime.d.ts +17 -0
- package/bin/chat/access/ChatAccessRuntime.d.ts.map +1 -0
- package/bin/chat/access/ChatAccessRuntime.js +31 -0
- package/bin/chat/access/ChatAccessRuntime.js.map +1 -0
- package/bin/chat/access/ChatAccessSchema.d.ts +16 -0
- package/bin/chat/access/ChatAccessSchema.d.ts.map +1 -0
- package/bin/chat/access/ChatAccessSchema.js +99 -0
- package/bin/chat/access/ChatAccessSchema.js.map +1 -0
- package/bin/chat/access/ChatAccessService.d.ts +44 -0
- package/bin/chat/access/ChatAccessService.d.ts.map +1 -0
- package/bin/chat/access/ChatAccessService.js +281 -0
- package/bin/chat/access/ChatAccessService.js.map +1 -0
- package/bin/chat/access/ChatAccessStore.d.ts +67 -0
- package/bin/chat/access/ChatAccessStore.d.ts.map +1 -0
- package/bin/chat/access/ChatAccessStore.js +367 -0
- package/bin/chat/access/ChatAccessStore.js.map +1 -0
- package/bin/chat/accounts/Crypto.d.ts +1 -1
- package/bin/chat/accounts/Crypto.js +1 -1
- package/bin/chat/accounts/Store.d.ts +1 -1
- package/bin/chat/accounts/Store.js +1 -1
- package/bin/chat/channels/BaseChatChannel.d.ts +18 -21
- package/bin/chat/channels/BaseChatChannel.d.ts.map +1 -1
- package/bin/chat/channels/BaseChatChannel.js +48 -58
- package/bin/chat/channels/BaseChatChannel.js.map +1 -1
- package/bin/chat/channels/BaseChatChannelQueue.d.ts +1 -1
- package/bin/chat/channels/BaseChatChannelQueue.d.ts.map +1 -1
- package/bin/chat/channels/BaseChatChannelQueue.js +2 -14
- package/bin/chat/channels/BaseChatChannelQueue.js.map +1 -1
- package/bin/chat/channels/Configuration.d.ts +2 -2
- package/bin/chat/channels/Configuration.d.ts.map +1 -1
- package/bin/chat/channels/Configuration.js +3 -3
- package/bin/chat/channels/Configuration.js.map +1 -1
- package/bin/chat/channels/feishu/Configuration.js +4 -4
- package/bin/chat/channels/feishu/Configuration.js.map +1 -1
- package/bin/chat/channels/feishu/Feishu.d.ts +2 -0
- package/bin/chat/channels/feishu/Feishu.d.ts.map +1 -1
- package/bin/chat/channels/feishu/Feishu.js +8 -7
- package/bin/chat/channels/feishu/Feishu.js.map +1 -1
- package/bin/chat/channels/feishu/FeishuMessageHandler.d.ts +9 -17
- package/bin/chat/channels/feishu/FeishuMessageHandler.d.ts.map +1 -1
- package/bin/chat/channels/feishu/FeishuMessageHandler.js +6 -17
- package/bin/chat/channels/feishu/FeishuMessageHandler.js.map +1 -1
- package/bin/chat/channels/qq/Configuration.js +4 -4
- package/bin/chat/channels/qq/Configuration.js.map +1 -1
- package/bin/chat/channels/qq/QQ.d.ts +2 -0
- package/bin/chat/channels/qq/QQ.d.ts.map +1 -1
- package/bin/chat/channels/qq/QQ.js +8 -7
- package/bin/chat/channels/qq/QQ.js.map +1 -1
- package/bin/chat/channels/qq/QQMessageHandler.d.ts +9 -17
- package/bin/chat/channels/qq/QQMessageHandler.d.ts.map +1 -1
- package/bin/chat/channels/qq/QQMessageHandler.js +7 -25
- package/bin/chat/channels/qq/QQMessageHandler.js.map +1 -1
- package/bin/chat/channels/telegram/Bot.d.ts +2 -0
- package/bin/chat/channels/telegram/Bot.d.ts.map +1 -1
- package/bin/chat/channels/telegram/Bot.js +8 -7
- package/bin/chat/channels/telegram/Bot.js.map +1 -1
- package/bin/chat/channels/telegram/Configuration.js +4 -4
- package/bin/chat/channels/telegram/Configuration.js.map +1 -1
- package/bin/chat/channels/telegram/TelegramMessageHandler.d.ts +9 -17
- package/bin/chat/channels/telegram/TelegramMessageHandler.d.ts.map +1 -1
- package/bin/chat/channels/telegram/TelegramMessageHandler.js +5 -16
- package/bin/chat/channels/telegram/TelegramMessageHandler.js.map +1 -1
- package/bin/chat/runtime/ChatChannelActions.d.ts +3 -2
- package/bin/chat/runtime/ChatChannelActions.d.ts.map +1 -1
- package/bin/chat/runtime/ChatChannelActions.js +57 -0
- package/bin/chat/runtime/ChatChannelActions.js.map +1 -1
- package/bin/chat/runtime/ChatChannelConfig.d.ts +2 -2
- package/bin/chat/runtime/ChatChannelConfig.js +3 -3
- package/bin/chat/runtime/ChatChannelConfig.js.map +1 -1
- package/bin/chat/runtime/ChatChannelCore.d.ts +2 -2
- package/bin/chat/runtime/ChatChannelCore.js +1 -1
- package/bin/chat/runtime/ChatChannelLifecycle.d.ts +1 -1
- package/bin/chat/runtime/ChatChannelLifecycle.js +1 -1
- package/bin/chat/runtime/PluginPoints.d.ts +0 -24
- package/bin/chat/runtime/PluginPoints.d.ts.map +1 -1
- package/bin/chat/runtime/PluginPoints.js +0 -24
- package/bin/chat/runtime/PluginPoints.js.map +1 -1
- package/bin/chat/runtime/QueuedUserMessage.d.ts.map +1 -1
- package/bin/chat/runtime/QueuedUserMessage.js +0 -2
- package/bin/chat/runtime/QueuedUserMessage.js.map +1 -1
- package/bin/chat/types/ChannelConfiguration.d.ts +4 -4
- package/bin/chat/types/ChannelConfiguration.d.ts.map +1 -1
- package/bin/chat/types/ChatAccess.d.ts +300 -0
- package/bin/chat/types/ChatAccess.d.ts.map +1 -0
- package/bin/chat/types/ChatAccess.js +22 -0
- package/bin/chat/types/ChatAccess.js.map +1 -0
- package/bin/chat/types/ChatPromptContext.d.ts +0 -15
- package/bin/chat/types/ChatPromptContext.d.ts.map +1 -1
- package/bin/index.d.ts +4 -4
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +3 -3
- package/bin/index.js.map +1 -1
- package/bin/skill/Config.d.ts +1 -1
- package/bin/skill/Config.js +1 -1
- package/bin/skill/runtime/Paths.d.ts +1 -1
- package/bin/skill/runtime/Paths.js +1 -1
- package/package.json +6 -4
- package/scripts/chat-access.test.mjs +90 -0
- package/scripts/chat-channel-config.test.mjs +82 -0
- package/src/chat/ChatPlugin.ts +4 -24
- package/src/chat/PROMPT.direct.ts +1 -1
- package/src/chat/PROMPT.direct.ts.txt +1 -1
- package/src/chat/access/ChatAccessActions.ts +159 -0
- package/src/chat/access/ChatAccessRuntime.ts +41 -0
- package/src/chat/access/ChatAccessSchema.ts +104 -0
- package/src/chat/access/ChatAccessService.ts +311 -0
- package/src/chat/access/ChatAccessStore.ts +462 -0
- package/src/chat/accounts/Crypto.ts +1 -1
- package/src/chat/accounts/Store.ts +1 -1
- package/src/chat/channels/BaseChatChannel.ts +59 -80
- package/src/chat/channels/BaseChatChannelQueue.ts +2 -14
- package/src/chat/channels/Configuration.ts +3 -3
- package/src/chat/channels/feishu/Configuration.ts +4 -4
- package/src/chat/channels/feishu/Feishu.ts +11 -9
- package/src/chat/channels/feishu/FeishuMessageHandler.ts +16 -40
- package/src/chat/channels/qq/Configuration.ts +4 -4
- package/src/chat/channels/qq/QQ.ts +11 -9
- package/src/chat/channels/qq/QQMessageHandler.ts +17 -49
- package/src/chat/channels/telegram/Bot.ts +11 -9
- package/src/chat/channels/telegram/Configuration.ts +4 -4
- package/src/chat/channels/telegram/TelegramMessageHandler.ts +15 -39
- package/src/chat/runtime/ChatChannelActions.ts +72 -1
- package/src/chat/runtime/ChatChannelConfig.ts +3 -3
- package/src/chat/runtime/ChatChannelCore.ts +1 -1
- package/src/chat/runtime/ChatChannelLifecycle.ts +1 -1
- package/src/chat/runtime/PluginPoints.ts +0 -24
- package/src/chat/runtime/QueuedUserMessage.ts +0 -2
- package/src/chat/types/ChannelConfiguration.ts +4 -4
- package/src/chat/types/ChatAccess.ts +335 -0
- package/src/chat/types/ChatPromptContext.ts +0 -17
- package/src/index.ts +27 -31
- package/src/skill/Config.ts +1 -1
- package/src/skill/runtime/Paths.ts +1 -1
- package/bin/auth/runtime/AuthorizationConfig.d.ts +0 -41
- package/bin/auth/runtime/AuthorizationConfig.d.ts.map +0 -1
- package/bin/auth/runtime/AuthorizationConfig.js +0 -185
- package/bin/auth/runtime/AuthorizationConfig.js.map +0 -1
- package/bin/auth/runtime/AuthorizationPolicy.d.ts +0 -28
- package/bin/auth/runtime/AuthorizationPolicy.d.ts.map +0 -1
- package/bin/auth/runtime/AuthorizationPolicy.js +0 -124
- package/bin/auth/runtime/AuthorizationPolicy.js.map +0 -1
- package/bin/auth/runtime/AuthorizationStore.d.ts +0 -29
- package/bin/auth/runtime/AuthorizationStore.d.ts.map +0 -1
- package/bin/auth/runtime/AuthorizationStore.js +0 -179
- package/bin/auth/runtime/AuthorizationStore.js.map +0 -1
- package/bin/auth/types/AuthPlugin.d.ts +0 -403
- package/bin/auth/types/AuthPlugin.d.ts.map +0 -1
- package/bin/auth/types/AuthPlugin.js +0 -111
- package/bin/auth/types/AuthPlugin.js.map +0 -1
- package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts +0 -22
- package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts.map +0 -1
- package/bin/chat/runtime/ChatAuthorizationRuntime.js +0 -230
- package/bin/chat/runtime/ChatAuthorizationRuntime.js.map +0 -1
- package/bin/chat/runtime/PluginDispatch.d.ts +0 -43
- package/bin/chat/runtime/PluginDispatch.d.ts.map +0 -1
- package/bin/chat/runtime/PluginDispatch.js +0 -57
- package/bin/chat/runtime/PluginDispatch.js.map +0 -1
- package/src/auth/runtime/AuthorizationConfig.ts +0 -247
- package/src/auth/runtime/AuthorizationPolicy.ts +0 -167
- package/src/auth/runtime/AuthorizationStore.ts +0 -220
- package/src/auth/types/AuthPlugin.ts +0 -540
- package/src/chat/runtime/ChatAuthorizationRuntime.ts +0 -270
- package/src/chat/runtime/PluginDispatch.ts +0 -89
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
5
|
* - audit / exec 入队都需要走同一套 prepare + emit 流程。
|
|
6
|
-
* - 这些逻辑抽离后,`BaseChatChannel`
|
|
6
|
+
* - 这些逻辑抽离后,`BaseChatChannel` 只负责渠道层输入整理与 Chat Access 判断。
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { resolveChatQueueStore } from "@/chat/runtime/ChatQueue.js";
|
|
10
10
|
import { buildQueuedUserMessageWithInfo } from "@/chat/runtime/QueuedUserMessage.js";
|
|
11
11
|
import { appendExecIngress } from "@/chat/runtime/ChatIngressStore.js";
|
|
12
|
-
import { resolveIncomingChatUserRole } from "@/chat/runtime/PluginDispatch.js";
|
|
13
12
|
import {
|
|
14
13
|
emitChatEnqueueEffect,
|
|
15
14
|
prepareChatEnqueue,
|
|
@@ -190,18 +189,9 @@ export async function enqueueExecChannelMessage(
|
|
|
190
189
|
params: EnqueueExecChannelMessageParams,
|
|
191
190
|
): Promise<{ chatKey: string; position: number }> {
|
|
192
191
|
const msg = params.message;
|
|
193
|
-
const userRole = await resolveIncomingChatUserRole({
|
|
194
|
-
context: params.context,
|
|
195
|
-
channel: params.channel,
|
|
196
|
-
userId: msg.userId,
|
|
197
|
-
});
|
|
198
192
|
const inboundExtra =
|
|
199
193
|
msg.extra && typeof msg.extra === "object" ? stripUndefinedMeta(msg.extra) : {};
|
|
200
|
-
const mergedExtra: JsonObject = {
|
|
201
|
-
...inboundExtra,
|
|
202
|
-
roleId: userRole?.roleId || "unknown",
|
|
203
|
-
permissions: userRole?.permissions || [],
|
|
204
|
-
};
|
|
194
|
+
const mergedExtra: JsonObject = { ...inboundExtra };
|
|
205
195
|
|
|
206
196
|
const chatKey = await resolveOrCreateChannelSessionId({
|
|
207
197
|
context: params.context,
|
|
@@ -218,8 +208,6 @@ export async function enqueueExecChannelMessage(
|
|
|
218
208
|
messageId: msg.messageId,
|
|
219
209
|
userId: msg.userId,
|
|
220
210
|
username: msg.username,
|
|
221
|
-
roleId: userRole?.roleId,
|
|
222
|
-
permissions: userRole?.permissions,
|
|
223
211
|
receivedAt: msg.receivedAt,
|
|
224
212
|
userTimezone: msg.userTimezone,
|
|
225
213
|
text: msg.text,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
5
|
* - 每个 channel 继承该基类,集中声明自己的配置字段。
|
|
6
|
-
* - 统一提供“可写
|
|
6
|
+
* - 统一提供“可写 Agent 配置字段”提取逻辑,避免在 service 中重复硬编码。
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type {
|
|
@@ -29,7 +29,7 @@ export abstract class ChatChannelConfiguration {
|
|
|
29
29
|
/**
|
|
30
30
|
* 返回可通过 `chat.configure` 更新的运行态字段定义。
|
|
31
31
|
*/
|
|
32
|
-
|
|
33
|
-
return this.describe().fields.
|
|
32
|
+
get_writable_agent_config_fields(): ChatChannelConfigurationField[] {
|
|
33
|
+
return this.describe().fields.agent_config.filter((field) => field.writable);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -28,14 +28,14 @@ export class FeishuChannelConfiguration extends ChatChannelConfiguration {
|
|
|
28
28
|
canConfigure: true,
|
|
29
29
|
},
|
|
30
30
|
fields: {
|
|
31
|
-
|
|
31
|
+
agent_config: [
|
|
32
32
|
{
|
|
33
33
|
key: "enabled",
|
|
34
34
|
label: "Enabled",
|
|
35
35
|
description:
|
|
36
36
|
"Whether feishu channel should be started by runtime.",
|
|
37
37
|
type: "boolean",
|
|
38
|
-
source: "
|
|
38
|
+
source: "agent_config",
|
|
39
39
|
required: false,
|
|
40
40
|
nullable: false,
|
|
41
41
|
writable: true,
|
|
@@ -47,9 +47,9 @@ export class FeishuChannelConfiguration extends ChatChannelConfiguration {
|
|
|
47
47
|
key: "channelAccountId",
|
|
48
48
|
label: "Chat Account ID",
|
|
49
49
|
description:
|
|
50
|
-
"Bind this chat platform to a
|
|
50
|
+
"Bind this chat platform to a channel_accounts row in the global downcity.db.",
|
|
51
51
|
type: "string",
|
|
52
|
-
source: "
|
|
52
|
+
source: "agent_config",
|
|
53
53
|
required: false,
|
|
54
54
|
nullable: true,
|
|
55
55
|
writable: true,
|
|
@@ -81,6 +81,11 @@ export class FeishuBot extends BaseChatChannel {
|
|
|
81
81
|
return this.buildChatKey(params.chatId);
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/** SDK 直连时使用飞书 App ID 作为 issuer。 */
|
|
85
|
+
protected getAccessIssuerFallback(): string {
|
|
86
|
+
return String(this.appId || "").trim();
|
|
87
|
+
}
|
|
88
|
+
|
|
84
89
|
protected async sendTextToPlatform(
|
|
85
90
|
params: ChannelSendTextParams,
|
|
86
91
|
): Promise<void> {
|
|
@@ -209,16 +214,13 @@ export class FeishuBot extends BaseChatChannel {
|
|
|
209
214
|
rememberChat: (threadId, value) => {
|
|
210
215
|
this.knownChats.set(threadId, value);
|
|
211
216
|
},
|
|
212
|
-
|
|
213
|
-
await this.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
await this.evaluateIncomingAuthorization(params),
|
|
217
|
-
sendAuthorizationText: async (params) => {
|
|
218
|
-
await this.sendAuthorizationText(params);
|
|
217
|
+
evaluateIncomingAccess: async (params) =>
|
|
218
|
+
await this.evaluateIncomingAccess(params),
|
|
219
|
+
sendAccessText: async (params) => {
|
|
220
|
+
await this.sendAccessText(params);
|
|
219
221
|
},
|
|
220
|
-
|
|
221
|
-
this.
|
|
222
|
+
buildAccessBlockedText: (params) =>
|
|
223
|
+
this.buildAccessBlockedText(params),
|
|
222
224
|
runInChat: async (chatKey, fn) => {
|
|
223
225
|
await this.runInChat(chatKey, fn);
|
|
224
226
|
},
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Feishu 入站消息处理器。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* -
|
|
5
|
+
* - 负责单条飞书消息的去重、解析、Chat Access、附件保存与执行入队。
|
|
6
6
|
* - 不持有 `FeishuBot` 实例;所有副作用通过显式依赖注入。
|
|
7
7
|
* - 解析失败/执行失败通过渠道门面提供的发送函数回写错误消息。
|
|
8
8
|
*/
|
|
@@ -11,8 +11,8 @@ import path from "path";
|
|
|
11
11
|
import type { Logger } from "@downcity/agent";
|
|
12
12
|
import type { AgentContext } from "@downcity/agent";
|
|
13
13
|
import type {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
IncomingChatAccessParams,
|
|
15
|
+
IncomingChatAccessResult,
|
|
16
16
|
} from "@/chat/channels/BaseChatChannel.js";
|
|
17
17
|
import type { JsonObject } from "@downcity/agent";
|
|
18
18
|
import type { InboundReplyContext } from "@/chat/types/ReplyContext.js";
|
|
@@ -109,34 +109,22 @@ export interface FeishuMessageHandlerOptions {
|
|
|
109
109
|
threadId: string,
|
|
110
110
|
value: { chatId: string; chatType: string; chatTitle?: string },
|
|
111
111
|
): void;
|
|
112
|
+
/** 入站 Chat Access 判定。 */
|
|
113
|
+
evaluateIncomingAccess(
|
|
114
|
+
params: IncomingChatAccessParams,
|
|
115
|
+
): Promise<IncomingChatAccessResult>;
|
|
112
116
|
/**
|
|
113
|
-
*
|
|
117
|
+
* 发送 Chat Access 失败提示。
|
|
114
118
|
*/
|
|
115
|
-
|
|
116
|
-
params: IncomingAuthorizationParams,
|
|
117
|
-
): Promise<void>;
|
|
118
|
-
/**
|
|
119
|
-
* 入站授权判定。
|
|
120
|
-
*/
|
|
121
|
-
evaluateIncomingAuthorization(
|
|
122
|
-
params: IncomingAuthorizationParams,
|
|
123
|
-
): Promise<IncomingAuthorizationResult>;
|
|
124
|
-
/**
|
|
125
|
-
* 发送授权失败提示。
|
|
126
|
-
*/
|
|
127
|
-
sendAuthorizationText(params: {
|
|
119
|
+
sendAccessText(params: {
|
|
128
120
|
chatId: string;
|
|
129
121
|
text: string;
|
|
130
122
|
chatType?: string;
|
|
131
123
|
}): Promise<void>;
|
|
132
124
|
/**
|
|
133
|
-
*
|
|
125
|
+
* 构建 Chat Access 失败提示文案。
|
|
134
126
|
*/
|
|
135
|
-
|
|
136
|
-
userId?: string;
|
|
137
|
-
chatId?: string;
|
|
138
|
-
chatType?: string;
|
|
139
|
-
}): string;
|
|
127
|
+
buildAccessBlockedText(params: { result: IncomingChatAccessResult }): string;
|
|
140
128
|
/**
|
|
141
129
|
* 按 chatKey 串行执行。
|
|
142
130
|
*/
|
|
@@ -337,7 +325,7 @@ async function parseIncomingMessage(params: {
|
|
|
337
325
|
}
|
|
338
326
|
|
|
339
327
|
/**
|
|
340
|
-
*
|
|
328
|
+
* Chat Access 通过后处理消息内容。
|
|
341
329
|
*/
|
|
342
330
|
async function handleAuthorizedMessage(params: {
|
|
343
331
|
options: FeishuMessageHandlerOptions;
|
|
@@ -374,31 +362,19 @@ async function handleAuthorizedMessage(params: {
|
|
|
374
362
|
const resolvedChatTitle = await options.resolveChatTitle(chatId);
|
|
375
363
|
const chatTitle = resolvedChatTitle || (chatType === "p2p" ? actorName : undefined);
|
|
376
364
|
|
|
377
|
-
await options.
|
|
378
|
-
chatId,
|
|
379
|
-
chatType,
|
|
380
|
-
chatTitle,
|
|
381
|
-
userId: actorId,
|
|
382
|
-
username: actorName,
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
const authResult = await options.evaluateIncomingAuthorization({
|
|
365
|
+
const access_result = await options.evaluateIncomingAccess({
|
|
386
366
|
chatId,
|
|
387
367
|
chatType,
|
|
388
368
|
chatTitle,
|
|
389
369
|
userId: actorId,
|
|
390
370
|
username: actorName,
|
|
391
371
|
});
|
|
392
|
-
if (
|
|
372
|
+
if (!access_result.allowed) {
|
|
393
373
|
if (chatType === "p2p") {
|
|
394
|
-
await options.
|
|
374
|
+
await options.sendAccessText({
|
|
395
375
|
chatId,
|
|
396
376
|
chatType,
|
|
397
|
-
text: options.
|
|
398
|
-
chatId,
|
|
399
|
-
chatType,
|
|
400
|
-
userId: actorId,
|
|
401
|
-
}),
|
|
377
|
+
text: options.buildAccessBlockedText({ result: access_result }),
|
|
402
378
|
});
|
|
403
379
|
}
|
|
404
380
|
return true;
|
|
@@ -28,13 +28,13 @@ export class QqChannelConfiguration extends ChatChannelConfiguration {
|
|
|
28
28
|
canConfigure: true,
|
|
29
29
|
},
|
|
30
30
|
fields: {
|
|
31
|
-
|
|
31
|
+
agent_config: [
|
|
32
32
|
{
|
|
33
33
|
key: "enabled",
|
|
34
34
|
label: "Enabled",
|
|
35
35
|
description: "Whether qq channel should be started by runtime.",
|
|
36
36
|
type: "boolean",
|
|
37
|
-
source: "
|
|
37
|
+
source: "agent_config",
|
|
38
38
|
required: false,
|
|
39
39
|
nullable: false,
|
|
40
40
|
writable: true,
|
|
@@ -46,9 +46,9 @@ export class QqChannelConfiguration extends ChatChannelConfiguration {
|
|
|
46
46
|
key: "channelAccountId",
|
|
47
47
|
label: "Chat Account ID",
|
|
48
48
|
description:
|
|
49
|
-
"Bind this chat platform to a
|
|
49
|
+
"Bind this chat platform to a channel_accounts row in the global downcity.db.",
|
|
50
50
|
type: "string",
|
|
51
|
-
source: "
|
|
51
|
+
source: "agent_config",
|
|
52
52
|
required: false,
|
|
53
53
|
nullable: true,
|
|
54
54
|
writable: true,
|
|
@@ -82,6 +82,11 @@ export class QQBot extends BaseChatChannel {
|
|
|
82
82
|
return `qq-${chatType}-${params.chatId}`;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
/** SDK 直连时使用 QQ App ID 作为 issuer。 */
|
|
86
|
+
protected getAccessIssuerFallback(): string {
|
|
87
|
+
return String(this.appId || "").trim();
|
|
88
|
+
}
|
|
89
|
+
|
|
85
90
|
protected async sendTextToPlatform(
|
|
86
91
|
params: ChannelSendTextParams,
|
|
87
92
|
): Promise<void> {
|
|
@@ -266,16 +271,13 @@ export class QQBot extends BaseChatChannel {
|
|
|
266
271
|
logger: this.logger,
|
|
267
272
|
getBotUserId: () => this.botUserId,
|
|
268
273
|
getChatKey: (params) => this.getChatKey(params),
|
|
269
|
-
|
|
270
|
-
await this.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
await this.evaluateIncomingAuthorization(params),
|
|
274
|
-
sendAuthorizationText: async (params) => {
|
|
275
|
-
await this.sendAuthorizationText(params);
|
|
274
|
+
evaluateIncomingAccess: async (params) =>
|
|
275
|
+
await this.evaluateIncomingAccess(params),
|
|
276
|
+
sendAccessText: async (params) => {
|
|
277
|
+
await this.sendAccessText(params);
|
|
276
278
|
},
|
|
277
|
-
|
|
278
|
-
this.
|
|
279
|
+
buildAccessBlockedText: (params) =>
|
|
280
|
+
this.buildAccessBlockedText(params),
|
|
279
281
|
shouldSkipDuplicatedInboundMessage: async (eventType, messageId) =>
|
|
280
282
|
await this.shouldSkipDuplicatedInboundMessage(eventType, messageId),
|
|
281
283
|
enqueueAuditMessage: async (params) => {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* QQ 入站消息处理器。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* - 负责 group / c2c / channel
|
|
5
|
+
* - 负责 group / c2c / channel 三类入站消息的 Chat Access、去重、审计与执行入队。
|
|
6
6
|
* - 不直接持有 `QQBot` 实例;所有副作用通过显式函数注入。
|
|
7
7
|
* - `QQBot` 因此只保留渠道生命周期、dispatch 分流、发送与命令处理。
|
|
8
8
|
*/
|
|
@@ -11,8 +11,8 @@ import type { Logger } from "@downcity/agent";
|
|
|
11
11
|
import type { AgentContext } from "@downcity/agent";
|
|
12
12
|
import type {
|
|
13
13
|
ChannelChatKeyParams,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
IncomingChatAccessParams,
|
|
15
|
+
IncomingChatAccessResult,
|
|
16
16
|
} from "@/chat/channels/BaseChatChannel.js";
|
|
17
17
|
import type { ChannelUserMessageMeta } from "@/chat/channels/BaseChatChannelSupport.js";
|
|
18
18
|
import {
|
|
@@ -69,34 +69,22 @@ export interface QQMessageHandlerOptions {
|
|
|
69
69
|
* 计算 channel chatKey。
|
|
70
70
|
*/
|
|
71
71
|
getChatKey(params: ChannelChatKeyParams): string;
|
|
72
|
+
/** 入站 Chat Access 判定。 */
|
|
73
|
+
evaluateIncomingAccess(
|
|
74
|
+
params: IncomingChatAccessParams,
|
|
75
|
+
): Promise<IncomingChatAccessResult>;
|
|
72
76
|
/**
|
|
73
|
-
*
|
|
77
|
+
* 发送 Chat Access 失败提示。
|
|
74
78
|
*/
|
|
75
|
-
|
|
76
|
-
params: IncomingAuthorizationParams,
|
|
77
|
-
): Promise<void>;
|
|
78
|
-
/**
|
|
79
|
-
* 入站授权判定。
|
|
80
|
-
*/
|
|
81
|
-
evaluateIncomingAuthorization(
|
|
82
|
-
params: IncomingAuthorizationParams,
|
|
83
|
-
): Promise<IncomingAuthorizationResult>;
|
|
84
|
-
/**
|
|
85
|
-
* 发送授权失败提示。
|
|
86
|
-
*/
|
|
87
|
-
sendAuthorizationText(params: {
|
|
79
|
+
sendAccessText(params: {
|
|
88
80
|
chatId: string;
|
|
89
81
|
text: string;
|
|
90
82
|
chatType?: string;
|
|
91
83
|
}): Promise<void>;
|
|
92
84
|
/**
|
|
93
|
-
*
|
|
85
|
+
* 构建 Chat Access 失败提示文案。
|
|
94
86
|
*/
|
|
95
|
-
|
|
96
|
-
userId?: string;
|
|
97
|
-
chatId?: string;
|
|
98
|
-
chatType?: string;
|
|
99
|
-
}): string;
|
|
87
|
+
buildAccessBlockedText(params: { result: IncomingChatAccessResult }): string;
|
|
100
88
|
/**
|
|
101
89
|
* 入站去重判断。
|
|
102
90
|
*/
|
|
@@ -234,22 +222,14 @@ export async function handleQqChannelMessage(
|
|
|
234
222
|
actorName: actor.username,
|
|
235
223
|
});
|
|
236
224
|
|
|
237
|
-
await options.
|
|
238
|
-
chatId: channelId,
|
|
239
|
-
chatType,
|
|
240
|
-
chatTitle,
|
|
241
|
-
userId: actor.userId,
|
|
242
|
-
username: actor.username,
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
const authResult = await options.evaluateIncomingAuthorization({
|
|
225
|
+
const access_result = await options.evaluateIncomingAccess({
|
|
246
226
|
chatId: channelId,
|
|
247
227
|
chatType,
|
|
248
228
|
chatTitle,
|
|
249
229
|
userId: actor.userId,
|
|
250
230
|
username: actor.username,
|
|
251
231
|
});
|
|
252
|
-
if (
|
|
232
|
+
if (!access_result.allowed) return;
|
|
253
233
|
|
|
254
234
|
const botUserId = options.getBotUserId();
|
|
255
235
|
if (actor.userId && botUserId && actor.userId === botUserId) {
|
|
@@ -347,31 +327,19 @@ async function handleQqInboundMessage(
|
|
|
347
327
|
? stripQqBotMention(rawContent, botUserId)
|
|
348
328
|
: extractQqTextContent(rawContent);
|
|
349
329
|
|
|
350
|
-
await options.
|
|
351
|
-
chatId,
|
|
352
|
-
chatType,
|
|
353
|
-
chatTitle,
|
|
354
|
-
userId: actor.userId,
|
|
355
|
-
username: actor.username,
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
const authResult = await options.evaluateIncomingAuthorization({
|
|
330
|
+
const access_result = await options.evaluateIncomingAccess({
|
|
359
331
|
chatId,
|
|
360
332
|
chatType,
|
|
361
333
|
chatTitle,
|
|
362
334
|
userId: actor.userId,
|
|
363
335
|
username: actor.username,
|
|
364
336
|
});
|
|
365
|
-
if (
|
|
337
|
+
if (!access_result.allowed) {
|
|
366
338
|
if (!isGroup) {
|
|
367
|
-
await options.
|
|
339
|
+
await options.sendAccessText({
|
|
368
340
|
chatId,
|
|
369
341
|
chatType,
|
|
370
|
-
text: options.
|
|
371
|
-
chatId,
|
|
372
|
-
chatType,
|
|
373
|
-
userId: actor.userId,
|
|
374
|
-
}),
|
|
342
|
+
text: options.buildAccessBlockedText({ result: access_result }),
|
|
375
343
|
});
|
|
376
344
|
}
|
|
377
345
|
return;
|
|
@@ -72,6 +72,11 @@ export class TelegramBot extends BaseChatChannel {
|
|
|
72
72
|
return buildTelegramChatKey(params.chatId, params.messageThreadId);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/** SDK 直连时使用 Telegram Bot ID 作为 issuer。 */
|
|
76
|
+
protected getAccessIssuerFallback(): string {
|
|
77
|
+
return String(this.platform.getBotId() || "").trim();
|
|
78
|
+
}
|
|
79
|
+
|
|
75
80
|
protected async sendTextToPlatform(
|
|
76
81
|
params: ChannelSendTextParams,
|
|
77
82
|
): Promise<void> {
|
|
@@ -207,16 +212,13 @@ export class TelegramBot extends BaseChatChannel {
|
|
|
207
212
|
logger: this.logger,
|
|
208
213
|
inboundAckEmoji: TelegramBot.INBOUND_ACK_EMOJI,
|
|
209
214
|
platform: this.platform,
|
|
210
|
-
|
|
211
|
-
await this.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
await this.evaluateIncomingAuthorization(params),
|
|
215
|
-
sendAuthorizationText: async (params) => {
|
|
216
|
-
await this.sendAuthorizationText(params);
|
|
215
|
+
evaluateIncomingAccess: async (params) =>
|
|
216
|
+
await this.evaluateIncomingAccess(params),
|
|
217
|
+
sendAccessText: async (params) => {
|
|
218
|
+
await this.sendAccessText(params);
|
|
217
219
|
},
|
|
218
|
-
|
|
219
|
-
this.
|
|
220
|
+
buildAccessBlockedText: (params) =>
|
|
221
|
+
this.buildAccessBlockedText(params),
|
|
220
222
|
enqueueAuditMessage: async (params) => {
|
|
221
223
|
await this.enqueueAuditMessage(params);
|
|
222
224
|
},
|
|
@@ -28,14 +28,14 @@ export class TelegramChannelConfiguration extends ChatChannelConfiguration {
|
|
|
28
28
|
canConfigure: true,
|
|
29
29
|
},
|
|
30
30
|
fields: {
|
|
31
|
-
|
|
31
|
+
agent_config: [
|
|
32
32
|
{
|
|
33
33
|
key: "enabled",
|
|
34
34
|
label: "Enabled",
|
|
35
35
|
description:
|
|
36
36
|
"Whether telegram channel should be started by runtime.",
|
|
37
37
|
type: "boolean",
|
|
38
|
-
source: "
|
|
38
|
+
source: "agent_config",
|
|
39
39
|
required: false,
|
|
40
40
|
nullable: false,
|
|
41
41
|
writable: true,
|
|
@@ -47,9 +47,9 @@ export class TelegramChannelConfiguration extends ChatChannelConfiguration {
|
|
|
47
47
|
key: "channelAccountId",
|
|
48
48
|
label: "Chat Account ID",
|
|
49
49
|
description:
|
|
50
|
-
"Bind this chat platform to a
|
|
50
|
+
"Bind this chat platform to a channel_accounts row in the global downcity.db.",
|
|
51
51
|
type: "string",
|
|
52
|
-
source: "
|
|
52
|
+
source: "agent_config",
|
|
53
53
|
required: false,
|
|
54
54
|
nullable: true,
|
|
55
55
|
writable: true,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Telegram 普通消息处理器。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* - 负责单条 message
|
|
5
|
+
* - 负责单条 message 的 Chat Access、审计、附件保存、入队指令构造。
|
|
6
6
|
* - 不持有 channel 实例;所有副作用通过显式依赖注入。
|
|
7
7
|
* - `TelegramBot` 只保留平台生命周期与命令/callback 分发入口。
|
|
8
8
|
*/
|
|
@@ -12,8 +12,8 @@ import type { Logger } from "@downcity/agent";
|
|
|
12
12
|
import type { AgentContext } from "@downcity/agent";
|
|
13
13
|
import type { JsonObject } from "@downcity/agent";
|
|
14
14
|
import type {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
IncomingChatAccessParams,
|
|
16
|
+
IncomingChatAccessResult,
|
|
17
17
|
} from "@/chat/channels/BaseChatChannel.js";
|
|
18
18
|
import type { ChannelUserMessageMeta } from "@/chat/channels/BaseChatChannelSupport.js";
|
|
19
19
|
import {
|
|
@@ -127,35 +127,23 @@ export interface TelegramMessageHandlerOptions {
|
|
|
127
127
|
* Telegram 平台能力。
|
|
128
128
|
*/
|
|
129
129
|
platform: TelegramMessagePlatform;
|
|
130
|
+
/** 入站 Chat Access 判定。 */
|
|
131
|
+
evaluateIncomingAccess(
|
|
132
|
+
params: IncomingChatAccessParams,
|
|
133
|
+
): Promise<IncomingChatAccessResult>;
|
|
130
134
|
/**
|
|
131
|
-
*
|
|
135
|
+
* 发送 Chat Access 失败提示。
|
|
132
136
|
*/
|
|
133
|
-
|
|
134
|
-
params: IncomingAuthorizationParams,
|
|
135
|
-
): Promise<void>;
|
|
136
|
-
/**
|
|
137
|
-
* 入站授权判定。
|
|
138
|
-
*/
|
|
139
|
-
evaluateIncomingAuthorization(
|
|
140
|
-
params: IncomingAuthorizationParams,
|
|
141
|
-
): Promise<IncomingAuthorizationResult>;
|
|
142
|
-
/**
|
|
143
|
-
* 发送授权失败提示。
|
|
144
|
-
*/
|
|
145
|
-
sendAuthorizationText(params: {
|
|
137
|
+
sendAccessText(params: {
|
|
146
138
|
chatId: string;
|
|
147
139
|
text: string;
|
|
148
140
|
chatType?: string;
|
|
149
141
|
messageThreadId?: number;
|
|
150
142
|
}): Promise<void>;
|
|
151
143
|
/**
|
|
152
|
-
*
|
|
144
|
+
* 构建 Chat Access 失败提示文案。
|
|
153
145
|
*/
|
|
154
|
-
|
|
155
|
-
userId?: string;
|
|
156
|
-
chatId?: string;
|
|
157
|
-
chatType?: string;
|
|
158
|
-
}): string;
|
|
146
|
+
buildAccessBlockedText(params: { result: IncomingChatAccessResult }): string;
|
|
159
147
|
/**
|
|
160
148
|
* Audit 队列写入。
|
|
161
149
|
*/
|
|
@@ -223,32 +211,20 @@ export async function handleTelegramMessage(
|
|
|
223
211
|
return;
|
|
224
212
|
}
|
|
225
213
|
|
|
226
|
-
await options.
|
|
227
|
-
chatId,
|
|
228
|
-
chatType: message.chat.type,
|
|
229
|
-
chatTitle,
|
|
230
|
-
userId: actorId,
|
|
231
|
-
username: actorName,
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
const authResult = await options.evaluateIncomingAuthorization({
|
|
214
|
+
const access_result = await options.evaluateIncomingAccess({
|
|
235
215
|
chatId,
|
|
236
216
|
chatType: message.chat.type,
|
|
237
217
|
chatTitle,
|
|
238
218
|
userId: actorId,
|
|
239
219
|
username: actorName,
|
|
240
220
|
});
|
|
241
|
-
if (
|
|
221
|
+
if (!access_result.allowed) {
|
|
242
222
|
if (!isGroup) {
|
|
243
|
-
await options.
|
|
223
|
+
await options.sendAccessText({
|
|
244
224
|
chatId,
|
|
245
225
|
chatType: message.chat.type,
|
|
246
226
|
messageThreadId,
|
|
247
|
-
text: options.
|
|
248
|
-
chatId,
|
|
249
|
-
chatType: message.chat.type,
|
|
250
|
-
userId: actorId,
|
|
251
|
-
}),
|
|
227
|
+
text: options.buildAccessBlockedText({ result: access_result }),
|
|
252
228
|
});
|
|
253
229
|
}
|
|
254
230
|
return;
|