openclaw-mobile 1.1.1 → 1.1.3
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/index.ts +52 -41
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
package/index.ts
CHANGED
|
@@ -576,7 +576,17 @@ async function handleRelayMessage(ctx: any, accountId: string, state: RelayState
|
|
|
576
576
|
ctx.log?.info?.(`[${CHANNEL_ID}] [${accountId}] [E2E] Session ${sessionKey} reconnected, resetting E2E state`);
|
|
577
577
|
}
|
|
578
578
|
|
|
579
|
-
|
|
579
|
+
const sessionE2E = makeE2EState();
|
|
580
|
+
state.e2eSessions.set(sessionKey, sessionE2E);
|
|
581
|
+
|
|
582
|
+
const handshakeMsg = await e2eInit(sessionE2E);
|
|
583
|
+
|
|
584
|
+
// sessionKey를 포함시켜 relay가 올바른 app으로 라우팅하도록 함
|
|
585
|
+
const handshakeWithSession = JSON.stringify({ ...JSON.parse(handshakeMsg), sessionKey });
|
|
586
|
+
|
|
587
|
+
if (state.ws?.readyState === WebSocket.OPEN) {
|
|
588
|
+
state.ws.send(handshakeWithSession);
|
|
589
|
+
}
|
|
580
590
|
return;
|
|
581
591
|
}
|
|
582
592
|
|
|
@@ -591,15 +601,21 @@ async function handleRelayMessage(ctx: any, accountId: string, state: RelayState
|
|
|
591
601
|
let sessionE2E = state.e2eSessions.get(sessionKey);
|
|
592
602
|
if (!sessionE2E) {
|
|
593
603
|
// peer_joined 없이 app이 먼저 handshake를 보낸 경우 (예: plugin 재연결)
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
604
|
+
// 새 세션을 만들고 plugin의 pubkey를 먼저 전송한 후 ECDH 완성
|
|
605
|
+
sessionE2E = makeE2EState();
|
|
606
|
+
state.e2eSessions.set(sessionKey, sessionE2E);
|
|
607
|
+
const handshakeMsg = await e2eInit(sessionE2E);
|
|
608
|
+
const handshakeWithSession = JSON.stringify({ ...JSON.parse(handshakeMsg), sessionKey });
|
|
609
|
+
if (state.ws?.readyState === WebSocket.OPEN) {
|
|
610
|
+
state.ws.send(handshakeWithSession);
|
|
611
|
+
ctx.log?.info?.(`[${CHANNEL_ID}] [${accountId}] [E2E] Session ${sessionKey} — sent handshake (reactive, no prior peer_joined)`);
|
|
612
|
+
}
|
|
597
613
|
}
|
|
598
|
-
if (sessionE2E
|
|
614
|
+
if (sessionE2E.ready) {
|
|
599
615
|
ctx.log?.info?.(`[${CHANNEL_ID}] [${accountId}] [E2E] Session ${sessionKey} already ready, ignoring duplicate handshake`);
|
|
600
616
|
return;
|
|
601
617
|
}
|
|
602
|
-
if (!sessionE2E
|
|
618
|
+
if (!sessionE2E.localKeyPair) {
|
|
603
619
|
ctx.log?.warn?.(`[${CHANNEL_ID}] [${accountId}] [E2E] Session ${sessionKey} has no local keypair yet, dropping handshake`);
|
|
604
620
|
return;
|
|
605
621
|
}
|
|
@@ -622,9 +638,9 @@ async function handleRelayMessage(ctx: any, accountId: string, state: RelayState
|
|
|
622
638
|
}
|
|
623
639
|
const plaintext = await e2eDecrypt(sessionE2E, msg.nonce, msg.ct);
|
|
624
640
|
ctx.log?.info?.(`[${CHANNEL_ID}] [${accountId}] [E2E] Session ${sessionKey} decrypted: ${plaintext.slice(0, 200)}`);
|
|
625
|
-
|
|
626
641
|
const innerMsg = JSON.parse(plaintext);
|
|
627
|
-
innerMsg._connSessionKey = sessionKey;
|
|
642
|
+
innerMsg._connSessionKey = sessionKey; // routing key
|
|
643
|
+
if (!innerMsg.sessionKey) innerMsg.sessionKey = sessionKey;
|
|
628
644
|
await handleInbound(ctx, accountId, innerMsg);
|
|
629
645
|
return;
|
|
630
646
|
}
|
|
@@ -634,18 +650,6 @@ async function handleRelayMessage(ctx: any, accountId: string, state: RelayState
|
|
|
634
650
|
await handleInbound(ctx, accountId, msg);
|
|
635
651
|
}
|
|
636
652
|
|
|
637
|
-
async function initiateHandshake(ctx: any, state: RelayState, sessionKey: string, accountId: string): Promise<void> {
|
|
638
|
-
const sessionE2E = makeE2EState();
|
|
639
|
-
state.e2eSessions.set(sessionKey, sessionE2E);
|
|
640
|
-
|
|
641
|
-
const handshakeMsg = await e2eInit(sessionE2E);
|
|
642
|
-
const handshakeWithSession = JSON.stringify({ ...JSON.parse(handshakeMsg), sessionKey });
|
|
643
|
-
|
|
644
|
-
if (state.ws?.readyState === WebSocket.OPEN) {
|
|
645
|
-
state.ws.send(handshakeWithSession);
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
|
|
649
653
|
async function handleInbound(ctx: any, accountId: string, msg: any) {
|
|
650
654
|
ctx.log?.info?.(`[${CHANNEL_ID}] [${accountId}] handleInbound: type=${msg.type} content=${String(msg.content ?? "").slice(0, 100)}`);
|
|
651
655
|
|
|
@@ -679,7 +683,7 @@ async function handleInbound(ctx: any, accountId: string, msg: any) {
|
|
|
679
683
|
|
|
680
684
|
let sessionKey: string;
|
|
681
685
|
const appSessionKey = msg.sessionKey ? String(msg.sessionKey) : null;
|
|
682
|
-
const
|
|
686
|
+
const connSessionKey = msg._connSessionKey ? String(msg._connSessionKey) : appSessionKey;
|
|
683
687
|
|
|
684
688
|
if (appSessionKey) {
|
|
685
689
|
const mainKey = route.mainSessionKey as string;
|
|
@@ -689,7 +693,6 @@ async function handleInbound(ctx: any, accountId: string, msg: any) {
|
|
|
689
693
|
} else {
|
|
690
694
|
sessionKey = route.mainSessionKey;
|
|
691
695
|
}
|
|
692
|
-
|
|
693
696
|
const from = `${CHANNEL_ID}:${senderId}`;
|
|
694
697
|
const to = `user:${senderId}`;
|
|
695
698
|
|
|
@@ -753,32 +756,40 @@ async function handleInbound(ctx: any, accountId: string, msg: any) {
|
|
|
753
756
|
const chunkMode = runtime.channel.text.resolveChunkMode(cfg, CHANNEL_ID, accountId);
|
|
754
757
|
const chunks = runtime.channel.text.chunkMarkdownTextWithMode(replyText, textLimit, chunkMode);
|
|
755
758
|
|
|
756
|
-
// Since routingSessionKey maps 1:1 to the App's session ID:
|
|
757
|
-
const sessionE2E = routingSessionKey ? relayState.e2eSessions.get(routingSessionKey) : undefined;
|
|
758
759
|
const replySessionKey = appSessionKey ?? sessionKey;
|
|
760
|
+
const routingSessionKey = connSessionKey ?? sessionKey;
|
|
761
|
+
const sessionE2E = relayState.e2eSessions.get(routingSessionKey);
|
|
759
762
|
|
|
760
763
|
for (const chunk of chunks.length > 0 ? chunks : [replyText]) {
|
|
761
764
|
if (!chunk) continue;
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
}
|
|
765
|
+
|
|
766
|
+
let outMsg;
|
|
767
|
+
if (sessionE2E?.ready) {
|
|
768
|
+
const plainMsg = JSON.stringify({
|
|
769
|
+
type: "message",
|
|
770
|
+
role: "assistant",
|
|
771
|
+
content: chunk,
|
|
772
|
+
sessionKey: replySessionKey,
|
|
773
|
+
});
|
|
774
|
+
outMsg = await e2eEncrypt(sessionE2E, plainMsg);
|
|
775
|
+
try {
|
|
776
|
+
const parsedOut = JSON.parse(outMsg);
|
|
777
|
+
parsedOut.sessionKey = routingSessionKey;
|
|
778
|
+
outMsg = JSON.stringify(parsedOut);
|
|
779
|
+
} catch { }
|
|
780
|
+
} else {
|
|
781
|
+
outMsg = JSON.stringify({
|
|
782
|
+
type: "message",
|
|
783
|
+
role: "assistant",
|
|
784
|
+
content: chunk,
|
|
785
|
+
appSessionKey: replySessionKey,
|
|
786
|
+
sessionKey: routingSessionKey,
|
|
787
|
+
});
|
|
788
|
+
}
|
|
778
789
|
|
|
779
790
|
relayState.ws.send(outMsg);
|
|
780
791
|
}
|
|
781
|
-
ctx.log?.info?.(`[${CHANNEL_ID}] [${accountId}] Reply delivered (${replyText.length} chars) to
|
|
792
|
+
ctx.log?.info?.(`[${CHANNEL_ID}] [${accountId}] Reply delivered (${replyText.length} chars) to sessionKey=${replySessionKey}`);
|
|
782
793
|
},
|
|
783
794
|
onError: (err: any, info: any) => {
|
|
784
795
|
ctx.log?.error?.(`[${CHANNEL_ID}] [${accountId}] Reply dispatch error (${info?.kind}): ${err}`);
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-mobile",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "OpenClaw Mobile channel plugin — relay bridge for the OpenClaw Mobile app",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -28,4 +28,4 @@
|
|
|
28
28
|
"optional": true
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
}
|
|
31
|
+
}
|