@agent-wechat/agent-wechat 0.15.0 → 0.15.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/index.js +64 -25
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -5521,11 +5521,15 @@ var getMediaParamsSchema = external_exports.object({
|
|
|
5521
5521
|
quality: external_exports.enum(["full", "thumbnail"]).optional()
|
|
5522
5522
|
});
|
|
5523
5523
|
var mediaResultSchema = external_exports.object({
|
|
5524
|
-
type: external_exports.enum(["image", "emoji", "voice", "video", "file", "pending", "unsupported"]),
|
|
5524
|
+
type: external_exports.enum(["image", "emoji", "voice", "video", "file", "pending", "expired", "unsupported"]),
|
|
5525
5525
|
data: external_exports.string().optional(),
|
|
5526
5526
|
url: external_exports.string().optional(),
|
|
5527
5527
|
format: external_exports.string(),
|
|
5528
|
-
filename: external_exports.string()
|
|
5528
|
+
filename: external_exports.string(),
|
|
5529
|
+
quality: external_exports.enum(["full", "standard", "thumbnail"]).optional(),
|
|
5530
|
+
reason: external_exports.string().optional(),
|
|
5531
|
+
expiresAt: external_exports.number().int().positive().optional(),
|
|
5532
|
+
retryable: external_exports.boolean().optional()
|
|
5529
5533
|
});
|
|
5530
5534
|
var agentConfigSchema = external_exports.object({
|
|
5531
5535
|
maxTurns: external_exports.number().int().positive().default(30),
|
|
@@ -5563,6 +5567,9 @@ function attachmentKindForMessageType(baseType) {
|
|
|
5563
5567
|
if (baseType === 49) return "file";
|
|
5564
5568
|
return void 0;
|
|
5565
5569
|
}
|
|
5570
|
+
function mediaRequestQuality(baseType) {
|
|
5571
|
+
return baseType === 3 ? "best" : "full";
|
|
5572
|
+
}
|
|
5566
5573
|
function attachmentKindForResult(result, fallback) {
|
|
5567
5574
|
if (result.type === "image" || result.type === "emoji") return "image";
|
|
5568
5575
|
if (result.type === "voice") return "audio";
|
|
@@ -5600,6 +5607,9 @@ function renderAttachmentBody(originalBody, attachment, exposeNonVisualPath = tr
|
|
|
5600
5607
|
if (attachment.status === "pending") {
|
|
5601
5608
|
return appendReference(originalBody, `[${label} pending: ${name}]`);
|
|
5602
5609
|
}
|
|
5610
|
+
if (attachment.status === "expired") {
|
|
5611
|
+
return appendReference(originalBody, `[${label} expired: ${name}; no cached copy available. Ask the sender to resend.]`);
|
|
5612
|
+
}
|
|
5603
5613
|
return appendReference(originalBody, `[${label} unavailable: ${name} (${attachment.status})]`);
|
|
5604
5614
|
}
|
|
5605
5615
|
if (attachment.kind === "file") {
|
|
@@ -5615,8 +5625,11 @@ function renderAttachmentBody(originalBody, attachment, exposeNonVisualPath = tr
|
|
|
5615
5625
|
return appendReference(originalBody || "<media:video>", `[Video file: ${attachment.path}]`);
|
|
5616
5626
|
}
|
|
5617
5627
|
}
|
|
5618
|
-
|
|
5619
|
-
|
|
5628
|
+
const body = originalBody || (attachment.kind === "image" ? "<media:image>" : originalBody);
|
|
5629
|
+
if (attachment.kind === "image" && attachment.quality === "thumbnail") {
|
|
5630
|
+
return appendReference(body, "[Image preview only: thumbnail quality]");
|
|
5631
|
+
}
|
|
5632
|
+
return body;
|
|
5620
5633
|
}
|
|
5621
5634
|
function applyLiveAttachment(message, originalBody, attachment) {
|
|
5622
5635
|
const attachable = attachment?.status === "ready" && attachment.path && attachment.kind !== "file";
|
|
@@ -5889,6 +5902,41 @@ async function sendWeChatMedia(cfg, to, text, mediaUrl, audioAsVoice = false, id
|
|
|
5889
5902
|
return `agent-wechat:${to}:${Date.now()}`;
|
|
5890
5903
|
}
|
|
5891
5904
|
|
|
5905
|
+
// src/media-poll.ts
|
|
5906
|
+
function rejectsBestQuality(error) {
|
|
5907
|
+
return error instanceof Error && /^(400|422)\b/.test(error.message) && /\bbest\b/i.test(error.message);
|
|
5908
|
+
}
|
|
5909
|
+
async function pollMedia(client, chatId, localId, quality, log, maxAttempts = 15, intervalMs = 1e3) {
|
|
5910
|
+
let lastResult = null;
|
|
5911
|
+
let legacyImageServer = false;
|
|
5912
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
5913
|
+
let result;
|
|
5914
|
+
if (legacyImageServer) {
|
|
5915
|
+
const full = await client.getMedia(chatId, localId, "full");
|
|
5916
|
+
if (full.data || full.type === "unsupported" || full.type === "expired") return full;
|
|
5917
|
+
const preview = await client.getMedia(chatId, localId, "thumbnail");
|
|
5918
|
+
result = preview.data ? { ...preview, quality: "thumbnail" } : full;
|
|
5919
|
+
} else {
|
|
5920
|
+
try {
|
|
5921
|
+
result = await client.getMedia(chatId, localId, quality);
|
|
5922
|
+
} catch (error) {
|
|
5923
|
+
if (quality !== "best" || !rejectsBestQuality(error)) throw error;
|
|
5924
|
+
legacyImageServer = true;
|
|
5925
|
+
log?.info?.("[media] Server does not support best image quality; trying full then thumbnail");
|
|
5926
|
+
attempt--;
|
|
5927
|
+
continue;
|
|
5928
|
+
}
|
|
5929
|
+
}
|
|
5930
|
+
lastResult = result;
|
|
5931
|
+
if (result.type === "unsupported" || result.type === "expired" || result.data) return result;
|
|
5932
|
+
if (attempt < maxAttempts) {
|
|
5933
|
+
log?.info?.(`[media] Attempt ${attempt}/${maxAttempts} for ${chatId}:${localId} returned no data, retrying...`);
|
|
5934
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
5935
|
+
}
|
|
5936
|
+
}
|
|
5937
|
+
return lastResult;
|
|
5938
|
+
}
|
|
5939
|
+
|
|
5892
5940
|
// src/access-control.ts
|
|
5893
5941
|
import {
|
|
5894
5942
|
buildChannelKeyCandidates,
|
|
@@ -6117,24 +6165,6 @@ function sleep(ms, signal) {
|
|
|
6117
6165
|
});
|
|
6118
6166
|
});
|
|
6119
6167
|
}
|
|
6120
|
-
async function pollMedia(client, chatId, localId, log, maxAttempts = 15, intervalMs = 1e3) {
|
|
6121
|
-
let lastResult = null;
|
|
6122
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6123
|
-
const result = await client.getMedia(chatId, localId, "full");
|
|
6124
|
-
lastResult = result;
|
|
6125
|
-
if (result.type === "unsupported") {
|
|
6126
|
-
return result;
|
|
6127
|
-
}
|
|
6128
|
-
if (result.data) {
|
|
6129
|
-
return result;
|
|
6130
|
-
}
|
|
6131
|
-
if (attempt < maxAttempts) {
|
|
6132
|
-
log?.info?.(`[media] Attempt ${attempt}/${maxAttempts} for ${chatId}:${localId} returned no data, retrying...`);
|
|
6133
|
-
await new Promise((r) => setTimeout(r, intervalMs));
|
|
6134
|
-
}
|
|
6135
|
-
}
|
|
6136
|
-
return lastResult;
|
|
6137
|
-
}
|
|
6138
6168
|
function enqueueWeChatSystemEvent(text, contextKey) {
|
|
6139
6169
|
try {
|
|
6140
6170
|
const core = getWeChatRuntime();
|
|
@@ -6151,10 +6181,18 @@ async function retrieveAttachment(client, chatId, msg, liveAccount, log, maxAtte
|
|
|
6151
6181
|
if (!expectedKind) return void 0;
|
|
6152
6182
|
const fallbackFilename = attachmentFallbackFilename(expectedKind, msg.localId, msg.content);
|
|
6153
6183
|
try {
|
|
6154
|
-
const result = await pollMedia(client, chatId, msg.localId, log, maxAttempts);
|
|
6184
|
+
const result = await pollMedia(client, chatId, msg.localId, mediaRequestQuality(baseType), log, maxAttempts);
|
|
6155
6185
|
if (!result) {
|
|
6156
6186
|
return { kind: expectedKind, status: "unavailable", filename: fallbackFilename };
|
|
6157
6187
|
}
|
|
6188
|
+
if (result.type === "expired") {
|
|
6189
|
+
return {
|
|
6190
|
+
kind: expectedKind,
|
|
6191
|
+
status: "expired",
|
|
6192
|
+
filename: result.filename || fallbackFilename,
|
|
6193
|
+
expiresAt: result.expiresAt
|
|
6194
|
+
};
|
|
6195
|
+
}
|
|
6158
6196
|
if (result.type === "unsupported") {
|
|
6159
6197
|
if (baseType === 49) return void 0;
|
|
6160
6198
|
return { kind: expectedKind, status: "unsupported", filename: fallbackFilename };
|
|
@@ -6173,9 +6211,9 @@ async function retrieveAttachment(client, chatId, msg, liveAccount, log, maxAtte
|
|
|
6173
6211
|
saveMediaBuffer: getWeChatRuntime().channel.media.saveMediaBuffer
|
|
6174
6212
|
});
|
|
6175
6213
|
log?.info?.(
|
|
6176
|
-
`[wechat:${liveAccount.accountId}] Saved ${kind} attachment for msg ${msg.localId} (${saved.size} bytes)`
|
|
6214
|
+
`[wechat:${liveAccount.accountId}] Saved ${kind} attachment for msg ${msg.localId} (${saved.size} bytes${result.quality ? `, ${result.quality} quality` : ""})`
|
|
6177
6215
|
);
|
|
6178
|
-
return { kind, status: "ready", filename: saved.filename, mime, path: saved.path };
|
|
6216
|
+
return { kind, status: "ready", filename: saved.filename, mime, path: saved.path, quality: result.quality };
|
|
6179
6217
|
} catch (error) {
|
|
6180
6218
|
const status = error instanceof AttachmentTooLargeError ? "too_large" : "error";
|
|
6181
6219
|
log?.error?.(
|
|
@@ -6392,6 +6430,7 @@ ${replyBlock}` : replyBlock;
|
|
|
6392
6430
|
}
|
|
6393
6431
|
async function refreshAttachment(message, client, chatId, liveAccount, log) {
|
|
6394
6432
|
if (!message.attachment) return message;
|
|
6433
|
+
if (message.attachment.status === "expired") return message;
|
|
6395
6434
|
if (message.attachment.status === "ready" && await attachmentPathExists(message.attachment.path)) {
|
|
6396
6435
|
return message;
|
|
6397
6436
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-wechat/agent-wechat",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"esbuild": "^0.25.0",
|
|
12
12
|
"openclaw": "^2026.8.1",
|
|
13
13
|
"typescript": "^5.4.5",
|
|
14
|
-
"@agent-wechat/shared": "0.3.
|
|
14
|
+
"@agent-wechat/shared": "0.3.1"
|
|
15
15
|
},
|
|
16
16
|
"openclaw": {
|
|
17
17
|
"extensions": [
|