@chbo297/infoflow 2026.5.9-beta.1 → 2026.5.9-beta.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/README.md CHANGED
@@ -39,35 +39,49 @@ BAIDU_NPM_REGISTRY=http://registry.npm.baidu-int.com bash scripts/deploy.sh
39
39
 
40
40
  ### 首次安装(推荐命令)
41
41
 
42
- 首次在机器上安装时,推荐使用以下两种方式。
42
+ 下面的安装命令块由 `npm run sync-readme-install-version` 自动维护,版本号始终与 npm 上当前的 `latest` / `beta` dist-tag 保持一致,请直接复制使用。
43
43
 
44
- 方式 A:通过独立 tools 包安装并部署(推荐,支持 `update` 子命令)
44
+ #### 方式 A:通过独立 tools 包安装并部署(推荐,支持 `update` 子命令)
45
45
 
46
- <!-- sync:infoflow-plugin-version -->
46
+ 正式版(`latest` dist-tag):
47
+
48
+ <!-- sync:infoflow-plugin-version:latest -->
47
49
  ```bash
48
- # 正式版(latest)
49
- npx -y @chbo297/infoflow-openclaw-tools update --version 2026.5.9-beta.1 --registry https://registry.npmjs.org
50
+ npm cache clean --force
51
+ npx -y --prefer-online @chbo297/infoflow-openclaw-tools update \
52
+ --version 2026.5.8 --registry https://registry.npmjs.org
50
53
  ```
51
- <!-- /sync:infoflow-plugin-version -->
54
+ <!-- /sync:infoflow-plugin-version:latest -->
55
+
56
+ Beta 版(`beta` dist-tag,按需):
52
57
 
58
+ <!-- sync:infoflow-plugin-version:beta -->
53
59
  ```bash
54
- # Beta 版(示例,版本号请按实际预发包替换)
55
- npx -y @chbo297/infoflow-openclaw-tools@beta update --version 2026.5.8-beta.1 --registry https://registry.npmjs.org
60
+ npm cache clean --force
61
+ npx -y --prefer-online @chbo297/infoflow-openclaw-tools@beta update \
62
+ --version 2026.5.9-beta.1 --registry https://registry.npmjs.org
56
63
  ```
64
+ <!-- /sync:infoflow-plugin-version:beta -->
57
65
 
58
- 方式 B:通过 OpenClaw 插件命令安装
66
+ > 加上 `npm cache clean --force` 和 `--prefer-online`,可避免本机 npm metadata 缓存尚未刷新而看不到刚发布版本(典型表现为 `ETARGET: No matching version found`)。
59
67
 
60
- <!-- sync:infoflow-plugin-version -->
68
+ #### 方式 B:通过 OpenClaw 插件命令安装
69
+
70
+ 正式版:
71
+
72
+ <!-- sync:infoflow-plugin-version:latest -->
61
73
  ```bash
62
- # 正式版
63
- openclaw plugins install @chbo297/infoflow@2026.5.9-beta.1
74
+ openclaw plugins install @chbo297/infoflow@2026.5.8
64
75
  ```
65
- <!-- /sync:infoflow-plugin-version -->
76
+ <!-- /sync:infoflow-plugin-version:latest -->
77
+
78
+ Beta 版:
66
79
 
80
+ <!-- sync:infoflow-plugin-version:beta -->
67
81
  ```bash
68
- # Beta 版(示例,版本号请按实际预发包替换)
69
- openclaw plugins install @chbo297/infoflow@2026.5.8-beta.1
82
+ openclaw plugins install @chbo297/infoflow@2026.5.9-beta.1
70
83
  ```
84
+ <!-- /sync:infoflow-plugin-version:beta -->
71
85
 
72
86
  安装后建议检查插件状态:
73
87
 
@@ -76,17 +90,32 @@ openclaw plugins list
76
90
  openclaw plugins inspect infoflow
77
91
  ```
78
92
 
79
- ### 通过 npx 一键更新安装
93
+ #### 如遇 `ETARGET: No matching version found`
80
94
 
81
- 发布到 npm 后,可直接通过独立 tools 包执行安装/升级:
95
+ 刚发布的版本可能在本机 npm metadata 缓存里看不到,按下面顺序排查:
82
96
 
83
- <!-- sync:infoflow-plugin-version -->
84
97
  ```bash
