@takibeiy/moltbot_cn 2026.1.27 → 2026.2.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 (102) hide show
  1. package/dist/build-info.json +5 -0
  2. package/dist/canvas-host/a2ui/.bundle.hash +1 -0
  3. package/dist/canvas-host/a2ui/a2ui.bundle.js +17770 -0
  4. package/dist/canvas-host/a2ui/index.html +307 -0
  5. package/dist/control-ui/assets/index-BAFzd9IE.css +1 -0
  6. package/dist/control-ui/assets/index-CxUFDXFX.js +3162 -0
  7. package/dist/control-ui/assets/index-CxUFDXFX.js.map +1 -0
  8. package/dist/control-ui/favicon.ico +0 -0
  9. package/dist/control-ui/index.html +15 -0
  10. package/dist/hooks/bundled/boot-md/HOOK.md +19 -0
  11. package/dist/hooks/bundled/command-logger/HOOK.md +122 -0
  12. package/dist/hooks/bundled/session-memory/HOOK.md +86 -0
  13. package/dist/hooks/bundled/soul-evil/HOOK.md +71 -0
  14. package/extensions/diagnostics-otel/node_modules/.bin/acorn +3 -7
  15. package/extensions/googlechat/node_modules/.bin/clawdbot +3 -7
  16. package/extensions/googlechat/node_modules/.bin/moltbot +3 -7
  17. package/extensions/line/node_modules/.bin/clawdbot +3 -7
  18. package/extensions/line/node_modules/.bin/moltbot +3 -7
  19. package/extensions/matrix/node_modules/.bin/clawdbot +3 -7
  20. package/extensions/matrix/node_modules/.bin/markdown-it +3 -7
  21. package/extensions/matrix/node_modules/.bin/moltbot +3 -7
  22. package/extensions/memory-core/node_modules/.bin/clawdbot +3 -7
  23. package/extensions/memory-core/node_modules/.bin/moltbot +3 -7
  24. package/extensions/memory-lancedb/node_modules/.bin/arrow2csv +3 -7
  25. package/extensions/memory-lancedb/node_modules/.bin/openai +3 -7
  26. package/extensions/msteams/node_modules/.bin/clawdbot +3 -7
  27. package/extensions/msteams/node_modules/.bin/moltbot +3 -7
  28. package/extensions/nostr/node_modules/.bin/clawdbot +3 -7
  29. package/extensions/nostr/node_modules/.bin/moltbot +3 -7
  30. package/extensions/qq/node_modules/.bin/vitest +3 -7
  31. package/extensions/qq/src/channel.ts +30 -2
  32. package/extensions/qq/src/onebot/api.test.ts +44 -0
  33. package/extensions/qq/src/onebot/api.ts +13 -0
  34. package/extensions/qq/src/send.test.ts +53 -8
  35. package/extensions/qq/src/send.ts +29 -1
  36. package/extensions/twitch/node_modules/.bin/clawdbot +3 -7
  37. package/extensions/twitch/node_modules/.bin/moltbot +3 -7
  38. package/extensions/zalo/node_modules/.bin/clawdbot +3 -7
  39. package/extensions/zalo/node_modules/.bin/moltbot +3 -7
  40. package/extensions/zalouser/node_modules/.bin/clawdbot +3 -7
  41. package/extensions/zalouser/node_modules/.bin/moltbot +3 -7
  42. package/git-hooks/pre-commit +0 -0
  43. package/package.json +2 -2
  44. package/skills/nano-banana-pro/scripts/generate_image.py +0 -0
  45. package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +0 -0
  46. package/skills/tmux/scripts/find-sessions.sh +0 -0
  47. package/skills/tmux/scripts/wait-for-text.sh +0 -0
  48. package/extensions/diagnostics-otel/node_modules/.bin/acorn.CMD +0 -12
  49. package/extensions/diagnostics-otel/node_modules/.bin/acorn.ps1 +0 -41
  50. package/extensions/googlechat/node_modules/.bin/clawdbot.CMD +0 -12
  51. package/extensions/googlechat/node_modules/.bin/clawdbot.ps1 +0 -41
  52. package/extensions/googlechat/node_modules/.bin/moltbot.CMD +0 -12
  53. package/extensions/googlechat/node_modules/.bin/moltbot.ps1 +0 -41
  54. package/extensions/line/node_modules/.bin/clawdbot.CMD +0 -12
  55. package/extensions/line/node_modules/.bin/clawdbot.ps1 +0 -41
  56. package/extensions/line/node_modules/.bin/moltbot.CMD +0 -12
  57. package/extensions/line/node_modules/.bin/moltbot.ps1 +0 -41
  58. package/extensions/matrix/node_modules/.bin/clawdbot.CMD +0 -12
  59. package/extensions/matrix/node_modules/.bin/clawdbot.ps1 +0 -41
  60. package/extensions/matrix/node_modules/.bin/markdown-it.CMD +0 -12
  61. package/extensions/matrix/node_modules/.bin/markdown-it.ps1 +0 -41
  62. package/extensions/matrix/node_modules/.bin/moltbot.CMD +0 -12
  63. package/extensions/matrix/node_modules/.bin/moltbot.ps1 +0 -41
  64. package/extensions/memory-core/node_modules/.bin/clawdbot.CMD +0 -12
  65. package/extensions/memory-core/node_modules/.bin/clawdbot.ps1 +0 -41
  66. package/extensions/memory-core/node_modules/.bin/moltbot.CMD +0 -12
  67. package/extensions/memory-core/node_modules/.bin/moltbot.ps1 +0 -41
  68. package/extensions/memory-lancedb/node_modules/.bin/arrow2csv.CMD +0 -12
  69. package/extensions/memory-lancedb/node_modules/.bin/arrow2csv.ps1 +0 -41
  70. package/extensions/memory-lancedb/node_modules/.bin/openai.CMD +0 -12
  71. package/extensions/memory-lancedb/node_modules/.bin/openai.ps1 +0 -41
  72. package/extensions/msteams/node_modules/.bin/clawdbot.CMD +0 -12
  73. package/extensions/msteams/node_modules/.bin/clawdbot.ps1 +0 -41
  74. package/extensions/msteams/node_modules/.bin/moltbot.CMD +0 -12
  75. package/extensions/msteams/node_modules/.bin/moltbot.ps1 +0 -41
  76. package/extensions/nostr/node_modules/.bin/clawdbot.CMD +0 -12
  77. package/extensions/nostr/node_modules/.bin/clawdbot.ps1 +0 -41
  78. package/extensions/nostr/node_modules/.bin/moltbot.CMD +0 -12
  79. package/extensions/nostr/node_modules/.bin/moltbot.ps1 +0 -41
  80. package/extensions/nostr/node_modules/.bin/tsc +0 -21
  81. package/extensions/nostr/node_modules/.bin/tsc.CMD +0 -12
  82. package/extensions/nostr/node_modules/.bin/tsc.ps1 +0 -41
  83. package/extensions/nostr/node_modules/.bin/tsserver +0 -21
  84. package/extensions/nostr/node_modules/.bin/tsserver.CMD +0 -12
  85. package/extensions/nostr/node_modules/.bin/tsserver.ps1 +0 -41
  86. package/extensions/qq/node_modules/.bin/vite +0 -21
  87. package/extensions/qq/node_modules/.bin/vite.CMD +0 -12
  88. package/extensions/qq/node_modules/.bin/vite.ps1 +0 -41
  89. package/extensions/qq/node_modules/.bin/vitest.CMD +0 -12
  90. package/extensions/qq/node_modules/.bin/vitest.ps1 +0 -41
  91. package/extensions/twitch/node_modules/.bin/clawdbot.CMD +0 -12
  92. package/extensions/twitch/node_modules/.bin/clawdbot.ps1 +0 -41
  93. package/extensions/twitch/node_modules/.bin/moltbot.CMD +0 -12
  94. package/extensions/twitch/node_modules/.bin/moltbot.ps1 +0 -41
  95. package/extensions/zalo/node_modules/.bin/clawdbot.CMD +0 -12
  96. package/extensions/zalo/node_modules/.bin/clawdbot.ps1 +0 -41
  97. package/extensions/zalo/node_modules/.bin/moltbot.CMD +0 -12
  98. package/extensions/zalo/node_modules/.bin/moltbot.ps1 +0 -41
  99. package/extensions/zalouser/node_modules/.bin/clawdbot.CMD +0 -12
  100. package/extensions/zalouser/node_modules/.bin/clawdbot.ps1 +0 -41
  101. package/extensions/zalouser/node_modules/.bin/moltbot.CMD +0 -12
  102. package/extensions/zalouser/node_modules/.bin/moltbot.ps1 +0 -41
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../moltbot/moltbot.mjs" "$@"
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../moltbot/moltbot.mjs" "$@"
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../moltbot/moltbot.mjs" "$@"
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../moltbot/moltbot.mjs" "$@"
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/vitest@2.1.9_@types+node@25_b4324752439f1bdb60cd3e5090841c9f/node_modules/vitest/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/vitest@2.1.9_@types+node@25_b4324752439f1bdb60cd3e5090841c9f/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/vitest@2.1.9_@types+node@25.1.0/node_modules/vitest/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/vitest@2.1.9_@types+node@25.1.0/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/vitest@2.1.9_@types+node@25_b4324752439f1bdb60cd3e5090841c9f/node_modules/vitest/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/vitest@2.1.9_@types+node@25_b4324752439f1bdb60cd3e5090841c9f/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/vitest@2.1.9_@types+node@25.1.0/node_modules/vitest/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/vitest@2.1.9_@types+node@25.1.0/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../vitest/vitest.mjs" "$@"
@@ -8,6 +8,7 @@ import type { ChannelPlugin, MoltbotConfig } from "clawdbot/plugin-sdk";
8
8
  import {
9
9
  applyAccountNameToChannelSection,
10
10
  buildChannelConfigSchema,
11
+ createTypingCallbacks,
11
12
  DEFAULT_ACCOUNT_ID,
12
13
  migrateBaseNameToDefaultAccount,
13
14
  normalizeAccountId,
@@ -23,7 +24,7 @@ import { QQConfigSchema, QQ_DEFAULT_WS_URL } from "./config-schema.js";
23
24
  import { QQConnectionManager, createConnectionManager } from "./connection.js";
24
25
  import { parseQQTarget, normalizeQQMessagingTarget, looksLikeQQTargetId } from "./normalize.js";
25
26
  import { qqOnboardingAdapter } from "./onboarding.js";
26
- import { sendQQTextMessage, sendQQMediaMessage } from "./send.js";
27
+ import { sendQQTextMessage, sendQQMediaMessage, setQQTypingStatus } from "./send.js";
27
28
  import { isBotMentioned, removeBotMention } from "./monitor.js";
28
29
  import { getQQRuntime } from "./runtime.js";
29
30
  import type {
@@ -308,6 +309,31 @@ export const qqPlugin: ChannelPlugin<ResolvedQQAccount> = {
308
309
  currentCfg,
309
310
  route.agentId,
310
311
  );
312
+
313
+ // Create typing callbacks (only for private chats)
314
+ const typingCallbacks = isPrivate
315
+ ? createTypingCallbacks({
316
+ start: async () => {
317
+ const api = manager.getApi();
318
+ if (api) await setQQTypingStatus(api, message.senderId, true);
319
+ },
320
+ stop: async () => {
321
+ const api = manager.getApi();
322
+ if (api) await setQQTypingStatus(api, message.senderId, false);
323
+ },
324
+ onStartError: (err) => {
325
+ ctx.log?.debug?.(
326
+ `[${accountId}] typing start failed: ${String(err)}`,
327
+ );
328
+ },
329
+ onStopError: (err) => {
330
+ ctx.log?.debug?.(
331
+ `[${accountId}] typing stop failed: ${String(err)}`,
332
+ );
333
+ },
334
+ })
335
+ : undefined;
336
+
311
337
  const { dispatcher, replyOptions, markDispatchIdle } =
312
338
  core.channel.reply.createReplyDispatcherWithTyping({
313
339
  humanDelay,
@@ -345,6 +371,8 @@ export const qqPlugin: ChannelPlugin<ResolvedQQAccount> = {
345
371
  `[${accountId}] ${info.kind} reply failed: ${String(err)}`,
346
372
  );
347
373
  },
374
+ onReplyStart: typingCallbacks?.onReplyStart,
375
+ onIdle: typingCallbacks?.onIdle,
348
376
  });
349
377
 
350
378
  // Dispatch to auto-reply pipeline
@@ -460,7 +488,7 @@ export const qqPlugin: ChannelPlugin<ResolvedQQAccount> = {
460
488
  // Outbound Adapter - Sending Messages
461
489
  // ==========================================================================
462
490
  outbound: {
463
- deliveryMode: "direct",
491
+ deliveryMode: "gateway",
464
492
  textChunkLimit: 4000,
465
493
 
466
494
  sendText: async ({ to, text, accountId, replyToId }) => {
@@ -366,4 +366,48 @@ describe("OneBotApi", () => {
366
366
  expect(result).toBe(false);
367
367
  });
368
368
  });
369
+
370
+ describe("setInputStatus", () => {
371
+ it("sets typing status (text input)", async () => {
372
+ const client = createMockClient();
373
+ const api = new OneBotApi(client);
374
+
375
+ vi.mocked(client.callApi).mockResolvedValue(undefined);
376
+
377
+ await api.setInputStatus(12345, 1);
378
+
379
+ expect(client.callApi).toHaveBeenCalledWith("set_input_status", {
380
+ user_id: 12345,
381
+ event_type: 1,
382
+ });
383
+ });
384
+
385
+ it("sets normal status", async () => {
386
+ const client = createMockClient();
387
+ const api = new OneBotApi(client);
388
+
389
+ vi.mocked(client.callApi).mockResolvedValue(undefined);
390
+
391
+ await api.setInputStatus(12345, 2);
392
+
393
+ expect(client.callApi).toHaveBeenCalledWith("set_input_status", {
394
+ user_id: 12345,
395
+ event_type: 2,
396
+ });
397
+ });
398
+
399
+ it("defaults to text input (1)", async () => {
400
+ const client = createMockClient();
401
+ const api = new OneBotApi(client);
402
+
403
+ vi.mocked(client.callApi).mockResolvedValue(undefined);
404
+
405
+ await api.setInputStatus(12345);
406
+
407
+ expect(client.callApi).toHaveBeenCalledWith("set_input_status", {
408
+ user_id: 12345,
409
+ event_type: 1,
410
+ });
411
+ });
412
+ });
369
413
  });
