@53ai/53ai-openclaw 1.0.7 → 1.0.9
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/CHANGELOG.md +16 -0
- package/README.md +3 -3
- package/dist/index.cjs.js +82 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +82 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/src/compaction-hooks.d.ts +25 -0
- package/dist/src/message-sender.d.ts +1 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
|
|
7
|
+
## [1.0.9] - 2026-03-26
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- 更新 `homepage` 字段为 `https://www.53ai.com`。
|
|
11
|
+
|
|
12
|
+
## [1.0.8] - 2026-03-26
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- 新增压缩前后钩子(`handleBeforeCompaction` / `handleAfterCompaction`),支持在会话消息压缩前后向用户发送状态通知。
|
|
16
|
+
- 新增 `compaction-hooks.ts` 模块,实现从 `sessionKey` 解析 `chatId` 的逻辑,并对非本渠道会话自动跳过处理。
|
|
17
|
+
- 消息发送逻辑新增思考状态(thinking)支持,压缩过程中可向用户推送"正在整理对话记忆"等提示。
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- `message-sender.ts`:优化消息发送调用,支持传递思考状态标志。
|
|
21
|
+
- `monitor.ts`:增强监控逻辑以适配压缩钩子的事件上报。
|
|
22
|
+
|
|
7
23
|
## [1.0.7] - 2026-03-19
|
|
8
24
|
|
|
9
25
|
### Changed
|
package/README.md
CHANGED
|
@@ -142,8 +142,8 @@ openclaw plugins list | grep 53aihub
|
|
|
142
142
|
# 检查通道配置
|
|
143
143
|
openclaw config get channels.53aihub
|
|
144
144
|
|
|
145
|
-
# 检查 Gateway 日志
|
|
146
|
-
openclaw
|
|
145
|
+
# 检查 Gateway 日志 (用户级服务)
|
|
146
|
+
journalctl --user -u openclaw-gateway.service -f | grep -i 53aihub
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
## 多模态消息支持
|
|
@@ -397,7 +397,7 @@ npm test
|
|
|
397
397
|
|
|
398
398
|
1. 确认 `openclaw.plugin.json` 存在于插件根目录
|
|
399
399
|
2. 确认 `dist/` 目录包含编译后的文件
|
|
400
|
-
3. 检查 Gateway 日志: `openclaw
|
|
400
|
+
3. 检查 Gateway 日志: `journalctl --user -u openclaw-gateway.service -f`
|
|
401
401
|
|
|
402
402
|
### 通道未生效
|
|
403
403
|
|
package/dist/index.cjs.js
CHANGED
|
@@ -334,7 +334,7 @@ function parseMessageContent(msg) {
|
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
async function sendReply(params) {
|
|
337
|
-
const { wsClient, text, toChatId, replyToMsgId, runtime, finish, streamId, isError, errorCode, errorDetails } = params;
|
|
337
|
+
const { wsClient, text, toChatId, replyToMsgId, runtime, finish, streamId, isError, errorCode, errorDetails, isThinking } = params;
|
|
338
338
|
const reqId = replyToMsgId || streamId;
|
|
339
339
|
runtime.log?.(`[53aihub] sendReply START: reqId=${reqId}, finish=${finish}, isError=${isError}, textLen=${text?.length || 0}, wsReadyState=${wsClient.readyState}`);
|
|
340
340
|
if (wsClient.readyState !== 1) {
|
|
@@ -395,7 +395,7 @@ async function sendReply(params) {
|
|
|
395
395
|
const payload = {
|
|
396
396
|
req_id: reqId,
|
|
397
397
|
action: "chat",
|
|
398
|
-
status: finish ? "done" : "streaming",
|
|
398
|
+
status: finish ? "done" : isThinking ? "thinking" : "streaming",
|
|
399
399
|
data: chunk,
|
|
400
400
|
};
|
|
401
401
|
const jsonStr = JSON.stringify(payload);
|
|
@@ -973,7 +973,6 @@ async function processMessage(params) {
|
|
|
973
973
|
cfg: config,
|
|
974
974
|
dispatcherOptions: {
|
|
975
975
|
deliver: async (payload, info) => {
|
|
976
|
-
state.accumulatedText += payload.text;
|
|
977
976
|
runtime.log?.(`[53aihub] deliver: kind=${info.kind}, textLen=${payload.text?.length || 0}, accumulatedLen=${state.accumulatedText.length}, isError=${payload.isError}`);
|
|
978
977
|
if (payload.isError) {
|
|
979
978
|
const errorMsg = payload.text || "Unknown error";
|
|
@@ -993,6 +992,23 @@ async function processMessage(params) {
|
|
|
993
992
|
});
|
|
994
993
|
return;
|
|
995
994
|
}
|
|
995
|
+
const isCompaction = payload.text?.startsWith("🧹 Compacting context") ||
|
|
996
|
+
state.accumulatedText.startsWith("🧹 Compacting context");
|
|
997
|
+
if (isCompaction && info.kind !== "final") {
|
|
998
|
+
runtime.log?.(`[53aihub] deliver COMPACTION: text preview=${payload.text?.substring(0, 50)}...`);
|
|
999
|
+
await sendReply({
|
|
1000
|
+
wsClient,
|
|
1001
|
+
text: payload.text || "",
|
|
1002
|
+
toChatId: chatId,
|
|
1003
|
+
replyToMsgId: body.msgId,
|
|
1004
|
+
runtime,
|
|
1005
|
+
finish: false,
|
|
1006
|
+
streamId: state.streamId,
|
|
1007
|
+
isThinking: true,
|
|
1008
|
+
});
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
state.accumulatedText += payload.text;
|
|
996
1012
|
if (info.kind !== "final") {
|
|
997
1013
|
runtime.log?.(`[53aihub] deliver STREAMING: accumulatedText preview=${state.accumulatedText.substring(0, 50)}...`);
|
|
998
1014
|
await sendReply({
|
|
@@ -1592,6 +1608,67 @@ const aiHubPlugin = {
|
|
|
1592
1608
|
},
|
|
1593
1609
|
};
|
|
1594
1610
|
|
|
1611
|
+
const compactionSessions = new Map();
|
|
1612
|
+
/**
|
|
1613
|
+
* 从 sessionKey 中解析 chatId
|
|
1614
|
+
* sessionKey 格式: agent:{agentId}:{channel}:direct:{chatId}
|
|
1615
|
+
* 例如: agent:main:53aihub:direct:user123 -> user123
|
|
1616
|
+
*/
|
|
1617
|
+
function parseChatIdFromSessionKey(sessionKey) {
|
|
1618
|
+
if (!sessionKey)
|
|
1619
|
+
return null;
|
|
1620
|
+
const parts = sessionKey.split(":");
|
|
1621
|
+
// 格式: agent:{agentId}:{channel}:direct:{chatId}
|
|
1622
|
+
// parts: [0]agent, [1]agentId, [2]channel, [3]direct, [4]chatId
|
|
1623
|
+
if (parts.length >= 5 && parts[2] === CHANNEL_ID && parts[3] === "direct") {
|
|
1624
|
+
return parts[4];
|
|
1625
|
+
}
|
|
1626
|
+
return null;
|
|
1627
|
+
}
|
|
1628
|
+
async function handleBeforeCompaction(event, ctx) {
|
|
1629
|
+
const runtime = getRuntime();
|
|
1630
|
+
const logger = runtime.logging.getChildLogger({ component: "53aihub-compaction" });
|
|
1631
|
+
const log = (msg) => logger.info(msg);
|
|
1632
|
+
log(`before_compaction: sessionKey=${ctx.sessionKey}, channelId=${ctx.channelId}, messageCount=${event.messageCount}`);
|
|
1633
|
+
const sessionKey = ctx.sessionKey || "";
|
|
1634
|
+
if (!sessionKey.startsWith(`${CHANNEL_ID}:`) && !sessionKey.includes(`:${CHANNEL_ID}:`)) {
|
|
1635
|
+
log(`Skipping compaction hook for non-53aihub session: ${sessionKey}`);
|
|
1636
|
+
return;
|
|
1637
|
+
}
|
|
1638
|
+
const chatId = parseChatIdFromSessionKey(sessionKey);
|
|
1639
|
+
if (!chatId) {
|
|
1640
|
+
logger.error(`Cannot parse chatId from sessionKey: ${sessionKey}`);
|
|
1641
|
+
return;
|
|
1642
|
+
}
|
|
1643
|
+
compactionSessions.set(sessionKey, {
|
|
1644
|
+
startTime: Date.now(),
|
|
1645
|
+
messageCount: event.messageCount,
|
|
1646
|
+
});
|
|
1647
|
+
log(`Compaction started for chatId=${chatId}`);
|
|
1648
|
+
}
|
|
1649
|
+
async function handleAfterCompaction(event, ctx) {
|
|
1650
|
+
const runtime = getRuntime();
|
|
1651
|
+
const logger = runtime.logging.getChildLogger({ component: "53aihub-compaction" });
|
|
1652
|
+
const log = (msg) => logger.info(msg);
|
|
1653
|
+
log(`after_compaction: sessionKey=${ctx.sessionKey}, channelId=${ctx.channelId}, messageCount=${event.messageCount}, compactedCount=${event.compactedCount}`);
|
|
1654
|
+
const sessionKey = ctx.sessionKey || "";
|
|
1655
|
+
if (!sessionKey.startsWith(`${CHANNEL_ID}:`) && !sessionKey.includes(`:${CHANNEL_ID}:`)) {
|
|
1656
|
+
log(`Skipping compaction hook for non-53aihub session: ${sessionKey}`);
|
|
1657
|
+
return;
|
|
1658
|
+
}
|
|
1659
|
+
const chatId = parseChatIdFromSessionKey(sessionKey);
|
|
1660
|
+
if (!chatId) {
|
|
1661
|
+
logger.error(`Cannot parse chatId from sessionKey: ${sessionKey}`);
|
|
1662
|
+
return;
|
|
1663
|
+
}
|
|
1664
|
+
const sessionInfo = compactionSessions.get(sessionKey);
|
|
1665
|
+
compactionSessions.delete(sessionKey);
|
|
1666
|
+
if (sessionInfo) {
|
|
1667
|
+
const duration = Date.now() - sessionInfo.startTime;
|
|
1668
|
+
log(`Compaction completed: chatId=${chatId}, duration=${duration}ms, messagesBefore=${sessionInfo.messageCount}, messagesAfter=${event.messageCount}, compacted=${event.compactedCount}`);
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1595
1672
|
const plugin = {
|
|
1596
1673
|
id: "53ai-openclaw",
|
|
1597
1674
|
name: "53AI OpenClaw",
|
|
@@ -1600,6 +1677,8 @@ const plugin = {
|
|
|
1600
1677
|
register(api) {
|
|
1601
1678
|
setRuntime(api.runtime);
|
|
1602
1679
|
api.registerChannel({ plugin: aiHubPlugin });
|
|
1680
|
+
api.on("before_compaction", handleBeforeCompaction);
|
|
1681
|
+
api.on("after_compaction", handleAfterCompaction);
|
|
1603
1682
|
},
|
|
1604
1683
|
};
|
|
1605
1684
|
|