85
- npx -y @chbo297/infoflow-openclaw-tools update --version 2026.5.9-beta.1 --registry https://registry.npmjs.org
98
+ # 1) 强制清缓存 + 在线拉取最新元数据
99
+ npm cache clean --force
100
+ npx -y --prefer-online @chbo297/infoflow-openclaw-tools@beta update \
101
+ --version <要装的版本> --registry https://registry.npmjs.org
102
+
103
+ # 2) 直接查 registry,确认版本确实可见
104
+ npm view @chbo297/infoflow versions --registry https://registry.npmjs.org
105
+
106
+ # 3) 确认默认 registry 未被改到镜像源(有些内网会重写到 cnpm/baidu 镜像,那里同步可能滞后)
107
+ npm config get registry # 期望: https://registry.npmjs.org/
108
+ # 临时强制覆盖(不改全局配置):
109
+ npm_config_registry=https://registry.npmjs.org \
110
+ npx -y --prefer-online @chbo297/infoflow-openclaw-tools@beta update \
111
+ --version <要装的版本> --registry https://registry.npmjs.org
112
+
113
+ # 4) 直接 curl 验证那台机器能否拿到 manifest
114
+ curl -sI https://registry.npmjs.org/@chbo297/infoflow | head -5
115
+ curl -s https://registry.npmjs.org/@chbo297/infoflow/<要装的版本> | head -50
86
116
  ```
87
- <!-- /sync:infoflow-plugin-version -->
88
117
 
89
- 常用参数:
118
+ ### tools 包的常用参数
90
119
 
91
120
  - `--version <version>`: 指定安装版本(默认 `latest`)
92
121
  - `--registry <url>`: 插件包下载源(默认 `https://registry.npmjs.org`)
@@ -107,34 +136,102 @@ npx -y @chbo297/infoflow-openclaw-tools update --version 2026.5.9-beta.1 --regis
107
136
 
108
137
  ### 版本升级、打 tag、推送与 npm 发布流程
109
138
 
110
- 每次发布新版本时,先将 `package.json` `version` 设为待发版本号,再按下述顺序执行。上文「首次安装 / npx 更新」与下文发版流程中,各 bash 代码块外侧有一对用于自动替换的 HTML 注释标记;发版前请执行 **`npm run sync-readme-install-version`**,脚本会按当前 `package.json` `version` 更新这些块内的版本号,以免 README 与 npm 不一致。
139
+ 正式版与 Beta 预发各自有完整流程,区别只在 **`npm version` 用的版本号** **`npm publish` 是否带 `--tag beta`** 两处。请按需选择对应小节,从头到尾执行。
140
+
141
+ 执行 `npm run sync-readme-install-version` 时脚本会:
142
+
143
+ - 把"发版流程"代码块内 `--version` / `npm version` / `git tag` / `git commit -m "<version>"` 等示例同步到当前 `package.json.version`("current" stream);
144
+ - 同时把上文"首次安装"段落里 `:latest` / `:beta` 两个 marker 区按 npm 上的 dist-tag 刷新——发 stable 时 `:latest` 区会写成新版本号;发 prerelease 时 `:beta` 区会写成新版本号;另一条 stream 通过 npm registry 接口拉取真实 dist-tag。
145
+
146
+ #### A. 正式版(stable)发布流程
147
+
148
+ 发布一个不带预发后缀的版本(例如 `2026.5.10`),会同时占用 npm 的 `latest` dist-tag,是 `npx` 默认拉取的版本。
149
+
150
+ 将下方所有 `<X.Y.Z>` 替换为目标正式版本号(不带 `-beta.N`):
111
151
 
