@xiaozhi-pro/openclaw-plugin 1.0.9 → 1.0.10
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/dist/api.d.ts +1 -1
- package/dist/api.js +1 -1
- package/dist/src/channel.js +18 -14
- package/dist/src/runtime.d.ts +2 -2
- package/dist/src/runtime.js +2 -2
- package/dist/src/ws-client.js +9 -5
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { xiaozhiProPlugin } from "./src/channel.js";
|
|
2
|
-
export { setXiaozhiProRuntime, getXiaozhiProRuntime } from "./src/runtime.js";
|
|
2
|
+
export { setXiaozhiProRuntime, getXiaozhiProRuntime, tryGetXiaozhiProRuntime } from "./src/runtime.js";
|
package/dist/api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { xiaozhiProPlugin } from "./src/channel.js";
|
|
2
|
-
export { setXiaozhiProRuntime, getXiaozhiProRuntime } from "./src/runtime.js";
|
|
2
|
+
export { setXiaozhiProRuntime, getXiaozhiProRuntime, tryGetXiaozhiProRuntime } from "./src/runtime.js";
|
package/dist/src/channel.js
CHANGED
|
@@ -10,7 +10,7 @@ import { createEmptyChannelDirectoryAdapter } from "openclaw/plugin-sdk/director
|
|
|
10
10
|
import { createHybridChannelConfigAdapter, createScopedDmSecurityResolver, } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
11
11
|
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
|
|
12
12
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
|
13
|
-
import {
|
|
13
|
+
import { tryGetXiaozhiProRuntime } from "./runtime.js";
|
|
14
14
|
import { listAccountIds, resolveAccount, } from "./accounts.js";
|
|
15
15
|
import { XiaozhiProConfigSchema } from "./config-schema.js";
|
|
16
16
|
import { connectXiaozhiProWs, sendXiaozhiProWsMessage, } from "./ws-client.js";
|
|
@@ -68,7 +68,7 @@ export const xiaozhiProPlugin = createChatChannelPlugin({
|
|
|
68
68
|
// ============================================================================
|
|
69
69
|
gateway: {
|
|
70
70
|
startAccount: async (ctx) => {
|
|
71
|
-
const { cfg, accountId, log, abortSignal } = ctx;
|
|
71
|
+
const { cfg, accountId, log, abortSignal, channelRuntime } = ctx;
|
|
72
72
|
const account = resolveAccount(cfg, accountId);
|
|
73
73
|
if (!account.token) {
|
|
74
74
|
log?.warn?.("token 未配置,跳过启动");
|
|
@@ -85,6 +85,8 @@ export const xiaozhiProPlugin = createChatChannelPlugin({
|
|
|
85
85
|
account,
|
|
86
86
|
accountId,
|
|
87
87
|
msg,
|
|
88
|
+
cfg,
|
|
89
|
+
channelRuntime: channelRuntime ?? undefined,
|
|
88
90
|
});
|
|
89
91
|
},
|
|
90
92
|
});
|
|
@@ -122,7 +124,7 @@ export const xiaozhiProPlugin = createChatChannelPlugin({
|
|
|
122
124
|
resolvePolicy: (account) => account.dmPolicy,
|
|
123
125
|
resolveAllowFrom: (account) => account.allowedUserIds,
|
|
124
126
|
policyPathSuffix: "dmPolicy",
|
|
125
|
-
defaultPolicy: "
|
|
127
|
+
defaultPolicy: "open",
|
|
126
128
|
}),
|
|
127
129
|
},
|
|
128
130
|
// 出站适配器(用于 agent 主动推送等场景)
|
|
@@ -148,22 +150,24 @@ async function dispatchXiaozhiProInboundEvent(params) {
|
|
|
148
150
|
if (isDuplicateMessage(params.msg.messageId)) {
|
|
149
151
|
return;
|
|
150
152
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
// 优先使用 gateway ctx 注入的 channelRuntime,后备使用全局 runtime store
|
|
154
|
+
const globalRt = tryGetXiaozhiProRuntime();
|
|
155
|
+
const channelRt = params.channelRuntime ?? globalRt?.channel;
|
|
156
|
+
if (!channelRt?.inbound?.run || !channelRt?.routing?.resolveAgentRoute) {
|
|
153
157
|
console.error("[xiaozhi-pro] 运行时未就绪,丢弃消息。请确认插件已正确注册并重启服务。");
|
|
154
158
|
return;
|
|
155
159
|
}
|
|
156
|
-
const currentCfg =
|
|
160
|
+
const currentCfg = params.cfg;
|
|
157
161
|
// 1. 解析路由(哪个 agent 处理这个对话)
|
|
158
|
-
const route =
|
|
162
|
+
const route = channelRt.routing.resolveAgentRoute({
|
|
159
163
|
cfg: currentCfg,
|
|
160
164
|
channel: CHANNEL_ID,
|
|
161
165
|
accountId: params.accountId,
|
|
162
166
|
peer: { kind: "direct", id: params.msg.senderId },
|
|
163
167
|
});
|
|
164
|
-
const sessionKey =
|
|
168
|
+
const sessionKey = route.sessionKey;
|
|
165
169
|
// 2. 通过 inbound.run() 分发给 agent
|
|
166
|
-
await
|
|
170
|
+
await channelRt.inbound.run({
|
|
167
171
|
channel: CHANNEL_ID,
|
|
168
172
|
accountId: params.accountId,
|
|
169
173
|
raw: params.msg,
|
|
@@ -179,7 +183,7 @@ async function dispatchXiaozhiProInboundEvent(params) {
|
|
|
179
183
|
}),
|
|
180
184
|
// resolveTurn:构建完整上下文 + 回复投递回调
|
|
181
185
|
resolveTurn: async (input) => {
|
|
182
|
-
const msgCtx =
|
|
186
|
+
const msgCtx = channelRt.inbound.buildContext({
|
|
183
187
|
channel: CHANNEL_ID,
|
|
184
188
|
accountId: params.accountId,
|
|
185
189
|
timestamp: input.timestamp,
|
|
@@ -202,17 +206,17 @@ async function dispatchXiaozhiProInboundEvent(params) {
|
|
|
202
206
|
bodyForAgent: input.textForAgent,
|
|
203
207
|
},
|
|
204
208
|
});
|
|
205
|
-
const storePath =
|
|
209
|
+
const storePath = channelRt.session.resolveStorePath(currentCfg.session?.store, { agentId: route.agentId });
|
|
206
210
|
return {
|
|
207
211
|
cfg: currentCfg,
|
|
208
212
|
channel: CHANNEL_ID,
|
|
209
213
|
accountId: params.accountId,
|
|
210
214
|
agentId: route.agentId,
|
|
211
|
-
routeSessionKey:
|
|
215
|
+
routeSessionKey: sessionKey,
|
|
212
216
|
storePath,
|
|
213
217
|
ctxPayload: msgCtx,
|
|
214
|
-
recordInboundSession:
|
|
215
|
-
dispatchReplyWithBufferedBlockDispatcher:
|
|
218
|
+
recordInboundSession: channelRt.session.recordInboundSession,
|
|
219
|
+
dispatchReplyWithBufferedBlockDispatcher: channelRt.reply.dispatchReplyWithBufferedBlockDispatcher,
|
|
216
220
|
delivery: {
|
|
217
221
|
durable: () => ({ to: params.msg.senderId }),
|
|
218
222
|
// agent 回复通过这个回调投递 → 发 WS 回小智Pro
|
package/dist/src/runtime.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type PluginRuntime } from "openclaw/plugin-sdk/runtime-store";
|
|
2
|
-
declare const setXiaozhiProRuntime: (next: PluginRuntime) => void, getXiaozhiProRuntime: () => PluginRuntime;
|
|
3
|
-
export { setXiaozhiProRuntime, getXiaozhiProRuntime };
|
|
2
|
+
declare const setXiaozhiProRuntime: (next: PluginRuntime) => void, getXiaozhiProRuntime: () => PluginRuntime, tryGetXiaozhiProRuntime: () => PluginRuntime | null;
|
|
3
|
+
export { setXiaozhiProRuntime, getXiaozhiProRuntime, tryGetXiaozhiProRuntime };
|
package/dist/src/runtime.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// 小智Pro插件运行时存储
|
|
2
2
|
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
|
3
|
-
const { setRuntime: setXiaozhiProRuntime, getRuntime: getXiaozhiProRuntime } = createPluginRuntimeStore({
|
|
3
|
+
const { setRuntime: setXiaozhiProRuntime, getRuntime: getXiaozhiProRuntime, tryGetRuntime: tryGetXiaozhiProRuntime } = createPluginRuntimeStore({
|
|
4
4
|
pluginId: "xiaozhi-pro",
|
|
5
5
|
errorMessage: "小智Pro插件运行时未初始化 - 插件未注册",
|
|
6
6
|
});
|
|
7
|
-
export { setXiaozhiProRuntime, getXiaozhiProRuntime };
|
|
7
|
+
export { setXiaozhiProRuntime, getXiaozhiProRuntime, tryGetXiaozhiProRuntime };
|
package/dist/src/ws-client.js
CHANGED
|
@@ -10,6 +10,8 @@ export function connectXiaozhiProWs(config) {
|
|
|
10
10
|
let reconnectTimer = null;
|
|
11
11
|
let reconnectAttempts = 0;
|
|
12
12
|
let authFatal = false;
|
|
13
|
+
// 记录 auth_ok 返回的 user_id,作为 sender_id 的后备
|
|
14
|
+
let authenticatedUserId = null;
|
|
13
15
|
const MAX_RECONNECT_DELAY = 60_000;
|
|
14
16
|
function connect() {
|
|
15
17
|
if (abortSignal.aborted || authFatal)
|
|
@@ -20,14 +22,15 @@ export function connectXiaozhiProWs(config) {
|
|
|
20
22
|
log?.info?.(`[xiaozhi-pro] WS 已连接: ${url}`);
|
|
21
23
|
// 发送 auth 消息(和小智Pro服务端协议对齐)
|
|
22
24
|
const token = account.token;
|
|
23
|
-
log?.info?.(`[xiaozhi-pro] 发送认证: token=${token} (长度=${token.length})`);
|
|
25
|
+
log?.info?.(`[xiaozhi-pro] 发送认证: token=${token.length > 8 ? token.slice(0, 4) + "****" + token.slice(-4) : "****"} (长度=${token.length})`);
|
|
24
26
|
ws.send(JSON.stringify({ type: "auth", token }));
|
|
25
27
|
});
|
|
26
28
|
ws.on("message", (raw) => {
|
|
27
29
|
try {
|
|
28
30
|
const data = JSON.parse(raw.toString());
|
|
29
31
|
if (data.type === "auth_ok") {
|
|
30
|
-
|
|
32
|
+
authenticatedUserId = data.user_id ?? null;
|
|
33
|
+
log?.info?.(`[xiaozhi-pro] 认证成功: user_id=${authenticatedUserId}`);
|
|
31
34
|
return;
|
|
32
35
|
}
|
|
33
36
|
if (data.type === "auth_fail") {
|
|
@@ -49,15 +52,16 @@ export function connectXiaozhiProWs(config) {
|
|
|
49
52
|
// 服务端推送的入站消息
|
|
50
53
|
if (data.type === "message" || data.type === "response") {
|
|
51
54
|
const text = data.text ?? "";
|
|
52
|
-
|
|
55
|
+
// 优先用消息中的 sender_id,后备用 auth_ok 的 user_id
|
|
56
|
+
const senderId = data.sender_id ?? data.user_id ?? authenticatedUserId ?? "";
|
|
53
57
|
log?.info?.(`[xiaozhi-pro] 收到消息: type=${data.type}, sender=${senderId}, text=${text.slice(0, 200)}`);
|
|
54
58
|
// 入站消息,分发给 agent
|
|
55
59
|
onMessage({
|
|
56
60
|
type: "message",
|
|
57
|
-
senderId
|
|
61
|
+
senderId,
|
|
58
62
|
text: data.text ?? "",
|
|
59
63
|
chatType: data.chat_type ?? "dm",
|
|
60
|
-
chatId: data.chat_id ??
|
|
64
|
+
chatId: data.chat_id ?? senderId,
|
|
61
65
|
messageId: data.message_id ?? `msg-${Date.now()}`,
|
|
62
66
|
timestamp: data.timestamp ?? Date.now(),
|
|
63
67
|
}).catch((err) => {
|