@@ -355,6 +355,19 @@ export class OneBotApi {
355
355
  return false;
356
356
  }
357
357
  }
358
+
359
+ /**
360
+ * Set input status (typing indicator).
361
+ * Only works for private chats.
362
+ * @param userId Target user ID
363
+ * @param eventType 0=voice, 1=text typing, 2=normal
364
+ */
365
+ async setInputStatus(userId: number, eventType: 0 | 1 | 2 = 1): Promise<void> {
366
+ await this.client.callApi("set_input_status", {
367
+ user_id: userId,
368
+ event_type: eventType,
369
+ });
370
+ }
358
371
  }
359
372
 
360
373
  // ============================================================================
@@ -12,13 +12,25 @@ import {
12
12
  sendQQMediaMessage,
13
13
  sendQQRawMessage,
14
14
  sendQQTextMessage,
15
+ setQQTypingStatus,
15
16
  } from "./send.js";
16
17
 
18
+ // Mock loadWebMedia from plugin-sdk
19
+ vi.mock("clawdbot/plugin-sdk", () => ({
20
+ loadWebMedia: vi.fn().mockResolvedValue({
21
+ buffer: Buffer.from("fake-image-data"),
22
+ contentType: "image/jpeg",
23
+ kind: "image",
24
+ fileName: "image.jpg",
25
+ }),
26
+ }));
27
+
17
28
  // Mock API factory
