@sunnoy/wecom 2.2.1 → 2.3.0
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/README.md +2 -1
- package/index.js +11 -2
- package/openclaw.plugin.json +137 -1
- package/package.json +2 -3
- package/wecom/accounts.js +2 -0
- package/wecom/callback-inbound.js +9 -5
- package/wecom/channel-plugin.js +65 -1
- package/wecom/constants.js +14 -7
- package/wecom/image-studio-tool.js +764 -0
- package/wecom/parent-resolver.js +26 -0
- package/wecom/plugin-config.js +484 -0
- package/wecom/welcome-messages-file.js +155 -0
- package/wecom/workspace-template.js +40 -4
- package/wecom/ws-monitor.js +73 -8
package/README.md
CHANGED
|
@@ -180,7 +180,8 @@ npm test
|
|
|
180
180
|
| `channels.wecom.secret` | string | 是 | 企业微信 AI 机器人 Secret |
|
|
181
181
|
| `channels.wecom.websocketUrl` | string | 否 | WS 地址,默认 `wss://openws.work.weixin.qq.com` |
|
|
182
182
|
| `channels.wecom.sendThinkingMessage` | boolean | 否 | 是否先发送 `<think></think>` 占位,默认 `true` |
|
|
183
|
-
| `channels.wecom.welcomeMessage` | string | 否 |
|
|
183
|
+
| `channels.wecom.welcomeMessage` | string | 否 | 进入会话欢迎语(非空时固定使用该字符串) |
|
|
184
|
+
| `channels.wecom.welcomeMessagesFile` | string | 否 | 欢迎语列表文件路径。支持:`{ "messages": [ ... ] }` 或顶层数组;每条欢迎语可为**一行一个字符串的数组**(推荐,易读),或单条字符串(可含 `\\n`)。相对路径基于 OpenClaw 状态目录(`~/.openclaw` 或 `OPENCLAW_STATE_DIR`)。未设置 `welcomeMessage` 时从该文件随机选取;**修改文件后无需重启服务**(按 mtime 自动重读) |
|
|
184
185
|
| `channels.wecom.adminUsers` | string[] | 否 | 管理员用户 ID,可绕过命令白名单 |
|
|
185
186
|
| `channels.wecom.defaultAccount` | string | 否 | 多账号模式默认账号 |
|
|
186
187
|
|
package/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
|
|
2
1
|
import { logger } from "./logger.js";
|
|
3
2
|
import { wecomChannelPlugin } from "./wecom/channel-plugin.js";
|
|
4
3
|
import { createWeComMcpTool } from "./wecom/mcp-tool.js";
|
|
4
|
+
import { createImageStudioTool } from "./wecom/image-studio-tool.js";
|
|
5
|
+
import { resolveQwenImageToolsConfig, wecomPluginConfigSchema } from "./wecom/plugin-config.js";
|
|
5
6
|
import { setOpenclawConfig, setRuntime } from "./wecom/state.js";
|
|
6
7
|
import { buildReplyMediaGuidance } from "./wecom/ws-monitor.js";
|
|
7
8
|
import { listAccountIds, resolveAccount } from "./wecom/accounts.js";
|
|
@@ -11,7 +12,7 @@ const plugin = {
|
|
|
11
12
|
id: "wecom",
|
|
12
13
|
name: "Enterprise WeChat",
|
|
13
14
|
description: "Enterprise WeChat AI Bot channel plugin for OpenClaw",
|
|
14
|
-
configSchema:
|
|
15
|
+
configSchema: wecomPluginConfigSchema,
|
|
15
16
|
register(api) {
|
|
16
17
|
logger.info("Registering WeCom WS plugin");
|
|
17
18
|
setRuntime(api.runtime);
|
|
@@ -19,6 +20,14 @@ const plugin = {
|
|
|
19
20
|
api.registerChannel({ plugin: wecomChannelPlugin });
|
|
20
21
|
api.registerTool(createWeComMcpTool(), { name: "wecom_mcp" });
|
|
21
22
|
|
|
23
|
+
const qwenImageToolsConfig = resolveQwenImageToolsConfig(api.pluginConfig);
|
|
24
|
+
if (qwenImageToolsConfig.enabled) {
|
|
25
|
+
api.registerTool(createImageStudioTool(qwenImageToolsConfig), { name: "image_studio" });
|
|
26
|
+
logger.info(
|
|
27
|
+
`[image_studio] Registered with provider "${qwenImageToolsConfig.provider}" using qwen(generate=${qwenImageToolsConfig.models.qwen.generate}, edit=${qwenImageToolsConfig.models.qwen.edit}) wan(generate=${qwenImageToolsConfig.models.wan.generate}, edit=${qwenImageToolsConfig.models.wan.edit})`,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
22
31
|
// Register HTTP callback endpoints for all accounts that have callback config
|
|
23
32
|
for (const accountId of listAccountIds(api.config)) {
|
|
24
33
|
const account = resolveAccount(api.config, accountId);
|
package/openclaw.plugin.json
CHANGED
|
@@ -8,7 +8,143 @@
|
|
|
8
8
|
"configSchema": {
|
|
9
9
|
"type": "object",
|
|
10
10
|
"additionalProperties": true,
|
|
11
|
-
"properties": {
|
|
11
|
+
"properties": {
|
|
12
|
+
"qwenImageTools": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"additionalProperties": false,
|
|
15
|
+
"properties": {
|
|
16
|
+
"enabled": {
|
|
17
|
+
"type": "boolean"
|
|
18
|
+
},
|
|
19
|
+
"provider": {
|
|
20
|
+
"type": "string"
|
|
21
|
+
},
|
|
22
|
+
"route": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"enum": [
|
|
25
|
+
"auto",
|
|
26
|
+
"qwen",
|
|
27
|
+
"wan"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"endpoint": {
|
|
31
|
+
"type": "string"
|
|
32
|
+
},
|
|
33
|
+
"endpoints": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"additionalProperties": false,
|
|
36
|
+
"properties": {
|
|
37
|
+
"qwen": {
|
|
38
|
+
"type": "string"
|
|
39
|
+
},
|
|
40
|
+
"wan": {
|
|
41
|
+
"type": "string"
|
|
42
|
+
},
|
|
43
|
+
"task": {
|
|
44
|
+
"type": "string"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"timeoutMs": {
|
|
49
|
+
"type": "integer",
|
|
50
|
+
"minimum": 1000
|
|
51
|
+
},
|
|
52
|
+
"models": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"additionalProperties": false,
|
|
55
|
+
"properties": {
|
|
56
|
+
"generate": {
|
|
57
|
+
"type": "string"
|
|
58
|
+
},
|
|
59
|
+
"edit": {
|
|
60
|
+
"type": "string"
|
|
61
|
+
},
|
|
62
|
+
"qwen": {
|
|
63
|
+
"type": "object",
|
|
64
|
+
"additionalProperties": false,
|
|
65
|
+
"properties": {
|
|
66
|
+
"generate": {
|
|
67
|
+
"type": "string"
|
|
68
|
+
},
|
|
69
|
+
"edit": {
|
|
70
|
+
"type": "string"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"wan": {
|
|
75
|
+
"type": "object",
|
|
76
|
+
"additionalProperties": false,
|
|
77
|
+
"properties": {
|
|
78
|
+
"generate": {
|
|
79
|
+
"type": "string"
|
|
80
|
+
},
|
|
81
|
+
"edit": {
|
|
82
|
+
"type": "string"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"defaults": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"additionalProperties": false,
|
|
91
|
+
"properties": {
|
|
92
|
+
"size": {
|
|
93
|
+
"type": "string"
|
|
94
|
+
},
|
|
95
|
+
"aspect": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"enum": [
|
|
98
|
+
"landscape",
|
|
99
|
+
"square",
|
|
100
|
+
"portrait"
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
"n": {
|
|
104
|
+
"type": "integer",
|
|
105
|
+
"minimum": 1
|
|
106
|
+
},
|
|
107
|
+
"watermark": {
|
|
108
|
+
"type": "boolean"
|
|
109
|
+
},
|
|
110
|
+
"promptExtend": {
|
|
111
|
+
"type": "boolean"
|
|
112
|
+
},
|
|
113
|
+
"qwen": {
|
|
114
|
+
"type": "object",
|
|
115
|
+
"additionalProperties": false,
|
|
116
|
+
"properties": {
|
|
117
|
+
"landscape": {
|
|
118
|
+
"type": "string"
|
|
119
|
+
},
|
|
120
|
+
"square": {
|
|
121
|
+
"type": "string"
|
|
122
|
+
},
|
|
123
|
+
"portrait": {
|
|
124
|
+
"type": "string"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"wan": {
|
|
129
|
+
"type": "object",
|
|
130
|
+
"additionalProperties": false,
|
|
131
|
+
"properties": {
|
|
132
|
+
"landscape": {
|
|
133
|
+
"type": "string"
|
|
134
|
+
},
|
|
135
|
+
"square": {
|
|
136
|
+
"type": "string"
|
|
137
|
+
},
|
|
138
|
+
"portrait": {
|
|
139
|
+
"type": "string"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
12
148
|
},
|
|
13
149
|
"channels": [
|
|
14
150
|
"wecom"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sunnoy/wecom",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Enterprise WeChat AI Bot channel plugin for OpenClaw",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
"index.js",
|
|
9
9
|
"wecom",
|
|
10
10
|
"dynamic-agent.js",
|
|
11
|
-
|
|
12
11
|
"logger.js",
|
|
13
12
|
"README.md",
|
|
14
13
|
"LICENSE",
|
|
@@ -60,7 +59,7 @@
|
|
|
60
59
|
"author": "",
|
|
61
60
|
"license": "ISC",
|
|
62
61
|
"dependencies": {
|
|
63
|
-
"@wecom/aibot-node-sdk": "^1.0.
|
|
62
|
+
"@wecom/aibot-node-sdk": "^1.0.3",
|
|
64
63
|
"file-type": "^21.3.0"
|
|
65
64
|
}
|
|
66
65
|
}
|
package/wecom/accounts.js
CHANGED
|
@@ -9,6 +9,7 @@ const RESERVED_KEYS = new Set([
|
|
|
9
9
|
"websocketUrl",
|
|
10
10
|
"sendThinkingMessage",
|
|
11
11
|
"welcomeMessage",
|
|
12
|
+
"welcomeMessagesFile",
|
|
12
13
|
"allowFrom",
|
|
13
14
|
"dmPolicy",
|
|
14
15
|
"groupPolicy",
|
|
@@ -32,6 +33,7 @@ const SHARED_MULTI_ACCOUNT_KEYS = new Set([
|
|
|
32
33
|
"websocketUrl",
|
|
33
34
|
"sendThinkingMessage",
|
|
34
35
|
"welcomeMessage",
|
|
36
|
+
"welcomeMessagesFile",
|
|
35
37
|
"allowFrom",
|
|
36
38
|
"dmPolicy",
|
|
37
39
|
"groupPolicy",
|
|
@@ -321,10 +321,6 @@ async function processCallbackMessage({ parsedMsg, account, config, runtime }) {
|
|
|
321
321
|
? generateAgentId(peerKind, peerId, account.accountId)
|
|
322
322
|
: null;
|
|
323
323
|
|
|
324
|
-
if (dynamicAgentId) {
|
|
325
|
-
await ensureDynamicAgentListed(dynamicAgentId, account.config.workspaceTemplate);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
324
|
const route = core.routing.resolveAgentRoute({
|
|
329
325
|
cfg: config,
|
|
330
326
|
channel: CHANNEL_ID,
|
|
@@ -337,9 +333,17 @@ async function processCallbackMessage({ parsedMsg, account, config, runtime }) {
|
|
|
337
333
|
config.bindings.some(
|
|
338
334
|
(b) => b.match?.channel === CHANNEL_ID && b.match?.accountId === account.accountId,
|
|
339
335
|
);
|
|
336
|
+
|
|
340
337
|
if (dynamicAgentId && !hasExplicitBinding) {
|
|
338
|
+
const routeAgentId = route.agentId;
|
|
339
|
+
// Use the account's configured agentId as the base for property inheritance
|
|
340
|
+
// (model, subagents, tools). route.agentId may resolve to "main" when
|
|
341
|
+
// there is no explicit binding, but the account's agentId points to the
|
|
342
|
+
// actual parent agent whose properties the dynamic agent should inherit.
|
|
343
|
+
const baseAgentId = account.config.agentId || routeAgentId;
|
|
344
|
+
await ensureDynamicAgentListed(dynamicAgentId, account.config.workspaceTemplate, baseAgentId);
|
|
345
|
+
route.sessionKey = route.sessionKey.replace(`agent:${routeAgentId}:`, `agent:${dynamicAgentId}:`);
|
|
341
346
|
route.agentId = dynamicAgentId;
|
|
342
|
-
route.sessionKey = `agent:${dynamicAgentId}:${peerKind}:${peerId}`;
|
|
343
347
|
}
|
|
344
348
|
|
|
345
349
|
// Build a body object that mirrors the WS frame.body structure expected by
|
package/wecom/channel-plugin.js
CHANGED
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
} from "./constants.js";
|
|
37
37
|
import { uploadAndSendMedia } from "./media-uploader.js";
|
|
38
38
|
import { getExtendedMediaLocalRoots } from "./openclaw-compat.js";
|
|
39
|
+
import { extractParentAgentId } from "./parent-resolver.js";
|
|
39
40
|
import { sendWsMessage, startWsMonitor } from "./ws-monitor.js";
|
|
40
41
|
import { getWsClient } from "./ws-state.js";
|
|
41
42
|
|
|
@@ -262,6 +263,7 @@ export const wecomChannelPlugin = {
|
|
|
262
263
|
websocketUrl: { type: "string" },
|
|
263
264
|
sendThinkingMessage: { type: "boolean" },
|
|
264
265
|
welcomeMessage: { type: "string" },
|
|
266
|
+
welcomeMessagesFile: { type: "string" },
|
|
265
267
|
dmPolicy: { enum: ["pairing", "allowlist", "open", "disabled"] },
|
|
266
268
|
allowFrom: { type: "array", items: { type: "string" } },
|
|
267
269
|
groupPolicy: { enum: ["open", "allowlist", "disabled"] },
|
|
@@ -291,6 +293,10 @@ export const wecomChannelPlugin = {
|
|
|
291
293
|
secret: { label: "Secret", sensitive: true },
|
|
292
294
|
websocketUrl: { label: "WebSocket URL", placeholder: DEFAULT_WS_URL },
|
|
293
295
|
welcomeMessage: { label: "Welcome Message" },
|
|
296
|
+
welcomeMessagesFile: {
|
|
297
|
+
label: "Welcome Messages File",
|
|
298
|
+
placeholder: "welcome-messages.json",
|
|
299
|
+
},
|
|
294
300
|
"agent.corpSecret": { sensitive: true, label: "Application Secret" },
|
|
295
301
|
"agent.replyFormat": { label: "Reply Format", placeholder: "text" },
|
|
296
302
|
"agent.callback.token": { label: "Callback Token" },
|
|
@@ -404,6 +410,7 @@ export const wecomChannelPlugin = {
|
|
|
404
410
|
try {
|
|
405
411
|
if (!target.toParty && !target.toTag) {
|
|
406
412
|
const wsTarget = target.chatId || target.toUser || to;
|
|
413
|
+
logger.debug(`[wecom] sendText: trying WS accountId=${resolvedAccountId} target=${wsTarget}`);
|
|
407
414
|
return await sendWsMessage({
|
|
408
415
|
to: wsTarget,
|
|
409
416
|
content: text,
|
|
@@ -411,9 +418,17 @@ export const wecomChannelPlugin = {
|
|
|
411
418
|
});
|
|
412
419
|
}
|
|
413
420
|
} catch (error) {
|
|
414
|
-
logger.warn(`[wecom] WS sendText failed, falling back
|
|
421
|
+
logger.warn(`[wecom] WS sendText failed (accountId=${resolvedAccountId}), falling back: ${error.message}`);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Webhook fallback for accounts without Agent API (e.g. WS bot mode)
|
|
425
|
+
const account = resolveAccount(cfg, resolvedAccountId);
|
|
426
|
+
if (!account?.agentCredentials && account?.config?.webhooks?.default) {
|
|
427
|
+
logger.debug(`[wecom] sendText: Agent API unavailable, using webhook fallback accountId=${resolvedAccountId}`);
|
|
428
|
+
return sendViaWebhook({ cfg, accountId: resolvedAccountId, webhookName: "default", text });
|
|
415
429
|
}
|
|
416
430
|
|
|
431
|
+
logger.debug(`[wecom] sendText: trying Agent API accountId=${resolvedAccountId}`);
|
|
417
432
|
return sendViaAgent({
|
|
418
433
|
cfg,
|
|
419
434
|
accountId: resolvedAccountId,
|
|
@@ -631,6 +646,55 @@ export const wecomChannelPlugin = {
|
|
|
631
646
|
};
|
|
632
647
|
},
|
|
633
648
|
},
|
|
649
|
+
hooks: {
|
|
650
|
+
/**
|
|
651
|
+
* Ensure announce delivery uses a valid WeCom channel accountId.
|
|
652
|
+
*
|
|
653
|
+
* When a dynamic agent (e.g. wecom-yoyo-dm-xxx) spawns a sub-agent,
|
|
654
|
+
* the announce delivery may reference the dynamic agent ID as accountId.
|
|
655
|
+
* This hook resolves it to the actual WeCom account (e.g. yoyo) so the
|
|
656
|
+
* outbound sendText can find valid WS/Agent API credentials.
|
|
657
|
+
*/
|
|
658
|
+
subagent_delivery_target: async (event, ctx) => {
|
|
659
|
+
const origin = event.requesterOrigin;
|
|
660
|
+
if (!origin?.channel || origin.channel !== CHANNEL_ID) return;
|
|
661
|
+
|
|
662
|
+
const cfg = ctx?.cfg ?? getOpenclawConfig();
|
|
663
|
+
|
|
664
|
+
// Check whether current accountId already resolves to a valid account
|
|
665
|
+
const currentAccount = resolveAccount(cfg, origin.accountId);
|
|
666
|
+
if (currentAccount?.enabled) return;
|
|
667
|
+
|
|
668
|
+
// Try to extract the base account from a dynamic agent ID
|
|
669
|
+
const baseId = extractParentAgentId(origin.accountId);
|
|
670
|
+
if (baseId && baseId !== origin.accountId) {
|
|
671
|
+
const baseAccount = resolveAccount(cfg, baseId);
|
|
672
|
+
if (baseAccount?.enabled) {
|
|
673
|
+
logger.info(`[wecom] subagent_delivery_target: ${origin.accountId} → ${baseId}`);
|
|
674
|
+
return { origin: { ...origin, accountId: baseId } };
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// Fallback to default account
|
|
679
|
+
const defaultId = resolveDefaultAccountId(cfg);
|
|
680
|
+
if (defaultId && defaultId !== origin.accountId) {
|
|
681
|
+
logger.info(`[wecom] subagent_delivery_target: fallback → ${defaultId}`);
|
|
682
|
+
return { origin: { ...origin, accountId: defaultId } };
|
|
683
|
+
}
|
|
684
|
+
},
|
|
685
|
+
|
|
686
|
+
subagent_spawned: async (event) => {
|
|
687
|
+
logger.info(
|
|
688
|
+
`[wecom] subagent spawned: child=${event.childSessionKey} requester=${event.requesterSessionKey}`,
|
|
689
|
+
);
|
|
690
|
+
},
|
|
691
|
+
|
|
692
|
+
subagent_ended: async (event) => {
|
|
693
|
+
logger.info(
|
|
694
|
+
`[wecom] subagent ended: target=${event.targetSessionKey} reason=${event.reason} outcome=${event.outcome}`,
|
|
695
|
+
);
|
|
696
|
+
},
|
|
697
|
+
},
|
|
634
698
|
};
|
|
635
699
|
|
|
636
700
|
export const wecomChannelPluginTesting = {};
|
package/wecom/constants.js
CHANGED
|
@@ -47,7 +47,8 @@ export const DEFAULT_WELCOME_MESSAGES = [
|
|
|
47
47
|
"/compact 压缩对话",
|
|
48
48
|
"/help 帮助",
|
|
49
49
|
"/status 查看状态",
|
|
50
|
-
"
|
|
50
|
+
"你可以让我生成和编辑图片了",
|
|
51
|
+
"你可以用语音跟我对话",
|
|
51
52
|
].join("\n"),
|
|
52
53
|
[
|
|
53
54
|
"终于唤醒我啦,我已经准备就绪!😄",
|
|
@@ -57,7 +58,8 @@ export const DEFAULT_WELCOME_MESSAGES = [
|
|
|
57
58
|
"/compact 压缩对话",
|
|
58
59
|
"/help 帮助",
|
|
59
60
|
"/status 查看状态",
|
|
60
|
-
"
|
|
61
|
+
"你可以让我生成和编辑图片了",
|
|
62
|
+
"你可以用语音跟我对话",
|
|
61
63
|
].join("\n"),
|
|
62
64
|
[
|
|
63
65
|
"欢迎回来,准备开始今天的工作吧!✨",
|
|
@@ -67,7 +69,8 @@ export const DEFAULT_WELCOME_MESSAGES = [
|
|
|
67
69
|
"/compact 压缩对话",
|
|
68
70
|
"/help 帮助",
|
|
69
71
|
"/status 查看状态",
|
|
70
|
-
"
|
|
72
|
+
"你可以让我生成和编辑图片了",
|
|
73
|
+
"你可以用语音跟我对话",
|
|
71
74
|
].join("\n"),
|
|
72
75
|
[
|
|
73
76
|
"嗨,我已经在线!🤖",
|
|
@@ -77,7 +80,8 @@ export const DEFAULT_WELCOME_MESSAGES = [
|
|
|
77
80
|
"/compact 压缩对话",
|
|
78
81
|
"/help 帮助",
|
|
79
82
|
"/status 查看状态",
|
|
80
|
-
"
|
|
83
|
+
"你可以让我生成和编辑图片了",
|
|
84
|
+
"你可以用语音跟我对话",
|
|
81
85
|
].join("\n"),
|
|
82
86
|
[
|
|
83
87
|
"今天也一起高效开工吧!🚀",
|
|
@@ -87,7 +91,8 @@ export const DEFAULT_WELCOME_MESSAGES = [
|
|
|
87
91
|
"/compact 压缩对话",
|
|
88
92
|
"/help 帮助",
|
|
89
93
|
"/status 查看状态",
|
|
90
|
-
"
|
|
94
|
+
"你可以让我生成和编辑图片了",
|
|
95
|
+
"你可以用语音跟我对话",
|
|
91
96
|
].join("\n"),
|
|
92
97
|
[
|
|
93
98
|
"叮咚,你的数字助手已就位!🎉",
|
|
@@ -97,7 +102,8 @@ export const DEFAULT_WELCOME_MESSAGES = [
|
|
|
97
102
|
"/compact 压缩对话",
|
|
98
103
|
"/help 帮助",
|
|
99
104
|
"/status 查看状态",
|
|
100
|
-
"
|
|
105
|
+
"你可以让我生成和编辑图片了",
|
|
106
|
+
"你可以用语音跟我对话",
|
|
101
107
|
].join("\n"),
|
|
102
108
|
[
|
|
103
109
|
"灵感加载完成,随时可以开聊!💡",
|
|
@@ -107,7 +113,8 @@ export const DEFAULT_WELCOME_MESSAGES = [
|
|
|
107
113
|
"/compact 压缩对话",
|
|
108
114
|
"/help 帮助",
|
|
109
115
|
"/status 查看状态",
|
|
110
|
-
"
|
|
116
|
+
"你可以让我生成和编辑图片了",
|
|
117
|
+
"你可以用语音跟我对话",
|
|
111
118
|
].join("\n"),
|
|
112
119
|
];
|
|
113
120
|
export const DEFAULT_WELCOME_MESSAGE = DEFAULT_WELCOME_MESSAGES[0];
|