@openclaw/zalo 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-9NLDDlZ8.js +118 -0
- package/dist/actions.runtime-kJ65ZxW7.js +5 -0
- package/dist/api.js +5 -0
- package/dist/channel-VPbtV3Oq.js +343 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.runtime-BnTAWQx5.js +106 -0
- package/dist/contract-api.js +3 -0
- package/dist/group-access-DZR43lOR.js +30 -0
- package/dist/index.js +22 -0
- package/dist/monitor-DMysJBWa.js +823 -0
- package/dist/monitor.webhook-DqnuvgjV.js +175 -0
- package/dist/proxy-CY8VuC6H.js +135 -0
- package/dist/runtime-BRFxnYQx.js +8 -0
- package/dist/runtime-api-MOTmRW4F.js +19 -0
- package/dist/runtime-api.js +3 -0
- package/dist/secret-contract-Dw93tGo2.js +87 -0
- package/dist/secret-contract-api.js +2 -0
- package/dist/send-Gv3l5EGI.js +101 -0
- package/dist/setup-api.js +30 -0
- package/dist/setup-core-DigRD3j1.js +166 -0
- package/dist/setup-entry.js +15 -0
- package/dist/setup-surface-2Up3yWov.js +216 -0
- package/dist/test-api.js +2 -0
- package/package.json +15 -6
- package/api.ts +0 -9
- package/channel-plugin-api.ts +0 -1
- package/contract-api.ts +0 -5
- package/index.test.ts +0 -15
- package/index.ts +0 -20
- package/runtime-api.test.ts +0 -17
- package/runtime-api.ts +0 -75
- package/secret-contract-api.ts +0 -5
- package/setup-api.ts +0 -34
- package/setup-entry.ts +0 -13
- package/src/accounts.test.ts +0 -70
- package/src/accounts.ts +0 -60
- package/src/actions.runtime.ts +0 -5
- package/src/actions.test.ts +0 -32
- package/src/actions.ts +0 -62
- package/src/api.test.ts +0 -149
- package/src/api.ts +0 -265
- package/src/approval-auth.test.ts +0 -17
- package/src/approval-auth.ts +0 -25
- package/src/channel.directory.test.ts +0 -59
- package/src/channel.runtime.ts +0 -93
- package/src/channel.startup.test.ts +0 -101
- package/src/channel.ts +0 -275
- package/src/config-schema.test.ts +0 -30
- package/src/config-schema.ts +0 -29
- package/src/group-access.ts +0 -49
- package/src/monitor.group-policy.test.ts +0 -94
- package/src/monitor.image.polling.test.ts +0 -110
- package/src/monitor.lifecycle.test.ts +0 -198
- package/src/monitor.pairing.lifecycle.test.ts +0 -141
- package/src/monitor.polling.media-reply.test.ts +0 -425
- package/src/monitor.reply-once.lifecycle.test.ts +0 -171
- package/src/monitor.ts +0 -1028
- package/src/monitor.types.ts +0 -4
- package/src/monitor.webhook.test.ts +0 -806
- package/src/monitor.webhook.ts +0 -278
- package/src/outbound-media.test.ts +0 -182
- package/src/outbound-media.ts +0 -241
- package/src/outbound-payload.contract.test.ts +0 -45
- package/src/probe.ts +0 -45
- package/src/proxy.ts +0 -24
- package/src/runtime-api.ts +0 -75
- package/src/runtime-support.ts +0 -91
- package/src/runtime.ts +0 -9
- package/src/secret-contract.ts +0 -109
- package/src/secret-input.ts +0 -5
- package/src/send.test.ts +0 -120
- package/src/send.ts +0 -153
- package/src/session-route.ts +0 -32
- package/src/setup-allow-from.ts +0 -94
- package/src/setup-core.ts +0 -149
- package/src/setup-status.test.ts +0 -33
- package/src/setup-surface.test.ts +0 -175
- package/src/setup-surface.ts +0 -291
- package/src/status-issues.test.ts +0 -17
- package/src/status-issues.ts +0 -37
- package/src/test-support/lifecycle-test-support.ts +0 -413
- package/src/test-support/monitor-mocks-test-support.ts +0 -209
- package/src/token.test.ts +0 -92
- package/src/token.ts +0 -79
- package/src/types.ts +0 -50
- package/test-api.ts +0 -1
- package/tsconfig.json +0 -16
package/src/session-route.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
buildChannelOutboundSessionRoute,
|
|
3
|
-
stripChannelTargetPrefix,
|
|
4
|
-
stripTargetKindPrefix,
|
|
5
|
-
type ChannelOutboundSessionRouteParams,
|
|
6
|
-
} from "openclaw/plugin-sdk/core";
|
|
7
|
-
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
|
8
|
-
|
|
9
|
-
export function resolveZaloOutboundSessionRoute(params: ChannelOutboundSessionRouteParams) {
|
|
10
|
-
const trimmed = stripChannelTargetPrefix(params.target, "zalo", "zl");
|
|
11
|
-
if (!trimmed) {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
const isGroup = normalizeLowercaseStringOrEmpty(trimmed).startsWith("group:");
|
|
15
|
-
const peerId = stripTargetKindPrefix(trimmed);
|
|
16
|
-
if (!peerId) {
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
return buildChannelOutboundSessionRoute({
|
|
20
|
-
cfg: params.cfg,
|
|
21
|
-
agentId: params.agentId,
|
|
22
|
-
channel: "zalo",
|
|
23
|
-
accountId: params.accountId,
|
|
24
|
-
peer: {
|
|
25
|
-
kind: isGroup ? "group" : "direct",
|
|
26
|
-
id: peerId,
|
|
27
|
-
},
|
|
28
|
-
chatType: isGroup ? "group" : "direct",
|
|
29
|
-
from: isGroup ? `zalo:group:${peerId}` : `zalo:${peerId}`,
|
|
30
|
-
to: `zalo:${peerId}`,
|
|
31
|
-
});
|
|
32
|
-
}
|
package/src/setup-allow-from.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_ACCOUNT_ID,
|
|
3
|
-
formatDocsLink,
|
|
4
|
-
mergeAllowFromEntries,
|
|
5
|
-
type ChannelSetupDmPolicy,
|
|
6
|
-
type ChannelSetupWizard,
|
|
7
|
-
type OpenClawConfig,
|
|
8
|
-
} from "openclaw/plugin-sdk/setup";
|
|
9
|
-
import { resolveDefaultZaloAccountId, resolveZaloAccount } from "./accounts.js";
|
|
10
|
-
|
|
11
|
-
type ZaloAccountSetupConfig = {
|
|
12
|
-
enabled?: boolean;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export async function noteZaloTokenHelp(
|
|
16
|
-
prompter: Parameters<NonNullable<ChannelSetupWizard["finalize"]>>[0]["prompter"],
|
|
17
|
-
): Promise<void> {
|
|
18
|
-
await prompter.note(
|
|
19
|
-
[
|
|
20
|
-
"1) Open Zalo Bot Platform: https://bot.zaloplatforms.com",
|
|
21
|
-
"2) Create a bot and get the token",
|
|
22
|
-
"3) Token looks like 12345689:abc-xyz",
|
|
23
|
-
"Tip: you can also set ZALO_BOT_TOKEN in your env.",
|
|
24
|
-
`Docs: ${formatDocsLink("/channels/zalo", "zalo")}`,
|
|
25
|
-
].join("\n"),
|
|
26
|
-
"Zalo bot token",
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export async function promptZaloAllowFrom(params: {
|
|
31
|
-
cfg: OpenClawConfig;
|
|
32
|
-
prompter: Parameters<NonNullable<ChannelSetupDmPolicy["promptAllowFrom"]>>[0]["prompter"];
|
|
33
|
-
accountId?: string;
|
|
34
|
-
}): Promise<OpenClawConfig> {
|
|
35
|
-
const { cfg, prompter } = params;
|
|
36
|
-
const accountId = params.accountId ?? resolveDefaultZaloAccountId(cfg);
|
|
37
|
-
const resolved = resolveZaloAccount({ cfg, accountId });
|
|
38
|
-
const existingAllowFrom = resolved.config.allowFrom ?? [];
|
|
39
|
-
const entry = await prompter.text({
|
|
40
|
-
message: "Zalo allowFrom (user id)",
|
|
41
|
-
placeholder: "123456789",
|
|
42
|
-
initialValue: existingAllowFrom[0] ? String(existingAllowFrom[0]) : undefined,
|
|
43
|
-
validate: (value) => {
|
|
44
|
-
const raw = (value ?? "").trim();
|
|
45
|
-
if (!raw) {
|
|
46
|
-
return "Required";
|
|
47
|
-
}
|
|
48
|
-
if (!/^\d+$/.test(raw)) {
|
|
49
|
-
return "Use a numeric Zalo user id";
|
|
50
|
-
}
|
|
51
|
-
return undefined;
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
const normalized = entry.trim();
|
|
55
|
-
const unique = mergeAllowFromEntries(existingAllowFrom, [normalized]);
|
|
56
|
-
|
|
57
|
-
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
58
|
-
return {
|
|
59
|
-
...cfg,
|
|
60
|
-
channels: {
|
|
61
|
-
...cfg.channels,
|
|
62
|
-
zalo: {
|
|
63
|
-
...cfg.channels?.zalo,
|
|
64
|
-
enabled: true,
|
|
65
|
-
dmPolicy: "allowlist",
|
|
66
|
-
allowFrom: unique,
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
} as OpenClawConfig;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const currentAccount = cfg.channels?.zalo?.accounts?.[accountId] as
|
|
73
|
-
| ZaloAccountSetupConfig
|
|
74
|
-
| undefined;
|
|
75
|
-
return {
|
|
76
|
-
...cfg,
|
|
77
|
-
channels: {
|
|
78
|
-
...cfg.channels,
|
|
79
|
-
zalo: {
|
|
80
|
-
...cfg.channels?.zalo,
|
|
81
|
-
enabled: true,
|
|
82
|
-
accounts: {
|
|
83
|
-
...cfg.channels?.zalo?.accounts,
|
|
84
|
-
[accountId]: {
|
|
85
|
-
...currentAccount,
|
|
86
|
-
enabled: currentAccount?.enabled ?? true,
|
|
87
|
-
dmPolicy: "allowlist",
|
|
88
|
-
allowFrom: unique,
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
} as OpenClawConfig;
|
|
94
|
-
}
|
package/src/setup-core.ts
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addWildcardAllowFrom,
|
|
3
|
-
createDelegatedSetupWizardProxy,
|
|
4
|
-
createPatchedAccountSetupAdapter,
|
|
5
|
-
createSetupInputPresenceValidator,
|
|
6
|
-
DEFAULT_ACCOUNT_ID,
|
|
7
|
-
normalizeAccountId,
|
|
8
|
-
type ChannelSetupDmPolicy,
|
|
9
|
-
type ChannelSetupWizard,
|
|
10
|
-
} from "openclaw/plugin-sdk/setup";
|
|
11
|
-
import { resolveDefaultZaloAccountId, resolveZaloAccount } from "./accounts.js";
|
|
12
|
-
import { promptZaloAllowFrom } from "./setup-allow-from.js";
|
|
13
|
-
|
|
14
|
-
const channel = "zalo" as const;
|
|
15
|
-
|
|
16
|
-
type ZaloAccountSetupConfig = {
|
|
17
|
-
enabled?: boolean;
|
|
18
|
-
dmPolicy?: string;
|
|
19
|
-
allowFrom?: Array<string | number> | ReadonlyArray<string | number>;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const zaloSetupAdapter = createPatchedAccountSetupAdapter({
|
|
23
|
-
channelKey: channel,
|
|
24
|
-
validateInput: createSetupInputPresenceValidator({
|
|
25
|
-
defaultAccountOnlyEnvError: "ZALO_BOT_TOKEN can only be used for the default account.",
|
|
26
|
-
whenNotUseEnv: [
|
|
27
|
-
{
|
|
28
|
-
someOf: ["token", "tokenFile"],
|
|
29
|
-
message: "Zalo requires token or --token-file (or --use-env).",
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
}),
|
|
33
|
-
buildPatch: (input) =>
|
|
34
|
-
input.useEnv
|
|
35
|
-
? {}
|
|
36
|
-
: input.tokenFile
|
|
37
|
-
? { tokenFile: input.tokenFile }
|
|
38
|
-
: input.token
|
|
39
|
-
? { botToken: input.token }
|
|
40
|
-
: {},
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
export const zaloDmPolicy: ChannelSetupDmPolicy = {
|
|
44
|
-
label: "Zalo",
|
|
45
|
-
channel,
|
|
46
|
-
policyKey: "channels.zalo.dmPolicy",
|
|
47
|
-
allowFromKey: "channels.zalo.allowFrom",
|
|
48
|
-
resolveConfigKeys: (cfg, accountId) =>
|
|
49
|
-
(accountId ?? resolveDefaultZaloAccountId(cfg)) !== DEFAULT_ACCOUNT_ID
|
|
50
|
-
? {
|
|
51
|
-
policyKey: `channels.zalo.accounts.${accountId ?? resolveDefaultZaloAccountId(cfg)}.dmPolicy`,
|
|
52
|
-
allowFromKey: `channels.zalo.accounts.${accountId ?? resolveDefaultZaloAccountId(cfg)}.allowFrom`,
|
|
53
|
-
}
|
|
54
|
-
: {
|
|
55
|
-
policyKey: "channels.zalo.dmPolicy",
|
|
56
|
-
allowFromKey: "channels.zalo.allowFrom",
|
|
57
|
-
},
|
|
58
|
-
getCurrent: (cfg, accountId) =>
|
|
59
|
-
resolveZaloAccount({
|
|
60
|
-
cfg: cfg,
|
|
61
|
-
accountId: accountId ?? resolveDefaultZaloAccountId(cfg),
|
|
62
|
-
}).config.dmPolicy ?? "pairing",
|
|
63
|
-
setPolicy: (cfg, policy, accountId) => {
|
|
64
|
-
const resolvedAccountId =
|
|
65
|
-
accountId && normalizeAccountId(accountId)
|
|
66
|
-
? (normalizeAccountId(accountId) ?? DEFAULT_ACCOUNT_ID)
|
|
67
|
-
: resolveDefaultZaloAccountId(cfg);
|
|
68
|
-
const resolved = resolveZaloAccount({
|
|
69
|
-
cfg: cfg,
|
|
70
|
-
accountId: resolvedAccountId,
|
|
71
|
-
});
|
|
72
|
-
if (resolvedAccountId === DEFAULT_ACCOUNT_ID) {
|
|
73
|
-
return {
|
|
74
|
-
...cfg,
|
|
75
|
-
channels: {
|
|
76
|
-
...cfg.channels,
|
|
77
|
-
zalo: {
|
|
78
|
-
...cfg.channels?.zalo,
|
|
79
|
-
enabled: true,
|
|
80
|
-
dmPolicy: policy,
|
|
81
|
-
...(policy === "open"
|
|
82
|
-
? { allowFrom: addWildcardAllowFrom(resolved.config.allowFrom) }
|
|
83
|
-
: {}),
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
const currentAccount = cfg.channels?.zalo?.accounts?.[resolvedAccountId] as
|
|
89
|
-
| ZaloAccountSetupConfig
|
|
90
|
-
| undefined;
|
|
91
|
-
return {
|
|
92
|
-
...cfg,
|
|
93
|
-
channels: {
|
|
94
|
-
...cfg.channels,
|
|
95
|
-
zalo: {
|
|
96
|
-
...cfg.channels?.zalo,
|
|
97
|
-
enabled: true,
|
|
98
|
-
accounts: {
|
|
99
|
-
...cfg.channels?.zalo?.accounts,
|
|
100
|
-
[resolvedAccountId]: {
|
|
101
|
-
...currentAccount,
|
|
102
|
-
enabled: currentAccount?.enabled ?? true,
|
|
103
|
-
dmPolicy: policy,
|
|
104
|
-
...(policy === "open"
|
|
105
|
-
? { allowFrom: addWildcardAllowFrom(resolved.config.allowFrom) }
|
|
106
|
-
: {}),
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
};
|
|
112
|
-
},
|
|
113
|
-
promptAllowFrom: async ({ cfg, prompter, accountId }) =>
|
|
114
|
-
promptZaloAllowFrom({
|
|
115
|
-
cfg,
|
|
116
|
-
prompter,
|
|
117
|
-
accountId: accountId ?? resolveDefaultZaloAccountId(cfg),
|
|
118
|
-
}),
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
export function createZaloSetupWizardProxy(
|
|
122
|
-
loadWizard: () => Promise<ChannelSetupWizard>,
|
|
123
|
-
): ChannelSetupWizard {
|
|
124
|
-
return createDelegatedSetupWizardProxy({
|
|
125
|
-
channel,
|
|
126
|
-
loadWizard,
|
|
127
|
-
status: {
|
|
128
|
-
configuredLabel: "configured",
|
|
129
|
-
unconfiguredLabel: "needs token",
|
|
130
|
-
configuredHint: "recommended · configured",
|
|
131
|
-
unconfiguredHint: "recommended · newcomer-friendly",
|
|
132
|
-
configuredScore: 1,
|
|
133
|
-
unconfiguredScore: 10,
|
|
134
|
-
},
|
|
135
|
-
credentials: [],
|
|
136
|
-
delegateFinalize: true,
|
|
137
|
-
dmPolicy: zaloDmPolicy,
|
|
138
|
-
disable: (cfg) => ({
|
|
139
|
-
...cfg,
|
|
140
|
-
channels: {
|
|
141
|
-
...cfg.channels,
|
|
142
|
-
zalo: {
|
|
143
|
-
...cfg.channels?.zalo,
|
|
144
|
-
enabled: false,
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
}),
|
|
148
|
-
});
|
|
149
|
-
}
|
package/src/setup-status.test.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { createPluginSetupWizardStatus } from "openclaw/plugin-sdk/plugin-test-runtime";
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
import type { OpenClawConfig } from "../runtime-api.js";
|
|
4
|
-
import { zaloSetupWizard } from "./setup-surface.js";
|
|
5
|
-
|
|
6
|
-
const zaloGetStatus = createPluginSetupWizardStatus({
|
|
7
|
-
id: "zalo",
|
|
8
|
-
meta: {
|
|
9
|
-
label: "Zalo",
|
|
10
|
-
},
|
|
11
|
-
setupWizard: zaloSetupWizard,
|
|
12
|
-
} as never);
|
|
13
|
-
|
|
14
|
-
describe("zalo setup wizard status", () => {
|
|
15
|
-
it("treats SecretRef botToken as configured", async () => {
|
|
16
|
-
const status = await zaloGetStatus({
|
|
17
|
-
cfg: {
|
|
18
|
-
channels: {
|
|
19
|
-
zalo: {
|
|
20
|
-
botToken: {
|
|
21
|
-
source: "env",
|
|
22
|
-
provider: "default",
|
|
23
|
-
id: "ZALO_BOT_TOKEN",
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
} as OpenClawConfig,
|
|
28
|
-
accountOverrides: {},
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
expect(status.configured).toBe(true);
|
|
32
|
-
});
|
|
33
|
-
});
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
2
|
-
import {
|
|
3
|
-
createPluginSetupWizardConfigure,
|
|
4
|
-
createTestWizardPrompter,
|
|
5
|
-
runSetupWizardConfigure,
|
|
6
|
-
} from "openclaw/plugin-sdk/plugin-test-runtime";
|
|
7
|
-
import type { WizardPrompter } from "openclaw/plugin-sdk/plugin-test-runtime";
|
|
8
|
-
import { describe, expect, it, vi } from "vitest";
|
|
9
|
-
import type { OpenClawConfig } from "../runtime-api.js";
|
|
10
|
-
import { listZaloAccountIds, resolveDefaultZaloAccountId, resolveZaloAccount } from "./accounts.js";
|
|
11
|
-
import { zaloDmPolicy } from "./setup-core.js";
|
|
12
|
-
import { zaloSetupAdapter, zaloSetupWizard } from "./setup-surface.js";
|
|
13
|
-
|
|
14
|
-
const zaloSetupPlugin = {
|
|
15
|
-
id: "zalo",
|
|
16
|
-
meta: {
|
|
17
|
-
id: "zalo",
|
|
18
|
-
label: "Zalo",
|
|
19
|
-
selectionLabel: "Zalo (Bot API)",
|
|
20
|
-
docsPath: "/channels/zalo",
|
|
21
|
-
blurb: "Vietnam-focused messaging platform with Bot API.",
|
|
22
|
-
},
|
|
23
|
-
capabilities: {
|
|
24
|
-
chatTypes: ["direct", "group"] as Array<"direct" | "group">,
|
|
25
|
-
},
|
|
26
|
-
config: {
|
|
27
|
-
listAccountIds: (cfg: unknown) => listZaloAccountIds(cfg as never),
|
|
28
|
-
defaultAccountId: (cfg: unknown) => resolveDefaultZaloAccountId(cfg as never),
|
|
29
|
-
resolveAccount: adaptScopedAccountAccessor(resolveZaloAccount),
|
|
30
|
-
},
|
|
31
|
-
setup: zaloSetupAdapter,
|
|
32
|
-
setupWizard: zaloSetupWizard,
|
|
33
|
-
} as const;
|
|
34
|
-
|
|
35
|
-
const zaloConfigure = createPluginSetupWizardConfigure(zaloSetupPlugin);
|
|
36
|
-
|
|
37
|
-
describe("zalo setup wizard", () => {
|
|
38
|
-
it("configures a polling token flow", async () => {
|
|
39
|
-
const prompter = createTestWizardPrompter({
|
|
40
|
-
select: vi.fn(async () => "plaintext") as WizardPrompter["select"],
|
|
41
|
-
text: vi.fn(async ({ message }: { message: string }) => {
|
|
42
|
-
if (message === "Enter Zalo bot token") {
|
|
43
|
-
return "12345689:abc-xyz";
|
|
44
|
-
}
|
|
45
|
-
throw new Error(`Unexpected prompt: ${message}`);
|
|
46
|
-
}) as WizardPrompter["text"],
|
|
47
|
-
confirm: vi.fn(async ({ message }: { message: string }) => {
|
|
48
|
-
if (message === "Use webhook mode for Zalo?") {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
return false;
|
|
52
|
-
}),
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const result = await runSetupWizardConfigure({
|
|
56
|
-
configure: zaloConfigure,
|
|
57
|
-
cfg: {} as OpenClawConfig,
|
|
58
|
-
prompter,
|
|
59
|
-
options: { secretInputMode: "plaintext" as const },
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
expect(result.accountId).toBe("default");
|
|
63
|
-
expect(result.cfg.channels?.zalo?.enabled).toBe(true);
|
|
64
|
-
expect(result.cfg.channels?.zalo?.botToken).toBe("12345689:abc-xyz");
|
|
65
|
-
expect(result.cfg.channels?.zalo?.webhookUrl).toBeUndefined();
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it("reads the named-account DM policy instead of the channel root", () => {
|
|
69
|
-
expect(
|
|
70
|
-
zaloDmPolicy.getCurrent(
|
|
71
|
-
{
|
|
72
|
-
channels: {
|
|
73
|
-
zalo: {
|
|
74
|
-
dmPolicy: "disabled",
|
|
75
|
-
accounts: {
|
|
76
|
-
work: {
|
|
77
|
-
botToken: "12345689:abc-xyz",
|
|
78
|
-
dmPolicy: "allowlist",
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
} as OpenClawConfig,
|
|
84
|
-
"work",
|
|
85
|
-
),
|
|
86
|
-
).toBe("allowlist");
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("reports account-scoped config keys for named accounts", () => {
|
|
90
|
-
expect(zaloDmPolicy.resolveConfigKeys?.({} as OpenClawConfig, "work")).toEqual({
|
|
91
|
-
policyKey: "channels.zalo.accounts.work.dmPolicy",
|
|
92
|
-
allowFromKey: "channels.zalo.accounts.work.allowFrom",
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it("uses configured defaultAccount for omitted DM policy account context", () => {
|
|
97
|
-
const cfg = {
|
|
98
|
-
channels: {
|
|
99
|
-
zalo: {
|
|
100
|
-
defaultAccount: "work",
|
|
101
|
-
dmPolicy: "disabled",
|
|
102
|
-
allowFrom: ["123456789"],
|
|
103
|
-
accounts: {
|
|
104
|
-
work: {
|
|
105
|
-
botToken: "12345689:abc-xyz",
|
|
106
|
-
dmPolicy: "allowlist",
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
} as OpenClawConfig;
|
|
112
|
-
|
|
113
|
-
expect(zaloDmPolicy.getCurrent(cfg)).toBe("allowlist");
|
|
114
|
-
expect(zaloDmPolicy.resolveConfigKeys?.(cfg)).toEqual({
|
|
115
|
-
policyKey: "channels.zalo.accounts.work.dmPolicy",
|
|
116
|
-
allowFromKey: "channels.zalo.accounts.work.allowFrom",
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
const next = zaloDmPolicy.setPolicy(cfg, "open");
|
|
120
|
-
expect(next.channels?.zalo?.dmPolicy).toBe("disabled");
|
|
121
|
-
const workAccount = next.channels?.zalo?.accounts?.work as
|
|
122
|
-
| { dmPolicy?: string; allowFrom?: Array<string | number> }
|
|
123
|
-
| undefined;
|
|
124
|
-
expect(workAccount?.dmPolicy).toBe("open");
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('writes open policy state to the named account and preserves inherited allowFrom with "*"', () => {
|
|
128
|
-
const next = zaloDmPolicy.setPolicy(
|
|
129
|
-
{
|
|
130
|
-
channels: {
|
|
131
|
-
zalo: {
|
|
132
|
-
allowFrom: ["123456789"],
|
|
133
|
-
accounts: {
|
|
134
|
-
work: {
|
|
135
|
-
botToken: "12345689:abc-xyz",
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
} as OpenClawConfig,
|
|
141
|
-
"open",
|
|
142
|
-
"work",
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
expect(next.channels?.zalo?.dmPolicy).toBeUndefined();
|
|
146
|
-
const workAccount = next.channels?.zalo?.accounts?.work as
|
|
147
|
-
| { dmPolicy?: string; allowFrom?: Array<string | number> }
|
|
148
|
-
| undefined;
|
|
149
|
-
expect(workAccount?.dmPolicy).toBe("open");
|
|
150
|
-
expect(workAccount?.allowFrom).toEqual(["123456789", "*"]);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it("uses configured defaultAccount for omitted setup configured state", async () => {
|
|
154
|
-
const configured = await zaloSetupWizard.status.resolveConfigured({
|
|
155
|
-
cfg: {
|
|
156
|
-
channels: {
|
|
157
|
-
zalo: {
|
|
158
|
-
defaultAccount: "work",
|
|
159
|
-
botToken: "root-token",
|
|
160
|
-
accounts: {
|
|
161
|
-
alerts: {
|
|
162
|
-
botToken: "alerts-token",
|
|
163
|
-
},
|
|
164
|
-
work: {
|
|
165
|
-
botToken: "",
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
} as OpenClawConfig,
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
expect(configured).toBe(false);
|
|
174
|
-
});
|
|
175
|
-
});
|