@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.
Files changed (2) hide show
  1. package/dist/index.js +64 -25
  2. 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
- if (!originalBody) return attachment.kind === "image" ? "<media:image>" : originalBody;
5619
- return originalBody;
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.0",
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.0"
14
+ "@agent-wechat/shared": "0.3.1"
15
15
  },
16
16
  "openclaw": {
17
17
  "extensions": [