@ryantest/openclaw-qqbot 0.0.1

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 (197) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +483 -0
  3. package/README.zh.md +478 -0
  4. package/bin/qqbot-cli.js +243 -0
  5. package/clawdbot.plugin.json +16 -0
  6. package/dist/index.d.ts +17 -0
  7. package/dist/index.js +26 -0
  8. package/dist/src/admin-resolver.d.ts +27 -0
  9. package/dist/src/admin-resolver.js +122 -0
  10. package/dist/src/api.d.ts +156 -0
  11. package/dist/src/api.js +599 -0
  12. package/dist/src/channel.d.ts +11 -0
  13. package/dist/src/channel.js +354 -0
  14. package/dist/src/config.d.ts +25 -0
  15. package/dist/src/config.js +161 -0
  16. package/dist/src/credential-backup.d.ts +31 -0
  17. package/dist/src/credential-backup.js +66 -0
  18. package/dist/src/gateway.d.ts +18 -0
  19. package/dist/src/gateway.js +1265 -0
  20. package/dist/src/image-server.d.ts +68 -0
  21. package/dist/src/image-server.js +462 -0
  22. package/dist/src/inbound-attachments.d.ts +58 -0
  23. package/dist/src/inbound-attachments.js +234 -0
  24. package/dist/src/known-users.d.ts +100 -0
  25. package/dist/src/known-users.js +263 -0
  26. package/dist/src/message-queue.d.ts +50 -0
  27. package/dist/src/message-queue.js +115 -0
  28. package/dist/src/onboarding.d.ts +10 -0
  29. package/dist/src/onboarding.js +203 -0
  30. package/dist/src/outbound-deliver.d.ts +48 -0
  31. package/dist/src/outbound-deliver.js +462 -0
  32. package/dist/src/outbound.d.ts +203 -0
  33. package/dist/src/outbound.js +1102 -0
  34. package/dist/src/proactive.d.ts +170 -0
  35. package/dist/src/proactive.js +399 -0
  36. package/dist/src/ref-index-store.d.ts +70 -0
  37. package/dist/src/ref-index-store.js +273 -0
  38. package/dist/src/reply-dispatcher.d.ts +35 -0
  39. package/dist/src/reply-dispatcher.js +311 -0
  40. package/dist/src/runtime.d.ts +3 -0
  41. package/dist/src/runtime.js +10 -0
  42. package/dist/src/session-store.d.ts +52 -0
  43. package/dist/src/session-store.js +254 -0
  44. package/dist/src/slash-commands.d.ts +71 -0
  45. package/dist/src/slash-commands.js +1179 -0
  46. package/dist/src/startup-greeting.d.ts +30 -0
  47. package/dist/src/startup-greeting.js +78 -0
  48. package/dist/src/stt.d.ts +21 -0
  49. package/dist/src/stt.js +70 -0
  50. package/dist/src/tools/channel.d.ts +16 -0
  51. package/dist/src/tools/channel.js +234 -0
  52. package/dist/src/tools/remind.d.ts +2 -0
  53. package/dist/src/tools/remind.js +247 -0
  54. package/dist/src/types.d.ts +175 -0
  55. package/dist/src/types.js +1 -0
  56. package/dist/src/typing-keepalive.d.ts +27 -0
  57. package/dist/src/typing-keepalive.js +64 -0
  58. package/dist/src/update-checker.d.ts +34 -0
  59. package/dist/src/update-checker.js +166 -0
  60. package/dist/src/user-messages.d.ts +8 -0
  61. package/dist/src/user-messages.js +8 -0
  62. package/dist/src/utils/audio-convert.d.ts +89 -0
  63. package/dist/src/utils/audio-convert.js +704 -0
  64. package/dist/src/utils/file-utils.d.ts +55 -0
  65. package/dist/src/utils/file-utils.js +150 -0
  66. package/dist/src/utils/image-size.d.ts +51 -0
  67. package/dist/src/utils/image-size.js +234 -0
  68. package/dist/src/utils/media-tags.d.ts +14 -0
  69. package/dist/src/utils/media-tags.js +164 -0
  70. package/dist/src/utils/payload.d.ts +112 -0
  71. package/dist/src/utils/payload.js +186 -0
  72. package/dist/src/utils/platform.d.ts +137 -0
  73. package/dist/src/utils/platform.js +390 -0
  74. package/dist/src/utils/text-parsing.d.ts +32 -0
  75. package/dist/src/utils/text-parsing.js +80 -0
  76. package/dist/src/utils/upload-cache.d.ts +34 -0
  77. package/dist/src/utils/upload-cache.js +93 -0
  78. package/index.ts +31 -0
  79. package/moltbot.plugin.json +16 -0
  80. package/node_modules/@eshaz/web-worker/LICENSE +201 -0
  81. package/node_modules/@eshaz/web-worker/README.md +134 -0
  82. package/node_modules/@eshaz/web-worker/browser.js +17 -0
  83. package/node_modules/@eshaz/web-worker/cjs/browser.js +16 -0
  84. package/node_modules/@eshaz/web-worker/cjs/node.js +219 -0
  85. package/node_modules/@eshaz/web-worker/index.d.ts +4 -0
  86. package/node_modules/@eshaz/web-worker/node.js +223 -0
  87. package/node_modules/@eshaz/web-worker/package.json +54 -0
  88. package/node_modules/@wasm-audio-decoders/common/index.js +5 -0
  89. package/node_modules/@wasm-audio-decoders/common/package.json +36 -0
  90. package/node_modules/@wasm-audio-decoders/common/src/WASMAudioDecoderCommon.js +231 -0
  91. package/node_modules/@wasm-audio-decoders/common/src/WASMAudioDecoderWorker.js +129 -0
  92. package/node_modules/@wasm-audio-decoders/common/src/puff/README +67 -0
  93. package/node_modules/@wasm-audio-decoders/common/src/puff/build_puff.js +31 -0
  94. package/node_modules/@wasm-audio-decoders/common/src/puff/puff.c +863 -0
  95. package/node_modules/@wasm-audio-decoders/common/src/puff/puff.h +35 -0
  96. package/node_modules/@wasm-audio-decoders/common/src/utilities.js +3 -0
  97. package/node_modules/@wasm-audio-decoders/common/types.d.ts +7 -0
  98. package/node_modules/mpg123-decoder/README.md +265 -0
  99. package/node_modules/mpg123-decoder/dist/mpg123-decoder.min.js +185 -0
  100. package/node_modules/mpg123-decoder/dist/mpg123-decoder.min.js.map +1 -0
  101. package/node_modules/mpg123-decoder/index.js +8 -0
  102. package/node_modules/mpg123-decoder/package.json +58 -0
  103. package/node_modules/mpg123-decoder/src/EmscriptenWasm.js +464 -0
  104. package/node_modules/mpg123-decoder/src/MPEGDecoder.js +200 -0
  105. package/node_modules/mpg123-decoder/src/MPEGDecoderWebWorker.js +21 -0
  106. package/node_modules/mpg123-decoder/types.d.ts +30 -0
  107. package/node_modules/silk-wasm/LICENSE +21 -0
  108. package/node_modules/silk-wasm/README.md +85 -0
  109. package/node_modules/silk-wasm/lib/index.cjs +16 -0
  110. package/node_modules/silk-wasm/lib/index.d.ts +70 -0
  111. package/node_modules/silk-wasm/lib/index.mjs +16 -0
  112. package/node_modules/silk-wasm/lib/silk.wasm +0 -0
  113. package/node_modules/silk-wasm/lib/utils.d.ts +4 -0
  114. package/node_modules/silk-wasm/package.json +39 -0
  115. package/node_modules/simple-yenc/.github/FUNDING.yml +1 -0
  116. package/node_modules/simple-yenc/.prettierignore +1 -0
  117. package/node_modules/simple-yenc/LICENSE +7 -0
  118. package/node_modules/simple-yenc/README.md +163 -0
  119. package/node_modules/simple-yenc/dist/esm.js +1 -0
  120. package/node_modules/simple-yenc/dist/index.js +1 -0
  121. package/node_modules/simple-yenc/package.json +50 -0
  122. package/node_modules/simple-yenc/rollup.config.js +27 -0
  123. package/node_modules/simple-yenc/src/simple-yenc.js +302 -0
  124. package/node_modules/ws/LICENSE +20 -0
  125. package/node_modules/ws/README.md +548 -0
  126. package/node_modules/ws/browser.js +8 -0
  127. package/node_modules/ws/index.js +13 -0
  128. package/node_modules/ws/lib/buffer-util.js +131 -0
  129. package/node_modules/ws/lib/constants.js +19 -0
  130. package/node_modules/ws/lib/event-target.js +292 -0
  131. package/node_modules/ws/lib/extension.js +203 -0
  132. package/node_modules/ws/lib/limiter.js +55 -0
  133. package/node_modules/ws/lib/permessage-deflate.js +528 -0
  134. package/node_modules/ws/lib/receiver.js +706 -0
  135. package/node_modules/ws/lib/sender.js +602 -0
  136. package/node_modules/ws/lib/stream.js +161 -0
  137. package/node_modules/ws/lib/subprotocol.js +62 -0
  138. package/node_modules/ws/lib/validation.js +152 -0
  139. package/node_modules/ws/lib/websocket-server.js +554 -0
  140. package/node_modules/ws/lib/websocket.js +1393 -0
  141. package/node_modules/ws/package.json +69 -0
  142. package/node_modules/ws/wrapper.mjs +8 -0
  143. package/openclaw.plugin.json +16 -0
  144. package/package.json +76 -0
  145. package/scripts/cleanup-legacy-plugins.sh +124 -0
  146. package/scripts/proactive-api-server.ts +369 -0
  147. package/scripts/send-proactive.ts +293 -0
  148. package/scripts/set-markdown.sh +156 -0
  149. package/scripts/test-sendmedia.ts +116 -0
  150. package/scripts/upgrade-via-alt-pkg.sh +307 -0
  151. package/scripts/upgrade-via-npm.ps1 +296 -0
  152. package/scripts/upgrade-via-npm.sh +301 -0
  153. package/scripts/upgrade-via-source.sh +774 -0
  154. package/skills/qqbot-channel/SKILL.md +263 -0
  155. package/skills/qqbot-channel/references/api_references.md +521 -0
  156. package/skills/qqbot-media/SKILL.md +56 -0
  157. package/skills/qqbot-remind/SKILL.md +149 -0
  158. package/src/admin-resolver.ts +140 -0
  159. package/src/api.ts +819 -0
  160. package/src/bot-logs-2026-03-21T11-21-47(2).txt +46 -0
  161. package/src/channel.ts +381 -0
  162. package/src/config.ts +187 -0
  163. package/src/credential-backup.ts +72 -0
  164. package/src/gateway.log +43 -0
  165. package/src/gateway.ts +1404 -0
  166. package/src/image-server.ts +539 -0
  167. package/src/inbound-attachments.ts +304 -0
  168. package/src/known-users.ts +353 -0
  169. package/src/message-queue.ts +169 -0
  170. package/src/onboarding.ts +274 -0
  171. package/src/openclaw-2026-03-21.log +3729 -0
  172. package/src/openclaw-plugin-sdk.d.ts +522 -0
  173. package/src/outbound-deliver.ts +552 -0
  174. package/src/outbound.ts +1266 -0
  175. package/src/proactive.ts +530 -0
  176. package/src/ref-index-store.ts +357 -0
  177. package/src/reply-dispatcher.ts +334 -0
  178. package/src/runtime.ts +14 -0
  179. package/src/session-store.ts +303 -0
  180. package/src/slash-commands.ts +1305 -0
  181. package/src/startup-greeting.ts +98 -0
  182. package/src/stt.ts +86 -0
  183. package/src/tools/channel.ts +281 -0
  184. package/src/tools/remind.ts +296 -0
  185. package/src/types.ts +183 -0
  186. package/src/typing-keepalive.ts +59 -0
  187. package/src/update-checker.ts +179 -0
  188. package/src/user-messages.ts +7 -0
  189. package/src/utils/audio-convert.ts +803 -0
  190. package/src/utils/file-utils.ts +167 -0
  191. package/src/utils/image-size.ts +266 -0
  192. package/src/utils/media-tags.ts +182 -0
  193. package/src/utils/payload.ts +265 -0
  194. package/src/utils/platform.ts +435 -0
  195. package/src/utils/text-parsing.ts +82 -0
  196. package/src/utils/upload-cache.ts +128 -0
  197. package/tsconfig.json +16 -0
