@xmanrui/dsh-im 4.19.0 → 4.19.1

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.
@@ -1,34 +1,22 @@
1
- /**
2
- * Session-sync ownership registry: records which delivery targets of a
3
- * session are being mirrored as process cards by their owning bridge.
4
- *
5
- * The plain-text session-sync coordinator and the per-bridge card mirror
6
- * observe the same global session events. When a bridge mirrors a turn to a
7
- * specific target, the coordinator must suppress the plain-text delivery for
8
- * THAT target only — other targets (same or other channels) still receive
9
- * their normal text. Both sides live in the same Host process, so a
10
- * module-level registry is the whole contract: the mirror claims a target
11
- * when it opens the mirror card and releases it when the turn ends.
12
- */
13
- const claimed = new Map();
1
+ /** Optional per-bot card delivery. A registration is not a delivery receipt:
2
+ * the coordinator must await the renderer before suppressing final text. */
3
+ const renderers = new Map();
14
4
 
15
- function keyOf(sessionId, targetId) {
16
- return `${sessionId}\0${targetId ?? ''}`;
5
+ function botKey({ channel, botId }) {
6
+ return JSON.stringify([channel, botId]);
17
7
  }
18
8
 
19
- export function claimSessionSyncMirror(sessionId, targetId = '', turn = null) {
20
- if (typeof sessionId !== 'string' || !sessionId) return;
21
- claimed.set(keyOf(sessionId, targetId), { turn, claimedAt: Date.now() });
9
+ export function registerSessionSyncMirror(target, render) {
10
+ const key = botKey(target);
11
+ const entry = { render };
12
+ renderers.set(key, entry);
13
+ return () => {
14
+ if (renderers.get(key) === entry) renderers.delete(key);
15
+ };
22
16
  }
23
17
 
24
- export function releaseSessionSyncMirror(sessionId, targetId = '') {
25
- claimed.delete(keyOf(sessionId, targetId));
26
- }
27
-
28
- /** True when a live mirror claim covers this session and target. */
29
- export function isSessionSyncMirrored(sessionId, targetId = '', turn = null) {
30
- const claim = claimed.get(keyOf(sessionId, targetId));
31
- if (!claim) return false;
32
- if (turn !== null && claim.turn !== null && claim.turn !== turn) return false;
33
- return true;
18
+ export async function deliverSessionSyncMirror(target, sessionId, turn, text) {
19
+ const entry = renderers.get(botKey(target));
20
+ if (!entry) return false;
21
+ return await entry.render({ target, sessionId, turn, text }) === true;
34
22
  }