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
@@ -0,0 +1,115 @@
1
+ {
2
+ "name": "openclaw-mfa-auth",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "openclaw-mfa-auth",
9
+ "version": "1.0.0",
10
+ "dependencies": {
11
+ "@larksuiteoapi/node-sdk": "^1.59.0",
12
+ "qrcode-terminal": "^0.12.0",
13
+ "tsx": "^4.21.0"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "^20.0.0"
17
+ }
18
+ },
19
+ "../../node_modules/.pnpm/@larksuiteoapi+node-sdk@1.59.0/node_modules/@larksuiteoapi/node-sdk": {
20
+ "version": "1.59.0",
21
+ "license": "MIT",
22
+ "dependencies": {
23
+ "axios": "~1.13.3",
24
+ "lodash.identity": "^3.0.0",
25
+ "lodash.merge": "^4.6.2",
26
+ "lodash.pickby": "^4.6.0",
27
+ "protobufjs": "^7.2.6",
28
+ "qs": "^6.14.2",
29
+ "ws": "^8.19.0"
30
+ },
31
+ "devDependencies": {
32
+ "@koa/router": "^12.0.0",
33
+ "@rollup/plugin-alias": "^3.1.9",
34
+ "@rollup/plugin-typescript": "^8.3.2",
35
+ "@types/jest": "^28.1.3",
36
+ "@types/lodash.merge": "^4.6.7",
37
+ "@types/lodash.pick": "^4.4.7",
38
+ "@types/qs": "^6.9.16",
39
+ "@types/ws": "^8.5.10",
40
+ "@typescript-eslint/parser": "^5.27.1",
41
+ "body-parser": "^1.20.1",
42
+ "eslint": "^8.17.0",
43
+ "eslint-config-airbnb-base": "^15.0.0",
44
+ "eslint-config-prettier": "^8.5.0",
45
+ "eslint-plugin-import": "^2.26.0",
46
+ "express": "^4.18.2",
47
+ "jest": "^28.1.1",
48
+ "koa": "^2.13.4",
49
+ "koa-body": "^5.0.0",
50
+ "prettier": "2.6.2",
51
+ "rollup": "^2.75.5",
52
+ "rollup-plugin-dts": "^4.2.2",
53
+ "rollup-plugin-license": "^2.8.1",
54
+ "ts-jest": "^28.0.5",
55
+ "ts-node": "^10.8.1",
56
+ "tsconfig-paths": "^4.0.0",
57
+ "tslib": "^2.4.0",
58
+ "typescript": "^4.7.3"
59
+ }
60
+ },
61
+ "../../node_modules/.pnpm/@types+node@20.19.37/node_modules/@types/node": {
62
+ "version": "20.19.37",
63
+ "dev": true,
64
+ "license": "MIT",
65
+ "dependencies": {
66
+ "undici-types": "~6.21.0"
67
+ }
68
+ },
69
+ "../../node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules/qrcode-terminal": {
70
+ "version": "0.12.0",
71
+ "bin": {
72
+ "qrcode-terminal": "bin/qrcode-terminal.js"
73
+ },
74
+ "devDependencies": {
75
+ "expect.js": "*",
76
+ "jshint": "*",
77
+ "mocha": "*",
78
+ "sinon": "*"
79
+ }
80
+ },
81
+ "../../node_modules/.pnpm/tsx@4.21.0/node_modules/tsx": {
82
+ "version": "4.21.0",
83
+ "license": "MIT",
84
+ "dependencies": {
85
+ "esbuild": "~0.27.0",
86
+ "get-tsconfig": "^4.7.5"
87
+ },
88
+ "bin": {
89
+ "tsx": "dist/cli.mjs"
90
+ },
91
+ "engines": {
92
+ "node": ">=18.0.0"
93
+ },
94
+ "optionalDependencies": {
95
+ "fsevents": "~2.3.3"
96
+ }
97
+ },
98
+ "node_modules/@larksuiteoapi/node-sdk": {
99
+ "resolved": "../../node_modules/.pnpm/@larksuiteoapi+node-sdk@1.59.0/node_modules/@larksuiteoapi/node-sdk",
100
+ "link": true
101
+ },
102
+ "node_modules/@types/node": {
103
+ "resolved": "../../node_modules/.pnpm/@types+node@20.19.37/node_modules/@types/node",
104
+ "link": true
105
+ },
106
+ "node_modules/qrcode-terminal": {
107
+ "resolved": "../../node_modules/.pnpm/qrcode-terminal@0.12.0/node_modules/qrcode-terminal",
108
+ "link": true
109
+ },
110
+ "node_modules/tsx": {
111
+ "resolved": "../../node_modules/.pnpm/tsx@4.21.0/node_modules/tsx",
112
+ "link": true
113
+ }
114
+ }
115
+ }
@@ -6,7 +6,7 @@
6
6
  "dev": "tsx watch index.ts"
