@downcity/plugins 1.0.35 → 1.0.39

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 (62) hide show
  1. package/bin/auth/Plugin.js +2 -2
  2. package/bin/auth/Plugin.js.map +1 -1
  3. package/bin/chat/accounts/ChannelAccountManager.d.ts +3 -3
  4. package/bin/chat/accounts/ChannelAccountManager.js +6 -6
  5. package/bin/chat/accounts/ChannelAccountManager.js.map +1 -1
  6. package/bin/chat/accounts/Crypto.d.ts +1 -1
  7. package/bin/chat/accounts/Crypto.js +1 -1
  8. package/bin/chat/accounts/Store.d.ts +8 -8
  9. package/bin/chat/accounts/Store.js +13 -13
  10. package/bin/chat/accounts/Store.js.map +1 -1
  11. package/bin/chat/channels/feishu/Configuration.d.ts +1 -1
  12. package/bin/chat/channels/feishu/Configuration.js +5 -5
  13. package/bin/chat/channels/feishu/Configuration.js.map +1 -1
  14. package/bin/chat/channels/qq/Configuration.d.ts +1 -1
  15. package/bin/chat/channels/qq/Configuration.js +5 -5
  16. package/bin/chat/channels/qq/Configuration.js.map +1 -1
  17. package/bin/chat/channels/telegram/ApiClient.d.ts +12 -0
  18. package/bin/chat/channels/telegram/ApiClient.d.ts.map +1 -1
  19. package/bin/chat/channels/telegram/ApiClient.js +57 -4
  20. package/bin/chat/channels/telegram/ApiClient.js.map +1 -1
  21. package/bin/chat/channels/telegram/BotInfo.d.ts +1 -1
  22. package/bin/chat/channels/telegram/BotInfo.js +1 -1
  23. package/bin/chat/channels/telegram/Configuration.d.ts +1 -1
  24. package/bin/chat/channels/telegram/Configuration.js +5 -5
  25. package/bin/chat/channels/telegram/Configuration.js.map +1 -1
  26. package/bin/chat/runtime/ChatChannelCore.d.ts +1 -1
  27. package/bin/chat/runtime/ChatChannelCore.js +1 -1
  28. package/bin/chat/runtime/ChatChannelLifecycle.js +1 -1
  29. package/bin/chat/runtime/ChatChannelLifecycle.js.map +1 -1
  30. package/bin/chat/runtime/ChatPluginSystem.d.ts +2 -2
  31. package/bin/chat/runtime/ChatPluginSystem.js +1 -1
  32. package/bin/chat/runtime/ChatPromptAssets.d.ts +1 -1
  33. package/bin/chat/runtime/ChatPromptAssets.js +1 -1
  34. package/bin/chat/runtime/ChatQueueWorker.d.ts.map +1 -1
  35. package/bin/chat/runtime/ChatQueueWorker.js +12 -33
  36. package/bin/chat/runtime/ChatQueueWorker.js.map +1 -1
  37. package/bin/chat/types/BotInfo.d.ts +2 -2
  38. package/bin/chat/types/BotInfo.js +1 -1
  39. package/bin/chat/types/ChannelAccount.d.ts +12 -12
  40. package/bin/chat/types/ChannelAccount.js +2 -2
  41. package/bin/chat/types/ChannelConfiguration.d.ts +2 -2
  42. package/bin/chat/types/FeishuPost.d.ts +1 -1
  43. package/bin/chat/types/FeishuPost.js +1 -1
  44. package/package.json +2 -2
  45. package/src/auth/Plugin.ts +2 -2
  46. package/src/chat/accounts/ChannelAccountManager.ts +6 -6
  47. package/src/chat/accounts/Crypto.ts +1 -1
  48. package/src/chat/accounts/Store.ts +13 -13
  49. package/src/chat/channels/feishu/Configuration.ts +5 -5
  50. package/src/chat/channels/qq/Configuration.ts +5 -5
  51. package/src/chat/channels/telegram/ApiClient.ts +71 -4
  52. package/src/chat/channels/telegram/BotInfo.ts +1 -1
  53. package/src/chat/channels/telegram/Configuration.ts +5 -5
  54. package/src/chat/runtime/ChatChannelCore.ts +1 -1
  55. package/src/chat/runtime/ChatChannelLifecycle.ts +1 -1
  56. package/src/chat/runtime/ChatPluginSystem.ts +2 -2
  57. package/src/chat/runtime/ChatPromptAssets.ts +1 -1
  58. package/src/chat/runtime/ChatQueueWorker.ts +12 -39
  59. package/src/chat/types/BotInfo.ts +2 -2
  60. package/src/chat/types/ChannelAccount.ts +12 -12
  61. package/src/chat/types/ChannelConfiguration.ts +2 -3
  62. package/src/chat/types/FeishuPost.ts +1 -1
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Channel account 默认存储实现。
2
+ * Chat account 默认存储实现。
3
3
  *
