openclaw-multi-auto 1.4.3 → 1.4.4

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.
Files changed (81) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  3. package/dist/plugin-sdk/accounts-CJWOBzwB.js +35 -0
  4. package/dist/plugin-sdk/accounts-DP1-L-QS.js +288 -0
  5. package/dist/plugin-sdk/accounts-DZhWlEg3.js +46 -0
  6. package/dist/plugin-sdk/active-listener-B_sLJTXM.js +50 -0
  7. package/dist/plugin-sdk/api-key-rotation-BRE4X2tf.js +181 -0
  8. package/dist/plugin-sdk/audio-preflight-DGEUDxxR.js +69 -0
  9. package/dist/plugin-sdk/audio-transcription-runner-DkoPNPYt.js +2176 -0
  10. package/dist/plugin-sdk/audit-membership-runtime-DSBHHw7o.js +58 -0
  11. package/dist/plugin-sdk/channel-activity-F3d0yUwy.js +94 -0
  12. package/dist/plugin-sdk/channel-web-QF7EpjeP.js +2256 -0
  13. package/dist/plugin-sdk/chrome-BXoCyCkY.js +2415 -0
  14. package/dist/plugin-sdk/commands-registry-t7cXBTfN.js +1125 -0
  15. package/dist/plugin-sdk/config-BkEnz2Po.js +17913 -0
  16. package/dist/plugin-sdk/deliver-B6AG_l67.js +1694 -0
  17. package/dist/plugin-sdk/deliver-runtime-D585kJZc.js +32 -0
  18. package/dist/plugin-sdk/deps-send-discord.runtime-a_OKY2js.js +23 -0
  19. package/dist/plugin-sdk/deps-send-imessage.runtime-Baxy9TD4.js +22 -0
  20. package/dist/plugin-sdk/deps-send-signal.runtime-BwXoCrFl.js +21 -0
  21. package/dist/plugin-sdk/deps-send-slack.runtime-CLmKjgso.js +19 -0
  22. package/dist/plugin-sdk/deps-send-telegram.runtime-BKfdBKnZ.js +24 -0
  23. package/dist/plugin-sdk/deps-send-whatsapp.runtime-BOTwkbx_.js +57 -0
  24. package/dist/plugin-sdk/diagnostic-CsP-lEkI.js +319 -0
  25. package/dist/plugin-sdk/errors-DaiAM-yU.js +54 -0
  26. package/dist/plugin-sdk/fetch-guard-DETCcJzQ.js +156 -0
  27. package/dist/plugin-sdk/fs-safe-B8y811FR.js +352 -0
  28. package/dist/plugin-sdk/image-DjTEkYZE.js +2310 -0
  29. package/dist/plugin-sdk/image-ops-BSiMpAw4.js +584 -0
  30. package/dist/plugin-sdk/image-runtime-6xPp8m5a.js +25 -0
  31. package/dist/plugin-sdk/index.js +50 -50
  32. package/dist/plugin-sdk/ir-DQ7_HbvK.js +1296 -0
  33. package/dist/plugin-sdk/local-roots-BUP4YBmR.js +186 -0
  34. package/dist/plugin-sdk/logger-CZY9KIoY.js +1163 -0
  35. package/dist/plugin-sdk/login-BxEKLlCo.js +57 -0
  36. package/dist/plugin-sdk/login-qr-BQIpMPr9.js +320 -0
  37. package/dist/plugin-sdk/manager-I6KbPihW.js +3917 -0
  38. package/dist/plugin-sdk/manager-runtime-CFfYYWIQ.js +15 -0
  39. package/dist/plugin-sdk/mattermost.js +3 -3
  40. package/dist/plugin-sdk/outbound-NS6UHnB6.js +212 -0
  41. package/dist/plugin-sdk/outbound-attachment-Dy6fyf6H.js +19 -0
  42. package/dist/plugin-sdk/path-alias-guards-DBjLbIX_.js +43 -0
  43. package/dist/plugin-sdk/paths-vTM3Lh3X.js +166 -0
  44. package/dist/plugin-sdk/pi-embedded-helpers-1R1gu7eX.js +9627 -0
  45. package/dist/plugin-sdk/pi-model-discovery-runtime-Do9o-dUd.js +8 -0
  46. package/dist/plugin-sdk/pi-model-discovery-v-XPUOOf.js +134 -0
  47. package/dist/plugin-sdk/pi-tools.before-tool-call.runtime-D4sFsIks.js +354 -0
  48. package/dist/plugin-sdk/plugins-DeBZB9l_.js +864 -0
  49. package/dist/plugin-sdk/proxy-fetch-ChxOhWF4.js +38 -0
  50. package/dist/plugin-sdk/pw-ai-DEOmCSSC.js +1938 -0
  51. package/dist/plugin-sdk/qmd-manager-HyYKoEch.js +1448 -0
  52. package/dist/plugin-sdk/query-expansion-CeyKUeDW.js +1011 -0
  53. package/dist/plugin-sdk/redact-DjVX-1N3.js +319 -0
  54. package/dist/plugin-sdk/reply-DAo_Jt8K.js +97916 -0
  55. package/dist/plugin-sdk/resolve-outbound-target-B42qgQS9.js +40 -0
  56. package/dist/plugin-sdk/run-with-concurrency-Bt_ks0Qa.js +1994 -0
  57. package/dist/plugin-sdk/runtime-whatsapp-login.runtime-B6W989eF.js +10 -0
  58. package/dist/plugin-sdk/runtime-whatsapp-outbound.runtime-c_GDFy37.js +19 -0
  59. package/dist/plugin-sdk/send-CQpMudwO.js +2587 -0
  60. package/dist/plugin-sdk/send-DQHLzVyO.js +414 -0
  61. package/dist/plugin-sdk/send-DTB24bEF.js +3135 -0
  62. package/dist/plugin-sdk/send-DfHadjZ_.js +503 -0
  63. package/dist/plugin-sdk/send-XXlW2iny.js +540 -0
  64. package/dist/plugin-sdk/session-6TF6MyaC.js +169 -0
  65. package/dist/plugin-sdk/skill-commands-CkGeFUMl.js +342 -0
  66. package/dist/plugin-sdk/skills-CBkHBYPq.js +1428 -0
  67. package/dist/plugin-sdk/slash-commands.runtime-CxliuGaP.js +13 -0
  68. package/dist/plugin-sdk/slash-dispatch.runtime-DFaeYlJQ.js +52 -0
  69. package/dist/plugin-sdk/slash-skill-commands.runtime-0M0OLCxq.js +16 -0
  70. package/dist/plugin-sdk/ssrf-cFtplYtS.js +202 -0
  71. package/dist/plugin-sdk/store-5nyxY3WU.js +81 -0
  72. package/dist/plugin-sdk/subagent-registry-runtime-DCtmDwna.js +52 -0
  73. package/dist/plugin-sdk/tables-C47P4GTN.js +55 -0
  74. package/dist/plugin-sdk/target-errors-Blia4S69.js +195 -0
  75. package/dist/plugin-sdk/thinking-Bo2eosVa.js +1206 -0
  76. package/dist/plugin-sdk/tokens-DgNRBwIg.js +52 -0
  77. package/dist/plugin-sdk/tool-images-Gk_-0y2N.js +274 -0
  78. package/dist/plugin-sdk/web-CVxZbXyH.js +56 -0
  79. package/dist/plugin-sdk/whatsapp-actions-Bw0H9g-n.js +80 -0
  80. package/package.json +1 -1
  81. package/scripts/install-maca.sh +28 -5