7
7
  },
8
8
  "dependencies": {
9
- "@larksuiteoapi/node-sdk": "^1.24.0",
9
+ "@larksuiteoapi/node-sdk": "^1.59.0",
10
10
  "qrcode-terminal": "^0.12.0",
11
11
  "tsx": "^4.21.0"
12
12
  },
@@ -171,12 +171,12 @@ export class AuthManager {
171
171
  return this.providers.get(methodType);
172
172
  }
173
173
 
174
- generateSession(
174
+ async generateSession(
175
175
  userId: string,
176
176
  originalContext: PendingAuthContext,
177
177
  authMethod: string = this.config.defaultAuthMethod,
178
178
  extraFields?: Partial<AuthSession>,
179
- ): AuthSession | null {
179
+ ): Promise<AuthSession | null> {
180
180
  const provider = this.getProvider(authMethod);
181
181
  if (!provider) {
182
182
  console.error(`[mfa-auth] Auth provider not found: ${authMethod}`);
@@ -195,6 +195,8 @@ export class AuthManager {
195
195
 
196
196
  this.sessions.set(sessionId, session);
197
197
 
198
+ await provider.initialize(session);
199
+
198
200
  if (this.config.debug) {
199
201
  console.log(`[mfa-auth] Generated session: ${sessionId}`);
200
202
  console.log(`[mfa-auth] User ID: ${userId}`);
@@ -19,7 +19,6 @@ export const config: MfaConfig = {
19
19
  timeout: 5 * 60 * 1000,
20
20
  verificationDuration:
21
21
  Number.parseInt(process.env.MFA_VERIFICATION_DURATION || "", 10) || 2 * 60 * 1000,
22
- port: 18801,
23
22
  domain: process.env.MFA_AUTH_DOMAIN || "",
24
23
  allowlistUsers: [],
25
24
  enabledAuthMethods: ["qr-code"],
@@ -38,9 +37,7 @@ export const config: MfaConfig = {
38
37
  };
39
38
 
40
39
  export const dabbyConfig: DabbyConfig = {
41
- clientId: process.env.DABBY_CLIENT_ID || "",
42
- clientSecret: process.env.DABBY_CLIENT_SECRET || "",
40
+ apiKey: process.env.MFA_AUTH_API_KEY || "",
43
41
  apiBaseUrl: process.env.DABBY_API_BASE_URL || "",
44
- tokenCacheDuration: 7000000,
45
42
  pollInterval: 2000,
46
43
  };
@@ -9,223 +9,144 @@ describe("DabbyClient", () => {
9
9
  beforeEach(() => {
10
10
  mockFetch = vi.fn();
11
11
  global.fetch = mockFetch as any;
12
+ // Ensure apiKey is set for tests
13
+ dabbyConfig.apiKey = "test-api-key";
12
14
  client = new DabbyClient(dabbyConfig);
13
15
  });
14
16
 
15
- describe("getAccessToken", () => {
16
- it("should fetch and cache access token", async () => {
17
+ describe("getVerifyCode", () => {
18
+ it("should fetch verify code with API key", async () => {
19
+ const testQrCodeUrl = "https://example.com/auth?certToken=cert-token-789";
17
20
  mockFetch.mockResolvedValueOnce({
18
21
  ok: true,
19
22
  json: async () => ({
20
23
  retCode: 0,
21
- retMessage: "成功",
22
- accessToken: "test-token-123",
23
- expireSeconds: 7200,
24
- apiVersion: "3.3.0",
25
- timestamp: Date.now(),
26
- }),
27
- });
28
-
29
- const token = await client.getAccessToken();
30
- expect(token).toBe("test-token-123");
31
- expect(mockFetch).toHaveBeenCalledTimes(1);
32
- });
33
-
34
- it("should use cached token if not expired", async () => {
35
- mockFetch.mockResolvedValueOnce({
36
- ok: true,
37
- json: async () => ({
38
- retCode: 0,
39
- retMessage: "成功",
40
- accessToken: "test-token-123",
41
- expireSeconds: 7200,
42
- apiVersion: "3.3.0",
43
- timestamp: Date.now(),
24
+ message: "成功",
25
+ data: {
26
+ certToken: "cert-token-789",
27
+ qrCodeUrl: testQrCodeUrl,
28
+ },
44
29
  }),
45
30
  });
46
31
 
47
- await client.getAccessToken();
48
- await client.getAccessToken();
49
- expect(mockFetch).toHaveBeenCalledTimes(1);
50
- });
32
+ const result = await client.getVerifyCode();
33
+ expect(result.certToken).toBe("cert-token-789");
34
+ expect(result.qrCodeUrl).toBe(`${testQrCodeUrl}&fromSource=Cclawd`);
51
35
 
52
- it("should refresh token when forced", async () => {
53
- mockFetch.mockResolvedValue({
54
- ok: true,
55
- json: async () => ({
56
- retCode: 0,
57
- retMessage: "成功",
58
- accessToken: "new-token-456",
59
- expireSeconds: 7200,
60
- apiVersion: "3.3.0",
61
- timestamp: Date.now(),
36
+ expect(mockFetch).toHaveBeenCalledWith(
37
+ expect.stringContaining("/api/v1/getVerifyCode"),
38
+ expect.objectContaining({
39
+ method: "POST",
40
+ body: expect.stringContaining('"apiKey":"test-api-key"'),
62
41
  }),
63
- });
64
-
65
- await client.getAccessToken();
66
- await client.refreshAccessToken();
67
- expect(mockFetch).toHaveBeenCalledTimes(2);
68
- });
69
-
70
- it("should throw error when clientId or clientSecret is missing", async () => {
71
- const emptyClient = new DabbyClient({
72
- clientId: "",
73
- clientSecret: "",
74
- apiBaseUrl: "https://api.dabby.com.cn/v2/api",
75
- tokenCacheDuration: 7000000,
76
- pollInterval: 2000,
77
- });
78
-
79
- await expect(emptyClient.getAccessToken()).rejects.toThrow(
80
- "Dabby clientId and clientSecret are not configured",
81
42
  );
82
43
  });
83
44
 
84
45
  it("should throw error when API returns non-zero retCode", async () => {
85
- mockFetch.mockResolvedValueOnce({
46
+ mockFetch.mockResolvedValue({
86
47
  ok: true,
87
48
  json: async () => ({
88
49
  retCode: 1001,
89
- retMessage: "认证失败",
90
- accessToken: "",
91
- expireSeconds: 0,
92
- apiVersion: "3.3.0",
93
- timestamp: Date.now(),
50
+ message: "生成二维码失败",
51
+ data: null,
94
52
  }),
95
53
  });
96
54
 
97
- await expect(client.getAccessToken()).rejects.toThrow("Dabby API error: 认证失败");
55
+ await expect(client.getVerifyCode()).rejects.toThrow("Dabby API error: 生成二维码失败");
98
56
  });
99
57
  });
100
58
 
101
- describe("getQrCode", () => {
102
- it("should fetch QR code with access token", async () => {
103
- mockFetch.mockResolvedValueOnce({
104
- ok: true,
105
- json: async () => ({
106
- retCode: 0,
107
- retMessage: "成功",
108
- accessToken: "test-token",
109
- expireSeconds: 7200,
110
- apiVersion: "3.3.0",
111
- timestamp: Date.now(),
112
- }),
113
- });
114
-
59
+ describe("getAuthResult", () => {
60
+ it("should return verified status when authSuccess is true", async () => {
115
61
  mockFetch.mockResolvedValueOnce({
116
62
  ok: true,
117
63
  json: async () => ({
118
64
  retCode: 0,
119
- retMessage: "成功",
120
- apiVersion: "3.3.0",
121
- tokenInfo: {
122
- authType: "ScanAuth",
123
- certToken: "cert-token-789",
124
- createdAt: "2024-01-01 00:00:00",
125
- expireAt: "2024-01-01 00:05:00",
126
- expireTimeMs: Date.now() + 5 * 60 * 1000,
127
- qrcodeContent: "https://h5.dabby.com.cn/authhtml/#/auth?certToken=cert-token-789",
128
- timestamp: Date.now(),
65
+ message: "成功",
66
+ data: {
67
+ authSuccess: true,
68
+ authResult: {
69
+ idNum: "44000000000000",
70
+ fullName: "张三",
71
+ },
72
+ message: "成功",
129
73
  },
130
74
  }),
131
75
  });
132
76
 
133
- const result = await client.getQrCode();
134
- expect(result.certToken).toBe("cert-token-789");
135
- expect(result.qrcodeContent).toContain("h5.dabby.com.cn");
136
- });
137
- });
77
+ const result = await client.getAuthResult("cert-token-789");
78
+ expect(result.status).toBe("verified");
79
+ expect(result.authObject?.fullName).toBe("张三");
138
80
 
139
- describe("getAuthResult", () => {
140
- it("should return verified status when resCode is 0", async () => {
141
- mockFetch.mockResolvedValueOnce({
142
- ok: true,
143
- json: async () => ({
144
- retCode: 0,
145
- retMessage: "成功",
146
- accessToken: "test-token",
147
- expireSeconds: 7200,
148
- apiVersion: "3.3.0",
149
- timestamp: Date.now(),
81
+ expect(mockFetch).toHaveBeenCalledWith(
82
+ expect.stringContaining("/api/v1/checkAuthStatus"),
83
+ expect.objectContaining({
84
+ method: "POST",
85
+ body: expect.stringContaining('"apiKey":"test-api-key"'),
150
86
  }),
151
- });
87
+ );
88
+ });
152
89
 
90
+ it("should return failed status when authSuccess is false", async () => {
153
91
  mockFetch.mockResolvedValueOnce({
154
92
  ok: true,
155
93
  json: async () => ({
156
94
  retCode: 0,
157
- retMessage: "成功",
158
- apiVersion: "3.3.0",
159
- authData: {
160
- authMode: 66,
161
- authObject: {
162
- idNum: "44000000000000",
163
- fullName: "张三",
164
- },
165
- authType: "ScanAuth",
166
- portrait: "",
167
- resCode: 0,
168
- resStr: "00XX",
95
+ message: "成功",
96
+ data: {
97
+ authSuccess: false,
98
+ authResult: {},
99
+ message: "认证失败或超时",
169
100
  },
170
- authInfo: {},
171
101
  }),
172
102
  });
173
103
 
174
104
  const result = await client.getAuthResult("cert-token-789");
175
- expect(result.status).toBe("verified");
176
- expect(result.authObject?.fullName).toBe("张三");
105
+ expect(result.status).toBe("failed");
106
+ expect(result.error).toContain("认证失败或超时");
177
107
  });
178
108
 
179
- it("should return failed status when resCode is not 0", async () => {
109
+ it("should return pending status when retCode is 4401", async () => {
180
110
  mockFetch.mockResolvedValueOnce({
181
111
  ok: true,
182
112
  json: async () => ({
183
- retCode: 0,
184
- retMessage: "成功",
185
- accessToken: "test-token",
186
- expireSeconds: 7200,
187
- apiVersion: "3.3.0",
188
- timestamp: Date.now(),
113
+ retCode: 4401,
114
+ message: "等待认证",
115
+ data: null,
189
116
  }),
190
117
  });
191
118
 
119
+ const result = await client.getAuthResult("cert-token-789");
120
+ expect(result.status).toBe("pending");
121
+ });
122
+
123
+ it("should return failed status on API error", async () => {
192
124
  mockFetch.mockResolvedValueOnce({
193
125
  ok: true,
194
126
  json: async () => ({
195
- retCode: 0,
196
- retMessage: "成功",
197
- apiVersion: "3.3.0",
198
- authData: {
199
- authMode: 66,
200
- authObject: {
201
- idNum: "",
202
- fullName: "",
203
- },
204
- authType: "ScanAuth",
205
- portrait: "",
206
- resCode: 1002,
207
- resStr: "01XX",
208
- },
209
- authInfo: {},
127
+ retCode: 500,
128
+ message: "服务器错误",
129
+ data: null,
210
130
  }),
211
131
  });
212
132
 
213
133
  const result = await client.getAuthResult("cert-token-789");
214
134
  expect(result.status).toBe("failed");
215
- expect(result.error).toContain("认证失败");
135
+ expect(result.error).toContain("服务器错误");
216
136
  });
217
137
  });
218
138
 
219
139
  describe("checkQrCodeExpired", () => {
220
- it("should return true when QR code is expired", () => {
140
+ // This is not using config so we need to instantiate client
141
+ it("should return true when QR code is expired", async () => {
221
142
  const expiredTime = Date.now() - 1000;
222
- const isExpired = client.checkQrCodeExpired("cert-token", expiredTime);
143
+ const isExpired = await client.checkQrCodeExpired("cert-token", expiredTime);
223
144
  expect(isExpired).toBe(true);
224
145
  });
225
146
 
226
- it("should return false when QR code is not expired", () => {
147
+ it("should return false when QR code is not expired", async () => {
227
148
  const futureTime = Date.now() + 5 * 60 * 1000;
228
- const isExpired = client.checkQrCodeExpired("cert-token", futureTime);
149
+ const isExpired = await client.checkQrCodeExpired("cert-token", futureTime);
229
150
  expect(isExpired).toBe(false);
230
151
  });
231
152
  });