libp2p-mesh 2026.5.25 → 2026.5.27

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.
@@ -18,6 +18,18 @@ export async function handleIdentityMessage(msg, deps) {
18
18
  // Malformed payload — skip silently
19
19
  return;
20
20
  }
21
+ // sendToPeer 包装了一层 direct 外壳后,payload 里可能嵌套了 identity 消息:
22
+ // outer: {"type":"identity","from":"A","payload":"{\"agentId\":\"A\",\"channel\":\"feishu\",...}"}
23
+ // 先解析拿到外层,再检测 type 并递归解析内层 payload。
24
+ if (parsed.type === "identity" && typeof parsed.payload === "string") {
25
+ try {
26
+ parsed = JSON.parse(parsed.payload);
27
+ }
28
+ catch {
29
+ // Inner payload malformed — skip silently
30
+ return;
31
+ }
32
+ }
21
33
  const { agentId, channel, accountId, instanceId } = parsed;
22
34
  // Only register if all required fields are present
23
35
  if (agentId && channel && accountId) {
@@ -60,7 +60,8 @@ export async function handleP2PInbound(msg, deps) {
60
60
  else if (msg.type === "direct") {
61
61
  // onPeerConnect 通过 sendToPeer 发送 identity 时会被包装成
62
62
  // type=direct 的外壳,真正的 identity 消息藏在 payload 里。
63
- // 先检测并处理这种情况,确保双向身份交换能完成。
63
+ // 先检测并处理:注册对方身份,但继续往下执行让底部日志打印。
64
+ let isIdentity = false;
64
65
  try {
65
66
  const raw = JSON.parse(msg.payload);
66
67
  if (raw && raw.type === "identity") {
@@ -74,48 +75,49 @@ export async function handleP2PInbound(msg, deps) {
74
75
  send: async () => { }, // no-op; 双方都通过 onPeerConnect 主动发送身份
75
76
  logger,
76
77
  });
77
- // identity 处理完毕,不再走 direct 消息路由
78
- return;
78
+ isIdentity = true;
79
79
  }
80
80
  }
81
81
  catch {
82
82
  // payload 不是 JSON,正常走 direct 消息逻辑
83
83
  }
84
- if (!msg.to) {
85
- logger?.warn?.("[libp2p-mesh] Direct message missing 'to' field");
86
- }
87
- else {
88
- const receiver = deps.peerIdentityMap.resolve(msg.to);
89
- if (!receiver) {
90
- // Fallback: check if the recipient is our own local identity.
91
- // setLocalIdentity stores the local peer separately (not in peers
92
- // Map) to avoid duplication, so direct messages addressed to
93
- // ourselves need this fallback to resolve correctly.
94
- const localPeerId = deps.peerIdentityMap.getLocalPeerId();
95
- const localId = deps.peerIdentityMap.getLocalIdentity();
96
- if (localId && msg.to === localPeerId) {
84
+ if (!isIdentity) {
85
+ if (!msg.to) {
86
+ logger?.warn?.("[libp2p-mesh] Direct message missing 'to' field");
87
+ }
88
+ else {
89
+ const receiver = deps.peerIdentityMap.resolve(msg.to);
90
+ if (!receiver) {
91
+ // Fallback: check if the recipient is our own local identity.
92
+ // setLocalIdentity stores the local peer separately (not in peers
93
+ // Map) to avoid duplication, so direct messages addressed to
94
+ // ourselves need this fallback to resolve correctly.
95
+ const localPeerId = deps.peerIdentityMap.getLocalPeerId();
96
+ const localId = deps.peerIdentityMap.getLocalIdentity();
97
+ if (localId && msg.to === localPeerId) {
98
+ const sessionKey = buildAgentSessionKey({
99
+ agentId: localId.agentId,
100
+ channel: localId.channel,
101
+ accountId: localId.accountId,
102
+ });
103
+ const text = `【来自P2P网络的消息】\n来源:${msg.from}\n内容:${msg.payload}\n\n` +
104
+ `请你通过你当前的 channel 将此消息转发给你所服务的用户。转发完成后,请务必调用 p2p_send_message 工具向 ${msg.from} 回复送达确认。`;
105
+ deps.enqueueNextTurnInjection({ sessionKey, text, placement: "prepend_context" });
106
+ }
107
+ else {
108
+ logger?.warn?.(`[libp2p-mesh] Unknown recipient peer: ${msg.to}`);
109
+ }
110
+ }
111
+ else {
97
112
  const sessionKey = buildAgentSessionKey({
98
- agentId: localId.agentId,
99
- channel: localId.channel,
100
- accountId: localId.accountId,
113
+ agentId: receiver.agentId,
114
+ channel: receiver.channel,
115
+ accountId: receiver.accountId,
101
116
  });
102
117
  const text = `【来自P2P网络的消息】\n来源:${msg.from}\n内容:${msg.payload}\n\n` +
103
118
  `请你通过你当前的 channel 将此消息转发给你所服务的用户。转发完成后,请务必调用 p2p_send_message 工具向 ${msg.from} 回复送达确认。`;
104
119
  deps.enqueueNextTurnInjection({ sessionKey, text, placement: "prepend_context" });
105
120
  }
106
- else {
107
- logger?.warn?.(`[libp2p-mesh] Unknown recipient peer: ${msg.to}`);
108
- }
109
- }
110
- else {
111
- const sessionKey = buildAgentSessionKey({
112
- agentId: receiver.agentId,
113
- channel: receiver.channel,
114
- accountId: receiver.accountId,
115
- });
116
- const text = `【来自P2P网络的消息】\n来源:${msg.from}\n内容:${msg.payload}\n\n` +
117
- `请你通过你当前的 channel 将此消息转发给你所服务的用户。转发完成后,请务必调用 p2p_send_message 工具向 ${msg.from} 回复送达确认。`;
118
- deps.enqueueNextTurnInjection({ sessionKey, text, placement: "prepend_context" });
119
121
  }
120
122
  }
121
123
  // If the sender is not yet registered, register them synchronously
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libp2p-mesh",
3
- "version": "2026.5.25",
3
+ "version": "2026.5.27",
4
4
  "description": "OpenClaw libp2p P2P mesh network plugin for cross-instance agent communication",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -40,7 +40,7 @@ export async function handleIdentityMessage(
40
40
  const logger = deps.logger;
41
41
 
42
42
  // Parse remote identity payload
43
- let parsed: { agentId?: string; channel?: string; accountId?: string; instanceId?: string } = {};
43
+ let parsed: Record<string, unknown> = {};
44
44
  try {
45
45
  parsed = JSON.parse(msg.payload);
46
46
  } catch {
@@ -48,7 +48,24 @@ export async function handleIdentityMessage(
48
48
  return;
49
49
  }
50
50
 
51
- const { agentId, channel, accountId, instanceId } = parsed;
51
+ // sendToPeer 包装了一层 direct 外壳后,payload 里可能嵌套了 identity 消息:
52
+ // outer: {"type":"identity","from":"A","payload":"{\"agentId\":\"A\",\"channel\":\"feishu\",...}"}
53
+ // 先解析拿到外层,再检测 type 并递归解析内层 payload。
54
+ if (parsed.type === "identity" && typeof parsed.payload === "string") {
55
+ try {
56
+ parsed = JSON.parse(parsed.payload);
57
+ } catch {
58
+ // Inner payload malformed — skip silently
59
+ return;
60
+ }
61
+ }
62
+
63
+ const { agentId, channel, accountId, instanceId } = parsed as {
64
+ agentId?: string;
65
+ channel?: string;
66
+ accountId?: string;
67
+ instanceId?: string;
68
+ };
52
69
 
53
70
  // Only register if all required fields are present
54
71
  if (agentId && channel && accountId) {
package/src/inbound.ts CHANGED
@@ -77,7 +77,8 @@ export async function handleP2PInbound(msg: P2PMessage, deps?: InboundHandlerDep
77
77
  } else if (msg.type === "direct") {
78
78
  // onPeerConnect 通过 sendToPeer 发送 identity 时会被包装成
79
79
  // type=direct 的外壳,真正的 identity 消息藏在 payload 里。
80
- // 先检测并处理这种情况,确保双向身份交换能完成。
80
+ // 先检测并处理:注册对方身份,但继续往下执行让底部日志打印。
81
+ let isIdentity = false;
81
82
  try {
82
83
  const raw = JSON.parse(msg.payload);
83
84
  if (raw && raw.type === "identity") {
@@ -91,47 +92,48 @@ export async function handleP2PInbound(msg: P2PMessage, deps?: InboundHandlerDep
91
92
  send: async () => {}, // no-op; 双方都通过 onPeerConnect 主动发送身份
92
93
  logger,
93
94
  });
94
- // identity 处理完毕,不再走 direct 消息路由
95
- return;
95
+ isIdentity = true;
96
96
  }
97
97
  } catch {
98
98
  // payload 不是 JSON,正常走 direct 消息逻辑
99
99
  }
100
100
 
101
- if (!msg.to) {
102
- logger?.warn?.("[libp2p-mesh] Direct message missing 'to' field");
103
- } else {
104
- const receiver = deps.peerIdentityMap.resolve(msg.to);
105
- if (!receiver) {
106
- // Fallback: check if the recipient is our own local identity.
107
- // setLocalIdentity stores the local peer separately (not in peers
108
- // Map) to avoid duplication, so direct messages addressed to
109
- // ourselves need this fallback to resolve correctly.
110
- const localPeerId = deps.peerIdentityMap.getLocalPeerId();
111
- const localId = deps.peerIdentityMap.getLocalIdentity();
112
- if (localId && msg.to === localPeerId) {
101
+ if (!isIdentity) {
102
+ if (!msg.to) {
103
+ logger?.warn?.("[libp2p-mesh] Direct message missing 'to' field");
104
+ } else {
105
+ const receiver = deps.peerIdentityMap.resolve(msg.to);
106
+ if (!receiver) {
107
+ // Fallback: check if the recipient is our own local identity.
108
+ // setLocalIdentity stores the local peer separately (not in peers
109
+ // Map) to avoid duplication, so direct messages addressed to
110
+ // ourselves need this fallback to resolve correctly.
111
+ const localPeerId = deps.peerIdentityMap.getLocalPeerId();
112
+ const localId = deps.peerIdentityMap.getLocalIdentity();
113
+ if (localId && msg.to === localPeerId) {
114
+ const sessionKey = buildAgentSessionKey({
115
+ agentId: localId.agentId,
116
+ channel: localId.channel,
117
+ accountId: localId.accountId,
118
+ });
119
+ const text =
120
+ `【来自P2P网络的消息】\n来源:${msg.from}\n内容:${msg.payload}\n\n` +
121
+ `请你通过你当前的 channel 将此消息转发给你所服务的用户。转发完成后,请务必调用 p2p_send_message 工具向 ${msg.from} 回复送达确认。`;
122
+ deps.enqueueNextTurnInjection({ sessionKey, text, placement: "prepend_context" });
123
+ } else {
124
+ logger?.warn?.(`[libp2p-mesh] Unknown recipient peer: ${msg.to}`);
125
+ }
126
+ } else {
113
127
  const sessionKey = buildAgentSessionKey({
114
- agentId: localId.agentId,
115
- channel: localId.channel,
116
- accountId: localId.accountId,
128
+ agentId: receiver.agentId,
129
+ channel: receiver.channel,
130
+ accountId: receiver.accountId,
117
131
  });
118
132
  const text =
119
133
  `【来自P2P网络的消息】\n来源:${msg.from}\n内容:${msg.payload}\n\n` +
120
134
  `请你通过你当前的 channel 将此消息转发给你所服务的用户。转发完成后,请务必调用 p2p_send_message 工具向 ${msg.from} 回复送达确认。`;
121
135
  deps.enqueueNextTurnInjection({ sessionKey, text, placement: "prepend_context" });
122
- } else {
123
- logger?.warn?.(`[libp2p-mesh] Unknown recipient peer: ${msg.to}`);
124
136
  }
125
- } else {
126
- const sessionKey = buildAgentSessionKey({
127
- agentId: receiver.agentId,
128
- channel: receiver.channel,
129
- accountId: receiver.accountId,
130
- });
131
- const text =
132
- `【来自P2P网络的消息】\n来源:${msg.from}\n内容:${msg.payload}\n\n` +
133
- `请你通过你当前的 channel 将此消息转发给你所服务的用户。转发完成后,请务必调用 p2p_send_message 工具向 ${msg.from} 回复送达确认。`;
134
- deps.enqueueNextTurnInjection({ sessionKey, text, placement: "prepend_context" });
135
137
  }
136
138
  }
137
139