@silicaclaw/cli 2026.3.20-12 → 2026.3.20-13
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/CHANGELOG.md +6 -0
- package/VERSION +1 -1
- package/apps/local-console/dist/apps/local-console/src/server.d.ts +2 -1
- package/apps/local-console/dist/apps/local-console/src/server.js +50 -10
- package/apps/local-console/public/app/app.js +8 -1
- package/apps/local-console/src/server.ts +49 -11
- package/openclaw-skills/silicaclaw-broadcast/VERSION +1 -1
- package/openclaw-skills/silicaclaw-broadcast/manifest.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## v1.0 beta - 2026-03-20
|
|
4
4
|
|
|
5
|
+
### 2026.3.20-13
|
|
6
|
+
|
|
7
|
+
- release build:
|
|
8
|
+
- prepared another fresh latest-channel package build without publishing
|
|
9
|
+
- regenerated the npm tarball through the verified release packing workflow
|
|
10
|
+
|
|
5
11
|
### 2026.3.20-12
|
|
6
12
|
|
|
7
13
|
- release build:
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v2026.3.20-
|
|
1
|
+
v2026.3.20-13
|
|
@@ -38,7 +38,7 @@ type PrivateMessageView = {
|
|
|
38
38
|
body: string;
|
|
39
39
|
created_at: number;
|
|
40
40
|
is_self: boolean;
|
|
41
|
-
delivery_status: "sent" | "received" | "read";
|
|
41
|
+
delivery_status: "sent" | "direct-sent" | "fallback-sent" | "received" | "read";
|
|
42
42
|
};
|
|
43
43
|
type RuntimeMessageGovernance = SocialMessageGovernanceConfig;
|
|
44
44
|
type OpenClawBridgeStatus = {
|
|
@@ -181,6 +181,7 @@ export declare class LocalNodeService {
|
|
|
181
181
|
private privateEncryptionKeyPair;
|
|
182
182
|
private privatePeerRoutes;
|
|
183
183
|
private privateMessageBodyCache;
|
|
184
|
+
private privateMessageDeliveryStatusCache;
|
|
184
185
|
private messageGovernance;
|
|
185
186
|
private privateMessagesPersistDirty;
|
|
186
187
|
private privateMessageReceiptsPersistDirty;
|
|
@@ -787,6 +787,7 @@ class LocalNodeService {
|
|
|
787
787
|
privateEncryptionKeyPair = null;
|
|
788
788
|
privatePeerRoutes = {};
|
|
789
789
|
privateMessageBodyCache = new Map();
|
|
790
|
+
privateMessageDeliveryStatusCache = new Map();
|
|
790
791
|
messageGovernance;
|
|
791
792
|
privateMessagesPersistDirty = false;
|
|
792
793
|
privateMessageReceiptsPersistDirty = false;
|
|
@@ -1674,7 +1675,9 @@ class LocalNodeService {
|
|
|
1674
1675
|
body: this.decryptPrivateMessageBody(message),
|
|
1675
1676
|
created_at: message.created_at,
|
|
1676
1677
|
is_self: message.from_agent_id === this.identity?.agent_id,
|
|
1677
|
-
delivery_status: receiptsByMessageId.get(message.message_id) ||
|
|
1678
|
+
delivery_status: receiptsByMessageId.get(message.message_id) ||
|
|
1679
|
+
this.privateMessageDeliveryStatusCache.get(message.message_id) ||
|
|
1680
|
+
(message.from_agent_id === this.identity?.agent_id ? "fallback-sent" : "sent"),
|
|
1678
1681
|
}));
|
|
1679
1682
|
}
|
|
1680
1683
|
async sendPrivateMessage(input) {
|
|
@@ -1688,12 +1691,9 @@ class LocalNodeService {
|
|
|
1688
1691
|
return { sent: false, reason: "self_private_message_not_allowed" };
|
|
1689
1692
|
}
|
|
1690
1693
|
const toPeerId = this.privatePeerRoutes[toAgentId] || "";
|
|
1691
|
-
if (!toAgentId || !
|
|
1694
|
+
if (!toAgentId || !recipientKey || !body) {
|
|
1692
1695
|
return { sent: false, reason: "invalid_private_message_input" };
|
|
1693
1696
|
}
|
|
1694
|
-
if (typeof this.network.sendDirect !== "function") {
|
|
1695
|
-
return { sent: false, reason: "direct_delivery_not_supported" };
|
|
1696
|
-
}
|
|
1697
1697
|
const encrypted = (0, core_1.encryptPrivatePayload)({
|
|
1698
1698
|
plaintext: body,
|
|
1699
1699
|
recipient_public_key: recipientKey,
|
|
@@ -1710,11 +1710,28 @@ class LocalNodeService {
|
|
|
1710
1710
|
nonce: encrypted.nonce,
|
|
1711
1711
|
created_at: Date.now(),
|
|
1712
1712
|
});
|
|
1713
|
+
this.privateMessageBodyCache.set(message.message_id, body);
|
|
1713
1714
|
this.ingestPrivateMessage(message);
|
|
1714
1715
|
await this.persistPrivateMessages();
|
|
1715
|
-
|
|
1716
|
+
let reason = "fallback-sent";
|
|
1717
|
+
if (toPeerId && typeof this.network.sendDirect === "function") {
|
|
1718
|
+
try {
|
|
1719
|
+
await this.network.sendDirect(toPeerId, PRIVATE_MESSAGE_TOPIC, message);
|
|
1720
|
+
reason = "direct-sent";
|
|
1721
|
+
}
|
|
1722
|
+
catch {
|
|
1723
|
+
await this.publish(PRIVATE_MESSAGE_TOPIC, message);
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
else {
|
|
1727
|
+
await this.publish(PRIVATE_MESSAGE_TOPIC, message);
|
|
1728
|
+
}
|
|
1729
|
+
this.privateMessageDeliveryStatusCache.set(message.message_id, reason);
|
|
1716
1730
|
const view = this.getPrivateMessages(message.conversation_id).find((item) => item.message_id === message.message_id);
|
|
1717
|
-
|
|
1731
|
+
if (view) {
|
|
1732
|
+
view.delivery_status = reason;
|
|
1733
|
+
}
|
|
1734
|
+
return { sent: true, reason, message: view };
|
|
1718
1735
|
}
|
|
1719
1736
|
getOpenClawBridgeStatus() {
|
|
1720
1737
|
const now = Date.now();
|
|
@@ -2555,6 +2572,12 @@ class LocalNodeService {
|
|
|
2555
2572
|
this.network.subscribe(SOCIAL_MESSAGE_OBSERVATION_TOPIC, (data, meta) => {
|
|
2556
2573
|
this.onMessage(SOCIAL_MESSAGE_OBSERVATION_TOPIC, data, meta);
|
|
2557
2574
|
});
|
|
2575
|
+
this.network.subscribe(PRIVATE_MESSAGE_TOPIC, (data, meta) => {
|
|
2576
|
+
this.onDirectMessage(PRIVATE_MESSAGE_TOPIC, data, meta);
|
|
2577
|
+
});
|
|
2578
|
+
this.network.subscribe(PRIVATE_MESSAGE_RECEIPT_TOPIC, (data, meta) => {
|
|
2579
|
+
this.onDirectMessage(PRIVATE_MESSAGE_RECEIPT_TOPIC, data, meta);
|
|
2580
|
+
});
|
|
2558
2581
|
if (typeof this.network.subscribeDirect === "function") {
|
|
2559
2582
|
this.network.subscribeDirect(PRIVATE_MESSAGE_TOPIC, (data, meta) => {
|
|
2560
2583
|
this.onDirectMessage(PRIVATE_MESSAGE_TOPIC, data, meta);
|
|
@@ -3257,7 +3280,12 @@ class LocalNodeService {
|
|
|
3257
3280
|
created_at: Date.now(),
|
|
3258
3281
|
});
|
|
3259
3282
|
this.ingestPrivateMessageReceipt(receipt);
|
|
3260
|
-
|
|
3283
|
+
try {
|
|
3284
|
+
await this.network.sendDirect(replyPeerId, PRIVATE_MESSAGE_RECEIPT_TOPIC, receipt);
|
|
3285
|
+
}
|
|
3286
|
+
catch {
|
|
3287
|
+
await this.publish(PRIVATE_MESSAGE_RECEIPT_TOPIC, receipt);
|
|
3288
|
+
}
|
|
3261
3289
|
await this.persistPrivateMessageReceipts();
|
|
3262
3290
|
}
|
|
3263
3291
|
normalizeIncomingPrivateMessage(value) {
|
|
@@ -3387,12 +3415,19 @@ class LocalNodeService {
|
|
|
3387
3415
|
}
|
|
3388
3416
|
this.privateMessages = this.normalizePrivateMessages(this.privateMessages);
|
|
3389
3417
|
const validIds = new Set(this.privateMessages.map((item) => item.message_id));
|
|
3390
|
-
|
|
3418
|
+
if (message.from_agent_id !== this.identity?.agent_id) {
|
|
3419
|
+
this.privateMessageBodyCache.delete(message.message_id);
|
|
3420
|
+
}
|
|
3391
3421
|
for (const key of Array.from(this.privateMessageBodyCache.keys())) {
|
|
3392
3422
|
if (!validIds.has(key)) {
|
|
3393
3423
|
this.privateMessageBodyCache.delete(key);
|
|
3394
3424
|
}
|
|
3395
3425
|
}
|
|
3426
|
+
for (const key of Array.from(this.privateMessageDeliveryStatusCache.keys())) {
|
|
3427
|
+
if (!validIds.has(key)) {
|
|
3428
|
+
this.privateMessageDeliveryStatusCache.delete(key);
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3396
3431
|
}
|
|
3397
3432
|
ingestPrivateMessageReceipt(receipt) {
|
|
3398
3433
|
const existing = this.privateMessageReceipts.findIndex((item) => item.receipt_id === receipt.receipt_id);
|
|
@@ -3403,6 +3438,7 @@ class LocalNodeService {
|
|
|
3403
3438
|
this.privateMessageReceipts.push(receipt);
|
|
3404
3439
|
}
|
|
3405
3440
|
this.privateMessageReceipts = this.normalizePrivateMessageReceipts(this.privateMessageReceipts);
|
|
3441
|
+
this.privateMessageDeliveryStatusCache.set(receipt.message_id, receipt.status);
|
|
3406
3442
|
}
|
|
3407
3443
|
normalizeIncomingSocialMessage(value) {
|
|
3408
3444
|
if (typeof value !== "object" || value === null) {
|
|
@@ -3796,7 +3832,11 @@ async function main() {
|
|
|
3796
3832
|
body: String(req.body?.body || ""),
|
|
3797
3833
|
});
|
|
3798
3834
|
sendOk(res, result, {
|
|
3799
|
-
message: result.sent
|
|
3835
|
+
message: result.sent
|
|
3836
|
+
? (result.reason === "direct-sent"
|
|
3837
|
+
? "Private message sent directly"
|
|
3838
|
+
: "Private message sent via encrypted fallback")
|
|
3839
|
+
: `Private message skipped: ${result.reason}`,
|
|
3800
3840
|
});
|
|
3801
3841
|
}));
|
|
3802
3842
|
app.get("/api/openclaw/bridge", (_req, res) => {
|
|
@@ -692,6 +692,13 @@ const APP_UPDATE_SESSION_KEY = 'silicaclaw_pending_updated_version';
|
|
|
692
692
|
}
|
|
693
693
|
|
|
694
694
|
function renderPrivate() {
|
|
695
|
+
const privateDeliveryLabel = (status) => {
|
|
696
|
+
if (status === 'direct-sent') return 'Direct';
|
|
697
|
+
if (status === 'fallback-sent') return 'Fallback';
|
|
698
|
+
if (status === 'received') return 'Received';
|
|
699
|
+
if (status === 'read') return 'Read';
|
|
700
|
+
return 'Sent';
|
|
701
|
+
};
|
|
695
702
|
document.getElementById('privateStateMeta').textContent = privateState?.enabled
|
|
696
703
|
? `${privateConversations.length} conversation(s)`
|
|
697
704
|
: 'Private messaging unavailable';
|
|
@@ -716,7 +723,7 @@ const APP_UPDATE_SESSION_KEY = 'silicaclaw_pending_updated_version';
|
|
|
716
723
|
<div style="display:flex; align-items:center; justify-content:space-between; gap:12px;">
|
|
717
724
|
<div>
|
|
718
725
|
<strong>${item.is_self ? 'Me' : escapeHtml(privateTarget?.display_name || item.from_agent_id || 'Unknown')}</strong>
|
|
719
|
-
<span class="tag-chip" style="margin-left:8px;">${escapeHtml(item.delivery_status)}</span>
|
|
726
|
+
<span class="tag-chip" style="margin-left:8px;">${escapeHtml(privateDeliveryLabel(item.delivery_status))}</span>
|
|
720
727
|
</div>
|
|
721
728
|
<div class="mono" style="color:#90a2c3;">${new Date(item.created_at).toLocaleString()}</div>
|
|
722
729
|
</div>
|
|
@@ -899,7 +899,7 @@ type PrivateMessageView = {
|
|
|
899
899
|
body: string;
|
|
900
900
|
created_at: number;
|
|
901
901
|
is_self: boolean;
|
|
902
|
-
delivery_status: "sent" | "received" | "read";
|
|
902
|
+
delivery_status: "sent" | "direct-sent" | "fallback-sent" | "received" | "read";
|
|
903
903
|
};
|
|
904
904
|
|
|
905
905
|
type RuntimeMessageGovernance = SocialMessageGovernanceConfig;
|
|
@@ -1047,6 +1047,7 @@ export class LocalNodeService {
|
|
|
1047
1047
|
private privateEncryptionKeyPair: PrivateEncryptionKeyPair | null = null;
|
|
1048
1048
|
private privatePeerRoutes: Record<string, string> = {};
|
|
1049
1049
|
private privateMessageBodyCache = new Map<string, string>();
|
|
1050
|
+
private privateMessageDeliveryStatusCache = new Map<string, PrivateMessageView["delivery_status"]>();
|
|
1050
1051
|
private messageGovernance: RuntimeMessageGovernance;
|
|
1051
1052
|
private privateMessagesPersistDirty = false;
|
|
1052
1053
|
private privateMessageReceiptsPersistDirty = false;
|
|
@@ -2026,7 +2027,10 @@ export class LocalNodeService {
|
|
|
2026
2027
|
body: this.decryptPrivateMessageBody(message),
|
|
2027
2028
|
created_at: message.created_at,
|
|
2028
2029
|
is_self: message.from_agent_id === this.identity?.agent_id,
|
|
2029
|
-
delivery_status:
|
|
2030
|
+
delivery_status:
|
|
2031
|
+
receiptsByMessageId.get(message.message_id) ||
|
|
2032
|
+
this.privateMessageDeliveryStatusCache.get(message.message_id) ||
|
|
2033
|
+
(message.from_agent_id === this.identity?.agent_id ? "fallback-sent" : "sent"),
|
|
2030
2034
|
}));
|
|
2031
2035
|
}
|
|
2032
2036
|
|
|
@@ -2045,12 +2049,9 @@ export class LocalNodeService {
|
|
|
2045
2049
|
return { sent: false, reason: "self_private_message_not_allowed" };
|
|
2046
2050
|
}
|
|
2047
2051
|
const toPeerId = this.privatePeerRoutes[toAgentId] || "";
|
|
2048
|
-
if (!toAgentId || !
|
|
2052
|
+
if (!toAgentId || !recipientKey || !body) {
|
|
2049
2053
|
return { sent: false, reason: "invalid_private_message_input" };
|
|
2050
2054
|
}
|
|
2051
|
-
if (typeof this.network.sendDirect !== "function") {
|
|
2052
|
-
return { sent: false, reason: "direct_delivery_not_supported" };
|
|
2053
|
-
}
|
|
2054
2055
|
const encrypted = encryptPrivatePayload({
|
|
2055
2056
|
plaintext: body,
|
|
2056
2057
|
recipient_public_key: recipientKey,
|
|
@@ -2067,11 +2068,26 @@ export class LocalNodeService {
|
|
|
2067
2068
|
nonce: encrypted.nonce,
|
|
2068
2069
|
created_at: Date.now(),
|
|
2069
2070
|
});
|
|
2071
|
+
this.privateMessageBodyCache.set(message.message_id, body);
|
|
2070
2072
|
this.ingestPrivateMessage(message);
|
|
2071
2073
|
await this.persistPrivateMessages();
|
|
2072
|
-
|
|
2074
|
+
let reason = "fallback-sent";
|
|
2075
|
+
if (toPeerId && typeof this.network.sendDirect === "function") {
|
|
2076
|
+
try {
|
|
2077
|
+
await this.network.sendDirect(toPeerId, PRIVATE_MESSAGE_TOPIC, message);
|
|
2078
|
+
reason = "direct-sent";
|
|
2079
|
+
} catch {
|
|
2080
|
+
await this.publish(PRIVATE_MESSAGE_TOPIC, message);
|
|
2081
|
+
}
|
|
2082
|
+
} else {
|
|
2083
|
+
await this.publish(PRIVATE_MESSAGE_TOPIC, message);
|
|
2084
|
+
}
|
|
2085
|
+
this.privateMessageDeliveryStatusCache.set(message.message_id, reason as PrivateMessageView["delivery_status"]);
|
|
2073
2086
|
const view = this.getPrivateMessages(message.conversation_id).find((item) => item.message_id === message.message_id);
|
|
2074
|
-
|
|
2087
|
+
if (view) {
|
|
2088
|
+
view.delivery_status = reason as PrivateMessageView["delivery_status"];
|
|
2089
|
+
}
|
|
2090
|
+
return { sent: true, reason, message: view };
|
|
2075
2091
|
}
|
|
2076
2092
|
|
|
2077
2093
|
getOpenClawBridgeStatus(): OpenClawBridgeStatus {
|
|
@@ -3006,6 +3022,12 @@ export class LocalNodeService {
|
|
|
3006
3022
|
this.network.subscribe(SOCIAL_MESSAGE_OBSERVATION_TOPIC, (data: SocialMessageObservationRecord, meta?: { peerId?: string }) => {
|
|
3007
3023
|
this.onMessage(SOCIAL_MESSAGE_OBSERVATION_TOPIC, data, meta);
|
|
3008
3024
|
});
|
|
3025
|
+
this.network.subscribe(PRIVATE_MESSAGE_TOPIC, (data: PrivateMessageRecord, meta?: { peerId?: string }) => {
|
|
3026
|
+
this.onDirectMessage(PRIVATE_MESSAGE_TOPIC, data, meta);
|
|
3027
|
+
});
|
|
3028
|
+
this.network.subscribe(PRIVATE_MESSAGE_RECEIPT_TOPIC, (data: PrivateMessageReceiptRecord, meta?: { peerId?: string }) => {
|
|
3029
|
+
this.onDirectMessage(PRIVATE_MESSAGE_RECEIPT_TOPIC, data, meta);
|
|
3030
|
+
});
|
|
3009
3031
|
if (typeof this.network.subscribeDirect === "function") {
|
|
3010
3032
|
this.network.subscribeDirect(PRIVATE_MESSAGE_TOPIC, (data: PrivateMessageRecord, meta?: { peerId?: string }) => {
|
|
3011
3033
|
this.onDirectMessage(PRIVATE_MESSAGE_TOPIC, data, meta);
|
|
@@ -3799,7 +3821,11 @@ export class LocalNodeService {
|
|
|
3799
3821
|
created_at: Date.now(),
|
|
3800
3822
|
});
|
|
3801
3823
|
this.ingestPrivateMessageReceipt(receipt);
|
|
3802
|
-
|
|
3824
|
+
try {
|
|
3825
|
+
await this.network.sendDirect(replyPeerId, PRIVATE_MESSAGE_RECEIPT_TOPIC, receipt);
|
|
3826
|
+
} catch {
|
|
3827
|
+
await this.publish(PRIVATE_MESSAGE_RECEIPT_TOPIC, receipt);
|
|
3828
|
+
}
|
|
3803
3829
|
await this.persistPrivateMessageReceipts();
|
|
3804
3830
|
}
|
|
3805
3831
|
|
|
@@ -3938,12 +3964,19 @@ export class LocalNodeService {
|
|
|
3938
3964
|
}
|
|
3939
3965
|
this.privateMessages = this.normalizePrivateMessages(this.privateMessages);
|
|
3940
3966
|
const validIds = new Set(this.privateMessages.map((item) => item.message_id));
|
|
3941
|
-
|
|
3967
|
+
if (message.from_agent_id !== this.identity?.agent_id) {
|
|
3968
|
+
this.privateMessageBodyCache.delete(message.message_id);
|
|
3969
|
+
}
|
|
3942
3970
|
for (const key of Array.from(this.privateMessageBodyCache.keys())) {
|
|
3943
3971
|
if (!validIds.has(key)) {
|
|
3944
3972
|
this.privateMessageBodyCache.delete(key);
|
|
3945
3973
|
}
|
|
3946
3974
|
}
|
|
3975
|
+
for (const key of Array.from(this.privateMessageDeliveryStatusCache.keys())) {
|
|
3976
|
+
if (!validIds.has(key)) {
|
|
3977
|
+
this.privateMessageDeliveryStatusCache.delete(key);
|
|
3978
|
+
}
|
|
3979
|
+
}
|
|
3947
3980
|
}
|
|
3948
3981
|
|
|
3949
3982
|
private ingestPrivateMessageReceipt(receipt: PrivateMessageReceiptRecord): void {
|
|
@@ -3954,6 +3987,7 @@ export class LocalNodeService {
|
|
|
3954
3987
|
this.privateMessageReceipts.push(receipt);
|
|
3955
3988
|
}
|
|
3956
3989
|
this.privateMessageReceipts = this.normalizePrivateMessageReceipts(this.privateMessageReceipts);
|
|
3990
|
+
this.privateMessageDeliveryStatusCache.set(receipt.message_id, receipt.status);
|
|
3957
3991
|
}
|
|
3958
3992
|
|
|
3959
3993
|
private normalizeIncomingSocialMessage(value: unknown): SocialMessageRecord | null {
|
|
@@ -4441,7 +4475,11 @@ export async function main() {
|
|
|
4441
4475
|
body: String(req.body?.body || ""),
|
|
4442
4476
|
});
|
|
4443
4477
|
sendOk(res, result, {
|
|
4444
|
-
message: result.sent
|
|
4478
|
+
message: result.sent
|
|
4479
|
+
? (result.reason === "direct-sent"
|
|
4480
|
+
? "Private message sent directly"
|
|
4481
|
+
: "Private message sent via encrypted fallback")
|
|
4482
|
+
: `Private message skipped: ${result.reason}`,
|
|
4445
4483
|
});
|
|
4446
4484
|
})
|
|
4447
4485
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
2026.3.20-beta.
|
|
1
|
+
2026.3.20-beta.13
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "silicaclaw-broadcast",
|
|
3
|
-
"version": "2026.3.20-beta.
|
|
3
|
+
"version": "2026.3.20-beta.13",
|
|
4
4
|
"display_name": "SilicaClaw Broadcast",
|
|
5
5
|
"description": "Official OpenClaw skill for a bounded local SilicaClaw broadcast workflow: read public broadcasts, publish public broadcasts, and optionally forward owner-relevant summaries through OpenClaw's native channel.",
|
|
6
6
|
"entrypoints": {
|