cclawd 1.0.0 → 1.0.2

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 (111) hide show
  1. package/dist/{active-listener-DYmI7imH.js → active-listener-BLd27Pxd.js} +2 -2
  2. package/dist/{api-key-rotation-DLU4jvSu.js → api-key-rotation-Dg3JlNDQ.js} +1 -1
  3. package/dist/{audio-preflight-C9TMbRb4.js → audio-preflight-eV5m9mMp.js} +15 -15
  4. package/dist/{audio-transcription-runner-Q5zG_hYd.js → audio-transcription-runner-CQU4Eg1M.js} +10 -10
  5. package/dist/{audit-membership-runtime-DhxSwFnF.js → audit-membership-runtime-hXUuer4x.js} +6 -6
  6. package/dist/build-info.json +3 -3
  7. package/dist/bundled/boot-md/handler.js +35 -35
  8. package/dist/bundled/bootstrap-extra-files/handler.js +5 -5
  9. package/dist/bundled/command-logger/handler.js +2 -2
  10. package/dist/bundled/session-memory/handler.js +35 -35
  11. package/dist/{channel-activity-Bx08UTAg.js → channel-activity-dT3cYb0e.js} +2 -2
  12. package/dist/{commands-registry-llLVCTH9.js → commands-registry-CyLMCPuP.js} +2 -2
  13. package/dist/compact.runtime-DGRl4st4.js +39 -0
  14. package/dist/{deliver-DJf2ZBpe.js → deliver-B6eTtXSk.js} +19 -19
  15. package/dist/deliver-runtime-CLDpY6AW.js +19 -0
  16. package/dist/deps-send-discord.runtime-CxADlame.js +19 -0
  17. package/dist/deps-send-imessage.runtime-Wi79xm6H.js +18 -0
  18. package/dist/deps-send-signal.runtime-BDtzvsnR.js +17 -0
  19. package/dist/deps-send-slack.runtime-CgX24hgT.js +17 -0
  20. package/dist/deps-send-telegram.runtime-CEWc7ePn.js +20 -0
  21. package/dist/deps-send-whatsapp.runtime-B1KJ7YOp.js +43 -0
  22. package/dist/{diagnostic-BCCMF3O_.js → diagnostic-BZmAxdu9.js} +2 -2
  23. package/dist/{env-aYXLHjfZ.js → env-lw2hsIUY.js} +1 -1
  24. package/dist/{fetch-bvgIiupu.js → fetch-C0iyt-Iz.js} +3 -3
  25. package/dist/{fetch-DCTUdr1U.js → fetch-CMLoICyN.js} +5 -5
  26. package/dist/{fetch-guard-CqpEmMQ2.js → fetch-guard-DCj3k042.js} +2 -2
  27. package/dist/{frontmatter-DjZuS525.js → frontmatter-C_obXuTp.js} +3 -3
  28. package/dist/{github-copilot-token-CQmATy5E.js → github-copilot-token-8N63GdbE.js} +7 -7
  29. package/dist/{image-Q8E1-lZn.js → image-Bt49ybRv.js} +4 -4
  30. package/dist/image-runtime-Cilhq73U.js +12 -0
  31. package/dist/{ir-CzM3SxId.js → ir-CVtBjUiL.js} +6 -6
  32. package/dist/llm-slug-generator.js +35 -35
  33. package/dist/{logger-ChbX1G7s.js → logger-CbUVl62f.js} +7 -7
  34. package/dist/{login-B0mtU11X.js → login-D0fUoX-p.js} +4 -4
  35. package/dist/{login-qr-DY_i60f5.js → login-qr-ClBxstxZ.js} +10 -10
  36. package/dist/{manager-FAQPC0uO.js → manager-DSfEj66R.js} +12 -12
  37. package/dist/manager-runtime-BrZlGJsj.js +15 -0
  38. package/dist/{model-selection-wf3OY5DX.js → model-selection-CMEj8bpy.js} +130 -130
  39. package/dist/{outbound-Bw0dOVS7.js → outbound-BxIJyMzV.js} +6 -6
  40. package/dist/{outbound-attachment-1R6r9Pg_.js → outbound-attachment-CVJwpypG.js} +2 -2
  41. package/dist/{paths-C0HLtPu0.js → paths-CehYKFsO.js} +7 -7
  42. package/dist/{paths-hfkBoC7i.js → paths-DkxwiA8g.js} +5 -5
  43. package/dist/{pi-embedded-BAHaY-Oh.js → pi-embedded-CHNPEUAv.js} +159 -159
  44. package/dist/{pi-model-discovery-ItS07aJB.js → pi-model-discovery-D-r5y7kV.js} +7 -7
  45. package/dist/pi-model-discovery-runtime-DZQXYmdu.js +12 -0
  46. package/dist/{pi-tools.before-tool-call.runtime-D_mthvtC.js → pi-tools.before-tool-call.runtime-DagGpfw0.js} +10 -10
  47. package/dist/{proxy-fetch-c1ZUFFcO.js → proxy-fetch-BOh1PLOW.js} +1 -1
  48. package/dist/{pw-ai-Ok6KGelf.js → pw-ai-CoIUdns_.js} +9 -9
  49. package/dist/{qmd-manager-DhfEz4Ar.js → qmd-manager-DEscZz5_.js} +6 -6
  50. package/dist/{query-expansion-GqNV2iIE.js → query-expansion-BErUY8P2.js} +4 -4
  51. package/dist/runtime-whatsapp-login.runtime-ChqE9BkX.js +13 -0
  52. package/dist/runtime-whatsapp-outbound.runtime-yiy6jzKk.js +17 -0
  53. package/dist/{send-DPflcjM5.js → send-4rRrSKp9.js} +6 -6
  54. package/dist/{send-CEg4P96c.js → send-BKO1-P1t.js} +5 -5
  55. package/dist/{send-CS0ocZHl.js → send-EDBPXjTT.js} +3 -3
  56. package/dist/{send-6R8b9zsj.js → send-K2mAG7KC.js} +5 -5
  57. package/dist/{send-DwAoiT2p.js → send-V1MRV7QF.js} +25 -25
  58. package/dist/{session-BoIID5UR.js → session-CuVCho2m.js} +7 -7
  59. package/dist/{skill-commands-DhdiziMs.js → skill-commands-B55LOaMB.js} +9 -9
  60. package/dist/slash-commands.runtime-BchS0VkW.js +12 -0
  61. package/dist/slash-dispatch.runtime-BIKRY3fr.js +39 -0
  62. package/dist/slash-skill-commands.runtime-BP4jBHU9.js +13 -0
  63. package/dist/subagent-registry-runtime-DjEYzSyM.js +39 -0
  64. package/dist/{subsystem-C8z6w6xC.js → subsystem-DfXy5gUB.js} +14 -14
  65. package/dist/{tables-DQusRhkD.js → tables-BAGqh2XD.js} +1 -1
  66. package/dist/{target-errors-CfavnC9U.js → target-errors-CeBF8Pws.js} +1 -1
  67. package/dist/{tokens-BWDIKewp.js → tokens-6ul2IrzG.js} +1 -1
  68. package/dist/{web-CrcrTQ2c.js → web-BRSmQdtm.js} +39 -39
  69. package/dist/{whatsapp-actions-B0u0ZAme.js → whatsapp-actions-Dxb2K2Xh.js} +15 -15
  70. package/dist/{workspace-CWDYHR27.js → workspace-DGIcKCCW.js} +20 -20
  71. package/extensions/mfa-auth/README.md +33 -38
  72. package/extensions/mfa-auth/index.ts +97 -92
  73. package/extensions/mfa-auth/node_modules/.bin/qrcode-terminal +1 -6
  74. package/extensions/mfa-auth/node_modules/.bin/qrcode-terminal.cmd +17 -0
  75. package/extensions/mfa-auth/node_modules/.bin/qrcode-terminal.ps1 +0 -13
  76. package/extensions/mfa-auth/node_modules/.bin/tsx +1 -6
  77. package/extensions/mfa-auth/node_modules/.bin/tsx.cmd +17 -0
  78. package/extensions/mfa-auth/node_modules/.bin/tsx.ps1 +0 -13
  79. package/extensions/mfa-auth/node_modules/.package-lock.json +103 -0
  80. package/extensions/mfa-auth/package-lock.json +115 -0
  81. package/extensions/mfa-auth/package.json +1 -1
  82. package/extensions/mfa-auth/src/auth-manager.ts +4 -2
  83. package/extensions/mfa-auth/src/config.ts +1 -4
  84. package/extensions/mfa-auth/src/dabby-client.test.ts +68 -147
  85. package/extensions/mfa-auth/src/dabby-client.ts +70 -89
  86. package/extensions/mfa-auth/src/feishu-support/index.ts +2 -2
  87. package/extensions/mfa-auth/src/notification-service.ts +19 -14
  88. package/extensions/mfa-auth/src/providers/base.ts +0 -1
  89. package/extensions/mfa-auth/src/providers/qr-code.ts +3 -506
  90. package/extensions/mfa-auth/src/server.ts +3 -223
  91. package/extensions/mfa-auth/src/types.ts +13 -36
  92. package/package.json +458 -460
  93. package/dist/compact.runtime-BEn3giMt.js +0 -39
  94. package/dist/deliver-runtime-DkQ3XzGv.js +0 -19
  95. package/dist/deps-send-discord.runtime-BLpqSj6s.js +0 -19
  96. package/dist/deps-send-imessage.runtime-BFzyYqvR.js +0 -18
  97. package/dist/deps-send-signal.runtime-DT0TYCy1.js +0 -17
  98. package/dist/deps-send-slack.runtime-BhaGFfMX.js +0 -17
  99. package/dist/deps-send-telegram.runtime-B6Cic9NX.js +0 -20
  100. package/dist/deps-send-whatsapp.runtime-WtEhIq2S.js +0 -43
  101. package/dist/image-runtime-B1LFYfQ2.js +0 -12
  102. package/dist/manager-runtime-Da7ME9vS.js +0 -15
  103. package/dist/pi-model-discovery-runtime-DjM7Z1fx.js +0 -12
  104. package/dist/runtime-whatsapp-login.runtime-D4BRhQkK.js +0 -13
  105. package/dist/runtime-whatsapp-outbound.runtime-DJPpS6g-.js +0 -17
  106. package/dist/slash-commands.runtime-Cu1lTjV9.js +0 -12
  107. package/dist/slash-dispatch.runtime-DRVJEF4l.js +0 -39
  108. package/dist/slash-skill-commands.runtime-C373PJjv.js +0 -13
  109. package/dist/subagent-registry-runtime-D7hWBo1G.js +0 -39
  110. package/extensions/mfa-auth/node_modules/.bin/qrcode-terminal.CMD +0 -12
  111. package/extensions/mfa-auth/node_modules/.bin/tsx.CMD +0 -12
