@xiaozhi-pro/openclaw-plugin 1.0.8 → 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 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";
@@ -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 { getXiaozhiProRuntime } from "./runtime.js";
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: "allowlist",
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
- const rt = getXiaozhiProRuntime();
152
- if (!rt.channel?.inbound?.run || !rt.channel?.routing?.resolveAgentRoute) {
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 = rt.config.current();
160
+ const currentCfg = params.cfg;
157
161
  // 1. 解析路由(哪个 agent 处理这个对话)
158
- const route = rt.channel.routing.resolveAgentRoute({
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 = `xiaozhi-pro:${route.agentId}:${params.msg.senderId}`;
168
+ const sessionKey = route.sessionKey;
165
169
  // 2. 通过 inbound.run() 分发给 agent
166
- await rt.channel.inbound.run({
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 = rt.channel.inbound.buildContext({
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 = rt.channel.session.resolveStorePath(currentCfg.session?.store, { agentId: route.agentId });
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: route.sessionKey,
215
+ routeSessionKey: sessionKey,
212
216
  storePath,
213
217
  ctxPayload: msgCtx,
214
- recordInboundSession: rt.channel.session.recordInboundSession,
215
- dispatchReplyWithBufferedBlockDispatcher: rt.channel.reply.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
@@ -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 };
@@ -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 };
@@ -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
- log?.info?.(`[xiaozhi-pro] 认证成功: user_id=${data.user_id}`);
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") {
@@ -48,13 +51,17 @@ export function connectXiaozhiProWs(config) {
48
51
  }
49
52
  // 服务端推送的入站消息
50
53
  if (data.type === "message" || data.type === "response") {
54
+ const text = data.text ?? "";
55
+ // 优先用消息中的 sender_id,后备用 auth_ok 的 user_id
56
+ const senderId = data.sender_id ?? data.user_id ?? authenticatedUserId ?? "";
57
+ log?.info?.(`[xiaozhi-pro] 收到消息: type=${data.type}, sender=${senderId}, text=${text.slice(0, 200)}`);
51
58
  // 入站消息,分发给 agent
52
59
  onMessage({
53
60
  type: "message",
54
- senderId: data.sender_id ?? data.user_id ?? "",
61
+ senderId,
55
62
  text: data.text ?? "",
56
63
  chatType: data.chat_type ?? "dm",
57
- chatId: data.chat_id ?? "",
64
+ chatId: data.chat_id ?? senderId,
58
65
  messageId: data.message_id ?? `msg-${Date.now()}`,
59
66
  timestamp: data.timestamp ?? Date.now(),
60
67
  }).catch((err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xiaozhi-pro/openclaw-plugin",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "小智Pro (XiaoZhi Pro) channel plugin for OpenClaw via WebSocket",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",