@steve02081504/fount-p2p 0.0.4 → 0.0.6

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.
Files changed (64) hide show
  1. package/core/bytes_codec.mjs +0 -27
  2. package/core/constants.mjs +0 -31
  3. package/core/hexIds.mjs +0 -13
  4. package/crypto/key.mjs +14 -15
  5. package/dag/canonicalize_row.mjs +5 -5
  6. package/dag/index.mjs +0 -73
  7. package/dag/storage.mjs +0 -22
  8. package/discovery/mdns.mjs +4 -4
  9. package/discovery/nostr.mjs +3 -3
  10. package/federation/chunk_fetch_pending.mjs +3 -3
  11. package/federation/chunk_fetch_scheduler.mjs +3 -3
  12. package/federation/dag_order_cache.mjs +3 -3
  13. package/federation/entity_key_chain.mjs +0 -9
  14. package/federation/topo_order_memo.mjs +3 -18
  15. package/files/assemble.mjs +55 -39
  16. package/files/assemble_stream.mjs +96 -44
  17. package/files/chunk_provider_registry.mjs +0 -6
  18. package/files/chunk_responder.mjs +1 -1
  19. package/files/chunk_store.mjs +1 -11
  20. package/files/evfs.mjs +74 -47
  21. package/files/manifest.mjs +11 -2
  22. package/files/manifest_acl_registry.mjs +0 -6
  23. package/files/transfer_key.mjs +21 -15
  24. package/files/transfer_key_registry.mjs +9 -16
  25. package/governance/branch.mjs +0 -11
  26. package/governance/join_pow.mjs +17 -17
  27. package/link/channel_mux.mjs +9 -7
  28. package/link/frame.mjs +5 -5
  29. package/link/handshake.mjs +17 -17
  30. package/link/link.mjs +33 -33
  31. package/mailbox/deliver_or_store.mjs +13 -13
  32. package/mailbox/importance.mjs +0 -33
  33. package/mailbox/settings.mjs +0 -9
  34. package/mailbox/wire.mjs +4 -4
  35. package/node/denylist.mjs +0 -24
  36. package/node/network.mjs +0 -51
  37. package/node/personal_block.mjs +0 -35
  38. package/node/reputation_store.mjs +5 -14
  39. package/node/retention_policy.mjs +8 -23
  40. package/overlay/index.mjs +6 -6
  41. package/package.json +1 -1
  42. package/registries/event_type.mjs +0 -12
  43. package/registries/inbound.mjs +8 -30
  44. package/reputation/engine.mjs +0 -11
  45. package/rooms/scoped_link.mjs +18 -18
  46. package/schemas/part_query.mjs +156 -0
  47. package/timeline/append_core.mjs +3 -3
  48. package/transport/group_link_set.mjs +30 -30
  49. package/transport/ice_servers.mjs +0 -8
  50. package/transport/link_registry.mjs +13 -13
  51. package/transport/peer_identity_maps.mjs +0 -58
  52. package/transport/peer_pool.mjs +4 -4
  53. package/transport/remote_user_room.mjs +0 -12
  54. package/transport/rtc_connection_budget.mjs +2 -0
  55. package/transport/user_room.mjs +13 -24
  56. package/trust_graph/cache.mjs +0 -13
  57. package/trust_graph/engine.mjs +0 -24
  58. package/utils/async_mutex.mjs +0 -9
  59. package/wire/group_part.mjs +3 -3
  60. package/wire/part_fanout.mjs +0 -19
  61. package/wire/part_ingress.mjs +14 -14
  62. package/wire/part_query.mjs +486 -0
  63. package/wire/part_query.tunables.json +14 -0
  64. package/wire/part_query_cache.mjs +101 -0
@@ -34,61 +34,3 @@ export function pruneStaleRosterEntries(peerToNode, nodeToPeer, livePeerIds) {
34
34
  }
35
35
  return stale
36
36
  }