@@ -1,12 +1,12 @@
1
1
  import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
2
2
  import { authManager } from "./src/auth-manager.js";
3
3
  import { config } from "./src/config.js";
4
+ import { dabbyClient } from "./src/dabby-client.js";
4
5
  import { NotificationService } from "./src/notification-service.js";
5
6
  import { qrCodeAuthProvider } from "./src/providers/qr-code.js";
6
- import { startHttpServer, setNotifyCallback, getServerBaseUrl } from "./src/server.js";
7
+ import { setNotifyCallback } from "./src/server.js";
7
8
  import type { AuthSession } from "./src/types.js";
8
9
 
9
- let serverStarted = false;
10
10
  const notificationService = NotificationService.getInstance();
11
11
  const pendingAuthUsers = new Set<string>();
12
12
 
@@ -98,14 +98,17 @@ export default function register(api: OpenClawPluginApi) {
98
98
  const session = authManager.getLatestSessionByUserId(userId);
99
99
  const metadata = session?.metadata as Record<string, unknown> | undefined;
100
100
 
101
- if (metadata?.authUrl) {
101
+ if (metadata?.qrCodeUrl) {
102
102
  pendingAuthUsers.delete(userId);
103
103
 
104
104
  let messageText = "";
105
105
  if (metadata.triggerType === "first_message") {
106
- messageText = `🔐 首次对话需要进行认证\n\n为了您的账户安全,首次对话前需要完成身份验证。\n\n请点击链接完成验证:\n${metadata.authUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟`;
106
+ const isReauth = metadata.isReauth === true;
107
+ messageText = isReauth
108
+ ? `🔐 重新认证\n\n📱 请点击以下链接完成扫码认证:\n${metadata.qrCodeUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟`
109
+ : `🔐 首次对话需要进行认证\n\n为了您的账户安全,首次对话前需要完成身份验证。\n\n📱 请点击以下链接完成扫码认证:\n${metadata.qrCodeUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟`;
107
110
  } else if (metadata.triggerType === "sensitive_operation") {
108
- messageText = `🔐 该操作需要二次认证\n\n检测到敏感操作: ${metadata.commandPreview}\n\n请点击链接完成验证:\n${metadata.authUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟\n\n验证成功后,请回复"确认"或者重新发送之前的命令以继续执行。`;
111
+ messageText = `🔐 该操作需要二次认证\n\n检测到敏感操作: ${metadata.commandPreview}\n\n📱 请点击以下链接完成扫码认证:\n${metadata.qrCodeUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟\n\n验证成功后,请回复"确认"或者重新发送之前的命令以继续执行。`;
109
112
  }
110
113
 
111
114
  return { content: messageText };
@@ -207,7 +210,7 @@ export default function register(api: OpenClawPluginApi) {
207
210
  `[mfa-auth] Parsed from sessionKey: channel=${parsedChannel}, accountId=${parsedAccountId}, to=${parsedTo}`,
208
211
  );
209
212
 
210
- const session = authManager.generateSession(userId, {
213
+ const session = await authManager.generateSession(userId, {
211
214
  sessionKey,
212
215
  senderId: userId,
213
216
  commandBody: command,
@@ -225,8 +228,6 @@ export default function register(api: OpenClawPluginApi) {
225
228
  return undefined;
226
229
  }
227
230
 
228
- const authUrl = `${getServerBaseUrl()}/mfa-auth/${session.sessionId}`;
229
-
230
231
  api.logger.info(`[mfa-auth] Blocking sensitive tool call: ${toolName} from ${userId}`);
231
232
 
232
233
  // For webchat, use userId as sessionKey instead of agent:main:<userId>
@@ -238,7 +239,7 @@ export default function register(api: OpenClawPluginApi) {
238
239
  parsedChannel,
239
240
  parsedAccountId,
240
241
  parsedTo || userId,
241
- `🔐 该操作需要二次认证\n\n检测到敏感操作: ${preview}\n\n请点击链接完成验证:\n${authUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟\n\n验证成功后,请回复"确认"或者重新发送之前的命令以继续执行。`,
242
+ `🔐 该操作需要二次认证\n\n检测到敏感操作: ${preview}\n\n📱 请点击以下链接完成扫码认证:\n${session.qrCodeUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟\n\n验证成功后,请回复"确认"或者重新发送之前的命令以继续执行。`,
242
243
  userId,
243
244
  sessionKeyForWebchat,
244
245
  );
@@ -253,7 +254,7 @@ export default function register(api: OpenClawPluginApi) {
253
254
  // Also add to pending users as fallback
254
255
  pendingAuthUsers.add(userId);
255
256
  authManager.setSessionMetadata(session.sessionId, {
256
- authUrl,
257
+ qrCodeUrl: session.qrCodeUrl,
257
258
  triggerType: "sensitive_operation",
258
259
  commandPreview: preview,
259
260
  });
@@ -274,41 +275,29 @@ export default function register(api: OpenClawPluginApi) {
274
275
  }
275
276
 
276
277
  if (parsedChannel && parsedChannel !== "web") {
277
- if (parsedChannel !== "feishu") {
278
+ if (false) {
278
279
  api.logger.warn(
279
280
  `[mfa-auth] Channel ${parsedChannel} not supported, skipping auth notification`,
280
281
  );
281
282
  } else {
282
- api.logger.info(
283
- `[mfa-auth] Sensitive operation params: channel=${parsedChannel}, to=${parsedTo}, accountId=${parsedAccountId}, userId=${userId}`,
284
- );
283
+ const messageText = `🔐 该操作需要二次认证\n\n检测到敏感操作: ${preview}\n\n📱 请点击以下链接完成扫码认证:\n${session.qrCodeUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟\n\n验证成功后,请回复"确认"或者重新发送之前的命令以继续执行。`;
285
284
 
286
- try {
287
- await sendAuthMessage(
288
- parsedChannel,
289
- parsedAccountId,
290
- parsedTo || userId,
291
- `🔐 该操作需要二次认证\n\n检测到敏感操作: ${preview}\n\n请点击链接完成验证:\n${authUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟\n\n验证成功后,请回复"确认"或者重新发送之前的命令以继续执行。`,
292
- userId,
293
- );
285
+ await sendAuthMessage(
286
+ parsedChannel,
287
+ parsedAccountId,
288
+ parsedTo || userId,
289
+ messageText,
290
+ userId,
291
+ );
294
292
 
295
- startPollingForAuth(api, userId, session.sessionId, {
296
- triggerType: "sensitive_operation",
297
- isReauth: false,
298
- channel: parsedChannel,
299
- accountId: parsedAccountId,
300
- to: parsedTo,
301
- sessionKey: ctx.sessionKey || "",
302
- });
303
- } catch (error) {
304
- const errorDetails = error instanceof Error ? error.message : String(error);
305
- api.logger.error(
306
- `[mfa-auth] Failed to send sensitive operation auth notification: ${errorDetails}`,
307
- );
308
- api.logger.error(
309
- `[mfa-auth] Sensitive operation notification details: channel=${parsedChannel}, to=${parsedTo}, accountId=${parsedAccountId}`,
310
- );
311
- }
293
+ startPollingForAuth(api, userId, session.sessionId, {
294
+ triggerType: "sensitive_operation",
295
+ isReauth: false,
296
+ channel: parsedChannel,
297
+ accountId: parsedAccountId,
298
+ to: parsedTo,
299
+ sessionKey: ctx.sessionKey || "",
300
+ });
312
301
  }
313
302
  }
314
303
 
@@ -332,6 +321,14 @@ export default function register(api: OpenClawPluginApi) {
332
321
  return;
333
322
  }
334
323
 
324
+ const content = event.content || "";
325
+ const isReauthCommand = content.trim() === "/reauth";
326
+
327
+ if (isReauthCommand) {
328
+ api.logger.info(`[mfa-auth] /reauth command detected, skipping first message auth check`);
329
+ return;
330
+ }
331
+
335
332
  const userId = event.from || ctx.conversationId || "unknown";
336
333
 
337
334
  if (authManager.isUserVerifiedForFirstMessage(userId)) {
@@ -394,7 +391,7 @@ export default function register(api: OpenClawPluginApi) {
394
391
  }
395
392
  }
396
393
 
397
- const session = authManager.generateSession(userId, {
394
+ const session = await authManager.generateSession(userId, {
398
395
  sessionKey,
399
396
  senderId: userId,
400
397
  commandBody: event.content || "",
@@ -414,14 +411,12 @@ export default function register(api: OpenClawPluginApi) {
414
411
  return;
415
412
  }
416
413
 
417
- const authUrl = `${getServerBaseUrl()}/mfa-auth/${session.sessionId}`;
418
-
419
414
  api.logger.info(`[mfa-auth] Blocking first message from ${userId}`);
420
415
 
421
416
  if (parsedChannel === "webchat" || parsedChannel === "web") {
422
417
  pendingAuthUsers.add(userId);
423
418
  authManager.setSessionMetadata(session.sessionId, {
424
- authUrl,
419
+ qrCodeUrl: session.qrCodeUrl,
425
420
  triggerType: "first_message",
426
421
  });
427
422
 
@@ -438,41 +433,30 @@ export default function register(api: OpenClawPluginApi) {
438
433
  }
439
434
 
440
435
  if (parsedChannel && parsedChannel !== "web") {
441
- if (parsedChannel !== "feishu") {
436
+ if (false) {
442
437
  api.logger.warn(
443
438
  `[mfa-auth] Channel ${parsedChannel} not supported, skipping auth notification`,
444
439
  );
445
440
  } else {
446
- api.logger.info(
447
- `[mfa-auth] First message auth params: channel=${parsedChannel}, to=${parsedTo}, accountId=${parsedAccountId}, userId=${userId}`,
448
- );
441
+ const messageText = `🔐 首次对话需要进行认证\n\n为了您的账户安全,首次对话前需要完成身份验证。\n\n📱 请点击以下链接完成扫码认证:\n${session.qrCodeUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟`;
449
442
 
450
- try {
451
- await sendAuthMessage(
452
- parsedChannel,
453
- parsedAccountId,
454
- parsedTo || userId,
455
- `🔐 首次对话需要进行认证\n\n为了您的账户安全,首次对话前需要完成身份验证。\n\n请点击链接完成验证:\n${authUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟`,
456
- userId,
457
- );
443
+ await sendAuthMessage(
444
+ parsedChannel,
445
+ parsedAccountId,
446
+ parsedTo || userId,
447
+ messageText,
448
+ userId,
449
+ sessionKey,
450
+ );
458
451
 
459
- startPollingForAuth(api, userId, session.sessionId, {
460
- triggerType: "first_message",
461
- isReauth: false,
462
- channel: parsedChannel,
463
- accountId: parsedAccountId,
464
- to: parsedTo,
465
- sessionKey: sessionKey,
466
- });
467
- } catch (error) {
468
- const errorDetails = error instanceof Error ? error.message : String(error);
469
- api.logger.error(
470
- `[mfa-auth] Failed to send first message auth notification: ${errorDetails}`,
471
- );
472
- api.logger.error(
473
- `[mfa-auth] Notification details: channel=${parsedChannel}, to=${parsedTo}, accountId=${parsedAccountId}`,
474
- );
475
- }
452
+ startPollingForAuth(api, userId, session.sessionId, {
453
+ triggerType: "first_message",
454
+ isReauth: false,
455
+ channel: parsedChannel,
456
+ accountId: parsedAccountId,
457
+ to: parsedTo,
458
+ sessionKey: sessionKey,
459
+ });
476
460
  }
477
461
  }
478
462
  });
@@ -506,7 +490,7 @@ export default function register(api: OpenClawPluginApi) {
506
490
 
507
491
  api.logger.info(`[mfa-auth] Using sessionKey for reauth: ${sessionKey}`);
508
492
 
509
- const session = authManager.generateSession(userId, {
493
+ const session = await authManager.generateSession(userId, {
510
494
  sessionKey,
511
495
  senderId: userId,
512
496
  commandBody: "/reauth",
@@ -524,18 +508,23 @@ export default function register(api: OpenClawPluginApi) {
524
508
  return { text: "❌ 认证会话创建失败,请稍后重试。" };
525
509
  }
526
510
 
527
- const authUrl = `${getServerBaseUrl()}/mfa-auth/${session.sessionId}`;
528
-
529
511
  api.logger.info(
530
512
  `[mfa-auth] Reauth requested by user ${userId}, session=${session.sessionId}`,
531
513
  );
532
514
 
533
- const messageText = `🔐 重新认证\n\n请点击以下链接完成身份验证:\n${authUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟`;
515
+ const messageText = `🔐 重新认证\n\n📱 请点击以下链接完成扫码认证:\n${session.qrCodeUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟`;
534
516
 
535
517
  // Use sendAuthMessage to ensure consistent delivery via WebSocket for WebChat
536
518
  // This will use the new robust session resolution logic
537
519
  if (parsedChannel === "webchat" || parsedChannel === "web") {
538
520
  try {
521
+ pendingAuthUsers.add(userId);
522
+ authManager.setSessionMetadata(session.sessionId, {
523
+ qrCodeUrl: session.qrCodeUrl,
524
+ triggerType: "first_message",
525
+ isReauth: true,
526
+ });
527
+
539
528
  await sendAuthMessage(
540
529
  parsedChannel,
541
530
  parsedAccountId,
@@ -562,7 +551,7 @@ export default function register(api: OpenClawPluginApi) {
562
551
  }
563
552
  }
564
553
 
565
- if (!parsedChannel || parsedChannel !== "feishu") {
554
+ if (!parsedChannel) {
566
555
  api.logger.warn(`[mfa-auth] Channel ${parsedChannel} not supported`);
567
556
  return { text: "❌ 当前渠道不支持认证。" };
568
557
  }
@@ -576,7 +565,7 @@ export default function register(api: OpenClawPluginApi) {
576
565
  parsedChannel,
577
566
  parsedAccountId,
578
567
  parsedTo || userId,
579
- `🔐 重新认证\n\n请点击以下链接完成身份验证:\n${authUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟`,
568
+ `🔐 重新认证\n\n📱 请点击以下链接完成扫码认证:\n${session.qrCodeUrl}\n\n验证有效期: ${Math.floor(config.timeout / 60000)} 分钟`,
580
569
  userId,
581
570
  );
582
571
 
@@ -598,12 +587,7 @@ export default function register(api: OpenClawPluginApi) {
598
587
  },
599
588
  });
600
589
 
601
- if (!serverStarted) {
602
- api.logger.info("mfa-auth: Starting HTTP server...");
603
- startHttpServer();
604
- serverStarted = true;
605
- api.logger.info("mfa-auth plugin loaded");
606
- }
590
+ api.logger.info("mfa-auth plugin loaded");
607
591
  }
608
592
 
609
593
  function startPollingForAuth(
@@ -619,18 +603,11 @@ function startPollingForAuth(
619
603
  sessionKey?: string;
620
604
  },
621
605
  ) {
622
- // Only start polling if notification is disabled (passive mode)
623
- // Or we can always poll as a fallback?
624
- // User asked for this SPECIFICALLY when enableAuthNotification is false.
625
- // But if it's true, the callback will handle it.
626
- // To avoid double notification, we should check the config here or ensure consumption is atomic.
627
- // Since checkAndConsumeNotification is atomic, we can run this safely even if callback also runs.
628
-
629
606
  api.logger.info(
630
607
  `[mfa-auth] Starting polling for auth status: userId=${userId}, sessionId=${sessionId}`,
631
608
  );
632
609
 
633
- const pollInterval = setInterval(() => {
610
+ const pollInterval = setInterval(async () => {
634
611
  let isVerified = false;
635
612
  if (context.triggerType === "first_message") {
636
613
  isVerified = authManager.isUserVerifiedForFirstMessage(userId);
@@ -638,6 +615,34 @@ function startPollingForAuth(
638
615
  isVerified = authManager.isUserVerifiedForSensitiveOps(userId);
639
616
  }
640
617
 
618
+ if (!isVerified) {
619
+ const session = authManager.getSession(sessionId);
620
+ if (session && session.certToken) {
621
+ try {
622
+ const authResult = await dabbyClient.getAuthResult(session.certToken);
623
+ if (authResult.status === "verified") {
624
+ api.logger.info(`[mfa-auth] Auth verification successful for session ${sessionId}`);
625
+ authManager.markUserVerified(
626
+ userId,
627
+ context.triggerType === "first_message" ? "first_message" : "sensitive_operation",
628
+ context.isReauth,
629
+ );
630
+ isVerified = true;
631
+ } else if (authResult.status === "failed" || authResult.status === "expired") {
632
+ api.logger.warn(
633
+ `[mfa-auth] Auth failed or expired for session ${sessionId}: ${authResult.error}`,
634
+ );
635
+ clearInterval(pollInterval);
636
+ return;
637
+ }
638
+ } catch (error) {
639
+ api.logger.error(
640
+ `[mfa-auth] Failed to check auth status for session ${sessionId}: ${String(error)}`,
641
+ );
642
+ }
643
+ }
644
+ }
645
+
641
646
  if (isVerified) {
642
647
  clearInterval(pollInterval);
643
648
 
@@ -9,13 +9,8 @@ case `uname` in
9
9
  ;;
10
10
  esac
11
11
 
12
- if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules/qrcode-terminal/bin/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules/qrcode-terminal/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/node_modules"
14
- else
15
- export NODE_PATH="/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules/qrcode-terminal/bin/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules/qrcode-terminal/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/node_modules:$NODE_PATH"
16
- fi
17
12
  if [ -x "$basedir/node" ]; then
18
13
  exec "$basedir/node" "$basedir/../qrcode-terminal/bin/qrcode-terminal.js" "$@"
19
- else
14
+ else
20
15
  exec node "$basedir/../qrcode-terminal/bin/qrcode-terminal.js" "$@"
21
16
  fi
@@ -0,0 +1,17 @@
1
+ @ECHO off
2
+ GOTO start
3
+ :find_dp0
4
+ SET dp0=%~dp0
5
+ EXIT /b
6
+ :start
7
+ SETLOCAL
8
+ CALL :find_dp0
9
+
10
+ IF EXIST "%dp0%\node.exe" (
11
+ SET "_prog=%dp0%\node.exe"
12
+ ) ELSE (
13
+ SET "_prog=node"
14
+ SET PATHEXT=%PATHEXT:;.JS;=;%
15
+ )
16
+
17
+ endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\qrcode-terminal\bin\qrcode-terminal.js" %*
@@ -2,23 +2,11 @@
2
2
  $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
3
3
 
4
4
  $exe=""
5
- $pathsep=":"
6
- $env_node_path=$env:NODE_PATH
7
- $new_node_path="C:\Users\asta1\PycharmProjects\cclawd\node_modules\.pnpm\qrcode-terminal@0.12.0\node_modules\qrcode-terminal\bin\node_modules;C:\Users\asta1\PycharmProjects\cclawd\node_modules\.pnpm\qrcode-terminal@0.12.0\node_modules\qrcode-terminal\node_modules;C:\Users\asta1\PycharmProjects\cclawd\node_modules\.pnpm\qrcode-terminal@0.12.0\node_modules;C:\Users\asta1\PycharmProjects\cclawd\node_modules\.pnpm\node_modules"
8
5
  if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
9
6
  # Fix case when both the Windows and Linux builds of Node
10
7
  # are installed in the same directory
11
8
  $exe=".exe"
12
- $pathsep=";"
13
- } else {
14
- $new_node_path="/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules/qrcode-terminal/bin/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules/qrcode-terminal/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/node_modules"
15
- }
16
- if ([string]::IsNullOrEmpty($env_node_path)) {
17
- $env:NODE_PATH=$new_node_path
18
- } else {
19
- $env:NODE_PATH="$new_node_path$pathsep$env_node_path"
20
9
  }
21
-
22
10
  $ret=0
23
11
  if (Test-Path "$basedir/node$exe") {
24
12
  # Support pipeline input
@@ -37,5 +25,4 @@ if (Test-Path "$basedir/node$exe") {
37
25
  }
38
26
  $ret=$LASTEXITCODE
39
27
  }
40
- $env:NODE_PATH=$env_node_path
41
28
  exit $ret
@@ -9,13 +9,8 @@ case `uname` in
9
9
  ;;
10
10
  esac
11
11
 
12
- if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/dist/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/tsx@4.21.0/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/node_modules"
14
- else
15
- export NODE_PATH="/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/dist/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/tsx@4.21.0/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/node_modules:$NODE_PATH"
16
- fi
17
12
  if [ -x "$basedir/node" ]; then
18
13
  exec "$basedir/node" "$basedir/../tsx/dist/cli.mjs" "$@"
19
- else
14
+ else
20
15
  exec node "$basedir/../tsx/dist/cli.mjs" "$@"
21
16
  fi
@@ -0,0 +1,17 @@
1
+ @ECHO off
2
+ GOTO start
3
+ :find_dp0
4
+ SET dp0=%~dp0
5
+ EXIT /b
6
+ :start
7
+ SETLOCAL
8
+ CALL :find_dp0
9
+
10
+ IF EXIST "%dp0%\node.exe" (
11
+ SET "_prog=%dp0%\node.exe"
12
+ ) ELSE (
13
+ SET "_prog=node"
14
+ SET PATHEXT=%PATHEXT:;.JS;=;%
15
+ )
16
+
17
+ endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\tsx\dist\cli.mjs" %*
@@ -2,23 +2,11 @@
2
2
  $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
3
3
 
4
4
  $exe=""
5
- $pathsep=":"
6
- $env_node_path=$env:NODE_PATH
7
- $new_node_path="C:\Users\asta1\PycharmProjects\cclawd\node_modules\.pnpm\tsx@4.21.0\node_modules\tsx\dist\node_modules;C:\Users\asta1\PycharmProjects\cclawd\node_modules\.pnpm\tsx@4.21.0\node_modules\tsx\node_modules;C:\Users\asta1\PycharmProjects\cclawd\node_modules\.pnpm\tsx@4.21.0\node_modules;C:\Users\asta1\PycharmProjects\cclawd\node_modules\.pnpm\node_modules"
8
5
  if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
9
6
  # Fix case when both the Windows and Linux builds of Node
10
7
  # are installed in the same directory
11
8
  $exe=".exe"
12
- $pathsep=";"
13
- } else {
14
- $new_node_path="/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/dist/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/tsx@4.21.0/node_modules/tsx/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/tsx@4.21.0/node_modules:/mnt/c/Users/asta1/PycharmProjects/cclawd/node_modules/.pnpm/node_modules"
15
- }
16
- if ([string]::IsNullOrEmpty($env_node_path)) {
17
- $env:NODE_PATH=$new_node_path
18
- } else {
19
- $env:NODE_PATH="$new_node_path$pathsep$env_node_path"
20
9
  }
21
-
22
10
  $ret=0
23
11
  if (Test-Path "$basedir/node$exe") {
24
12
  # Support pipeline input
@@ -37,5 +25,4 @@ if (Test-Path "$basedir/node$exe") {
37
25
  }
38
26
  $ret=$LASTEXITCODE
39
27
  }
40
- $env:NODE_PATH=$env_node_path
41
28
  exit $ret
@@ -0,0 +1,103 @@
1
+ {
2
+ "name": "openclaw-mfa-auth",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "../../node_modules/.pnpm/@larksuiteoapi+node-sdk@1.59.0/node_modules/@larksuiteoapi/node-sdk": {
8
+ "version": "1.59.0",
9
+ "license": "MIT",
10
+ "dependencies": {
11
+ "axios": "~1.13.3",
12
+ "lodash.identity": "^3.0.0",
13
+ "lodash.merge": "^4.6.2",
14
+ "lodash.pickby": "^4.6.0",
15
+ "protobufjs": "^7.2.6",
16
+ "qs": "^6.14.2",
17
+ "ws": "^8.19.0"
18
+ },
19
+ "devDependencies": {
20
+ "@koa/router": "^12.0.0",
21
+ "@rollup/plugin-alias": "^3.1.9",
22
+ "@rollup/plugin-typescript": "^8.3.2",
23
+ "@types/jest": "^28.1.3",
24
+ "@types/lodash.merge": "^4.6.7",
25
+ "@types/lodash.pick": "^4.4.7",
26
+ "@types/qs": "^6.9.16",
27
+ "@types/ws": "^8.5.10",
28
+ "@typescript-eslint/parser": "^5.27.1",
29
+ "body-parser": "^1.20.1",
30
+ "eslint": "^8.17.0",
31
+ "eslint-config-airbnb-base": "^15.0.0",
32
+ "eslint-config-prettier": "^8.5.0",
33
+ "eslint-plugin-import": "^2.26.0",
34
+ "express": "^4.18.2",
35
+ "jest": "^28.1.1",
36
+ "koa": "^2.13.4",
37
+ "koa-body": "^5.0.0",
38
+ "prettier": "2.6.2",
39
+ "rollup": "^2.75.5",
40
+ "rollup-plugin-dts": "^4.2.2",
41
+ "rollup-plugin-license": "^2.8.1",
42
+ "ts-jest": "^28.0.5",
43
+ "ts-node": "^10.8.1",
44
+ "tsconfig-paths": "^4.0.0",
45
+ "tslib": "^2.4.0",
46
+ "typescript": "^4.7.3"
47
+ }
48
+ },
49
+ "../../node_modules/.pnpm/@types+node@20.19.37/node_modules/@types/node": {
50
+ "version": "20.19.37",
51
+ "dev": true,
52
+ "license": "MIT",
53
+ "dependencies": {
54
+ "undici-types": "~6.21.0"
55
+ }
56
+ },
57
+ "../../node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules/qrcode-terminal": {
58
+ "version": "0.12.0",
59
+ "bin": {
60
+ "qrcode-terminal": "bin/qrcode-terminal.js"
61
+ },
62
+ "devDependencies": {
63
+ "expect.js": "*",
64
+ "jshint": "*",
65
+ "mocha": "*",
66
+ "sinon": "*"
67
+ }
68
+ },
69
+ "../../node_modules/.pnpm/tsx@4.21.0/node_modules/tsx": {
70
+ "version": "4.21.0",
71
+ "license": "MIT",
72
+ "dependencies": {
73
+ "esbuild": "~0.27.0",
74
+ "get-tsconfig": "^4.7.5"
75
+ },
76
+ "bin": {
77
+ "tsx": "dist/cli.mjs"
78
+ },
79
+ "engines": {
80
+ "node": ">=18.0.0"
81
+ },
82
+ "optionalDependencies": {
83
+ "fsevents": "~2.3.3"
84
+ }
85
+ },
86
+ "node_modules/@larksuiteoapi/node-sdk": {
87
+ "resolved": "../../node_modules/.pnpm/@larksuiteoapi+node-sdk@1.59.0/node_modules/@larksuiteoapi/node-sdk",
88
+ "link": true
89
+ },
90
+ "node_modules/@types/node": {
91
+ "resolved": "../../node_modules/.pnpm/@types+node@20.19.37/node_modules/@types/node",
92
+ "link": true
93
+ },
94
+ "node_modules/qrcode-terminal": {
95
+ "resolved": "../../node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules/qrcode-terminal",
96
+ "link": true
97
+ },
98
+ "node_modules/tsx": {
99
+ "resolved": "../../node_modules/.pnpm/tsx@4.21.0/node_modules/tsx",
100
+ "link": true
101
+ }
102
+ }
103
+ }