@unicitylabs/openclaw-unicity 0.5.7 → 0.5.9
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/package.json +3 -3
- package/src/channel.ts +27 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unicitylabs/openclaw-unicity",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.9",
|
|
4
4
|
"description": "Unicity wallet identity and encrypted DMs for OpenClaw agents — powered by Sphere SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -44,13 +44,13 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@clack/prompts": "^0.10.0",
|
|
46
46
|
"@sinclair/typebox": "^0.34.48",
|
|
47
|
-
"@unicitylabs/sphere-sdk": "0.6.8-dev.
|
|
47
|
+
"@unicitylabs/sphere-sdk": "0.6.8-dev.3"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"openclaw": "*"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"openclaw": "^2026.3.
|
|
53
|
+
"openclaw": "^2026.3.13",
|
|
54
54
|
"oxlint": "^1.43.0",
|
|
55
55
|
"vitest": "^4.0.18"
|
|
56
56
|
},
|
package/src/channel.ts
CHANGED
|
@@ -103,6 +103,8 @@ let activeSphere: Sphere | null = null;
|
|
|
103
103
|
let pluginRuntime: PluginRuntime | null = null;
|
|
104
104
|
let ownerIdentity: string | null = null;
|
|
105
105
|
let pluginConfig: UnicityConfig = {};
|
|
106
|
+
/** Cleanup function from the previous gateway start — called before re-subscribing. */
|
|
107
|
+
let previousGatewayCleanup: (() => void) | null = null;
|
|
106
108
|
|
|
107
109
|
export function setUnicityRuntime(rt: PluginRuntime): void {
|
|
108
110
|
pluginRuntime = rt;
|
|
@@ -223,6 +225,14 @@ export const unicityChannelPlugin = {
|
|
|
223
225
|
log?: { info: (m: string) => void; warn: (m: string) => void; error: (m: string) => void; debug: (m: string) => void };
|
|
224
226
|
setStatus: (s: Record<string, unknown>) => void;
|
|
225
227
|
}) => {
|
|
228
|
+
// Clean up handlers from any previous gateway start (auto-restart scenario).
|
|
229
|
+
// Without this, each restart stacks duplicate onDirectMessage handlers on the
|
|
230
|
+
// shared Sphere singleton, causing messages to be processed N times.
|
|
231
|
+
if (previousGatewayCleanup) {
|
|
232
|
+
previousGatewayCleanup();
|
|
233
|
+
previousGatewayCleanup = null;
|
|
234
|
+
}
|
|
235
|
+
|
|
226
236
|
const sphere = activeSphere ?? await waitForSphere();
|
|
227
237
|
if (!sphere) throw new Error("Unicity Sphere not initialized — run `openclaw unicity init`");
|
|
228
238
|
|
|
@@ -233,6 +243,7 @@ export const unicityChannelPlugin = {
|
|
|
233
243
|
publicKey: sphere.identity?.chainPubkey,
|
|
234
244
|
nametag: sphere.identity?.nametag,
|
|
235
245
|
running: true,
|
|
246
|
+
connected: true,
|
|
236
247
|
lastStartAt: Date.now(),
|
|
237
248
|
});
|
|
238
249
|
|
|
@@ -277,6 +288,7 @@ export const unicityChannelPlugin = {
|
|
|
277
288
|
|
|
278
289
|
function dispatchDm(msg: DmMsg): void {
|
|
279
290
|
sendersInFlight.add(msg.senderPubkey);
|
|
291
|
+
ctx.setStatus({ lastEventAt: Date.now() });
|
|
280
292
|
|
|
281
293
|
// Immediately signal that we're composing a reply
|
|
282
294
|
sphere.communications.sendComposingIndicator(msg.senderPubkey)
|
|
@@ -402,6 +414,7 @@ export const unicityChannelPlugin = {
|
|
|
402
414
|
|
|
403
415
|
// Subscribe to incoming token transfers
|
|
404
416
|
const unsubTransfer = sphere.on("transfer:incoming", (transfer) => {
|
|
417
|
+
ctx.setStatus({ lastEventAt: Date.now() });
|
|
405
418
|
// Full address for DM replies; short form for display/logging only
|
|
406
419
|
const replyTo = transfer.senderNametag ? `@${transfer.senderNametag}` : transfer.senderPubkey;
|
|
407
420
|
const displayName = transfer.senderNametag ? `@${transfer.senderNametag}` : transfer.senderPubkey.slice(0, 12) + "…";
|
|
@@ -464,6 +477,7 @@ export const unicityChannelPlugin = {
|
|
|
464
477
|
|
|
465
478
|
// Subscribe to incoming payment requests
|
|
466
479
|
const unsubPaymentRequest = sphere.on("payment_request:incoming", (request) => {
|
|
480
|
+
ctx.setStatus({ lastEventAt: Date.now() });
|
|
467
481
|
const replyTo = request.senderNametag ? `@${request.senderNametag}` : request.senderPubkey;
|
|
468
482
|
const displayName = request.senderNametag ? `@${request.senderNametag}` : request.senderPubkey.slice(0, 12) + "…";
|
|
469
483
|
const decimals = getCoinDecimals(request.coinId) ?? 0;
|
|
@@ -618,6 +632,7 @@ export const unicityChannelPlugin = {
|
|
|
618
632
|
|
|
619
633
|
// Subscribe to incoming group messages
|
|
620
634
|
const unsubGroupMessage = sphere.groupChat?.onMessage?.((msg: GroupMsg) => {
|
|
635
|
+
ctx.setStatus({ lastEventAt: Date.now() });
|
|
621
636
|
// Skip messages from self (echoed back by the relay).
|
|
622
637
|
// Compare against the Nostr x-only pubkey, not chainPubkey.
|
|
623
638
|
if (myNostrPubkey && msg.senderPubkey === myNostrPubkey) return;
|
|
@@ -692,7 +707,7 @@ export const unicityChannelPlugin = {
|
|
|
692
707
|
groupBackfillStates.clear();
|
|
693
708
|
}
|
|
694
709
|
|
|
695
|
-
|
|
710
|
+
function cleanupSubscriptions(): void {
|
|
696
711
|
clearBackfillTimers();
|
|
697
712
|
unsub();
|
|
698
713
|
unsubTransfer();
|
|
@@ -701,18 +716,21 @@ export const unicityChannelPlugin = {
|
|
|
701
716
|
unsubGroupJoined();
|
|
702
717
|
unsubGroupLeft();
|
|
703
718
|
unsubGroupKicked();
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// Store cleanup so auto-restart can tear down stale handlers
|
|
722
|
+
previousGatewayCleanup = cleanupSubscriptions;
|
|
723
|
+
|
|
724
|
+
ctx.abortSignal.addEventListener("abort", () => {
|
|
725
|
+
cleanupSubscriptions();
|
|
726
|
+
previousGatewayCleanup = null;
|
|
704
727
|
}, { once: true });
|
|
705
728
|
|
|
706
729
|
return {
|
|
707
730
|
stop: () => {
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
unsubPaymentRequest();
|
|
712
|
-
unsubGroupMessage();
|
|
713
|
-
unsubGroupJoined();
|
|
714
|
-
unsubGroupLeft();
|
|
715
|
-
unsubGroupKicked();
|
|
731
|
+
cleanupSubscriptions();
|
|
732
|
+
previousGatewayCleanup = null;
|
|
733
|
+
ctx.setStatus({ connected: false, running: false });
|
|
716
734
|
ctx.log?.info(`[${ctx.account.accountId}] Unicity channel stopped`);
|
|
717
735
|
},
|
|
718
736
|
};
|