18
29
  function createMockApi(overrides: Partial<OneBotApi> = {}): OneBotApi {
19
30
  return {
20
31
  sendPrivateMsg: vi.fn().mockResolvedValue({ message_id: 100 }),
21
32
  sendGroupMsg: vi.fn().mockResolvedValue({ message_id: 200 }),
33
+ setInputStatus: vi.fn().mockResolvedValue(undefined),
22
34
  ...overrides,
23
35
  } as unknown as OneBotApi;
24
36
  }
@@ -107,6 +119,8 @@ describe("sendQQTextMessage", () => {
107
119
  });
108
120
 
109
121
  describe("sendQQMediaMessage", () => {
122
+ const expectedBase64 = `base64://${Buffer.from("fake-image-data").toString("base64")}`;
123
+
110
124
  it("sends image to private chat", async () => {
111
125
  const api = createMockApi();
112
126
 
@@ -118,7 +132,7 @@ describe("sendQQMediaMessage", () => {
118
132
 
119
133
  expect(result.ok).toBe(true);
120
134
  expect(api.sendPrivateMsg).toHaveBeenCalledWith(12345, [
121
- { type: "image", data: { file: "https://example.com/image.jpg" } },
135
+ { type: "image", data: { file: expectedBase64 } },
122
136
  ]);
123
137
  });
124
138
 
@@ -133,7 +147,7 @@ describe("sendQQMediaMessage", () => {
133
147
  });
134
148
 
135
149
  expect(api.sendPrivateMsg).toHaveBeenCalledWith(12345, [
136
- { type: "image", data: { file: "https://example.com/image.jpg" } },
150
+ { type: "image", data: { file: expectedBase64 } },
137
151
  { type: "text", data: { text: "Look at this!" } },
138
152
  ]);
139
153
  });
@@ -148,7 +162,7 @@ describe("sendQQMediaMessage", () => {
148
162
  });
149
163
 
150
164
  expect(api.sendPrivateMsg).toHaveBeenCalledWith(12345, [
151
- { type: "record", data: { file: "https://example.com/voice.mp3" } },
165
+ { type: "record", data: { file: expectedBase64 } },
152
166
  ]);
153
167
  });
