@wecom/wecom-openclaw-plugin 2026.3.24 → 2026.3.25-beta.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/README.md +10 -1
- package/dist/index.cjs.js +32 -61
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +32 -61
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,16 @@
|
|
|
4
4
|
>
|
|
5
5
|
> 💬 扫码加入企业微信交流群:
|
|
6
6
|
>
|
|
7
|
-
> <img src="https://wwcdn.weixin.qq.com/node/wework/images/
|
|
7
|
+
> <img src="https://wwcdn.weixin.qq.com/node/wework/images/202603241759.3fb01c32cc.png" alt="扫码入群交流" width="200" />
|
|
8
|
+
|
|
9
|
+
# 特别说明
|
|
10
|
+
> ****2026.3.22 版本 OpenClaw 兼容说明****
|
|
11
|
+
>
|
|
12
|
+
> 如果你的 OpenClaw 是 2026.3.22 及以上的版本,请升级插件到 2026.3.24 及以上版本。
|
|
13
|
+
>
|
|
14
|
+
> 如果你的 OpenClaw 是 2026.3.22 以下的版本,请保持插件版本在 2026.3.20 版本。
|
|
15
|
+
>
|
|
16
|
+
> 你可以使用以下命令快速安装: `npx -y @wecom/wecom-openclaw-cli install --force`
|
|
8
17
|
|
|
9
18
|
# 🤖 WeCom OpenClaw Plugin
|
|
10
19
|
|
package/dist/index.cjs.js
CHANGED
|
@@ -1525,14 +1525,6 @@ const PLUGIN_VERSION = getVersion();
|
|
|
1525
1525
|
* - state-manager.ts : 全局状态管理(带 TTL 清理)
|
|
1526
1526
|
* - timeout.ts : 超时工具
|
|
1527
1527
|
*/
|
|
1528
|
-
/**
|
|
1529
|
-
* 去除文本中的 `<think>...</think>` 标签(支持跨行),返回剩余可见文本。
|
|
1530
|
-
* 用于判断大模型回复中是否包含实际用户可见内容(而非仅有 thinking 推理过程)。
|
|
1531
|
-
*/
|
|
1532
|
-
function stripThinkTags(text) {
|
|
1533
|
-
return text;
|
|
1534
|
-
// return text.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
|
|
1535
|
-
}
|
|
1536
1528
|
// ============================================================================
|
|
1537
1529
|
// 媒体本地路径白名单扩展
|
|
1538
1530
|
// ============================================================================
|
|
@@ -1678,15 +1670,6 @@ async function sendThinkingReply(params) {
|
|
|
1678
1670
|
runtime.error?.(`[wecom] Failed to send thinking message: ${String(err)}`);
|
|
1679
1671
|
}
|
|
1680
1672
|
}
|
|
1681
|
-
/**
|
|
1682
|
-
* 累积文本并判断是否有可见内容(去除 <think> 标签后)
|
|
1683
|
-
*/
|
|
1684
|
-
function accumulateText(state, text) {
|
|
1685
|
-
state.accumulatedText += text;
|
|
1686
|
-
if (!state.hasText && stripThinkTags(state.accumulatedText)) {
|
|
1687
|
-
state.hasText = true;
|
|
1688
|
-
}
|
|
1689
|
-
}
|
|
1690
1673
|
/**
|
|
1691
1674
|
* 上传并发送一批媒体文件(统一走主动发送通道)
|
|
1692
1675
|
*
|
|
@@ -1742,30 +1725,22 @@ async function sendMediaBatch(ctx, mediaUrls) {
|
|
|
1742
1725
|
*/
|
|
1743
1726
|
async function finishThinkingStream(ctx) {
|
|
1744
1727
|
const { wsClient, frame, state, runtime } = ctx;
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
}
|
|
1755
|
-
else if (state.hasMediaFailed && state.mediaErrorSummary) {
|
|
1756
|
-
// 媒体发送失败:直接用错误摘要替换 thinking 流(不再额外发 sendMessage)
|
|
1757
|
-
finishText = state.mediaErrorSummary;
|
|
1728
|
+
let finishText = state.accumulatedText;
|
|
1729
|
+
if (state.hasMedia) {
|
|
1730
|
+
if (state.hasMediaFailed && state.mediaErrorSummary) {
|
|
1731
|
+
// 媒体成功发送:用友好提示告知用户
|
|
1732
|
+
finishText = finishText ? `${finishText}\n\n${state.mediaErrorSummary}` : state.mediaErrorSummary;
|
|
1733
|
+
}
|
|
1734
|
+
else if (!finishText) {
|
|
1735
|
+
finishText = "📎 文件已发送,请查收。";
|
|
1736
|
+
}
|
|
1758
1737
|
}
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
// 回调,所以 state.deliverCalled / state.hasMedia 均为 false,但文件
|
|
1765
|
-
// 实际已送达用户。此时显示 "未生成回复" 会误导用户。
|
|
1766
|
-
finishText = "✅ 处理完成。";
|
|
1738
|
+
// if (!finishText) {
|
|
1739
|
+
// finishText = "✅ 处理完成。";
|
|
1740
|
+
// }
|
|
1741
|
+
if (finishText) {
|
|
1742
|
+
await sendWeComReply({ wsClient, frame, text: finishText, runtime, finish: true, streamId: state.streamId });
|
|
1767
1743
|
}
|
|
1768
|
-
await sendWeComReply({ wsClient, frame, text: finishText, runtime, finish: true, streamId: state.streamId });
|
|
1769
1744
|
}
|
|
1770
1745
|
/**
|
|
1771
1746
|
* 路由消息到核心处理流程并处理回复
|
|
@@ -1782,17 +1757,29 @@ async function routeAndDispatchMessage(params) {
|
|
|
1782
1757
|
onCleanup();
|
|
1783
1758
|
}
|
|
1784
1759
|
};
|
|
1760
|
+
let isShowThink = !(account.sendThinkingMessage ?? true);
|
|
1785
1761
|
try {
|
|
1786
1762
|
await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
1787
1763
|
ctx: ctxPayload,
|
|
1788
1764
|
cfg: config,
|
|
1789
1765
|
dispatcherOptions: {
|
|
1766
|
+
onReplyStart: async () => {
|
|
1767
|
+
if (!isShowThink && state.streamId && !state.accumulatedText) {
|
|
1768
|
+
try {
|
|
1769
|
+
await sendThinkingReply({ wsClient, frame, streamId: state.streamId, runtime });
|
|
1770
|
+
}
|
|
1771
|
+
catch (e) {
|
|
1772
|
+
runtime.error?.(`[wecom] sendThinkingReply threw err: ${String(e)}`);
|
|
1773
|
+
}
|
|
1774
|
+
isShowThink = true;
|
|
1775
|
+
}
|
|
1776
|
+
},
|
|
1790
1777
|
deliver: async (payload, info) => {
|
|
1791
1778
|
state.deliverCalled = true;
|
|
1792
1779
|
// runtime.log?.(`[openclaw -> plugin] kind=${info.kind}, text=${payload.text ?? ''}, mediaUrl=${payload.mediaUrl ?? ''}, mediaUrls=${JSON.stringify(payload.mediaUrls ?? [])}`);
|
|
1793
1780
|
// 累积文本
|
|
1794
1781
|
if (payload.text) {
|
|
1795
|
-
|
|
1782
|
+
state.accumulatedText += (payload.text || '');
|
|
1796
1783
|
}
|
|
1797
1784
|
// 发送媒体(统一走主动发送)
|
|
1798
1785
|
const mediaUrls = payload.mediaUrls?.length ? payload.mediaUrls : payload.mediaUrl ? [payload.mediaUrl] : [];
|
|
@@ -1930,11 +1917,11 @@ async function processWeComMessage(params) {
|
|
|
1930
1917
|
const cleanupState = () => {
|
|
1931
1918
|
deleteMessageState(messageId);
|
|
1932
1919
|
};
|
|
1933
|
-
// Step 6: 发送"思考中"消息
|
|
1934
|
-
const shouldSendThinking = account.sendThinkingMessage ?? true;
|
|
1935
|
-
if (shouldSendThinking) {
|
|
1936
|
-
|
|
1937
|
-
}
|
|
1920
|
+
// // Step 6: 发送"思考中"消息
|
|
1921
|
+
// const shouldSendThinking = account.sendThinkingMessage ?? true;
|
|
1922
|
+
// if (shouldSendThinking) {
|
|
1923
|
+
// await sendThinkingReply({ wsClient, frame, streamId, runtime });
|
|
1924
|
+
// }
|
|
1938
1925
|
// Step 7: 构建上下文并路由到核心处理流程(带整体超时保护)
|
|
1939
1926
|
const ctxPayload = buildMessageContext(frame, account, config, text, mediaList, quoteContent);
|
|
1940
1927
|
// runtime.log?.(`[plugin -> openclaw] body=${text}, mediaPaths=${JSON.stringify(mediaList.map(m => m.path))}${quoteContent ? `, quote=${quoteContent}` : ''}`);
|
|
@@ -1952,22 +1939,6 @@ async function processWeComMessage(params) {
|
|
|
1952
1939
|
}
|
|
1953
1940
|
catch (err) {
|
|
1954
1941
|
runtime.error?.(`[wecom][plugin] Message processing failed or timed out: ${String(err)}`);
|
|
1955
|
-
// 确保 thinking 流被关闭,防止异常/超时时 thinking 消息一直残留
|
|
1956
|
-
try {
|
|
1957
|
-
if (shouldSendThinking) {
|
|
1958
|
-
await sendWeComReply({
|
|
1959
|
-
wsClient,
|
|
1960
|
-
frame,
|
|
1961
|
-
text: "处理消息时出现异常,请稍后重试。",
|
|
1962
|
-
runtime,
|
|
1963
|
-
finish: true,
|
|
1964
|
-
streamId: state.streamId,
|
|
1965
|
-
});
|
|
1966
|
-
}
|
|
1967
|
-
}
|
|
1968
|
-
catch (finishErr) {
|
|
1969
|
-
runtime.error?.(`[wecom] Failed to finish thinking stream on error: ${String(finishErr)}`);
|
|
1970
|
-
}
|
|
1971
1942
|
cleanupState();
|
|
1972
1943
|
}
|
|
1973
1944
|
}
|