@clawdbot/zalouser 2026.1.16 → 2026.1.21
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.
- package/CHANGELOG.md +23 -0
- package/clawdbot.plugin.json +11 -0
- package/index.ts +7 -3
- package/package.json +21 -2
- package/src/accounts.ts +17 -21
- package/src/channel.ts +196 -103
- package/src/config-schema.ts +24 -0
- package/src/monitor.ts +229 -46
- package/src/onboarding.ts +259 -83
- package/src/probe.ts +28 -0
- package/src/runtime.ts +14 -0
- package/src/status-issues.test.ts +58 -0
- package/src/status-issues.ts +81 -0
- package/src/types.ts +4 -11
- package/src/zca.ts +26 -1
- package/src/core-bridge.ts +0 -171
package/src/monitor.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import type { ChildProcess } from "node:child_process";
|
|
2
2
|
|
|
3
|
-
import type { RuntimeEnv } from "
|
|
4
|
-
import {
|
|
5
|
-
isControlCommandMessage,
|
|
6
|
-
shouldComputeCommandAuthorized,
|
|
7
|
-
} from "../../../src/auto-reply/command-detection.js";
|
|
8
|
-
import { finalizeInboundContext } from "../../../src/auto-reply/reply/inbound-context.js";
|
|
9
|
-
import { resolveCommandAuthorizedFromAuthorizers } from "../../../src/channels/command-gating.js";
|
|
10
|
-
import { loadCoreChannelDeps, type CoreChannelDeps } from "./core-bridge.js";
|
|
3
|
+
import type { ClawdbotConfig, RuntimeEnv } from "clawdbot/plugin-sdk";
|
|
4
|
+
import { mergeAllowlist, summarizeMapping } from "clawdbot/plugin-sdk";
|
|
11
5
|
import { sendMessageZalouser } from "./send.js";
|
|
12
|
-
import type {
|
|
13
|
-
|
|
6
|
+
import type {
|
|
7
|
+
ResolvedZalouserAccount,
|
|
8
|
+
ZcaFriend,
|
|
9
|
+
ZcaGroup,
|
|
10
|
+
ZcaMessage,
|
|
11
|
+
} from "./types.js";
|
|
12
|
+
import { getZalouserRuntime } from "./runtime.js";
|
|
13
|
+
import { parseJsonOutput, runZca, runZcaStreaming } from "./zca.js";
|
|
14
14
|
|
|
15
15
|
export type ZalouserMonitorOptions = {
|
|
16
16
|
account: ResolvedZalouserAccount;
|
|
17
|
-
config:
|
|
17
|
+
config: ClawdbotConfig;
|
|
18
18
|
runtime: RuntimeEnv;
|
|
19
19
|
abortSignal: AbortSignal;
|
|
20
20
|
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
|
|
@@ -26,8 +26,29 @@ export type ZalouserMonitorResult = {
|
|
|
26
26
|
|
|
27
27
|
const ZALOUSER_TEXT_LIMIT = 2000;
|
|
28
28
|
|
|
29
|
-
function
|
|
30
|
-
|
|
29
|
+
function normalizeZalouserEntry(entry: string): string {
|
|
30
|
+
return entry.replace(/^(zalouser|zlu):/i, "").trim();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function buildNameIndex<T>(
|
|
34
|
+
items: T[],
|
|
35
|
+
nameFn: (item: T) => string | undefined,
|
|
36
|
+
): Map<string, T[]> {
|
|
37
|
+
const index = new Map<string, T[]>();
|
|
38
|
+
for (const item of items) {
|
|
39
|
+
const name = nameFn(item)?.trim().toLowerCase();
|
|
40
|
+
if (!name) continue;
|
|
41
|
+
const list = index.get(name) ?? [];
|
|
42
|
+
list.push(item);
|
|
43
|
+
index.set(name, list);
|
|
44
|
+
}
|
|
45
|
+
return index;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type ZalouserCoreRuntime = ReturnType<typeof getZalouserRuntime>;
|
|
49
|
+
|
|
50
|
+
function logVerbose(core: ZalouserCoreRuntime, runtime: RuntimeEnv, message: string): void {
|
|
51
|
+
if (core.logging.shouldLogVerbose()) {
|
|
31
52
|
runtime.log(`[zalouser] ${message}`);
|
|
32
53
|
}
|
|
33
54
|
}
|
|
@@ -41,6 +62,39 @@ function isSenderAllowed(senderId: string, allowFrom: string[]): boolean {
|
|
|
41
62
|
});
|
|
42
63
|
}
|
|
43
64
|
|
|
65
|
+
function normalizeGroupSlug(raw?: string | null): string {
|
|
66
|
+
const trimmed = raw?.trim().toLowerCase() ?? "";
|
|
67
|
+
if (!trimmed) return "";
|
|
68
|
+
return trimmed
|
|
69
|
+
.replace(/^#/, "")
|
|
70
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
71
|
+
.replace(/^-+|-+$/g, "");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isGroupAllowed(params: {
|
|
75
|
+
groupId: string;
|
|
76
|
+
groupName?: string | null;
|
|
77
|
+
groups: Record<string, { allow?: boolean; enabled?: boolean }>;
|
|
78
|
+
}): boolean {
|
|
79
|
+
const groups = params.groups ?? {};
|
|
80
|
+
const keys = Object.keys(groups);
|
|
81
|
+
if (keys.length === 0) return false;
|
|
82
|
+
const candidates = [
|
|
83
|
+
params.groupId,
|
|
84
|
+
`group:${params.groupId}`,
|
|
85
|
+
params.groupName ?? "",
|
|
86
|
+
normalizeGroupSlug(params.groupName ?? ""),
|
|
87
|
+
].filter(Boolean);
|
|
88
|
+
for (const candidate of candidates) {
|
|
89
|
+
const entry = groups[candidate];
|
|
90
|
+
if (!entry) continue;
|
|
91
|
+
return entry.allow !== false && entry.enabled !== false;
|
|
92
|
+
}
|
|
93
|
+
const wildcard = groups["*"];
|
|
94
|
+
if (wildcard) return wildcard.allow !== false && wildcard.enabled !== false;
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
44
98
|
function startZcaListener(
|
|
45
99
|
runtime: RuntimeEnv,
|
|
46
100
|
profile: string,
|
|
@@ -95,8 +149,8 @@ function startZcaListener(
|
|
|
95
149
|
async function processMessage(
|
|
96
150
|
message: ZcaMessage,
|
|
97
151
|
account: ResolvedZalouserAccount,
|
|
98
|
-
config:
|
|
99
|
-
|
|
152
|
+
config: ClawdbotConfig,
|
|
153
|
+
core: ZalouserCoreRuntime,
|
|
100
154
|
runtime: RuntimeEnv,
|
|
101
155
|
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void,
|
|
102
156
|
): Promise<void> {
|
|
@@ -106,21 +160,42 @@ async function processMessage(
|
|
|
106
160
|
const isGroup = metadata?.isGroup ?? false;
|
|
107
161
|
const senderId = metadata?.fromId ?? threadId;
|
|
108
162
|
const senderName = metadata?.senderName ?? "";
|
|
163
|
+
const groupName = metadata?.threadName ?? "";
|
|
109
164
|
const chatId = threadId;
|
|
110
165
|
|
|
166
|
+
const defaultGroupPolicy = config.channels?.defaults?.groupPolicy;
|
|
167
|
+
const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "open";
|
|
168
|
+
const groups = account.config.groups ?? {};
|
|
169
|
+
if (isGroup) {
|
|
170
|
+
if (groupPolicy === "disabled") {
|
|
171
|
+
logVerbose(core, runtime, `zalouser: drop group ${chatId} (groupPolicy=disabled)`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (groupPolicy === "allowlist") {
|
|
175
|
+
const allowed = isGroupAllowed({ groupId: chatId, groupName, groups });
|
|
176
|
+
if (!allowed) {
|
|
177
|
+
logVerbose(core, runtime, `zalouser: drop group ${chatId} (not allowlisted)`);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
111
183
|
const dmPolicy = account.config.dmPolicy ?? "pairing";
|
|
112
184
|
const configAllowFrom = (account.config.allowFrom ?? []).map((v) => String(v));
|
|
113
185
|
const rawBody = content.trim();
|
|
114
|
-
const shouldComputeAuth = shouldComputeCommandAuthorized(
|
|
186
|
+
const shouldComputeAuth = core.channel.commands.shouldComputeCommandAuthorized(
|
|
187
|
+
rawBody,
|
|
188
|
+
config,
|
|
189
|
+
);
|
|
115
190
|
const storeAllowFrom =
|
|
116
191
|
!isGroup && (dmPolicy !== "open" || shouldComputeAuth)
|
|
117
|
-
? await
|
|
192
|
+
? await core.channel.pairing.readAllowFromStore("zalouser").catch(() => [])
|
|
118
193
|
: [];
|
|
119
194
|
const effectiveAllowFrom = [...configAllowFrom, ...storeAllowFrom];
|
|
120
195
|
const useAccessGroups = config.commands?.useAccessGroups !== false;
|
|
121
196
|
const senderAllowedForCommands = isSenderAllowed(senderId, effectiveAllowFrom);
|
|
122
197
|
const commandAuthorized = shouldComputeAuth
|
|
123
|
-
? resolveCommandAuthorizedFromAuthorizers({
|
|
198
|
+
? core.channel.commands.resolveCommandAuthorizedFromAuthorizers({
|
|
124
199
|
useAccessGroups,
|
|
125
200
|
authorizers: [{ configured: effectiveAllowFrom.length > 0, allowed: senderAllowedForCommands }],
|
|
126
201
|
})
|
|
@@ -128,7 +203,7 @@ async function processMessage(
|
|
|
128
203
|
|
|
129
204
|
if (!isGroup) {
|
|
130
205
|
if (dmPolicy === "disabled") {
|
|
131
|
-
logVerbose(
|
|
206
|
+
logVerbose(core, runtime, `Blocked zalouser DM from ${senderId} (dmPolicy=disabled)`);
|
|
132
207
|
return;
|
|
133
208
|
}
|
|
134
209
|
|
|
@@ -137,18 +212,18 @@ async function processMessage(
|
|
|
137
212
|
|
|
138
213
|
if (!allowed) {
|
|
139
214
|
if (dmPolicy === "pairing") {
|
|
140
|
-
const { code, created } = await
|
|
215
|
+
const { code, created } = await core.channel.pairing.upsertPairingRequest({
|
|
141
216
|
channel: "zalouser",
|
|
142
217
|
id: senderId,
|
|
143
218
|
meta: { name: senderName || undefined },
|
|
144
219
|
});
|
|
145
220
|
|
|
146
221
|
if (created) {
|
|
147
|
-
logVerbose(
|
|
222
|
+
logVerbose(core, runtime, `zalouser pairing request sender=${senderId}`);
|
|
148
223
|
try {
|
|
149
224
|
await sendMessageZalouser(
|
|
150
225
|
chatId,
|
|
151
|
-
|
|
226
|
+
core.channel.pairing.buildPairingReply({
|
|
152
227
|
channel: "zalouser",
|
|
153
228
|
idLine: `Your Zalo user id: ${senderId}`,
|
|
154
229
|
code,
|
|
@@ -158,7 +233,7 @@ async function processMessage(
|
|
|
158
233
|
statusSink?.({ lastOutboundAt: Date.now() });
|
|
159
234
|
} catch (err) {
|
|
160
235
|
logVerbose(
|
|
161
|
-
|
|
236
|
+
core,
|
|
162
237
|
runtime,
|
|
163
238
|
`zalouser pairing reply failed for ${senderId}: ${String(err)}`,
|
|
164
239
|
);
|
|
@@ -166,7 +241,7 @@ async function processMessage(
|
|
|
166
241
|
}
|
|
167
242
|
} else {
|
|
168
243
|
logVerbose(
|
|
169
|
-
|
|
244
|
+
core,
|
|
170
245
|
runtime,
|
|
171
246
|
`Blocked unauthorized zalouser sender ${senderId} (dmPolicy=${dmPolicy})`,
|
|
172
247
|
);
|
|
@@ -176,14 +251,18 @@ async function processMessage(
|
|
|
176
251
|
}
|
|
177
252
|
}
|
|
178
253
|
|
|
179
|
-
if (
|
|
180
|
-
|
|
254
|
+
if (
|
|
255
|
+
isGroup &&
|
|
256
|
+
core.channel.commands.isControlCommandMessage(rawBody, config) &&
|
|
257
|
+
commandAuthorized !== true
|
|
258
|
+
) {
|
|
259
|
+
logVerbose(core, runtime, `zalouser: drop control command from unauthorized sender ${senderId}`);
|
|
181
260
|
return;
|
|
182
261
|
}
|
|
183
262
|
|
|
184
263
|
const peer = isGroup ? { kind: "group" as const, id: chatId } : { kind: "group" as const, id: senderId };
|
|
185
264
|
|
|
186
|
-
const route =
|
|
265
|
+
const route = core.channel.routing.resolveAgentRoute({
|
|
187
266
|
cfg: config,
|
|
188
267
|
channel: "zalouser",
|
|
189
268
|
accountId: account.accountId,
|
|
@@ -194,16 +273,25 @@ async function processMessage(
|
|
|
194
273
|
},
|
|
195
274
|
});
|
|
196
275
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
276
|
+
const fromLabel = isGroup ? `group:${chatId}` : senderName || `user:${senderId}`;
|
|
277
|
+
const storePath = core.channel.session.resolveStorePath(config.session?.store, {
|
|
278
|
+
agentId: route.agentId,
|
|
279
|
+
});
|
|
280
|
+
const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(config);
|
|
281
|
+
const previousTimestamp = core.channel.session.readSessionUpdatedAt({
|
|
282
|
+
storePath,
|
|
283
|
+
sessionKey: route.sessionKey,
|
|
284
|
+
});
|
|
285
|
+
const body = core.channel.reply.formatAgentEnvelope({
|
|
286
|
+
channel: "Zalo Personal",
|
|
287
|
+
from: fromLabel,
|
|
202
288
|
timestamp: timestamp ? timestamp * 1000 : undefined,
|
|
289
|
+
previousTimestamp,
|
|
290
|
+
envelope: envelopeOptions,
|
|
203
291
|
body: rawBody,
|
|
204
292
|
});
|
|
205
293
|
|
|
206
|
-
const ctxPayload = finalizeInboundContext({
|
|
294
|
+
const ctxPayload = core.channel.reply.finalizeInboundContext({
|
|
207
295
|
Body: body,
|
|
208
296
|
RawBody: rawBody,
|
|
209
297
|
CommandBody: rawBody,
|
|
@@ -223,7 +311,15 @@ async function processMessage(
|
|
|
223
311
|
OriginatingTo: `zalouser:${chatId}`,
|
|
224
312
|
});
|
|
225
313
|
|
|
226
|
-
|
|
314
|
+
void core.channel.session.recordSessionMetaFromInbound({
|
|
315
|
+
storePath,
|
|
316
|
+
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
|
317
|
+
ctx: ctxPayload,
|
|
318
|
+
}).catch((err) => {
|
|
319
|
+
runtime.error?.(`zalouser: failed updating session meta: ${String(err)}`);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
227
323
|
ctx: ctxPayload,
|
|
228
324
|
cfg: config,
|
|
229
325
|
dispatcherOptions: {
|
|
@@ -234,7 +330,7 @@ async function processMessage(
|
|
|
234
330
|
chatId,
|
|
235
331
|
isGroup,
|
|
236
332
|
runtime,
|
|
237
|
-
|
|
333
|
+
core,
|
|
238
334
|
statusSink,
|
|
239
335
|
});
|
|
240
336
|
},
|
|
@@ -253,10 +349,10 @@ async function deliverZalouserReply(params: {
|
|
|
253
349
|
chatId: string;
|
|
254
350
|
isGroup: boolean;
|
|
255
351
|
runtime: RuntimeEnv;
|
|
256
|
-
|
|
352
|
+
core: ZalouserCoreRuntime;
|
|
257
353
|
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
|
|
258
354
|
}): Promise<void> {
|
|
259
|
-
const { payload, profile, chatId, isGroup, runtime,
|
|
355
|
+
const { payload, profile, chatId, isGroup, runtime, core, statusSink } = params;
|
|
260
356
|
|
|
261
357
|
const mediaList = payload.mediaUrls?.length
|
|
262
358
|
? payload.mediaUrls
|
|
@@ -270,7 +366,7 @@ async function deliverZalouserReply(params: {
|
|
|
270
366
|
const caption = first ? payload.text : undefined;
|
|
271
367
|
first = false;
|
|
272
368
|
try {
|
|
273
|
-
logVerbose(
|
|
369
|
+
logVerbose(core, runtime, `Sending media to ${chatId}`);
|
|
274
370
|
await sendMessageZalouser(chatId, caption ?? "", {
|
|
275
371
|
profile,
|
|
276
372
|
mediaUrl,
|
|
@@ -285,8 +381,8 @@ async function deliverZalouserReply(params: {
|
|
|
285
381
|
}
|
|
286
382
|
|
|
287
383
|
if (payload.text) {
|
|
288
|
-
const chunks =
|
|
289
|
-
logVerbose(
|
|
384
|
+
const chunks = core.channel.text.chunkMarkdownText(payload.text, ZALOUSER_TEXT_LIMIT);
|
|
385
|
+
logVerbose(core, runtime, `Sending ${chunks.length} text chunk(s) to ${chatId}`);
|
|
290
386
|
for (const chunk of chunks) {
|
|
291
387
|
try {
|
|
292
388
|
await sendMessageZalouser(chatId, chunk, { profile, isGroup });
|
|
@@ -301,14 +397,101 @@ async function deliverZalouserReply(params: {
|
|
|
301
397
|
export async function monitorZalouserProvider(
|
|
302
398
|
options: ZalouserMonitorOptions,
|
|
303
399
|
): Promise<ZalouserMonitorResult> {
|
|
304
|
-
|
|
400
|
+
let { account, config } = options;
|
|
401
|
+
const { abortSignal, statusSink, runtime } = options;
|
|
305
402
|
|
|
306
|
-
const
|
|
403
|
+
const core = getZalouserRuntime();
|
|
307
404
|
let stopped = false;
|
|
308
405
|
let proc: ChildProcess | null = null;
|
|
309
406
|
let restartTimer: ReturnType<typeof setTimeout> | null = null;
|
|
310
407
|
let resolveRunning: (() => void) | null = null;
|
|
311
408
|
|
|
409
|
+
try {
|
|
410
|
+
const profile = account.profile;
|
|
411
|
+
const allowFromEntries = (account.config.allowFrom ?? [])
|
|
412
|
+
.map((entry) => normalizeZalouserEntry(String(entry)))
|
|
413
|
+
.filter((entry) => entry && entry !== "*");
|
|
414
|
+
|
|
415
|
+
if (allowFromEntries.length > 0) {
|
|
416
|
+
const result = await runZca(["friend", "list", "-j"], { profile, timeout: 15000 });
|
|
417
|
+
if (result.ok) {
|
|
418
|
+
const friends = parseJsonOutput<ZcaFriend[]>(result.stdout) ?? [];
|
|
419
|
+
const byName = buildNameIndex(friends, (friend) => friend.displayName);
|
|
420
|
+
const additions: string[] = [];
|
|
421
|
+
const mapping: string[] = [];
|
|
422
|
+
const unresolved: string[] = [];
|
|
423
|
+
for (const entry of allowFromEntries) {
|
|
424
|
+
if (/^\d+$/.test(entry)) {
|
|
425
|
+
additions.push(entry);
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
const matches = byName.get(entry.toLowerCase()) ?? [];
|
|
429
|
+
const match = matches[0];
|
|
430
|
+
const id = match?.userId ? String(match.userId) : undefined;
|
|
431
|
+
if (id) {
|
|
432
|
+
additions.push(id);
|
|
433
|
+
mapping.push(`${entry}→${id}`);
|
|
434
|
+
} else {
|
|
435
|
+
unresolved.push(entry);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
const allowFrom = mergeAllowlist({ existing: account.config.allowFrom, additions });
|
|
439
|
+
account = {
|
|
440
|
+
...account,
|
|
441
|
+
config: {
|
|
442
|
+
...account.config,
|
|
443
|
+
allowFrom,
|
|
444
|
+
},
|
|
445
|
+
};
|
|
446
|
+
summarizeMapping("zalouser users", mapping, unresolved, runtime);
|
|
447
|
+
} else {
|
|
448
|
+
runtime.log?.(`zalouser user resolve failed; using config entries. ${result.stderr}`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const groupsConfig = account.config.groups ?? {};
|
|
453
|
+
const groupKeys = Object.keys(groupsConfig).filter((key) => key !== "*");
|
|
454
|
+
if (groupKeys.length > 0) {
|
|
455
|
+
const result = await runZca(["group", "list", "-j"], { profile, timeout: 15000 });
|
|
456
|
+
if (result.ok) {
|
|
457
|
+
const groups = parseJsonOutput<ZcaGroup[]>(result.stdout) ?? [];
|
|
458
|
+
const byName = buildNameIndex(groups, (group) => group.name);
|
|
459
|
+
const mapping: string[] = [];
|
|
460
|
+
const unresolved: string[] = [];
|
|
461
|
+
const nextGroups = { ...groupsConfig };
|
|
462
|
+
for (const entry of groupKeys) {
|
|
463
|
+
const cleaned = normalizeZalouserEntry(entry);
|
|
464
|
+
if (/^\d+$/.test(cleaned)) {
|
|
465
|
+
if (!nextGroups[cleaned]) nextGroups[cleaned] = groupsConfig[entry];
|
|
466
|
+
mapping.push(`${entry}→${cleaned}`);
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
const matches = byName.get(cleaned.toLowerCase()) ?? [];
|
|
470
|
+
const match = matches[0];
|
|
471
|
+
const id = match?.groupId ? String(match.groupId) : undefined;
|
|
472
|
+
if (id) {
|
|
473
|
+
if (!nextGroups[id]) nextGroups[id] = groupsConfig[entry];
|
|
474
|
+
mapping.push(`${entry}→${id}`);
|
|
475
|
+
} else {
|
|
476
|
+
unresolved.push(entry);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
account = {
|
|
480
|
+
...account,
|
|
481
|
+
config: {
|
|
482
|
+
...account.config,
|
|
483
|
+
groups: nextGroups,
|
|
484
|
+
},
|
|
485
|
+
};
|
|
486
|
+
summarizeMapping("zalouser groups", mapping, unresolved, runtime);
|
|
487
|
+
} else {
|
|
488
|
+
runtime.log?.(`zalouser group resolve failed; using config entries. ${result.stderr}`);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
} catch (err) {
|
|
492
|
+
runtime.log?.(`zalouser resolve failed; using config entries. ${String(err)}`);
|
|
493
|
+
}
|
|
494
|
+
|
|
312
495
|
const stop = () => {
|
|
313
496
|
stopped = true;
|
|
314
497
|
if (restartTimer) {
|
|
@@ -329,7 +512,7 @@ export async function monitorZalouserProvider(
|
|
|
329
512
|
}
|
|
330
513
|
|
|
331
514
|
logVerbose(
|
|
332
|
-
|
|
515
|
+
core,
|
|
333
516
|
runtime,
|
|
334
517
|
`[${account.accountId}] starting zca listener (profile=${account.profile})`,
|
|
335
518
|
);
|
|
@@ -338,16 +521,16 @@ export async function monitorZalouserProvider(
|
|
|
338
521
|
runtime,
|
|
339
522
|
account.profile,
|
|
340
523
|
(msg) => {
|
|
341
|
-
logVerbose(
|
|
524
|
+
logVerbose(core, runtime, `[${account.accountId}] inbound message`);
|
|
342
525
|
statusSink?.({ lastInboundAt: Date.now() });
|
|
343
|
-
processMessage(msg, account, config,
|
|
526
|
+
processMessage(msg, account, config, core, runtime, statusSink).catch((err) => {
|
|
344
527
|
runtime.error(`[${account.accountId}] Failed to process message: ${String(err)}`);
|
|
345
528
|
});
|
|
346
529
|
},
|
|
347
530
|
(err) => {
|
|
348
531
|
runtime.error(`[${account.accountId}] zca listener error: ${String(err)}`);
|
|
349
532
|
if (!stopped && !abortSignal.aborted) {
|
|
350
|
-
logVerbose(
|
|
533
|
+
logVerbose(core, runtime, `[${account.accountId}] restarting listener in 5s...`);
|
|
351
534
|
restartTimer = setTimeout(startListener, 5000);
|
|
352
535
|
} else {
|
|
353
536
|
resolveRunning?.();
|