@@ -0,0 +1,112 @@
1
+ /**
2
+ * QQBot 结构化消息载荷工具
3
+ *
4
+ * 用于处理 AI 输出的结构化消息载荷,包括:
5
+ * - 定时提醒载荷 (cron_reminder)
6
+ * - 媒体消息载荷 (media)
7
+ */
8
+ /**
9
+ * 定时提醒载荷
10
+ */
11
+ export interface CronReminderPayload {
12
+ type: 'cron_reminder';
13
+ /** 提醒内容 */
14
+ content: string;
15
+ /** 目标类型:c2c (私聊) 或 group (群聊) */
16
+ targetType: 'c2c' | 'group';
17
+ /** 目标地址:user_openid 或 group_openid */
18
+ targetAddress: string;
19
+ /** 原始消息 ID(可选) */
20
+ originalMessageId?: string;
21
+ }
22
+ /**
23
+ * 媒体消息载荷
24
+ */
25
+ export interface MediaPayload {
26
+ type: 'media';
27
+ /** 媒体类型:image, audio, video, file */
28
+ mediaType: 'image' | 'audio' | 'video' | 'file';
29
+ /** 来源类型:url 或 file */
30
+ source: 'url' | 'file';
31
+ /** 媒体路径或 URL */
32
+ path: string;
33
+ /** 媒体描述(可选) */
34
+ caption?: string;
35
+ }
36
+ /**
37
+ * QQBot 载荷联合类型
38
+ */
39
+ export type QQBotPayload = CronReminderPayload | MediaPayload;
40
+ /**
41
+ * 解析结果
42
+ */
43
+ export interface ParseResult {
44
+ /** 是否为结构化载荷 */
45
+ isPayload: boolean;
46
+ /** 解析后的载荷对象(如果是结构化载荷) */
47
+ payload?: QQBotPayload;
48
+ /** 原始文本(如果不是结构化载荷) */
49
+ text?: string;
50
+ /** 解析错误信息(如果解析失败) */
51
+ error?: string;
52
+ }
53
+ /**
54
+ * 解析 AI 输出的结构化载荷
55
+ *
56
+ * 检测消息是否以 QQBOT_PAYLOAD: 前缀开头,如果是则提取并解析 JSON
57
+ *
58
+ * @param text AI 输出的原始文本
59
+ * @returns 解析结果
60
+ *
61
+ * @example
62
+ * const result = parseQQBotPayload('QQBOT_PAYLOAD:\n{"type": "media", "mediaType": "image", ...}');
63
+ * if (result.isPayload && result.payload) {
64
+ * // 处理结构化载荷
65
+ * }
66
+ */
67
+ export declare function parseQQBotPayload(text: string): ParseResult;
68
+ /**
69
+ * 将定时提醒载荷编码为 Cron 消息格式
70
+ *
71
+ * 将 JSON 编码为 Base64,并添加 QQBOT_CRON: 前缀
72
+ *
73
+ * @param payload 定时提醒载荷
74
+ * @returns 编码后的消息字符串,格式为 QQBOT_CRON:{base64}
75
+ *
76
+ * @example
77
+ * const message = encodePayloadForCron({
78
+ * type: 'cron_reminder',
79
+ * content: '喝水时间到!',
80
+ * targetType: 'c2c',
81
+ * targetAddress: 'user_openid_xxx'
82
+ * });
83
+ * // 返回: QQBOT_CRON:eyJ0eXBlIjoiY3Jvbl9yZW1pbmRlciIs...
84
+ */
85
+ export declare function encodePayloadForCron(payload: CronReminderPayload): string;
86
+ /**
87
+ * 解码 Cron 消息中的载荷
88
+ *
89
+ * 检测 QQBOT_CRON: 前缀,解码 Base64 并解析 JSON
90
+ *
91
+ * @param message Cron 触发时收到的消息
92
+ * @returns 解码结果,包含是否为 Cron 载荷、解析后的载荷对象或错误信息
93
+ *
94
+ * @example
95
+ * const result = decodeCronPayload('QQBOT_CRON:eyJ0eXBlIjoiY3Jvbl9yZW1pbmRlciIs...');
96
+ * if (result.isCronPayload && result.payload) {
97
+ * // 处理定时提醒
98
+ * }
99
+ */
100
+ export declare function decodeCronPayload(message: string): {
101
+ isCronPayload: boolean;
102
+ payload?: CronReminderPayload;
103
+ error?: string;
104
+ };
105
+ /**
106
+ * 判断载荷是否为定时提醒类型
107
+ */
108
+ export declare function isCronReminderPayload(payload: QQBotPayload): payload is CronReminderPayload;
109
+ /**
110
+ * 判断载荷是否为媒体消息类型
111
+ */
112
+ export declare function isMediaPayload(payload: QQBotPayload): payload is MediaPayload;
@@ -0,0 +1,186 @@
1
+ /**
2
+ * QQBot 结构化消息载荷工具
3
+ *
4
+ * 用于处理 AI 输出的结构化消息载荷,包括:
5
+ * - 定时提醒载荷 (cron_reminder)
6
+ * - 媒体消息载荷 (media)
7
+ */
8
+ // ============================================
9
+ // 常量定义
10
+ // ============================================
11
+ /** AI 输出的结构化载荷前缀 */
12
+ const PAYLOAD_PREFIX = 'QQBOT_PAYLOAD:';
13
+ /** Cron 消息存储的前缀 */
14
+ const CRON_PREFIX = 'QQBOT_CRON:';
15
+ // ============================================
16
+ // 解析函数
17
+ // ============================================
18
+ /**
19
+ * 解析 AI 输出的结构化载荷
20
+ *
21
+ * 检测消息是否以 QQBOT_PAYLOAD: 前缀开头,如果是则提取并解析 JSON
22
+ *
23
+ * @param text AI 输出的原始文本
24
+ * @returns 解析结果
25
+ *
26
+ * @example
27
+ * const result = parseQQBotPayload('QQBOT_PAYLOAD:\n{"type": "media", "mediaType": "image", ...}');
28
+ * if (result.isPayload && result.payload) {
29
+ * // 处理结构化载荷
30
+ * }
31
+ */
32
+ export function parseQQBotPayload(text) {
33
+ const trimmedText = text.trim();
34
+ // 检查是否以 QQBOT_PAYLOAD: 开头
35
+ if (!trimmedText.startsWith(PAYLOAD_PREFIX)) {
36
+ return {
37
+ isPayload: false,
38
+ text: text
39
+ };
40
+ }
41
+ // 提取 JSON 内容(去掉前缀)
42
+ const jsonContent = trimmedText.slice(PAYLOAD_PREFIX.length).trim();
43
+ if (!jsonContent) {
44
+ return {
45
+ isPayload: true,
46
+ error: '载荷内容为空'
47
+ };
48
+ }
49
+ try {
50
+ const payload = JSON.parse(jsonContent);
51
+ // 验证必要字段
52
+ if (!payload.type) {
53
+ return {
54
+ isPayload: true,
55
+ error: '载荷缺少 type 字段'
56
+ };
57
+ }
58
+ // 根据 type 进行额外验证
59
+ if (payload.type === 'cron_reminder') {
60
+ if (!payload.content || !payload.targetType || !payload.targetAddress) {
61
+ return {
62
+ isPayload: true,
63
+ error: 'cron_reminder 载荷缺少必要字段 (content, targetType, targetAddress)'
64
+ };
65
+ }
66
+ }
67
+ else if (payload.type === 'media') {
68
+ if (!payload.mediaType || !payload.source || !payload.path) {
69
+ return {
70
+ isPayload: true,
71
+ error: 'media 载荷缺少必要字段 (mediaType, source, path)'
72
+ };
73
+ }
74
+ }
75
+ return {
76
+ isPayload: true,
77
+ payload
78
+ };
79
+ }
80
+ catch (e) {
81
+ return {
82
+ isPayload: true,
83
+ error: `JSON 解析失败: ${e instanceof Error ? e.message : String(e)}`
84
+ };
85
+ }
86
+ }
87
+ // ============================================
88
+ // Cron 编码/解码函数
89
+ // ============================================
90
+ /**
91
+ * 将定时提醒载荷编码为 Cron 消息格式
92
+ *
93
+ * 将 JSON 编码为 Base64,并添加 QQBOT_CRON: 前缀
94
+ *
95
+ * @param payload 定时提醒载荷
96
+ * @returns 编码后的消息字符串,格式为 QQBOT_CRON:{base64}
97
+ *
98
+ * @example
99
+ * const message = encodePayloadForCron({
100
+ * type: 'cron_reminder',
101
+ * content: '喝水时间到!',
102
+ * targetType: 'c2c',
103
+ * targetAddress: 'user_openid_xxx'
104
+ * });
105
+ * // 返回: QQBOT_CRON:eyJ0eXBlIjoiY3Jvbl9yZW1pbmRlciIs...
106
+ */
107
+ export function encodePayloadForCron(payload) {
108
+ const jsonString = JSON.stringify(payload);
109
+ const base64 = Buffer.from(jsonString, 'utf-8').toString('base64');
110
+ return `${CRON_PREFIX}${base64}`;
111
+ }
112
+ /**
113
+ * 解码 Cron 消息中的载荷
114
+ *
115
+ * 检测 QQBOT_CRON: 前缀,解码 Base64 并解析 JSON
116
+ *
117
+ * @param message Cron 触发时收到的消息
118
+ * @returns 解码结果,包含是否为 Cron 载荷、解析后的载荷对象或错误信息
119
+ *
120
+ * @example
121
+ * const result = decodeCronPayload('QQBOT_CRON:eyJ0eXBlIjoiY3Jvbl9yZW1pbmRlciIs...');
122
+ * if (result.isCronPayload && result.payload) {
123
+ * // 处理定时提醒
124
+ * }
125
+ */
126
+ export function decodeCronPayload(message) {
127
+ const trimmedMessage = message.trim();
128
+ // 检查是否以 QQBOT_CRON: 开头
129
+ if (!trimmedMessage.startsWith(CRON_PREFIX)) {
130
+ return {
131
+ isCronPayload: false
132
+ };
133
+ }
134
+ // 提取 Base64 内容
135
+ const base64Content = trimmedMessage.slice(CRON_PREFIX.length);
136
+ if (!base64Content) {
137
+ return {
138
+ isCronPayload: true,
139
+ error: 'Cron 载荷内容为空'
140
+ };
141
+ }
142
+ try {
143
+ // Base64 解码
144
+ const jsonString = Buffer.from(base64Content, 'base64').toString('utf-8');
145
+ const payload = JSON.parse(jsonString);
146
+ // 验证类型
147
+ if (payload.type !== 'cron_reminder') {
148
+ return {
149
+ isCronPayload: true,
150
+ error: `期望 type 为 cron_reminder,实际为 ${payload.type}`
151
+ };
152
+ }
153
+ // 验证必要字段
154
+ if (!payload.content || !payload.targetType || !payload.targetAddress) {
155
+ return {
156
+ isCronPayload: true,
157
+ error: 'Cron 载荷缺少必要字段'
158
+ };
159
+ }
160
+ return {
161
+ isCronPayload: true,
162
+ payload
163
+ };
164
+ }
165
+ catch (e) {
166
+ return {
167
+ isCronPayload: true,
168
+ error: `Cron 载荷解码失败: ${e instanceof Error ? e.message : String(e)}`
169
+ };
170
+ }
171
+ }
172
+ // ============================================
173
+ // 辅助函数
174
+ // ============================================
175
+ /**
176
+ * 判断载荷是否为定时提醒类型
177
+ */
178
+ export function isCronReminderPayload(payload) {
179
+ return payload.type === 'cron_reminder';
180
+ }
181
+ /**
182
+ * 判断载荷是否为媒体消息类型
183
+ */
184
+ export function isMediaPayload(payload) {
185
+ return payload.type === 'media';
186
+ }
@@ -0,0 +1,137 @@
1
+ /**
2
+ * 跨平台兼容工具
3
+ *
4
+ * 统一 Mac / Linux / Windows 三大系统的:
5
+ * - 用户主目录获取
6
+ * - 临时目录获取
7
+ * - 本地路径判断
8
+ * - ffmpeg / ffprobe 可执行文件路径
9
+ * - silk-wasm 原生模块兼容性检测
10
+ * - 启动诊断报告
11
+ */
12
+ export type PlatformType = "darwin" | "linux" | "win32" | "other";
13
+ export declare function getPlatform(): PlatformType;
14
+ export declare function isWindows(): boolean;
15
+ /**
16
+ * 安全获取用户主目录
17
+ *
18
+ * 优先级:
19
+ * 1. os.homedir()(Node 原生,所有平台)
20
+ * 2. $HOME(Mac/Linux)或 %USERPROFILE%(Windows)
21
+ * 3. 降级到 /tmp(Linux/Mac)或 os.tmpdir()(Windows)
22
+ *
23
+ * 与之前 `process.env.HOME || "/home/ubuntu"` 的硬编码相比,
24
+ * 现在能正确处理 Windows 和非 ubuntu 用户。
25
+ */
26
+ export declare function getHomeDir(): string;
27
+ /**
28
+ * 获取 .openclaw/qqbot 下的子目录路径,并自动创建
29
+ * 替代各文件中分散的 path.join(HOME, ".openclaw", "qqbot", ...)
30
+ */
31
+ export declare function getQQBotDataDir(...subPaths: string[]): string;
32
+ /**
33
+ * 获取 .openclaw/media/qqbot 下的子目录路径,并自动创建
34
+ *
35
+ * 与 getQQBotDataDir 不同,此目录位于 OpenClaw 核心的媒体安全白名单
36
+ * (~/.openclaw/media) 之下,下载到这里的文件可以被框架的 image/media
37
+ * 工具直接访问,不会触发 "Local media path is not under an allowed directory" 错误。
38
+ *
39
+ * 用于存放从 QQ 下载的图片、语音等需要被框架处理的媒体文件。
40
+ */
41
+ export declare function getQQBotMediaDir(...subPaths: string[]): string;
42
+ /**
43
+ * 获取系统临时目录(跨平台安全)
44
+ * Mac: /var/folders/... 或 /tmp
45
+ * Linux: /tmp
46
+ * Windows: %TEMP% 或 C:\Users\xxx\AppData\Local\Temp
47
+ */
48
+ export declare function getTempDir(): string;
49
+ /**
50
+ * 展开路径中的波浪线(~)为用户主目录
51
+ *
52
+ * Mac/Linux 用户经常使用 `~/Desktop/file.png` 这样的路径,
53
+ * 但 Node.js 的 fs 模块不会像 shell 一样自动展开 `~`。
54
+ *
55
+ * 支持:
56
+ * - `~/xxx` → `/Users/you/xxx`(Mac)或 `/home/you/xxx`(Linux)
57
+ * - `~` → `/Users/you`
58
+ * - 非 `~` 开头的路径原样返回
59
+ *
60
+ * 注意: 不支持 `~otheruser/xxx` 语法(极少使用,且需要系统调用获取其他用户信息)
61
+ */
62
+ export declare function expandTilde(p: string): string;
63
+ /**
64
+ * 对路径进行完整的规范化处理:剥离 file:// 前缀 + 展开波浪线 + 去除首尾空白
65
+ * 所有文件操作前应通过此函数处理用户输入的路径
66
+ */
67
+ export declare function normalizePath(p: string): string;
68
+ /**
69
+ * 规范化文件名为 QQ Bot API 要求的 UTF-8 编码格式
70
+ *
71
+ * 问题场景:
72
+ * - macOS HFS+/APFS 文件系统使用 NFD(Unicode 分解形式)存储文件名,
73
+ * 例如「中文.txt」被分解为多个码点,QQ Bot API 可能拒绝
74
+ * - 文件名可能包含 API 不接受的特殊控制字符
75
+ * - URL 路径中可能包含 percent-encoded 的文件名需要解码
76
+ *
77
+ * 处理:
78
+ * 1. Unicode NFC 规范化(将 NFD 分解形式合并为 NFC 组合形式)
79
+ * 2. 去除 ASCII 控制字符(0x00-0x1F, 0x7F)
80
+ * 3. 去除首尾空白
81
+ * 4. 对 percent-encoded 的文件名尝试 URI 解码
82
+ */
83
+ export declare function sanitizeFileName(name: string): string;
84
+ /**
85
+ * 判断字符串是否为本地文件路径(非 URL)
86
+ *
87
+ * 覆盖:
88
+ * - Unix 绝对路径: /Users/..., /home/..., /tmp/...
89
+ * - Windows 绝对路径: C:\..., D:/..., \\server\share
90
+ * - 相对路径: ./file, ../file
91
+ * - 波浪线路径: ~/Desktop/file.png
92
+ * - file:// 协议: file:///Users/..., file:///home/...
93
+ *
94
+ * 不匹配:
95
+ * - http:// / https:// URL
96
+ * - data: URL
97
+ */
98
+ export declare function isLocalPath(p: string): boolean;
99
+ /**
100
+ * 判断 markdown 中提取的路径是否像本地路径
101
+ * 比 isLocalPath 更宽松,用于从 markdown ![](path) 中检测误用
102
+ */
103
+ export declare function looksLikeLocalPath(p: string): boolean;
104
+ /**
105
+ * 检测 ffmpeg 是否可用,返回可执行路径
106
+ *
107
+ * Windows 上检测 ffmpeg.exe,Mac/Linux 检测 ffmpeg
108
+ * 支持通过环境变量 FFMPEG_PATH 指定自定义路径
109
+ *
110
+ * @returns ffmpeg 可执行文件路径,不可用返回 null
111
+ */
112
+ export declare function detectFfmpeg(): Promise<string | null>;
113
+ /** 重置 ffmpeg 缓存(用于测试) */
114
+ export declare function resetFfmpegCache(): void;
115
+ /**
116
+ * 检测 silk-wasm 是否可用
117
+ *
118
+ * silk-wasm 依赖 WASM 运行时,在某些环境(如老版本 Node、某些容器)可能不可用。
119
+ * 提前检测避免运行时崩溃。
120
+ */
121
+ export declare function checkSilkWasmAvailable(): Promise<boolean>;
122
+ export interface DiagnosticReport {
123
+ platform: string;
124
+ arch: string;
125
+ nodeVersion: string;
126
+ homeDir: string;
127
+ tempDir: string;
128
+ dataDir: string;
129
+ ffmpeg: string | null;
130
+ silkWasm: boolean;
131
+ warnings: string[];
132
+ }
133
+ /**
134
+ * 运行启动诊断,返回环境报告
135
+ * 在 gateway 启动时调用,打印环境信息并给出警告
136
+ */
137
+ export declare function runDiagnostics(): Promise<DiagnosticReport>;