@downcity/plugins 1.0.153 → 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.
Files changed (175) hide show
  1. package/bin/chat/ChatPlugin.d.ts +2 -10
  2. package/bin/chat/ChatPlugin.d.ts.map +1 -1
  3. package/bin/chat/ChatPlugin.js +3 -13
  4. package/bin/chat/ChatPlugin.js.map +1 -1
  5. package/bin/chat/PROMPT.direct.d.ts +1 -1
  6. package/bin/chat/PROMPT.direct.d.ts.map +1 -1
  7. package/bin/chat/PROMPT.direct.js +1 -1
  8. package/bin/chat/PROMPT.direct.js.map +1 -1
  9. package/bin/chat/access/ChatAccessActions.d.ts +11 -0
  10. package/bin/chat/access/ChatAccessActions.d.ts.map +1 -0
  11. package/bin/chat/access/ChatAccessActions.js +137 -0
  12. package/bin/chat/access/ChatAccessActions.js.map +1 -0
  13. package/bin/chat/access/ChatAccessRuntime.d.ts +17 -0
  14. package/bin/chat/access/ChatAccessRuntime.d.ts.map +1 -0
  15. package/bin/chat/access/ChatAccessRuntime.js +31 -0
  16. package/bin/chat/access/ChatAccessRuntime.js.map +1 -0
  17. package/bin/chat/access/ChatAccessSchema.d.ts +16 -0
  18. package/bin/chat/access/ChatAccessSchema.d.ts.map +1 -0
  19. package/bin/chat/access/ChatAccessSchema.js +99 -0
  20. package/bin/chat/access/ChatAccessSchema.js.map +1 -0
  21. package/bin/chat/access/ChatAccessService.d.ts +44 -0
  22. package/bin/chat/access/ChatAccessService.d.ts.map +1 -0
  23. package/bin/chat/access/ChatAccessService.js +281 -0
  24. package/bin/chat/access/ChatAccessService.js.map +1 -0
  25. package/bin/chat/access/ChatAccessStore.d.ts +67 -0
  26. package/bin/chat/access/ChatAccessStore.d.ts.map +1 -0
  27. package/bin/chat/access/ChatAccessStore.js +367 -0
  28. package/bin/chat/access/ChatAccessStore.js.map +1 -0
  29. package/bin/chat/accounts/Crypto.d.ts +1 -1
  30. package/bin/chat/accounts/Crypto.js +1 -1
  31. package/bin/chat/accounts/Store.d.ts +1 -1
  32. package/bin/chat/accounts/Store.js +1 -1
  33. package/bin/chat/channels/BaseChatChannel.d.ts +18 -21
  34. package/bin/chat/channels/BaseChatChannel.d.ts.map +1 -1
  35. package/bin/chat/channels/BaseChatChannel.js +48 -58
  36. package/bin/chat/channels/BaseChatChannel.js.map +1 -1
  37. package/bin/chat/channels/BaseChatChannelQueue.d.ts +1 -1
  38. package/bin/chat/channels/BaseChatChannelQueue.d.ts.map +1 -1
  39. package/bin/chat/channels/BaseChatChannelQueue.js +2 -14
  40. package/bin/chat/channels/BaseChatChannelQueue.js.map +1 -1
  41. package/bin/chat/channels/Configuration.d.ts +2 -2
  42. package/bin/chat/channels/Configuration.d.ts.map +1 -1
  43. package/bin/chat/channels/Configuration.js +3 -3
  44. package/bin/chat/channels/Configuration.js.map +1 -1
  45. package/bin/chat/channels/feishu/Configuration.js +4 -4
  46. package/bin/chat/channels/feishu/Configuration.js.map +1 -1
  47. package/bin/chat/channels/feishu/Feishu.d.ts +2 -0
  48. package/bin/chat/channels/feishu/Feishu.d.ts.map +1 -1
  49. package/bin/chat/channels/feishu/Feishu.js +8 -7
  50. package/bin/chat/channels/feishu/Feishu.js.map +1 -1
  51. package/bin/chat/channels/feishu/FeishuMessageHandler.d.ts +9 -17
  52. package/bin/chat/channels/feishu/FeishuMessageHandler.d.ts.map +1 -1
  53. package/bin/chat/channels/feishu/FeishuMessageHandler.js +6 -17
  54. package/bin/chat/channels/feishu/FeishuMessageHandler.js.map +1 -1
  55. package/bin/chat/channels/qq/Configuration.js +4 -4
  56. package/bin/chat/channels/qq/Configuration.js.map +1 -1
  57. package/bin/chat/channels/qq/QQ.d.ts +2 -0
  58. package/bin/chat/channels/qq/QQ.d.ts.map +1 -1
  59. package/bin/chat/channels/qq/QQ.js +8 -7
  60. package/bin/chat/channels/qq/QQ.js.map +1 -1
  61. package/bin/chat/channels/qq/QQMessageHandler.d.ts +9 -17
  62. package/bin/chat/channels/qq/QQMessageHandler.d.ts.map +1 -1
  63. package/bin/chat/channels/qq/QQMessageHandler.js +7 -25
  64. package/bin/chat/channels/qq/QQMessageHandler.js.map +1 -1
  65. package/bin/chat/channels/telegram/Bot.d.ts +2 -0
  66. package/bin/chat/channels/telegram/Bot.d.ts.map +1 -1
  67. package/bin/chat/channels/telegram/Bot.js +8 -7
  68. package/bin/chat/channels/telegram/Bot.js.map +1 -1
  69. package/bin/chat/channels/telegram/Configuration.js +4 -4
  70. package/bin/chat/channels/telegram/Configuration.js.map +1 -1
  71. package/bin/chat/channels/telegram/TelegramMessageHandler.d.ts +9 -17
  72. package/bin/chat/channels/telegram/TelegramMessageHandler.d.ts.map +1 -1
  73. package/bin/chat/channels/telegram/TelegramMessageHandler.js +5 -16
  74. package/bin/chat/channels/telegram/TelegramMessageHandler.js.map +1 -1
  75. package/bin/chat/runtime/ChatChannelActions.d.ts +3 -2
  76. package/bin/chat/runtime/ChatChannelActions.d.ts.map +1 -1
  77. package/bin/chat/runtime/ChatChannelActions.js +57 -0
  78. package/bin/chat/runtime/ChatChannelActions.js.map +1 -1
  79. package/bin/chat/runtime/ChatChannelConfig.d.ts +2 -2
  80. package/bin/chat/runtime/ChatChannelConfig.js +3 -3
  81. package/bin/chat/runtime/ChatChannelConfig.js.map +1 -1
  82. package/bin/chat/runtime/ChatChannelCore.d.ts +2 -2
  83. package/bin/chat/runtime/ChatChannelCore.js +1 -1
  84. package/bin/chat/runtime/ChatChannelLifecycle.d.ts +1 -1
  85. package/bin/chat/runtime/ChatChannelLifecycle.js +1 -1
  86. package/bin/chat/runtime/PluginPoints.d.ts +0 -24
  87. package/bin/chat/runtime/PluginPoints.d.ts.map +1 -1
  88. package/bin/chat/runtime/PluginPoints.js +0 -24
  89. package/bin/chat/runtime/PluginPoints.js.map +1 -1
  90. package/bin/chat/runtime/QueuedUserMessage.d.ts.map +1 -1
  91. package/bin/chat/runtime/QueuedUserMessage.js +0 -2
  92. package/bin/chat/runtime/QueuedUserMessage.js.map +1 -1
  93. package/bin/chat/types/ChannelConfiguration.d.ts +4 -4
  94. package/bin/chat/types/ChannelConfiguration.d.ts.map +1 -1
  95. package/bin/chat/types/ChatAccess.d.ts +300 -0
  96. package/bin/chat/types/ChatAccess.d.ts.map +1 -0
  97. package/bin/chat/types/ChatAccess.js +22 -0
  98. package/bin/chat/types/ChatAccess.js.map +1 -0
  99. package/bin/chat/types/ChatPromptContext.d.ts +0 -15
  100. package/bin/chat/types/ChatPromptContext.d.ts.map +1 -1
  101. package/bin/index.d.ts +4 -4
  102. package/bin/index.d.ts.map +1 -1
  103. package/bin/index.js +3 -3
  104. package/bin/index.js.map +1 -1
  105. package/bin/skill/Config.d.ts +1 -1
  106. package/bin/skill/Config.js +1 -1
  107. package/bin/skill/runtime/Paths.d.ts +1 -1
  108. package/bin/skill/runtime/Paths.js +1 -1
  109. package/package.json +6 -4
  110. package/scripts/chat-access.test.mjs +90 -0
  111. package/scripts/chat-channel-config.test.mjs +82 -0
  112. package/src/chat/ChatPlugin.ts +4 -24
  113. package/src/chat/PROMPT.direct.ts +1 -1
  114. package/src/chat/PROMPT.direct.ts.txt +1 -1
  115. package/src/chat/access/ChatAccessActions.ts +159 -0
  116. package/src/chat/access/ChatAccessRuntime.ts +41 -0
  117. package/src/chat/access/ChatAccessSchema.ts +104 -0
  118. package/src/chat/access/ChatAccessService.ts +311 -0
  119. package/src/chat/access/ChatAccessStore.ts +462 -0
  120. package/src/chat/accounts/Crypto.ts +1 -1
  121. package/src/chat/accounts/Store.ts +1 -1
  122. package/src/chat/channels/BaseChatChannel.ts +59 -80
  123. package/src/chat/channels/BaseChatChannelQueue.ts +2 -14
  124. package/src/chat/channels/Configuration.ts +3 -3
  125. package/src/chat/channels/feishu/Configuration.ts +4 -4
  126. package/src/chat/channels/feishu/Feishu.ts +11 -9
  127. package/src/chat/channels/feishu/FeishuMessageHandler.ts +16 -40
  128. package/src/chat/channels/qq/Configuration.ts +4 -4
  129. package/src/chat/channels/qq/QQ.ts +11 -9
  130. package/src/chat/channels/qq/QQMessageHandler.ts +17 -49
  131. package/src/chat/channels/telegram/Bot.ts +11 -9
  132. package/src/chat/channels/telegram/Configuration.ts +4 -4
  133. package/src/chat/channels/telegram/TelegramMessageHandler.ts +15 -39
  134. package/src/chat/runtime/ChatChannelActions.ts +72 -1
  135. package/src/chat/runtime/ChatChannelConfig.ts +3 -3
  136. package/src/chat/runtime/ChatChannelCore.ts +1 -1
  137. package/src/chat/runtime/ChatChannelLifecycle.ts +1 -1
  138. package/src/chat/runtime/PluginPoints.ts +0 -24
  139. package/src/chat/runtime/QueuedUserMessage.ts +0 -2
  140. package/src/chat/types/ChannelConfiguration.ts +4 -4
  141. package/src/chat/types/ChatAccess.ts +335 -0
  142. package/src/chat/types/ChatPromptContext.ts +0 -17
  143. package/src/index.ts +27 -31
  144. package/src/skill/Config.ts +1 -1
  145. package/src/skill/runtime/Paths.ts +1 -1
  146. package/bin/auth/runtime/AuthorizationConfig.d.ts +0 -41
  147. package/bin/auth/runtime/AuthorizationConfig.d.ts.map +0 -1
  148. package/bin/auth/runtime/AuthorizationConfig.js +0 -185
  149. package/bin/auth/runtime/AuthorizationConfig.js.map +0 -1
  150. package/bin/auth/runtime/AuthorizationPolicy.d.ts +0 -28
  151. package/bin/auth/runtime/AuthorizationPolicy.d.ts.map +0 -1
  152. package/bin/auth/runtime/AuthorizationPolicy.js +0 -124
  153. package/bin/auth/runtime/AuthorizationPolicy.js.map +0 -1
  154. package/bin/auth/runtime/AuthorizationStore.d.ts +0 -29
  155. package/bin/auth/runtime/AuthorizationStore.d.ts.map +0 -1
  156. package/bin/auth/runtime/AuthorizationStore.js +0 -179
  157. package/bin/auth/runtime/AuthorizationStore.js.map +0 -1
  158. package/bin/auth/types/AuthPlugin.d.ts +0 -403
  159. package/bin/auth/types/AuthPlugin.d.ts.map +0 -1
  160. package/bin/auth/types/AuthPlugin.js +0 -111
  161. package/bin/auth/types/AuthPlugin.js.map +0 -1
  162. package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts +0 -22
  163. package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts.map +0 -1
  164. package/bin/chat/runtime/ChatAuthorizationRuntime.js +0 -230
  165. package/bin/chat/runtime/ChatAuthorizationRuntime.js.map +0 -1
  166. package/bin/chat/runtime/PluginDispatch.d.ts +0 -43
  167. package/bin/chat/runtime/PluginDispatch.d.ts.map +0 -1
  168. package/bin/chat/runtime/PluginDispatch.js +0 -57
  169. package/bin/chat/runtime/PluginDispatch.js.map +0 -1
  170. package/src/auth/runtime/AuthorizationConfig.ts +0 -247
  171. package/src/auth/runtime/AuthorizationPolicy.ts +0 -167
  172. package/src/auth/runtime/AuthorizationStore.ts +0 -220
  173. package/src/auth/types/AuthPlugin.ts +0 -540
  174. package/src/chat/runtime/ChatAuthorizationRuntime.ts +0 -270
  175. 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
