@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/zalouser",
|
|
3
|
-
"version": "2026.5.2",
|
|
3
|
+
"version": "2026.5.3-beta.2",
|
|
4
4
|
"description": "OpenClaw Zalo Personal Account plugin via native zca-js integration",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"openclaw": "workspace:*"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"openclaw": ">=2026.5.2"
|
|
19
|
+
"openclaw": ">=2026.5.3-beta.2"
|
|
20
20
|
},
|
|
21
21
|
"peerDependenciesMeta": {
|
|
22
22
|
"openclaw": {
|
|
@@ -53,14 +53,23 @@
|
|
|
53
53
|
"minHostVersion": ">=2026.4.10"
|
|
54
54
|
},
|
|
55
55
|
"compat": {
|
|
56
|
-
"pluginApi": ">=2026.5.2"
|
|
56
|
+
"pluginApi": ">=2026.5.3-beta.2"
|
|
57
57
|
},
|
|
58
58
|
"build": {
|
|
59
|
-
"openclawVersion": "2026.5.2"
|
|
59
|
+
"openclawVersion": "2026.5.3-beta.2"
|
|
60
60
|
},
|
|
61
61
|
"release": {
|
|
62
62
|
"publishToClawHub": true,
|
|
63
63
|
"publishToNpm": true
|
|
64
|
-
}
|
|
65
|
-
|
|
64
|
+
},
|
|
65
|
+
"runtimeExtensions": [
|
|
66
|
+
"./dist/index.js"
|
|
67
|
+
],
|
|
68
|
+
"runtimeSetupEntry": "./dist/setup-entry.js"
|
|
69
|
+
},
|
|
70
|
+
"files": [
|
|
71
|
+
"dist/**",
|
|
72
|
+
"openclaw.plugin.json",
|
|
73
|
+
"README.md"
|
|
74
|
+
]
|
|
66
75
|
}
|
package/api.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { zalouserPlugin } from "./src/channel.js";
|
|
2
|
-
export { zalouserSetupPlugin } from "./src/channel.setup.js";
|
|
3
|
-
export { createZalouserTool } from "./src/tool.js";
|
|
4
|
-
export { createZalouserSetupWizardProxy, zalouserSetupAdapter } from "./src/setup-core.js";
|
|
5
|
-
export { zalouserSetupWizard } from "./src/setup-surface.js";
|
|
6
|
-
export {
|
|
7
|
-
collectZalouserSecurityAuditFindings,
|
|
8
|
-
isZalouserMutableGroupEntry,
|
|
9
|
-
} from "./src/security-audit.js";
|
package/channel-plugin-api.ts
DELETED
package/contract-api.ts
DELETED
package/doctor-contract-api.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { normalizeCompatibilityConfig, legacyConfigRules } from "./src/doctor-contract.js";
|
package/index.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type AnyAgentTool,
|
|
3
|
-
defineBundledChannelEntry,
|
|
4
|
-
loadBundledEntryExportSync,
|
|
5
|
-
} from "openclaw/plugin-sdk/channel-entry-contract";
|
|
6
|
-
|
|
7
|
-
function createZalouserTool(context?: unknown): AnyAgentTool {
|
|
8
|
-
const createTool = loadBundledEntryExportSync<(context?: unknown) => AnyAgentTool>(
|
|
9
|
-
import.meta.url,
|
|
10
|
-
{
|
|
11
|
-
specifier: "./api.js",
|
|
12
|
-
exportName: "createZalouserTool",
|
|
13
|
-
},
|
|
14
|
-
);
|
|
15
|
-
return createTool(context);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default defineBundledChannelEntry({
|
|
19
|
-
id: "zalouser",
|
|
20
|
-
name: "Zalo Personal",
|
|
21
|
-
description: "Zalo personal account messaging via native zca-js integration",
|
|
22
|
-
importMetaUrl: import.meta.url,
|
|
23
|
-
plugin: {
|
|
24
|
-
specifier: "./channel-plugin-api.js",
|
|
25
|
-
exportName: "zalouserPlugin",
|
|
26
|
-
},
|
|
27
|
-
runtime: {
|
|
28
|
-
specifier: "./runtime-api.js",
|
|
29
|
-
exportName: "setZalouserRuntime",
|
|
30
|
-
},
|
|
31
|
-
registerFull(api) {
|
|
32
|
-
api.registerTool((ctx) => createZalouserTool(ctx), { name: "zalouser" });
|
|
33
|
-
},
|
|
34
|
-
});
|
package/runtime-api.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
collectZalouserSecurityAuditFindings,
|
|
3
|
-
createZalouserSetupWizardProxy,
|
|
4
|
-
createZalouserTool,
|
|
5
|
-
isZalouserMutableGroupEntry,
|
|
6
|
-
zalouserPlugin,
|
|
7
|
-
zalouserSetupAdapter,
|
|
8
|
-
zalouserSetupPlugin,
|
|
9
|
-
zalouserSetupWizard,
|
|
10
|
-
} from "./api.js";
|
|
11
|
-
export { setZalouserRuntime } from "./src/runtime.js";
|
|
12
|
-
export type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
|
13
|
-
export type {
|
|
14
|
-
BaseProbeResult,
|
|
15
|
-
ChannelAccountSnapshot,
|
|
16
|
-
ChannelDirectoryEntry,
|
|
17
|
-
ChannelGroupContext,
|
|
18
|
-
ChannelMessageActionAdapter,
|
|
19
|
-
ChannelStatusIssue,
|
|
20
|
-
} from "openclaw/plugin-sdk/channel-contract";
|
|
21
|
-
export type {
|
|
22
|
-
OpenClawConfig,
|
|
23
|
-
GroupToolPolicyConfig,
|
|
24
|
-
MarkdownTableMode,
|
|
25
|
-
} from "openclaw/plugin-sdk/config-types";
|
|
26
|
-
export type {
|
|
27
|
-
PluginRuntime,
|
|
28
|
-
AnyAgentTool,
|
|
29
|
-
ChannelPlugin,
|
|
30
|
-
OpenClawPluginToolContext,
|
|
31
|
-
} from "openclaw/plugin-sdk/core";
|
|
32
|
-
export type { RuntimeEnv } from "openclaw/plugin-sdk/runtime";
|
|
33
|
-
export {
|
|
34
|
-
DEFAULT_ACCOUNT_ID,
|
|
35
|
-
buildChannelConfigSchema,
|
|
36
|
-
normalizeAccountId,
|
|
37
|
-
} from "openclaw/plugin-sdk/core";
|
|
38
|
-
export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
|
39
|
-
export { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
|
|
40
|
-
export {
|
|
41
|
-
resolveDefaultGroupPolicy,
|
|
42
|
-
resolveOpenProviderRuntimeGroupPolicy,
|
|
43
|
-
warnMissingProviderGroupPolicyFallbackOnce,
|
|
44
|
-
} from "openclaw/plugin-sdk/runtime-group-policy";
|
|
45
|
-
export {
|
|
46
|
-
mergeAllowlist,
|
|
47
|
-
summarizeMapping,
|
|
48
|
-
formatAllowFromLowercase,
|
|
49
|
-
} from "openclaw/plugin-sdk/allow-from";
|
|
50
|
-
export { resolveInboundMentionDecision } from "openclaw/plugin-sdk/channel-inbound";
|
|
51
|
-
export { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
|
|
52
|
-
export { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline";
|
|
53
|
-
export { buildBaseAccountStatusSnapshot } from "openclaw/plugin-sdk/status-helpers";
|
|
54
|
-
export { resolveSenderCommandAuthorization } from "openclaw/plugin-sdk/command-auth";
|
|
55
|
-
export {
|
|
56
|
-
evaluateGroupRouteAccessForPolicy,
|
|
57
|
-
resolveSenderScopedGroupPolicy,
|
|
58
|
-
} from "openclaw/plugin-sdk/group-access";
|
|
59
|
-
export { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
|
|
60
|
-
export {
|
|
61
|
-
deliverTextOrMediaReply,
|
|
62
|
-
isNumericTargetId,
|
|
63
|
-
resolveSendableOutboundReplyParts,
|
|
64
|
-
sendPayloadWithChunkedTextAndMedia,
|
|
65
|
-
type OutboundReplyPayload,
|
|
66
|
-
} from "openclaw/plugin-sdk/reply-payload";
|
|
67
|
-
export { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/temp-path";
|
package/secret-contract-api.ts
DELETED
package/setup-entry.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
|
2
|
-
|
|
3
|
-
export default defineBundledChannelSetupEntry({
|
|
4
|
-
importMetaUrl: import.meta.url,
|
|
5
|
-
plugin: {
|
|
6
|
-
specifier: "./setup-plugin-api.js",
|
|
7
|
-
exportName: "zalouserSetupPlugin",
|
|
8
|
-
},
|
|
9
|
-
});
|
package/setup-plugin-api.ts
DELETED
package/src/accounts.runtime.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { checkZaloAuthenticated, getZaloUserInfo } from "./zalo-js.js";
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { vi } from "vitest";
|
|
2
|
-
import { createDefaultResolvedZalouserAccount } from "./test-helpers.js";
|
|
3
|
-
|
|
4
|
-
vi.mock("./accounts.js", () => {
|
|
5
|
-
return {
|
|
6
|
-
listZalouserAccountIds: () => ["default"],
|
|
7
|
-
resolveDefaultZalouserAccountId: () => "default",
|
|
8
|
-
resolveZalouserAccountSync: () => createDefaultResolvedZalouserAccount(),
|
|
9
|
-
resolveZalouserAccount: async () => createDefaultResolvedZalouserAccount(),
|
|
10
|
-
listEnabledZalouserAccounts: async () => [createDefaultResolvedZalouserAccount()],
|
|
11
|
-
getZcaUserInfo: async () => null,
|
|
12
|
-
checkZcaAuthenticated: async () => false,
|
|
13
|
-
};
|
|
14
|
-
});
|
package/src/accounts.test.ts
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
|
2
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
-
import type { OpenClawConfig } from "../runtime-api.js";
|
|
4
|
-
import {
|
|
5
|
-
getZcaUserInfo,
|
|
6
|
-
listEnabledZalouserAccounts,
|
|
7
|
-
listZalouserAccountIds,
|
|
8
|
-
resolveDefaultZalouserAccountId,
|
|
9
|
-
resolveZalouserAccount,
|
|
10
|
-
resolveZalouserAccountSync,
|
|
11
|
-
} from "./accounts.js";
|
|
12
|
-
import { checkZaloAuthenticated, getZaloUserInfo } from "./zalo-js.js";
|
|
13
|
-
|
|
14
|
-
vi.mock("./zalo-js.js", () => ({
|
|
15
|
-
checkZaloAuthenticated: vi.fn(),
|
|
16
|
-
getZaloUserInfo: vi.fn(),
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
|
-
const mockCheckAuthenticated = vi.mocked(checkZaloAuthenticated);
|
|
20
|
-
const mockGetUserInfo = vi.mocked(getZaloUserInfo);
|
|
21
|
-
|
|
22
|
-
function asConfig(value: unknown): OpenClawConfig {
|
|
23
|
-
return value as OpenClawConfig;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
describe("zalouser account resolution", () => {
|
|
27
|
-
beforeEach(() => {
|
|
28
|
-
mockCheckAuthenticated.mockReset();
|
|
29
|
-
mockGetUserInfo.mockReset();
|
|
30
|
-
delete process.env.ZALOUSER_PROFILE;
|
|
31
|
-
delete process.env.ZCA_PROFILE;
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("returns default account id when no accounts are configured", () => {
|
|
35
|
-
expect(listZalouserAccountIds(asConfig({}))).toEqual([DEFAULT_ACCOUNT_ID]);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("returns sorted configured account ids", () => {
|
|
39
|
-
const cfg = asConfig({
|
|
40
|
-
channels: {
|
|
41
|
-
zalouser: {
|
|
42
|
-
accounts: {
|
|
43
|
-
work: {},
|
|
44
|
-
personal: {},
|
|
45
|
-
default: {},
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
expect(listZalouserAccountIds(cfg)).toEqual(["default", "personal", "work"]);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("uses configured defaultAccount when present", () => {
|
|
55
|
-
const cfg = asConfig({
|
|
56
|
-
channels: {
|
|
57
|
-
zalouser: {
|
|
58
|
-
defaultAccount: "work",
|
|
59
|
-
accounts: {
|
|
60
|
-
default: {},
|
|
61
|
-
work: {},
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
expect(resolveDefaultZalouserAccountId(cfg)).toBe("work");
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("falls back to default account when configured defaultAccount is missing", () => {
|
|
71
|
-
const cfg = asConfig({
|
|
72
|
-
channels: {
|
|
73
|
-
zalouser: {
|
|
74
|
-
defaultAccount: "missing",
|
|
75
|
-
accounts: {
|
|
76
|
-
default: {},
|
|
77
|
-
work: {},
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
expect(resolveDefaultZalouserAccountId(cfg)).toBe("default");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("falls back to first sorted configured account when default is absent", () => {
|
|
87
|
-
const cfg = asConfig({
|
|
88
|
-
channels: {
|
|
89
|
-
zalouser: {
|
|
90
|
-
accounts: {
|
|
91
|
-
zzz: {},
|
|
92
|
-
aaa: {},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
expect(resolveDefaultZalouserAccountId(cfg)).toBe("aaa");
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it("resolves sync account by merging base + account config", () => {
|
|
102
|
-
const cfg = asConfig({
|
|
103
|
-
channels: {
|
|
104
|
-
zalouser: {
|
|
105
|
-
enabled: true,
|
|
106
|
-
dmPolicy: "pairing",
|
|
107
|
-
accounts: {
|
|
108
|
-
work: {
|
|
109
|
-
enabled: false,
|
|
110
|
-
name: "Work",
|
|
111
|
-
dmPolicy: "allowlist",
|
|
112
|
-
allowFrom: ["123"],
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
const resolved = resolveZalouserAccountSync({ cfg, accountId: "work" });
|
|
120
|
-
expect(resolved.accountId).toBe("work");
|
|
121
|
-
expect(resolved.enabled).toBe(false);
|
|
122
|
-
expect(resolved.name).toBe("Work");
|
|
123
|
-
expect(resolved.config.dmPolicy).toBe("allowlist");
|
|
124
|
-
expect(resolved.config.allowFrom).toEqual(["123"]);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("uses configured defaultAccount when accountId is omitted", () => {
|
|
128
|
-
const cfg = asConfig({
|
|
129
|
-
channels: {
|
|
130
|
-
zalouser: {
|
|
131
|
-
defaultAccount: "work",
|
|
132
|
-
accounts: {
|
|
133
|
-
work: {
|
|
134
|
-
name: "Work",
|
|
135
|
-
profile: "work-profile",
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
const resolved = resolveZalouserAccountSync({ cfg });
|
|
143
|
-
expect(resolved.accountId).toBe("work");
|
|
144
|
-
expect(resolved.name).toBe("Work");
|
|
145
|
-
expect(resolved.profile).toBe("work-profile");
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("resolves account config when account key casing differs from normalized id", () => {
|
|
149
|
-
const cfg = asConfig({
|
|
150
|
-
channels: {
|
|
151
|
-
zalouser: {
|
|
152
|
-
accounts: {
|
|
153
|
-
Work: {
|
|
154
|
-
name: "Work",
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
const resolved = resolveZalouserAccountSync({ cfg, accountId: "work" });
|
|
162
|
-
expect(resolved.accountId).toBe("work");
|
|
163
|
-
expect(resolved.name).toBe("Work");
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it("defaults group policy to allowlist when unset", () => {
|
|
167
|
-
const cfg = asConfig({
|
|
168
|
-
channels: {
|
|
169
|
-
zalouser: {
|
|
170
|
-
enabled: true,
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const resolved = resolveZalouserAccountSync({ cfg, accountId: "default" });
|
|
176
|
-
expect(resolved.config.groupPolicy).toBe("allowlist");
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it("resolves profile precedence correctly", () => {
|
|
180
|
-
const cfg = asConfig({
|
|
181
|
-
channels: {
|
|
182
|
-
zalouser: {
|
|
183
|
-
accounts: {
|
|
184
|
-
work: {},
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
process.env.ZALOUSER_PROFILE = "zalo-env";
|
|
191
|
-
expect(resolveZalouserAccountSync({ cfg, accountId: "work" }).profile).toBe("zalo-env");
|
|
192
|
-
|
|
193
|
-
delete process.env.ZALOUSER_PROFILE;
|
|
194
|
-
process.env.ZCA_PROFILE = "zca-env";
|
|
195
|
-
expect(resolveZalouserAccountSync({ cfg, accountId: "work" }).profile).toBe("zca-env");
|
|
196
|
-
|
|
197
|
-
delete process.env.ZCA_PROFILE;
|
|
198
|
-
expect(resolveZalouserAccountSync({ cfg, accountId: "work" }).profile).toBe("work");
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
it("uses explicit profile from config over env fallback", () => {
|
|
202
|
-
process.env.ZALOUSER_PROFILE = "env-profile";
|
|
203
|
-
const cfg = asConfig({
|
|
204
|
-
channels: {
|
|
205
|
-
zalouser: {
|
|
206
|
-
accounts: {
|
|
207
|
-
work: {
|
|
208
|
-
profile: "explicit-profile",
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
},
|
|
212
|
-
},
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
expect(resolveZalouserAccountSync({ cfg, accountId: "work" }).profile).toBe("explicit-profile");
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it("checks authentication during async account resolution", async () => {
|
|
219
|
-
mockCheckAuthenticated.mockResolvedValueOnce(true);
|
|
220
|
-
const cfg = asConfig({
|
|
221
|
-
channels: {
|
|
222
|
-
zalouser: {
|
|
223
|
-
accounts: {
|
|
224
|
-
default: {},
|
|
225
|
-
},
|
|
226
|
-
},
|
|
227
|
-
},
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
const resolved = await resolveZalouserAccount({ cfg, accountId: "default" });
|
|
231
|
-
expect(mockCheckAuthenticated).toHaveBeenCalledWith("default");
|
|
232
|
-
expect(resolved.authenticated).toBe(true);
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it("filters disabled accounts when listing enabled accounts", async () => {
|
|
236
|
-
mockCheckAuthenticated.mockResolvedValue(true);
|
|
237
|
-
const cfg = asConfig({
|
|
238
|
-
channels: {
|
|
239
|
-
zalouser: {
|
|
240
|
-
accounts: {
|
|
241
|
-
default: { enabled: true },
|
|
242
|
-
work: { enabled: false },
|
|
243
|
-
},
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
const accounts = await listEnabledZalouserAccounts(cfg);
|
|
249
|
-
expect(accounts.map((account) => account.accountId)).toEqual(["default"]);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it("maps account info helper from zalo-js", async () => {
|
|
253
|
-
mockGetUserInfo.mockResolvedValueOnce({
|
|
254
|
-
userId: "123",
|
|
255
|
-
displayName: "Alice",
|
|
256
|
-
avatar: "https://example.com/avatar.png",
|
|
257
|
-
});
|
|
258
|
-
expect(await getZcaUserInfo("default")).toEqual({
|
|
259
|
-
userId: "123",
|
|
260
|
-
displayName: "Alice",
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
mockGetUserInfo.mockResolvedValueOnce(null);
|
|
264
|
-
expect(await getZcaUserInfo("default")).toBeNull();
|
|
265
|
-
});
|
|
266
|
-
});
|
package/src/accounts.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createAccountListHelpers,
|
|
3
|
-
DEFAULT_ACCOUNT_ID,
|
|
4
|
-
normalizeAccountId,
|
|
5
|
-
resolveMergedAccountConfig,
|
|
6
|
-
} from "openclaw/plugin-sdk/account-resolution";
|
|
7
|
-
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
|
|
8
|
-
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
|
9
|
-
import type { ResolvedZalouserAccount, ZalouserAccountConfig, ZalouserConfig } from "./types.js";
|
|
10
|
-
|
|
11
|
-
let zalouserAccountsRuntimePromise: Promise<typeof import("./accounts.runtime.js")> | undefined;
|
|
12
|
-
|
|
13
|
-
async function loadZalouserAccountsRuntime() {
|
|
14
|
-
zalouserAccountsRuntimePromise ??= import("./accounts.runtime.js");
|
|
15
|
-
return await zalouserAccountsRuntimePromise;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const {
|
|
19
|
-
listAccountIds: listZalouserAccountIds,
|
|
20
|
-
resolveDefaultAccountId: resolveDefaultZalouserAccountId,
|
|
21
|
-
} = createAccountListHelpers("zalouser");
|
|
22
|
-
export { listZalouserAccountIds, resolveDefaultZalouserAccountId };
|
|
23
|
-
|
|
24
|
-
function mergeZalouserAccountConfig(cfg: OpenClawConfig, accountId: string): ZalouserAccountConfig {
|
|
25
|
-
const merged = resolveMergedAccountConfig<ZalouserAccountConfig>({
|
|
26
|
-
channelConfig: cfg.channels?.zalouser as ZalouserAccountConfig | undefined,
|
|
27
|
-
accounts: (cfg.channels?.zalouser as ZalouserConfig | undefined)?.accounts as
|
|
28
|
-
| Record<string, Partial<ZalouserAccountConfig>>
|
|
29
|
-
| undefined,
|
|
30
|
-
accountId,
|
|
31
|
-
omitKeys: ["defaultAccount"],
|
|
32
|
-
});
|
|
33
|
-
return {
|
|
34
|
-
...merged,
|
|
35
|
-
// Match Telegram's safe default: groups stay allowlisted unless explicitly opened.
|
|
36
|
-
groupPolicy: merged.groupPolicy ?? "allowlist",
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function resolveProfile(config: ZalouserAccountConfig, accountId: string): string {
|
|
41
|
-
if (config.profile?.trim()) {
|
|
42
|
-
return config.profile.trim();
|
|
43
|
-
}
|
|
44
|
-
if (process.env.ZALOUSER_PROFILE?.trim()) {
|
|
45
|
-
return process.env.ZALOUSER_PROFILE.trim();
|
|
46
|
-
}
|
|
47
|
-
if (process.env.ZCA_PROFILE?.trim()) {
|
|
48
|
-
return process.env.ZCA_PROFILE.trim();
|
|
49
|
-
}
|
|
50
|
-
if (accountId !== DEFAULT_ACCOUNT_ID) {
|
|
51
|
-
return accountId;
|
|
52
|
-
}
|
|
53
|
-
return "default";
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function resolveZalouserAccountBase(params: { cfg: OpenClawConfig; accountId?: string | null }) {
|
|
57
|
-
const accountId = normalizeAccountId(
|
|
58
|
-
params.accountId ?? resolveDefaultZalouserAccountId(params.cfg),
|
|
59
|
-
);
|
|
60
|
-
const baseEnabled =
|
|
61
|
-
(params.cfg.channels?.zalouser as ZalouserConfig | undefined)?.enabled !== false;
|
|
62
|
-
const merged = mergeZalouserAccountConfig(params.cfg, accountId);
|
|
63
|
-
return {
|
|
64
|
-
accountId,
|
|
65
|
-
enabled: baseEnabled && merged.enabled !== false,
|
|
66
|
-
merged,
|
|
67
|
-
profile: resolveProfile(merged, accountId),
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export async function resolveZalouserAccount(params: {
|
|
72
|
-
cfg: OpenClawConfig;
|
|
73
|
-
accountId?: string | null;
|
|
74
|
-
}): Promise<ResolvedZalouserAccount> {
|
|
75
|
-
const { accountId, enabled, merged, profile } = resolveZalouserAccountBase(params);
|
|
76
|
-
const authenticated = await (await loadZalouserAccountsRuntime()).checkZaloAuthenticated(profile);
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
accountId,
|
|
80
|
-
name: normalizeOptionalString(merged.name),
|
|
81
|
-
enabled,
|
|
82
|
-
profile,
|
|
83
|
-
authenticated,
|
|
84
|
-
config: merged,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function resolveZalouserAccountSync(params: {
|
|
89
|
-
cfg: OpenClawConfig;
|
|
90
|
-
accountId?: string | null;
|
|
91
|
-
}): ResolvedZalouserAccount {
|
|
92
|
-
const { accountId, enabled, merged, profile } = resolveZalouserAccountBase(params);
|
|
93
|
-
|
|
94
|
-
return {
|
|
95
|
-
accountId,
|
|
96
|
-
name: normalizeOptionalString(merged.name),
|
|
97
|
-
enabled,
|
|
98
|
-
profile,
|
|
99
|
-
authenticated: false,
|
|
100
|
-
config: merged,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export async function listEnabledZalouserAccounts(
|
|
105
|
-
cfg: OpenClawConfig,
|
|
106
|
-
): Promise<ResolvedZalouserAccount[]> {
|
|
107
|
-
const ids = listZalouserAccountIds(cfg);
|
|
108
|
-
const accounts = await Promise.all(
|
|
109
|
-
ids.map((accountId) => resolveZalouserAccount({ cfg, accountId })),
|
|
110
|
-
);
|
|
111
|
-
return accounts.filter((account) => account.enabled);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export async function getZcaUserInfo(
|
|
115
|
-
profile: string,
|
|
116
|
-
): Promise<{ userId?: string; displayName?: string } | null> {
|
|
117
|
-
const info = await (await loadZalouserAccountsRuntime()).getZaloUserInfo(profile);
|
|
118
|
-
if (!info) {
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
return {
|
|
122
|
-
userId: info.userId,
|
|
123
|
-
displayName: info.displayName,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export async function checkZcaAuthenticated(profile: string): Promise<boolean> {
|
|
128
|
-
return await (await loadZalouserAccountsRuntime()).checkZaloAuthenticated(profile);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export type { ResolvedZalouserAccount } from "./types.js";
|
package/src/channel-api.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
|
|
2
|
-
export type {
|
|
3
|
-
ChannelDirectoryEntry,
|
|
4
|
-
ChannelGroupContext,
|
|
5
|
-
ChannelMessageActionAdapter,
|
|
6
|
-
} from "openclaw/plugin-sdk/channel-contract";
|
|
7
|
-
export { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
|
|
8
|
-
export type { ChannelPlugin } from "openclaw/plugin-sdk/core";
|
|
9
|
-
export {
|
|
10
|
-
DEFAULT_ACCOUNT_ID,
|
|
11
|
-
normalizeAccountId,
|
|
12
|
-
type OpenClawConfig,
|
|
13
|
-
} from "openclaw/plugin-sdk/core";
|
|
14
|
-
export { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
|
|
15
|
-
export type { GroupToolPolicyConfig } from "openclaw/plugin-sdk/config-types";
|
|
16
|
-
export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
|
17
|
-
export {
|
|
18
|
-
isNumericTargetId,
|
|
19
|
-
sendPayloadWithChunkedTextAndMedia,
|
|
20
|
-
} from "openclaw/plugin-sdk/reply-payload";
|