@openclaw/zalo 2026.9.8 → 2026.10.1-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/.setup/{api-YaSbmx07.mjs → api-Do4fKxXr.mjs} +1 -1
- package/dist/.setup/{channel-COgJOEix.mjs → channel-f4tP7sv3.mjs} +3 -3
- package/dist/.setup/{channel.runtime-F1ScBwNC.mjs → channel.runtime-I1gRRKZx.mjs} +2 -2
- package/dist/.setup/{monitor-BbW2wx_3.mjs → monitor-BcLcFy7k.mjs} +19 -37
- package/dist/.setup/{monitor.webhook-CaknDJfy.mjs → monitor.webhook-cIt_VYBI.mjs} +1 -1
- package/dist/.setup/secret-contract-DF_0WQX4.mjs +33 -0
- package/dist/.setup/{secret-contract-api-DKDS_ZlS.mjs → secret-contract-api-CRklpdRx.mjs} +1 -1
- package/dist/.setup/{send-sCQINy2G.mjs → send-Cj1YI36h.mjs} +3 -28
- package/dist/.setup/{webhook-spool-CTCugbD_.mjs → webhook-spool-MSe2Vqq3.mjs} +8 -6
- package/dist/api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/secret-contract-api.js +1 -1
- package/dist/setup-entry.js +2 -2
- package/package.json +5 -5
- package/dist/.setup/secret-contract-Cpsqe5Cv.mjs +0 -46
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as zaloDmPolicy, r as zaloSetupAdapter, t as createZaloSetupWizardProxy } from "./setup-core-BE-EaCnS.mjs";
|
|
2
|
-
import { t as zaloPlugin } from "./channel-
|
|
2
|
+
import { t as zaloPlugin } from "./channel-f4tP7sv3.mjs";
|
|
3
3
|
import { n as resolveZaloRuntimeGroupPolicy } from "./group-access-Blsyu-ot.mjs";
|
|
4
4
|
import { zaloSetupWizard } from "../setup-api.js";
|
|
5
5
|
import "../api.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as isZaloAccountConfigured, d as resolveZaloAccount, i as zaloSetupContract, l as listZaloAccountIds, p as buildSecretInputSchema, s as inspectZaloAccount, t as createZaloSetupWizardProxy, u as resolveDefaultZaloAccountId } from "./setup-core-BE-EaCnS.mjs";
|
|
2
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-
|
|
2
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DF_0WQX4.mjs";
|
|
3
3
|
import { describeWebhookAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
4
4
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
|
5
5
|
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
|
|
@@ -24,7 +24,7 @@ import { z } from "zod";
|
|
|
24
24
|
import { buildChannelOutboundSessionRoute, stripChannelTargetPrefix, stripTargetKindPrefix } from "openclaw/plugin-sdk/core";
|
|
25
25
|
import { coerceStatusIssueAccountId, readStatusIssueFields } from "openclaw/plugin-sdk/extension-shared";
|
|
26
26
|
//#region extensions/zalo/src/actions.ts
|
|
27
|
-
const loadZaloActionsRuntime = createLazyRuntimeNamedExport(() => import("./send-
|
|
27
|
+
const loadZaloActionsRuntime = createLazyRuntimeNamedExport(() => import("./send-Cj1YI36h.mjs"), "sendMessageZalo");
|
|
28
28
|
const providerId = "zalo";
|
|
29
29
|
const ZALO_ACTIONS = /* @__PURE__ */ new Set(["send"]);
|
|
30
30
|
function listEnabledAccounts(cfg, accountId) {
|
|
@@ -186,7 +186,7 @@ function looksLikeZaloChatId(raw, normalized) {
|
|
|
186
186
|
const target = normalizeZaloMessagingTarget(normalized ?? raw);
|
|
187
187
|
return Boolean(target);
|
|
188
188
|
}
|
|
189
|
-
const loadZaloChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-
|
|
189
|
+
const loadZaloChannelRuntime = createLazyRuntimeModule(() => import("./channel.runtime-I1gRRKZx.mjs"));
|
|
190
190
|
const zaloSetupWizard = createZaloSetupWizardProxy(async () => (await import("./setup-surface-DMW4dLWX.mjs").then((n) => n.t)).zaloSetupWizard);
|
|
191
191
|
const zaloTextChunkLimit = 2e3;
|
|
192
192
|
async function sendZaloDelivery(ctx) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { m as normalizeSecretInputString } from "./setup-core-BE-EaCnS.mjs";
|
|
2
|
-
import { i as getMe, n as ZaloApiError, sendMessageZalo, t as resolveZaloProxyFetch } from "./send-
|
|
2
|
+
import { i as getMe, n as ZaloApiError, sendMessageZalo, t as resolveZaloProxyFetch } from "./send-Cj1YI36h.mjs";
|
|
3
3
|
import { createAccountStatusSink } from "openclaw/plugin-sdk/channel-outbound";
|
|
4
4
|
import { runChannelProbe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
5
5
|
//#region extensions/zalo/src/probe.ts
|
|
@@ -62,7 +62,7 @@ async function startZaloGatewayAccount(ctx) {
|
|
|
62
62
|
setStatus: ctx.setStatus
|
|
63
63
|
});
|
|
64
64
|
ctx.log?.info(`[${account.accountId}] starting provider${zaloBotLabel} mode=${mode}`);
|
|
65
|
-
const { monitorZaloProvider } = await import("./monitor-
|
|
65
|
+
const { monitorZaloProvider } = await import("./monitor-BcLcFy7k.mjs");
|
|
66
66
|
return monitorZaloProvider({
|
|
67
67
|
token,
|
|
68
68
|
account,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as resolveZaloRuntimeGroupPolicy, t as normalizeZaloAllowEntry } from "./group-access-Blsyu-ot.mjs";
|
|
2
2
|
import { t as getZaloRuntime } from "./runtime-Dfhzt7qb.mjs";
|
|
3
|
-
import { a as getUpdates, c as sendMessage, d as ZALO_OUTBOUND_MEDIA_TTL_MS, l as sendPhoto, n as ZaloApiError, o as getWebhookInfo, r as deleteWebhook, s as sendChatAction, t as resolveZaloProxyFetch, u as setWebhook } from "./send-
|
|
3
|
+
import { a as getUpdates, c as sendMessage, d as ZALO_OUTBOUND_MEDIA_TTL_MS, l as sendPhoto, n as ZaloApiError, o as getWebhookInfo, r as deleteWebhook, s as sendChatAction, t as resolveZaloProxyFetch, u as setWebhook } from "./send-Cj1YI36h.mjs";
|
|
4
4
|
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
|
|
5
5
|
import { createLazyRuntimeModule, createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
|
|
6
6
|
import { deliverTextOrMediaReply, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
7
|
-
import { normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
|
+
import { normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
8
|
import { resolveDefaultGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
9
9
|
import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
10
10
|
import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
|
|
@@ -159,9 +159,7 @@ async function tryHandleHostedZaloMediaRequest(req, res) {
|
|
|
159
159
|
}
|
|
160
160
|
//#endregion
|
|
161
161
|
//#region extensions/zalo/src/monitor.ts
|
|
162
|
-
/** Default idle timeout for Zalo inbound photo downloads (30 seconds). */
|
|
163
162
|
const ZALO_MEDIA_READ_IDLE_TIMEOUT_MS = 3e4;
|
|
164
|
-
/** Maximum wait for Zalo inbound photo response headers (120 seconds). */
|
|
165
163
|
const ZALO_MEDIA_RESPONSE_HEADER_TIMEOUT_MS = 12e4;
|
|
166
164
|
const ZALO_TEXT_LIMIT = 2e3;
|
|
167
165
|
const DEFAULT_MEDIA_MAX_MB = 5;
|
|
@@ -172,8 +170,8 @@ function resolveZaloTimestampMs(date) {
|
|
|
172
170
|
if (!date) return;
|
|
173
171
|
return date >= UNIX_MILLISECONDS_THRESHOLD ? date : date * 1e3;
|
|
174
172
|
}
|
|
175
|
-
const loadZaloWebhookRuntime = createLazyRuntimeNamedExport(() => import("./monitor.webhook-
|
|
176
|
-
const loadZaloWebhookIngressRuntime = createLazyRuntimeNamedExport(() => import("./webhook-spool-
|
|
173
|
+
const loadZaloWebhookRuntime = createLazyRuntimeNamedExport(() => import("./monitor.webhook-cIt_VYBI.mjs"), "zaloWebhookRuntime");
|
|
174
|
+
const loadZaloWebhookIngressRuntime = createLazyRuntimeNamedExport(() => import("./webhook-spool-MSe2Vqq3.mjs"), "zaloWebhookIngressRuntime");
|
|
177
175
|
const loadZaloWebhookModule = createLazyRuntimeModule(async () => ({
|
|
178
176
|
...await loadZaloWebhookRuntime(),
|
|
179
177
|
...await loadZaloWebhookIngressRuntime()
|
|
@@ -209,10 +207,6 @@ function describeWebhookTarget(rawUrl) {
|
|
|
209
207
|
return rawUrl;
|
|
210
208
|
}
|
|
211
209
|
}
|
|
212
|
-
function normalizeWebhookUrl(url) {
|
|
213
|
-
const trimmed = url?.trim();
|
|
214
|
-
return trimmed ? trimmed : void 0;
|
|
215
|
-
}
|
|
216
210
|
function logVerbose(core, runtime, message) {
|
|
217
211
|
if (core.logging.shouldLogVerbose()) runtime.log?.(`[zalo] ${message}`);
|
|
218
212
|
}
|
|
@@ -259,8 +253,9 @@ async function processUpdate(params) {
|
|
|
259
253
|
if (!message) return;
|
|
260
254
|
switch (event_name) {
|
|
261
255
|
case "message.text.received":
|
|
262
|
-
await
|
|
256
|
+
if (message.text?.trim()) await processMessageWithPipeline({
|
|
263
257
|
message,
|
|
258
|
+
text: message.text,
|
|
264
259
|
...sharedContext
|
|
265
260
|
});
|
|
266
261
|
break;
|
|
@@ -276,15 +271,6 @@ async function processUpdate(params) {
|
|
|
276
271
|
case "message.unsupported.received": logVerbose(core, runtime, `[${account.accountId}] Received unsupported message type from ${message.from.id}`);
|
|
277
272
|
}
|
|
278
273
|
}
|
|
279
|
-
async function handleTextMessage(params) {
|
|
280
|
-
const { message } = params;
|
|
281
|
-
const { text } = message;
|
|
282
|
-
if (!text?.trim()) return;
|
|
283
|
-
await processMessageWithPipeline({
|
|
284
|
-
...params,
|
|
285
|
-
text
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
274
|
async function handleImageMessage(params) {
|
|
289
275
|
const { message, mediaMaxMb, account, core, runtime } = params;
|
|
290
276
|
const { photo_url, caption } = message;
|
|
@@ -634,7 +620,7 @@ async function monitorZaloProvider(options) {
|
|
|
634
620
|
const effectiveMediaMaxMb = typeof configuredMediaMaxMb === "number" && configuredMediaMaxMb > 0 ? configuredMediaMaxMb : DEFAULT_MEDIA_MAX_MB;
|
|
635
621
|
const fetcher = fetcherOverride ?? resolveZaloProxyFetch(account.config.proxy);
|
|
636
622
|
const mode = useWebhook ? "webhook" : "polling";
|
|
637
|
-
const effectiveWebhookUrl =
|
|
623
|
+
const effectiveWebhookUrl = normalizeOptionalString(webhookUrl ?? account.config.webhookUrl);
|
|
638
624
|
const effectiveWebhookPath = effectiveWebhookUrl || webhookPath?.trim() || account.config.webhookPath?.trim() ? resolveWebhookPath({
|
|
639
625
|
webhookPath: webhookPath ?? account.config.webhookPath,
|
|
640
626
|
webhookUrl: effectiveWebhookUrl,
|
|
@@ -647,7 +633,7 @@ async function monitorZaloProvider(options) {
|
|
|
647
633
|
}) : void 0;
|
|
648
634
|
let stopped = false;
|
|
649
635
|
const stopHandlers = [];
|
|
650
|
-
|
|
636
|
+
let stopIngress;
|
|
651
637
|
let cleanupWebhook;
|
|
652
638
|
const stop = () => {
|
|
653
639
|
if (stopped) return;
|
|
@@ -702,7 +688,7 @@ async function monitorZaloProvider(options) {
|
|
|
702
688
|
}
|
|
703
689
|
});
|
|
704
690
|
ingress.start();
|
|
705
|
-
|
|
691
|
+
stopIngress = ingress.stop;
|
|
706
692
|
const unregister = registerZaloWebhookTarget({
|
|
707
693
|
account,
|
|
708
694
|
config,
|
|
@@ -732,19 +718,15 @@ async function monitorZaloProvider(options) {
|
|
|
732
718
|
secret_token: webhookSecret
|
|
733
719
|
}, fetcher);
|
|
734
720
|
statusSink?.(channelReadyPatch());
|
|
735
|
-
let webhookCleanupPromise;
|
|
736
721
|
cleanupWebhook = async () => {
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
}
|
|
746
|
-
})();
|
|
747
|
-
await webhookCleanupPromise;
|
|
722
|
+
runtime.log?.(`[${account.accountId}] Zalo stopping; deleting webhook`);
|
|
723
|
+
try {
|
|
724
|
+
await deleteWebhook(token, fetcher, WEBHOOK_CLEANUP_TIMEOUT_MS);
|
|
725
|
+
runtime.log?.(`[${account.accountId}] Zalo webhook deleted`);
|
|
726
|
+
} catch (err) {
|
|
727
|
+
const detail = err instanceof Error && err.name === "AbortError" ? `timed out after ${String(WEBHOOK_CLEANUP_TIMEOUT_MS)}ms` : formatZaloError(err);
|
|
728
|
+
runtime.error?.(`[${account.accountId}] Zalo webhook delete failed: ${detail}`);
|
|
729
|
+
}
|
|
748
730
|
};
|
|
749
731
|
runtime.log?.(`[${account.accountId}] Zalo webhook registered path=${path}`);
|
|
750
732
|
await waitForAbortSignal(abortSignal);
|
|
@@ -752,7 +734,7 @@ async function monitorZaloProvider(options) {
|
|
|
752
734
|
}
|
|
753
735
|
runtime.log?.(`[${account.accountId}] Zalo polling mode: clearing webhook before startup`);
|
|
754
736
|
try {
|
|
755
|
-
const currentWebhookUrl =
|
|
737
|
+
const currentWebhookUrl = normalizeOptionalString((await getWebhookInfo(token, fetcher)).result?.url);
|
|
756
738
|
if (!currentWebhookUrl) runtime.log?.(`[${account.accountId}] Zalo polling mode ready (no webhook configured)`);
|
|
757
739
|
else {
|
|
758
740
|
runtime.log?.(`[${account.accountId}] Zalo polling mode disabling existing webhook ${describeWebhookTarget(currentWebhookUrl)}`);
|
|
@@ -792,7 +774,7 @@ async function monitorZaloProvider(options) {
|
|
|
792
774
|
abortSignal.removeEventListener("abort", stopOnAbort);
|
|
793
775
|
await cleanupWebhook?.();
|
|
794
776
|
stop();
|
|
795
|
-
|
|
777
|
+
await stopIngress?.();
|
|
796
778
|
runtime.log?.(`[${account.accountId}] Zalo provider stopped mode=${mode}`);
|
|
797
779
|
}
|
|
798
780
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ZaloWebhookPayloadError } from "./webhook-spool-
|
|
1
|
+
import { ZaloWebhookPayloadError } from "./webhook-spool-MSe2Vqq3.mjs";
|
|
2
2
|
import { resolveClientIp } from "openclaw/plugin-sdk/core";
|
|
3
3
|
import { WEBHOOK_ANOMALY_COUNTER_DEFAULTS, WEBHOOK_RATE_LIMIT_DEFAULTS, applyBasicWebhookRequestGuards, createFixedWindowRateLimiter, createWebhookAnomalyTracker, registerWebhookTarget, registerWebhookTargetWithPluginRoute, resolveWebhookTargetWithAuthOrRejectSync, withResolvedWebhookRequestPipeline } from "openclaw/plugin-sdk/webhook-ingress";
|
|
4
4
|
import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { collectConditionalChannelFieldAssignments, createChannelSecretContract, hasOwnProperty, normalizeSecretStringValue } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
|
|
2
|
+
//#region extensions/zalo/src/secret-contract.ts
|
|
3
|
+
const channelSecrets = createChannelSecretContract({
|
|
4
|
+
channelKey: "zalo",
|
|
5
|
+
account: ["botToken", "webhookSecret"],
|
|
6
|
+
channel: ["botToken", "webhookSecret"],
|
|
7
|
+
collect(params) {
|
|
8
|
+
const { channel: zalo } = params;
|
|
9
|
+
collectConditionalChannelFieldAssignments({
|
|
10
|
+
...params,
|
|
11
|
+
field: "botToken",
|
|
12
|
+
topLevelActiveWithoutAccounts: true,
|
|
13
|
+
topLevelInheritedAccountActive: ({ account, enabled }) => enabled && !hasOwnProperty(account, "botToken") && !normalizeSecretStringValue(account.tokenFile),
|
|
14
|
+
accountActive: ({ enabled }) => enabled,
|
|
15
|
+
topInactiveReason: "no enabled Zalo surface inherits this top-level botToken.",
|
|
16
|
+
accountInactiveReason: "Zalo account is disabled."
|
|
17
|
+
});
|
|
18
|
+
const baseWebhookUrl = typeof zalo.webhookUrl === "string" ? zalo.webhookUrl.trim() : "";
|
|
19
|
+
const accountWebhookUrl = (account) => hasOwnProperty(account, "webhookUrl") ? typeof account.webhookUrl === "string" ? account.webhookUrl.trim() : "" : baseWebhookUrl;
|
|
20
|
+
collectConditionalChannelFieldAssignments({
|
|
21
|
+
...params,
|
|
22
|
+
field: "webhookSecret",
|
|
23
|
+
topLevelActiveWithoutAccounts: baseWebhookUrl.length > 0,
|
|
24
|
+
topLevelInheritedAccountActive: ({ account, enabled }) => enabled && !hasOwnProperty(account, "webhookSecret") && accountWebhookUrl(account).length > 0,
|
|
25
|
+
accountActive: ({ account, enabled }) => enabled && accountWebhookUrl(account).length > 0,
|
|
26
|
+
topInactiveReason: "no enabled Zalo webhook surface inherits this top-level webhookSecret (webhook mode is not active).",
|
|
27
|
+
accountInactiveReason: "Zalo account is disabled or webhook mode is not active for this account."
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const { secretTargetRegistryEntries, collectRuntimeConfigAssignments } = channelSecrets;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { collectRuntimeConfigAssignments as n, secretTargetRegistryEntries as r, channelSecrets as t };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-
|
|
1
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-DF_0WQX4.mjs";
|
|
2
2
|
import "../secret-contract-api.js";
|
|
3
3
|
export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
|
|
@@ -32,8 +32,8 @@ var ZaloApiError = class extends Error {
|
|
|
32
32
|
return this.errorCode === 408;
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
|
-
function resolveZaloApiUrl(
|
|
36
|
-
const value =
|
|
35
|
+
function resolveZaloApiUrl() {
|
|
36
|
+
const value = process.env[ZALO_API_URL_ENV]?.trim() ?? ZALO_API_BASE;
|
|
37
37
|
if (!value) throw new Error(`${ZALO_API_URL_ENV} must not be empty.`);
|
|
38
38
|
let parsed;
|
|
39
39
|
try {
|
|
@@ -45,11 +45,8 @@ function resolveZaloApiUrl(apiUrl) {
|
|
|
45
45
|
if (parsed.search || parsed.hash) throw new Error(`${ZALO_API_URL_ENV} must not include a query string or fragment.`);
|
|
46
46
|
return parsed.href.replace(/\/+$/u, "");
|
|
47
47
|
}
|
|
48
|
-
/**
|
|
49
|
-
* Call the Zalo Bot API
|
|
50
|
-
*/
|
|
51
48
|
async function callZaloApi(method, token, body, options) {
|
|
52
|
-
const url = `${resolveZaloApiUrl(
|
|
49
|
+
const url = `${resolveZaloApiUrl()}/bot${token}/${method}`;
|
|
53
50
|
const controller = new AbortController();
|
|
54
51
|
const requestTimeoutMs = resolveTimerTimeoutMs(options?.timeoutMs, ZALO_DEFAULT_REQUEST_TIMEOUT_MS);
|
|
55
52
|
const timeoutId = setTimeout(() => controller.abort(), requestTimeoutMs);
|
|
@@ -71,27 +68,18 @@ async function callZaloApi(method, token, body, options) {
|
|
|
71
68
|
clearTimeout(timeoutId);
|
|
72
69
|
}
|
|
73
70
|
}
|
|
74
|
-
/**
|
|
75
|
-
* Validate bot token and get bot info
|
|
76
|
-
*/
|
|
77
71
|
async function getMe(token, timeoutMs, fetcher) {
|
|
78
72
|
return callZaloApi("getMe", token, void 0, {
|
|
79
73
|
timeoutMs,
|
|
80
74
|
fetch: fetcher
|
|
81
75
|
});
|
|
82
76
|
}
|
|
83
|
-
/**
|
|
84
|
-
* Send a text message
|
|
85
|
-
*/
|
|
86
77
|
async function sendMessage(token, params, fetcher, assertDirectAdapterHandoff) {
|
|
87
78
|
return callZaloApi("sendMessage", token, params, {
|
|
88
79
|
fetch: fetcher,
|
|
89
80
|
assertDirectAdapterHandoff
|
|
90
81
|
});
|
|
91
82
|
}
|
|
92
|
-
/**
|
|
93
|
-
* Send a photo message
|
|
94
|
-
*/
|
|
95
83
|
async function sendPhoto(token, params, fetcher, assertDirectAdapterHandoff) {
|
|
96
84
|
const photoUrl = params.photo.trim();
|
|
97
85
|
let parsedPhotoUrl;
|
|
@@ -112,9 +100,6 @@ async function sendPhoto(token, params, fetcher, assertDirectAdapterHandoff) {
|
|
|
112
100
|
assertDirectAdapterHandoff
|
|
113
101
|
});
|
|
114
102
|
}
|
|
115
|
-
/**
|
|
116
|
-
* Send a temporary chat action such as typing.
|
|
117
|
-
*/
|
|
118
103
|
async function sendChatAction(token, params, fetcher, timeoutMs) {
|
|
119
104
|
return callZaloApi("sendChatAction", token, params, {
|
|
120
105
|
timeoutMs,
|
|
@@ -122,7 +107,6 @@ async function sendChatAction(token, params, fetcher, timeoutMs) {
|
|
|
122
107
|
});
|
|
123
108
|
}
|
|
124
109
|
/**
|
|
125
|
-
* Get updates using long polling (dev/testing only)
|
|
126
110
|
* Note: Zalo returns a single update per call, not an array like Telegram
|
|
127
111
|
*/
|
|
128
112
|
async function getUpdates(token, params, fetcher) {
|
|
@@ -133,24 +117,15 @@ async function getUpdates(token, params, fetcher) {
|
|
|
133
117
|
fetch: fetcher
|
|
134
118
|
});
|
|
135
119
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Set webhook URL for receiving updates
|
|
138
|
-
*/
|
|
139
120
|
async function setWebhook(token, params, fetcher) {
|
|
140
121
|
return callZaloApi("setWebhook", token, params, { fetch: fetcher });
|
|
141
122
|
}
|
|
142
|
-
/**
|
|
143
|
-
* Delete webhook configuration
|
|
144
|
-
*/
|
|
145
123
|
async function deleteWebhook(token, fetcher, timeoutMs) {
|
|
146
124
|
return callZaloApi("deleteWebhook", token, void 0, {
|
|
147
125
|
timeoutMs,
|
|
148
126
|
fetch: fetcher
|
|
149
127
|
});
|
|
150
128
|
}
|
|
151
|
-
/**
|
|
152
|
-
* Get current webhook info
|
|
153
|
-
*/
|
|
154
129
|
async function getWebhookInfo(token, fetcher) {
|
|
155
130
|
return callZaloApi("getWebhookInfo", token, void 0, { fetch: fetcher });
|
|
156
131
|
}
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import { t as getZaloRuntime } from "./runtime-Dfhzt7qb.mjs";
|
|
2
|
-
import { n as ZaloApiError } from "./send-
|
|
2
|
+
import { n as ZaloApiError } from "./send-Cj1YI36h.mjs";
|
|
3
3
|
import { DEFAULT_INGRESS_ADOPTION_STALL_MS, DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS, bindIngressLifecycleToReplyOptions, createChannelIngressError, createChannelIngressMonitor } from "openclaw/plugin-sdk/channel-outbound";
|
|
4
4
|
import { normalizeNullableString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
7
7
|
import { runDetachedWebhookWork } from "openclaw/plugin-sdk/webhook-request-guards";
|
|
8
|
-
//#region extensions/zalo/src/
|
|
9
|
-
const ZALO_WEBHOOK_SPOOL_VERSION = 1;
|
|
10
|
-
const ZALO_WEBHOOK_DRAIN_INTERVAL_MS = 500;
|
|
11
|
-
const ZALO_WEBHOOK_MAX_CONCURRENT_DELIVERIES = 8;
|
|
12
|
-
const ZaloWebhookPayloadError = createChannelIngressError("ZaloWebhookPayloadError");
|
|
8
|
+
//#region extensions/zalo/src/message-schema.ts
|
|
13
9
|
const nonEmptyWebhookStringSchema = z.string().transform((value) => normalizeNullableString(value)).pipe(z.string());
|
|
14
10
|
const optionalWebhookStringSchema = z.string().optional().catch(void 0);
|
|
15
11
|
const webhookEnvelopeSchema = z.looseObject({
|
|
@@ -57,6 +53,12 @@ const webhookUpdateSchema = z.object({
|
|
|
57
53
|
message: "text event requires message.text"
|
|
58
54
|
});
|
|
59
55
|
});
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region extensions/zalo/src/webhook-spool.ts
|
|
58
|
+
const ZALO_WEBHOOK_SPOOL_VERSION = 1;
|
|
59
|
+
const ZALO_WEBHOOK_DRAIN_INTERVAL_MS = 500;
|
|
60
|
+
const ZALO_WEBHOOK_MAX_CONCURRENT_DELIVERIES = 8;
|
|
61
|
+
const ZaloWebhookPayloadError = createChannelIngressError("ZaloWebhookPayloadError");
|
|
60
62
|
function parseRawRecord(rawEvent) {
|
|
61
63
|
let parsed;
|
|
62
64
|
try {
|
package/dist/api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as zaloDmPolicy, r as zaloSetupAdapter, t as createZaloSetupWizardProxy } from "./.setup/setup-core-BE-EaCnS.mjs";
|
|
2
|
-
import { t as zaloPlugin } from "./.setup/channel-
|
|
2
|
+
import { t as zaloPlugin } from "./.setup/channel-f4tP7sv3.mjs";
|
|
3
3
|
import { n as resolveZaloRuntimeGroupPolicy } from "./.setup/group-access-Blsyu-ot.mjs";
|
|
4
4
|
import { zaloSetupWizard } from "./setup-api.js";
|
|
5
5
|
export { createZaloSetupWizardProxy, resolveZaloRuntimeGroupPolicy, zaloDmPolicy, zaloPlugin, zaloSetupAdapter, zaloSetupWizard };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as zaloPlugin } from "./.setup/channel-
|
|
1
|
+
import { t as zaloPlugin } from "./.setup/channel-f4tP7sv3.mjs";
|
|
2
2
|
export { zaloPlugin };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./.setup/secret-contract-
|
|
1
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./.setup/secret-contract-DF_0WQX4.mjs";
|
|
2
2
|
export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
|
package/dist/setup-entry.js
CHANGED
|
@@ -4,11 +4,11 @@ import { fileURLToPath } from "node:url";
|
|
|
4
4
|
var setup_entry_default = defineBundledChannelSetupEntry({
|
|
5
5
|
importMetaUrl: import.meta.url,
|
|
6
6
|
plugin: {
|
|
7
|
-
specifier: fileURLToPath(new URL(".setup/api-
|
|
7
|
+
specifier: fileURLToPath(new URL(".setup/api-Do4fKxXr.mjs", import.meta.url).href),
|
|
8
8
|
exportName: "zaloPlugin"
|
|
9
9
|
},
|
|
10
10
|
secrets: {
|
|
11
|
-
specifier: fileURLToPath(new URL(".setup/secret-contract-api-
|
|
11
|
+
specifier: fileURLToPath(new URL(".setup/secret-contract-api-CRklpdRx.mjs", import.meta.url).href),
|
|
12
12
|
exportName: "channelSecrets"
|
|
13
13
|
}
|
|
14
14
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/zalo",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.10.1-beta.2",
|
|
4
4
|
"description": "OpenClaw Zalo channel plugin for bot and webhook chats.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"peerDependencies": {
|
|
11
|
-
"openclaw": ">=2026.
|
|
11
|
+
"openclaw": ">=2026.10.1-beta.2"
|
|
12
12
|
},
|
|
13
13
|
"peerDependenciesMeta": {
|
|
14
14
|
"openclaw": {
|
|
@@ -80,13 +80,13 @@
|
|
|
80
80
|
"clawhubSpec": "clawhub:@openclaw/zalo",
|
|
81
81
|
"npmSpec": "@openclaw/zalo",
|
|
82
82
|
"defaultChoice": "npm",
|
|
83
|
-
"minHostVersion": ">=2026.
|
|
83
|
+
"minHostVersion": ">=2026.9.8"
|
|
84
84
|
},
|
|
85
85
|
"compat": {
|
|
86
|
-
"pluginApi": ">=2026.
|
|
86
|
+
"pluginApi": ">=2026.10.1-beta.2"
|
|
87
87
|
},
|
|
88
88
|
"build": {
|
|
89
|
-
"openclawVersion": "2026.
|
|
89
|
+
"openclawVersion": "2026.10.1-beta.2"
|
|
90
90
|
},
|
|
91
91
|
"release": {
|
|
92
92
|
"publishToClawHub": true,
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { collectConditionalChannelFieldAssignments, createChannelSecretTargetRegistryEntries, getChannelSurface, hasOwnProperty, normalizeSecretStringValue } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
|
|
2
|
-
//#region extensions/zalo/src/secret-contract.ts
|
|
3
|
-
const secretTargetRegistryEntries = createChannelSecretTargetRegistryEntries({
|
|
4
|
-
channelKey: "zalo",
|
|
5
|
-
account: ["botToken", "webhookSecret"],
|
|
6
|
-
channel: ["botToken", "webhookSecret"]
|
|
7
|
-
});
|
|
8
|
-
function collectRuntimeConfigAssignments(params) {
|
|
9
|
-
const resolved = getChannelSurface(params.config, "zalo");
|
|
10
|
-
if (!resolved) return;
|
|
11
|
-
const { channel: zalo, surface } = resolved;
|
|
12
|
-
collectConditionalChannelFieldAssignments({
|
|
13
|
-
channelKey: "zalo",
|
|
14
|
-
field: "botToken",
|
|
15
|
-
channel: zalo,
|
|
16
|
-
surface,
|
|
17
|
-
defaults: params.defaults,
|
|
18
|
-
context: params.context,
|
|
19
|
-
topLevelActiveWithoutAccounts: true,
|
|
20
|
-
topLevelInheritedAccountActive: ({ account, enabled }) => enabled && !hasOwnProperty(account, "botToken") && !normalizeSecretStringValue(account.tokenFile),
|
|
21
|
-
accountActive: ({ enabled }) => enabled,
|
|
22
|
-
topInactiveReason: "no enabled Zalo surface inherits this top-level botToken.",
|
|
23
|
-
accountInactiveReason: "Zalo account is disabled."
|
|
24
|
-
});
|
|
25
|
-
const baseWebhookUrl = typeof zalo.webhookUrl === "string" ? zalo.webhookUrl.trim() : "";
|
|
26
|
-
const accountWebhookUrl = (account) => hasOwnProperty(account, "webhookUrl") ? typeof account.webhookUrl === "string" ? account.webhookUrl.trim() : "" : baseWebhookUrl;
|
|
27
|
-
collectConditionalChannelFieldAssignments({
|
|
28
|
-
channelKey: "zalo",
|
|
29
|
-
field: "webhookSecret",
|
|
30
|
-
channel: zalo,
|
|
31
|
-
surface,
|
|
32
|
-
defaults: params.defaults,
|
|
33
|
-
context: params.context,
|
|
34
|
-
topLevelActiveWithoutAccounts: baseWebhookUrl.length > 0,
|
|
35
|
-
topLevelInheritedAccountActive: ({ account, enabled }) => enabled && !hasOwnProperty(account, "webhookSecret") && accountWebhookUrl(account).length > 0,
|
|
36
|
-
accountActive: ({ account, enabled }) => enabled && accountWebhookUrl(account).length > 0,
|
|
37
|
-
topInactiveReason: "no enabled Zalo webhook surface inherits this top-level webhookSecret (webhook mode is not active).",
|
|
38
|
-
accountInactiveReason: "Zalo account is disabled or webhook mode is not active for this account."
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
const channelSecrets = {
|
|
42
|
-
secretTargetRegistryEntries,
|
|
43
|
-
collectRuntimeConfigAssignments
|
|
44
|
-
};
|
|
45
|
-
//#endregion
|
|
46
|
-
export { collectRuntimeConfigAssignments as n, secretTargetRegistryEntries as r, channelSecrets as t };
|