112
- <!-- sync:infoflow-plugin-version -->
113
152
  ```bash
114
153
  # 1) 修改版本号(会同步 package-lock.json)
115
- npm version 2026.5.9-beta.1 --no-git-tag-version
154
+ npm version <X.Y.Z> --no-git-tag-version
116
155
 
117
- # 2) 同步 README 中标记块内的推荐安装命令与下文中的 tag / commit 示例版本号
156
+ # 2) 同步 README:current 区写入 <X.Y.Z>;:latest 区也写入 <X.Y.Z>(因为本次发的就是新 latest);
157
+ # :beta 区从 npm 拉取当前 beta dist-tag 保持不变
118
158
  npm run sync-readme-install-version
119
159
 
120
- # 3) 发布前校验
160
+ # 3) 编辑 CHANGELOG.md 顶部,添加本版本章节
161
+
162
+ # 4) 发布前校验
121
163
  npm run typecheck
122
164
  npm run test
123
165
  npm run build
124
166
 
125
- # 4) 提交版本变更(含 README、CHANGELOG 等)
167
+ # 5) 提交版本变更
126
168
  git add package.json package-lock.json README.md CHANGELOG.md scripts src
127
- git commit -m "2026.5.9-beta.1"
169
+ git commit -m "<X.Y.Z>"
128
170
 
129
- # 5) 打 tag 并推送代码与 tag
130
- git tag 2026.5.9-beta.1
171
+ # 6) 打 tag 并推送代码与 tag
172
+ git tag <X.Y.Z>
131
173
  git push origin main
132
- git push origin 2026.5.9-beta.1
174
+ git push origin <X.Y.Z>
175
+
176
+ # 7) 发布到 npm(占用 latest dist-tag)
177
+ npm publish --registry https://registry.npmjs.org
178
+
179
+ # 8) 发布成功后再跑一次 sync,把 :latest 区刷新成 npm registry 真实状态(通常已经一致,
180
+ # 但若另一条 stream 在期间也有新发布,这一步会顺带更新),并补一个 docs 提交
181
+ npm run sync-readme-install-version
182
+ git add README.md && git diff --cached --quiet || git commit -m "docs: refresh README install commands"
183
+ git push origin main
184
+ ```
185
+
186
+ #### B. Beta 预发布流程
133
187
 
134
- # 6) 发布 npm(可按需指定 registry)
135
- npm publish
136
- #
137
- # npm publish --registry https://registry.npmjs.org
188
+ 发布一个带预发后缀的版本(例如 `2026.5.10-beta.1`),通过 `--tag beta` 占用 `beta` dist-tag,**不会**改写 `latest`,默认 `npx` 装到的仍是正式版。
189
+
190
+ 将下方所有 `<X.Y.Z-beta.N>` 替换为目标预发版本号:
191
+
192
+ ```bash
193
+ # 1) 修改版本号(会同步 package-lock.json)
194
+ npm version <X.Y.Z-beta.N> --no-git-tag-version
195
+
196
+ # 2) 同步 README:current 区写入 <X.Y.Z-beta.N>;:beta 区也写入 <X.Y.Z-beta.N>(因为本次发的就是新 beta);
197
+ # :latest 区从 npm 拉取当前 latest dist-tag 保持不变
198
+ npm run sync-readme-install-version
199
+
200
+ # 3) 编辑 CHANGELOG.md 顶部,添加本版本章节
201
+
202
+ # 4) 发布前校验
203
+ npm run typecheck
204
+ npm run test
205
+ npm run build
206
+
207
+ # 5) 提交版本变更
208
+ git add package.json package-lock.json README.md CHANGELOG.md scripts src
209
+ git commit -m "<X.Y.Z-beta.N>"
210
+
211
+ # 6) 打 tag 并推送代码与 tag
212
+ git tag <X.Y.Z-beta.N>
213
+ git push origin main
214
+ git push origin <X.Y.Z-beta.N>
215
+
216
+ # 7) 发布到 npm(占用 beta dist-tag;不影响 latest)
217
+ npm publish --tag beta --registry https://registry.npmjs.org
218
+
219
+ # 8) 发布成功后再跑一次 sync 并补一个 docs 提交(同 A.8)
220
+ npm run sync-readme-install-version
221
+ git add README.md && git diff --cached --quiet || git commit -m "docs: refresh README install commands"
222
+ git push origin main
223
+ ```
224
+
225
+ #### 当前 `package.json` 的版本号示例
226
+
227
+ 以下示例由 `sync` 脚本自动维护,反映**仓库当前 `package.json.version`**(可作为复制 A / B 流程时的版本号参考):
228
+
229
+ <!-- sync:infoflow-plugin-version -->
230
+ ```bash
231
+ npm version 2026.5.9-beta.1 --no-git-tag-version
232
+ git commit -m "2026.5.9-beta.1"
233
+ git tag 2026.5.9-beta.1
234
+ git push origin 2026.5.9-beta.1
138
235
  ```
