@agent-wechat/agent-wechat 0.14.0 → 0.15.0
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 +160 -88
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1127,6 +1127,9 @@ function getWeChatRuntime() {
|
|
|
1127
1127
|
return runtime;
|
|
1128
1128
|
}
|
|
1129
1129
|
|
|
1130
|
+
// src/monitor.ts
|
|
1131
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
1132
|
+
|
|
1130
1133
|
// ../shared/dist/client.js
|
|
1131
1134
|
function normalizeUrl(base) {
|
|
1132
1135
|
const url = base.startsWith("http") ? base : `http://${base}`;
|
|
@@ -1230,6 +1233,23 @@ var WeChatClient = class {
|
|
|
1230
1233
|
async sendMessage(params) {
|
|
1231
1234
|
return this.post("/api/messages/send", params);
|
|
1232
1235
|
}
|
|
1236
|
+
async createVoiceJob(chatId, audio, idempotencyKey) {
|
|
1237
|
+
const form = new FormData();
|
|
1238
|
+
form.set("chatId", chatId);
|
|
1239
|
+
form.set("audio", new Blob([new Uint8Array(audio)]), "voice-audio");
|
|
1240
|
+
const headers = { ...this.headers, "Idempotency-Key": idempotencyKey };
|
|
1241
|
+
delete headers["Content-Type"];
|
|
1242
|
+
const res = await fetch(`${this.base}/api/messages/voice`, { method: "POST", headers, body: form });
|
|
1243
|
+
if (!res.ok)
|
|
1244
|
+
throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
|
|
1245
|
+
return res.json();
|
|
1246
|
+
}
|
|
1247
|
+
async getVoiceJob(jobId) {
|
|
1248
|
+
return this.get(`/api/messages/voice/${encodeURIComponent(jobId)}`);
|
|
1249
|
+
}
|
|
1250
|
+
async cancelVoiceJob(jobId) {
|
|
1251
|
+
return this.post(`/api/messages/voice/${encodeURIComponent(jobId)}/cancel`);
|
|
1252
|
+
}
|
|
1233
1253
|
// ---- Debug ----
|
|
1234
1254
|
async screenshot() {
|
|
1235
1255
|
return this.get("/api/debug/screenshot");
|
|
@@ -5779,6 +5799,96 @@ async function listMessageWindow(client, chatId, previousLastSeen, firstPoll, un
|
|
|
5779
5799
|
return messages;
|
|
5780
5800
|
}
|
|
5781
5801
|
|
|
5802
|
+
// src/outbound-media.ts
|
|
5803
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
5804
|
+
import { readFile } from "node:fs/promises";
|
|
5805
|
+
import { basename, extname } from "node:path";
|
|
5806
|
+
var EXT_MIME = {
|
|
5807
|
+
png: "image/png",
|
|
5808
|
+
jpg: "image/jpeg",
|
|
5809
|
+
jpeg: "image/jpeg",
|
|
5810
|
+
gif: "image/gif",
|
|
5811
|
+
webp: "image/webp",
|
|
5812
|
+
mp3: "audio/mpeg",
|
|
5813
|
+
wav: "audio/wav",
|
|
5814
|
+
ogg: "audio/ogg",
|
|
5815
|
+
opus: "audio/ogg",
|
|
5816
|
+
m4a: "audio/mp4",
|
|
5817
|
+
flac: "audio/flac",
|
|
5818
|
+
aac: "audio/aac"
|
|
5819
|
+
};
|
|
5820
|
+
function isTerminal(job) {
|
|
5821
|
+
return ["completed", "failed", "cancelled", "needs_review"].includes(job.status);
|
|
5822
|
+
}
|
|
5823
|
+
async function waitForVoiceJob(client, jobId) {
|
|
5824
|
+
const deadline = Date.now() + 25 * 6e4;
|
|
5825
|
+
let lastStatusAt = Date.now();
|
|
5826
|
+
while (Date.now() < deadline) {
|
|
5827
|
+
let job;
|
|
5828
|
+
try {
|
|
5829
|
+
job = await client.getVoiceJob(jobId);
|
|
5830
|
+
lastStatusAt = Date.now();
|
|
5831
|
+
} catch (error) {
|
|
5832
|
+
if (Date.now() - lastStatusAt > 3e4) {
|
|
5833
|
+
throw new Error(`Voice job ${jobId} status is unavailable: ${String(error)}. Inspect the job before retrying.`);
|
|
5834
|
+
}
|
|
5835
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
5836
|
+
continue;
|
|
5837
|
+
}
|
|
5838
|
+
if (isTerminal(job)) {
|
|
5839
|
+
if (job.status === "completed") return job;
|
|
5840
|
+
const sent = job.chunks.filter((chunk) => chunk.status === "verified").length;
|
|
5841
|
+
throw new Error(`Voice job ${jobId} ${job.status}: ${sent}/${job.chunks.length} notes verified. ${job.error ?? ""} Do not resend the whole recording.`);
|
|
5842
|
+
}
|
|
5843
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
5844
|
+
}
|
|
5845
|
+
throw new Error(`Voice job ${jobId} exceeded the 25-minute wait. Inspect the job before retrying.`);
|
|
5846
|
+
}
|
|
5847
|
+
async function sendWeChatMedia(cfg, to, text, mediaUrl, audioAsVoice = false, idempotencyKey) {
|
|
5848
|
+
const account = resolveWeChatAccount(cfg);
|
|
5849
|
+
if (!account?.serverUrl) throw new Error("No serverUrl configured");
|
|
5850
|
+
const client = new WeChatClient({ baseUrl: account.serverUrl, token: account.token });
|
|
5851
|
+
if (!mediaUrl) {
|
|
5852
|
+
if (audioAsVoice) throw new Error("Voice sending requires an audio attachment");
|
|
5853
|
+
const result2 = await client.sendMessage({ chatId: to, text: text || void 0 });
|
|
5854
|
+
if (!result2.success) throw new Error(result2.error ?? "Send failed");
|
|
5855
|
+
return `agent-wechat:${to}:${Date.now()}`;
|
|
5856
|
+
}
|
|
5857
|
+
let bytes;
|
|
5858
|
+
let mimeType;
|
|
5859
|
+
let filename;
|
|
5860
|
+
if (mediaUrl.startsWith("http://") || mediaUrl.startsWith("https://")) {
|
|
5861
|
+
const res = await fetch(mediaUrl);
|
|
5862
|
+
if (!res.ok) throw new Error(`Media fetch failed: ${res.status}`);
|
|
5863
|
+
bytes = new Uint8Array(await res.arrayBuffer());
|
|
5864
|
+
mimeType = res.headers.get("content-type")?.split(";")[0] ?? "application/octet-stream";
|
|
5865
|
+
filename = basename(new URL(mediaUrl).pathname) || "file";
|
|
5866
|
+
if (mimeType === "application/octet-stream") {
|
|
5867
|
+
mimeType = EXT_MIME[extname(filename).toLowerCase().slice(1)] ?? mimeType;
|
|
5868
|
+
}
|
|
5869
|
+
} else {
|
|
5870
|
+
const localPath = mediaUrl.startsWith("file://") ? new URL(mediaUrl) : mediaUrl;
|
|
5871
|
+
const pathText = localPath instanceof URL ? localPath.pathname : localPath;
|
|
5872
|
+
bytes = new Uint8Array(await readFile(localPath));
|
|
5873
|
+
filename = basename(pathText);
|
|
5874
|
+
mimeType = EXT_MIME[extname(filename).toLowerCase().slice(1)] ?? "application/octet-stream";
|
|
5875
|
+
}
|
|
5876
|
+
if (audioAsVoice) {
|
|
5877
|
+
if (!mimeType.startsWith("audio/")) throw new Error(`Voice media must be audio, got ${mimeType}`);
|
|
5878
|
+
const job = await client.createVoiceJob(to, bytes, idempotencyKey ?? randomUUID2());
|
|
5879
|
+
await waitForVoiceJob(client, job.jobId);
|
|
5880
|
+
if (text) {
|
|
5881
|
+
const caption = await client.sendMessage({ chatId: to, text });
|
|
5882
|
+
if (!caption.success) throw new Error(`Voice job ${job.jobId} completed, but caption failed: ${caption.error ?? "unknown error"}`);
|
|
5883
|
+
}
|
|
5884
|
+
return `agent-wechat:voice:${job.jobId}`;
|
|
5885
|
+
}
|
|
5886
|
+
const base64 = Buffer.from(bytes).toString("base64");
|
|
5887
|
+
const result = mimeType.startsWith("image/") ? await client.sendMessage({ chatId: to, text: text || void 0, image: { data: base64, mimeType } }) : await client.sendMessage({ chatId: to, text: text || void 0, file: { data: base64, filename } });
|
|
5888
|
+
if (!result.success) throw new Error(result.error ?? "Send media failed");
|
|
5889
|
+
return `agent-wechat:${to}:${Date.now()}`;
|
|
5890
|
+
}
|
|
5891
|
+
|
|
5782
5892
|
// src/access-control.ts
|
|
5783
5893
|
import {
|
|
5784
5894
|
buildChannelKeyCandidates,
|
|
@@ -5989,6 +6099,7 @@ function resolveWeChatMentionGate(params) {
|
|
|
5989
6099
|
// src/monitor.ts
|
|
5990
6100
|
var HISTORY_CONTEXT_MARKER = "[Chat messages since your last reply - for context]";
|
|
5991
6101
|
var CURRENT_MESSAGE_MARKER = "[Current message - respond to this]";
|
|
6102
|
+
var voiceTranscriptCache = /* @__PURE__ */ new Map();
|
|
5992
6103
|
function isProcessedMessage(value) {
|
|
5993
6104
|
if (!value || typeof value !== "object") return false;
|
|
5994
6105
|
const message = value;
|
|
@@ -6360,6 +6471,36 @@ async function dispatchSegment(segment, client, chatId, chat, liveAccount, polic
|
|
|
6360
6471
|
return "ignored";
|
|
6361
6472
|
}
|
|
6362
6473
|
try {
|
|
6474
|
+
for (const item of segment) {
|
|
6475
|
+
const attachment = item.attachment;
|
|
6476
|
+
if (item.mediaPath || attachment?.kind !== "audio" || attachment.status !== "ready" || !attachment.path) continue;
|
|
6477
|
+
const cacheKey = `${liveAccount.accountId}:${chatId}:${item.msg.localId}:${attachment.path}`;
|
|
6478
|
+
let transcript = voiceTranscriptCache.get(cacheKey);
|
|
6479
|
+
if (!transcript) {
|
|
6480
|
+
try {
|
|
6481
|
+
const result = await core.mediaUnderstanding.transcribeAudioFile({
|
|
6482
|
+
filePath: attachment.path,
|
|
6483
|
+
cfg,
|
|
6484
|
+
mime: attachment.mime
|
|
6485
|
+
});
|
|
6486
|
+
transcript = result.text?.trim();
|
|
6487
|
+
if (transcript) {
|
|
6488
|
+
if (voiceTranscriptCache.size >= 500) voiceTranscriptCache.clear();
|
|
6489
|
+
voiceTranscriptCache.set(cacheKey, transcript);
|
|
6490
|
+
}
|
|
6491
|
+
} catch (error) {
|
|
6492
|
+
log?.error?.(`[wechat:${liveAccount.accountId}] Voice transcription failed for ${item.msg.localId}: ${String(error)}`);
|
|
6493
|
+
}
|
|
6494
|
+
}
|
|
6495
|
+
if (transcript) {
|
|
6496
|
+
item.rawBody += `
|
|
6497
|
+
[Voice transcript: ${transcript.slice(0, 1e4)}]`;
|
|
6498
|
+
item.commandBody = normalizeWeChatCommandBody(item.rawBody, {
|
|
6499
|
+
isGroup: item.isGroup,
|
|
6500
|
+
wasMentioned: item.isMentioned
|
|
6501
|
+
});
|
|
6502
|
+
}
|
|
6503
|
+
}
|
|
6363
6504
|
const route = core.channel.routing.resolveAgentRoute({
|
|
6364
6505
|
cfg,
|
|
6365
6506
|
channel: "agent-wechat",
|
|
@@ -6388,7 +6529,7 @@ async function dispatchSegment(segment, client, chatId, chat, liveAccount, polic
|
|
|
6388
6529
|
timestamp,
|
|
6389
6530
|
previousTimestamp,
|
|
6390
6531
|
envelope: envelopeOptions,
|
|
6391
|
-
body: isGroup ? `${senderName}: ${rawBody}` : rawBody
|
|
6532
|
+
body: isGroup ? `${senderName}: ${lastMsg.rawBody}` : lastMsg.rawBody
|
|
6392
6533
|
});
|
|
6393
6534
|
} else {
|
|
6394
6535
|
const historyMessages = segment.slice(0, -1);
|
|
@@ -6408,7 +6549,7 @@ async function dispatchSegment(segment, client, chatId, chat, liveAccount, polic
|
|
|
6408
6549
|
timestamp,
|
|
6409
6550
|
previousTimestamp,
|
|
6410
6551
|
envelope: envelopeOptions,
|
|
6411
|
-
body: isGroup ? `${senderName}: ${rawBody}` : rawBody
|
|
6552
|
+
body: isGroup ? `${senderName}: ${lastMsg.rawBody}` : lastMsg.rawBody
|
|
6412
6553
|
});
|
|
6413
6554
|
body = [
|
|
6414
6555
|
HISTORY_CONTEXT_MARKER,
|
|
@@ -6430,8 +6571,8 @@ async function dispatchSegment(segment, client, chatId, chat, liveAccount, polic
|
|
|
6430
6571
|
}
|
|
6431
6572
|
const ctxPayload = core.channel.reply.finalizeInboundContext({
|
|
6432
6573
|
Body: body,
|
|
6433
|
-
BodyForAgent: rawBody,
|
|
6434
|
-
RawBody: rawBody,
|
|
6574
|
+
BodyForAgent: lastMsg.rawBody,
|
|
6575
|
+
RawBody: lastMsg.rawBody,
|
|
6435
6576
|
CommandBody: commandBody,
|
|
6436
6577
|
InboundHistory: inboundHistory,
|
|
6437
6578
|
From: isGroup ? `wechat:group:${chatId}` : `wechat:${senderId}`,
|
|
@@ -6473,12 +6614,14 @@ async function dispatchSegment(segment, client, chatId, chat, liveAccount, polic
|
|
|
6473
6614
|
accountId: liveAccount.accountId
|
|
6474
6615
|
});
|
|
6475
6616
|
let replyFailed = false;
|
|
6617
|
+
let deliverySequence = 0;
|
|
6476
6618
|
await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
6477
6619
|
ctx: ctxPayload,
|
|
6478
6620
|
cfg,
|
|
6479
6621
|
dispatcherOptions: {
|
|
6480
6622
|
...prefixOptions,
|
|
6481
6623
|
deliver: async (payload) => {
|
|
6624
|
+
const deliveryIndex = deliverySequence++;
|
|
6482
6625
|
const mediaList = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
|
|
6483
6626
|
const tableMode = core.channel.text.resolveMarkdownTableMode({
|
|
6484
6627
|
cfg,
|
|
@@ -6490,49 +6633,17 @@ async function dispatchSegment(segment, client, chatId, chat, liveAccount, polic
|
|
|
6490
6633
|
tableMode
|
|
6491
6634
|
);
|
|
6492
6635
|
if (mediaList.length > 0) {
|
|
6493
|
-
for (
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
const pathmod = await import("path");
|
|
6497
|
-
let base64;
|
|
6498
|
-
let mimeType;
|
|
6499
|
-
let filename;
|
|
6500
|
-
if (mediaUrl.startsWith("http://") || mediaUrl.startsWith("https://")) {
|
|
6501
|
-
const res = await fetch(mediaUrl);
|
|
6502
|
-
const buffer = await res.arrayBuffer();
|
|
6503
|
-
base64 = Buffer.from(buffer).toString("base64");
|
|
6504
|
-
mimeType = res.headers.get("content-type") ?? "application/octet-stream";
|
|
6505
|
-
const urlPath = new URL(mediaUrl).pathname;
|
|
6506
|
-
filename = pathmod.basename(urlPath) || "file";
|
|
6507
|
-
} else {
|
|
6508
|
-
const buf = await fsmod.readFile(mediaUrl);
|
|
6509
|
-
base64 = buf.toString("base64");
|
|
6510
|
-
filename = pathmod.basename(mediaUrl);
|
|
6511
|
-
const ext = pathmod.extname(mediaUrl).toLowerCase().replace(".", "");
|
|
6512
|
-
const extMime = {
|
|
6513
|
-
png: "image/png",
|
|
6514
|
-
jpg: "image/jpeg",
|
|
6515
|
-
jpeg: "image/jpeg",
|
|
6516
|
-
gif: "image/gif",
|
|
6517
|
-
webp: "image/webp"
|
|
6518
|
-
};
|
|
6519
|
-
mimeType = extMime[ext] ?? "application/octet-stream";
|
|
6520
|
-
}
|
|
6521
|
-
const isImage = mimeType.startsWith("image/");
|
|
6522
|
-
if (isImage) {
|
|
6523
|
-
await client.sendMessage({ chatId, image: { data: base64, mimeType } });
|
|
6524
|
-
} else {
|
|
6525
|
-
await client.sendMessage({ chatId, file: { data: base64, filename } });
|
|
6526
|
-
}
|
|
6527
|
-
} catch (err) {
|
|
6528
|
-
log?.error?.(`[wechat:${liveAccount.accountId}] Failed to send media: ${err}`);
|
|
6529
|
-
}
|
|
6636
|
+
for (let index = 0; index < mediaList.length; index++) {
|
|
6637
|
+
const retryKey = createHash3("sha256").update(`${liveAccount.accountId}\0${chatId}\0${msg.localId}\0${deliveryIndex}\0${index}`).digest("hex");
|
|
6638
|
+
await sendWeChatMedia(cfg, chatId, "", mediaList[index], payload.audioAsVoice === true, retryKey);
|
|
6530
6639
|
}
|
|
6531
6640
|
if (text) {
|
|
6532
|
-
await client.sendMessage({ chatId, text });
|
|
6641
|
+
const result = await client.sendMessage({ chatId, text });
|
|
6642
|
+
if (!result.success) throw new Error(result.error ?? "Text send failed");
|
|
6533
6643
|
}
|
|
6534
6644
|
} else if (text) {
|
|
6535
|
-
await client.sendMessage({ chatId, text });
|
|
6645
|
+
const result = await client.sendMessage({ chatId, text });
|
|
6646
|
+
if (!result.success) throw new Error(result.error ?? "Text send failed");
|
|
6536
6647
|
}
|
|
6537
6648
|
},
|
|
6538
6649
|
onError: (err, info) => {
|
|
@@ -7109,46 +7220,6 @@ async function sendWeChatText(cfg, to, text) {
|
|
|
7109
7220
|
if (!result.success) throw new Error(result.error ?? "Send failed");
|
|
7110
7221
|
return `agent-wechat:${to}:${Date.now()}`;
|
|
7111
7222
|
}
|
|
7112
|
-
async function sendWeChatMedia(cfg, to, text, mediaUrl) {
|
|
7113
|
-
const account = resolveWeChatAccount(cfg);
|
|
7114
|
-
if (!account?.serverUrl) throw new Error("No serverUrl configured");
|
|
7115
|
-
const client = new WeChatClient({ baseUrl: account.serverUrl, token: account.token });
|
|
7116
|
-
if (!mediaUrl) {
|
|
7117
|
-
const result2 = await client.sendMessage({ chatId: to, text: text || void 0 });
|
|
7118
|
-
if (!result2.success) throw new Error(result2.error ?? "Send failed");
|
|
7119
|
-
return `agent-wechat:${to}:${Date.now()}`;
|
|
7120
|
-
}
|
|
7121
|
-
const fsmod = await import("fs/promises");
|
|
7122
|
-
const pathmod = await import("path");
|
|
7123
|
-
let base64;
|
|
7124
|
-
let mimeType;
|
|
7125
|
-
let filename;
|
|
7126
|
-
if (mediaUrl.startsWith("http://") || mediaUrl.startsWith("https://")) {
|
|
7127
|
-
const res = await fetch(mediaUrl);
|
|
7128
|
-
const buffer = await res.arrayBuffer();
|
|
7129
|
-
base64 = Buffer.from(buffer).toString("base64");
|
|
7130
|
-
mimeType = res.headers.get("content-type") ?? "application/octet-stream";
|
|
7131
|
-
const urlPath = new URL(mediaUrl).pathname;
|
|
7132
|
-
filename = pathmod.basename(urlPath) || "file";
|
|
7133
|
-
} else {
|
|
7134
|
-
const buf = await fsmod.readFile(mediaUrl);
|
|
7135
|
-
base64 = buf.toString("base64");
|
|
7136
|
-
filename = pathmod.basename(mediaUrl);
|
|
7137
|
-
const ext = pathmod.extname(mediaUrl).toLowerCase().replace(".", "");
|
|
7138
|
-
const extMime = {
|
|
7139
|
-
png: "image/png",
|
|
7140
|
-
jpg: "image/jpeg",
|
|
7141
|
-
jpeg: "image/jpeg",
|
|
7142
|
-
gif: "image/gif",
|
|
7143
|
-
webp: "image/webp"
|
|
7144
|
-
};
|
|
7145
|
-
mimeType = extMime[ext] ?? "application/octet-stream";
|
|
7146
|
-
}
|
|
7147
|
-
const isImage = mimeType.startsWith("image/");
|
|
7148
|
-
const result = isImage ? await client.sendMessage({ chatId: to, text: text || void 0, image: { data: base64, mimeType } }) : await client.sendMessage({ chatId: to, text: text || void 0, file: { data: base64, filename } });
|
|
7149
|
-
if (!result.success) throw new Error(result.error ?? "Send media failed");
|
|
7150
|
-
return `agent-wechat:${to}:${Date.now()}`;
|
|
7151
|
-
}
|
|
7152
7223
|
var wechatMessageAdapter = createChannelMessageAdapterFromOutbound({
|
|
7153
7224
|
id: "agent-wechat",
|
|
7154
7225
|
capabilities: {
|
|
@@ -7161,9 +7232,9 @@ var wechatMessageAdapter = createChannelMessageAdapterFromOutbound({
|
|
|
7161
7232
|
channel: "agent-wechat",
|
|
7162
7233
|
messageId: await sendWeChatText(cfg, to, text)
|
|
7163
7234
|
}),
|
|
7164
|
-
sendMedia: async ({ cfg, to, text, mediaUrl }) => ({
|
|
7235
|
+
sendMedia: async ({ cfg, to, text, mediaUrl, audioAsVoice }) => ({
|
|
7165
7236
|
channel: "agent-wechat",
|
|
7166
|
-
messageId: await sendWeChatMedia(cfg, to, text, mediaUrl)
|
|
7237
|
+
messageId: await sendWeChatMedia(cfg, to, text, mediaUrl, audioAsVoice)
|
|
7167
7238
|
})
|
|
7168
7239
|
}
|
|
7169
7240
|
});
|
|
@@ -7184,7 +7255,8 @@ var wechatPlugin = {
|
|
|
7184
7255
|
reactions: false,
|
|
7185
7256
|
threads: false,
|
|
7186
7257
|
media: true,
|
|
7187
|
-
reply: true
|
|
7258
|
+
reply: true,
|
|
7259
|
+
tts: { voice: { synthesisTarget: "voice-note", transcodesAudio: true } }
|
|
7188
7260
|
},
|
|
7189
7261
|
reload: { configPrefixes: ["channels.agent-wechat"] },
|
|
7190
7262
|
configSchema: {
|
|
@@ -7311,9 +7383,9 @@ var wechatPlugin = {
|
|
|
7311
7383
|
channel: "agent-wechat",
|
|
7312
7384
|
messageId: await sendWeChatText(cfg, to, text)
|
|
7313
7385
|
}),
|
|
7314
|
-
sendMedia: async ({ cfg, to, text, mediaUrl }) => ({
|
|
7386
|
+
sendMedia: async ({ cfg, to, text, mediaUrl, audioAsVoice }) => ({
|
|
7315
7387
|
channel: "agent-wechat",
|
|
7316
|
-
messageId: await sendWeChatMedia(cfg, to, text, mediaUrl)
|
|
7388
|
+
messageId: await sendWeChatMedia(cfg, to, text, mediaUrl, audioAsVoice)
|
|
7317
7389
|
})
|
|
7318
7390
|
},
|
|
7319
7391
|
message: wechatMessageAdapter,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-wechat/agent-wechat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
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.
|
|
14
|
+
"@agent-wechat/shared": "0.3.0"
|
|
15
15
|
},
|
|
16
16
|
"openclaw": {
|
|
17
17
|
"extensions": [
|