@@ -0,0 +1,52 @@
1
+ import { _ as escapeRegExp } from "./logger-CZY9KIoY.js";
2
+
3
+ //#region src/auto-reply/tokens.ts
4
+ const HEARTBEAT_TOKEN = "HEARTBEAT_OK";
5
+ const SILENT_REPLY_TOKEN = "NO_REPLY";
6
+ const silentExactRegexByToken = /* @__PURE__ */ new Map();
7
+ const silentTrailingRegexByToken = /* @__PURE__ */ new Map();
8
+ function getSilentExactRegex(token) {
9
+ const cached = silentExactRegexByToken.get(token);
10
+ if (cached) return cached;
11
+ const escaped = escapeRegExp(token);
12
+ const regex = new RegExp(`^\\s*${escaped}\\s*$`);
13
+ silentExactRegexByToken.set(token, regex);
14
+ return regex;
15
+ }
16
+ function getSilentTrailingRegex(token) {
17
+ const cached = silentTrailingRegexByToken.get(token);
18
+ if (cached) return cached;
19
+ const escaped = escapeRegExp(token);
20
+ const regex = new RegExp(`(?:^|\\s+|\\*+)${escaped}\\s*$`);
21
+ silentTrailingRegexByToken.set(token, regex);
22
+ return regex;
23
+ }
24
+ function isSilentReplyText(text, token = SILENT_REPLY_TOKEN) {
25
+ if (!text) return false;
26
+ return getSilentExactRegex(token).test(text);
27
+ }
28
+ /**
29
+ * Strip a trailing silent reply token from mixed-content text.
30
+ * Returns the remaining text with the token removed (trimmed).
31
+ * If the result is empty, the entire message should be treated as silent.
32
+ */
33
+ function stripSilentToken(text, token = SILENT_REPLY_TOKEN) {
34
+ return text.replace(getSilentTrailingRegex(token), "").trim();
35
+ }
36
+ function isSilentReplyPrefixText(text, token = SILENT_REPLY_TOKEN) {
37
+ if (!text) return false;
38
+ const trimmed = text.trimStart();
39
+ if (!trimmed) return false;
40
+ if (trimmed !== trimmed.toUpperCase()) return false;
41
+ const normalized = trimmed.toUpperCase();
42
+ if (!normalized) return false;
43
+ if (normalized.length < 2) return false;
44
+ if (/[^A-Z_]/.test(normalized)) return false;
45
+ const tokenUpper = token.toUpperCase();
46
+ if (!tokenUpper.startsWith(normalized)) return false;
47
+ if (normalized.includes("_")) return true;
48
+ return tokenUpper === SILENT_REPLY_TOKEN && normalized === "NO";
49
+ }
50
+
51
+ //#endregion
52
+ export { stripSilentToken as a, isSilentReplyText as i, SILENT_REPLY_TOKEN as n, isSilentReplyPrefixText as r, HEARTBEAT_TOKEN as t };
@@ -0,0 +1,274 @@
1
+ import { a as createSubsystemLogger } from "./logger-CZY9KIoY.js";
2
+ import { i as getImageMetadata, n as buildImageResizeSideGrid, s as resizeToJpeg, t as IMAGE_REDUCE_QUALITY_STEPS } from "./image-ops-BSiMpAw4.js";
3
+
4
+ //#region src/media/base64.ts
5
+ function estimateBase64DecodedBytes(base64) {
6
+ let effectiveLen = 0;
7
+ for (let i = 0; i < base64.length; i += 1) {
8
+ if (base64.charCodeAt(i) <= 32) continue;
9
+ effectiveLen += 1;
10
+ }
11
+ if (effectiveLen === 0) return 0;
12
+ let padding = 0;
13
+ let end = base64.length - 1;
14
+ while (end >= 0 && base64.charCodeAt(end) <= 32) end -= 1;
15
+ if (end >= 0 && base64[end] === "=") {
16
+ padding = 1;
17
+ end -= 1;
18
+ while (end >= 0 && base64.charCodeAt(end) <= 32) end -= 1;
19
+ if (end >= 0 && base64[end] === "=") padding = 2;
20
+ }
21
+ const estimated = Math.floor(effectiveLen * 3 / 4) - padding;
22
+ return Math.max(0, estimated);
23
+ }
24
+ const BASE64_CHARS_RE = /^[A-Za-z0-9+/]+={0,2}$/;
25
+ /**
26
+ * Normalize and validate a base64 string.
27
+ * Returns canonical base64 (no whitespace) or undefined when invalid.
28
+ */
29
+ function canonicalizeBase64(base64) {
30
+ const cleaned = base64.replace(/\s+/g, "");
31
+ if (!cleaned || cleaned.length % 4 !== 0 || !BASE64_CHARS_RE.test(cleaned)) return;
32
+ return cleaned;
33
+ }
34
+
35
+ //#endregion
36
+ //#region src/agents/image-sanitization.ts
37
+ const DEFAULT_IMAGE_MAX_DIMENSION_PX = 1200;
38
+ const DEFAULT_IMAGE_MAX_BYTES = 5 * 1024 * 1024;
39
+ function resolveImageSanitizationLimits(cfg) {
40
+ const configured = cfg?.agents?.defaults?.imageMaxDimensionPx;
41
+ if (typeof configured !== "number" || !Number.isFinite(configured)) return {};
42
+ return { maxDimensionPx: Math.max(1, Math.floor(configured)) };
43
+ }
44
+
45
+ //#endregion
46
+ //#region src/agents/tool-images.ts
47
+ const MAX_IMAGE_DIMENSION_PX = DEFAULT_IMAGE_MAX_DIMENSION_PX;
48
+ const MAX_IMAGE_BYTES = DEFAULT_IMAGE_MAX_BYTES;
49
+ const log = createSubsystemLogger("agents/tool-images");
50
+ function isImageBlock(block) {
51
+ if (!block || typeof block !== "object") return false;
52
+ const rec = block;
53
+ return rec.type === "image" && typeof rec.data === "string" && typeof rec.mimeType === "string";
54
+ }
55
+ function isTextBlock(block) {
56
+ if (!block || typeof block !== "object") return false;
57
+ const rec = block;
58
+ return rec.type === "text" && typeof rec.text === "string";
59
+ }
60
+ function inferMimeTypeFromBase64(base64) {
61
+ const trimmed = base64.trim();
62
+ if (!trimmed) return;
63
+ if (trimmed.startsWith("/9j/")) return "image/jpeg";
64
+ if (trimmed.startsWith("iVBOR")) return "image/png";
65
+ if (trimmed.startsWith("R0lGOD")) return "image/gif";
66
+ }
67
+ function formatBytesShort(bytes) {
68
+ if (!Number.isFinite(bytes) || bytes < 1024) return `${Math.max(0, Math.round(bytes))}B`;
69
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
70
+ return `${(bytes / (1024 * 1024)).toFixed(2)}MB`;
71
+ }
72
+ function parseMediaPathFromText(text) {
73
+ for (const line of text.split(/\r?\n/u)) {
74
+ const trimmed = line.trim();
75
+ if (!trimmed.startsWith("MEDIA:")) continue;
76
+ const raw = trimmed.slice(6).trim();
77
+ if (!raw) continue;
78
+ return (raw.match(/^`([^`]+)`$/u)?.[1] ?? raw).trim();
79
+ }
80
+ }
81
+ function fileNameFromPathLike(pathLike) {
82
+ const value = pathLike.trim();
83
+ if (!value) return;
84
+ try {
85
+ const candidate = new URL(value).pathname.split("/").filter(Boolean).at(-1);
86
+ return candidate && candidate.length > 0 ? candidate : void 0;
87
+ } catch {}
88
+ const candidate = value.replaceAll("\\", "/").split("/").filter(Boolean).at(-1);
89
+ return candidate && candidate.length > 0 ? candidate : void 0;
90
+ }
91
+ function inferImageFileName(params) {
92
+ const rec = params.block;
93
+ for (const key of [
94
+ "fileName",
95
+ "filename",
96
+ "path",
97
+ "url"
98
+ ]) {
99
+ const raw = rec[key];
100
+ if (typeof raw !== "string" || raw.trim().length === 0) continue;
101
+ const candidate = fileNameFromPathLike(raw);
102
+ if (candidate) return candidate;
103
+ }
104
+ if (typeof rec.name === "string" && rec.name.trim().length > 0) return rec.name.trim();
105
+ if (params.mediaPathHint) {
106
+ const candidate = fileNameFromPathLike(params.mediaPathHint);
107
+ if (candidate) return candidate;
108
+ }
109
+ if (typeof params.label === "string" && params.label.startsWith("read:")) {
110
+ const candidate = fileNameFromPathLike(params.label.slice(5));
111
+ if (candidate) return candidate;
112
+ }
113
+ }
114
+ async function resizeImageBase64IfNeeded(params) {
115
+ const buf = Buffer.from(params.base64, "base64");
116
+ const meta = await getImageMetadata(buf);
117
+ const width = meta?.width;
118
+ const height = meta?.height;
119
+ const overBytes = buf.byteLength > params.maxBytes;
120
+ const hasDimensions = typeof width === "number" && typeof height === "number";
121
+ const overDimensions = hasDimensions && (width > params.maxDimensionPx || height > params.maxDimensionPx);
122
+ if (hasDimensions && !overBytes && width <= params.maxDimensionPx && height <= params.maxDimensionPx) return {
123
+ base64: params.base64,
124
+ mimeType: params.mimeType,
125
+ resized: false,
126
+ width,
127
+ height
128
+ };
129
+ const maxDim = hasDimensions ? Math.max(width ?? 0, height ?? 0) : params.maxDimensionPx;
130
+ const sideStart = maxDim > 0 ? Math.min(params.maxDimensionPx, maxDim) : params.maxDimensionPx;
131
+ const sideGrid = buildImageResizeSideGrid(params.maxDimensionPx, sideStart);
132
+ let smallest = null;
133
+ for (const side of sideGrid) for (const quality of IMAGE_REDUCE_QUALITY_STEPS) {
134
+ const out = await resizeToJpeg({
135
+ buffer: buf,
136
+ maxSide: side,
137
+ quality,
138
+ withoutEnlargement: true
139
+ });
140
+ if (!smallest || out.byteLength < smallest.size) smallest = {
141
+ buffer: out,
142
+ size: out.byteLength
143
+ };
144
+ if (out.byteLength <= params.maxBytes) {
145
+ const sourcePixels = typeof width === "number" && typeof height === "number" ? `${width}x${height}px` : "unknown";
146
+ const sourceWithFile = params.fileName ? `${params.fileName} ${sourcePixels}` : sourcePixels;
147
+ const byteReductionPct = buf.byteLength > 0 ? Number(((buf.byteLength - out.byteLength) / buf.byteLength * 100).toFixed(1)) : 0;
148
+ log.info(`Image resized to fit limits: ${sourceWithFile} ${formatBytesShort(buf.byteLength)} -> ${formatBytesShort(out.byteLength)} (-${byteReductionPct}%)`, {
149
+ label: params.label,
150
+ fileName: params.fileName,
151
+ sourceMimeType: params.mimeType,
152
+ sourceWidth: width,
153
+ sourceHeight: height,
154
+ sourceBytes: buf.byteLength,
155
+ maxBytes: params.maxBytes,
156
+ maxDimensionPx: params.maxDimensionPx,
157
+ triggerOverBytes: overBytes,
158
+ triggerOverDimensions: overDimensions,
159
+ outputMimeType: "image/jpeg",
160
+ outputBytes: out.byteLength,
161
+ outputQuality: quality,
162
+ outputMaxSide: side,
163
+ byteReductionPct
164
+ });
165
+ return {
166
+ base64: out.toString("base64"),
167
+ mimeType: "image/jpeg",
168
+ resized: true,
169
+ width,
170
+ height
171
+ };
172
+ }
173
+ }
174
+ const best = smallest?.buffer ?? buf;
175
+ const maxMb = (params.maxBytes / (1024 * 1024)).toFixed(0);
176
+ const gotMb = (best.byteLength / (1024 * 1024)).toFixed(2);
177
+ const sourcePixels = typeof width === "number" && typeof height === "number" ? `${width}x${height}px` : "unknown";
178
+ const sourceWithFile = params.fileName ? `${params.fileName} ${sourcePixels}` : sourcePixels;
179
+ log.warn(`Image resize failed to fit limits: ${sourceWithFile} best=${formatBytesShort(best.byteLength)} limit=${formatBytesShort(params.maxBytes)}`, {
180
+ label: params.label,
181
+ fileName: params.fileName,
182
+ sourceMimeType: params.mimeType,
183
+ sourceWidth: width,
184
+ sourceHeight: height,
185
+ sourceBytes: buf.byteLength,
186
+ maxDimensionPx: params.maxDimensionPx,
187
+ maxBytes: params.maxBytes,
188
+ smallestCandidateBytes: best.byteLength,
189
+ triggerOverBytes: overBytes,
190
+ triggerOverDimensions: overDimensions
191
+ });
192
+ throw new Error(`Image could not be reduced below ${maxMb}MB (got ${gotMb}MB)`);
193
+ }
194
+ async function sanitizeContentBlocksImages(blocks, label, opts = {}) {
195
+ const maxDimensionPx = Math.max(opts.maxDimensionPx ?? MAX_IMAGE_DIMENSION_PX, 1);
196
+ const maxBytes = Math.max(opts.maxBytes ?? MAX_IMAGE_BYTES, 1);
197
+ const out = [];
198
+ let mediaPathHint;
199
+ for (const block of blocks) {
200
+ if (isTextBlock(block)) {
201
+ const mediaPath = parseMediaPathFromText(block.text);
202
+ if (mediaPath) mediaPathHint = mediaPath;
203
+ }
204
+ if (!isImageBlock(block)) {
205
+ out.push(block);
206
+ continue;
207
+ }
208
+ const data = block.data.trim();
209
+ if (!data) {
210
+ out.push({
211
+ type: "text",
212
+ text: `[${label}] omitted empty image payload`
213
+ });
214
+ continue;
215
+ }
216
+ const canonicalData = canonicalizeBase64(data);
217
+ if (!canonicalData) {
218
+ out.push({
219
+ type: "text",
220
+ text: `[${label}] omitted image payload: invalid base64`
221
+ });
222
+ continue;
223
+ }
224
+ try {
225
+ const mimeType = inferMimeTypeFromBase64(canonicalData) ?? block.mimeType;
226
+ const resized = await resizeImageBase64IfNeeded({
227
+ base64: canonicalData,
228
+ mimeType,
229
+ maxDimensionPx,
230
+ maxBytes,
231
+ label,
232
+ fileName: inferImageFileName({
233
+ block,
234
+ label,
235
+ mediaPathHint
236
+ })
237
+ });
238
+ out.push({
239
+ ...block,
240
+ data: resized.base64,
241
+ mimeType: resized.resized ? resized.mimeType : mimeType
242
+ });
243
+ } catch (err) {
244
+ out.push({
245
+ type: "text",
246
+ text: `[${label}] omitted image payload: ${String(err)}`
247
+ });
248
+ }
249
+ }
250
+ return out;
251
+ }
252
+ async function sanitizeImageBlocks(images, label, opts = {}) {
253
+ if (images.length === 0) return {
254
+ images,
255
+ dropped: 0
256
+ };
257
+ const next = (await sanitizeContentBlocksImages(images, label, opts)).filter(isImageBlock);
258
+ return {
259
+ images: next,
260
+ dropped: Math.max(0, images.length - next.length)
261
+ };
262
+ }
263
+ async function sanitizeToolResultImages(result, label, opts = {}) {
264
+ const content = Array.isArray(result.content) ? result.content : [];
265
+ if (!content.some((b) => isImageBlock(b) || isTextBlock(b))) return result;
266
+ const next = await sanitizeContentBlocksImages(content, label, opts);
267
+ return {
268
+ ...result,
269
+ content: next
270
+ };
271
+ }
272
+
273
+ //#endregion
274
+ export { canonicalizeBase64 as a, resolveImageSanitizationLimits as i, sanitizeImageBlocks as n, estimateBase64DecodedBytes as o, sanitizeToolResultImages as r, sanitizeContentBlocksImages as t };
@@ -0,0 +1,56 @@
1
+ import "./run-with-concurrency-Bt_ks0Qa.js";
2
+ import { _ as webAuthExists, c as logWebSelfId, d as pickWebChannel, o as WA_WEB_AUTH_DIR } from "./accounts-DP1-L-QS.js";
3
+ import "./reply-DAo_Jt8K.js";
4
+ import "./paths-MKyEVmEb.js";
5
+ import "./github-copilot-token-D5fdS6xD.js";
6
+ import "./config-BkEnz2Po.js";
7
+ import "./logger-CZY9KIoY.js";
8
+ import "./thinking-Bo2eosVa.js";
9
+ import "./image-ops-BSiMpAw4.js";
10
+ import "./pi-embedded-helpers-1R1gu7eX.js";
11
+ import "./plugins-DeBZB9l_.js";
12
+ import "./accounts-CJWOBzwB.js";
13
+ import "./accounts-DZhWlEg3.js";
14
+ import "./send-DTB24bEF.js";
15
+ import "./paths-vTM3Lh3X.js";
16
+ import "./fetch-Bv4TQOMH.js";
17
+ import "./redact-DjVX-1N3.js";
18
+ import "./errors-DaiAM-yU.js";
19
+ import "./channel-activity-F3d0yUwy.js";
20
+ import "./path-alias-guards-DBjLbIX_.js";
21
+ import "./fs-safe-B8y811FR.js";
22
+ import "./ssrf-cFtplYtS.js";
23
+ import "./fetch-guard-DETCcJzQ.js";
24
+ import "./local-roots-BUP4YBmR.js";
25
+ import "./ir-DQ7_HbvK.js";
26
+ import "./render-HmipMDlP.js";
27
+ import "./tables-C47P4GTN.js";
28
+ import "./send-DfHadjZ_.js";
29
+ import "./send-CQpMudwO.js";
30
+ import "./tool-images-Gk_-0y2N.js";
31
+ import "./target-errors-Blia4S69.js";
32
+ import "./send-DQHLzVyO.js";
33
+ import "./audio-transcription-runner-DkoPNPYt.js";
34
+ import "./tokens-DgNRBwIg.js";
35
+ import "./skill-commands-CkGeFUMl.js";
36
+ import "./skills-CBkHBYPq.js";
37
+ import "./chrome-BXoCyCkY.js";
38
+ import "./deliver-B6AG_l67.js";
39
+ import "./diagnostic-CsP-lEkI.js";
40
+ import "./store-5nyxY3WU.js";
41
+ import "./commands-registry-t7cXBTfN.js";
42
+ import { n as monitorWebInbox, t as monitorWebChannel } from "./channel-web-QF7EpjeP.js";
43
+ import "./image-DjTEkYZE.js";
44
+ import "./api-key-rotation-BRE4X2tf.js";
45
+ import "./proxy-fetch-ChxOhWF4.js";
46
+ import "./pi-model-discovery-v-XPUOOf.js";
47
+ import "./send-XXlW2iny.js";
48
+ import "./outbound-attachment-Dy6fyf6H.js";
49
+ import "./proxy-BKdNrmWL.js";
50
+ import "./manager-I6KbPihW.js";
51
+ import "./query-expansion-CeyKUeDW.js";
52
+ import { t as sendMessageWhatsApp } from "./outbound-NS6UHnB6.js";
53
+ import { i as waitForWaConnection, t as createWaSocket } from "./session-6TF6MyaC.js";
54
+ import { t as loginWeb } from "./login-BxEKLlCo.js";
55
+
56
+ export { WA_WEB_AUTH_DIR, createWaSocket, logWebSelfId, loginWeb, monitorWebChannel, monitorWebInbox, pickWebChannel, sendMessageWhatsApp, waitForWaConnection, webAuthExists };
@@ -0,0 +1,80 @@
1
+ import "./run-with-concurrency-Bt_ks0Qa.js";
2
+ import { i as resolveWhatsAppAccount } from "./accounts-DP1-L-QS.js";
3
+ import "./paths-MKyEVmEb.js";
4
+ import "./github-copilot-token-D5fdS6xD.js";
5
+ import "./config-BkEnz2Po.js";
6
+ import "./logger-CZY9KIoY.js";
7
+ import "./image-ops-BSiMpAw4.js";
8
+ import "./plugins-DeBZB9l_.js";
9
+ import "./path-alias-guards-DBjLbIX_.js";
10
+ import "./fs-safe-B8y811FR.js";
11
+ import "./ssrf-cFtplYtS.js";
12
+ import "./fetch-guard-DETCcJzQ.js";
13
+ import "./local-roots-BUP4YBmR.js";
14
+ import "./ir-DQ7_HbvK.js";
15
+ import "./render-HmipMDlP.js";
16
+ import "./tables-C47P4GTN.js";
17
+ import "./tool-images-Gk_-0y2N.js";
18
+ import { f as readReactionParams, h as readStringParam, i as ToolAuthorizationError, l as jsonResult, o as createActionGate } from "./target-errors-Blia4S69.js";
19
+ import { t as resolveWhatsAppOutboundTarget } from "./resolve-outbound-target-B42qgQS9.js";
20
+ import { r as sendReactionWhatsApp } from "./outbound-NS6UHnB6.js";
21
+
22
+ //#region src/agents/tools/whatsapp-target-auth.ts
23
+ function resolveAuthorizedWhatsAppOutboundTarget(params) {
24
+ const account = resolveWhatsAppAccount({
25
+ cfg: params.cfg,
26
+ accountId: params.accountId
27
+ });
28
+ const resolution = resolveWhatsAppOutboundTarget({
29
+ to: params.chatJid,
30
+ allowFrom: account.allowFrom ?? [],
31
+ mode: "implicit"
32
+ });
33
+ if (!resolution.ok) throw new ToolAuthorizationError(`WhatsApp ${params.actionLabel} blocked: chatJid "${params.chatJid}" is not in the configured allowFrom list for account "${account.accountId}".`);
34
+ return {
35
+ to: resolution.to,
36
+ accountId: account.accountId
37
+ };
38
+ }
39
+
40
+ //#endregion
41
+ //#region src/agents/tools/whatsapp-actions.ts
42
+ async function handleWhatsAppAction(params, cfg) {
43
+ const action = readStringParam(params, "action", { required: true });
44
+ const isActionEnabled = createActionGate(cfg.channels?.whatsapp?.actions);
45
+ if (action === "react") {
46
+ if (!isActionEnabled("reactions")) throw new Error("WhatsApp reactions are disabled.");
47
+ const chatJid = readStringParam(params, "chatJid", { required: true });
48
+ const messageId = readStringParam(params, "messageId", { required: true });
49
+ const { emoji, remove, isEmpty } = readReactionParams(params, { removeErrorMessage: "Emoji is required to remove a WhatsApp reaction." });
50
+ const participant = readStringParam(params, "participant");
51
+ const accountId = readStringParam(params, "accountId");
52
+ const fromMeRaw = params.fromMe;
53
+ const fromMe = typeof fromMeRaw === "boolean" ? fromMeRaw : void 0;
54
+ const resolved = resolveAuthorizedWhatsAppOutboundTarget({
55
+ cfg,
56
+ chatJid,
57
+ accountId,
58
+ actionLabel: "reaction"
59
+ });
60
+ const resolvedEmoji = remove ? "" : emoji;
61
+ await sendReactionWhatsApp(resolved.to, messageId, resolvedEmoji, {
62
+ verbose: false,
63
+ fromMe,
64
+ participant: participant ?? void 0,
65
+ accountId: resolved.accountId
66
+ });
67
+ if (!remove && !isEmpty) return jsonResult({
68
+ ok: true,
69
+ added: emoji
70
+ });
71
+ return jsonResult({
72
+ ok: true,
73
+ removed: true
74
+ });
75
+ }
76
+ throw new Error(`Unsupported WhatsApp action: ${action}`);
77
+ }
78
+
79
+ //#endregion
80
+ export { handleWhatsAppAction };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-multi-auto",
3
- "version": "1.4.3",
3
+ "version": "1.4.4",
4
4
  "description": "Multi-channel AI gateway with extensible messaging integrations",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/openclaw/openclaw#readme",
@@ -172,13 +172,36 @@ if [[ "$install_model_choice" == "y" || "$install_model_choice" == "Y" ]]; then
172
172
 
173
173
  echo -e "${YELLOW}正在拉取模型 qwen3vl:8b,这可能需要一些时间...${NC}"
174
174
 
175
- # 3. 执行拉取(修正拼写:qwen3vl)
176
- if ollama pull qwen3vl:8b; then
177
- echo -e "${GREEN}✅ 模型 qqwen3-vl:8b 拉取成功${NC}"
175
+ # ==================== 模型拉取配置 ====================
176
+ TARGET_MODEL="qwen3-vl:8b"
177
+ if command -v ollama &> /dev/null; then
178
+ echo -e "${YELLOW}🔍 正在检查本地模型库...${NC}"
179
+
180
+ # 使用 grep -w 进行全字匹配,确保精准识别 qwen3-vl:8b
181
+ if ollama list | grep -w "$TARGET_MODEL" > /dev/null; then
182
+ echo -e "${GREEN}✅ 检测到本地已存在 $TARGET_MODEL,跳过下载。${NC}"
183
+ else
184
+ echo -e "${YELLOW}📥 本地未发现 $TARGET_MODEL,准备拉取...${NC}"
185
+
186
+ # 确保 Ollama 服务处于运行状态
187
+ if ! pgrep -x "ollama" > /dev/null; then
188
+ echo -e "${YELLOW}🚀 正在后台启动 Ollama 服务...${NC}"
189
+ open -a Ollama.app --args serve > /dev/null 2>&1 &
190
+ sleep 5
191
+ fi
192
+
193
+ echo -e "${BLUE}开始拉取模型,这取决于你的网络环境...${NC}"
194
+ if ollama pull "$TARGET_MODEL"; then
195
+ echo -e "${GREEN}✅ 模型 $TARGET_MODEL 部署成功!${NC}"
196
+ else
197
+ echo -e "${RED}❌ 拉取失败。${NC}"
198
+ echo -e "${YELLOW}请检查网络或配置终端代理后再试。${NC}"
199
+ fi
200
+ fi
178
201
  else
179
- echo -e "${RED}❌ 模型拉取失败。${NC}"
180
- echo -e "${YELLOW}手动尝试:export https_proxy=http://127.0.0.1:你的代理端口 && ollama pull qwen3vl:8b${NC}"
202
+ echo -e "${RED}❌ 错误:系统中未找到 Ollama,请先完成安装。${NC}"
181
203
  fi
204
+ 22
182
205
  else
183
206
  echo -e "${RED}❌ 未检测到 ollama 命令,请确保已安装并添加到 PATH。${NC}"
184
207
  fi