139
236
  <!-- /sync:infoflow-plugin-version -->
140
237
 
@@ -6,6 +6,7 @@
6
6
  import { jsonResult, readStringParam } from "openclaw/plugin-sdk/core";
7
7
  import { extractToolSend } from "openclaw/plugin-sdk/tool-send";
8
8
  import { resolveInfoflowAccount } from "./accounts.js";
9
+ import { looksLikeRecallLatest } from "./recall-intent.js";
9
10
  import { lookupInboundContext } from "./inbound-context.js";
10
11
  import { logVerbose } from "./logging.js";
11
12
  import { prepareInfoflowImageBase64, sendInfoflowImageMessage } from "./media.js";
@@ -34,7 +35,44 @@ function resolveInboundReplyToMessageId(params) {
34
35
  return undefined;
35
36
  if (ctx.target !== params.target)
36
37
  return undefined;
37
- return ctx.replyToMessageId;
38
+ }
39
+ /**
40
+ * Aggressive guard: when LLM passes messageId === inbound currentMessageId (a known
41
+ * confusion pattern), auto-correct based on context instead of failing.
42
+ *
43
+ * Priorities:
44
+ * 1) Use replyToMessageId — user quote-replied to a bot message (highest confidence).
45
+ * 2) Drop to count=1 mode — when no replyTo AND text indicates "recall latest one".
46
+ * 3) Defer to existing fallback chain — ambiguous intent (e.g., "recall the one about X").
47
+ *
48
+ * Returns the corrected messageId (or undefined to signal count=1 mode).
49
+ */
50
+ function applyAggressiveGuardForInboundMessageId(params) {
51
+ const inboundMsgId = params.currentMessageId != null ? String(params.currentMessageId) : undefined;
52
+ // Guard only triggers when LLM passes the inbound message id as delete target
53
+ if (!inboundMsgId || params.messageId !== inboundMsgId) {
54
+ return params.messageId;
55
+ }
56
+ const ctxRec = lookupInboundContext(inboundMsgId);
57
+ const scopeOk = ctxRec && ctxRec.accountId === params.accountId && ctxRec.target === params.target;
58
+ if (!scopeOk) {
59
+ // No inbound context to guide correction — defer to existing fallback chain
60
+ return params.messageId;
61
+ }
62
+ // Priority 1: replyToMessageId (user quote-replied to a bot message)
63
+ const replyToId = ctxRec.replyToMessageId;
64
+ if (replyToId && findSentMessage(params.accountId, replyToId)) {
65
+ logVerbose(`[infoflow:delete] aggressive: messageId==inboundMsgId(${params.messageId}); using replyTo=${replyToId}`);
66
+ return replyToId;
67
+ }
68
+ // Priority 2: text indicates "recall latest one" — safe to auto-correct to count=1
69
+ if (looksLikeRecallLatest(ctxRec.inboundBody ?? "")) {
70
+ logVerbose(`[infoflow:delete] aggressive: messageId==inboundMsgId(${params.messageId}); recall-latest intent → drop to count=1`);
71
+ return undefined; // undefined → count=1 mode
72
+ }
73
+ // Priority 3: ambiguous intent — defer to existing fallback chain
74
+ logVerbose(`[infoflow:delete] aggressive: messageId==inboundMsgId(${params.messageId}); ambiguous intent → defer to candidate-error path`);
75
+ return params.messageId;
38
76
  }
39
77
  /** Format up to N recent sent messages for an error-path hint to the LLM. */
