@kodelyth/zalouser 2026.5.42 → 2026.6.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 (71) hide show
  1. package/klaw.plugin.json +286 -3
  2. package/package.json +17 -4
  3. package/api.ts +0 -9
  4. package/channel-plugin-api.ts +0 -3
  5. package/contract-api.ts +0 -2
  6. package/doctor-contract-api.ts +0 -1
  7. package/index.ts +0 -34
  8. package/runtime-api.ts +0 -62
  9. package/secret-contract-api.ts +0 -4
  10. package/setup-entry.ts +0 -9
  11. package/setup-plugin-api.ts +0 -2
  12. package/src/accounts.runtime.ts +0 -1
  13. package/src/accounts.test-mocks.ts +0 -14
  14. package/src/accounts.test.ts +0 -298
  15. package/src/accounts.ts +0 -136
  16. package/src/channel-api.ts +0 -16
  17. package/src/channel.adapters.ts +0 -432
  18. package/src/channel.directory.test.ts +0 -59
  19. package/src/channel.runtime.ts +0 -12
  20. package/src/channel.sendpayload.test.ts +0 -311
  21. package/src/channel.setup.test.ts +0 -30
  22. package/src/channel.setup.ts +0 -12
  23. package/src/channel.test.ts +0 -424
  24. package/src/channel.ts +0 -221
  25. package/src/config-schema.ts +0 -33
  26. package/src/directory.ts +0 -54
  27. package/src/doctor-contract.ts +0 -156
  28. package/src/doctor.test.ts +0 -87
  29. package/src/doctor.ts +0 -37
  30. package/src/group-policy.test.ts +0 -61
  31. package/src/group-policy.ts +0 -83
  32. package/src/message-sid.test.ts +0 -66
  33. package/src/message-sid.ts +0 -80
  34. package/src/monitor.account-scope.test.ts +0 -122
  35. package/src/monitor.group-gating.test.ts +0 -967
  36. package/src/monitor.send-mocks.ts +0 -20
  37. package/src/monitor.ts +0 -1057
  38. package/src/probe.test.ts +0 -60
  39. package/src/probe.ts +0 -35
  40. package/src/qr-temp-file.ts +0 -19
  41. package/src/reaction.test.ts +0 -19
  42. package/src/reaction.ts +0 -32
  43. package/src/runtime.ts +0 -9
  44. package/src/security-audit.test.ts +0 -83
  45. package/src/security-audit.ts +0 -71
  46. package/src/send-receipt.ts +0 -31
  47. package/src/send.test.ts +0 -424
  48. package/src/send.ts +0 -280
  49. package/src/session-route.ts +0 -121
  50. package/src/setup-core.ts +0 -36
  51. package/src/setup-surface.test.ts +0 -367
  52. package/src/setup-surface.ts +0 -481
  53. package/src/setup-test-helpers.ts +0 -42
  54. package/src/shared.ts +0 -92
  55. package/src/status-issues.test.ts +0 -31
  56. package/src/status-issues.ts +0 -55
  57. package/src/test-helpers.ts +0 -26
  58. package/src/text-styles.test.ts +0 -203
  59. package/src/text-styles.ts +0 -540
  60. package/src/tool.test.ts +0 -212
  61. package/src/tool.ts +0 -200
  62. package/src/types.ts +0 -127
  63. package/src/zalo-js.credentials.test.ts +0 -465
  64. package/src/zalo-js.test-mocks.ts +0 -89
  65. package/src/zalo-js.ts +0 -1889
  66. package/src/zca-client.test.ts +0 -27
  67. package/src/zca-client.ts +0 -259
  68. package/src/zca-constants.ts +0 -55
  69. package/src/zca-js-exports.d.ts +0 -22
  70. package/test-api.ts +0 -21
  71. package/tsconfig.json +0 -16
