@silicaclaw/cli 2026.3.20-17 → 2026.3.20-19
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 +12 -0
- package/VERSION +1 -1
- package/apps/local-console/dist/apps/local-console/src/server.d.ts +9 -1
- package/apps/local-console/dist/apps/local-console/src/server.js +100 -9
- package/apps/local-console/dist/packages/storage/src/repos.d.ts +14 -0
- package/apps/local-console/dist/packages/storage/src/repos.js +17 -1
- package/apps/local-console/src/server.ts +111 -9
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/repos.d.ts +14 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/repos.js +17 -1
- package/node_modules/@silicaclaw/storage/src/repos.ts +28 -0
- package/openclaw-skills/silicaclaw-broadcast/VERSION +1 -1
- package/openclaw-skills/silicaclaw-broadcast/manifest.json +1 -1
- package/package.json +1 -1
- package/packages/storage/dist/packages/storage/src/repos.d.ts +14 -0
- package/packages/storage/dist/packages/storage/src/repos.js +17 -1
- package/packages/storage/src/repos.ts +28 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## v1.0 beta - 2026-03-20
|
|
4
4
|
|
|
5
|
+
### 2026.3.20-19
|
|
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
|
+
|
|
11
|
+
### 2026.3.20-18
|
|
12
|
+
|
|
13
|
+
- release build:
|
|
14
|
+
- prepared another fresh latest-channel package build without publishing
|
|
15
|
+
- regenerated the npm tarball through the verified release packing workflow
|
|
16
|
+
|
|
5
17
|
### 2026.3.20-17
|
|
6
18
|
|
|
7
19
|
- release build:
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v2026.3.20-
|
|
1
|
+
v2026.3.20-19
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentIdentity, DirectoryState, ProfileInput, PublicProfile, PublicProfileSummary, SocialConfig, SocialMessageRecord, SocialRuntimeConfig } from "@silicaclaw/core";
|
|
2
|
-
import { SocialMessageGovernanceConfig } from "@silicaclaw/storage";
|
|
2
|
+
import { PrivateMessagingRuntimeState, SocialMessageGovernanceConfig } from "@silicaclaw/storage";
|
|
3
3
|
type InitState = {
|
|
4
4
|
identity_auto_created: boolean;
|
|
5
5
|
profile_auto_created: boolean;
|
|
@@ -170,6 +170,7 @@ export declare class LocalNodeService {
|
|
|
170
170
|
private privateMessageRepo;
|
|
171
171
|
private privateMessageReceiptRepo;
|
|
172
172
|
private privateEncryptionKeyRepo;
|
|
173
|
+
private privateMessagingRuntimeRepo;
|
|
173
174
|
private socialRuntimeRepo;
|
|
174
175
|
private identity;
|
|
175
176
|
private profile;
|
|
@@ -179,7 +180,9 @@ export declare class LocalNodeService {
|
|
|
179
180
|
private privateMessages;
|
|
180
181
|
private privateMessageReceipts;
|
|
181
182
|
private privateEncryptionKeyPair;
|
|
183
|
+
private privateMessagingRuntime;
|
|
182
184
|
private privatePeerRoutes;
|
|
185
|
+
private privatePeerEncryptionKeys;
|
|
183
186
|
private privateMessageBodyCache;
|
|
184
187
|
private privateMessageDeliveryStatusCache;
|
|
185
188
|
private messageGovernance;
|
|
@@ -646,6 +649,7 @@ export declare class LocalNodeService {
|
|
|
646
649
|
encryption_public_key: string;
|
|
647
650
|
conversation_count: number;
|
|
648
651
|
message_count: number;
|
|
652
|
+
runtime: PrivateMessagingRuntimeState | null;
|
|
649
653
|
};
|
|
650
654
|
getPrivateConversations(): Array<{
|
|
651
655
|
conversation_id: string;
|
|
@@ -850,6 +854,8 @@ export declare class LocalNodeService {
|
|
|
850
854
|
private persistPrivateMessageReceipts;
|
|
851
855
|
private flushPrivatePersistence;
|
|
852
856
|
private flushPrivateMessagesPersist;
|
|
857
|
+
private hydratePrivateMessageBodyCache;
|
|
858
|
+
private buildPersistedPrivateMessages;
|
|
853
859
|
private flushPrivateMessageReceiptsPersist;
|
|
854
860
|
private log;
|
|
855
861
|
private getAdapterDiagnostics;
|
|
@@ -857,6 +863,8 @@ export declare class LocalNodeService {
|
|
|
857
863
|
private toPublicProfileSummary;
|
|
858
864
|
private mergeMessageOnlyAgentSummaries;
|
|
859
865
|
private fingerprintPublicKey;
|
|
866
|
+
private buildPrivateMessagingRuntimeState;
|
|
867
|
+
private refreshPrivateMessagingRuntime;
|
|
860
868
|
private getOnboardingSummary;
|
|
861
869
|
private getDefaultDisplayName;
|
|
862
870
|
private getModeExplainer;
|
|
@@ -776,6 +776,7 @@ class LocalNodeService {
|
|
|
776
776
|
privateMessageRepo;
|
|
777
777
|
privateMessageReceiptRepo;
|
|
778
778
|
privateEncryptionKeyRepo;
|
|
779
|
+
privateMessagingRuntimeRepo;
|
|
779
780
|
socialRuntimeRepo;
|
|
780
781
|
identity = null;
|
|
781
782
|
profile = null;
|
|
@@ -785,7 +786,9 @@ class LocalNodeService {
|
|
|
785
786
|
privateMessages = [];
|
|
786
787
|
privateMessageReceipts = [];
|
|
787
788
|
privateEncryptionKeyPair = null;
|
|
789
|
+
privateMessagingRuntime = null;
|
|
788
790
|
privatePeerRoutes = {};
|
|
791
|
+
privatePeerEncryptionKeys = {};
|
|
789
792
|
privateMessageBodyCache = new Map();
|
|
790
793
|
privateMessageDeliveryStatusCache = new Map();
|
|
791
794
|
messageGovernance;
|
|
@@ -862,6 +865,7 @@ class LocalNodeService {
|
|
|
862
865
|
this.privateMessageRepo = new storage_1.PrivateMessageRepo(this.storageRoot);
|
|
863
866
|
this.privateMessageReceiptRepo = new storage_1.PrivateMessageReceiptRepo(this.storageRoot);
|
|
864
867
|
this.privateEncryptionKeyRepo = new storage_1.PrivateEncryptionKeyRepo(this.storageRoot);
|
|
868
|
+
this.privateMessagingRuntimeRepo = new storage_1.PrivateMessagingRuntimeRepo(this.storageRoot);
|
|
865
869
|
this.socialRuntimeRepo = new storage_1.SocialRuntimeRepo(this.storageRoot);
|
|
866
870
|
this.messageGovernance = this.defaultMessageGovernance();
|
|
867
871
|
let loadedSocial = (0, core_1.loadSocialConfig)(this.projectRoot);
|
|
@@ -1623,6 +1627,7 @@ class LocalNodeService {
|
|
|
1623
1627
|
encryption_public_key: this.privateEncryptionKeyPair?.public_key || "",
|
|
1624
1628
|
conversation_count: this.getPrivateConversations().length,
|
|
1625
1629
|
message_count: this.privateMessages.length,
|
|
1630
|
+
runtime: this.privateMessagingRuntime,
|
|
1626
1631
|
};
|
|
1627
1632
|
}
|
|
1628
1633
|
getPrivateConversations() {
|
|
@@ -1638,12 +1643,13 @@ class LocalNodeService {
|
|
|
1638
1643
|
const peerProfile = this.directory.profiles[peerAgentId];
|
|
1639
1644
|
const current = conversations.get(message.conversation_id);
|
|
1640
1645
|
const nextLast = Math.max(current?.last_message_at || 0, message.created_at || 0) || null;
|
|
1646
|
+
const learnedPeerKey = this.privatePeerEncryptionKeys[peerAgentId] || "";
|
|
1641
1647
|
conversations.set(message.conversation_id, {
|
|
1642
1648
|
conversation_id: message.conversation_id,
|
|
1643
1649
|
peer_agent_id: peerAgentId,
|
|
1644
1650
|
peer_display_name: peerProfile?.display_name || peerAgentId,
|
|
1645
1651
|
peer_avatar_url: peerProfile?.avatar_url || "",
|
|
1646
|
-
peer_public_key: peerProfile?.private_encryption_public_key || "",
|
|
1652
|
+
peer_public_key: learnedPeerKey || peerProfile?.private_encryption_public_key || "",
|
|
1647
1653
|
last_message_at: nextLast,
|
|
1648
1654
|
unread_count: current?.unread_count || 0,
|
|
1649
1655
|
});
|
|
@@ -1665,8 +1671,8 @@ class LocalNodeService {
|
|
|
1665
1671
|
}
|
|
1666
1672
|
return !normalizedConversationId || message.conversation_id === normalizedConversationId;
|
|
1667
1673
|
})
|
|
1668
|
-
.sort((a, b) =>
|
|
1669
|
-
.slice(
|
|
1674
|
+
.sort((a, b) => b.created_at - a.created_at)
|
|
1675
|
+
.slice(0, resolvedLimit)
|
|
1670
1676
|
.map((message) => ({
|
|
1671
1677
|
message_id: message.message_id,
|
|
1672
1678
|
conversation_id: message.conversation_id,
|
|
@@ -1685,7 +1691,9 @@ class LocalNodeService {
|
|
|
1685
1691
|
return { sent: false, reason: "missing_identity_or_private_key" };
|
|
1686
1692
|
}
|
|
1687
1693
|
const toAgentId = String(input.to_agent_id || "").trim();
|
|
1688
|
-
const
|
|
1694
|
+
const learnedRecipientKey = this.privatePeerEncryptionKeys[toAgentId] || "";
|
|
1695
|
+
const profileRecipientKey = this.directory.profiles[toAgentId]?.private_encryption_public_key || "";
|
|
1696
|
+
const recipientKey = String(learnedRecipientKey || input.recipient_encryption_public_key || profileRecipientKey || "").trim();
|
|
1689
1697
|
const body = String(input.body || "").trim();
|
|
1690
1698
|
if (toAgentId === this.identity.agent_id) {
|
|
1691
1699
|
return { sent: false, reason: "self_private_message_not_allowed" };
|
|
@@ -1717,6 +1725,7 @@ class LocalNodeService {
|
|
|
1717
1725
|
if (toPeerId && typeof this.network.sendDirect === "function") {
|
|
1718
1726
|
try {
|
|
1719
1727
|
await this.network.sendDirect(toPeerId, PRIVATE_MESSAGE_TOPIC, message);
|
|
1728
|
+
await this.publish(PRIVATE_MESSAGE_TOPIC, message);
|
|
1720
1729
|
reason = "direct-sent";
|
|
1721
1730
|
}
|
|
1722
1731
|
catch {
|
|
@@ -2345,8 +2354,11 @@ class LocalNodeService {
|
|
|
2345
2354
|
};
|
|
2346
2355
|
this.socialMessages = this.normalizeSocialMessages(await this.socialMessageRepo.get());
|
|
2347
2356
|
this.socialMessageObservations = this.normalizeSocialMessageObservations(await this.socialMessageObservationRepo.get());
|
|
2348
|
-
|
|
2357
|
+
const storedPrivateMessages = await this.privateMessageRepo.get();
|
|
2358
|
+
this.hydratePrivateMessageBodyCache(storedPrivateMessages);
|
|
2359
|
+
this.privateMessages = this.normalizePrivateMessages(storedPrivateMessages);
|
|
2349
2360
|
this.privateMessageReceipts = this.normalizePrivateMessageReceipts(await this.privateMessageReceiptRepo.get());
|
|
2361
|
+
await this.refreshPrivateMessagingRuntime();
|
|
2350
2362
|
this.directory = (0, core_1.ingestProfileRecord)(this.directory, { type: "profile", profile: this.profile });
|
|
2351
2363
|
this.compactCacheInMemory();
|
|
2352
2364
|
await this.persistCache();
|
|
@@ -2439,7 +2451,7 @@ class LocalNodeService {
|
|
|
2439
2451
|
return;
|
|
2440
2452
|
}
|
|
2441
2453
|
}
|
|
2442
|
-
if (meta?.peerId && record.profile.agent_id) {
|
|
2454
|
+
if (meta?.peerId && record.profile.agent_id && !this.privatePeerRoutes[record.profile.agent_id]) {
|
|
2443
2455
|
this.privatePeerRoutes[record.profile.agent_id] = meta.peerId;
|
|
2444
2456
|
}
|
|
2445
2457
|
this.directory = (0, core_1.ingestProfileRecord)(this.directory, record);
|
|
@@ -2458,7 +2470,7 @@ class LocalNodeService {
|
|
|
2458
2470
|
return;
|
|
2459
2471
|
}
|
|
2460
2472
|
}
|
|
2461
|
-
if (meta?.peerId && record.agent_id) {
|
|
2473
|
+
if (meta?.peerId && record.agent_id && !this.privatePeerRoutes[record.agent_id]) {
|
|
2462
2474
|
this.privatePeerRoutes[record.agent_id] = meta.peerId;
|
|
2463
2475
|
}
|
|
2464
2476
|
this.directory = (0, core_1.ingestPresenceRecord)(this.directory, record);
|
|
@@ -2475,7 +2487,7 @@ class LocalNodeService {
|
|
|
2475
2487
|
await this.log("warn", `Rejected social message with invalid signature (${record.message_id.slice(0, 10)})`);
|
|
2476
2488
|
return;
|
|
2477
2489
|
}
|
|
2478
|
-
if (meta?.peerId && record.agent_id) {
|
|
2490
|
+
if (meta?.peerId && record.agent_id && !this.privatePeerRoutes[record.agent_id]) {
|
|
2479
2491
|
this.privatePeerRoutes[record.agent_id] = meta.peerId;
|
|
2480
2492
|
}
|
|
2481
2493
|
if (this.hasSocialMessage(record.message_id)) {
|
|
@@ -2519,6 +2531,12 @@ class LocalNodeService {
|
|
|
2519
2531
|
if (!record || !(0, core_1.verifyPrivateMessage)(record)) {
|
|
2520
2532
|
return;
|
|
2521
2533
|
}
|
|
2534
|
+
if (meta?.peerId && record.from_agent_id) {
|
|
2535
|
+
this.privatePeerRoutes[record.from_agent_id] = meta.peerId;
|
|
2536
|
+
}
|
|
2537
|
+
if (record.from_agent_id && record.sender_encryption_public_key) {
|
|
2538
|
+
this.privatePeerEncryptionKeys[record.from_agent_id] = record.sender_encryption_public_key;
|
|
2539
|
+
}
|
|
2522
2540
|
if (record.to_agent_id !== this.identity?.agent_id || this.hasPrivateMessage(record.message_id)) {
|
|
2523
2541
|
return;
|
|
2524
2542
|
}
|
|
@@ -2531,6 +2549,9 @@ class LocalNodeService {
|
|
|
2531
2549
|
if (!receipt || !(0, core_1.verifyPrivateMessageReceipt)(receipt)) {
|
|
2532
2550
|
return;
|
|
2533
2551
|
}
|
|
2552
|
+
if (meta?.peerId && receipt.from_agent_id) {
|
|
2553
|
+
this.privatePeerRoutes[receipt.from_agent_id] = meta.peerId;
|
|
2554
|
+
}
|
|
2534
2555
|
if (receipt.to_agent_id !== this.identity?.agent_id) {
|
|
2535
2556
|
return;
|
|
2536
2557
|
}
|
|
@@ -2840,7 +2861,37 @@ class LocalNodeService {
|
|
|
2840
2861
|
return;
|
|
2841
2862
|
}
|
|
2842
2863
|
this.privateMessagesPersistDirty = false;
|
|
2843
|
-
await this.privateMessageRepo.set(this.
|
|
2864
|
+
await this.privateMessageRepo.set(this.buildPersistedPrivateMessages());
|
|
2865
|
+
}
|
|
2866
|
+
hydratePrivateMessageBodyCache(items) {
|
|
2867
|
+
if (!Array.isArray(items)) {
|
|
2868
|
+
return;
|
|
2869
|
+
}
|
|
2870
|
+
for (const item of items) {
|
|
2871
|
+
if (typeof item !== "object" || item === null) {
|
|
2872
|
+
continue;
|
|
2873
|
+
}
|
|
2874
|
+
const record = item;
|
|
2875
|
+
const messageId = String(record.message_id || "").trim();
|
|
2876
|
+
const localPlaintext = typeof record.local_plaintext === "string" ? record.local_plaintext : "";
|
|
2877
|
+
if (messageId && localPlaintext) {
|
|
2878
|
+
this.privateMessageBodyCache.set(messageId, localPlaintext);
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
buildPersistedPrivateMessages() {
|
|
2883
|
+
return this.privateMessages.map((message) => {
|
|
2884
|
+
const localPlaintext = message.from_agent_id === this.identity?.agent_id
|
|
2885
|
+
? this.privateMessageBodyCache.get(message.message_id) || ""
|
|
2886
|
+
: "";
|
|
2887
|
+
if (!localPlaintext) {
|
|
2888
|
+
return { ...message };
|
|
2889
|
+
}
|
|
2890
|
+
return {
|
|
2891
|
+
...message,
|
|
2892
|
+
local_plaintext: localPlaintext,
|
|
2893
|
+
};
|
|
2894
|
+
});
|
|
2844
2895
|
}
|
|
2845
2896
|
async flushPrivateMessageReceiptsPersist() {
|
|
2846
2897
|
if (this.privateMessageReceiptsPersistTimer) {
|
|
@@ -2975,6 +3026,45 @@ class LocalNodeService {
|
|
|
2975
3026
|
const digest = (0, crypto_1.createHash)("sha256").update(publicKey, "utf8").digest("hex");
|
|
2976
3027
|
return `${digest.slice(0, 12)}:${digest.slice(-8)}`;
|
|
2977
3028
|
}
|
|
3029
|
+
buildPrivateMessagingRuntimeState() {
|
|
3030
|
+
const warnings = [];
|
|
3031
|
+
const keypair = this.privateEncryptionKeyPair;
|
|
3032
|
+
const selfSentMessages = this.privateMessages.filter((message) => message.from_agent_id === this.identity?.agent_id);
|
|
3033
|
+
let cachedPlaintextCount = 0;
|
|
3034
|
+
for (const message of selfSentMessages) {
|
|
3035
|
+
if (this.privateMessageBodyCache.get(message.message_id)) {
|
|
3036
|
+
cachedPlaintextCount += 1;
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
if (!keypair?.public_key || !keypair?.private_key) {
|
|
3040
|
+
warnings.push("missing_private_encryption_keypair");
|
|
3041
|
+
}
|
|
3042
|
+
if (selfSentMessages.length > 0 && cachedPlaintextCount === 0) {
|
|
3043
|
+
warnings.push("missing_local_plaintext_cache_for_self_messages");
|
|
3044
|
+
}
|
|
3045
|
+
if (selfSentMessages.length > 0 && cachedPlaintextCount < selfSentMessages.length) {
|
|
3046
|
+
warnings.push("partial_local_plaintext_cache_for_self_messages");
|
|
3047
|
+
}
|
|
3048
|
+
return {
|
|
3049
|
+
schema_version: 1,
|
|
3050
|
+
app_version: this.appVersion,
|
|
3051
|
+
last_started_at: Date.now(),
|
|
3052
|
+
encryption_public_key: keypair?.public_key || "",
|
|
3053
|
+
encryption_public_key_fingerprint: keypair?.public_key ? this.fingerprintPublicKey(keypair.public_key) : "",
|
|
3054
|
+
message_count: this.privateMessages.length,
|
|
3055
|
+
self_sent_count: selfSentMessages.length,
|
|
3056
|
+
cached_plaintext_count: cachedPlaintextCount,
|
|
3057
|
+
warnings,
|
|
3058
|
+
};
|
|
3059
|
+
}
|
|
3060
|
+
async refreshPrivateMessagingRuntime() {
|
|
3061
|
+
const runtime = this.buildPrivateMessagingRuntimeState();
|
|
3062
|
+
this.privateMessagingRuntime = runtime;
|
|
3063
|
+
await this.privateMessagingRuntimeRepo.set(runtime);
|
|
3064
|
+
for (const warning of runtime.warnings) {
|
|
3065
|
+
await this.log("warn", `Private messaging startup check: ${warning}`);
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
2978
3068
|
getOnboardingSummary() {
|
|
2979
3069
|
const summary = this.getIntegrationSummary();
|
|
2980
3070
|
const publicEnabled = Boolean(this.profile?.public_enabled);
|
|
@@ -3282,6 +3372,7 @@ class LocalNodeService {
|
|
|
3282
3372
|
this.ingestPrivateMessageReceipt(receipt);
|
|
3283
3373
|
try {
|
|
3284
3374
|
await this.network.sendDirect(replyPeerId, PRIVATE_MESSAGE_RECEIPT_TOPIC, receipt);
|
|
3375
|
+
await this.publish(PRIVATE_MESSAGE_RECEIPT_TOPIC, receipt);
|
|
3285
3376
|
}
|
|
3286
3377
|
catch {
|
|
3287
3378
|
await this.publish(PRIVATE_MESSAGE_RECEIPT_TOPIC, receipt);
|
|
@@ -40,6 +40,17 @@ export type SocialMessageGovernanceConfig = {
|
|
|
40
40
|
export type PrivateMessageDecryptedContent = {
|
|
41
41
|
body: string;
|
|
42
42
|
};
|
|
43
|
+
export type PrivateMessagingRuntimeState = {
|
|
44
|
+
schema_version: number;
|
|
45
|
+
app_version: string;
|
|
46
|
+
last_started_at: number;
|
|
47
|
+
encryption_public_key: string;
|
|
48
|
+
encryption_public_key_fingerprint: string;
|
|
49
|
+
message_count: number;
|
|
50
|
+
self_sent_count: number;
|
|
51
|
+
cached_plaintext_count: number;
|
|
52
|
+
warnings: string[];
|
|
53
|
+
};
|
|
43
54
|
export declare class IdentityRepo extends JsonFileRepo<AgentIdentity | null> {
|
|
44
55
|
constructor(rootDir?: string);
|
|
45
56
|
}
|
|
@@ -71,3 +82,6 @@ export declare class PrivateMessageReceiptRepo extends JsonFileRepo<PrivateMessa
|
|
|
71
82
|
export declare class PrivateEncryptionKeyRepo extends JsonFileRepo<PrivateEncryptionKeyPair | null> {
|
|
72
83
|
constructor(rootDir?: string);
|
|
73
84
|
}
|
|
85
|
+
export declare class PrivateMessagingRuntimeRepo extends JsonFileRepo<PrivateMessagingRuntimeState> {
|
|
86
|
+
constructor(rootDir?: string);
|
|
87
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PrivateEncryptionKeyRepo = exports.PrivateMessageReceiptRepo = exports.PrivateMessageRepo = exports.SocialMessageGovernanceRepo = exports.SocialMessageObservationRepo = exports.SocialMessageRepo = exports.LogRepo = exports.CacheRepo = exports.ProfileRepo = exports.IdentityRepo = void 0;
|
|
3
|
+
exports.PrivateMessagingRuntimeRepo = exports.PrivateEncryptionKeyRepo = exports.PrivateMessageReceiptRepo = exports.PrivateMessageRepo = exports.SocialMessageGovernanceRepo = exports.SocialMessageObservationRepo = exports.SocialMessageRepo = exports.LogRepo = exports.CacheRepo = exports.ProfileRepo = exports.IdentityRepo = void 0;
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
const core_1 = require("@silicaclaw/core");
|
|
6
6
|
const jsonRepo_1 = require("./jsonRepo");
|
|
@@ -83,3 +83,19 @@ class PrivateEncryptionKeyRepo extends jsonRepo_1.JsonFileRepo {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
exports.PrivateEncryptionKeyRepo = PrivateEncryptionKeyRepo;
|
|
86
|
+
class PrivateMessagingRuntimeRepo extends jsonRepo_1.JsonFileRepo {
|
|
87
|
+
constructor(rootDir = process.cwd()) {
|
|
88
|
+
super((0, path_1.resolve)(rootDir, ".silicaclaw", "private-messaging.runtime.json"), () => ({
|
|
89
|
+
schema_version: 1,
|
|
90
|
+
app_version: "",
|
|
91
|
+
last_started_at: 0,
|
|
92
|
+
encryption_public_key: "",
|
|
93
|
+
encryption_public_key_fingerprint: "",
|
|
94
|
+
message_count: 0,
|
|
95
|
+
self_sent_count: 0,
|
|
96
|
+
cached_plaintext_count: 0,
|
|
97
|
+
warnings: [],
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.PrivateMessagingRuntimeRepo = PrivateMessagingRuntimeRepo;
|
|
@@ -72,6 +72,8 @@ import {
|
|
|
72
72
|
IdentityRepo,
|
|
73
73
|
LogRepo,
|
|
74
74
|
PrivateEncryptionKeyRepo,
|
|
75
|
+
PrivateMessagingRuntimeRepo,
|
|
76
|
+
PrivateMessagingRuntimeState,
|
|
75
77
|
PrivateMessageReceiptRepo,
|
|
76
78
|
PrivateMessageRepo,
|
|
77
79
|
ProfileRepo,
|
|
@@ -139,6 +141,10 @@ const SOCIAL_MESSAGE_REPLAY_MAX_PER_BROADCAST = Number(process.env.SOCIAL_MESSAG
|
|
|
139
141
|
const SOCIAL_MESSAGE_REPLAY_REFRESH_INTERVAL_MS = Number(
|
|
140
142
|
process.env.SOCIAL_MESSAGE_REPLAY_REFRESH_INTERVAL_MS || 120_000
|
|
141
143
|
);
|
|
144
|
+
|
|
145
|
+
type StoredPrivateMessageRecord = PrivateMessageRecord & {
|
|
146
|
+
local_plaintext?: string;
|
|
147
|
+
};
|
|
142
148
|
const PROFILE_RELAY_REFRESH_INTERVAL_MS = Number(
|
|
143
149
|
process.env.PROFILE_RELAY_REFRESH_INTERVAL_MS || 120_000
|
|
144
150
|
);
|
|
@@ -1035,6 +1041,7 @@ export class LocalNodeService {
|
|
|
1035
1041
|
private privateMessageRepo: PrivateMessageRepo;
|
|
1036
1042
|
private privateMessageReceiptRepo: PrivateMessageReceiptRepo;
|
|
1037
1043
|
private privateEncryptionKeyRepo: PrivateEncryptionKeyRepo;
|
|
1044
|
+
private privateMessagingRuntimeRepo: PrivateMessagingRuntimeRepo;
|
|
1038
1045
|
private socialRuntimeRepo: SocialRuntimeRepo;
|
|
1039
1046
|
|
|
1040
1047
|
private identity: AgentIdentity | null = null;
|
|
@@ -1045,7 +1052,9 @@ export class LocalNodeService {
|
|
|
1045
1052
|
private privateMessages: PrivateMessageRecord[] = [];
|
|
1046
1053
|
private privateMessageReceipts: PrivateMessageReceiptRecord[] = [];
|
|
1047
1054
|
private privateEncryptionKeyPair: PrivateEncryptionKeyPair | null = null;
|
|
1055
|
+
private privateMessagingRuntime: PrivateMessagingRuntimeState | null = null;
|
|
1048
1056
|
private privatePeerRoutes: Record<string, string> = {};
|
|
1057
|
+
private privatePeerEncryptionKeys: Record<string, string> = {};
|
|
1049
1058
|
private privateMessageBodyCache = new Map<string, string>();
|
|
1050
1059
|
private privateMessageDeliveryStatusCache = new Map<string, PrivateMessageView["delivery_status"]>();
|
|
1051
1060
|
private messageGovernance: RuntimeMessageGovernance;
|
|
@@ -1129,6 +1138,7 @@ export class LocalNodeService {
|
|
|
1129
1138
|
this.privateMessageRepo = new PrivateMessageRepo(this.storageRoot);
|
|
1130
1139
|
this.privateMessageReceiptRepo = new PrivateMessageReceiptRepo(this.storageRoot);
|
|
1131
1140
|
this.privateEncryptionKeyRepo = new PrivateEncryptionKeyRepo(this.storageRoot);
|
|
1141
|
+
this.privateMessagingRuntimeRepo = new PrivateMessagingRuntimeRepo(this.storageRoot);
|
|
1132
1142
|
this.socialRuntimeRepo = new SocialRuntimeRepo(this.storageRoot);
|
|
1133
1143
|
this.messageGovernance = this.defaultMessageGovernance();
|
|
1134
1144
|
|
|
@@ -1955,6 +1965,7 @@ export class LocalNodeService {
|
|
|
1955
1965
|
encryption_public_key: this.privateEncryptionKeyPair?.public_key || "",
|
|
1956
1966
|
conversation_count: this.getPrivateConversations().length,
|
|
1957
1967
|
message_count: this.privateMessages.length,
|
|
1968
|
+
runtime: this.privateMessagingRuntime,
|
|
1958
1969
|
};
|
|
1959
1970
|
}
|
|
1960
1971
|
|
|
@@ -1987,12 +1998,13 @@ export class LocalNodeService {
|
|
|
1987
1998
|
const peerProfile = this.directory.profiles[peerAgentId];
|
|
1988
1999
|
const current = conversations.get(message.conversation_id);
|
|
1989
2000
|
const nextLast = Math.max(current?.last_message_at || 0, message.created_at || 0) || null;
|
|
2001
|
+
const learnedPeerKey = this.privatePeerEncryptionKeys[peerAgentId] || "";
|
|
1990
2002
|
conversations.set(message.conversation_id, {
|
|
1991
2003
|
conversation_id: message.conversation_id,
|
|
1992
2004
|
peer_agent_id: peerAgentId,
|
|
1993
2005
|
peer_display_name: peerProfile?.display_name || peerAgentId,
|
|
1994
2006
|
peer_avatar_url: peerProfile?.avatar_url || "",
|
|
1995
|
-
peer_public_key: peerProfile?.private_encryption_public_key || "",
|
|
2007
|
+
peer_public_key: learnedPeerKey || peerProfile?.private_encryption_public_key || "",
|
|
1996
2008
|
last_message_at: nextLast,
|
|
1997
2009
|
unread_count: current?.unread_count || 0,
|
|
1998
2010
|
});
|
|
@@ -2017,8 +2029,8 @@ export class LocalNodeService {
|
|
|
2017
2029
|
}
|
|
2018
2030
|
return !normalizedConversationId || message.conversation_id === normalizedConversationId;
|
|
2019
2031
|
})
|
|
2020
|
-
.sort((a, b) =>
|
|
2021
|
-
.slice(
|
|
2032
|
+
.sort((a, b) => b.created_at - a.created_at)
|
|
2033
|
+
.slice(0, resolvedLimit)
|
|
2022
2034
|
.map((message) => ({
|
|
2023
2035
|
message_id: message.message_id,
|
|
2024
2036
|
conversation_id: message.conversation_id,
|
|
@@ -2043,7 +2055,9 @@ export class LocalNodeService {
|
|
|
2043
2055
|
return { sent: false, reason: "missing_identity_or_private_key" };
|
|
2044
2056
|
}
|
|
2045
2057
|
const toAgentId = String(input.to_agent_id || "").trim();
|
|
2046
|
-
const
|
|
2058
|
+
const learnedRecipientKey = this.privatePeerEncryptionKeys[toAgentId] || "";
|
|
2059
|
+
const profileRecipientKey = this.directory.profiles[toAgentId]?.private_encryption_public_key || "";
|
|
2060
|
+
const recipientKey = String(learnedRecipientKey || input.recipient_encryption_public_key || profileRecipientKey || "").trim();
|
|
2047
2061
|
const body = String(input.body || "").trim();
|
|
2048
2062
|
if (toAgentId === this.identity.agent_id) {
|
|
2049
2063
|
return { sent: false, reason: "self_private_message_not_allowed" };
|
|
@@ -2075,6 +2089,7 @@ export class LocalNodeService {
|
|
|
2075
2089
|
if (toPeerId && typeof this.network.sendDirect === "function") {
|
|
2076
2090
|
try {
|
|
2077
2091
|
await this.network.sendDirect(toPeerId, PRIVATE_MESSAGE_TOPIC, message);
|
|
2092
|
+
await this.publish(PRIVATE_MESSAGE_TOPIC, message);
|
|
2078
2093
|
reason = "direct-sent";
|
|
2079
2094
|
} catch {
|
|
2080
2095
|
await this.publish(PRIVATE_MESSAGE_TOPIC, message);
|
|
@@ -2763,8 +2778,11 @@ export class LocalNodeService {
|
|
|
2763
2778
|
};
|
|
2764
2779
|
this.socialMessages = this.normalizeSocialMessages(await this.socialMessageRepo.get());
|
|
2765
2780
|
this.socialMessageObservations = this.normalizeSocialMessageObservations(await this.socialMessageObservationRepo.get());
|
|
2766
|
-
|
|
2781
|
+
const storedPrivateMessages = await this.privateMessageRepo.get();
|
|
2782
|
+
this.hydratePrivateMessageBodyCache(storedPrivateMessages);
|
|
2783
|
+
this.privateMessages = this.normalizePrivateMessages(storedPrivateMessages);
|
|
2767
2784
|
this.privateMessageReceipts = this.normalizePrivateMessageReceipts(await this.privateMessageReceiptRepo.get());
|
|
2785
|
+
await this.refreshPrivateMessagingRuntime();
|
|
2768
2786
|
this.directory = ingestProfileRecord(this.directory, { type: "profile", profile: this.profile });
|
|
2769
2787
|
this.compactCacheInMemory();
|
|
2770
2788
|
await this.persistCache();
|
|
@@ -2870,7 +2888,7 @@ export class LocalNodeService {
|
|
|
2870
2888
|
return;
|
|
2871
2889
|
}
|
|
2872
2890
|
}
|
|
2873
|
-
if (meta?.peerId && record.profile.agent_id) {
|
|
2891
|
+
if (meta?.peerId && record.profile.agent_id && !this.privatePeerRoutes[record.profile.agent_id]) {
|
|
2874
2892
|
this.privatePeerRoutes[record.profile.agent_id] = meta.peerId;
|
|
2875
2893
|
}
|
|
2876
2894
|
|
|
@@ -2892,7 +2910,7 @@ export class LocalNodeService {
|
|
|
2892
2910
|
return;
|
|
2893
2911
|
}
|
|
2894
2912
|
}
|
|
2895
|
-
if (meta?.peerId && record.agent_id) {
|
|
2913
|
+
if (meta?.peerId && record.agent_id && !this.privatePeerRoutes[record.agent_id]) {
|
|
2896
2914
|
this.privatePeerRoutes[record.agent_id] = meta.peerId;
|
|
2897
2915
|
}
|
|
2898
2916
|
|
|
@@ -2911,7 +2929,7 @@ export class LocalNodeService {
|
|
|
2911
2929
|
await this.log("warn", `Rejected social message with invalid signature (${record.message_id.slice(0, 10)})`);
|
|
2912
2930
|
return;
|
|
2913
2931
|
}
|
|
2914
|
-
if (meta?.peerId && record.agent_id) {
|
|
2932
|
+
if (meta?.peerId && record.agent_id && !this.privatePeerRoutes[record.agent_id]) {
|
|
2915
2933
|
this.privatePeerRoutes[record.agent_id] = meta.peerId;
|
|
2916
2934
|
}
|
|
2917
2935
|
if (this.hasSocialMessage(record.message_id)) {
|
|
@@ -2962,6 +2980,12 @@ export class LocalNodeService {
|
|
|
2962
2980
|
if (!record || !verifyPrivateMessage(record)) {
|
|
2963
2981
|
return;
|
|
2964
2982
|
}
|
|
2983
|
+
if (meta?.peerId && record.from_agent_id) {
|
|
2984
|
+
this.privatePeerRoutes[record.from_agent_id] = meta.peerId;
|
|
2985
|
+
}
|
|
2986
|
+
if (record.from_agent_id && record.sender_encryption_public_key) {
|
|
2987
|
+
this.privatePeerEncryptionKeys[record.from_agent_id] = record.sender_encryption_public_key;
|
|
2988
|
+
}
|
|
2965
2989
|
if (record.to_agent_id !== this.identity?.agent_id || this.hasPrivateMessage(record.message_id)) {
|
|
2966
2990
|
return;
|
|
2967
2991
|
}
|
|
@@ -2975,6 +2999,9 @@ export class LocalNodeService {
|
|
|
2975
2999
|
if (!receipt || !verifyPrivateMessageReceipt(receipt)) {
|
|
2976
3000
|
return;
|
|
2977
3001
|
}
|
|
3002
|
+
if (meta?.peerId && receipt.from_agent_id) {
|
|
3003
|
+
this.privatePeerRoutes[receipt.from_agent_id] = meta.peerId;
|
|
3004
|
+
}
|
|
2978
3005
|
if (receipt.to_agent_id !== this.identity?.agent_id) {
|
|
2979
3006
|
return;
|
|
2980
3007
|
}
|
|
@@ -3323,7 +3350,40 @@ export class LocalNodeService {
|
|
|
3323
3350
|
return;
|
|
3324
3351
|
}
|
|
3325
3352
|
this.privateMessagesPersistDirty = false;
|
|
3326
|
-
await this.privateMessageRepo.set(this.
|
|
3353
|
+
await this.privateMessageRepo.set(this.buildPersistedPrivateMessages() as unknown as PrivateMessageRecord[]);
|
|
3354
|
+
}
|
|
3355
|
+
|
|
3356
|
+
private hydratePrivateMessageBodyCache(items: unknown): void {
|
|
3357
|
+
if (!Array.isArray(items)) {
|
|
3358
|
+
return;
|
|
3359
|
+
}
|
|
3360
|
+
for (const item of items) {
|
|
3361
|
+
if (typeof item !== "object" || item === null) {
|
|
3362
|
+
continue;
|
|
3363
|
+
}
|
|
3364
|
+
const record = item as Partial<StoredPrivateMessageRecord>;
|
|
3365
|
+
const messageId = String(record.message_id || "").trim();
|
|
3366
|
+
const localPlaintext = typeof record.local_plaintext === "string" ? record.local_plaintext : "";
|
|
3367
|
+
if (messageId && localPlaintext) {
|
|
3368
|
+
this.privateMessageBodyCache.set(messageId, localPlaintext);
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
|
|
3373
|
+
private buildPersistedPrivateMessages(): StoredPrivateMessageRecord[] {
|
|
3374
|
+
return this.privateMessages.map((message) => {
|
|
3375
|
+
const localPlaintext =
|
|
3376
|
+
message.from_agent_id === this.identity?.agent_id
|
|
3377
|
+
? this.privateMessageBodyCache.get(message.message_id) || ""
|
|
3378
|
+
: "";
|
|
3379
|
+
if (!localPlaintext) {
|
|
3380
|
+
return { ...message };
|
|
3381
|
+
}
|
|
3382
|
+
return {
|
|
3383
|
+
...message,
|
|
3384
|
+
local_plaintext: localPlaintext,
|
|
3385
|
+
};
|
|
3386
|
+
});
|
|
3327
3387
|
}
|
|
3328
3388
|
|
|
3329
3389
|
private async flushPrivateMessageReceiptsPersist(): Promise<void> {
|
|
@@ -3482,6 +3542,47 @@ export class LocalNodeService {
|
|
|
3482
3542
|
return `${digest.slice(0, 12)}:${digest.slice(-8)}`;
|
|
3483
3543
|
}
|
|
3484
3544
|
|
|
3545
|
+
private buildPrivateMessagingRuntimeState(): PrivateMessagingRuntimeState {
|
|
3546
|
+
const warnings: string[] = [];
|
|
3547
|
+
const keypair = this.privateEncryptionKeyPair;
|
|
3548
|
+
const selfSentMessages = this.privateMessages.filter((message) => message.from_agent_id === this.identity?.agent_id);
|
|
3549
|
+
let cachedPlaintextCount = 0;
|
|
3550
|
+
for (const message of selfSentMessages) {
|
|
3551
|
+
if (this.privateMessageBodyCache.get(message.message_id)) {
|
|
3552
|
+
cachedPlaintextCount += 1;
|
|
3553
|
+
}
|
|
3554
|
+
}
|
|
3555
|
+
if (!keypair?.public_key || !keypair?.private_key) {
|
|
3556
|
+
warnings.push("missing_private_encryption_keypair");
|
|
3557
|
+
}
|
|
3558
|
+
if (selfSentMessages.length > 0 && cachedPlaintextCount === 0) {
|
|
3559
|
+
warnings.push("missing_local_plaintext_cache_for_self_messages");
|
|
3560
|
+
}
|
|
3561
|
+
if (selfSentMessages.length > 0 && cachedPlaintextCount < selfSentMessages.length) {
|
|
3562
|
+
warnings.push("partial_local_plaintext_cache_for_self_messages");
|
|
3563
|
+
}
|
|
3564
|
+
return {
|
|
3565
|
+
schema_version: 1,
|
|
3566
|
+
app_version: this.appVersion,
|
|
3567
|
+
last_started_at: Date.now(),
|
|
3568
|
+
encryption_public_key: keypair?.public_key || "",
|
|
3569
|
+
encryption_public_key_fingerprint: keypair?.public_key ? this.fingerprintPublicKey(keypair.public_key) : "",
|
|
3570
|
+
message_count: this.privateMessages.length,
|
|
3571
|
+
self_sent_count: selfSentMessages.length,
|
|
3572
|
+
cached_plaintext_count: cachedPlaintextCount,
|
|
3573
|
+
warnings,
|
|
3574
|
+
};
|
|
3575
|
+
}
|
|
3576
|
+
|
|
3577
|
+
private async refreshPrivateMessagingRuntime(): Promise<void> {
|
|
3578
|
+
const runtime = this.buildPrivateMessagingRuntimeState();
|
|
3579
|
+
this.privateMessagingRuntime = runtime;
|
|
3580
|
+
await this.privateMessagingRuntimeRepo.set(runtime);
|
|
3581
|
+
for (const warning of runtime.warnings) {
|
|
3582
|
+
await this.log("warn", `Private messaging startup check: ${warning}`);
|
|
3583
|
+
}
|
|
3584
|
+
}
|
|
3585
|
+
|
|
3485
3586
|
private getOnboardingSummary() {
|
|
3486
3587
|
const summary = this.getIntegrationSummary();
|
|
3487
3588
|
const publicEnabled = Boolean(this.profile?.public_enabled);
|
|
@@ -3823,6 +3924,7 @@ export class LocalNodeService {
|
|
|
3823
3924
|
this.ingestPrivateMessageReceipt(receipt);
|
|
3824
3925
|
try {
|
|
3825
3926
|
await this.network.sendDirect(replyPeerId, PRIVATE_MESSAGE_RECEIPT_TOPIC, receipt);
|
|
3927
|
+
await this.publish(PRIVATE_MESSAGE_RECEIPT_TOPIC, receipt);
|
|
3826
3928
|
} catch {
|
|
3827
3929
|
await this.publish(PRIVATE_MESSAGE_RECEIPT_TOPIC, receipt);
|
|
3828
3930
|
}
|
|
@@ -40,6 +40,17 @@ export type SocialMessageGovernanceConfig = {
|
|
|
40
40
|
export type PrivateMessageDecryptedContent = {
|
|
41
41
|
body: string;
|
|
42
42
|
};
|
|
43
|
+
export type PrivateMessagingRuntimeState = {
|
|
44
|
+
schema_version: number;
|
|
45
|
+
app_version: string;
|
|
46
|
+
last_started_at: number;
|
|
47
|
+
encryption_public_key: string;
|
|
48
|
+
encryption_public_key_fingerprint: string;
|
|
49
|
+
message_count: number;
|
|
50
|
+
self_sent_count: number;
|
|
51
|
+
cached_plaintext_count: number;
|
|
52
|
+
warnings: string[];
|
|
53
|
+
};
|
|
43
54
|
export declare class IdentityRepo extends JsonFileRepo<AgentIdentity | null> {
|
|
44
55
|
constructor(rootDir?: string);
|
|
45
56
|
}
|
|
@@ -71,3 +82,6 @@ export declare class PrivateMessageReceiptRepo extends JsonFileRepo<PrivateMessa
|
|
|
71
82
|
export declare class PrivateEncryptionKeyRepo extends JsonFileRepo<PrivateEncryptionKeyPair | null> {
|
|
72
83
|
constructor(rootDir?: string);
|
|
73
84
|
}
|
|
85
|
+
export declare class PrivateMessagingRuntimeRepo extends JsonFileRepo<PrivateMessagingRuntimeState> {
|
|
86
|
+
constructor(rootDir?: string);
|
|
87
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PrivateEncryptionKeyRepo = exports.PrivateMessageReceiptRepo = exports.PrivateMessageRepo = exports.SocialMessageGovernanceRepo = exports.SocialMessageObservationRepo = exports.SocialMessageRepo = exports.LogRepo = exports.CacheRepo = exports.ProfileRepo = exports.IdentityRepo = void 0;
|
|
3
|
+
exports.PrivateMessagingRuntimeRepo = exports.PrivateEncryptionKeyRepo = exports.PrivateMessageReceiptRepo = exports.PrivateMessageRepo = exports.SocialMessageGovernanceRepo = exports.SocialMessageObservationRepo = exports.SocialMessageRepo = exports.LogRepo = exports.CacheRepo = exports.ProfileRepo = exports.IdentityRepo = void 0;
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
const core_1 = require("@silicaclaw/core");
|
|
6
6
|
const jsonRepo_1 = require("./jsonRepo");
|
|
@@ -83,3 +83,19 @@ class PrivateEncryptionKeyRepo extends jsonRepo_1.JsonFileRepo {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
exports.PrivateEncryptionKeyRepo = PrivateEncryptionKeyRepo;
|
|
86
|
+
class PrivateMessagingRuntimeRepo extends jsonRepo_1.JsonFileRepo {
|
|
87
|
+
constructor(rootDir = process.cwd()) {
|
|
88
|
+
super((0, path_1.resolve)(rootDir, ".silicaclaw", "private-messaging.runtime.json"), () => ({
|
|
89
|
+
schema_version: 1,
|
|
90
|
+
app_version: "",
|
|
91
|
+
last_started_at: 0,
|
|
92
|
+
encryption_public_key: "",
|
|
93
|
+
encryption_public_key_fingerprint: "",
|
|
94
|
+
message_count: 0,
|
|
95
|
+
self_sent_count: 0,
|
|
96
|
+
cached_plaintext_count: 0,
|
|
97
|
+
warnings: [],
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.PrivateMessagingRuntimeRepo = PrivateMessagingRuntimeRepo;
|
|
@@ -55,6 +55,18 @@ export type PrivateMessageDecryptedContent = {
|
|
|
55
55
|
body: string;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
+
export type PrivateMessagingRuntimeState = {
|
|
59
|
+
schema_version: number;
|
|
60
|
+
app_version: string;
|
|
61
|
+
last_started_at: number;
|
|
62
|
+
encryption_public_key: string;
|
|
63
|
+
encryption_public_key_fingerprint: string;
|
|
64
|
+
message_count: number;
|
|
65
|
+
self_sent_count: number;
|
|
66
|
+
cached_plaintext_count: number;
|
|
67
|
+
warnings: string[];
|
|
68
|
+
};
|
|
69
|
+
|
|
58
70
|
export class IdentityRepo extends JsonFileRepo<AgentIdentity | null> {
|
|
59
71
|
constructor(rootDir = process.cwd()) {
|
|
60
72
|
super(resolve(rootDir, "data", "identity.json"), () => null);
|
|
@@ -134,3 +146,19 @@ export class PrivateEncryptionKeyRepo extends JsonFileRepo<PrivateEncryptionKeyP
|
|
|
134
146
|
super(resolve(rootDir, "data", "private-encryption-keypair.json"), () => null);
|
|
135
147
|
}
|
|
136
148
|
}
|
|
149
|
+
|
|
150
|
+
export class PrivateMessagingRuntimeRepo extends JsonFileRepo<PrivateMessagingRuntimeState> {
|
|
151
|
+
constructor(rootDir = process.cwd()) {
|
|
152
|
+
super(resolve(rootDir, ".silicaclaw", "private-messaging.runtime.json"), () => ({
|
|
153
|
+
schema_version: 1,
|
|
154
|
+
app_version: "",
|
|
155
|
+
last_started_at: 0,
|
|
156
|
+
encryption_public_key: "",
|
|
157
|
+
encryption_public_key_fingerprint: "",
|
|
158
|
+
message_count: 0,
|
|
159
|
+
self_sent_count: 0,
|
|
160
|
+
cached_plaintext_count: 0,
|
|
161
|
+
warnings: [],
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
2026.3.20-beta.
|
|
1
|
+
2026.3.20-beta.19
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "silicaclaw-broadcast",
|
|
3
|
-
"version": "2026.3.20-beta.
|
|
3
|
+
"version": "2026.3.20-beta.19",
|
|
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": {
|
package/package.json
CHANGED
|
@@ -40,6 +40,17 @@ export type SocialMessageGovernanceConfig = {
|
|
|
40
40
|
export type PrivateMessageDecryptedContent = {
|
|
41
41
|
body: string;
|
|
42
42
|
};
|
|
43
|
+
export type PrivateMessagingRuntimeState = {
|
|
44
|
+
schema_version: number;
|
|
45
|
+
app_version: string;
|
|
46
|
+
last_started_at: number;
|
|
47
|
+
encryption_public_key: string;
|
|
48
|
+
encryption_public_key_fingerprint: string;
|
|
49
|
+
message_count: number;
|
|
50
|
+
self_sent_count: number;
|
|
51
|
+
cached_plaintext_count: number;
|
|
52
|
+
warnings: string[];
|
|
53
|
+
};
|
|
43
54
|
export declare class IdentityRepo extends JsonFileRepo<AgentIdentity | null> {
|
|
44
55
|
constructor(rootDir?: string);
|
|
45
56
|
}
|
|
@@ -71,3 +82,6 @@ export declare class PrivateMessageReceiptRepo extends JsonFileRepo<PrivateMessa
|
|
|
71
82
|
export declare class PrivateEncryptionKeyRepo extends JsonFileRepo<PrivateEncryptionKeyPair | null> {
|
|
72
83
|
constructor(rootDir?: string);
|
|
73
84
|
}
|
|
85
|
+
export declare class PrivateMessagingRuntimeRepo extends JsonFileRepo<PrivateMessagingRuntimeState> {
|
|
86
|
+
constructor(rootDir?: string);
|
|
87
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PrivateEncryptionKeyRepo = exports.PrivateMessageReceiptRepo = exports.PrivateMessageRepo = exports.SocialMessageGovernanceRepo = exports.SocialMessageObservationRepo = exports.SocialMessageRepo = exports.LogRepo = exports.CacheRepo = exports.ProfileRepo = exports.IdentityRepo = void 0;
|
|
3
|
+
exports.PrivateMessagingRuntimeRepo = exports.PrivateEncryptionKeyRepo = exports.PrivateMessageReceiptRepo = exports.PrivateMessageRepo = exports.SocialMessageGovernanceRepo = exports.SocialMessageObservationRepo = exports.SocialMessageRepo = exports.LogRepo = exports.CacheRepo = exports.ProfileRepo = exports.IdentityRepo = void 0;
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
const core_1 = require("@silicaclaw/core");
|
|
6
6
|
const jsonRepo_1 = require("./jsonRepo");
|
|
@@ -83,3 +83,19 @@ class PrivateEncryptionKeyRepo extends jsonRepo_1.JsonFileRepo {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
exports.PrivateEncryptionKeyRepo = PrivateEncryptionKeyRepo;
|
|
86
|
+
class PrivateMessagingRuntimeRepo extends jsonRepo_1.JsonFileRepo {
|
|
87
|
+
constructor(rootDir = process.cwd()) {
|
|
88
|
+
super((0, path_1.resolve)(rootDir, ".silicaclaw", "private-messaging.runtime.json"), () => ({
|
|
89
|
+
schema_version: 1,
|
|
90
|
+
app_version: "",
|
|
91
|
+
last_started_at: 0,
|
|
92
|
+
encryption_public_key: "",
|
|
93
|
+
encryption_public_key_fingerprint: "",
|
|
94
|
+
message_count: 0,
|
|
95
|
+
self_sent_count: 0,
|
|
96
|
+
cached_plaintext_count: 0,
|
|
97
|
+
warnings: [],
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.PrivateMessagingRuntimeRepo = PrivateMessagingRuntimeRepo;
|
|
@@ -55,6 +55,18 @@ export type PrivateMessageDecryptedContent = {
|
|
|
55
55
|
body: string;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
+
export type PrivateMessagingRuntimeState = {
|
|
59
|
+
schema_version: number;
|
|
60
|
+
app_version: string;
|
|
61
|
+
last_started_at: number;
|
|
62
|
+
encryption_public_key: string;
|
|
63
|
+
encryption_public_key_fingerprint: string;
|
|
64
|
+
message_count: number;
|
|
65
|
+
self_sent_count: number;
|
|
66
|
+
cached_plaintext_count: number;
|
|
67
|
+
warnings: string[];
|
|
68
|
+
};
|
|
69
|
+
|
|
58
70
|
export class IdentityRepo extends JsonFileRepo<AgentIdentity | null> {
|
|
59
71
|
constructor(rootDir = process.cwd()) {
|
|
60
72
|
super(resolve(rootDir, "data", "identity.json"), () => null);
|
|
@@ -134,3 +146,19 @@ export class PrivateEncryptionKeyRepo extends JsonFileRepo<PrivateEncryptionKeyP
|
|
|
134
146
|
super(resolve(rootDir, "data", "private-encryption-keypair.json"), () => null);
|
|
135
147
|
}
|
|
136
148
|
}
|
|
149
|
+
|
|
150
|
+
export class PrivateMessagingRuntimeRepo extends JsonFileRepo<PrivateMessagingRuntimeState> {
|
|
151
|
+
constructor(rootDir = process.cwd()) {
|
|
152
|
+
super(resolve(rootDir, ".silicaclaw", "private-messaging.runtime.json"), () => ({
|
|
153
|
+
schema_version: 1,
|
|
154
|
+
app_version: "",
|
|
155
|
+
last_started_at: 0,
|
|
156
|
+
encryption_public_key: "",
|
|
157
|
+
encryption_public_key_fingerprint: "",
|
|
158
|
+
message_count: 0,
|
|
159
|
+
self_sent_count: 0,
|
|
160
|
+
cached_plaintext_count: 0,
|
|
161
|
+
warnings: [],
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
164
|
+
}
|