4
4
  * 职责说明(中文)
5
- * - 提供 `chat` plugin 默认使用的全局 channel account 读写能力。
5
+ * - 提供 `chat` plugin 默认使用的全局 chat account 读写能力。
6
6
  * - 默认直接操作 `~/.downcity/downcity.db` 里的 `channel_accounts` 表。
7
7
  * - 对 `city` 而言,这里也是统一的默认账号池实现来源。
8
8
  *
9
9
  * 边界说明(中文)
10
- * - 这里只负责 channel account 这一个表,不扩展成通用平台数据库门面。
10
+ * - 这里只负责 chat account 这一个表,不扩展成通用平台数据库门面。
11
11
  * - 模型池、env、其他平台级配置仍由各自模块独立管理。
12
12
  */
13
13
 
@@ -40,7 +40,7 @@ function optionalTrimmedText(value: string | undefined): string | undefined {
40
40
  }
41
41
 
42
42
  /**
43
- * 规范化 channel 类型。
43
+ * 规范化 chat platform 类型。
44
44
  */
45
45
  export function normalizeChannelAccountChannel(
46
46
  input: string,
@@ -49,7 +49,7 @@ export function normalizeChannelAccountChannel(
49
49
  if (channel === "telegram" || channel === "feishu" || channel === "qq") {
50
50
  return channel;
51
51
  }
52
- throw new Error(`Unsupported channel account type: ${input}`);
52
+ throw new Error(`Unsupported chat account platform: ${input}`);
53
53
  }
54
54
 
55
55
  function ensureChannelAccountSchema(database: Database.Database): void {
@@ -138,7 +138,7 @@ function buildChannelAccountFromRow(
138
138
  }
139
139
 
140
140
  /**
141
- * 同步列出全部 channel account。
141
+ * 同步列出全部 chat account。
142
142
  */
143
143
  export function listStoredChannelAccountsSync(
144
144
  channelInput?: string,
@@ -178,12 +178,12 @@ export function listStoredChannelAccountsSync(
178
178
  }
179
179
 
180
180
  /**
181
- * 同步按 ID 读取单个 channel account。
181
+ * 同步按 ID 读取单个 chat account。
182
182
  */
183
183
  export function getStoredChannelAccountSync(
184
184
  accountIdInput: string,
185
185
  ): StoredChannelAccount | null {
186
- const accountId = normalizeNonEmptyText(accountIdInput, "channel account id");
186
+ const accountId = normalizeNonEmptyText(accountIdInput, "chat account id");
187
187
  return withChannelAccountDb((database) => {
188
188
  const row = database.prepare(
189
189
  `
@@ -201,7 +201,7 @@ export function getStoredChannelAccountSync(
201
201
  }
202
202
 
203
203
  /**
204
- * 新增或更新 channel account。
204
+ * 新增或更新 chat account。
205
205
  *
206
206
  * 关键点(中文)
207
207
  * - 这里保留和现有平台库一致的落盘结构,避免默认实现切换后出现数据断层。
@@ -210,9 +210,9 @@ export function getStoredChannelAccountSync(
210
210
  export async function upsertStoredChannelAccount(
211
211
  input: UpsertChannelAccountInput,
212
212
  ): Promise<void> {
213
- const id = normalizeNonEmptyText(input.id, "channel account id");
213
+ const id = normalizeNonEmptyText(input.id, "chat account id");
214
214
  const channel = normalizeChannelAccountChannel(input.channel);
215
- const name = normalizeNonEmptyText(input.name, "channel account name");
215
+ const name = normalizeNonEmptyText(input.name, "chat account name");
216
216
  const existing = getStoredChannelAccountSync(id);
217
217
  const createdAt = existing?.createdAt || nowIso();
218
218
  const updatedAt = nowIso();
@@ -275,12 +275,12 @@ export async function upsertStoredChannelAccount(
275
275
  }
276
276
 
277
277
  /**
278
- * 删除单个 channel account。
278
+ * 删除单个 chat account。
279
279
  */
280
280
  export async function removeStoredChannelAccount(
281
281
  accountIdInput: string,
282
282
  ): Promise<void> {
283
- const accountId = normalizeNonEmptyText(accountIdInput, "channel account id");
283
+ const accountId = normalizeNonEmptyText(accountIdInput, "chat account id");
284
284
  withChannelAccountDb((database) => {
285
285
  database.prepare("DELETE FROM channel_accounts WHERE id = ?;").run(accountId);
286
286
  });
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - ship 层只保留绑定字段。
6
- * - appId/appSecret/domain 由 channel account 维护。
6
+ * - appId/appSecret/domain 由 chat account 维护。
7
7
  */
8
8
 
9
9
  import { ChatChannelConfiguration } from "@/chat/channels/Configuration.js";
@@ -18,9 +18,9 @@ export class FeishuChannelConfiguration extends ChatChannelConfiguration {
18
18
  describe(): ChatChannelConfigurationDescriptor {
19
19
  return {
20
20
  channel: this.channel,
21
- title: "Feishu Channel Configuration",
21
+ title: "Feishu Chat Platform Configuration",
22
22
  description:
23
- "Bind a Feishu/Lark channel account and control runtime enable/disable state.",
23
+ "Bind a Feishu/Lark chat account and control runtime enable/disable state.",
24
24
  version: "1.0.0",
25
25
  capabilities: {
26
26
  canToggleEnabled: true,
@@ -45,9 +45,9 @@ export class FeishuChannelConfiguration extends ChatChannelConfiguration {
45
45
  },
46
46
  {
47
47
  key: "channelAccountId",
48
- label: "Channel Account ID",
48
+ label: "Chat Account ID",
49
49
  description:
50
- "Bind channel to a channel account row in ~/.downcity/downcity.db channel_accounts.",
50
+ "Bind this chat platform to a chat account row in ~/.downcity/downcity.db channel_accounts.",
51
51
  type: "string",
52
52
  source: "ship_json",
53
53
  required: false,
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - ship 层只保留 `enabled` 与 `channelAccountId`。
6
- * - QQ 专属参数(sandbox 等)在 channel account 中维护。
6
+ * - QQ 专属参数(sandbox 等)在 chat account 中维护。
7
7
  */
8
8
 
9
9
  import { ChatChannelConfiguration } from "@/chat/channels/Configuration.js";
@@ -18,9 +18,9 @@ export class QqChannelConfiguration extends ChatChannelConfiguration {
18
18
  describe(): ChatChannelConfigurationDescriptor {
19
19
  return {
20
20
  channel: this.channel,
21
- title: "QQ Channel Configuration",
21
+ title: "QQ Chat Platform Configuration",
22
22
  description:
23
- "Bind a QQ channel account and control runtime enable/disable state.",
23
+ "Bind a QQ chat account and control runtime enable/disable state.",
24
24
  version: "1.0.0",
25
25
  capabilities: {
26
26
  canToggleEnabled: true,
@@ -44,9 +44,9 @@ export class QqChannelConfiguration extends ChatChannelConfiguration {
44
44
  },
45
45
  {
46
46
  key: "channelAccountId",
47
- label: "Channel Account ID",
47
+ label: "Chat Account ID",
48
48
  description:
49
- "Bind channel to a channel account row in ~/.downcity/downcity.db channel_accounts.",
49
+ "Bind this chat platform to a chat account row in ~/.downcity/downcity.db channel_accounts.",
50
50
  type: "string",
51
51
  source: "ship_json",
52
52
  required: false,
@@ -10,6 +10,12 @@ import {
10
10
  type TelegramAttachmentType,
11
11
  } from "./Shared.js";
12
12
 
13
+ const TELEGRAM_SEND_MAX_ATTEMPTS = 3;
14
+ const TELEGRAM_SEND_RETRY_DELAYS_MS = [1_000, 3_000];
15
+
16
+ function sleep(ms: number): Promise<void> {
17
+ return new Promise((resolve) => setTimeout(resolve, ms));
18
+ }
13
19
 
14
20
  /**
15
21
  * Telegram API 客户端。
@@ -104,6 +110,61 @@ export class TelegramApiClient {
104
110
  return payload.result as T;
105
111
  }
106
112
 
113
+ /**
114
+ * 发送类 JSON 请求的短重试。
115
+ *
116
+ * 关键点(中文)
117
+ * - 只重试网络抖动 / Telegram 5xx 这类瞬时失败。
118
+ * - 不重试 Telegram 4xx,避免 Markdown 参数错误、权限错误等被重复打扰。
119
+ */
120
+ private async requestSendJson<T>(
121
+ method: string,
122
+ data: Record<string, unknown>,
123
+ ): Promise<T> {
124
+ let lastError: unknown;
125
+ for (let attempt = 0; attempt < TELEGRAM_SEND_MAX_ATTEMPTS; attempt += 1) {
126
+ try {
127
+ return await this.requestJson<T>(method, data);
128
+ } catch (error) {
129
+ lastError = error;
130
+ if (
131
+ attempt >= TELEGRAM_SEND_MAX_ATTEMPTS - 1 ||
132
+ !this.isRetryableSendError(error)
133
+ ) {
134
+ throw error;
135
+ }
136
+
137
+ const delayMs =
138
+ TELEGRAM_SEND_RETRY_DELAYS_MS[attempt] ||
139
+ TELEGRAM_SEND_RETRY_DELAYS_MS[
140
+ TELEGRAM_SEND_RETRY_DELAYS_MS.length - 1
141
+ ];
142
+ this.logger.warn("Telegram send failed, retrying", {
143
+ method,
144
+ attempt: attempt + 1,
145
+ retryInMs: delayMs,
146
+ error: String(error),
147
+ });
148
+ await sleep(delayMs);
149
+ }
150
+ }
151
+
152
+ throw lastError;
153
+ }
154
+
155
+ /**
156
+ * 判断发送失败是否适合短重试。
157
+ */
158
+ private isRetryableSendError(error: unknown): boolean {
159
+ const text = String(error || "");
160
+ if (/Telegram API (HTTP|error)\s+4\d\d/i.test(text)) {
161
+ return false;
162
+ }
163
+ return /fetch failed|network|TLS|ECONN|ETIMEDOUT|EAI_AGAIN|UND_ERR|HTTP\s+5\d\d/i.test(
164
+ text,
165
+ );
166
+ }
167
+
107
168
  /**
108
169
  * 下载 Telegram 文件并保存到 `.downcity/.cache/telegram`。
109
170
  *
@@ -174,7 +235,7 @@ export class TelegramApiClient {
174
235
  for (const chunk of chunks) {
175
236
  if (!chunk) continue;
176
237
  try {
177
- await this.requestJson("sendMessage", {
238
+ await this.requestSendJson("sendMessage", {
178
239
  chat_id: chatId,
179
240
  text: chunk,
180
241
  parse_mode: "Markdown",
@@ -184,7 +245,7 @@ export class TelegramApiClient {
184
245
  } catch {
185
246
  // Fallback to plain text (Markdown is strict and often fails)
186
247
  try {
187
- await this.requestJson("sendMessage", {
248
+ await this.requestSendJson("sendMessage", {
188
249
  chat_id: chatId,
189
250
  text: chunk,
190
251
  ...(message_thread_id ? { message_thread_id } : {}),
@@ -192,6 +253,8 @@ export class TelegramApiClient {
192
253
  });
193
254
  } catch (error2) {
194
255
  this.logger.error(`Failed to send message: ${String(error2)}`);
256
+ // 关键点(中文):平台发送失败必须向上冒泡,避免 history 误记为已发送。
257
+ throw error2;
195
258
  }
196
259
  }
197
260
  }
@@ -205,7 +268,7 @@ export class TelegramApiClient {
205
268
  });
206
269
  } catch (e) {
207
270
  try {
208
- await this.requestJson("sendMessage", {
271
+ await this.requestSendJson("sendMessage", {
209
272
  chat_id: chatId,
210
273
  text: `❌ Failed to send ${segment.attachment.type}: ${String(e)}`,
211
274
  ...(message_thread_id ? { message_thread_id } : {}),
@@ -215,6 +278,8 @@ export class TelegramApiClient {
215
278
  this.logger.error(
216
279
  `Failed to send attachment error message: ${String(e2)}`,
217
280
  );
281
+ // 关键点(中文):附件和错误提示都发送失败时,上层必须感知失败。
282
+ throw e2;
218
283
  }
219
284
  }
220
285
  }
@@ -231,7 +296,7 @@ export class TelegramApiClient {
231
296
  ? opts.messageThreadId
232
297
  : undefined;
233
298
  try {
234
- await this.requestJson("sendMessage", {
299
+ await this.requestSendJson("sendMessage", {
235
300
  chat_id: chatId,
236
301
  text,
237
302
  ...(message_thread_id ? { message_thread_id } : {}),
@@ -243,6 +308,8 @@ export class TelegramApiClient {
243
308
  });
244
309
  } catch (error) {
245
310
  this.logger.error(`Failed to send message: ${String(error)}`);
311
+ // 关键点(中文):inline keyboard 发送失败也要返回失败状态给调用方。
312
+ throw error;
246
313
  }
247
314
  }
248
315
 
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 基于 `getMe` 接口验证 token 有效性。
6
- * - 返回统一结构,供 channel account 创建流程复用。
6
+ * - 返回统一结构,供 chat account 创建流程复用。
7
7
  */
8
8
 
9
9
  import type {
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - ship 层只绑定 `enabled` 与 `channelAccountId`。
6
- * - 真实密钥由 channel account 统一托管。
6
+ * - 真实密钥由 chat account 统一托管。
7
7
  */
8
8
 
9
9
  import { ChatChannelConfiguration } from "@/chat/channels/Configuration.js";
@@ -18,9 +18,9 @@ export class TelegramChannelConfiguration extends ChatChannelConfiguration {
18
18
  describe(): ChatChannelConfigurationDescriptor {
19
19
  return {
20
20
  channel: this.channel,
21
- title: "Telegram Channel Configuration",
21
+ title: "Telegram Chat Platform Configuration",
22
22
  description:
23
- "Bind a Telegram channel account and control runtime enable/disable state.",
23
+ "Bind a Telegram chat account and control runtime enable/disable state.",
24
24
  version: "1.0.0",
25
25
  capabilities: {
26
26
  canToggleEnabled: true,
@@ -45,9 +45,9 @@ export class TelegramChannelConfiguration extends ChatChannelConfiguration {
45
45
  },
46
46
  {
47
47
  key: "channelAccountId",
48
- label: "Channel Account ID",
48
+ label: "Chat Account ID",
49
49
  description:
50
- "Bind channel to a channel account row in ~/.downcity/downcity.db channel_accounts.",
50
+ "Bind this chat platform to a chat account row in ~/.downcity/downcity.db channel_accounts.",
51
51
  type: "string",
52
52
  source: "ship_json",
53
53
  required: false,
@@ -4,7 +4,7 @@
4
4
  * 关键点(中文)
5
5
  * - 这里只放最基础的渠道状态/名称/account 解析能力。
6
6
  * - 生命周期、配置写入、action 执行分别放到更细的模块中。
7
- * - 目标是让 chat channel 子模块共享同一套最小公共基元。
7
+ * - 目标是让 chat platform 子模块共享同一套最小公共基元。
8
8
  */
9
9
 
10
10
  import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
@@ -69,7 +69,7 @@ async function startQQChannel(
69
69
  context: AgentContext,
70
70
  ): Promise<void> {
71
71
  if (!isChatChannelEnabled(context, "qq")) return;
72
- context.logger.info("QQ channel enabled");
72
+ context.logger.info("QQ chat platform enabled");
73
73
  const account = resolveChannelAccount(context, "qq");
74
74
  const appId = String(account?.appId || "").trim();
75
75
  const appSecret = String(account?.appSecret || "").trim();
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - chat plugin prompt 与 channel prompt 都属于静态资产。
6
- * - 当前请求只注入当前 channel 的 prompt,避免平台规则串味。
6
+ * - 当前请求只注入当前 chat platform 的 prompt,避免平台规则串味。
7
7
  * - 该模块只负责 prompt 解析与拼装,不承担运行态控制职责。
8
8
  */
9
9
  import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
@@ -38,7 +38,7 @@ function resolveCurrentChatPromptChannel(
38
38
  *
39
39
  * 关键点(中文)
40
40
  * - 仅注入当前 context 对应的 channel prompt,避免把其他平台规则混入本轮会话。
41
- * - 若当前 context 不是 chat channel(如 consoleui)或尚无路由元信息,则不注入 channel prompt。
41
+ * - 若当前 context 不是 chat platform(如 Console UI)或尚无路由元信息,则不注入 platform prompt。
42
42
  */
43
43
  export async function buildCurrentChannelPrompts(
44
44
  context: AgentContext,
@@ -22,7 +22,7 @@ export const CHAT_PLUGIN_PROMPT = chatPluginPromptText.trim();
22
22
  export const FEISHU_CHAT_CHANNEL_PROMPT = feishuChatPromptText.trim();
23
23
 
24
24
  /**
25
- * QQ channel prompt。
25
+ * QQ chat platform prompt。
26
26
  */
27
27
  export const QQ_CHAT_CHANNEL_PROMPT = qqChatPromptText.trim();
28
28
 
@@ -44,7 +44,6 @@ type TurnObservation = {
44
44
  turnId: string;
45
45
  sessionId: string;
46
46
  messageId?: string;
47
- assistantStepDispatched: boolean;
48
47
  typing: { stop: () => void };
49
48
  };
50
49
 
@@ -342,13 +341,18 @@ export class ChatQueueWorker {
342
341
  if (event.visibility === "internal") return;
343
342
  const stepText = String(event.text || "").trim();
344
343
  if (!stepText) return;
345
- const dispatched = await this.dispatchAssistantStepMessage({
346
- sessionId: observation.sessionId,
347
- text: stepText,
348
- messageId: observation.messageId,
349
- });
350
- if (dispatched) {
351
- observation.assistantStepDispatched = true;
344
+
345
+ try {
346
+ await this.dispatchAssistantStepMessage({
347
+ sessionId: observation.sessionId,
348
+ text: stepText,
349
+ messageId: observation.messageId,
350
+ });
351
+ } catch (error) {
352
+ this.logger.warn("ChatQueueWorker assistant step dispatch failed", {
353
+ sessionId: observation.sessionId,
354
+ error: String(error),
355
+ });
352
356
  }
353
357
  }
354
358
 
@@ -369,7 +373,6 @@ export class ChatQueueWorker {
369
373
  turnId: turn.id,
370
374
  sessionId: item.sessionId,
371
375
  messageId: item.messageId,
372
- assistantStepDispatched: false,
373
376
  typing: this.startTypingHeartbeat(item),
374
377
  };
375
378
  params.lane.turnObservers.set(turn.id, observation);
@@ -437,36 +440,6 @@ export class ChatQueueWorker {
437
440
  });
438
441
  return;
439
442
  }
440
-
441
- if (observation.assistantStepDispatched) {
442
- return;
443
- }
444
-
445
- const finalAssistantText =
446
- pickLastSuccessfulChatSendText(result.assistantMessage) || result.text;
447
- if (!finalAssistantText) {
448
- return;
449
- }
450
-
451
- const dispatchedDirectly = await dispatchAssistantTextDirect({
452
- logger: this.logger,
453
- context: this.context,
454
- sessionId: observation.sessionId,
455
- assistantText: finalAssistantText,
456
- phase: "final",
457
- });
458
- if (dispatchedDirectly) {
459
- return;
460
- }
461
-
462
- await dispatchTextToChannel({
463
- logger: this.logger,
464
- context: this.context,
465
- sessionId: observation.sessionId,
466
- text: finalAssistantText,
467
- messageId: observation.messageId,
468
- phase: "final",
469
- });
470
443
  }
471
444
 
472
445
  /**
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 将“凭据 -> bot 基础信息”的探测输入输出结构标准化。
6
- * - Console、Channel Account 存储、后续自动化流程都复用该结构。
6
+ * - Console、Chat Account 存储、后续自动化流程都复用该结构。
7
7
  */
8
8
 
9
9
  import type { ChatChannelName } from "@/chat/types/ChannelStatus.js";
@@ -77,7 +77,7 @@ export interface ChatBotInfoResult {
77
77
  */
78
78
  botUserId?: string;
79
79
  /**
80
- * 建议用于生成 channel account id 的稳定种子。
80
+ * 建议用于生成 chat account id 的稳定种子。
81
81
  */
82
82
  idSeed?: string;
83
83
  /**
@@ -1,24 +1,24 @@
1
1
  /**
2
- * Chat channel account 管理类型。
2
+ * Chat account 管理类型。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 这些类型描述 agent 运行时内部的 chat channel account 管理输入输出。
5
+ * - 这些类型描述 agent 运行时内部的 chat account 管理输入输出。
6
6
  * - 凭据明文只允许出现在写入输入中,读取结果必须是脱敏后的安全视图。
7
7
  */
8
8
 
9
9
  import type { StoredChannelAccountChannel } from "@downcity/agent/internal/types/platform/Store.js";
10
10
 
11
11
  /**
12
- * 支持的 chat channel account 类型。
12
+ * 支持的 chat account 平台类型。
13
13
  */
14
14
  export type ChatChannelAccountChannel = StoredChannelAccountChannel;
15
15
 
16
16
  /**
17
- * Channel account 探测结果。
17
+ * Chat account 探测结果。
18
18
  */
19
19
  export interface ChatChannelAccountProbeResult {
20
20
  /**
21
- * 账号所属 chat channel
21
+ * 账号所属 chat platform
22
22
  */
23
23
  channel: ChatChannelAccountChannel;
24
24
  /**
@@ -52,7 +52,7 @@ export interface ChatChannelAccountProbeResult {
52
52
  }
53
53
 
54
54
  /**
55
- * Channel account 列表中的安全视图。
55
+ * Chat account 列表中的安全视图。
56
56
  */
57
57
  export interface ChatChannelAccountListItem {
58
58
  /**
@@ -60,7 +60,7 @@ export interface ChatChannelAccountListItem {
60
60
  */
61
61
  id: string;
62
62
  /**
63
- * 账号所属 chat channel
63
+ * 账号所属 chat platform
64
64
  */
65
65
  channel: ChatChannelAccountChannel;
66
66
  /**
@@ -122,7 +122,7 @@ export interface ChatChannelAccountListItem {
122
122
  }
123
123
 
124
124
  /**
125
- * Channel account 列表结果。
125
+ * Chat account 列表结果。
126
126
  */
127
127
  export interface ChatChannelAccountListResult {
128
128
  /**
@@ -132,7 +132,7 @@ export interface ChatChannelAccountListResult {
132
132
  }
133
133
 
134
134
  /**
135
- * Channel account 写入输入。
135
+ * Chat account 写入输入。
136
136
  */
137
137
  export interface ChatChannelAccountUpsertInput {
138
138
  /**
@@ -140,7 +140,7 @@ export interface ChatChannelAccountUpsertInput {
140
140
  */
141
141
  id: string;
142
142
  /**
143
- * 账号所属 chat channel
143
+ * 账号所属 chat platform
144
144
  */
145
145
  channel: string;
146
146
  /**
@@ -194,11 +194,11 @@ export interface ChatChannelAccountUpsertInput {
194
194
  }
195
195
 
196
196
  /**
197
- * Channel account 凭据创建输入。
197
+ * Chat account 凭据创建输入。
198
198
  */
199
199
  export interface ChatChannelAccountCreateInput {
200
200
  /**
201
- * 账号所属 chat channel
201
+ * 账号所属 chat platform
202
202
  */
203
203
  channel: string;
204
204
  /**
@@ -70,7 +70,7 @@ export interface ChatChannelConfigurationField {
70
70
  */
71
71
  type: ChatChannelConfigurationFieldType;
72
72
  /**
73
- * 字段值来源(downcity.json / channel account / env fallback)。
73
+ * 字段值来源(downcity.json / chat account / env fallback)。
74
74
  */
75
75
  source: ChatChannelConfigurationFieldSource;
76
76
  /**
@@ -132,7 +132,7 @@ export interface ChatChannelConfigurationDescriptor {
132
132
  */
133
133
  canToggleEnabled: boolean;
134
134
  /**
135
- * 是否支持 channel account 绑定。
135
+ * 是否支持 chat account 绑定。
136
136
  */
137
137
  canBindChannelAccount: boolean;
138
138
  /**
@@ -158,4 +158,3 @@ export interface ChatChannelConfigurationDescriptor {
158
158
  envFallback: ChatChannelConfigurationField[];
159
159
  };
160
160
  }
161
-
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * 关键点(中文)
5
5
  * - 统一描述飞书 `msg_type=post` 的核心结构,供入站解析与出站构建复用。
6
- * - 这里只保留当前 chat channel 真正会消费的字段,避免把平台超大 schema 整体引入运行时。
6
+ * - 这里只保留当前 chat platform 真正会消费的字段,避免把平台超大 schema 整体引入运行时。
7
7
  */
8
8
 
9
9
  /**