diff --git a/extensions/zalouser/src/accounts.runtime.ts b/extensions/zalouser/src/accounts.runtime.ts new file mode 100644 index 00000000000..6a3f6dcea29 --- /dev/null +++ b/extensions/zalouser/src/accounts.runtime.ts @@ -0,0 +1 @@ +export { checkZaloAuthenticated, getZaloUserInfo } from "./zalo-js.js"; diff --git a/extensions/zalouser/src/accounts.ts b/extensions/zalouser/src/accounts.ts index 2f2cc80d3a0..743f6090e11 100644 --- a/extensions/zalouser/src/accounts.ts +++ b/extensions/zalouser/src/accounts.ts @@ -6,7 +6,13 @@ import { } from "openclaw/plugin-sdk/account-resolution"; import type { OpenClawConfig } from "../runtime-api.js"; import type { ResolvedZalouserAccount, ZalouserAccountConfig, ZalouserConfig } from "./types.js"; -import { checkZaloAuthenticated, getZaloUserInfo } from "./zalo-js.js"; + +let zalouserAccountsRuntimePromise: Promise | undefined; + +async function loadZalouserAccountsRuntime() { + zalouserAccountsRuntimePromise ??= import("./accounts.runtime.js"); + return await zalouserAccountsRuntimePromise; +} const { listAccountIds: listZalouserAccountIds, @@ -66,7 +72,7 @@ export async function resolveZalouserAccount(params: { accountId?: string | null; }): Promise { const { accountId, enabled, merged, profile } = resolveZalouserAccountBase(params); - const authenticated = await checkZaloAuthenticated(profile); + const authenticated = await (await loadZalouserAccountsRuntime()).checkZaloAuthenticated(profile); return { accountId, @@ -107,7 +113,7 @@ export async function listEnabledZalouserAccounts( export async function getZcaUserInfo( profile: string, ): Promise<{ userId?: string; displayName?: string } | null> { - const info = await getZaloUserInfo(profile); + const info = await (await loadZalouserAccountsRuntime()).getZaloUserInfo(profile); if (!info) { return null; } @@ -117,6 +123,8 @@ export async function getZcaUserInfo( }; } -export { checkZaloAuthenticated as checkZcaAuthenticated }; +export async function checkZcaAuthenticated(profile: string): Promise { + return await (await loadZalouserAccountsRuntime()).checkZaloAuthenticated(profile); +} export type { ResolvedZalouserAccount } from "./types.js"; diff --git a/extensions/zalouser/src/channel.runtime.ts b/extensions/zalouser/src/channel.runtime.ts new file mode 100644 index 00000000000..6e01fe9d14e --- /dev/null +++ b/extensions/zalouser/src/channel.runtime.ts @@ -0,0 +1,12 @@ +export { probeZalouser } from "./probe.js"; +export { collectZalouserSecurityAuditFindings } from "./security-audit.js"; +export { sendMessageZalouser, sendReactionZalouser } from "./send.js"; +export { + listZaloFriendsMatching, + listZaloGroupMembers, + listZaloGroupsMatching, + logoutZaloProfile, + startZaloQrLogin, + waitForZaloQrLogin, + getZaloUserInfo, +} from "./zalo-js.js"; diff --git a/extensions/zalouser/src/channel.ts b/extensions/zalouser/src/channel.ts index 91719a64806..d3fe444379d 100644 --- a/extensions/zalouser/src/channel.ts +++ b/extensions/zalouser/src/channel.ts @@ -8,6 +8,7 @@ import { import { createStaticReplyToModeResolver } from "openclaw/plugin-sdk/conversation-runtime"; import { createChatChannelPlugin } from "openclaw/plugin-sdk/core"; import { buildPassiveProbedChannelStatusSummary } from "openclaw/plugin-sdk/extension-shared"; +import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; import { createAsyncComputedAccountStatusAdapter, createDefaultChannelRuntimeState, @@ -16,7 +17,6 @@ import { listZalouserAccountIds, resolveDefaultZalouserAccountId, resolveZalouserAccountSync, - getZcaUserInfo, checkZcaAuthenticated, type ResolvedZalouserAccount, } from "./accounts.js"; @@ -39,11 +39,9 @@ import { } from "./channel-api.js"; import { buildZalouserGroupCandidates, findZalouserGroupEntry } from "./group-policy.js"; import { resolveZalouserReactionMessageIds } from "./message-sid.js"; -import { probeZalouser, type ZalouserProbeResult } from "./probe.js"; +import type { ZalouserProbeResult } from "./probe.js"; import { writeQrDataUrlToTempFile } from "./qr-temp-file.js"; import { getZalouserRuntime } from "./runtime.js"; -import { collectZalouserSecurityAuditFindings } from "./security-audit.js"; -import { sendMessageZalouser, sendReactionZalouser } from "./send.js"; import { normalizeZalouserTarget, parseZalouserDirectoryGroupId, @@ -54,20 +52,14 @@ import { zalouserSetupAdapter } from "./setup-core.js"; import { zalouserSetupWizard } from "./setup-surface.js"; import { createZalouserPluginBase } from "./shared.js"; import { collectZalouserStatusIssues } from "./status-issues.js"; -import { - listZaloFriendsMatching, - listZaloGroupMembers, - listZaloGroupsMatching, - logoutZaloProfile, - startZaloQrLogin, - waitForZaloQrLogin, - getZaloUserInfo, -} from "./zalo-js.js"; + +const loadZalouserChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime.js")); const ZALOUSER_TEXT_CHUNK_LIMIT = 2000; const zalouserRawSendResultAdapter = createRawChannelSendResultAdapter({ channel: "zalouser", sendText: async ({ to, text, accountId, cfg }) => { + const { sendMessageZalouser } = await loadZalouserChannelRuntime(); const account = resolveZalouserAccountSync({ cfg: cfg, accountId }); const target = parseZalouserOutboundTarget(to); return await sendMessageZalouser(target.threadId, text, { @@ -79,6 +71,7 @@ const zalouserRawSendResultAdapter = createRawChannelSendResultAdapter({ }); }, sendMedia: async ({ to, text, mediaUrl, accountId, cfg, mediaLocalRoots, mediaReadFile }) => { + const { sendMessageZalouser } = await loadZalouserChannelRuntime(); const account = resolveZalouserAccountSync({ cfg: cfg, accountId }); const target = parseZalouserOutboundTarget(to); return await sendMessageZalouser(target.threadId, text, { @@ -198,6 +191,7 @@ const zalouserMessageActions: ChannelMessageActionAdapter = { if (action !== "react") { throw new Error(`Zalouser action ${action} not supported`); } + const { sendReactionZalouser } = await loadZalouserChannelRuntime(); const account = resolveZalouserAccountSync({ cfg, accountId }); const threadId = (typeof params.threadId === "string" ? params.threadId.trim() : "") || @@ -283,6 +277,7 @@ export const zalouserPlugin: ChannelPlugin { + const { getZaloUserInfo } = await loadZalouserChannelRuntime(); const account = resolveZalouserAccountSync({ cfg: cfg, accountId }); const parsed = await getZaloUserInfo(account.profile); if (!parsed?.userId) { @@ -296,6 +291,7 @@ export const zalouserPlugin: ChannelPlugin { + const { listZaloFriendsMatching } = await loadZalouserChannelRuntime(); const account = resolveZalouserAccountSync({ cfg: cfg, accountId }); const friends = await listZaloFriendsMatching(account.profile, query); const rows = friends.map((friend) => @@ -309,6 +305,7 @@ export const zalouserPlugin: ChannelPlugin 0 ? rows.slice(0, limit) : rows; }, listGroups: async ({ cfg, accountId, query, limit }) => { + const { listZaloGroupsMatching } = await loadZalouserChannelRuntime(); const account = resolveZalouserAccountSync({ cfg: cfg, accountId }); const groups = await listZaloGroupsMatching(account.profile, query); const rows = groups.map((group) => @@ -321,6 +318,7 @@ export const zalouserPlugin: ChannelPlugin 0 ? rows.slice(0, limit) : rows; }, listGroupMembers: async ({ cfg, accountId, groupId, limit }) => { + const { listZaloGroupMembers } = await loadZalouserChannelRuntime(); const account = resolveZalouserAccountSync({ cfg: cfg, accountId }); const normalizedGroupId = parseZalouserDirectoryGroupId(groupId); const members = await listZaloGroupMembers(account.profile, normalizedGroupId); @@ -349,12 +347,16 @@ export const zalouserPlugin: ChannelPlugin 1 ? "multiple matches; chose first" : undefined, }); } else { - const groups = await listZaloGroupsMatching(account.profile, trimmed); + const groups = await runtimeModule.listZaloGroupsMatching(account.profile, trimmed); const best = groups.find((group) => group.name.toLowerCase() === trimmed.toLowerCase()) ?? groups[0]; @@ -386,6 +388,7 @@ export const zalouserPlugin: ChannelPlugin { + const { startZaloQrLogin, waitForZaloQrLogin } = await loadZalouserChannelRuntime(); const account = resolveZalouserAccountSync({ cfg: cfg, accountId: accountId ?? resolveDefaultZalouserAccountId(cfg), @@ -423,7 +426,8 @@ export const zalouserPlugin: ChannelPlugin buildPassiveProbedChannelStatusSummary(snapshot), - probeAccount: async ({ account, timeoutMs }) => probeZalouser(account.profile, timeoutMs), + probeAccount: async ({ account, timeoutMs }) => + (await loadZalouserChannelRuntime()).probeZalouser(account.profile, timeoutMs), resolveAccountSnapshot: async ({ account, runtime }) => { const configured = await checkZcaAuthenticated(account.profile); const configError = "not authenticated"; @@ -444,10 +448,11 @@ export const zalouserPlugin: ChannelPlugin { + const { getZaloUserInfo } = await loadZalouserChannelRuntime(); const account = ctx.account; let userLabel = ""; try { - const userInfo = await getZcaUserInfo(account.profile); + const userInfo = await getZaloUserInfo(account.profile); if (userInfo?.displayName) { userLabel = ` (${userInfo.displayName})`; } @@ -473,6 +478,7 @@ export const zalouserPlugin: ChannelPlugin { + const { startZaloQrLogin } = await loadZalouserChannelRuntime(); const profile = resolveZalouserQrProfile(params.accountId); return await startZaloQrLogin({ profile, @@ -481,6 +487,7 @@ export const zalouserPlugin: ChannelPlugin { + const { waitForZaloQrLogin } = await loadZalouserChannelRuntime(); const profile = resolveZalouserQrProfile(params.accountId); return await waitForZaloQrLogin({ profile, @@ -488,12 +495,15 @@ export const zalouserPlugin: ChannelPlugin - await logoutZaloProfile(ctx.account.profile || resolveZalouserQrProfile(ctx.accountId)), + await ( + await loadZalouserChannelRuntime() + ).logoutZaloProfile(ctx.account.profile || resolveZalouserQrProfile(ctx.accountId)), }, }, security: { resolveDmPolicy: resolveZalouserDmPolicy, - collectAuditFindings: collectZalouserSecurityAuditFindings, + collectAuditFindings: async (params) => + (await loadZalouserChannelRuntime()).collectZalouserSecurityAuditFindings(params), }, threading: { resolveReplyToMode: createStaticReplyToModeResolver("off"), @@ -504,6 +514,7 @@ export const zalouserPlugin: ChannelPlugin { + const { sendMessageZalouser } = await loadZalouserChannelRuntime(); const account = resolveZalouserAccountSync({ cfg: cfg }); const authenticated = await checkZcaAuthenticated(account.profile); if (!authenticated) {