gewe-openclaw 2026.2.1 → 2026.2.3

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/README.md CHANGED
@@ -72,6 +72,7 @@ openclaw plugins install ./gewe-openclaw.tgz
72
72
  - `mediaPath`:本地媒体服务的路由前缀(默认 `/gewe-media`)。
73
73
  - `mediaPublicUrl`:公网访问地址的“基础前缀”,会自动拼接媒体 ID。通常应与 `mediaPath` 对齐,例如 `mediaPath="/gewe-media"` 时,`mediaPublicUrl` 也应包含 `/gewe-media`。
74
74
  - `allowFrom`:允许私聊触发的微信 ID(或在群里走 allowlist 规则)。
75
+ - `voiceAutoConvert`:自动将音频转为 silk(默认开启;设为 `false` 可关闭)。
75
76
  - `silkAutoDownload`:自动下载 `rust-silk`(默认开启;可关闭后自行配置 `voiceSilkPath` / `voiceDecodePath`)。
76
77
  - `silkVersion`:自动下载的 `rust-silk` 版本(`latest` 会自动清理旧版本)。
77
78
  - `silkBaseUrl`:自定义下载源(默认 GitHub Releases)。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gewe-openclaw",
3
- "version": "2026.2.1",
3
+ "version": "2026.2.3",
4
4
  "type": "module",
5
5
  "description": "OpenClaw GeWe channel plugin",
6
6
  "license": "MIT",
package/src/delivery.ts CHANGED
@@ -252,7 +252,7 @@ async function convertAudioToSilk(params: {
252
252
  }): Promise<{ buffer: Buffer; durationMs: number } | null> {
253
253
  const core = getGeweRuntime();
254
254
  const logger = core.logging.getChildLogger({ channel: CHANNEL_ID, module: "voice" });
255
- if (!params.account.config.voiceAutoConvert) return null;
255
+ if (params.account.config.voiceAutoConvert === false) return null;
256
256
 
257
257
  const sampleRate = resolveVoiceSampleRate(params.account);
258
258
  const ffmpegPath = params.account.config.voiceFfmpegPath?.trim() || DEFAULT_VOICE_FFMPEG;
@@ -497,6 +497,21 @@ async function resolveLinkThumbUrl(params: {
497
497
  }
498
498
  }
499
499
 
500
+ function normalizeMediaToken(raw: string): string {
501
+ let value = raw.trim();
502
+ if (value.toUpperCase().startsWith("MEDIA:")) {
503
+ value = value.slice("MEDIA:".length).trim();
504
+ }
505
+ if (
506
+ (value.startsWith("`") && value.endsWith("`")) ||
507
+ (value.startsWith("\"") && value.endsWith("\"")) ||
508
+ (value.startsWith("'") && value.endsWith("'"))
509
+ ) {
510
+ value = value.slice(1, -1).trim();
511
+ }
512
+ return value;
513
+ }
514
+
500
515
  async function stageMedia(params: {
501
516
  account: ResolvedGeweAccount;
502
517
  cfg: OpenClawConfig;
@@ -504,7 +519,7 @@ async function stageMedia(params: {
504
519
  allowRemote: boolean;
505
520
  }): Promise<ResolvedMedia> {
506
521
  const core = getGeweRuntime();
507
- const rawUrl = params.mediaUrl.trim();
522
+ const rawUrl = normalizeMediaToken(params.mediaUrl);
508
523
  if (!rawUrl) throw new Error("mediaUrl is empty");
509
524
 
510
525
  if (looksLikeHttpUrl(rawUrl) && params.allowRemote) {
@@ -598,6 +613,7 @@ export async function deliverGewePayload(params: {
598
613
  const trimmedText = payload.text?.trim() ?? "";
599
614
  const mediaUrl =
600
615
  payload.mediaUrl?.trim() || payload.mediaUrls?.[0]?.trim() || "";
616
+ const normalizedMediaUrl = normalizeMediaToken(mediaUrl);
601
617
 
602
618
  if (geweData?.link) {
603
619
  const link = geweData.link;
@@ -625,12 +641,12 @@ export async function deliverGewePayload(params: {
625
641
  if (mediaUrl) {
626
642
  const audioAsVoice = payload.audioAsVoice === true;
627
643
  const forceFile = geweData?.forceFile === true;
628
- const ttsVoiceHint = !forceFile && looksLikeTtsVoiceMediaUrl(mediaUrl);
644
+ const ttsVoiceHint = !forceFile && looksLikeTtsVoiceMediaUrl(normalizedMediaUrl);
629
645
  const wantsVoice = !forceFile && (audioAsVoice || ttsVoiceHint);
630
646
  const staged = await stageMedia({
631
647
  account,
632
648
  cfg,
633
- mediaUrl,
649
+ mediaUrl: normalizedMediaUrl,
634
650
  allowRemote: !wantsVoice,
635
651
  });
636
652
  const contentType = staged.contentType;
package/src/silk.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- import { createReadStream, existsSync } from "node:fs";
2
+ import { createReadStream, createWriteStream, existsSync } from "node:fs";
3
3
  import fs from "node:fs/promises";
4
4
  import os from "node:os";
5
5
  import path from "node:path";