154
168
 
@@ -162,7 +176,7 @@ describe("sendQQMediaMessage", () => {
162
176
  });
163
177
 
164
178
  expect(api.sendGroupMsg).toHaveBeenCalledWith(67890, [
165
- { type: "video", data: { file: "https://example.com/video.mp4" } },
179
+ { type: "video", data: { file: expectedBase64 } },
166
180
  ]);
167
181
  });
168
182
 
@@ -176,7 +190,7 @@ describe("sendQQMediaMessage", () => {
176
190
  });
177
191
 
178
192
  expect(api.sendPrivateMsg).toHaveBeenCalledWith(12345, [
179
- { type: "text", data: { text: "[文件] https://example.com/doc.pdf" } },
193
+ { type: "text", data: { text: `[文件] ${expectedBase64}` } },
180
194
  ]);
181
195
  });
182
196
 
@@ -192,7 +206,7 @@ describe("sendQQMediaMessage", () => {
192
206
 
193
207
  expect(api.sendPrivateMsg).toHaveBeenCalledWith(12345, [
194
208
  { type: "reply", data: { id: "888" } },
195
- { type: "image", data: { file: "https://example.com/image.jpg" } },
209
+ { type: "image", data: { file: expectedBase64 } },
196
210
  ]);
197
211
  });