40
78
  function formatRecentCandidatesForError(records, limit = 5) {
@@ -76,7 +114,7 @@ export const infoflowMessageActions = {
76
114
  if (!account.config.appKey || !account.config.appSecret) {
77
115
  throw new Error("Infoflow appKey/appSecret not configured.");
78
116
  }
79
- const messageId = readStringParam(params, "messageId");
117
+ let messageId = readStringParam(params, "messageId");
80
118
  // Default to count=1 (recall latest message) when neither messageId nor count is provided
81
119
  const countStr = readStringParam(params, "count") ?? (messageId ? undefined : "1");
82
120
  const groupMatch = target.match(/^group:(\d+)/i);
@@ -85,6 +123,16 @@ export const infoflowMessageActions = {
85
123
  // 群消息撤回
86
124
  // -----------------------------------------------------------------
87
125
  const groupId = Number(groupMatch[1]);
126
+ const targetForStore = `group:${groupId}`;
127
+ // Apply aggressive guard when messageId equals inbound currentMessageId (LLM confusion pattern)
128
+ if (messageId) {
129
+ messageId = applyAggressiveGuardForInboundMessageId({
130
+ messageId,
131
+ currentMessageId: toolContext?.currentMessageId,
132
+ accountId: account.accountId,
133
+ target: targetForStore,
134
+ });
135
+ }
88
136
  // Mode A: single message recall by messageId
89
137
  if (messageId) {
90
138
  // Resolve msgseqid (group recall requires it). If the LLM-passed messageId
@@ -97,7 +145,7 @@ export const infoflowMessageActions = {
97
145
  if (!stored && !msgseqid) {
98
146
  const fallbackId = resolveInboundReplyToMessageId({
99
147
  accountId: account.accountId,
100
- target: `group:${groupId}`,
148
+ target: targetForStore,
101
149
  currentMessageId: toolContext?.currentMessageId,
102
150
  });
103
151
  if (fallbackId && fallbackId !== effectiveMessageId) {
@@ -151,7 +199,7 @@ export const infoflowMessageActions = {
151
199
  throw new Error("count must be a positive integer.");
152
200
  }
153
201
  const records = querySentMessages(account.accountId, {
154
- target: `group:${groupId}`,
202
+ target: targetForStore,
155
203
  count,
156
204
  });
157
205
  // Filter to records that have msgseqid (required for group recall)
@@ -221,6 +269,15 @@ export const infoflowMessageActions = {
221
269
  throw new Error("Infoflow private message recall requires appAgentId configuration. " +
222
270
  "Set channels.infoflow.appAgentId to your application ID (如流企业后台的应用ID).");
223
271
  }
272
+ // Apply aggressive guard when messageId equals inbound currentMessageId (LLM confusion pattern)
273
+ if (messageId) {
274
+ messageId = applyAggressiveGuardForInboundMessageId({
275
+ messageId,
276
+ currentMessageId: toolContext?.currentMessageId,
277
+ accountId: account.accountId,
278
+ target,
279
+ });
280
+ }
224
281
  // Mode A: single message recall by messageId (msgkey)
225
282
  if (messageId) {
226
283
  // Attempt the inbound-context fallback when the LLM-passed messageId is
package/dist/src/bot.js CHANGED
@@ -4,6 +4,7 @@ import { resolveInfoflowAccount } from "./accounts.js";
4
4
  import { registerInboundContext } from "./inbound-context.js";
5
5
  import { getInfoflowBotLog, formatInfoflowError, logVerbose } from "./logging.js";
6
6
  import { createInfoflowReplyDispatcher } from "./reply-dispatcher.js";
7
+ import { looksLikeRecallIntent, looksLikeRecallLatest } from "./recall-intent.js";
7
8
  import { getInfoflowRuntime } from "./runtime.js";
8
9
  import { findSentMessage, querySentMessages } from "./sent-message-store.js";
9
10
  /**
@@ -226,13 +227,7 @@ function resolveReplyTargets(bodyItems, accountId) {
226
227
  // in the target group" bug. sent-messages.db tracks all bot-sent messages
227
228
  // keyed by target, so a single push surfaces messages sent from any session.
228
229
  // ---------------------------------------------------------------------------
229
- /** Detect inbound text that semantically asks the bot to recall/delete messages. */
230
- const RECALL_INTENT_REGEX = /(撤回|收回|删[掉了除]|取消|清除|recall|unsend|undo\s*send|delete\s+(?:that|those|the\s+(?:last|previous(?:\s+\d+)?)))/i;
231
- function looksLikeRecallIntent(text) {
232
- if (!text)
233
- return false;
234
- return RECALL_INTENT_REGEX.test(text);
235
- }
230
+ // Recall-intent detection lives in ./recall-intent.js shared with actions.ts.
236
231
  const RECENT_BOT_AMBIENT_WINDOW_MS = 24 * 60 * 60 * 1000;
237
232
  const RECENT_BOT_AMBIENT_COUNT = 5;
238
233
  const RECENT_BOT_DETAIL_COUNT = 10;
@@ -886,10 +881,11 @@ export async function handleInfoflowMessage(params) {
886
881
  }
887
882
  }
888
883
  // Register inbound context so the delete action handler can fall back to the
889
- // bot-message id the inbound is quote-replying to (when present) only used
890
- // when the LLM otherwise passes an unknown id. We intentionally only pick a
891
- // bot-sent reply target: falling back to a non-bot reply id would never help
892
- // (it can't be in sent-messages.db) and only adds noise.
884
+ // bot-message id the inbound is quote-replying to (when present), or detect
885
+ // the "messageId===inboundMessageId" LLM confusion pattern with the body
886
+ // text to decide whether it's safe to auto-correct to count=1. We only pick
887
+ // a bot-sent reply target: falling back to a non-bot reply id would never
888
+ // help (it can't be in sent-messages.db) and only adds noise.
893
889
  if (event.messageId) {
894
890
  registerInboundContext({
895
891
  accountId,
@@ -897,6 +893,7 @@ export async function handleInfoflowMessage(params) {
897
893
  inboundMessageId: event.messageId,
898
894
  replyToMessageId: event.replyTargets?.find((t) => t.isBotMessage)?.messageid,
899
895
  replyTargets: event.replyTargets,
896
+ inboundBody: bodyForAgent || mes || event.replyContext?.join(" "),
900
897
  registeredAt: Date.now(),
901
898
  });
902
899
  }
@@ -1163,6 +1160,8 @@ export function _checkReplyToBot(bodyItems, accountId) {
1163
1160
  export const _buildGroupOutputHygienePrompt = buildGroupOutputHygienePrompt;
1164
1161
  /** @internal — Recall intent regex. Only exported for tests. */
1165
1162
  export const _looksLikeRecallIntent = looksLikeRecallIntent;
1163
+ /** @internal — Stricter recall-latest detector. Only exported for tests. */
1164
+ export const _looksLikeRecallLatest = looksLikeRecallLatest;
1166
1165
  /** @internal — Sent-messages section builder. Only exported for tests. */
1167
1166
  export const _buildBotRecentMessagesSection = buildBotRecentMessagesSection;
1168
1167
  /** @internal — Quoted-reply targets section builder. Only exported for tests. */
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Lightweight recall-intent detection used by both the prompt-injection path
3
+ * (bot.ts) and the delete action's aggressive guard (actions.ts).
4
+ *
5
+ * Two helpers:
6
+ * - looksLikeRecallIntent: matches any "撤回/删除/recall/unsend/..." verb.
7
+ * - looksLikeRecallLatest: requires both a recall verb AND an explicit
8
+ * "the latest one" qualifier (上一条 / 最后一条 / 刚才那条 / 最近一条 /
9
+ * last / previous / most recent / ...). Used to decide whether it's safe
10
+ * to auto-correct `messageId=inbound_user_msg_id` to count=1 (recall most
11
+ * recent). Standalone "撤回那条" without a temporal qualifier is rejected:
12
+ * it could refer to a specific quoted message and we'd rather surface
13
+ * candidates to the LLM than risk recalling the wrong one.
14
+ */
15
+ const RECALL_INTENT_REGEX = /(撤回|收回|删[掉了除]|取消|清除|recall|unsend|undo\s*send|delete\s+(?:that|those|the\s+(?:last|previous(?:\s+\d+)?)))/i;
16
+ const RECALL_LATEST_HINT_REGEX = /(上一?条|最后一?条|刚才那?条|最近一?条|last(?:\s+(?:one|message|two|few|reply))?|previous|most\s*recent)/iu;
17
+ export function looksLikeRecallIntent(text) {
18
+ if (!text)
19
+ return false;
20
+ return RECALL_INTENT_REGEX.test(text);
21
+ }
22
+ export function looksLikeRecallLatest(text) {
23
+ if (!text)
24
+ return false;
25
+ return RECALL_INTENT_REGEX.test(text) && RECALL_LATEST_HINT_REGEX.test(text);
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chbo297/infoflow",
3
- "version": "2026.5.9-beta.1",
3
+ "version": "2026.5.9-beta.2",
4
4
  "description": "OpenClaw Infoflow (如流) channel plugin for Baidu enterprise messaging",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",