- * - 统一提供“可写 ship 字段”提取逻辑,避免在 service 中重复硬编码。
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
- getWritableShipFields(): ChatChannelConfigurationField[] {
33
- return this.describe().fields.ship.filter((field) => field.writable);
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
- ship: [
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: "ship_json",
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 chat account row in ~/.downcity/downcity.db channel_accounts.",
50
+ "Bind this chat platform to a channel_accounts row in the global downcity.db.",
51
51
  type: "string",
52
- source: "ship_json",
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
- observeIncomingAuthorization: async (params) => {
213
- await this.observeIncomingAuthorization(params);
214
- },
215
- evaluateIncomingAuthorization: async (params) =>
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
- buildUnauthorizedBlockedText: (params) =>
221
- this.buildUnauthorizedBlockedText(params),
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
- IncomingAuthorizationParams,
15
- IncomingAuthorizationResult,
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
- observeIncomingAuthorization(
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
- buildUnauthorizedBlockedText(params?: {
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.observeIncomingAuthorization({
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 (authResult.decision !== "allow") {
372
+ if (!access_result.allowed) {
393
373
  if (chatType === "p2p") {
394
- await options.sendAuthorizationText({
374
+ await options.sendAccessText({
395
375
  chatId,
396
376
  chatType,
397
- text: options.buildUnauthorizedBlockedText({
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
- ship: [
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: "ship_json",
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 chat account row in ~/.downcity/downcity.db channel_accounts.",
49
+ "Bind this chat platform to a channel_accounts row in the global downcity.db.",
50
50
  type: "string",
51
- source: "ship_json",
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
- observeIncomingAuthorization: async (params) => {
270
- await this.observeIncomingAuthorization(params);
271
- },
272
- evaluateIncomingAuthorization: async (params) =>
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
- buildUnauthorizedBlockedText: (params) =>
278
- this.buildUnauthorizedBlockedText(params),
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
- IncomingAuthorizationParams,
15
- IncomingAuthorizationResult,
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
- observeIncomingAuthorization(
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
- buildUnauthorizedBlockedText(params?: {
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.observeIncomingAuthorization({
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 (authResult.decision !== "allow") return;
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.observeIncomingAuthorization({
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 (authResult.decision !== "allow") {
337
+ if (!access_result.allowed) {
366
338
  if (!isGroup) {
367
- await options.sendAuthorizationText({
339
+ await options.sendAccessText({
368
340
  chatId,
369
341
  chatType,
370
- text: options.buildUnauthorizedBlockedText({
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
- observeIncomingAuthorization: async (params) => {
211
- await this.observeIncomingAuthorization(params);
212
- },
213
- evaluateIncomingAuthorization: async (params) =>
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
- buildUnauthorizedBlockedText: (params) =>
219
- this.buildUnauthorizedBlockedText(params),
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
- ship: [
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: "ship_json",
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 chat account row in ~/.downcity/downcity.db channel_accounts.",
50
+ "Bind this chat platform to a channel_accounts row in the global downcity.db.",
51
51
  type: "string",
52
- source: "ship_json",
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
- IncomingAuthorizationParams,
16
- IncomingAuthorizationResult,
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
- observeIncomingAuthorization(
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
- buildUnauthorizedBlockedText(params?: {
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.observeIncomingAuthorization({
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 (authResult.decision !== "allow") {
221
+ if (!access_result.allowed) {
242
222
  if (!isGroup) {
243
- await options.sendAuthorizationText({
223
+ await options.sendAccessText({
244
224
  chatId,
245
225
  chatType: message.chat.type,
246
226
  messageThreadId,
247
- text: options.buildUnauthorizedBlockedText({
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;