198
212
 
@@ -289,6 +303,8 @@ describe("convenience functions", () => {
289
303
  });
290
304
 
291
305
  describe("sendPrivateImage", () => {
306
+ const expectedBase64 = `base64://${Buffer.from("fake-image-data").toString("base64")}`;
307
+
292
308
  it("sends image to user", async () => {
293
309
  const api = createMockApi();
294
310
 
@@ -301,13 +317,15 @@ describe("convenience functions", () => {
301
317
 
302
318
  expect(result.ok).toBe(true);
303
319
  expect(api.sendPrivateMsg).toHaveBeenCalledWith(12345, [
304
- { type: "image", data: { file: "https://example.com/img.jpg" } },
320
+ { type: "image", data: { file: expectedBase64 } },
305
321
  { type: "text", data: { text: "Check this out!" } },
306
322
  ]);
307
323
  });
308
324
  });
309
325
 
310
326
  describe("sendGroupImage", () => {
327
+ const expectedBase64 = `base64://${Buffer.from("fake-image-data").toString("base64")}`;
328
+
311
329
  it("sends image to group", async () => {
312
330
  const api = createMockApi();
313
331
 
@@ -315,8 +333,35 @@ describe("convenience functions", () => {
315
333
 
316
334
  expect(result.ok).toBe(true);
317
335
  expect(api.sendGroupMsg).toHaveBeenCalledWith(67890, [
318
- { type: "image", data: { file: "https://example.com/img.jpg" } },
336
+ { type: "image", data: { file: expectedBase64 } },
319
337
  ]);
320
338
  });
321
339
  });
322
340
  });
341
+
342
+ describe("setQQTypingStatus", () => {
343
+ it("sets typing status to true", async () => {
344
+ const api = createMockApi();
345
+
346
+ await setQQTypingStatus(api, 12345, true);
347
+
348
+ expect(api.setInputStatus).toHaveBeenCalledWith(12345, 1);
349
+ });
350
+
351
+ it("sets typing status to false (normal)", async () => {
352
+ const api = createMockApi();
353
+
354
+ await setQQTypingStatus(api, 12345, false);
355
+
356
+ expect(api.setInputStatus).toHaveBeenCalledWith(12345, 2);
357
+ });
358
+
359
+ it("silently ignores errors", async () => {
360
+ const api = createMockApi({
361
+ setInputStatus: vi.fn().mockRejectedValue(new Error("API not supported")),
362
+ });
363
+
364
+ // Should not throw
365
+ await expect(setQQTypingStatus(api, 12345, true)).resolves.toBeUndefined();
366
+ });
367
+ });
@@ -4,6 +4,7 @@
4
4
  * Handles sending text and media messages via OneBot API.
5
5
  */
6
6
 
7
+ import { loadWebMedia } from "clawdbot/plugin-sdk";
7
8
  import type { OneBotApi } from "./onebot/api.js";
8
9
  import type { OneBotMessageSegment, OneBotSendMsgResponse } from "./onebot/types.js";
9
10
  import { formatQQTarget, parseQQTarget, type ParsedQQTarget } from "./normalize.js";
@@ -149,6 +150,7 @@ export async function sendQQTextMessage(
149
150
 
150
151
  /**
151
152
  * Send a media message to a QQ target.
153
+ * Downloads the media and converts to base64 for NapCatQQ compatibility.
152
154
  */
153
155
  export async function sendQQMediaMessage(
154
156
  api: OneBotApi,
@@ -163,9 +165,13 @@ export async function sendQQMediaMessage(
163
165
  }
164
166
 
165
167
  try {
168
+ // Load media and convert to base64 for NapCatQQ compatibility
169
+ const media = await loadWebMedia(options.file);
170
+ const base64File = `base64://${media.buffer.toString("base64")}`;
171
+
166
172
  const segments = buildMediaSegments(
167
173
  options.mediaType,
168
- options.file,
174
+ base64File,
169
175
  options.caption,
170
176
  options.replyToMessageId,
171
177
  );
@@ -285,3 +291,25 @@ export async function sendGroupImage(
285
291
  caption,
286
292
  });
287
293
  }
294
+
295
+ // ============================================================================
296
+ // Typing Status
297
+ // ============================================================================
298
+
299
+ /**
300
+ * Set typing status for a private chat.
301
+ * Only works for private chats (OneBot v11 limitation).
302
+ * Silently ignores errors since not all implementations support this API.
303
+ */
304
+ export async function setQQTypingStatus(
305
+ api: OneBotApi,
306
+ userId: number,
307
+ typing: boolean,
308
+ ): Promise<void> {
309
+ try {
310
+ // 0=voice, 1=text typing, 2=normal
311
+ await api.setInputStatus(userId, typing ? 1 : 2);
312
+ } catch {
313
+ // Silently ignore - not all OneBot implementations support this
314
+ }
315
+ }
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../moltbot/moltbot.mjs" "$@"
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../moltbot/moltbot.mjs" "$@"
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../moltbot/moltbot.mjs" "$@"
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../moltbot/moltbot.mjs" "$@"
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../moltbot/moltbot.mjs" "$@"
@@ -2,17 +2,13 @@
2
2
  basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
3
 
4
4
  case `uname` in
5
- *CYGWIN*|*MINGW*|*MSYS*)
6
- if command -v cygpath > /dev/null 2>&1; then
7
- basedir=`cygpath -w "$basedir"`
8
- fi
9
- ;;
5
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
10
6
  esac
11
7
 
12
8
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules"
14
10
  else
15
- export NODE_PATH="/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules:/proc/cygdrive/d/WorkSpace/repos/node_modules:/proc/cygdrive/d/WorkSpace/node_modules:/proc/cygdrive/d/node_modules:/proc/cygdrive/d/WorkSpace/repos/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/Users/taki/Documents/Node/moltbot/node_modules:/Users/taki/Documents/Node/node_modules:/Users/taki/Documents/node_modules:/Users/taki/node_modules:/Users/node_modules:/node_modules:/Users/taki/Documents/Node/moltbot/node_modules/.pnpm/node_modules:$NODE_PATH"
16
12
  fi
17
13
  if [ -x "$basedir/node" ]; then
18
14
  exec "$basedir/node" "$basedir/../moltbot/moltbot.mjs" "$@"
File without changes
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@takibeiy/moltbot_cn",
3
- "version": "2026.1.27",
4
- "description": "Multi-channel AI assistant gateway (QQ, Telegram, WhatsApp, Discord, Slack)",
3
+ "version": "2026.2.1",
4
+ "description": "WhatsApp gateway CLI (Baileys web) with Pi RPC agent",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
File without changes
File without changes
File without changes
File without changes