@@ -1,424 +0,0 @@
1
- import { createNonExitingRuntimeEnv } from "klaw/plugin-sdk/plugin-test-runtime";
2
- import { beforeEach, describe, expect, it, vi } from "vitest";
3
- import "./zalo-js.test-mocks.js";
4
- import {
5
- zalouserAuthAdapter,
6
- zalouserGroupsAdapter,
7
- zalouserMessageActions,
8
- zalouserOutboundAdapter,
9
- zalouserPairingTextAdapter,
10
- zalouserResolverAdapter,
11
- zalouserSecurityAdapter,
12
- } from "./channel.adapters.js";
13
- import { setZalouserRuntime } from "./runtime.js";
14
- import { sendMessageZalouser, sendReactionZalouser } from "./send.js";
15
- import {
16
- listZaloFriendsMatchingMock,
17
- startZaloQrLoginMock,
18
- waitForZaloQrLoginMock,
19
- } from "./zalo-js.test-mocks.js";
20
-
21
- vi.mock("./qr-temp-file.js", () => ({
22
- writeQrDataUrlToTempFile: vi.fn(async () => null),
23
- }));
24
-
25
- vi.mock("./send.js", async () => {
26
- const actual = (await vi.importActual("./send.js")) as Record<string, unknown>;
27
- return {
28
- ...actual,
29
- sendMessageZalouser: vi.fn(async () => ({ ok: true, messageId: "mid-1" })),
30
- sendReactionZalouser: vi.fn(async () => ({ ok: true })),
31
- };
32
- });
33
-
34
- const mockSendMessage = vi.mocked(sendMessageZalouser);
35
- const mockSendReaction = vi.mocked(sendReactionZalouser);
36
-
37
- function requireZalouserSendText() {
38
- const sendText = zalouserOutboundAdapter.sendText;
39
- if (!sendText) {
40
- throw new Error("zalouser outbound.sendText unavailable");
41
- }
42
- return sendText;
43
- }
44
-
45
- function getResolveToolPolicy() {
46
- const resolveToolPolicy = zalouserGroupsAdapter.resolveToolPolicy;
47
- if (!resolveToolPolicy) {
48
- throw new Error("resolveToolPolicy unavailable");
49
- }
50
- return resolveToolPolicy;
51
- }
52
-
53
- function requireZalouserResolveRequireMention() {
54
- const resolveRequireMention = zalouserGroupsAdapter.resolveRequireMention;
55
- if (!resolveRequireMention) {
56
- throw new Error("resolveRequireMention unavailable");
57
- }
58
- return resolveRequireMention;
59
- }
60
-
61
- function requireZalouserPairingNormalizer() {
62
- const normalizeAllowEntry = zalouserPairingTextAdapter.normalizeAllowEntry;
63
- if (!normalizeAllowEntry) {
64
- throw new Error("pairing.normalizeAllowEntry unavailable");
65
- }
66
- return normalizeAllowEntry;
67
- }
68
-
69
- function resolveGroupToolPolicy(
70
- groups: Record<string, { tools: { allow?: string[]; deny?: string[] } }>,
71
- groupId: string,
72
- ) {
73
- return getResolveToolPolicy()({
74
- cfg: {
75
- channels: {
76
- zalouser: {
77
- groups,
78
- },
79
- },
80
- },
81
- accountId: "default",
82
- groupId,
83
- groupChannel: groupId,
84
- });
85
- }
86
-
87
- describe("zalouser outbound", () => {
88
- beforeEach(() => {
89
- mockSendMessage.mockClear();
90
- setZalouserRuntime({
91
- channel: {
92
- text: {
93
- resolveChunkMode: vi.fn(() => "newline"),
94
- resolveTextChunkLimit: vi.fn(() => 10),
95
- },
96
- },
97
- } as never);
98
- });
99
-
100
- it("passes markdown chunk settings through sendText", async () => {
101
- const sendText = requireZalouserSendText();
102
-
103
- const result = await sendText({
104
- cfg: { channels: { zalouser: { enabled: true } } } as never,
105
- to: "group:123456",
106
- text: "hello world\nthis is a test",
107
- accountId: "default",
108
- } as never);
109
-
110
- expect(mockSendMessage).toHaveBeenCalledWith("123456", "hello world\nthis is a test", {
111
- profile: "default",
112
- isGroup: true,
113
- textMode: "markdown",
114
- textChunkMode: "newline",
115
- textChunkLimit: 10,
116
- });
117
- expect(result).toEqual({
118
- channel: "zalouser",
119
- messageId: "mid-1",
120
- ok: true,
121
- });
122
- });
123
-
124
- it("uses the selected account profile for direct outbound messages", async () => {
125
- const sendText = requireZalouserSendText();
126
-
127
- const result = await sendText({
128
- cfg: {
129
- channels: {
130
- zalouser: {
131
- accounts: {
132
- work: {
133
- profile: "work-profile",
134
- },
135
- },
136
- },
137
- },
138
- } as never,
139
- to: "user:987654",
140
- text: "hello user",
141
- accountId: "work",
142
- } as never);
143
-
144
- expect(mockSendMessage).toHaveBeenCalledWith("987654", "hello user", {
145
- profile: "work-profile",
146
- isGroup: false,
147
- textMode: "markdown",
148
- textChunkMode: "newline",
149
- textChunkLimit: 10,
150
- });
151
- expect(result).toEqual({
152
- channel: "zalouser",
153
- messageId: "mid-1",
154
- ok: true,
155
- });
156
- });
157
-
158
- it("keeps the default account profile for unscoped outbound messages", async () => {
159
- const sendText = requireZalouserSendText();
160
-
161
- await sendText({
162
- cfg: { channels: { zalouser: { enabled: true } } } as never,
163
- to: "user:111222",
164
- text: "hello default",
165
- } as never);
166
-
167
- expect(mockSendMessage).toHaveBeenCalledWith("111222", "hello default", {
168
- profile: "default",
169
- isGroup: false,
170
- textMode: "markdown",
171
- textChunkMode: "newline",
172
- textChunkLimit: 10,
173
- });
174
- });
175
- });
176
-
177
- describe("zalouser outbound chunking", () => {
178
- it("chunks outbound text without requiring Zalouser runtime initialization", () => {
179
- const chunker = zalouserOutboundAdapter.chunker;
180
- if (!chunker) {
181
- throw new Error("zalouser outbound.chunker unavailable");
182
- }
183
-
184
- expect(chunker("alpha beta", 5)).toEqual(["alpha", "beta"]);
185
- });
186
- });
187
-
188
- describe("zalouser channel policies", () => {
189
- beforeEach(() => {
190
- mockSendReaction.mockClear();
191
- mockSendReaction.mockResolvedValue({ ok: true } as never);
192
- });
193
-
194
- it("normalizes dm allowlist entries after trimming channel prefixes", () => {
195
- const resolveDmPolicy = zalouserSecurityAdapter.resolveDmPolicy;
196
- if (!resolveDmPolicy) {
197
- throw new Error("resolveDmPolicy unavailable");
198
- }
199
-
200
- const cfg = {
201
- channels: {
202
- zalouser: {
203
- dmPolicy: "allowlist",
204
- allowFrom: [" zlu:123456 "],
205
- },
206
- },
207
- } as never;
208
- const account = {
209
- accountId: "default",
210
- enabled: true,
211
- authenticated: false,
212
- profile: "default",
213
- config: {
214
- dmPolicy: "allowlist",
215
- allowFrom: [" zlu:123456 "],
216
- },
217
- } as never;
218
-
219
- const result = resolveDmPolicy({ cfg, account });
220
- if (!result) {
221
- throw new Error("zalouser resolveDmPolicy returned null");
222
- }
223
-
224
- expect(result.policy).toBe("allowlist");
225
- expect(result.allowFrom).toEqual([" zlu:123456 "]);
226
- expect(result.normalizeEntry?.(" zlu:123456 ")).toBe("123456");
227
- });
228
-
229
- it("normalizes pairing allowlist entries after trimming channel prefixes", () => {
230
- const normalizeAllowEntry = requireZalouserPairingNormalizer();
231
-
232
- expect(normalizeAllowEntry(" zlu:123456 ")).toBe("123456");
233
- expect(normalizeAllowEntry(" zalouser:654321 ")).toBe("654321");
234
- });
235
-
236
- it("resolves requireMention from group config", () => {
237
- const resolveRequireMention = requireZalouserResolveRequireMention();
238
- const requireMention = resolveRequireMention({
239
- cfg: {
240
- channels: {
241
- zalouser: {
242
- groups: {
243
- "123": { requireMention: false },
244
- },
245
- },
246
- },
247
- },
248
- accountId: "default",
249
- groupId: "123",
250
- groupChannel: "123",
251
- });
252
- expect(requireMention).toBe(false);
253
- });
254
-
255
- it("resolves group tool policy by explicit group id", () => {
256
- const policy = resolveGroupToolPolicy({ "123": { tools: { allow: ["search"] } } }, "123");
257
- expect(policy).toEqual({ allow: ["search"] });
258
- });
259
-
260
- it("falls back to wildcard group policy", () => {
261
- const policy = resolveGroupToolPolicy({ "*": { tools: { deny: ["system.run"] } } }, "missing");
262
- expect(policy).toEqual({ deny: ["system.run"] });
263
- });
264
-
265
- it("handles react action", async () => {
266
- const actions = zalouserMessageActions;
267
- expect(
268
- actions?.describeMessageTool?.({ cfg: { channels: { zalouser: { enabled: true } } } })
269
- ?.actions,
270
- ).toEqual(["react"]);
271
- const result = await actions?.handleAction?.({
272
- channel: "zalouser",
273
- action: "react",
274
- params: {
275
- threadId: "123456",
276
- messageId: "111",
277
- cliMsgId: "222",
278
- emoji: "👍",
279
- },
280
- cfg: {
281
- channels: {
282
- zalouser: {
283
- enabled: true,
284
- profile: "default",
285
- },
286
- },
287
- },
288
- });
289
- expect(mockSendReaction).toHaveBeenCalledWith({
290
- profile: "default",
291
- threadId: "123456",
292
- isGroup: false,
293
- msgId: "111",
294
- cliMsgId: "222",
295
- emoji: "👍",
296
- remove: false,
297
- });
298
- expect(result).toEqual({
299
- content: [{ type: "text", text: "Reacted 👍 on 111" }],
300
- details: {
301
- messageId: "111",
302
- cliMsgId: "222",
303
- threadId: "123456",
304
- },
305
- });
306
- });
307
-
308
- it("honors the selected Zalouser account during discovery", () => {
309
- const actions = zalouserMessageActions;
310
- const cfg = {
311
- channels: {
312
- zalouser: {
313
- enabled: true,
314
- profile: "default",
315
- accounts: {
316
- default: {
317
- enabled: false,
318
- profile: "default",
319
- },
320
- work: {
321
- enabled: true,
322
- profile: "work",
323
- },
324
- },
325
- },
326
- },
327
- };
328
-
329
- expect(actions?.describeMessageTool?.({ cfg, accountId: "default" })).toBeNull();
330
- expect(actions?.describeMessageTool?.({ cfg, accountId: "work" })?.actions).toEqual(["react"]);
331
- });
332
- });
333
-
334
- describe("zalouser account resolution", () => {
335
- beforeEach(() => {
336
- listZaloFriendsMatchingMock.mockReset();
337
- startZaloQrLoginMock.mockReset();
338
- waitForZaloQrLoginMock.mockReset();
339
- });
340
-
341
- it("uses the configured default account for omitted target lookup", async () => {
342
- const resolveTargets = zalouserResolverAdapter.resolveTargets;
343
- if (!resolveTargets) {
344
- throw new Error("zalouser resolver.resolveTargets unavailable");
345
- }
346
-
347
- listZaloFriendsMatchingMock.mockResolvedValue([
348
- { userId: "42", displayName: "Work User" } as never,
349
- ]);
350
-
351
- const result = await resolveTargets({
352
- cfg: {
353
- channels: {
354
- zalouser: {
355
- defaultAccount: "work",
356
- accounts: {
357
- work: {
358
- profile: "work-profile",
359
- },
360
- },
361
- },
362
- },
363
- } as never,
364
- inputs: ["Work User"],
365
- kind: "user",
366
- runtime: createNonExitingRuntimeEnv(),
367
- });
368
-
369
- expect(listZaloFriendsMatchingMock).toHaveBeenCalledWith("work-profile", "Work User");
370
- expect(result).toEqual([
371
- {
372
- input: "Work User",
373
- resolved: true,
374
- id: "42",
375
- name: "Work User",
376
- note: undefined,
377
- },
378
- ]);
379
- });
380
-
381
- it("uses the configured default account for omitted qr login", async () => {
382
- const login = zalouserAuthAdapter.login;
383
- if (!login) {
384
- throw new Error("zalouser auth.login unavailable");
385
- }
386
-
387
- startZaloQrLoginMock.mockResolvedValue({
388
- message: "qr ready",
389
- qrDataUrl: "data:image/png;base64,abc",
390
- } as never);
391
- waitForZaloQrLoginMock.mockResolvedValue({
392
- connected: true,
393
- userId: "u-1",
394
- displayName: "Work User",
395
- } as never);
396
-
397
- const runtime = createNonExitingRuntimeEnv();
398
-
399
- await login({
400
- cfg: {
401
- channels: {
402
- zalouser: {
403
- defaultAccount: "work",
404
- accounts: {
405
- work: {
406
- profile: "work-profile",
407
- },
408
- },
409
- },
410
- },
411
- } as never,
412
- runtime,
413
- });
414
-
415
- expect(startZaloQrLoginMock).toHaveBeenCalledWith({
416
- profile: "work-profile",
417
- timeoutMs: 35_000,
418
- });
419
- expect(waitForZaloQrLoginMock).toHaveBeenCalledWith({
420
- profile: "work-profile",
421
- timeoutMs: 180_000,
422
- });
423
- });
424
- });
package/src/channel.ts DELETED
@@ -1,221 +0,0 @@
1
- import { createChatChannelPlugin } from "klaw/plugin-sdk/channel-core";
2
- import { createAccountStatusSink } from "klaw/plugin-sdk/channel-lifecycle";
3
- import { buildPassiveProbedChannelStatusSummary } from "klaw/plugin-sdk/extension-shared";
4
- import { createLazyRuntimeModule } from "klaw/plugin-sdk/lazy-runtime";
5
- import {
6
- createAsyncComputedAccountStatusAdapter,
7
- createDefaultChannelRuntimeState,
8
- } from "klaw/plugin-sdk/status-helpers";
9
- import {
10
- checkZcaAuthenticated,
11
- resolveZalouserAccountSync,
12
- type ResolvedZalouserAccount,
13
- } from "./accounts.js";
14
- import type { ChannelDirectoryEntry, ChannelPlugin } from "./channel-api.js";
15
- import { DEFAULT_ACCOUNT_ID } from "./channel-api.js";
16
- import {
17
- zalouserAuthAdapter,
18
- zalouserGroupsAdapter,
19
- zalouserMessageAdapter,
20
- zalouserMessageActions,
21
- zalouserMessagingAdapter,
22
- zalouserOutboundAdapter,
23
- zalouserPairingTextAdapter,
24
- resolveZalouserQrProfile,
25
- zalouserResolverAdapter,
26
- zalouserSecurityAdapter,
27
- zalouserThreadingAdapter,
28
- } from "./channel.adapters.js";
29
- import { listZalouserDirectoryGroupMembers } from "./directory.js";
30
- import type { ZalouserProbeResult } from "./probe.js";
31
- import { createZalouserSetupWizardProxy, zalouserSetupAdapter } from "./setup-core.js";
32
- import { createZalouserPluginBase } from "./shared.js";
33
- import { collectZalouserStatusIssues } from "./status-issues.js";
34
-
35
- const loadZalouserChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime.js"));
36
- const zalouserSetupWizardProxy = createZalouserSetupWizardProxy(
37
- async () => (await import("./setup-surface.js")).zalouserSetupWizard,
38
- );
39
-
40
- function mapUser(params: {
41
- id: string;
42
- name?: string | null;
43
- avatarUrl?: string | null;
44
- raw?: unknown;
45
- }): ChannelDirectoryEntry {
46
- return {
47
- kind: "user",
48
- id: params.id,
49
- name: params.name ?? undefined,
50
- avatarUrl: params.avatarUrl ?? undefined,
51
- raw: params.raw,
52
- };
53
- }
54
-
55
- function mapGroup(params: {
56
- id: string;
57
- name?: string | null;
58
- raw?: unknown;
59
- }): ChannelDirectoryEntry {
60
- return {
61
- kind: "group",
62
- id: params.id,
63
- name: params.name ?? undefined,
64
- raw: params.raw,
65
- };
66
- }
67
-
68
- export const zalouserPlugin: ChannelPlugin<ResolvedZalouserAccount, ZalouserProbeResult> =
69
- createChatChannelPlugin({
70
- base: {
71
- ...createZalouserPluginBase({
72
- setupWizard: zalouserSetupWizardProxy,
73
- setup: zalouserSetupAdapter,
74
- }),
75
- groups: zalouserGroupsAdapter,
76
- actions: zalouserMessageActions,
77
- messaging: zalouserMessagingAdapter,
78
- directory: {
79
- self: async ({ cfg, accountId }) => {
80
- const { getZaloUserInfo } = await loadZalouserChannelRuntime();
81
- const account = resolveZalouserAccountSync({ cfg: cfg, accountId });
82
- const parsed = await getZaloUserInfo(account.profile);
83
- if (!parsed?.userId) {
84
- return null;
85
- }
86
- return mapUser({
87
- id: parsed.userId,
88
- name: parsed.displayName ?? null,
89
- avatarUrl: parsed.avatar ?? null,
90
- raw: parsed,
91
- });
92
- },
93
- listPeers: async ({ cfg, accountId, query, limit }) => {
94
- const { listZaloFriendsMatching } = await loadZalouserChannelRuntime();
95
- const account = resolveZalouserAccountSync({ cfg: cfg, accountId });
96
- const friends = await listZaloFriendsMatching(account.profile, query);
97
- const rows = friends.map((friend) =>
98
- mapUser({
99
- id: friend.userId,
100
- name: friend.displayName ?? null,
101
- avatarUrl: friend.avatar ?? null,
102
- raw: friend,
103
- }),
104
- );
105
- return typeof limit === "number" && limit > 0 ? rows.slice(0, limit) : rows;
106
- },
107
- listGroups: async ({ cfg, accountId, query, limit }) => {
108
- const { listZaloGroupsMatching } = await loadZalouserChannelRuntime();
109
- const account = resolveZalouserAccountSync({ cfg: cfg, accountId });
110
- const groups = await listZaloGroupsMatching(account.profile, query);
111
- const rows = groups.map((group) =>
112
- mapGroup({
113
- id: `group:${group.groupId}`,
114
- name: group.name ?? null,
115
- raw: group,
116
- }),
117
- );
118
- return typeof limit === "number" && limit > 0 ? rows.slice(0, limit) : rows;
119
- },
120
- listGroupMembers: async ({ cfg, accountId, groupId, limit }) => {
121
- const { listZaloGroupMembers } = await loadZalouserChannelRuntime();
122
- return await listZalouserDirectoryGroupMembers(
123
- {
124
- cfg,
125
- accountId: accountId ?? undefined,
126
- groupId,
127
- limit: limit ?? undefined,
128
- },
129
- { listZaloGroupMembers },
130
- );
131
- },
132
- },
133
- resolver: zalouserResolverAdapter,
134
- auth: zalouserAuthAdapter,
135
- message: zalouserMessageAdapter,
136
- status: createAsyncComputedAccountStatusAdapter<ResolvedZalouserAccount, ZalouserProbeResult>(
137
- {
138
- defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID),
139
- collectStatusIssues: collectZalouserStatusIssues,
140
- buildChannelSummary: ({ snapshot }) => buildPassiveProbedChannelStatusSummary(snapshot),
141
- probeAccount: async ({ account, timeoutMs }) =>
142
- (await loadZalouserChannelRuntime()).probeZalouser(account.profile, timeoutMs),
143
- resolveAccountSnapshot: async ({ account, runtime }) => {
144
- const configured = await checkZcaAuthenticated(account.profile);
145
- const configError = "not authenticated";
146
- return {
147
- accountId: account.accountId,
148
- name: account.name,
149
- enabled: account.enabled,
150
- configured,
151
- extra: {
152
- dmPolicy: account.config.dmPolicy ?? "pairing",
153
- lastError: configured
154
- ? (runtime?.lastError ?? null)
155
- : (runtime?.lastError ?? configError),
156
- },
157
- };
158
- },
159
- },
160
- ),
161
- gateway: {
162
- startAccount: async (ctx) => {
163
- const { getZaloUserInfo } = await loadZalouserChannelRuntime();
164
- const account = ctx.account;
165
- let userLabel = "";
166
- try {
167
- const userInfo = await getZaloUserInfo(account.profile);
168
- if (userInfo?.displayName) {
169
- userLabel = ` (${userInfo.displayName})`;
170
- }
171
- ctx.setStatus({
172
- accountId: account.accountId,
173
- profile: userInfo,
174
- });
175
- } catch {
176
- // ignore probe errors
177
- }
178
- const statusSink = createAccountStatusSink({
179
- accountId: ctx.accountId,
180
- setStatus: ctx.setStatus,
181
- });
182
- ctx.log?.info(`[${account.accountId}] starting zalouser provider${userLabel}`);
183
- const { monitorZalouserProvider } = await import("./monitor.js");
184
- return monitorZalouserProvider({
185
- account,
186
- config: ctx.cfg,
187
- runtime: ctx.runtime,
188
- abortSignal: ctx.abortSignal,
189
- statusSink,
190
- });
191
- },
192
- loginWithQrStart: async (params) => {
193
- const { startZaloQrLogin } = await loadZalouserChannelRuntime();
194
- const profile = resolveZalouserQrProfile(params.accountId);
195
- return await startZaloQrLogin({
196
- profile,
197
- force: params.force,
198
- timeoutMs: params.timeoutMs,
199
- });
200
- },
201
- loginWithQrWait: async (params) => {
202
- const { waitForZaloQrLogin } = await loadZalouserChannelRuntime();
203
- const profile = resolveZalouserQrProfile(params.accountId);
204
- return await waitForZaloQrLogin({
205
- profile,
206
- timeoutMs: params.timeoutMs,
207
- });
208
- },
209
- logoutAccount: async (ctx) =>
210
- await (
211
- await loadZalouserChannelRuntime()
212
- ).logoutZaloProfile(ctx.account.profile || resolveZalouserQrProfile(ctx.accountId)),
213
- },
214
- },
215
- security: zalouserSecurityAdapter,
216
- threading: zalouserThreadingAdapter,
217
- pairing: {
218
- text: zalouserPairingTextAdapter,
219
- },
220
- outbound: zalouserOutboundAdapter,
221
- });
@@ -1,33 +0,0 @@
1
- import {
2
- AllowFromListSchema,
3
- buildCatchallMultiAccountChannelSchema,
4
- DmPolicySchema,
5
- GroupPolicySchema,
6
- MarkdownConfigSchema,
7
- ToolPolicySchema,
8
- } from "klaw/plugin-sdk/channel-config-schema";
9
- import { z } from "zod";
10
-
11
- const groupConfigSchema = z.object({
12
- enabled: z.boolean().optional(),
13
- requireMention: z.boolean().optional(),
14
- tools: ToolPolicySchema,
15
- });
16
-
17
- const zalouserAccountSchema = z.object({
18
- name: z.string().optional(),
19
- enabled: z.boolean().optional(),
20
- markdown: MarkdownConfigSchema,
21
- profile: z.string().optional(),
22
- dangerouslyAllowNameMatching: z.boolean().optional(),
23
- dmPolicy: DmPolicySchema.optional(),
24
- allowFrom: AllowFromListSchema,
25
- historyLimit: z.number().int().min(0).optional(),
26
- groupAllowFrom: AllowFromListSchema,
27
- groupPolicy: GroupPolicySchema.optional().default("allowlist"),
28
- groups: z.object({}).catchall(groupConfigSchema).optional(),
29
- messagePrefix: z.string().optional(),
30
- responsePrefix: z.string().optional(),
31
- });
32
-
33
- export const ZalouserConfigSchema = buildCatchallMultiAccountChannelSchema(zalouserAccountSchema);