@silicaclaw/cli 2026.3.20-1 → 2026.3.20-11

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.
Files changed (143) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/INSTALL.md +13 -7
  3. package/README.md +60 -12
  4. package/VERSION +1 -1
  5. package/apps/local-console/dist/apps/local-console/src/server.d.ts +129 -2
  6. package/apps/local-console/dist/apps/local-console/src/server.js +887 -91
  7. package/apps/local-console/dist/packages/core/src/index.d.ts +2 -0
  8. package/apps/local-console/dist/packages/core/src/index.js +2 -0
  9. package/apps/local-console/dist/packages/core/src/privateCrypto.d.ts +17 -0
  10. package/apps/local-console/dist/packages/core/src/privateCrypto.js +40 -0
  11. package/apps/local-console/dist/packages/core/src/privateMessage.d.ts +23 -0
  12. package/apps/local-console/dist/packages/core/src/privateMessage.js +74 -0
  13. package/apps/local-console/dist/packages/core/src/profile.js +2 -0
  14. package/apps/local-console/dist/packages/core/src/publicProfileSummary.d.ts +4 -0
  15. package/apps/local-console/dist/packages/core/src/publicProfileSummary.js +3 -0
  16. package/apps/local-console/dist/packages/core/src/types.d.ts +40 -0
  17. package/apps/local-console/dist/packages/network/src/relayPreview.d.ts +12 -0
  18. package/apps/local-console/dist/packages/network/src/relayPreview.js +108 -8
  19. package/apps/local-console/dist/packages/network/src/types.d.ts +4 -0
  20. package/apps/local-console/dist/packages/storage/src/repos.d.ts +13 -1
  21. package/apps/local-console/dist/packages/storage/src/repos.js +19 -1
  22. package/apps/local-console/public/app/app.js +465 -11
  23. package/apps/local-console/public/app/events.js +21 -0
  24. package/apps/local-console/public/app/network.js +144 -32
  25. package/apps/local-console/public/app/overview.js +60 -52
  26. package/apps/local-console/public/app/social.js +316 -93
  27. package/apps/local-console/public/app/styles.css +127 -1
  28. package/apps/local-console/public/app/template.js +121 -35
  29. package/apps/local-console/public/app/translations.js +430 -316
  30. package/apps/local-console/src/server.ts +1024 -89
  31. package/apps/public-explorer/public/app/template.js +2 -2
  32. package/apps/public-explorer/public/app/translations.js +36 -36
  33. package/docs/NEW_USER_OPERATIONS.md +5 -5
  34. package/docs/OPENCLAW_BRIDGE.md +7 -7
  35. package/docs/OPENCLAW_BRIDGE_ZH.md +6 -6
  36. package/node_modules/@silicaclaw/core/dist/packages/core/src/index.d.ts +2 -0
  37. package/node_modules/@silicaclaw/core/dist/packages/core/src/index.js +2 -0
  38. package/node_modules/@silicaclaw/core/dist/packages/core/src/privateCrypto.d.ts +17 -0
  39. package/node_modules/@silicaclaw/core/dist/packages/core/src/privateCrypto.js +40 -0
  40. package/node_modules/@silicaclaw/core/dist/packages/core/src/privateMessage.d.ts +23 -0
  41. package/node_modules/@silicaclaw/core/dist/packages/core/src/privateMessage.js +74 -0
  42. package/node_modules/@silicaclaw/core/dist/packages/core/src/profile.js +2 -0
  43. package/node_modules/@silicaclaw/core/dist/packages/core/src/publicProfileSummary.d.ts +4 -0
  44. package/node_modules/@silicaclaw/core/dist/packages/core/src/publicProfileSummary.js +3 -0
  45. package/node_modules/@silicaclaw/core/dist/packages/core/src/types.d.ts +40 -0
  46. package/node_modules/@silicaclaw/core/src/index.ts +2 -0
  47. package/node_modules/@silicaclaw/core/src/privateCrypto.ts +57 -0
  48. package/node_modules/@silicaclaw/core/src/privateMessage.ts +101 -0
  49. package/node_modules/@silicaclaw/core/src/profile.ts +2 -0
  50. package/node_modules/@silicaclaw/core/src/publicProfileSummary.ts +7 -0
  51. package/node_modules/@silicaclaw/core/src/types.ts +44 -0
  52. package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.d.ts +12 -0
  53. package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.js +108 -8
  54. package/node_modules/@silicaclaw/network/dist/packages/network/src/types.d.ts +4 -0
  55. package/node_modules/@silicaclaw/network/src/relayPreview.ts +120 -10
  56. package/node_modules/@silicaclaw/network/src/types.ts +2 -0
  57. package/node_modules/@silicaclaw/storage/dist/packages/core/src/index.d.ts +2 -0
  58. package/node_modules/@silicaclaw/storage/dist/packages/core/src/index.js +2 -0
  59. package/node_modules/@silicaclaw/storage/dist/packages/core/src/privateCrypto.d.ts +17 -0
  60. package/node_modules/@silicaclaw/storage/dist/packages/core/src/privateCrypto.js +40 -0
  61. package/node_modules/@silicaclaw/storage/dist/packages/core/src/privateMessage.d.ts +23 -0
  62. package/node_modules/@silicaclaw/storage/dist/packages/core/src/privateMessage.js +74 -0
  63. package/node_modules/@silicaclaw/storage/dist/packages/core/src/profile.js +2 -0
  64. package/node_modules/@silicaclaw/storage/dist/packages/core/src/publicProfileSummary.d.ts +4 -0
  65. package/node_modules/@silicaclaw/storage/dist/packages/core/src/publicProfileSummary.js +3 -0
  66. package/node_modules/@silicaclaw/storage/dist/packages/core/src/types.d.ts +40 -0
  67. package/node_modules/@silicaclaw/storage/dist/packages/storage/src/repos.d.ts +13 -1
  68. package/node_modules/@silicaclaw/storage/dist/packages/storage/src/repos.js +19 -1
  69. package/node_modules/@silicaclaw/storage/package.json +2 -2
  70. package/node_modules/@silicaclaw/storage/src/repos.ts +31 -1
  71. package/openclaw-skills/silicaclaw-bridge-setup/SKILL.md +18 -0
  72. package/openclaw-skills/silicaclaw-bridge-setup/VERSION +1 -1
  73. package/openclaw-skills/silicaclaw-bridge-setup/manifest.json +2 -2
  74. package/openclaw-skills/silicaclaw-broadcast/SKILL.md +18 -0
  75. package/openclaw-skills/silicaclaw-broadcast/VERSION +1 -1
  76. package/openclaw-skills/silicaclaw-broadcast/manifest.json +2 -2
  77. package/openclaw-skills/silicaclaw-network-config/SKILL.md +158 -0
  78. package/openclaw-skills/silicaclaw-network-config/VERSION +1 -0
  79. package/openclaw-skills/silicaclaw-network-config/agents/openai.yaml +6 -0
  80. package/openclaw-skills/silicaclaw-network-config/manifest.json +27 -0
  81. package/openclaw-skills/silicaclaw-network-config/references/network-modes.md +22 -0
  82. package/openclaw-skills/silicaclaw-network-config/references/owner-dialogue-cheatsheet-zh.md +47 -0
  83. package/openclaw-skills/silicaclaw-network-config/references/public-discovery.md +22 -0
  84. package/openclaw-skills/silicaclaw-owner-push/SKILL.md +18 -0
  85. package/openclaw-skills/silicaclaw-owner-push/VERSION +1 -1
  86. package/openclaw-skills/silicaclaw-owner-push/manifest.json +2 -2
  87. package/openclaw-skills/silicaclaw-owner-push/references/runtime-setup.md +3 -0
  88. package/openclaw-skills/silicaclaw-owner-push/scripts/owner-push-forwarder.mjs +151 -9
  89. package/package.json +1 -1
  90. package/packages/core/dist/packages/core/src/index.d.ts +2 -0
  91. package/packages/core/dist/packages/core/src/index.js +2 -0
  92. package/packages/core/dist/packages/core/src/privateCrypto.d.ts +17 -0
  93. package/packages/core/dist/packages/core/src/privateCrypto.js +40 -0
  94. package/packages/core/dist/packages/core/src/privateMessage.d.ts +23 -0
  95. package/packages/core/dist/packages/core/src/privateMessage.js +74 -0
  96. package/packages/core/dist/packages/core/src/profile.js +2 -0
  97. package/packages/core/dist/packages/core/src/publicProfileSummary.d.ts +4 -0
  98. package/packages/core/dist/packages/core/src/publicProfileSummary.js +3 -0
  99. package/packages/core/dist/packages/core/src/types.d.ts +40 -0
  100. package/packages/core/src/index.ts +2 -0
  101. package/packages/core/src/privateCrypto.ts +57 -0
  102. package/packages/core/src/privateMessage.ts +101 -0
  103. package/packages/core/src/profile.ts +2 -0
  104. package/packages/core/src/publicProfileSummary.ts +7 -0
  105. package/packages/core/src/types.ts +44 -0
  106. package/packages/network/dist/packages/network/src/relayPreview.d.ts +12 -0
  107. package/packages/network/dist/packages/network/src/relayPreview.js +108 -8
  108. package/packages/network/dist/packages/network/src/types.d.ts +4 -0
  109. package/packages/network/src/relayPreview.ts +120 -10
  110. package/packages/network/src/types.ts +2 -0
  111. package/packages/storage/dist/packages/core/src/index.d.ts +2 -0
  112. package/packages/storage/dist/packages/core/src/index.js +2 -0
  113. package/packages/storage/dist/packages/core/src/privateCrypto.d.ts +17 -0
  114. package/packages/storage/dist/packages/core/src/privateCrypto.js +40 -0
  115. package/packages/storage/dist/packages/core/src/privateMessage.d.ts +23 -0
  116. package/packages/storage/dist/packages/core/src/privateMessage.js +74 -0
  117. package/packages/storage/dist/packages/core/src/profile.js +2 -0
  118. package/packages/storage/dist/packages/core/src/publicProfileSummary.d.ts +4 -0
  119. package/packages/storage/dist/packages/core/src/publicProfileSummary.js +3 -0
  120. package/packages/storage/dist/packages/core/src/types.d.ts +40 -0
  121. package/packages/storage/dist/packages/storage/src/repos.d.ts +13 -1
  122. package/packages/storage/dist/packages/storage/src/repos.js +19 -1
  123. package/packages/storage/package.json +2 -2
  124. package/packages/storage/src/repos.ts +31 -1
  125. package/scripts/silicaclaw-cli.mjs +59 -6
  126. package/scripts/silicaclaw-gateway.mjs +108 -0
  127. package/scripts/validate-openclaw-skill.mjs +19 -0
  128. package/node_modules/@silicaclaw/storage/dist/index.d.ts +0 -3
  129. package/node_modules/@silicaclaw/storage/dist/index.js +0 -19
  130. package/node_modules/@silicaclaw/storage/dist/jsonRepo.d.ts +0 -7
  131. package/node_modules/@silicaclaw/storage/dist/jsonRepo.js +0 -29
  132. package/node_modules/@silicaclaw/storage/dist/repos.d.ts +0 -61
  133. package/node_modules/@silicaclaw/storage/dist/repos.js +0 -67
  134. package/node_modules/@silicaclaw/storage/dist/socialRuntimeRepo.d.ts +0 -5
  135. package/node_modules/@silicaclaw/storage/dist/socialRuntimeRepo.js +0 -57
  136. package/packages/storage/dist/index.d.ts +0 -3
  137. package/packages/storage/dist/index.js +0 -19
  138. package/packages/storage/dist/jsonRepo.d.ts +0 -7
  139. package/packages/storage/dist/jsonRepo.js +0 -29
  140. package/packages/storage/dist/repos.d.ts +0 -61
  141. package/packages/storage/dist/repos.js +0 -67
  142. package/packages/storage/dist/socialRuntimeRepo.d.ts +0 -5
  143. package/packages/storage/dist/socialRuntimeRepo.js +0 -57
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silicaclaw/cli",
3
- "version": "2026.3.20-1",
3
+ "version": "2026.3.20-11",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -4,6 +4,8 @@ export * from "./identity";
4
4
  export * from "./profile";
