@53ai/53ai-openclaw 1.0.6 → 1.0.8
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 +6 -0
- package/README.md +10 -10
- package/dist/index.cjs.js +91 -12
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +91 -12
- 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/dist/src/utils.d.ts +2 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -310,7 +310,7 @@ function parseMessageContent(msg) {
|
|
|
310
310
|
}
|
|
311
311
|
|
|
312
312
|
async function sendReply(params) {
|
|
313
|
-
const { wsClient, text, toChatId, replyToMsgId, runtime, finish, streamId, isError, errorCode, errorDetails } = params;
|
|
313
|
+
const { wsClient, text, toChatId, replyToMsgId, runtime, finish, streamId, isError, errorCode, errorDetails, isThinking } = params;
|
|
314
314
|
const reqId = replyToMsgId || streamId;
|
|
315
315
|
runtime.log?.(`[53aihub] sendReply START: reqId=${reqId}, finish=${finish}, isError=${isError}, textLen=${text?.length || 0}, wsReadyState=${wsClient.readyState}`);
|
|
316
316
|
if (wsClient.readyState !== 1) {
|
|
@@ -371,7 +371,7 @@ async function sendReply(params) {
|
|
|
371
371
|
const payload = {
|
|
372
372
|
req_id: reqId,
|
|
373
373
|
action: "chat",
|
|
374
|
-
status: finish ? "done" : "streaming",
|
|
374
|
+
status: finish ? "done" : isThinking ? "thinking" : "streaming",
|
|
375
375
|
data: chunk,
|
|
376
376
|
};
|
|
377
377
|
const jsonStr = JSON.stringify(payload);
|
|
@@ -949,7 +949,6 @@ async function processMessage(params) {
|
|
|
949
949
|
cfg: config,
|
|
950
950
|
dispatcherOptions: {
|
|
951
951
|
deliver: async (payload, info) => {
|
|
952
|
-
state.accumulatedText += payload.text;
|
|
953
952
|
runtime.log?.(`[53aihub] deliver: kind=${info.kind}, textLen=${payload.text?.length || 0}, accumulatedLen=${state.accumulatedText.length}, isError=${payload.isError}`);
|
|
954
953
|
if (payload.isError) {
|
|
955
954
|
const errorMsg = payload.text || "Unknown error";
|
|
@@ -969,6 +968,23 @@ async function processMessage(params) {
|
|
|
969
968
|
});
|
|
970
969
|
return;
|
|
971
970
|
}
|
|
971
|
+
const isCompaction = payload.text?.startsWith("🧹 Compacting context") ||
|
|
972
|
+
state.accumulatedText.startsWith("🧹 Compacting context");
|
|
973
|
+
if (isCompaction && info.kind !== "final") {
|
|
974
|
+
runtime.log?.(`[53aihub] deliver COMPACTION: text preview=${payload.text?.substring(0, 50)}...`);
|
|
975
|
+
await sendReply({
|
|
976
|
+
wsClient,
|
|
977
|
+
text: payload.text || "",
|
|
978
|
+
toChatId: chatId,
|
|
979
|
+
replyToMsgId: body.msgId,
|
|
980
|
+
runtime,
|
|
981
|
+
finish: false,
|
|
982
|
+
streamId: state.streamId,
|
|
983
|
+
isThinking: true,
|
|
984
|
+
});
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
state.accumulatedText += payload.text;
|
|
972
988
|
if (info.kind !== "final") {
|
|
973
989
|
runtime.log?.(`[53aihub] deliver STREAMING: accumulatedText preview=${state.accumulatedText.substring(0, 50)}...`);
|
|
974
990
|
await sendReply({
|
|
@@ -1084,7 +1100,7 @@ async function monitorProvider(options) {
|
|
|
1084
1100
|
if (isAborted)
|
|
1085
1101
|
return;
|
|
1086
1102
|
// 安全: 不在 URL 中传递敏感信息,仅通过 headers 传递认证
|
|
1087
|
-
const wsUrl = account.
|
|
1103
|
+
const wsUrl = account.WSUrl;
|
|
1088
1104
|
const botId = account.botId || account.config.botId;
|
|
1089
1105
|
const secret = account.secret || account.token || account.config.secret || account.config.token;
|
|
1090
1106
|
// 日志输出时隐藏敏感信息
|
|
@@ -1183,7 +1199,7 @@ function resolveAccount(cfg, accountId = DEFAULT_ACCOUNT_ID) {
|
|
|
1183
1199
|
accountId,
|
|
1184
1200
|
name: config.name ?? "53AIHub",
|
|
1185
1201
|
enabled: config.enabled !== false,
|
|
1186
|
-
|
|
1202
|
+
WSUrl: config.WSUrl || DEFAULT_WS_URL,
|
|
1187
1203
|
botId: config.botId ?? config.userId ?? "",
|
|
1188
1204
|
secret: config.secret ?? config.token ?? "",
|
|
1189
1205
|
token: config.token ?? config.secret ?? "",
|
|
@@ -1204,8 +1220,8 @@ function setAccount(cfg, account) {
|
|
|
1204
1220
|
allowFrom: account.allowFrom ?? existing.allowFrom,
|
|
1205
1221
|
accessPolicy: account.accessPolicy ?? existing.accessPolicy,
|
|
1206
1222
|
sendThinkingMessage: account.sendThinkingMessage ?? existing.sendThinkingMessage,
|
|
1207
|
-
...(account.
|
|
1208
|
-
? {
|
|
1223
|
+
...(account.WSUrl || existing.WSUrl
|
|
1224
|
+
? { WSUrl: account.WSUrl ?? existing.WSUrl }
|
|
1209
1225
|
: {}),
|
|
1210
1226
|
...(account.name || existing.name
|
|
1211
1227
|
? { name: account.name ?? existing.name }
|
|
@@ -1243,10 +1259,10 @@ async function promptSecret(prompter, account) {
|
|
|
1243
1259
|
validate: (value) => (value?.trim() ? undefined : "必填"),
|
|
1244
1260
|
})).trim();
|
|
1245
1261
|
}
|
|
1246
|
-
async function
|
|
1262
|
+
async function promptWSUrl(prompter, account) {
|
|
1247
1263
|
return String(await prompter.text({
|
|
1248
1264
|
message: "WebSocket URL (例如: ws://localhost:8080/ws)",
|
|
1249
|
-
initialValue: account?.
|
|
1265
|
+
initialValue: account?.WSUrl ?? "",
|
|
1250
1266
|
validate: (value) => {
|
|
1251
1267
|
const trimmed = value?.trim();
|
|
1252
1268
|
if (!trimmed)
|
|
@@ -1316,11 +1332,11 @@ const aiHubOnboardingAdapter = {
|
|
|
1316
1332
|
}
|
|
1317
1333
|
const botId = await promptBotId(prompter, account);
|
|
1318
1334
|
const secret = await promptSecret(prompter, account);
|
|
1319
|
-
const
|
|
1335
|
+
const WSUrl = await promptWSUrl(prompter, account);
|
|
1320
1336
|
const cfgWithAccount = setAccount(cfg, {
|
|
1321
1337
|
botId,
|
|
1322
1338
|
secret,
|
|
1323
|
-
|
|
1339
|
+
WSUrl: WSUrl || undefined,
|
|
1324
1340
|
enabled: true,
|
|
1325
1341
|
accessPolicy: account.config.accessPolicy ?? "open",
|
|
1326
1342
|
allowFrom: account.config.allowFrom ?? [],
|
|
@@ -1399,7 +1415,7 @@ const aiHubPlugin = {
|
|
|
1399
1415
|
enabled: account.enabled,
|
|
1400
1416
|
configured: Boolean(account.botId?.trim() || account.token?.trim()),
|
|
1401
1417
|
botId: account.botId,
|
|
1402
|
-
|
|
1418
|
+
WSUrl: account.WSUrl,
|
|
1403
1419
|
accessPolicy: account.config.accessPolicy ?? "open",
|
|
1404
1420
|
}),
|
|
1405
1421
|
resolveAllowFrom: ({ cfg }) => {
|
|
@@ -1568,6 +1584,67 @@ const aiHubPlugin = {
|
|
|
1568
1584
|
},
|
|
1569
1585
|
};
|
|
1570
1586
|
|
|
1587
|
+
const compactionSessions = new Map();
|
|
1588
|
+
/**
|
|
1589
|
+
* 从 sessionKey 中解析 chatId
|
|
1590
|
+
* sessionKey 格式: agent:{agentId}:{channel}:direct:{chatId}
|
|
1591
|
+
* 例如: agent:main:53aihub:direct:user123 -> user123
|
|
1592
|
+
*/
|
|
1593
|
+
function parseChatIdFromSessionKey(sessionKey) {
|
|
1594
|
+
if (!sessionKey)
|
|
1595
|
+
return null;
|
|
1596
|
+
const parts = sessionKey.split(":");
|
|
1597
|
+
// 格式: agent:{agentId}:{channel}:direct:{chatId}
|
|
1598
|
+
// parts: [0]agent, [1]agentId, [2]channel, [3]direct, [4]chatId
|
|
1599
|
+
if (parts.length >= 5 && parts[2] === CHANNEL_ID && parts[3] === "direct") {
|
|
1600
|
+
return parts[4];
|
|
1601
|
+
}
|
|
1602
|
+
return null;
|
|
1603
|
+
}
|
|
1604
|
+
async function handleBeforeCompaction(event, ctx) {
|
|
1605
|
+
const runtime = getRuntime();
|
|
1606
|
+
const logger = runtime.logging.getChildLogger({ component: "53aihub-compaction" });
|
|
1607
|
+
const log = (msg) => logger.info(msg);
|
|
1608
|
+
log(`before_compaction: sessionKey=${ctx.sessionKey}, channelId=${ctx.channelId}, messageCount=${event.messageCount}`);
|
|
1609
|
+
const sessionKey = ctx.sessionKey || "";
|
|
1610
|
+
if (!sessionKey.startsWith(`${CHANNEL_ID}:`) && !sessionKey.includes(`:${CHANNEL_ID}:`)) {
|
|
1611
|
+
log(`Skipping compaction hook for non-53aihub session: ${sessionKey}`);
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
const chatId = parseChatIdFromSessionKey(sessionKey);
|
|
1615
|
+
if (!chatId) {
|
|
1616
|
+
logger.error(`Cannot parse chatId from sessionKey: ${sessionKey}`);
|
|
1617
|
+
return;
|
|
1618
|
+
}
|
|
1619
|
+
compactionSessions.set(sessionKey, {
|
|
1620
|
+
startTime: Date.now(),
|
|
1621
|
+
messageCount: event.messageCount,
|
|
1622
|
+
});
|
|
1623
|
+
log(`Compaction started for chatId=${chatId}`);
|
|
1624
|
+
}
|
|
1625
|
+
async function handleAfterCompaction(event, ctx) {
|
|
1626
|
+
const runtime = getRuntime();
|
|
1627
|
+
const logger = runtime.logging.getChildLogger({ component: "53aihub-compaction" });
|
|
1628
|
+
const log = (msg) => logger.info(msg);
|
|
1629
|
+
log(`after_compaction: sessionKey=${ctx.sessionKey}, channelId=${ctx.channelId}, messageCount=${event.messageCount}, compactedCount=${event.compactedCount}`);
|
|
1630
|
+
const sessionKey = ctx.sessionKey || "";
|
|
1631
|
+
if (!sessionKey.startsWith(`${CHANNEL_ID}:`) && !sessionKey.includes(`:${CHANNEL_ID}:`)) {
|
|
1632
|
+
log(`Skipping compaction hook for non-53aihub session: ${sessionKey}`);
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
const chatId = parseChatIdFromSessionKey(sessionKey);
|
|
1636
|
+
if (!chatId) {
|
|
1637
|
+
logger.error(`Cannot parse chatId from sessionKey: ${sessionKey}`);
|
|
1638
|
+
return;
|
|
1639
|
+
}
|
|
1640
|
+
const sessionInfo = compactionSessions.get(sessionKey);
|
|
1641
|
+
compactionSessions.delete(sessionKey);
|
|
1642
|
+
if (sessionInfo) {
|
|
1643
|
+
const duration = Date.now() - sessionInfo.startTime;
|
|
1644
|
+
log(`Compaction completed: chatId=${chatId}, duration=${duration}ms, messagesBefore=${sessionInfo.messageCount}, messagesAfter=${event.messageCount}, compacted=${event.compactedCount}`);
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1571
1648
|
const plugin = {
|
|
1572
1649
|
id: "53ai-openclaw",
|
|
1573
1650
|
name: "53AI OpenClaw",
|
|
@@ -1576,6 +1653,8 @@ const plugin = {
|
|
|
1576
1653
|
register(api) {
|
|
1577
1654
|
setRuntime(api.runtime);
|
|
1578
1655
|
api.registerChannel({ plugin: aiHubPlugin });
|
|
1656
|
+
api.on("before_compaction", handleBeforeCompaction);
|
|
1657
|
+
api.on("after_compaction", handleAfterCompaction);
|
|
1579
1658
|
},
|
|
1580
1659
|
};
|
|
1581
1660
|
|