37
-
38
- /**
39
- * 创建 peer id 与 nodeHash 双向映射及 roster 查询辅助。
40
- * @param {object} [opts] 选项
41
- * @param {() => Iterable<string>} [opts.getLivePeerIds] 获取当前在线 peer id 的回调
42
- * @param {(stale: Array<{ peerId: string, remoteNodeHash?: string }>) => void} [opts.onStalePruned] stale 条目被清理时的回调
43
- * @returns {{ peerToNode: Map<string, string>, nodeToPeer: Map<string, string>, getRoster: () => Array<{ peerId: string, remoteNodeHash: string | undefined }>, getPeerIdByNodeHash: (nodeHash: string) => string | null, onPeerLeave: (peerId: string) => void }} 映射与查询接口
44
- */
45
- export function createPeerIdentityMaps(opts = {}) {
46
- /** @type {Map<string, string>} */
47
- const peerToNode = new Map()
48
- /** @type {Map<string, string>} */
49
- const nodeToPeer = new Map()
50
- const getLivePeerIds = typeof opts.getLivePeerIds === 'function' ? opts.getLivePeerIds : null
51
- const onStalePruned = typeof opts.onStalePruned === 'function' ? opts.onStalePruned : null
52
-
53
- /**
54
- * 根据 live peer 集合清理 stale 映射。
55
- * @returns {void}
56
- */
57
- const reconcile = () => {
58
- if (!getLivePeerIds) return
59
- const stale = pruneStaleRosterEntries(peerToNode, nodeToPeer, getLivePeerIds())
60
- if (stale.length && onStalePruned) onStalePruned(stale)
61
- }
62
-
63
- return {
64
- peerToNode,
65
- nodeToPeer,
66
- /**
67
- * 返回当前 roster(会先 reconcile stale 条目)。
68
- * @returns {Array<{ peerId: string, remoteNodeHash: string | undefined }>} roster 列表
69
- */
70
- getRoster() {
71
- reconcile()
72
- return [...peerToNode.entries()].map(([peerId, remoteNodeHash]) => ({ peerId, remoteNodeHash }))
73
- },
74
- /**
75
- * 按 nodeHash 查找对应 peer id。
76
- * @param {string} targetNodeHash 目标节点 64 hex
77
- * @returns {string | null} 对端 id;无映射时为 null
78
- */
79
- getPeerIdByNodeHash(targetNodeHash) {
80
- reconcile()
81
- return nodeToPeer.get(String(targetNodeHash).trim().toLowerCase()) || null
82
- },
83
- /**
84
- * peer 离线时从映射中移除。
85
- * @param {string} peerId 离线的 peer id
86
- * @returns {void}
87
- */
88
- onPeerLeave(peerId) {
89
- const remote = peerToNode.get(peerId)
90
- if (remote) nodeToPeer.delete(remote)
91
- peerToNode.delete(peerId)
92
- },
93
- }
94
- }
@@ -141,7 +141,7 @@ export function selectExploreWithSourceQuota(exploreIds, exploreSources, k, maxP
141
141
  * selfNodeHash: string,
142
142
  * inRoomNodeHashes?: Set<string> | string[] 群内在线 node_id;有则优先,仅全不可达时用 explore 中非房内节点
143
143
  * hintSources?: Map<string, string> explore 节点来源(用于配额)
144
- * }} opts 选取参数(roster、peers、rep、limits、selfNodeHash)
144
+ * }} options 选取参数(roster、peers、rep、limits、selfNodeHash)
145
145
  * @returns {string[]} 目标 Trystero peerId 列表(去重,长度 ≤ maxPeers)
146
146
  */
147
147
  export function selectPeerIdsFromPool({ roster, peers, rep, limits, selfNodeHash, inRoomNodeHashes, hintSources }) {
@@ -212,7 +212,7 @@ export function selectPeerIdsFromPool({ roster, peers, rep, limits, selfNodeHash
212
212
  * peers: { trustedPeers: string[], explorePeers: string[], blockedPeers: string[], hintSources?: Map<string, string> },
213
213
  * limits: ReturnType<typeof resolveFederationPoolLimits>,
214
214
  * anchors?: Iterable<string>,
215
- * }} opts 选取参数(members、selfNodeHash、rep、peers、limits、anchors)
215
+ * }} options 选取参数(members、selfNodeHash、rep、peers、limits、anchors)
216
216
  * @returns {string[]} 应建链的 nodeHash 列表(去重)
217
217
  */
218
218
  export function selectLinkTargetsFromMembers({ members, selfNodeHash, rep, peers, limits, anchors = [] }) {
@@ -245,7 +245,7 @@ export function selectLinkTargetsFromMembers({ members, selfNodeHash, rep, peers
245
245
  * rep: { byNodeHash?: Record<string, { score?: number }> },
246
246
  * hints: string[],
247
247
  * limits: ReturnType<typeof resolveFederationPoolLimits>,
248
- * }} opts 合并参数(peers、rep、hints、limits)
248
+ * }} options 合并参数(peers、rep、hints、limits)
249
249
  * @returns {{ trustedPeers: string[], explorePeers: string[] }} 更新后的 trusted/explore 列表
