@downcity/plugins 1.0.153 → 1.0.157

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 +34 -21
  34. package/bin/chat/channels/BaseChatChannel.d.ts.map +1 -1
  35. package/bin/chat/channels/BaseChatChannel.js +71 -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 +12 -0
  66. package/bin/chat/channels/telegram/Bot.d.ts.map +1 -1
  67. package/bin/chat/channels/telegram/Bot.js +24 -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 +126 -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 +86 -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 +29 -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
@@ -72,6 +72,29 @@ 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
+
80
+ /**
81
+ * 使用 Telegram 行内代码展示授权值。
82
+ *
83
+ * 说明(中文)
84
+ * - Telegram 的 Markdown 会把普通文本中的成对下划线解析为强调标记。
85
+ * - 行内代码可以原样保留 request ID 和 Agent ID,便于管理员直接复制执行。
86
+ */
87
+ protected format_access_code(value: string): string {
88
+ const escaped_value = value.replace(/([\\`])/g, "\\$1");
89
+ return `\`${escaped_value}\``;
90
+ }
91
+
92
+ /** 使用带语言标记的代码块展示可直接执行的管理命令。 */
93
+ protected format_access_command(command: string): string {
94
+ const escaped_command = command.replace(/([\\`])/g, "\\$1");
95
+ return `\`\`\`bash\n${escaped_command}\n\`\`\``;
96
+ }
97
+
75
98
  protected async sendTextToPlatform(
76
99
  params: ChannelSendTextParams,
77
100
  ): Promise<void> {
@@ -207,16 +230,13 @@ export class TelegramBot extends BaseChatChannel {
207
230
  logger: this.logger,
208
231
  inboundAckEmoji: TelegramBot.INBOUND_ACK_EMOJI,
209
232
  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);
233
+ evaluateIncomingAccess: async (params) =>
234
+ await this.evaluateIncomingAccess(params),
235
+ sendAccessText: async (params) => {
236
+ await this.sendAccessText(params);
217
237
  },
218
- buildUnauthorizedBlockedText: (params) =>
219
- this.buildUnauthorizedBlockedText(params),
238
+ buildAccessBlockedText: (params) =>
239
+ this.buildAccessBlockedText(params),
220
240
  enqueueAuditMessage: async (params) => {
221
241
  await this.enqueueAuditMessage(params);
222
242
  },
@@ -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;
@@ -7,7 +7,11 @@
7
7
  * - 对外只暴露 action 级入口,供 ChatPluginActions 装配使用。
8
8
  */
9
9
 
10
- import type { AgentContext } from "@downcity/agent";
10
+ import type {
11
+ AgentContext,
12
+ DowncityChatChannelConfig,
13
+ DowncityConfig,
14
+ } from "@downcity/agent";
11
15
  import type { ChatChannelState } from "@/chat/types/ChatRuntime.js";
12
16
  import { getStoredChannelAccountSync } from "@/chat/accounts/Store.js";
13
17
  import type {
@@ -20,6 +24,7 @@ import type {
20
24
  ChatTestActionPayload,
21
25
  } from "@/chat/types/ChatPluginActionPayload.js";
22
26
  import type { ChatChannelTestResult } from "@/chat/types/ChannelStatus.js";
27
+ import type { ChatChannelName } from "@/chat/types/ChannelStatus.js";
23
28
  import {
24
29
  describeChatChannelConfiguration,
25
30
  getChatChannelStatus,
@@ -49,6 +54,54 @@ function getChatRuntimeBindings(context: AgentContext): ChatRuntimeControlBindin
49
54
  return plugin as ChatRuntimeControlBindings;
50
55
  }
51
56
 
57
+ /**
58
+ * 将 channel patch 合并进完整 plugins 配置并交给宿主持久化。
59
+ *
60
+ * 关键点(中文)
61
+ * - 始终写回完整 plugins 对象,避免覆盖其他 plugin 配置。
62
+ * - 宿主持久化成功后才更新当前 context 快照,保证运行态与存储态一致。
63
+ */
64
+ async function persist_chat_channel_patches(params: {
65
+ context: AgentContext;
66
+ patches: Array<{
67
+ channel: ChatChannelName;
68
+ enabled?: boolean;
69
+ channel_account_id?: string | null;
70
+ }>;
71
+ }): Promise<DowncityConfig["plugins"]> {
72
+ const current_plugins = params.context.config.plugins || {};
73
+ const current_chat = current_plugins.chat || {};
74
+ const next_channels = { ...(current_chat.channels || {}) };
75
+
76
+ for (const patch of params.patches) {
77
+ const current_channel = next_channels[patch.channel] || {};
78
+ const next_channel: DowncityChatChannelConfig = { ...current_channel };
79
+ if (typeof patch.enabled === "boolean") {
80
+ next_channel.enabled = patch.enabled;
81
+ }
82
+ if (Object.prototype.hasOwnProperty.call(patch, "channel_account_id")) {
83
+ const channel_account_id = String(patch.channel_account_id || "").trim();
84
+ if (channel_account_id) {
85
+ next_channel.channelAccountId = channel_account_id;
86
+ } else {
87
+ delete next_channel.channelAccountId;
88
+ }
89
+ }
90
+ next_channels[patch.channel] = next_channel;
91
+ }
92
+
93
+ const next_plugins: DowncityConfig["plugins"] = {
94
+ ...current_plugins,
95
+ chat: {
96
+ ...current_chat,
97
+ channels: next_channels,
98
+ },
99
+ };
100
+ await params.context.pluginConfig.persistProjectPlugins(next_plugins);
101
+ params.context.config.plugins = next_plugins;
102
+ return next_plugins;
103
+ }
104
+
52
105
  /**
53
106
  * 执行 `chat.status` action。
54
107
  */
@@ -176,6 +229,10 @@ export async function executeChatOpenAction(params: {
176
229
  }) {
177
230
  const targets = resolveTargetChannels(params.payload.channel);
178
231
  const plugin = getChatRuntimeBindings(params.context);
232
+ await persist_chat_channel_patches({
233
+ context: params.context,
234
+ patches: targets.map((channel) => ({ channel, enabled: true })),
235
+ });
179
236
  for (const channel of targets) {
180
237
  plugin.applyChannelRuntimePatch({
181
238
  channel,
@@ -211,6 +268,10 @@ export async function executeChatCloseAction(params: {
211
268
  }) {
212
269
  const targets = resolveTargetChannels(params.payload.channel);
213
270
  const plugin = getChatRuntimeBindings(params.context);
271
+ await persist_chat_channel_patches({
272
+ context: params.context,
273
+ patches: targets.map((channel) => ({ channel, enabled: false })),
274
+ });
214
275
  for (const channel of targets) {
215
276
  await stopSingleChatChannel(params.state, channel);
216
277
  plugin.applyChannelRuntimePatch({
@@ -293,6 +354,16 @@ export async function executeChatConfigureAction(params: {
293
354
  }
294
355
 
295
356
  const plugin = getChatRuntimeBindings(params.context);
357
+ await persist_chat_channel_patches({
358
+ context: params.context,
359
+ patches: [{
360
+ channel,
361
+ ...(typeof patch.enabled === "boolean" ? { enabled: patch.enabled } : {}),
362
+ ...(Object.prototype.hasOwnProperty.call(patch, "channelAccountId")
363
+ ? { channel_account_id: String(patch.channelAccountId || "").trim() || null }
364
+ : {}),
365
+ }],
366
+ });
296
367
  plugin.applyChannelRuntimePatch({
297
368
  channel,
298
369
  ...(typeof patch.enabled === "boolean" ? { enabled: patch.enabled } : {}),
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 渠道配置摘要、状态快照、patch 归一化都收敛在这里。
6
- * - chat.configure 的运行态写入由 ChatPlugin 实例承载,不再落盘到 downcity.json。
6
+ * - chat.configure 的配置持久化由宿主能力承载,运行态更新由 ChatPlugin 实例承载。
7
7
  * - 该模块不直接负责 action 流程控制,只提供可复用的底层能力。
8
8
  */
9
9
 
@@ -37,7 +37,7 @@ function toJsonObject(input: unknown): JsonObject {
37
37
  *
38
38
  * 关键点(中文)
39
39
  * - 不返回明文密钥,只返回布尔“是否已配置”。
40
- * - 字段命名尽量贴近 `downcity.json`,便于前端直接映射编辑。
40
+ * - 字段命名与 Agent 全局配置保持一致,便于前端直接映射编辑。
41
41
  */
42
42
  export function buildChatChannelConfigSummary(
43
43
  context: AgentContext,
@@ -194,7 +194,7 @@ export function normalizeChatChannelConfigPatch(params: {
194
194
  config: Record<string, JsonValue>;
195
195
  }): Record<string, string | number | boolean | null> {
196
196
  const configDefinition = getChatChannelConfiguration(params.channel);
197
- const writableFields = configDefinition.getWritableShipFields();
197
+ const writableFields = configDefinition.get_writable_agent_config_fields();
198
198
  const patch: Record<string, string | number | boolean | null> = {};
199
199
 
200
200
  for (const field of writableFields) {
@@ -101,7 +101,7 @@ export function resolveChannelAccountId(
101
101
  * 关键点(中文)
102
102
  * - 优先使用 ChatPlugin 实例上的显式解析逻辑。
103
103
  * - 若实例只提供 channelAccountId,再从默认全局账号池读取对应账号。
104
- * - 不再从 downcity.json 隐式推断运行时账号。
104
+ * - 不从项目文件隐式推断运行时账号。
105
105
  */
106
106
  export function resolveChannelAccount(
107
107
  context: AgentContext,
@@ -4,7 +4,7 @@
4
4
  * 关键点(中文)
5
5
  * - 渠道 bot 的创建、启动、停止逻辑统一收敛在这里。
6
6
  * - 渠道 bot 状态归属于 chat plugin runtime 实例持有的 `ChatChannelState`。
7
- * - 本模块不处理 downcity.json 写入,也不负责 action 输入输出包装。
7
+ * - 本模块不处理配置持久化,也不负责 action 输入输出包装。
8
8
  */
9
9
 
10
10
  import type { AgentContext } from "@downcity/agent";
@@ -51,28 +51,4 @@ export const CHAT_PLUGIN_POINTS = {
51
51
  * - plugin 可在这里做统计、观测、调试落点。
52
52
  */
53
53
  afterEnqueue: "chat.afterEnqueue",
54
- /**
55
- * 观测入站主体信息。
56
- *
57
- * 说明(中文)
58
- * - 仅做副作用记录,不返回值。
59
- * - ChatPlugin 内置授权能力会使用该点记录主体快照。
60
- */
61
- observePrincipal: "chat.observePrincipal",
62
- /**
63
- * 判定当前入站消息是否允许执行。
64
- *
65
- * 说明(中文)
66
- * - 由 chat plugin runtime 在 ingress 阶段显式调用。
67
- * - ChatPlugin 内置授权能力会使用该点执行角色与权限判定。
68
- */
69
- authorizeIncoming: "chat.authorizeIncoming",
70
- /**
71
- * 解析当前用户角色。
72
- *
73
- * 说明(中文)
74
- * - 主要用于在 history / queue metadata 中补齐授权上下文。
75
- * - ChatPlugin 内置授权能力会使用该点补齐用户角色。
76
- */
77
- resolveUserRole: "chat.resolveUserRole",
78
54
  } as const;
@@ -43,8 +43,6 @@ export function buildQueuedUserMessageWithInfo(params: {
43
43
  `message_id: ${normalizeInfoValue(params.messageId || "unknown")}`,
44
44
  `user_id: ${normalizeInfoValue(params.userId || "unknown")}`,
45
45
  `username: ${normalizeInfoValue(params.username || "unknown")}`,
46
- `role_id: ${normalizeInfoValue(params.roleId || "unknown")}`,
47
- `permissions: ${normalizeInfoValue((params.permissions || []).join(",") || "none")}`,
48
46
  `received_at: ${normalizeInfoValue(receivedAtIso)}`,
49
47
  `received_at_local: ${normalizeInfoValue(formatDateTimeInTimezone(receivedAtDate, runtimeTimezone))}`,
50
48
  `runtime_timezone: ${normalizeInfoValue(runtimeTimezone)}`,
@@ -27,7 +27,7 @@ export type ChatChannelConfigurationFieldType =
27
27
  * 配置字段来源枚举。
28
28
  */
29
29
  export type ChatChannelConfigurationFieldSource =
30
- | "ship_json"
30
+ | "agent_config"
31
31
  | "bot_account"
32
32
  | "env_fallback";
33
33
 
@@ -70,7 +70,7 @@ export interface ChatChannelConfigurationField {
70
70
  */
71
71
  type: ChatChannelConfigurationFieldType;
72
72
  /**
73
- * 字段值来源(downcity.json / chat account / env fallback)。
73
+ * 字段值来源(Agent config / chat account / env fallback)。
74
74
  */
75
75
  source: ChatChannelConfigurationFieldSource;
76
76
  /**
@@ -145,9 +145,9 @@ export interface ChatChannelConfigurationDescriptor {
145
145
  */
146
146
  fields: {
147
147
  /**
148
- * `downcity.json` 可声明字段。
148
+ * Agent 全局配置可声明字段。
149
149
  */
150
- ship: ChatChannelConfigurationField[];
150
+ agent_config: ChatChannelConfigurationField[];
151
151
  /**
152
152
  * `channel_accounts` 字段。
153
153
  */