@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.
- package/bin/auth/Plugin.js +2 -2
- package/bin/auth/Plugin.js.map +1 -1
- package/bin/chat/accounts/ChannelAccountManager.d.ts +3 -3
- package/bin/chat/accounts/ChannelAccountManager.js +6 -6
- package/bin/chat/accounts/ChannelAccountManager.js.map +1 -1
- package/bin/chat/accounts/Crypto.d.ts +1 -1
- package/bin/chat/accounts/Crypto.js +1 -1
- package/bin/chat/accounts/Store.d.ts +8 -8
- package/bin/chat/accounts/Store.js +13 -13
- package/bin/chat/accounts/Store.js.map +1 -1
- package/bin/chat/channels/feishu/Configuration.d.ts +1 -1
- package/bin/chat/channels/feishu/Configuration.js +5 -5
- package/bin/chat/channels/feishu/Configuration.js.map +1 -1
- package/bin/chat/channels/qq/Configuration.d.ts +1 -1
- package/bin/chat/channels/qq/Configuration.js +5 -5
- package/bin/chat/channels/qq/Configuration.js.map +1 -1
- package/bin/chat/channels/telegram/ApiClient.d.ts +12 -0
- package/bin/chat/channels/telegram/ApiClient.d.ts.map +1 -1
- package/bin/chat/channels/telegram/ApiClient.js +57 -4
- package/bin/chat/channels/telegram/ApiClient.js.map +1 -1
- package/bin/chat/channels/telegram/BotInfo.d.ts +1 -1
- package/bin/chat/channels/telegram/BotInfo.js +1 -1
- package/bin/chat/channels/telegram/Configuration.d.ts +1 -1
- package/bin/chat/channels/telegram/Configuration.js +5 -5
- package/bin/chat/channels/telegram/Configuration.js.map +1 -1
- package/bin/chat/runtime/ChatChannelCore.d.ts +1 -1
- package/bin/chat/runtime/ChatChannelCore.js +1 -1
- package/bin/chat/runtime/ChatChannelLifecycle.js +1 -1
- package/bin/chat/runtime/ChatChannelLifecycle.js.map +1 -1
- package/bin/chat/runtime/ChatPluginSystem.d.ts +2 -2
- package/bin/chat/runtime/ChatPluginSystem.js +1 -1
- package/bin/chat/runtime/ChatPromptAssets.d.ts +1 -1
- package/bin/chat/runtime/ChatPromptAssets.js +1 -1
- package/bin/chat/runtime/ChatQueueWorker.d.ts.map +1 -1
- package/bin/chat/runtime/ChatQueueWorker.js +12 -33
- package/bin/chat/runtime/ChatQueueWorker.js.map +1 -1
- package/bin/chat/types/BotInfo.d.ts +2 -2
- package/bin/chat/types/BotInfo.js +1 -1
- package/bin/chat/types/ChannelAccount.d.ts +12 -12
- package/bin/chat/types/ChannelAccount.js +2 -2
- package/bin/chat/types/ChannelConfiguration.d.ts +2 -2
- package/bin/chat/types/FeishuPost.d.ts +1 -1
- package/bin/chat/types/FeishuPost.js +1 -1
- package/package.json +2 -2
- package/src/auth/Plugin.ts +2 -2
- package/src/chat/accounts/ChannelAccountManager.ts +6 -6
- package/src/chat/accounts/Crypto.ts +1 -1
- package/src/chat/accounts/Store.ts +13 -13
- package/src/chat/channels/feishu/Configuration.ts +5 -5
- package/src/chat/channels/qq/Configuration.ts +5 -5
- package/src/chat/channels/telegram/ApiClient.ts +71 -4
- package/src/chat/channels/telegram/BotInfo.ts +1 -1
- package/src/chat/channels/telegram/Configuration.ts +5 -5
- package/src/chat/runtime/ChatChannelCore.ts +1 -1
- package/src/chat/runtime/ChatChannelLifecycle.ts +1 -1
- package/src/chat/runtime/ChatPluginSystem.ts +2 -2
- package/src/chat/runtime/ChatPromptAssets.ts +1 -1
- package/src/chat/runtime/ChatQueueWorker.ts +12 -39
- package/src/chat/types/BotInfo.ts +2 -2
- package/src/chat/types/ChannelAccount.ts +12 -12
- package/src/chat/types/ChannelConfiguration.ts +2 -3
- package/src/chat/types/FeishuPost.ts +1 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Chat account 默认存储实现。
|
|
3
3
|
*
|
|
4
4
|
* 职责说明(中文)
|
|
5
|
-
* - 提供 `chat` plugin 默认使用的全局
|
|
5
|
+
* - 提供 `chat` plugin 默认使用的全局 chat account 读写能力。
|
|
6
6
|
* - 默认直接操作 `~/.downcity/downcity.db` 里的 `channel_accounts` 表。
|
|
7
7
|
* - 对 `city` 而言,这里也是统一的默认账号池实现来源。
|
|
8
8
|
*
|
|
9
9
|
* 边界说明(中文)
|
|
10
|
-
* - 这里只负责
|
|
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
|
-
* 规范化
|
|
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
|
|
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
|
-
* 同步列出全部
|
|
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 读取单个
|
|
181
|
+
* 同步按 ID 读取单个 chat account。
|
|
182
182
|
*/
|
|
183
183
|
export function getStoredChannelAccountSync(
|
|
184
184
|
accountIdInput: string,
|
|
185
185
|
): StoredChannelAccount | null {
|
|
186
|
-
const accountId = normalizeNonEmptyText(accountIdInput, "
|
|
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
|
-
* 新增或更新
|
|
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, "
|
|
213
|
+
const id = normalizeNonEmptyText(input.id, "chat account id");
|
|
214
214
|
const channel = normalizeChannelAccountChannel(input.channel);
|
|
215
|
-
const name = normalizeNonEmptyText(input.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
|
-
* 删除单个
|
|
278
|
+
* 删除单个 chat account。
|
|
279
279
|
*/
|
|
280
280
|
export async function removeStoredChannelAccount(
|
|
281
281
|
accountIdInput: string,
|
|
282
282
|
): Promise<void> {
|
|
283
|
-
const accountId = normalizeNonEmptyText(accountIdInput, "
|
|
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 由
|
|
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
|
|
21
|
+
title: "Feishu Chat Platform Configuration",
|
|
22
22
|
description:
|
|
23
|
-
"Bind a Feishu/Lark
|
|
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: "
|
|
48
|
+
label: "Chat Account ID",
|
|
49
49
|
description:
|
|
50
|
-
"Bind
|
|
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 等)在
|
|
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
|
|
21
|
+
title: "QQ Chat Platform Configuration",
|
|
22
22
|
description:
|
|
23
|
-
"Bind a QQ
|
|
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: "
|
|
47
|
+
label: "Chat Account ID",
|
|
48
48
|
description:
|
|
49
|
-
"Bind
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
* - ship 层只绑定 `enabled` 与 `channelAccountId`。
|
|
6
|
-
* - 真实密钥由
|
|
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
|
|
21
|
+
title: "Telegram Chat Platform Configuration",
|
|
22
22
|
description:
|
|
23
|
-
"Bind a Telegram
|
|
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: "
|
|
48
|
+
label: "Chat Account ID",
|
|
49
49
|
description:
|
|
50
|
-
"Bind
|
|
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
|
|
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
|
|
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
|
-
* - 当前请求只注入当前
|
|
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
|
|
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
|
|
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
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
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、
|
|
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
|
-
* 建议用于生成
|
|
80
|
+
* 建议用于生成 chat account id 的稳定种子。
|
|
81
81
|
*/
|
|
82
82
|
idSeed?: string;
|
|
83
83
|
/**
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Chat
|
|
2
|
+
* Chat account 管理类型。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* - 这些类型描述 agent 运行时内部的 chat
|
|
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
|
|
12
|
+
* 支持的 chat account 平台类型。
|
|
13
13
|
*/
|
|
14
14
|
export type ChatChannelAccountChannel = StoredChannelAccountChannel;
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Chat account 探测结果。
|
|
18
18
|
*/
|
|
19
19
|
export interface ChatChannelAccountProbeResult {
|
|
20
20
|
/**
|
|
21
|
-
* 账号所属 chat
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
197
|
+
* Chat account 凭据创建输入。
|
|
198
198
|
*/
|
|
199
199
|
export interface ChatChannelAccountCreateInput {
|
|
200
200
|
/**
|
|
201
|
-
* 账号所属 chat
|
|
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 /
|
|
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
|
-
* 是否支持
|
|
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
|
-
|