250
250
  */
251
251
  export function applyPexHints({ peers, rep, hints, limits }) {
@@ -275,7 +275,7 @@ export function applyPexHints({ peers, rep, hints, limits }) {
275
275
  * rep: { byNodeHash?: Record<string, { score?: number }> },
276
276
  * roster: Array<{ remoteNodeHash?: string }>,
277
277
  * limits: ReturnType<typeof resolveFederationPoolLimits>,
278
- * }} opts roster 更新参数(peers、rep、roster、limits)
278
+ * }} options roster 更新参数(peers、rep、roster、limits)
279
279
  * @returns {{ trustedPeers: string[], explorePeers: string[] }} 更新后的 trusted/explore 列表
280
280
  */
281
281
  export function applyRosterToPeerPool({ peers, rep, roster, limits }) {
@@ -95,15 +95,3 @@ export async function ensureRemoteUserRoom(username, targetNodeHash) {
95
95
  inflights.set(key, task)
96
96
  return await task
97
97
  }
98
-
99
- /**
100
- * 释放目标节点的远端用户房间连接。
101
- * @param {string} targetNodeHash 目标节点 64 hex
102
- * @returns {void}
103
- */
104
- export function releaseRemoteUserRoom(targetNodeHash) {
105
- const key = targetNodeHash.toLowerCase()
106
- const slot = slots.get(key)
107
- if (slot) void Promise.resolve(slot.leave()).catch(() => { })
108
- slots.delete(key)
109
- }
@@ -162,6 +162,8 @@ const NON_CRITICAL_FED_ACTIONS = new Set([
162
162
  'fed_manifest_get',
163
163
  'fed_manifest_data',
164
164
  'part_invoke',
165
+ 'part_query_req',
166
+ 'part_query_res',
165
167
  'discovery_announce',
166
168
  'discovery_query',
167
169
  'char_rpc',
@@ -4,6 +4,7 @@ import { attachMailboxWire } from '../mailbox/wire.mjs'
4
4
  import { ensureNodeDefaults, getNodeHash } from '../node/identity.mjs'
5
5
  import { registerFederationRoomProvider } from '../registries/room_provider.mjs'
6
6
  import { attachPartWire } from '../wire/part_ingress.mjs'
7
+ import { attachPartQueryWire } from '../wire/part_query.mjs'
7
8
 
8
9
  import { listLinks, sendToNodeLink, subscribeScope, getLinkRegistry } from './link_registry.mjs'
9
10
  import { USER_ROOM_SCOPE } from './room_scopes.mjs'
@@ -90,12 +91,12 @@ function activeLinkRoster() {
90
91
 
91
92
  /**
92
93
  * 初始化 node scope 订阅与 wire 派发(幂等)。
93
- * @param {{ replicaUsername?: string }} ctx 入站上下文
94
+ * @param {{ replicaUsername?: string }} wireContext 入站上下文
94
95
  * @returns {Promise<void>}
95
96
  */
96
- async function ensureNodeScopeRuntime(ctx) {
97
+ async function ensureNodeScopeRuntime(wireContext) {
97
98
  if (nodeScopeCleanup) return
98
- nodeScopeReplicaUsername = String(ctx.replicaUsername || nodeScopeReplicaUsername || '')
99
+ nodeScopeReplicaUsername = String(wireContext.replicaUsername || nodeScopeReplicaUsername || '')
99
100
  nodeScopeCleanup = subscribeScope('node', (senderNodeHash, envelope) => {
100
101
  const handlers = nodeActionHandlers.get(String(envelope?.action || ''))
101
102
  if (!handlers?.size) return
@@ -104,11 +105,12 @@ async function ensureNodeScopeRuntime(ctx) {
104
105
  })
105
106
  const wire = createNodeScopeWire()
106
107
  nodeScopeWire = wire
107
- attachPartWire({ replicaUsername: ctx.replicaUsername }, wire)
108
- attachMailboxWire({ replicaUsername: ctx.replicaUsername }, wire)
109
- attachUserRoomChunkHandlers(ctx.replicaUsername || '', wire)
108
+ attachPartWire({ replicaUsername: wireContext.replicaUsername }, wire)
109
+ attachPartQueryWire({ replicaUsername: wireContext.replicaUsername }, wire)
110
+ attachMailboxWire({ replicaUsername: wireContext.replicaUsername }, wire)
111
+ attachUserRoomChunkHandlers(wireContext.replicaUsername || '', wire)
110
112
  for (const hook of nodeScopeWireHooks)
111
- try { hook(ctx.replicaUsername || '', wire) } catch { /* ignore */ }
113
+ try { hook(wireContext.replicaUsername || '', wire) } catch { /* ignore */ }
112
114
  }
113
115
 
114
116
  /**
@@ -160,10 +162,10 @@ export function resolveUserRoomCredentials() {
160
162
  }
161
163
 
162
164
  /**
163
- * @param {{ replicaUsername?: string }} [ctx] 入站上下文(part/mailbox 派发用)
165
+ * @param {{ replicaUsername?: string }} [wireContext] 入站上下文(part/mailbox 派发用)
164
166
  * @returns {Promise<UserRoomSlot | null>} 用户级联邦房间槽
165
167
  */
166
- export async function ensureUserRoom(ctx = {}) {
168
+ export async function ensureUserRoom(wireContext = {}) {
167
169
  if (userRoomSlot) return userRoomSlot
168
170
  if (userRoomInflight) return await userRoomInflight
169
171
 
@@ -171,7 +173,7 @@ export async function ensureUserRoom(ctx = {}) {
171
173
  ensureNodeDefaults()
172
174
  try {
173
175
  await getLinkRegistry().ensureRuntime()
174
- await ensureNodeScopeRuntime(ctx)
176
+ await ensureNodeScopeRuntime(wireContext)
175
177
  const creds = resolveUserRoomCredentials()
176
178
  /** @type {UserRoomSlot} */
177
179
  userRoomSlot = {
@@ -217,17 +219,6 @@ export async function ensureUserRoom(ctx = {}) {
217
219
  return await userRoomInflight
218
220
  }
219
221
 
220
- /**
221
- * @returns {void}
222
- */
223
- export function invalidateUserRoom() {
224
- userRoomSlot = null
225
- userRoomInflight = null
226
- nodeScopeWire = null
227
- nodeScopeReplicaUsername = ''
228
- nodeScopeCleanup = null
229
- }
230
-
231
222
  /**
232
223
  * @param {string} username 副本用户名
233
224
  * @param {string} actionName 节点 scope action
@@ -247,9 +238,7 @@ export async function deliverToUserRoomPeers(username, actionName, payload, exce
247
238
  .filter(({ peerId }) => peerId && peerId !== exceptPeerId)]
248
239
  for (let swapIndex = peers.length - 1; swapIndex > 0; swapIndex--) {
249
240
  const pickIndex = Math.floor(Math.random() * (swapIndex + 1))
250
- const tmp = peers[swapIndex]
251
- peers[swapIndex] = peers[pickIndex]
252
- peers[pickIndex] = tmp
241
+ ;[peers[swapIndex], peers[pickIndex]] = [peers[pickIndex], peers[swapIndex]]
253
242
  }
254
243
  for (const { peerId } of peers)
255
244
  try {
@@ -4,13 +4,6 @@ let revision = 0
4
4
 
5
5
  const DEFAULT_TTL_MS = 30_000
6
6
 
7
- /**
8
- * @returns {number} 当前 revision
9
- */
10
- export function getTrustGraphRevision() {
11
- return revision
12
- }
13
-
14
7
  /**
15
8
  * @returns {void}
16
9
  */
@@ -36,9 +29,3 @@ export async function getCachedTrustGraph(username, build, ttlMs = DEFAULT_TTL_M
36
29
  cacheByUsername.set(key, { graph, builtAt: now, revision })
37
30
  return graph
38
31
  }
39
-
40
- /** @returns {void} 测试用 */
41
- export function clearTrustGraphCache() {
42
- cacheByUsername.clear()
43
- revision = 0
44
- }
@@ -17,30 +17,6 @@ import trustGraphTunables from './tunables.json' with { type: 'json' }
17
17
  * }} TrustGraphInputs
18
18
  */
19
19
 
20
- /**
21
- * @returns {typeof trustGraphTunables} 默认 tunables
22
- */
23
- export function defaultTrustGraphTunables() {
24
- return trustGraphTunables
25
- }
26
-
27
- /**
28
- * @param {Map<string, TrustNode>} byNode 累积图
29
- * @param {string} scopeId scope 标识
30
- * @param {string} nodeHash 64 位十六进制
31
- * @param {number} score 信誉分
32
- */
33
- export function mergeTrustNode(byNode, scopeId, nodeHash, score) {
34
- const previous = byNode.get(nodeHash)
35
- if (previous) {
36
- const seenCount = previous.scopeIds.length
37
- previous.score = (previous.score * seenCount + score) / (seenCount + 1)
38
- if (!previous.scopeIds.includes(scopeId)) previous.scopeIds.push(scopeId)
39
- return
40
- }
41
- byNode.set(nodeHash, { nodeHash, score, scopeIds: [scopeId] })
42
- }
43
-
44
20
  /**
45
21
  * @param {TrustGraphInputs} inputs 图输入
46
22
  * @param {typeof trustGraphTunables} [tunables] tunables
@@ -58,12 +58,3 @@ export async function withAsyncMutex(key, fn) {
58
58
  }
59
59
  })
60
60
  }
61
-
62
- /**
63
- * @param {string} keyPrefix 前缀
64
- * @returns {(key: string, fn: () => Promise<T>) => Promise<T>} 带前缀的 mutex 函数
65
- * @template T
66
- */
67
- export function asyncMutexForPrefix(keyPrefix) {
68
- return (key, fn) => withAsyncMutex(`${keyPrefix}:${key}`, fn)
69
- }
@@ -29,14 +29,14 @@ function wrapWireOn(wire, groupId) {
29
29
 
30
30
  /**
31
31
  * 群联邦房间挂载 part_wire(要求线载荷带 `groupId`)。
32
- * @param {{ replicaUsername?: string }} ctx 入站上下文
32
+ * @param {{ replicaUsername?: string }} wireContext 入站上下文
33
33
  * @param {string} groupId 群 ID
34
34
  * @param {import('./part_ingress.mjs').PartWireAdapter} wire Trystero 适配器
35
35
  * @param {{ allowPartInvoke?: (payload: object) => boolean }} [options] 入站过滤
36
36
  * @returns {void}
37
37
  */
38
- export function attachGroupPartWire(ctx, groupId, wire, options = {}) {
39
- attachPartWire(ctx, {
38
+ export function attachGroupPartWire(wireContext, groupId, wire, options = {}) {
39
+ attachPartWire(wireContext, {
40
40
  send: wire.send.bind(wire),
41
41
  on: wrapWireOn(wire, groupId),
42
42
  }, options)
@@ -50,22 +50,3 @@ export async function collectPartInvokeResponses(username, partpath, invoke, tim
50
50
 
51
51
  return waitForResponses
52
52
  }
53
-
54
- /**
55
- * 单向 part_invoke fanout(mailbox put 等)。
56
- * @param {string} username 用户
57
- * @param {string} partpath part 路径
58
- * @param {import('./part_invoke.mjs').PartInvoke} invoke 调用体
59
- * @param {number} limit fanout 上限
60
- * @param {string} [nodeHash] 来源节点
61
- * @param {string} [groupId] 群上下文
62
- * @returns {Promise<number>} 发送次数
63
- */
64
- export async function fanoutPartInvoke(username, partpath, invoke, limit, nodeHash, groupId) {
65
- return requireTrustGraphProvider(DEFAULT_TRUST_GRAPH_OWNER).fanoutToTopNodes(username, 'part_invoke', buildPartInvokePayload({
66
- partpath,
67
- invoke,
68
- nodeHash,
69
- groupId,
70
- }), limit)
71
- }
@@ -45,16 +45,16 @@ function parsePartTimelinePut(data, partpath) {
45
45
  }
46
46
 
47
47
  /**
48
- * @param {PartWireContext} ctx 入站上下文
48
+ * @param {PartWireContext} wireContext 入站上下文
49
49
  * @param {object} payload part_invoke 请求
50
50
  * @returns {Promise<PartInvokeResponse | null>} RPC 处理器返回值
51
51
  */
52
- async function dispatchPartInvoke(ctx, payload) {
52
+ async function dispatchPartInvoke(wireContext, payload) {
53
53
  const partpath = normalizePartpath(payload?.partpath)
54
54
  const invoke = payload?.invoke
55
55
  if (!partpath || !isPlainObject(invoke)) return null
56
56
  return dispatchRpcInbound({
57
- replicaUsername: ctx.replicaUsername,
57
+ replicaUsername: wireContext.replicaUsername,
58
58
  requesterNodeHash: payload.nodeHash ? String(payload.nodeHash).trim() : null,
59
59
  groupId: payload.groupId ? String(payload.groupId).trim() : undefined,
60
60
  peerId: payload.peerId,
@@ -70,12 +70,12 @@ async function dispatchPartInvoke(ctx, payload) {
70
70
 
71
71
  /**
72
72
  * 挂载 part_timeline_put / part_invoke / part_invoke_response。
73
- * @param {PartWireContext} ctx 入站上下文
73
+ * @param {PartWireContext} wireContext 入站上下文
74
74
  * @param {PartWireAdapter} wire Trystero 适配器
75
75
  * @param {{ allowPartInvoke?: (payload: object) => boolean }} [options] 入站过滤
76
76
  * @returns {void}
77
77
  */
78
- export function attachPartWire(ctx, wire, options = {}) {
78
+ export function attachPartWire(wireContext, wire, options = {}) {
79
79
  wire.on('part_timeline_put', data => {
80
80
  if (!isPlainObject(data)) return
81
81
  const partpath = normalizePartpath(data.partpath)
@@ -83,7 +83,7 @@ export function attachPartWire(ctx, wire, options = {}) {
83
83
  const message = parsePartTimelinePut(data, partpath)
84
84
  if (!message) return
85
85
  void dispatchDeliveryInbound({
86
- replicaUsername: ctx.replicaUsername,
86
+ replicaUsername: wireContext.replicaUsername,
87
87
  requesterNodeHash: data.nodeHash ? String(data.nodeHash).trim() : null,
88
88
  }, message)
89
89
  })
@@ -93,9 +93,9 @@ export function attachPartWire(ctx, wire, options = {}) {
93
93
  if (options.allowPartInvoke?.(data) === false) return
94
94
  const payload = { ...data, peerId }
95
95
  if (payload.requestId)
96
- void handleIncomingPartInvokeRequest(ctx, payload, wire, peerId)
96
+ void handleIncomingPartInvokeRequest(wireContext, payload, wire, peerId)
97
97
  else
98
- void handleIncomingPartInvokeFireAndForget(ctx, payload, wire, peerId)
98
+ void handleIncomingPartInvokeFireAndForget(wireContext, payload, wire, peerId)
99
99
  })
100
100
 
101
101
  wire.on('part_invoke_response', (data, peerId) => {
@@ -105,17 +105,17 @@ export function attachPartWire(ctx, wire, options = {}) {
105
105
  }
106
106
 
107
107
  /**
108
- * @param {PartWireContext} ctx 入站上下文
108
+ * @param {PartWireContext} wireContext 入站上下文
109
109
  * @param {object} payload part_invoke 请求(含 requestId)
110
110
  * @param {PartWireAdapter} wire 发送适配器
111
111
  * @param {string} peerId 对端
112
112
  * @returns {Promise<void>}
113
113
  */
114
- export async function handleIncomingPartInvokeRequest(ctx, payload, wire, peerId) {
114
+ export async function handleIncomingPartInvokeRequest(wireContext, payload, wire, peerId) {
115
115
  const partpath = normalizePartpath(payload?.partpath)
116
116
  if (!partpath || !payload.requestId) return
117
117
 
118
- const response = await dispatchPartInvoke(ctx, { ...payload, peerId })
118
+ const response = await dispatchPartInvoke(wireContext, { ...payload, peerId })
119
119
  if (response == null || !isPartInvokeResponse(response)) return
120
120
 
121
121
  try {
@@ -129,17 +129,17 @@ export async function handleIncomingPartInvokeRequest(ctx, payload, wire, peerId
129
129
  }
130
130
 
131
131
  /**
132
- * @param {PartWireContext} ctx 入站上下文
132
+ * @param {PartWireContext} wireContext 入站上下文
133
133
  * @param {object} payload part_invoke 请求(无 requestId)
134
134
  * @param {PartWireAdapter} wire 发送适配器
135
135
  * @param {string} peerId 对端
136
136
  * @returns {Promise<void>}
137
137
  */
138
- export async function handleIncomingPartInvokeFireAndForget(ctx, payload, wire, peerId) {
138
+ export async function handleIncomingPartInvokeFireAndForget(wireContext, payload, wire, peerId) {
139
139
  const partpath = normalizePartpath(payload?.partpath)
140
140
  if (!partpath) return
141
141
 
142
- const response = await dispatchPartInvoke(ctx, { ...payload, peerId })
142
+ const response = await dispatchPartInvoke(wireContext, { ...payload, peerId })
143
143
  const followUp = unwrapPartInvokeResult(response)
144
144
  if (!isPartInvoke(followUp)) return
145
145
  try {