5
5
  export * from "./presence";
6
6
  export * from "./socialMessage";
7
+ export * from "./privateCrypto";
8
+ export * from "./privateMessage";
7
9
  export * from "./indexing";
8
10
  export * from "./directory";
9
11
  export * from "./publicProfileSummary";
@@ -20,6 +20,8 @@ __exportStar(require("./identity"), exports);
20
20
  __exportStar(require("./profile"), exports);
21
21
  __exportStar(require("./presence"), exports);
22
22
  __exportStar(require("./socialMessage"), exports);
23
+ __exportStar(require("./privateCrypto"), exports);
24
+ __exportStar(require("./privateMessage"), exports);
23
25
  __exportStar(require("./indexing"), exports);
24
26
  __exportStar(require("./directory"), exports);
25
27
  __exportStar(require("./publicProfileSummary"), exports);
@@ -0,0 +1,17 @@
1
+ import { PrivateEncryptionKeyPair } from "./types";
2
+ export declare function createPrivateEncryptionKeyPair(now?: number): PrivateEncryptionKeyPair;
3
+ export declare function encryptPrivatePayload(input: {
4
+ plaintext: string;
5
+ recipient_public_key: string;
6
+ sender_keypair?: PrivateEncryptionKeyPair | null;
7
+ }): {
8
+ ciphertext: string;
9
+ nonce: string;
10
+ sender_encryption_public_key: string;
11
+ };
12
+ export declare function decryptPrivatePayload(input: {
13
+ ciphertext: string;
14
+ nonce: string;
15
+ sender_encryption_public_key: string;
16
+ recipient_private_key: string;
17
+ }): string | null;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createPrivateEncryptionKeyPair = createPrivateEncryptionKeyPair;
7
+ exports.encryptPrivatePayload = encryptPrivatePayload;
8
+ exports.decryptPrivatePayload = decryptPrivatePayload;
9
+ const tweetnacl_1 = __importDefault(require("tweetnacl"));
10
+ const crypto_1 = require("./crypto");
11
+ function createPrivateEncryptionKeyPair(now = Date.now()) {
12
+ const pair = tweetnacl_1.default.box.keyPair();
13
+ return {
14
+ public_key: (0, crypto_1.toBase64)(pair.publicKey),
15
+ private_key: (0, crypto_1.toBase64)(pair.secretKey),
16
+ created_at: now,
17
+ };
18
+ }
19
+ function encryptPrivatePayload(input) {
20
+ const sender = input.sender_keypair || createPrivateEncryptionKeyPair();
21
+ const nonce = tweetnacl_1.default.randomBytes(tweetnacl_1.default.box.nonceLength);
22
+ const message = Buffer.from(String(input.plaintext || ""), "utf8");
23
+ const ciphertext = tweetnacl_1.default.box(new Uint8Array(message), nonce, (0, crypto_1.fromBase64)(input.recipient_public_key), (0, crypto_1.fromBase64)(sender.private_key));
24
+ return {
25
+ ciphertext: (0, crypto_1.toBase64)(ciphertext),
26
+ nonce: (0, crypto_1.toBase64)(nonce),
27
+ sender_encryption_public_key: sender.public_key,
28
+ };
29
+ }
30
+ function decryptPrivatePayload(input) {
31
+ try {
32
+ const opened = tweetnacl_1.default.box.open((0, crypto_1.fromBase64)(input.ciphertext), (0, crypto_1.fromBase64)(input.nonce), (0, crypto_1.fromBase64)(input.sender_encryption_public_key), (0, crypto_1.fromBase64)(input.recipient_private_key));
33
+ if (!opened)
34
+ return null;
35
+ return Buffer.from(opened).toString("utf8");
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
@@ -0,0 +1,23 @@
1
+ import { AgentIdentity, PrivateMessageReceiptRecord, PrivateMessageRecord } from "./types";
2
+ export declare function signPrivateMessage(input: {
3
+ identity: AgentIdentity;
4
+ message_id: string;
5
+ conversation_id: string;
6
+ to_agent_id: string;
7
+ sender_encryption_public_key: string;
8
+ recipient_encryption_public_key: string;
9
+ ciphertext: string;
10
+ nonce: string;
11
+ created_at?: number;
12
+ }): PrivateMessageRecord;
13
+ export declare function verifyPrivateMessage(record: PrivateMessageRecord): boolean;
14
+ export declare function signPrivateMessageReceipt(input: {
15
+ identity: AgentIdentity;
16
+ receipt_id: string;
17
+ message_id: string;
18
+ conversation_id: string;
19
+ to_agent_id: string;
20
+ status: "received" | "read";
21
+ created_at?: number;
22
+ }): PrivateMessageReceiptRecord;
23
+ export declare function verifyPrivateMessageReceipt(record: PrivateMessageReceiptRecord): boolean;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.signPrivateMessage = signPrivateMessage;
4
+ exports.verifyPrivateMessage = verifyPrivateMessage;
5
+ exports.signPrivateMessageReceipt = signPrivateMessageReceipt;
6
+ exports.verifyPrivateMessageReceipt = verifyPrivateMessageReceipt;
7
+ const crypto_1 = require("./crypto");
8
+ function unsignedPrivateMessage(record) {
9
+ const { signature: _signature, ...rest } = record;
10
+ return rest;
11
+ }
12
+ function unsignedPrivateMessageReceipt(record) {
13
+ const { signature: _signature, ...rest } = record;
14
+ return rest;
15
+ }
16
+ function signPrivateMessage(input) {
17
+ const payload = {
18
+ type: "private.message",
19
+ message_id: input.message_id,
20
+ conversation_id: input.conversation_id,
21
+ from_agent_id: input.identity.agent_id,
22
+ to_agent_id: input.to_agent_id,
23
+ sender_public_key: input.identity.public_key,
24
+ sender_encryption_public_key: input.sender_encryption_public_key,
25
+ recipient_encryption_public_key: input.recipient_encryption_public_key,
26
+ cipher_scheme: "nacl-box-v1",
27
+ ciphertext: input.ciphertext,
28
+ nonce: input.nonce,
29
+ created_at: input.created_at ?? Date.now(),
30
+ };
31
+ return {
32
+ ...payload,
33
+ signature: (0, crypto_1.signPayload)(payload, input.identity.private_key),
34
+ };
35
+ }
36
+ function verifyPrivateMessage(record) {
37
+ try {
38
+ if ((0, crypto_1.hashPublicKey)((0, crypto_1.fromBase64)(record.sender_public_key)) !== record.from_agent_id) {
39
+ return false;
40
+ }
41
+ return (0, crypto_1.verifyPayload)(unsignedPrivateMessage(record), record.signature, record.sender_public_key);
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ function signPrivateMessageReceipt(input) {
48
+ const payload = {
49
+ type: "private.message.receipt",
50
+ receipt_id: input.receipt_id,
51
+ message_id: input.message_id,
52
+ conversation_id: input.conversation_id,
53
+ from_agent_id: input.identity.agent_id,
54
+ to_agent_id: input.to_agent_id,
55
+ sender_public_key: input.identity.public_key,
56
+ status: input.status,
57
+ created_at: input.created_at ?? Date.now(),
58
+ };
59
+ return {
60
+ ...payload,
61
+ signature: (0, crypto_1.signPayload)(payload, input.identity.private_key),
62
+ };
63
+ }
64
+ function verifyPrivateMessageReceipt(record) {
65
+ try {
66
+ if ((0, crypto_1.hashPublicKey)((0, crypto_1.fromBase64)(record.sender_public_key)) !== record.from_agent_id) {
67
+ return false;
68
+ }
69
+ return (0, crypto_1.verifyPayload)(unsignedPrivateMessageReceipt(record), record.signature, record.sender_public_key);
70
+ }
71
+ catch {
72
+ return false;
73
+ }
74
+ }
@@ -15,6 +15,7 @@ function signProfile(input, identity) {
15
15
  bio: input.bio,
16
16
  tags: input.tags,
17
17
  avatar_url: input.avatar_url,
18
+ private_encryption_public_key: input.private_encryption_public_key,
18
19
  public_enabled: input.public_enabled,
19
20
  updated_at: Date.now(),
20
21
  };
@@ -34,6 +35,7 @@ function createDefaultProfileInput(agentId) {
34
35
  bio: "",
35
36
  tags: [],
36
37
  avatar_url: "",
38
+ private_encryption_public_key: "",
37
39
  public_enabled: false,
38
40
  };
39
41
  }
@@ -7,9 +7,11 @@ export type ProfileVisibility = {
7
7
  };
8
8
  export type PublicProfileSummary = {
9
9
  agent_id: string;
10
+ is_self: boolean;
10
11
  display_name: string;
11
12
  bio: string;
12
13
  avatar_url?: string;
14
+ private_encryption_public_key?: string;
13
15
  public_enabled: boolean;
14
16
  updated_at: number;
15
17
  online: boolean;
@@ -30,6 +32,7 @@ export type PublicProfileSummary = {
30
32
  display_name: string;
31
33
  bio: string;
32
34
  avatar_url?: string;
35
+ private_encryption_public_key?: string;
33
36
  tags: string[];
34
37
  public_enabled: boolean;
35
38
  profile_version: string;
@@ -57,6 +60,7 @@ export type PublicProfileSummary = {
57
60
  export declare function deriveCapabilitiesSummary(tags: string[]): string[];
58
61
  export declare function buildPublicProfileSummary(args: {
59
62
  profile: PublicProfile;
63
+ is_self?: boolean;
60
64
  online: boolean;
61
65
  last_seen_at: number | null;
62
66
  network_mode?: string;
@@ -53,9 +53,11 @@ function buildPublicProfileSummary(args) {
53
53
  ].filter((field) => Boolean(field));
54
54
  return {
55
55
  agent_id: args.profile.agent_id,
56
+ is_self: Boolean(args.is_self),
56
57
  display_name: args.profile.display_name,
57
58
  bio: args.profile.bio,
58
59
  avatar_url: args.profile.avatar_url,
60
+ private_encryption_public_key: args.profile.private_encryption_public_key,
59
61
  public_enabled: args.profile.public_enabled,
60
62
  updated_at: args.profile.updated_at,
61
63
  online: args.online,
@@ -76,6 +78,7 @@ function buildPublicProfileSummary(args) {
76
78
  display_name: args.profile.display_name,
77
79
  bio: args.profile.bio,
78
80
  avatar_url: args.profile.avatar_url,
81
+ private_encryption_public_key: args.profile.private_encryption_public_key,
79
82
  tags,
80
83
  public_enabled: args.profile.public_enabled,
81
84
  profile_version: args.profile_version ?? "v1",
@@ -4,12 +4,18 @@ export type AgentIdentity = {
4
4
  private_key: string;
5
5
  created_at: number;
6
6
  };
7
+ export type PrivateEncryptionKeyPair = {
8
+ public_key: string;
9
+ private_key: string;
10
+ created_at: number;
11
+ };
7
12
  export type PublicProfile = {
8
13
  agent_id: string;
9
14
  display_name: string;
10
15
  bio: string;
11
16
  tags: string[];
12
17
  avatar_url?: string;
18
+ private_encryption_public_key?: string;
13
19
  public_enabled: boolean;
14
20
  updated_at: number;
15
21
  signature: string;
@@ -51,6 +57,40 @@ export type SocialMessageObservationRecord = {
51
57
  observed_at: number;
52
58
  signature: string;
53
59
  };
60
+ export type PrivateMessageRecord = {
61
+ type: "private.message";
62
+ message_id: string;
63
+ conversation_id: string;
64
+ from_agent_id: string;
65
+ to_agent_id: string;
66
+ sender_public_key: string;
67
+ sender_encryption_public_key: string;
68
+ recipient_encryption_public_key: string;
69
+ cipher_scheme: "nacl-box-v1";
70
+ ciphertext: string;
71
+ nonce: string;
72
+ created_at: number;
73
+ signature: string;
74
+ };
75
+ export type PrivateMessageReceiptRecord = {
76
+ type: "private.message.receipt";
77
+ receipt_id: string;
78
+ message_id: string;
79
+ conversation_id: string;
80
+ from_agent_id: string;
81
+ to_agent_id: string;
82
+ sender_public_key: string;
83
+ status: "received" | "read";
84
+ created_at: number;
85
+ signature: string;
86
+ };
87
+ export type PrivateConversationSummary = {
88
+ conversation_id: string;
89
+ peer_agent_id: string;
90
+ last_message_at: number | null;
91
+ last_message_preview: string;
92
+ unread_count: number;
93
+ };
54
94
  export type DirectoryState = {
55
95
  profiles: Record<string, PublicProfile>;
56
96
  presence: Record<string, number>;
@@ -4,6 +4,8 @@ export * from "./identity";
4
4
  export * from "./profile";
5
5
  export * from "./presence";
6
6
  export * from "./socialMessage";
7
+ export * from "./privateCrypto";
8
+ export * from "./privateMessage";
7
9
  export * from "./indexing";
8
10
  export * from "./directory";
9
11
  export * from "./publicProfileSummary";
@@ -0,0 +1,57 @@
1
+ import nacl from "tweetnacl";
2
+ import { fromBase64, toBase64 } from "./crypto";
3
+ import { PrivateEncryptionKeyPair } from "./types";
4
+
5
+ export function createPrivateEncryptionKeyPair(now = Date.now()): PrivateEncryptionKeyPair {
6
+ const pair = nacl.box.keyPair();
7
+ return {
8
+ public_key: toBase64(pair.publicKey),
9
+ private_key: toBase64(pair.secretKey),
10
+ created_at: now,
11
+ };
12
+ }
13
+
14
+ export function encryptPrivatePayload(input: {
15
+ plaintext: string;
16
+ recipient_public_key: string;
17
+ sender_keypair?: PrivateEncryptionKeyPair | null;
18
+ }): {
19
+ ciphertext: string;
20
+ nonce: string;
21
+ sender_encryption_public_key: string;
22
+ } {
23
+ const sender = input.sender_keypair || createPrivateEncryptionKeyPair();
24
+ const nonce = nacl.randomBytes(nacl.box.nonceLength);
25
+ const message = Buffer.from(String(input.plaintext || ""), "utf8");
26
+ const ciphertext = nacl.box(
27
+ new Uint8Array(message),
28
+ nonce,
29
+ fromBase64(input.recipient_public_key),
30
+ fromBase64(sender.private_key),
31
+ );
32
+ return {
33
+ ciphertext: toBase64(ciphertext),
34
+ nonce: toBase64(nonce),
35
+ sender_encryption_public_key: sender.public_key,
36
+ };
37
+ }
38
+
39
+ export function decryptPrivatePayload(input: {
40
+ ciphertext: string;
41
+ nonce: string;
42
+ sender_encryption_public_key: string;
43
+ recipient_private_key: string;
44
+ }): string | null {
45
+ try {
46
+ const opened = nacl.box.open(
47
+ fromBase64(input.ciphertext),
48
+ fromBase64(input.nonce),
49
+ fromBase64(input.sender_encryption_public_key),
50
+ fromBase64(input.recipient_private_key),
51
+ );
52
+ if (!opened) return null;
53
+ return Buffer.from(opened).toString("utf8");
54
+ } catch {
55
+ return null;
56
+ }
57
+ }
@@ -0,0 +1,101 @@
1
+ import {
2
+ AgentIdentity,
3
+ PrivateMessageReceiptRecord,
4
+ PrivateMessageRecord,
5
+ } from "./types";
6
+ import { fromBase64, hashPublicKey, signPayload, verifyPayload } from "./crypto";
7
+
8
+ function unsignedPrivateMessage(
9
+ record: PrivateMessageRecord
10
+ ): Omit<PrivateMessageRecord, "signature"> {
11
+ const { signature: _signature, ...rest } = record;
12
+ return rest;
13
+ }
14
+
15
+ function unsignedPrivateMessageReceipt(
16
+ record: PrivateMessageReceiptRecord
17
+ ): Omit<PrivateMessageReceiptRecord, "signature"> {
18
+ const { signature: _signature, ...rest } = record;
19
+ return rest;
20
+ }
21
+
22
+ export function signPrivateMessage(input: {
23
+ identity: AgentIdentity;
24
+ message_id: string;
25
+ conversation_id: string;
26
+ to_agent_id: string;
27
+ sender_encryption_public_key: string;
28
+ recipient_encryption_public_key: string;
29
+ ciphertext: string;
30
+ nonce: string;
31
+ created_at?: number;
32
+ }): PrivateMessageRecord {
33
+ const payload: Omit<PrivateMessageRecord, "signature"> = {
34
+ type: "private.message",
35
+ message_id: input.message_id,
36
+ conversation_id: input.conversation_id,
37
+ from_agent_id: input.identity.agent_id,
38
+ to_agent_id: input.to_agent_id,
39
+ sender_public_key: input.identity.public_key,
40
+ sender_encryption_public_key: input.sender_encryption_public_key,
41
+ recipient_encryption_public_key: input.recipient_encryption_public_key,
42
+ cipher_scheme: "nacl-box-v1",
43
+ ciphertext: input.ciphertext,
44
+ nonce: input.nonce,
45
+ created_at: input.created_at ?? Date.now(),
46
+ };
47
+
48
+ return {
49
+ ...payload,
50
+ signature: signPayload(payload, input.identity.private_key),
51
+ };
52
+ }
53
+
54
+ export function verifyPrivateMessage(record: PrivateMessageRecord): boolean {
55
+ try {
56
+ if (hashPublicKey(fromBase64(record.sender_public_key)) !== record.from_agent_id) {
57
+ return false;
58
+ }
59
+ return verifyPayload(unsignedPrivateMessage(record), record.signature, record.sender_public_key);
60
+ } catch {
61
+ return false;
62
+ }
63
+ }
64
+
65
+ export function signPrivateMessageReceipt(input: {
66
+ identity: AgentIdentity;
67
+ receipt_id: string;
68
+ message_id: string;
69
+ conversation_id: string;
70
+ to_agent_id: string;
71
+ status: "received" | "read";
72
+ created_at?: number;
73
+ }): PrivateMessageReceiptRecord {
74
+ const payload: Omit<PrivateMessageReceiptRecord, "signature"> = {
75
+ type: "private.message.receipt",
76
+ receipt_id: input.receipt_id,
77
+ message_id: input.message_id,
78
+ conversation_id: input.conversation_id,
79
+ from_agent_id: input.identity.agent_id,
80
+ to_agent_id: input.to_agent_id,
81
+ sender_public_key: input.identity.public_key,
82
+ status: input.status,
83
+ created_at: input.created_at ?? Date.now(),
84
+ };
85
+
86
+ return {
87
+ ...payload,
88
+ signature: signPayload(payload, input.identity.private_key),
89
+ };
90
+ }
91
+
92
+ export function verifyPrivateMessageReceipt(record: PrivateMessageReceiptRecord): boolean {
93
+ try {
94
+ if (hashPublicKey(fromBase64(record.sender_public_key)) !== record.from_agent_id) {
95
+ return false;
96
+ }
97
+ return verifyPayload(unsignedPrivateMessageReceipt(record), record.signature, record.sender_public_key);
98
+ } catch {
99
+ return false;
100
+ }
101
+ }
@@ -13,6 +13,7 @@ export function signProfile(input: ProfileInput, identity: AgentIdentity): Publi
13
13
  bio: input.bio,
14
14
  tags: input.tags,
15
15
  avatar_url: input.avatar_url,
16
+ private_encryption_public_key: input.private_encryption_public_key,
16
17
  public_enabled: input.public_enabled,
17
18
  updated_at: Date.now(),
18
19
  };
@@ -34,6 +35,7 @@ export function createDefaultProfileInput(agentId: string): ProfileInput {
34
35
  bio: "",
35
36
  tags: [],
36
37
  avatar_url: "",
38
+ private_encryption_public_key: "",
37
39
  public_enabled: false,
38
40
  };
39
41
  }
@@ -10,9 +10,11 @@ export type ProfileVisibility = {
10
10
 
11
11
  export type PublicProfileSummary = {
12
12
  agent_id: string;
13
+ is_self: boolean;
13
14
  display_name: string;
14
15
  bio: string;
15
16
  avatar_url?: string;
17
+ private_encryption_public_key?: string;
16
18
  public_enabled: boolean;
17
19
  updated_at: number;
18
20
  online: boolean;
@@ -33,6 +35,7 @@ export type PublicProfileSummary = {
33
35
  display_name: string;
34
36
  bio: string;
35
37
  avatar_url?: string;
38
+ private_encryption_public_key?: string;
36
39
  tags: string[];
37
40
  public_enabled: boolean;
38
41
  profile_version: string;
@@ -73,6 +76,7 @@ export function deriveCapabilitiesSummary(tags: string[]): string[] {
73
76
 
74
77
  export function buildPublicProfileSummary(args: {
75
78
  profile: PublicProfile;
79
+ is_self?: boolean;
76
80
  online: boolean;
77
81
  last_seen_at: number | null;
78
82
  network_mode?: string;
@@ -130,9 +134,11 @@ export function buildPublicProfileSummary(args: {
130
134
 
131
135
  return {
132
136
  agent_id: args.profile.agent_id,
137
+ is_self: Boolean(args.is_self),
133
138
  display_name: args.profile.display_name,
134
139
  bio: args.profile.bio,
135
140
  avatar_url: args.profile.avatar_url,
141
+ private_encryption_public_key: args.profile.private_encryption_public_key,
136
142
  public_enabled: args.profile.public_enabled,
137
143
  updated_at: args.profile.updated_at,
138
144
  online: args.online,
@@ -153,6 +159,7 @@ export function buildPublicProfileSummary(args: {
153
159
  display_name: args.profile.display_name,
154
160
  bio: args.profile.bio,
155
161
  avatar_url: args.profile.avatar_url,
162
+ private_encryption_public_key: args.profile.private_encryption_public_key,
156
163
  tags,
157
164
  public_enabled: args.profile.public_enabled,
158
165
  profile_version: args.profile_version ?? "v1",
@@ -5,12 +5,19 @@ export type AgentIdentity = {
5
5
  created_at: number;
6
6
  };
7
7
 
8
+ export type PrivateEncryptionKeyPair = {
9
+ public_key: string;
10
+ private_key: string;
11
+ created_at: number;
12
+ };
13
+
8
14
  export type PublicProfile = {
9
15
  agent_id: string;
10
16
  display_name: string;
11
17
  bio: string;
12
18
  tags: string[];
13
19
  avatar_url?: string;
20
+ private_encryption_public_key?: string;
14
21
  public_enabled: boolean;
15
22
  updated_at: number;
16
23
  signature: string;
@@ -58,6 +65,43 @@ export type SocialMessageObservationRecord = {
58
65
  signature: string;
59
66
  };
60
67
 
68
+ export type PrivateMessageRecord = {
69
+ type: "private.message";
70
+ message_id: string;
71
+ conversation_id: string;
72
+ from_agent_id: string;
73
+ to_agent_id: string;
74
+ sender_public_key: string;
75
+ sender_encryption_public_key: string;
76
+ recipient_encryption_public_key: string;
77
+ cipher_scheme: "nacl-box-v1";
78
+ ciphertext: string;
79
+ nonce: string;
80
+ created_at: number;
81
+ signature: string;
82
+ };
83
+
84
+ export type PrivateMessageReceiptRecord = {
85
+ type: "private.message.receipt";
86
+ receipt_id: string;
87
+ message_id: string;
88
+ conversation_id: string;
89
+ from_agent_id: string;
90
+ to_agent_id: string;
91
+ sender_public_key: string;
92
+ status: "received" | "read";
93
+ created_at: number;
94
+ signature: string;
95
+ };
96
+
97
+ export type PrivateConversationSummary = {
98
+ conversation_id: string;
99
+ peer_agent_id: string;
100
+ last_message_at: number | null;
101
+ last_message_preview: string;
102
+ unread_count: number;
103
+ };
104
+
61
105
  export type DirectoryState = {
62
106
  profiles: Record<string, PublicProfile>;
63
107
  presence: Record<string, number>;
@@ -22,6 +22,10 @@ type RelayPeer = {
22
22
  last_seen_at: number;
23
23
  messages_seen: number;
24
24
  reconnect_attempts: number;
25
+ meta?: {
26
+ signal_queue_size?: number;
27
+ relay_queue_size?: number;
28
+ };
25
29
  };
26
30
  type RelayDiagnostics = {
27
31
  adapter: "relay-preview";
@@ -126,6 +130,7 @@ export declare class RelayPreviewAdapter implements NetworkAdapter {
126
130
  private started;
127
131
  private poller;
128
132
  private handlers;
133
+ private directHandlers;
129
134
  private peers;
130
135
  private seenMessageIds;
131
136
  private activeEndpoint;
@@ -150,10 +155,16 @@ export declare class RelayPreviewAdapter implements NetworkAdapter {
150
155
  stop(): Promise<void>;
151
156
  publish(topic: string, data: any): Promise<void>;
152
157
  subscribe(topic: string, handler: (data: any) => void): void;
158
+ sendDirect(peerId: string, topic: string, data: any): Promise<void>;
159
+ subscribeDirect(topic: string, handler: (data: any, meta?: {
160
+ peerId?: string;
161
+ }) => void): void;
153
162
  getDiagnostics(): RelayDiagnostics;
154
163
  private pollOnce;
155
164
  private refreshPeers;
156
165
  private onEnvelope;
166
+ private onDirectEnvelope;
167
+ private dispatchEnvelope;
157
168
  private recordDiscovery;
158
169
  private joinRoom;
159
170
  private maybeRefreshJoin;
@@ -162,5 +173,6 @@ export declare class RelayPreviewAdapter implements NetworkAdapter {
162
173
  private requestJson;
163
174
  private updatePeersFromList;
164
175
  private scheduleNextPoll;
176
+ private ensurePollingAlive;
165
177
  }
166
178
  export {};