@openclaw/zalouser 2026.5.2 → 2026.5.3-beta.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.
- package/dist/accounts-C00IMUgd.js +63 -0
- package/dist/accounts.runtime-uG7S8cXT.js +2 -0
- package/dist/api-BRwdUWuS.js +139 -0
- package/dist/api.js +7 -0
- package/dist/channel-ou_w_2j-.js +484 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.runtime-C9WxiAiR.js +25 -0
- package/dist/channel.setup-CiDeBFrn.js +10 -0
- package/dist/contract-api.js +3 -0
- package/dist/doctor-contract-DgqHp8E2.js +128 -0
- package/dist/doctor-contract-api.js +2 -0
- package/dist/index.js +27 -0
- package/dist/monitor-Cg7K_s_s.js +705 -0
- package/dist/runtime-QNU7vLgI.js +106 -0
- package/dist/runtime-api.js +22 -0
- package/dist/secret-contract-api.js +5 -0
- package/dist/security-audit-BZLhil-V.js +34 -0
- package/dist/send-BsmySxe3.js +534 -0
- package/dist/session-route-C0-Xr8bt.js +92 -0
- package/dist/setup-core-CqipqY98.js +40 -0
- package/dist/setup-entry.js +11 -0
- package/dist/setup-plugin-api.js +2 -0
- package/dist/setup-surface-NCOuKu-l.js +359 -0
- package/dist/shared-DSy8aIUx.js +120 -0
- package/dist/test-api.js +5 -0
- package/dist/zalo-js-CHCUlY3c.js +1279 -0
- package/package.json +15 -6
- package/api.ts +0 -9
- package/channel-plugin-api.ts +0 -3
- package/contract-api.ts +0 -2
- package/doctor-contract-api.ts +0 -1
- package/index.ts +0 -34
- package/runtime-api.ts +0 -67
- package/secret-contract-api.ts +0 -4
- package/setup-entry.ts +0 -9
- package/setup-plugin-api.ts +0 -2
- package/src/accounts.runtime.ts +0 -1
- package/src/accounts.test-mocks.ts +0 -14
- package/src/accounts.test.ts +0 -266
- package/src/accounts.ts +0 -131
- package/src/channel-api.ts +0 -20
- package/src/channel.adapters.ts +0 -391
- package/src/channel.directory.test.ts +0 -59
- package/src/channel.runtime.ts +0 -12
- package/src/channel.sendpayload.test.ts +0 -172
- package/src/channel.setup.test.ts +0 -33
- package/src/channel.setup.ts +0 -12
- package/src/channel.test.ts +0 -377
- package/src/channel.ts +0 -219
- package/src/config-schema.ts +0 -33
- package/src/directory.ts +0 -54
- package/src/doctor-contract.ts +0 -156
- package/src/doctor.test.ts +0 -77
- package/src/doctor.ts +0 -37
- package/src/group-policy.test.ts +0 -61
- package/src/group-policy.ts +0 -83
- package/src/message-sid.test.ts +0 -66
- package/src/message-sid.ts +0 -80
- package/src/monitor.account-scope.test.ts +0 -107
- package/src/monitor.group-gating.test.ts +0 -816
- package/src/monitor.send-mocks.ts +0 -20
- package/src/monitor.ts +0 -1044
- package/src/probe.test.ts +0 -60
- package/src/probe.ts +0 -35
- package/src/qr-temp-file.ts +0 -22
- package/src/reaction.test.ts +0 -19
- package/src/reaction.ts +0 -32
- package/src/runtime.ts +0 -9
- package/src/security-audit.test.ts +0 -80
- package/src/security-audit.ts +0 -71
- package/src/send.test.ts +0 -395
- package/src/send.ts +0 -272
- package/src/session-route.ts +0 -121
- package/src/setup-core.ts +0 -33
- package/src/setup-surface.test.ts +0 -363
- package/src/setup-surface.ts +0 -470
- package/src/setup-test-helpers.ts +0 -42
- package/src/shared.ts +0 -92
- package/src/status-issues.test.ts +0 -31
- package/src/status-issues.ts +0 -58
- package/src/test-helpers.ts +0 -26
- package/src/text-styles.test.ts +0 -203
- package/src/text-styles.ts +0 -540
- package/src/tool.test.ts +0 -212
- package/src/tool.ts +0 -210
- package/src/types.ts +0 -125
- package/src/zalo-js.credentials.test.ts +0 -465
- package/src/zalo-js.test-mocks.ts +0 -89
- package/src/zalo-js.ts +0 -1911
- package/src/zca-client.test.ts +0 -24
- package/src/zca-client.ts +0 -259
- package/src/zca-constants.ts +0 -55
- package/src/zca-js-exports.d.ts +0 -22
- package/test-api.ts +0 -21
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { a as resolveZalouserAccountSync, i as resolveDefaultZalouserAccountId, r as listZalouserAccountIds, t as checkZcaAuthenticated } from "./accounts-C00IMUgd.js";
|
|
2
|
+
import { r as writeQrDataUrlToTempFile } from "./setup-core-CqipqY98.js";
|
|
3
|
+
import { b as waitForZaloQrLogin, c as logoutZaloProfile, d as resolveZaloGroupsByEntries, l as resolveZaloAllowFromEntries, y as startZaloQrLogin } from "./zalo-js-CHCUlY3c.js";
|
|
4
|
+
import { DEFAULT_ACCOUNT_ID, addWildcardAllowFrom, formatCliCommand, formatDocsLink, formatResolvedUnresolvedNote, mergeAllowFromEntries, normalizeAccountId, patchScopedAccountConfig } from "openclaw/plugin-sdk/setup";
|
|
5
|
+
//#region \0rolldown/runtime.js
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __exportAll = (all, no_symbols) => {
|
|
8
|
+
let target = {};
|
|
9
|
+
for (var name in all) __defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true
|
|
12
|
+
});
|
|
13
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
14
|
+
return target;
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region extensions/zalouser/src/setup-surface.ts
|
|
18
|
+
var setup_surface_exports = /* @__PURE__ */ __exportAll({ zalouserSetupWizard: () => zalouserSetupWizard });
|
|
19
|
+
const channel = "zalouser";
|
|
20
|
+
const ZALOUSER_ALLOW_FROM_PLACEHOLDER = "Alice, 123456789, or leave empty to configure later";
|
|
21
|
+
const ZALOUSER_GROUPS_PLACEHOLDER = "Family, Work, 123456789, or leave empty for now";
|
|
22
|
+
const ZALOUSER_DM_ACCESS_TITLE = "Zalo Personal DM access";
|
|
23
|
+
const ZALOUSER_ALLOWLIST_TITLE = "Zalo Personal allowlist";
|
|
24
|
+
const ZALOUSER_GROUPS_TITLE = "Zalo groups";
|
|
25
|
+
function parseZalouserEntries(raw) {
|
|
26
|
+
return raw.split(/[\n,;]+/g).map((entry) => entry.trim()).filter(Boolean);
|
|
27
|
+
}
|
|
28
|
+
function setZalouserAccountScopedConfig(cfg, accountId, defaultPatch, accountPatch = defaultPatch) {
|
|
29
|
+
return patchScopedAccountConfig({
|
|
30
|
+
cfg,
|
|
31
|
+
channelKey: channel,
|
|
32
|
+
accountId,
|
|
33
|
+
patch: defaultPatch,
|
|
34
|
+
accountPatch
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function setZalouserDmPolicy(cfg, accountId, policy) {
|
|
38
|
+
const resolvedAccountId = normalizeAccountId(accountId) ?? DEFAULT_ACCOUNT_ID;
|
|
39
|
+
const resolved = resolveZalouserAccountSync({
|
|
40
|
+
cfg,
|
|
41
|
+
accountId: resolvedAccountId
|
|
42
|
+
});
|
|
43
|
+
return setZalouserAccountScopedConfig(cfg, resolvedAccountId, {
|
|
44
|
+
dmPolicy: policy,
|
|
45
|
+
...policy === "open" ? { allowFrom: addWildcardAllowFrom(resolved.config.allowFrom) } : {}
|
|
46
|
+
}, {
|
|
47
|
+
dmPolicy: policy,
|
|
48
|
+
...policy === "open" ? { allowFrom: addWildcardAllowFrom(resolved.config.allowFrom) } : {}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function setZalouserGroupPolicy(cfg, accountId, groupPolicy) {
|
|
52
|
+
return setZalouserAccountScopedConfig(cfg, accountId, { groupPolicy });
|
|
53
|
+
}
|
|
54
|
+
function setZalouserGroupAllowlist(cfg, accountId, groupKeys) {
|
|
55
|
+
return setZalouserAccountScopedConfig(cfg, accountId, { groups: Object.fromEntries(groupKeys.map((key) => [key, {
|
|
56
|
+
enabled: true,
|
|
57
|
+
requireMention: true
|
|
58
|
+
}])) });
|
|
59
|
+
}
|
|
60
|
+
function ensureZalouserPluginEnabled(cfg) {
|
|
61
|
+
const next = {
|
|
62
|
+
...cfg,
|
|
63
|
+
plugins: {
|
|
64
|
+
...cfg.plugins,
|
|
65
|
+
entries: {
|
|
66
|
+
...cfg.plugins?.entries,
|
|
67
|
+
zalouser: {
|
|
68
|
+
...cfg.plugins?.entries?.zalouser,
|
|
69
|
+
enabled: true
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const allow = next.plugins?.allow;
|
|
75
|
+
if (!Array.isArray(allow) || allow.includes(channel)) return next;
|
|
76
|
+
return {
|
|
77
|
+
...next,
|
|
78
|
+
plugins: {
|
|
79
|
+
...next.plugins,
|
|
80
|
+
allow: [...allow, channel]
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async function noteZalouserHelp(prompter) {
|
|
85
|
+
await prompter.note([
|
|
86
|
+
"Zalo Personal Account login via QR code.",
|
|
87
|
+
"",
|
|
88
|
+
"This plugin uses zca-js directly (no external CLI dependency).",
|
|
89
|
+
"",
|
|
90
|
+
`Docs: ${formatDocsLink("/channels/zalouser", "zalouser")}`
|
|
91
|
+
].join("\n"), "Zalo Personal Setup");
|
|
92
|
+
}
|
|
93
|
+
async function promptZalouserAllowFrom(params) {
|
|
94
|
+
const { cfg, prompter, accountId } = params;
|
|
95
|
+
const resolved = resolveZalouserAccountSync({
|
|
96
|
+
cfg,
|
|
97
|
+
accountId
|
|
98
|
+
});
|
|
99
|
+
const existingAllowFrom = resolved.config.allowFrom ?? [];
|
|
100
|
+
while (true) {
|
|
101
|
+
const parts = parseZalouserEntries(await prompter.text({
|
|
102
|
+
message: "Zalouser allowFrom (name or user id)",
|
|
103
|
+
placeholder: ZALOUSER_ALLOW_FROM_PLACEHOLDER,
|
|
104
|
+
initialValue: existingAllowFrom.length > 0 ? existingAllowFrom.join(", ") : void 0
|
|
105
|
+
}));
|
|
106
|
+
if (parts.length === 0) {
|
|
107
|
+
await prompter.note([
|
|
108
|
+
"No DM allowlist entries added yet.",
|
|
109
|
+
"Direct chats will stay blocked until you add people later.",
|
|
110
|
+
`Tip: use \`${formatCliCommand("openclaw directory peers list --channel zalouser")}\` to look up people after onboarding.`
|
|
111
|
+
].join("\n"), ZALOUSER_ALLOWLIST_TITLE);
|
|
112
|
+
return setZalouserAccountScopedConfig(cfg, accountId, {
|
|
113
|
+
dmPolicy: "allowlist",
|
|
114
|
+
allowFrom: []
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const resolvedEntries = await resolveZaloAllowFromEntries({
|
|
118
|
+
profile: resolved.profile,
|
|
119
|
+
entries: parts
|
|
120
|
+
});
|
|
121
|
+
const unresolved = resolvedEntries.filter((item) => !item.resolved).map((item) => item.input);
|
|
122
|
+
if (unresolved.length > 0) {
|
|
123
|
+
await prompter.note(`Could not resolve: ${unresolved.join(", ")}. Use numeric user ids or exact friend names.`, ZALOUSER_ALLOWLIST_TITLE);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const unique = mergeAllowFromEntries(existingAllowFrom, resolvedEntries.filter((item) => item.resolved && item.id).map((item) => item.id));
|
|
127
|
+
const notes = resolvedEntries.filter((item) => item.note).map((item) => `${item.input} -> ${item.id} (${item.note})`);
|
|
128
|
+
if (notes.length > 0) await prompter.note(notes.join("\n"), ZALOUSER_ALLOWLIST_TITLE);
|
|
129
|
+
return setZalouserAccountScopedConfig(cfg, accountId, {
|
|
130
|
+
dmPolicy: "allowlist",
|
|
131
|
+
allowFrom: unique
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const zalouserDmPolicy = {
|
|
136
|
+
label: "Zalo Personal",
|
|
137
|
+
channel,
|
|
138
|
+
policyKey: "channels.zalouser.dmPolicy",
|
|
139
|
+
allowFromKey: "channels.zalouser.allowFrom",
|
|
140
|
+
resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultZalouserAccountId(cfg)) !== DEFAULT_ACCOUNT_ID ? {
|
|
141
|
+
policyKey: `channels.zalouser.accounts.${accountId ?? resolveDefaultZalouserAccountId(cfg)}.dmPolicy`,
|
|
142
|
+
allowFromKey: `channels.zalouser.accounts.${accountId ?? resolveDefaultZalouserAccountId(cfg)}.allowFrom`
|
|
143
|
+
} : {
|
|
144
|
+
policyKey: "channels.zalouser.dmPolicy",
|
|
145
|
+
allowFromKey: "channels.zalouser.allowFrom"
|
|
146
|
+
},
|
|
147
|
+
getCurrent: (cfg, accountId) => resolveZalouserAccountSync({
|
|
148
|
+
cfg,
|
|
149
|
+
accountId: accountId ?? resolveDefaultZalouserAccountId(cfg)
|
|
150
|
+
}).config.dmPolicy ?? "pairing",
|
|
151
|
+
setPolicy: (cfg, policy, accountId) => setZalouserDmPolicy(cfg, accountId ?? resolveDefaultZalouserAccountId(cfg), policy),
|
|
152
|
+
promptAllowFrom: async ({ cfg, prompter, accountId }) => {
|
|
153
|
+
return await promptZalouserAllowFrom({
|
|
154
|
+
cfg,
|
|
155
|
+
prompter,
|
|
156
|
+
accountId: accountId && normalizeAccountId(accountId) ? normalizeAccountId(accountId) ?? DEFAULT_ACCOUNT_ID : resolveDefaultZalouserAccountId(cfg)
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
async function promptZalouserQuickstartDmPolicy(params) {
|
|
161
|
+
const { cfg, prompter, accountId } = params;
|
|
162
|
+
const resolved = resolveZalouserAccountSync({
|
|
163
|
+
cfg,
|
|
164
|
+
accountId
|
|
165
|
+
});
|
|
166
|
+
const existingPolicy = resolved.config.dmPolicy ?? "pairing";
|
|
167
|
+
const existingAllowFrom = resolved.config.allowFrom ?? [];
|
|
168
|
+
const existingLabel = existingAllowFrom.length > 0 ? existingAllowFrom.join(", ") : "unset";
|
|
169
|
+
await prompter.note([
|
|
170
|
+
"Direct chats are configured separately from group chats.",
|
|
171
|
+
"- pairing (default): unknown people get a pairing code",
|
|
172
|
+
"- allowlist: only listed people can DM",
|
|
173
|
+
"- open: anyone can DM",
|
|
174
|
+
"- disabled: ignore DMs",
|
|
175
|
+
"",
|
|
176
|
+
`Current: dmPolicy=${existingPolicy}, allowFrom=${existingLabel}`,
|
|
177
|
+
"If you choose allowlist now, you can leave it empty and add people later."
|
|
178
|
+
].join("\n"), ZALOUSER_DM_ACCESS_TITLE);
|
|
179
|
+
const policy = await prompter.select({
|
|
180
|
+
message: "Zalo Personal DM policy",
|
|
181
|
+
options: [
|
|
182
|
+
{
|
|
183
|
+
value: "pairing",
|
|
184
|
+
label: "Pairing (recommended)"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
value: "allowlist",
|
|
188
|
+
label: "Allowlist (specific users only)"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
value: "open",
|
|
192
|
+
label: "Open (public inbound DMs)"
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
value: "disabled",
|
|
196
|
+
label: "Disabled (ignore DMs)"
|
|
197
|
+
}
|
|
198
|
+
],
|
|
199
|
+
initialValue: existingPolicy
|
|
200
|
+
});
|
|
201
|
+
if (policy === "allowlist") return await promptZalouserAllowFrom({
|
|
202
|
+
cfg,
|
|
203
|
+
prompter,
|
|
204
|
+
accountId
|
|
205
|
+
});
|
|
206
|
+
return setZalouserDmPolicy(cfg, accountId, policy);
|
|
207
|
+
}
|
|
208
|
+
const zalouserSetupWizard = {
|
|
209
|
+
channel,
|
|
210
|
+
status: {
|
|
211
|
+
configuredLabel: "logged in",
|
|
212
|
+
unconfiguredLabel: "needs QR login",
|
|
213
|
+
configuredHint: "recommended · logged in",
|
|
214
|
+
unconfiguredHint: "recommended · QR login",
|
|
215
|
+
configuredScore: 1,
|
|
216
|
+
unconfiguredScore: 15,
|
|
217
|
+
resolveConfigured: async ({ cfg, accountId }) => {
|
|
218
|
+
const ids = accountId ? [accountId] : listZalouserAccountIds(cfg);
|
|
219
|
+
for (const resolvedAccountId of ids) if (await checkZcaAuthenticated(resolveZalouserAccountSync({
|
|
220
|
+
cfg,
|
|
221
|
+
accountId: resolvedAccountId
|
|
222
|
+
}).profile)) return true;
|
|
223
|
+
return false;
|
|
224
|
+
},
|
|
225
|
+
resolveStatusLines: async ({ cfg, accountId, configured }) => {
|
|
226
|
+
return [`${accountId && accountId !== DEFAULT_ACCOUNT_ID ? `Zalo Personal (${accountId})` : "Zalo Personal"}: ${configured ? "logged in" : "needs QR login"}`];
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
prepare: async ({ cfg, accountId, prompter, options }) => {
|
|
230
|
+
let next = cfg;
|
|
231
|
+
const account = resolveZalouserAccountSync({
|
|
232
|
+
cfg: next,
|
|
233
|
+
accountId
|
|
234
|
+
});
|
|
235
|
+
if (!await checkZcaAuthenticated(account.profile)) {
|
|
236
|
+
await noteZalouserHelp(prompter);
|
|
237
|
+
if (await prompter.confirm({
|
|
238
|
+
message: "Login via QR code now?",
|
|
239
|
+
initialValue: true
|
|
240
|
+
})) {
|
|
241
|
+
const start = await startZaloQrLogin({
|
|
242
|
+
profile: account.profile,
|
|
243
|
+
timeoutMs: 35e3
|
|
244
|
+
});
|
|
245
|
+
if (start.qrDataUrl) {
|
|
246
|
+
const qrPath = await writeQrDataUrlToTempFile(start.qrDataUrl, account.profile);
|
|
247
|
+
await prompter.note([
|
|
248
|
+
start.message,
|
|
249
|
+
qrPath ? `QR image saved to: ${qrPath}` : "Could not write QR image file; use gateway web login UI instead.",
|
|
250
|
+
"Scan + approve on phone, then continue."
|
|
251
|
+
].join("\n"), "QR Login");
|
|
252
|
+
if (await prompter.confirm({
|
|
253
|
+
message: "Did you scan and approve the QR on your phone?",
|
|
254
|
+
initialValue: true
|
|
255
|
+
})) {
|
|
256
|
+
const waited = await waitForZaloQrLogin({
|
|
257
|
+
profile: account.profile,
|
|
258
|
+
timeoutMs: 12e4
|
|
259
|
+
});
|
|
260
|
+
await prompter.note(waited.message, waited.connected ? "Success" : "Login pending");
|
|
261
|
+
}
|
|
262
|
+
} else await prompter.note(start.message, "Login pending");
|
|
263
|
+
}
|
|
264
|
+
} else if (!await prompter.confirm({
|
|
265
|
+
message: "Zalo Personal already logged in. Keep session?",
|
|
266
|
+
initialValue: true
|
|
267
|
+
})) {
|
|
268
|
+
await logoutZaloProfile(account.profile);
|
|
269
|
+
const start = await startZaloQrLogin({
|
|
270
|
+
profile: account.profile,
|
|
271
|
+
force: true,
|
|
272
|
+
timeoutMs: 35e3
|
|
273
|
+
});
|
|
274
|
+
if (start.qrDataUrl) {
|
|
275
|
+
const qrPath = await writeQrDataUrlToTempFile(start.qrDataUrl, account.profile);
|
|
276
|
+
await prompter.note([start.message, qrPath ? `QR image saved to: ${qrPath}` : void 0].filter(Boolean).join("\n"), "QR Login");
|
|
277
|
+
const waited = await waitForZaloQrLogin({
|
|
278
|
+
profile: account.profile,
|
|
279
|
+
timeoutMs: 12e4
|
|
280
|
+
});
|
|
281
|
+
await prompter.note(waited.message, waited.connected ? "Success" : "Login pending");
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
next = setZalouserAccountScopedConfig(next, accountId, { profile: account.profile !== "default" ? account.profile : void 0 }, {
|
|
285
|
+
profile: account.profile,
|
|
286
|
+
enabled: true
|
|
287
|
+
});
|
|
288
|
+
if (options?.quickstartDefaults) next = await promptZalouserQuickstartDmPolicy({
|
|
289
|
+
cfg: next,
|
|
290
|
+
prompter,
|
|
291
|
+
accountId
|
|
292
|
+
});
|
|
293
|
+
return { cfg: next };
|
|
294
|
+
},
|
|
295
|
+
credentials: [],
|
|
296
|
+
groupAccess: {
|
|
297
|
+
label: "Zalo groups",
|
|
298
|
+
placeholder: ZALOUSER_GROUPS_PLACEHOLDER,
|
|
299
|
+
currentPolicy: ({ cfg, accountId }) => resolveZalouserAccountSync({
|
|
300
|
+
cfg,
|
|
301
|
+
accountId
|
|
302
|
+
}).config.groupPolicy ?? "allowlist",
|
|
303
|
+
currentEntries: ({ cfg, accountId }) => Object.keys(resolveZalouserAccountSync({
|
|
304
|
+
cfg,
|
|
305
|
+
accountId
|
|
306
|
+
}).config.groups ?? {}),
|
|
307
|
+
updatePrompt: ({ cfg, accountId }) => Boolean(resolveZalouserAccountSync({
|
|
308
|
+
cfg,
|
|
309
|
+
accountId
|
|
310
|
+
}).config.groups),
|
|
311
|
+
setPolicy: ({ cfg, accountId, policy }) => setZalouserGroupPolicy(cfg, accountId, policy),
|
|
312
|
+
resolveAllowlist: async ({ cfg, accountId, entries, prompter }) => {
|
|
313
|
+
if (entries.length === 0) {
|
|
314
|
+
await prompter.note([
|
|
315
|
+
"No group allowlist entries added yet.",
|
|
316
|
+
"Group chats will stay blocked until you add groups later.",
|
|
317
|
+
`Tip: use \`${formatCliCommand("openclaw directory groups list --channel zalouser")}\` after onboarding to find group IDs.`,
|
|
318
|
+
"Mention requirement stays on by default for groups you allow later."
|
|
319
|
+
].join("\n"), ZALOUSER_GROUPS_TITLE);
|
|
320
|
+
return [];
|
|
321
|
+
}
|
|
322
|
+
const updatedAccount = resolveZalouserAccountSync({
|
|
323
|
+
cfg,
|
|
324
|
+
accountId
|
|
325
|
+
});
|
|
326
|
+
try {
|
|
327
|
+
const resolved = await resolveZaloGroupsByEntries({
|
|
328
|
+
profile: updatedAccount.profile,
|
|
329
|
+
entries
|
|
330
|
+
});
|
|
331
|
+
const resolvedIds = resolved.filter((entry) => entry.resolved && entry.id).map((entry) => entry.id);
|
|
332
|
+
const unresolved = resolved.filter((entry) => !entry.resolved).map((entry) => entry.input);
|
|
333
|
+
const keys = [...resolvedIds, ...unresolved.map((entry) => entry.trim()).filter(Boolean)];
|
|
334
|
+
const resolution = formatResolvedUnresolvedNote({
|
|
335
|
+
resolved: resolvedIds,
|
|
336
|
+
unresolved
|
|
337
|
+
});
|
|
338
|
+
if (resolution) await prompter.note(resolution, ZALOUSER_GROUPS_TITLE);
|
|
339
|
+
return keys;
|
|
340
|
+
} catch (err) {
|
|
341
|
+
await prompter.note(`Group lookup failed; keeping entries as typed. ${String(err)}`, ZALOUSER_GROUPS_TITLE);
|
|
342
|
+
return entries.map((entry) => entry.trim()).filter(Boolean);
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
applyAllowlist: ({ cfg, accountId, resolved }) => setZalouserGroupAllowlist(cfg, accountId, resolved)
|
|
346
|
+
},
|
|
347
|
+
finalize: async ({ cfg, accountId, forceAllowFrom, options, prompter }) => {
|
|
348
|
+
let next = cfg;
|
|
349
|
+
if (forceAllowFrom && !options?.quickstartDefaults) next = await promptZalouserAllowFrom({
|
|
350
|
+
cfg: next,
|
|
351
|
+
prompter,
|
|
352
|
+
accountId
|
|
353
|
+
});
|
|
354
|
+
return { cfg: ensureZalouserPluginEnabled(next) };
|
|
355
|
+
},
|
|
356
|
+
dmPolicy: zalouserDmPolicy
|
|
357
|
+
};
|
|
358
|
+
//#endregion
|
|
359
|
+
export { zalouserSetupWizard as n, setup_surface_exports as t };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { a as resolveZalouserAccountSync, i as resolveDefaultZalouserAccountId, r as listZalouserAccountIds, t as checkZcaAuthenticated } from "./accounts-C00IMUgd.js";
|
|
2
|
+
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-DgqHp8E2.js";
|
|
3
|
+
import { n as isZalouserMutableGroupEntry } from "./security-audit-BZLhil-V.js";
|
|
4
|
+
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
|
|
5
|
+
import { AllowFromListSchema, DmPolicySchema, GroupPolicySchema, MarkdownConfigSchema, ToolPolicySchema, buildCatchallMultiAccountChannelSchema, buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
|
|
6
|
+
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/core";
|
|
7
|
+
import { isDangerousNameMatchingEnabled as isDangerousNameMatchingEnabled$1 } from "openclaw/plugin-sdk/dangerous-name-runtime";
|
|
8
|
+
import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
|
9
|
+
import { isNumericTargetId, sendPayloadWithChunkedTextAndMedia } from "openclaw/plugin-sdk/reply-payload";
|
|
10
|
+
import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
11
|
+
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
12
|
+
import { z } from "openclaw/plugin-sdk/zod";
|
|
13
|
+
import { createDangerousNameMatchingMutableAllowlistWarningCollector } from "openclaw/plugin-sdk/channel-policy";
|
|
14
|
+
//#region extensions/zalouser/src/config-schema.ts
|
|
15
|
+
const groupConfigSchema = z.object({
|
|
16
|
+
enabled: z.boolean().optional(),
|
|
17
|
+
requireMention: z.boolean().optional(),
|
|
18
|
+
tools: ToolPolicySchema
|
|
19
|
+
});
|
|
20
|
+
const ZalouserConfigSchema = buildCatchallMultiAccountChannelSchema(z.object({
|
|
21
|
+
name: z.string().optional(),
|
|
22
|
+
enabled: z.boolean().optional(),
|
|
23
|
+
markdown: MarkdownConfigSchema,
|
|
24
|
+
profile: z.string().optional(),
|
|
25
|
+
dangerouslyAllowNameMatching: z.boolean().optional(),
|
|
26
|
+
dmPolicy: DmPolicySchema.optional(),
|
|
27
|
+
allowFrom: AllowFromListSchema,
|
|
28
|
+
historyLimit: z.number().int().min(0).optional(),
|
|
29
|
+
groupAllowFrom: AllowFromListSchema,
|
|
30
|
+
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
|
|
31
|
+
groups: z.object({}).catchall(groupConfigSchema).optional(),
|
|
32
|
+
messagePrefix: z.string().optional(),
|
|
33
|
+
responsePrefix: z.string().optional()
|
|
34
|
+
}));
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region extensions/zalouser/src/doctor.ts
|
|
37
|
+
function asObjectRecord(value) {
|
|
38
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
39
|
+
}
|
|
40
|
+
const zalouserDoctor = {
|
|
41
|
+
dmAllowFromMode: "topOnly",
|
|
42
|
+
groupModel: "hybrid",
|
|
43
|
+
groupAllowFromFallbackToAllowFrom: false,
|
|
44
|
+
warnOnEmptyGroupSenderAllowlist: false,
|
|
45
|
+
legacyConfigRules,
|
|
46
|
+
normalizeCompatibilityConfig,
|
|
47
|
+
collectMutableAllowlistWarnings: createDangerousNameMatchingMutableAllowlistWarningCollector({
|
|
48
|
+
channel: "zalouser",
|
|
49
|
+
detector: isZalouserMutableGroupEntry,
|
|
50
|
+
collectLists: (scope) => {
|
|
51
|
+
const groups = asObjectRecord(scope.account.groups);
|
|
52
|
+
return groups ? [{
|
|
53
|
+
pathLabel: `${scope.prefix}.groups`,
|
|
54
|
+
list: Object.keys(groups)
|
|
55
|
+
}] : [];
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region extensions/zalouser/src/shared.ts
|
|
61
|
+
const zalouserMeta = {
|
|
62
|
+
id: "zalouser",
|
|
63
|
+
label: "Zalo Personal",
|
|
64
|
+
selectionLabel: "Zalo (Personal Account)",
|
|
65
|
+
docsPath: "/channels/zalouser",
|
|
66
|
+
docsLabel: "zalouser",
|
|
67
|
+
blurb: "Zalo personal account via QR code login.",
|
|
68
|
+
aliases: ["zlu"],
|
|
69
|
+
order: 85,
|
|
70
|
+
quickstartAllowFrom: false
|
|
71
|
+
};
|
|
72
|
+
const zalouserConfigAdapter = createScopedChannelConfigAdapter({
|
|
73
|
+
sectionKey: "zalouser",
|
|
74
|
+
listAccountIds: listZalouserAccountIds,
|
|
75
|
+
resolveAccount: adaptScopedAccountAccessor(resolveZalouserAccountSync),
|
|
76
|
+
defaultAccountId: resolveDefaultZalouserAccountId,
|
|
77
|
+
clearBaseFields: [
|
|
78
|
+
"profile",
|
|
79
|
+
"name",
|
|
80
|
+
"dmPolicy",
|
|
81
|
+
"allowFrom",
|
|
82
|
+
"historyLimit",
|
|
83
|
+
"groupAllowFrom",
|
|
84
|
+
"groupPolicy",
|
|
85
|
+
"groups",
|
|
86
|
+
"messagePrefix"
|
|
87
|
+
],
|
|
88
|
+
resolveAllowFrom: (account) => account.config.allowFrom,
|
|
89
|
+
formatAllowFrom: (allowFrom) => formatAllowFromLowercase({
|
|
90
|
+
allowFrom,
|
|
91
|
+
stripPrefixRe: /^(zalouser|zlu):/i
|
|
92
|
+
})
|
|
93
|
+
});
|
|
94
|
+
function createZalouserPluginBase(params) {
|
|
95
|
+
return {
|
|
96
|
+
id: "zalouser",
|
|
97
|
+
meta: zalouserMeta,
|
|
98
|
+
setupWizard: params.setupWizard,
|
|
99
|
+
capabilities: {
|
|
100
|
+
chatTypes: ["direct", "group"],
|
|
101
|
+
media: true,
|
|
102
|
+
reactions: true,
|
|
103
|
+
threads: false,
|
|
104
|
+
polls: false,
|
|
105
|
+
nativeCommands: false,
|
|
106
|
+
blockStreaming: true
|
|
107
|
+
},
|
|
108
|
+
doctor: zalouserDoctor,
|
|
109
|
+
reload: { configPrefixes: ["channels.zalouser"] },
|
|
110
|
+
configSchema: buildChannelConfigSchema(ZalouserConfigSchema),
|
|
111
|
+
config: {
|
|
112
|
+
...zalouserConfigAdapter,
|
|
113
|
+
isConfigured: async (account) => await checkZcaAuthenticated(account.profile),
|
|
114
|
+
describeAccount: (account) => describeAccountSnapshot({ account })
|
|
115
|
+
},
|
|
116
|
+
setup: params.setup
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
export { isNumericTargetId as a, isDangerousNameMatchingEnabled$1 as i, DEFAULT_ACCOUNT_ID as n, normalizeAccountId as o, chunkTextForOutbound as r, sendPayloadWithChunkedTextAndMedia as s, createZalouserPluginBase as t };
|
package/dist/test-api.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { a as resolveZalouserAccountSync, i as resolveDefaultZalouserAccountId, n as getZcaUserInfo, r as listZalouserAccountIds, t as checkZcaAuthenticated } from "./accounts-C00IMUgd.js";
|
|
2
|
+
import { r as parseZalouserOutboundTarget } from "./session-route-C0-Xr8bt.js";
|
|
3
|
+
import { a as listZaloGroupMembers, b as waitForZaloQrLogin, c as logoutZaloProfile, d as resolveZaloGroupsByEntries, i as listZaloFriendsMatching, l as resolveZaloAllowFromEntries, n as getZaloUserInfo, s as listZaloGroupsMatching, t as checkZaloAuthenticated, y as startZaloQrLogin } from "./zalo-js-CHCUlY3c.js";
|
|
4
|
+
import { i as sendMessageZalouser } from "./send-BsmySxe3.js";
|
|
5
|
+
export { checkZaloAuthenticated, checkZcaAuthenticated, getZaloUserInfo, getZcaUserInfo, listZaloFriendsMatching, listZaloGroupMembers, listZaloGroupsMatching, listZalouserAccountIds, logoutZaloProfile, parseZalouserOutboundTarget, resolveDefaultZalouserAccountId, resolveZaloAllowFromEntries, resolveZaloGroupsByEntries, resolveZalouserAccountSync, sendMessageZalouser, startZaloQrLogin, waitForZaloQrLogin };
|