@silicaclaw/cli 1.0.0-beta.2 → 1.0.0-beta.21

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 (79) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/INSTALL.md +36 -0
  3. package/README.md +40 -0
  4. package/apps/local-console/public/index.html +81 -63
  5. package/apps/local-console/src/server.ts +41 -21
  6. package/docs/CLOUDFLARE_RELAY.md +61 -0
  7. package/package.json +6 -1
  8. package/packages/core/dist/crypto.d.ts +6 -0
  9. package/packages/core/dist/crypto.js +50 -0
  10. package/packages/core/dist/directory.d.ts +17 -0
  11. package/packages/core/dist/directory.js +145 -0
  12. package/packages/core/dist/identity.d.ts +2 -0
  13. package/packages/core/dist/identity.js +18 -0
  14. package/packages/core/dist/index.d.ts +11 -0
  15. package/packages/core/dist/index.js +27 -0
  16. package/packages/core/dist/indexing.d.ts +6 -0
  17. package/packages/core/dist/indexing.js +43 -0
  18. package/packages/core/dist/presence.d.ts +4 -0
  19. package/packages/core/dist/presence.js +23 -0
  20. package/packages/core/dist/profile.d.ts +4 -0
  21. package/packages/core/dist/profile.js +39 -0
  22. package/packages/core/dist/publicProfileSummary.d.ts +70 -0
  23. package/packages/core/dist/publicProfileSummary.js +103 -0
  24. package/packages/core/dist/socialConfig.d.ts +99 -0
  25. package/packages/core/dist/socialConfig.js +288 -0
  26. package/packages/core/dist/socialResolver.d.ts +46 -0
  27. package/packages/core/dist/socialResolver.js +237 -0
  28. package/packages/core/dist/socialTemplate.d.ts +2 -0
  29. package/packages/core/dist/socialTemplate.js +88 -0
  30. package/packages/core/dist/types.d.ts +37 -0
  31. package/packages/core/dist/types.js +2 -0
  32. package/packages/core/src/socialConfig.ts +7 -6
  33. package/packages/core/src/socialResolver.ts +17 -5
  34. package/packages/network/dist/abstractions/messageEnvelope.d.ts +28 -0
  35. package/packages/network/dist/abstractions/messageEnvelope.js +36 -0
  36. package/packages/network/dist/abstractions/peerDiscovery.d.ts +43 -0
  37. package/packages/network/dist/abstractions/peerDiscovery.js +2 -0
  38. package/packages/network/dist/abstractions/topicCodec.d.ts +4 -0
  39. package/packages/network/dist/abstractions/topicCodec.js +2 -0
  40. package/packages/network/dist/abstractions/transport.d.ts +36 -0
  41. package/packages/network/dist/abstractions/transport.js +2 -0
  42. package/packages/network/dist/codec/jsonMessageEnvelopeCodec.d.ts +5 -0
  43. package/packages/network/dist/codec/jsonMessageEnvelopeCodec.js +24 -0
  44. package/packages/network/dist/codec/jsonTopicCodec.d.ts +5 -0
  45. package/packages/network/dist/codec/jsonTopicCodec.js +12 -0
  46. package/packages/network/dist/discovery/heartbeatPeerDiscovery.d.ts +28 -0
  47. package/packages/network/dist/discovery/heartbeatPeerDiscovery.js +144 -0
  48. package/packages/network/dist/index.d.ts +14 -0
  49. package/packages/network/dist/index.js +30 -0
  50. package/packages/network/dist/localEventBus.d.ts +9 -0
  51. package/packages/network/dist/localEventBus.js +47 -0
  52. package/packages/network/dist/mock.d.ts +8 -0
  53. package/packages/network/dist/mock.js +24 -0
  54. package/packages/network/dist/realPreview.d.ts +105 -0
  55. package/packages/network/dist/realPreview.js +327 -0
  56. package/packages/network/dist/relayPreview.d.ts +133 -0
  57. package/packages/network/dist/relayPreview.js +320 -0
  58. package/packages/network/dist/transport/udpLanBroadcastTransport.d.ts +23 -0
  59. package/packages/network/dist/transport/udpLanBroadcastTransport.js +153 -0
  60. package/packages/network/dist/types.d.ts +6 -0
  61. package/packages/network/dist/types.js +2 -0
  62. package/packages/network/dist/webrtcPreview.d.ts +163 -0
  63. package/packages/network/dist/webrtcPreview.js +844 -0
  64. package/packages/network/src/index.ts +1 -0
  65. package/packages/network/src/relayPreview.ts +425 -0
  66. package/packages/storage/dist/index.d.ts +3 -0
  67. package/packages/storage/dist/index.js +19 -0
  68. package/packages/storage/dist/jsonRepo.d.ts +7 -0
  69. package/packages/storage/dist/jsonRepo.js +29 -0
  70. package/packages/storage/dist/repos.d.ts +21 -0
  71. package/packages/storage/dist/repos.js +41 -0
  72. package/packages/storage/dist/socialRuntimeRepo.d.ts +5 -0
  73. package/packages/storage/dist/socialRuntimeRepo.js +52 -0
  74. package/packages/storage/src/socialRuntimeRepo.ts +3 -3
  75. package/packages/storage/tsconfig.json +6 -1
  76. package/scripts/quickstart.sh +286 -20
  77. package/scripts/silicaclaw-cli.mjs +271 -1
  78. package/scripts/silicaclaw-gateway.mjs +411 -0
  79. package/scripts/webrtc-signaling-server.mjs +52 -1
@@ -3,6 +3,7 @@ export * from "./mock";
3
3
  export * from "./localEventBus";
4
4
  export * from "./realPreview";
5
5
  export * from "./webrtcPreview";
6
+ export * from "./relayPreview";
6
7
 
7
8
  export * from "./abstractions/messageEnvelope";
8
9
  export * from "./abstractions/topicCodec";
@@ -0,0 +1,425 @@
1
+ import { randomUUID } from "crypto";
2
+ import { NetworkAdapter } from "./types";
3
+ import {
4
+ MessageEnvelopeCodec,
5
+ NetworkMessageEnvelope,
6
+ validateNetworkMessageEnvelope,
7
+ } from "./abstractions/messageEnvelope";
8
+ import { TopicCodec } from "./abstractions/topicCodec";
9
+ import { JsonMessageEnvelopeCodec } from "./codec/jsonMessageEnvelopeCodec";
10
+ import { JsonTopicCodec } from "./codec/jsonTopicCodec";
11
+
12
+ type RelayPreviewOptions = {
13
+ peerId?: string;
14
+ namespace?: string;
15
+ signalingUrl?: string;
16
+ signalingUrls?: string[];
17
+ room?: string;
18
+ seedPeers?: string[];
19
+ bootstrapHints?: string[];
20
+ bootstrapSources?: string[];
21
+ maxMessageBytes?: number;
22
+ pollIntervalMs?: number;
23
+ maxFutureDriftMs?: number;
24
+ maxPastDriftMs?: number;
25
+ };
26
+
27
+ type RelayPeer = {
28
+ peer_id: string;
29
+ status: "online";
30
+ first_seen_at: number;
31
+ last_seen_at: number;
32
+ messages_seen: number;
33
+ reconnect_attempts: number;
34
+ };
35
+
36
+ type RelayDiagnostics = {
37
+ adapter: "relay-preview";
38
+ peer_id: string;
39
+ namespace: string;
40
+ room: string;
41
+ signaling_url: string;
42
+ signaling_endpoints: string[];
43
+ bootstrap_sources: string[];
44
+ seed_peers_count: number;
45
+ bootstrap_hints_count: number;
46
+ discovery_events_total: number;
47
+ last_discovery_event_at: number;
48
+ discovery_events: Array<{
49
+ id: string;
50
+ type: string;
51
+ at: number;
52
+ peer_id?: string;
53
+ endpoint?: string;
54
+ detail?: string;
55
+ }>;
56
+ signaling_messages_sent_total: number;
57
+ signaling_messages_received_total: number;
58
+ reconnect_attempts_total: number;
59
+ active_webrtc_peers: number;
60
+ components: {
61
+ transport: string;
62
+ discovery: string;
63
+ envelope_codec: string;
64
+ topic_codec: string;
65
+ };
66
+ limits: {
67
+ max_message_bytes: number;
68
+ max_future_drift_ms: number;
69
+ max_past_drift_ms: number;
70
+ };
71
+ config: {
72
+ started: boolean;
73
+ topic_handler_count: number;
74
+ poll_interval_ms: number;
75
+ };
76
+ peers: {
77
+ total: number;
78
+ online: number;
79
+ stale: number;
80
+ items: RelayPeer[];
81
+ };
82
+ stats: {
83
+ publish_attempted: number;
84
+ publish_sent: number;
85
+ received_total: number;
86
+ delivered_total: number;
87
+ dropped_malformed: number;
88
+ dropped_oversized: number;
89
+ dropped_namespace_mismatch: number;
90
+ dropped_timestamp_future_drift: number;
91
+ dropped_timestamp_past_drift: number;
92
+ dropped_decode_failed: number;
93
+ dropped_self: number;
94
+ dropped_topic_decode_error: number;
95
+ dropped_handler_error: number;
96
+ signaling_errors: number;
97
+ invalid_signaling_payload_total: number;
98
+ duplicate_sdp_total: number;
99
+ duplicate_ice_total: number;
100
+ start_errors: number;
101
+ stop_errors: number;
102
+ received_validated: number;
103
+ };
104
+ };
105
+
106
+ function dedupe(values: string[]): string[] {
107
+ return Array.from(new Set(values.map((value) => value.trim()).filter(Boolean)));
108
+ }
109
+
110
+ export class RelayPreviewAdapter implements NetworkAdapter {
111
+ private readonly peerId: string;
112
+ private readonly namespace: string;
113
+ private readonly signalingEndpoints: string[];
114
+ private readonly room: string;
115
+ private readonly seedPeers: string[];
116
+ private readonly bootstrapHints: string[];
117
+ private readonly bootstrapSources: string[];
118
+ private readonly maxMessageBytes: number;
119
+ private readonly pollIntervalMs: number;
120
+ private readonly maxFutureDriftMs: number;
121
+ private readonly maxPastDriftMs: number;
122
+ private readonly envelopeCodec: MessageEnvelopeCodec;
123
+ private readonly topicCodec: TopicCodec;
124
+
125
+ private started = false;
126
+ private poller: NodeJS.Timeout | null = null;
127
+ private handlers = new Map<string, Set<(data: any) => void>>();
128
+ private peers = new Map<string, RelayPeer>();
129
+ private seenMessageIds = new Set<string>();
130
+ private activeEndpoint = "";
131
+ private discoveryEvents: RelayDiagnostics["discovery_events"] = [];
132
+ private discoveryEventsTotal = 0;
133
+ private lastDiscoveryEventAt = 0;
134
+ private signalingMessagesSentTotal = 0;
135
+ private signalingMessagesReceivedTotal = 0;
136
+ private reconnectAttemptsTotal = 0;
137
+
138
+ private stats: RelayDiagnostics["stats"] = {
139
+ publish_attempted: 0,
140
+ publish_sent: 0,
141
+ received_total: 0,
142
+ delivered_total: 0,
143
+ dropped_malformed: 0,
144
+ dropped_oversized: 0,
145
+ dropped_namespace_mismatch: 0,
146
+ dropped_timestamp_future_drift: 0,
147
+ dropped_timestamp_past_drift: 0,
148
+ dropped_decode_failed: 0,
149
+ dropped_self: 0,
150
+ dropped_topic_decode_error: 0,
151
+ dropped_handler_error: 0,
152
+ signaling_errors: 0,
153
+ invalid_signaling_payload_total: 0,
154
+ duplicate_sdp_total: 0,
155
+ duplicate_ice_total: 0,
156
+ start_errors: 0,
157
+ stop_errors: 0,
158
+ received_validated: 0,
159
+ };
160
+
161
+ constructor(options: RelayPreviewOptions = {}) {
162
+ this.peerId = options.peerId ?? `peer-${process.pid}-${Math.random().toString(36).slice(2, 10)}`;
163
+ this.namespace = String(options.namespace || "silicaclaw.preview").trim() || "silicaclaw.preview";
164
+ this.signalingEndpoints = dedupe(
165
+ (options.signalingUrls && options.signalingUrls.length > 0
166
+ ? options.signalingUrls
167
+ : [options.signalingUrl || "http://localhost:4510"])
168
+ );
169
+ this.activeEndpoint = this.signalingEndpoints[0] || "http://localhost:4510";
170
+ this.room = String(options.room || "silicaclaw-global-preview").trim() || "silicaclaw-global-preview";
171
+ this.seedPeers = dedupe(options.seedPeers || []);
172
+ this.bootstrapHints = dedupe(options.bootstrapHints || []);
173
+ this.bootstrapSources = dedupe(options.bootstrapSources || []);
174
+ this.maxMessageBytes = options.maxMessageBytes ?? 64 * 1024;
175
+ this.pollIntervalMs = options.pollIntervalMs ?? 2000;
176
+ this.maxFutureDriftMs = options.maxFutureDriftMs ?? 30_000;
177
+ this.maxPastDriftMs = options.maxPastDriftMs ?? 120_000;
178
+ this.envelopeCodec = new JsonMessageEnvelopeCodec();
179
+ this.topicCodec = new JsonTopicCodec();
180
+ }
181
+
182
+ async start(): Promise<void> {
183
+ if (this.started) return;
184
+ try {
185
+ await this.post("/join", { room: this.room, peer_id: this.peerId });
186
+ this.started = true;
187
+ await this.refreshPeers();
188
+ await this.pollOnce();
189
+ this.poller = setInterval(() => {
190
+ this.pollOnce().catch(() => {});
191
+ }, this.pollIntervalMs);
192
+ this.recordDiscovery("signaling_connected", { endpoint: this.activeEndpoint });
193
+ } catch (error) {
194
+ this.stats.start_errors += 1;
195
+ throw new Error(`Relay start failed: ${error instanceof Error ? error.message : String(error)}`);
196
+ }
197
+ }
198
+
199
+ async stop(): Promise<void> {
200
+ if (!this.started) return;
201
+ if (this.poller) {
202
+ clearInterval(this.poller);
203
+ this.poller = null;
204
+ }
205
+ try {
206
+ await this.post("/leave", { room: this.room, peer_id: this.peerId });
207
+ } catch {
208
+ this.stats.stop_errors += 1;
209
+ }
210
+ this.started = false;
211
+ this.recordDiscovery("signaling_disconnected", { endpoint: this.activeEndpoint });
212
+ }
213
+
214
+ async publish(topic: string, data: any): Promise<void> {
215
+ if (!this.started) return;
216
+ this.stats.publish_attempted += 1;
217
+ const envelope: NetworkMessageEnvelope = {
218
+ version: 1,
219
+ message_id: randomUUID(),
220
+ topic: `${this.namespace}:${topic}`,
221
+ source_peer_id: this.peerId,
222
+ timestamp: Date.now(),
223
+ payload: this.topicCodec.encode(topic, data),
224
+ };
225
+ const raw = this.envelopeCodec.encode(envelope);
226
+ if (raw.length > this.maxMessageBytes) {
227
+ this.stats.dropped_oversized += 1;
228
+ return;
229
+ }
230
+ await this.post("/relay/publish", { room: this.room, peer_id: this.peerId, envelope });
231
+ this.stats.publish_sent += 1;
232
+ this.signalingMessagesSentTotal += 1;
233
+ }
234
+
235
+ subscribe(topic: string, handler: (data: any) => void): void {
236
+ const key = `${this.namespace}:${topic}`;
237
+ if (!this.handlers.has(key)) {
238
+ this.handlers.set(key, new Set());
239
+ }
240
+ this.handlers.get(key)?.add(handler);
241
+ }
242
+
243
+ getDiagnostics(): RelayDiagnostics {
244
+ const peerItems = Array.from(this.peers.values()).sort((a, b) => b.last_seen_at - a.last_seen_at);
245
+ return {
246
+ adapter: "relay-preview",
247
+ peer_id: this.peerId,
248
+ namespace: this.namespace,
249
+ room: this.room,
250
+ signaling_url: this.activeEndpoint,
251
+ signaling_endpoints: this.signalingEndpoints,
252
+ bootstrap_sources: this.bootstrapSources,
253
+ seed_peers_count: this.seedPeers.length,
254
+ bootstrap_hints_count: this.bootstrapHints.length,
255
+ discovery_events_total: this.discoveryEventsTotal,
256
+ last_discovery_event_at: this.lastDiscoveryEventAt,
257
+ discovery_events: this.discoveryEvents,
258
+ signaling_messages_sent_total: this.signalingMessagesSentTotal,
259
+ signaling_messages_received_total: this.signalingMessagesReceivedTotal,
260
+ reconnect_attempts_total: this.reconnectAttemptsTotal,
261
+ active_webrtc_peers: peerItems.length,
262
+ components: {
263
+ transport: "HttpRelayTransport",
264
+ discovery: "RelayRoomPeerList",
265
+ envelope_codec: this.envelopeCodec.constructor.name,
266
+ topic_codec: this.topicCodec.constructor.name,
267
+ },
268
+ limits: {
269
+ max_message_bytes: this.maxMessageBytes,
270
+ max_future_drift_ms: this.maxFutureDriftMs,
271
+ max_past_drift_ms: this.maxPastDriftMs,
272
+ },
273
+ config: {
274
+ started: this.started,
275
+ topic_handler_count: this.handlers.size,
276
+ poll_interval_ms: this.pollIntervalMs,
277
+ },
278
+ peers: {
279
+ total: peerItems.length,
280
+ online: peerItems.length,
281
+ stale: 0,
282
+ items: peerItems,
283
+ },
284
+ stats: { ...this.stats },
285
+ };
286
+ }
287
+
288
+ private async pollOnce(): Promise<void> {
289
+ const payload = await this.get(`/relay/poll?room=${encodeURIComponent(this.room)}&peer_id=${encodeURIComponent(this.peerId)}`);
290
+ const messages = Array.isArray(payload?.messages) ? payload.messages : [];
291
+ for (const message of messages) {
292
+ this.signalingMessagesReceivedTotal += 1;
293
+ this.onEnvelope(message?.envelope);
294
+ }
295
+ await this.refreshPeers();
296
+ }
297
+
298
+ private async refreshPeers(): Promise<void> {
299
+ const payload = await this.get(`/peers?room=${encodeURIComponent(this.room)}`);
300
+ const peerIds = Array.isArray(payload?.peers) ? payload.peers.map((value: unknown) => String(value || "").trim()).filter(Boolean) : [];
301
+ const now = Date.now();
302
+ const next = new Map<string, RelayPeer>();
303
+ for (const peerId of peerIds) {
304
+ if (peerId === this.peerId) continue;
305
+ const existing = this.peers.get(peerId);
306
+ if (!existing) {
307
+ this.recordDiscovery("peer_joined", { peer_id: peerId });
308
+ }
309
+ next.set(peerId, {
310
+ peer_id: peerId,
311
+ status: "online",
312
+ first_seen_at: existing?.first_seen_at ?? now,
313
+ last_seen_at: now,
314
+ messages_seen: existing?.messages_seen ?? 0,
315
+ reconnect_attempts: existing?.reconnect_attempts ?? 0,
316
+ });
317
+ }
318
+ for (const peerId of this.peers.keys()) {
319
+ if (!next.has(peerId)) {
320
+ this.recordDiscovery("peer_removed", { peer_id: peerId });
321
+ }
322
+ }
323
+ this.peers = next;
324
+ }
325
+
326
+ private onEnvelope(envelope: unknown): void {
327
+ this.stats.received_total += 1;
328
+ const validated = validateNetworkMessageEnvelope(envelope, {
329
+ max_future_drift_ms: this.maxFutureDriftMs,
330
+ max_past_drift_ms: this.maxPastDriftMs,
331
+ });
332
+ if (!validated.ok || !validated.envelope) {
333
+ if (validated.reason === "timestamp_future_drift") {
334
+ this.stats.dropped_timestamp_future_drift += 1;
335
+ } else if (validated.reason === "timestamp_past_drift") {
336
+ this.stats.dropped_timestamp_past_drift += 1;
337
+ } else {
338
+ this.stats.dropped_malformed += 1;
339
+ }
340
+ return;
341
+ }
342
+ const message = validated.envelope;
343
+ if (message.source_peer_id === this.peerId) {
344
+ this.stats.dropped_self += 1;
345
+ return;
346
+ }
347
+ if (!message.topic.startsWith(`${this.namespace}:`)) {
348
+ this.stats.dropped_namespace_mismatch += 1;
349
+ return;
350
+ }
351
+ if (this.seenMessageIds.has(message.message_id)) {
352
+ return;
353
+ }
354
+ this.seenMessageIds.add(message.message_id);
355
+ if (this.seenMessageIds.size > 10000) {
356
+ const first = this.seenMessageIds.values().next().value;
357
+ if (first) this.seenMessageIds.delete(first);
358
+ }
359
+ this.stats.received_validated += 1;
360
+
361
+ const topicKey = message.topic;
362
+ const topic = topicKey.slice(this.namespace.length + 1);
363
+ const handlers = this.handlers.get(topicKey);
364
+ if (!handlers || handlers.size === 0) return;
365
+
366
+ const peer = this.peers.get(message.source_peer_id);
367
+ if (peer) {
368
+ peer.last_seen_at = Date.now();
369
+ peer.messages_seen += 1;
370
+ }
371
+
372
+ let payload: unknown;
373
+ try {
374
+ payload = this.topicCodec.decode(topic, message.payload);
375
+ } catch {
376
+ this.stats.dropped_topic_decode_error += 1;
377
+ return;
378
+ }
379
+ for (const handler of handlers) {
380
+ try {
381
+ handler(payload);
382
+ this.stats.delivered_total += 1;
383
+ } catch {
384
+ this.stats.dropped_handler_error += 1;
385
+ }
386
+ }
387
+ }
388
+
389
+ private recordDiscovery(type: string, extra: { peer_id?: string; endpoint?: string; detail?: string } = {}): void {
390
+ const event = {
391
+ id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
392
+ type,
393
+ at: Date.now(),
394
+ ...extra,
395
+ };
396
+ this.discoveryEvents.unshift(event);
397
+ this.discoveryEvents = this.discoveryEvents.slice(0, 200);
398
+ this.discoveryEventsTotal += 1;
399
+ this.lastDiscoveryEventAt = event.at;
400
+ }
401
+
402
+ private async get(path: string): Promise<any> {
403
+ const endpoint = this.activeEndpoint.replace(/\/+$/, "");
404
+ const response = await fetch(`${endpoint}${path}`);
405
+ if (!response.ok) {
406
+ this.stats.signaling_errors += 1;
407
+ throw new Error(`Relay GET failed (${response.status})`);
408
+ }
409
+ return response.json();
410
+ }
411
+
412
+ private async post(path: string, body: any): Promise<any> {
413
+ const endpoint = this.activeEndpoint.replace(/\/+$/, "");
414
+ const response = await fetch(`${endpoint}${path}`, {
415
+ method: "POST",
416
+ headers: { "content-type": "application/json" },
417
+ body: JSON.stringify(body),
418
+ });
419
+ if (!response.ok) {
420
+ this.stats.signaling_errors += 1;
421
+ throw new Error(`Relay POST failed (${response.status})`);
422
+ }
423
+ return response.json();
424
+ }
425
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./jsonRepo";
2
+ export * from "./repos";
3
+ export * from "./socialRuntimeRepo";
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./jsonRepo"), exports);
18
+ __exportStar(require("./repos"), exports);
19
+ __exportStar(require("./socialRuntimeRepo"), exports);
@@ -0,0 +1,7 @@
1
+ export declare class JsonFileRepo<T> {
2
+ private filePath;
3
+ private fallback;
4
+ constructor(filePath: string, fallback: () => T);
5
+ get(): Promise<T>;
6
+ set(value: T): Promise<void>;
7
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsonFileRepo = void 0;
4
+ const promises_1 = require("fs/promises");
5
+ const path_1 = require("path");
6
+ class JsonFileRepo {
7
+ filePath;
8
+ fallback;
9
+ constructor(filePath, fallback) {
10
+ this.filePath = filePath;
11
+ this.fallback = fallback;
12
+ }
13
+ async get() {
14
+ try {
15
+ const raw = await (0, promises_1.readFile)(this.filePath, "utf8");
16
+ return JSON.parse(raw);
17
+ }
18
+ catch {
19
+ const seed = this.fallback();
20
+ await this.set(seed);
21
+ return seed;
22
+ }
23
+ }
24
+ async set(value) {
25
+ await (0, promises_1.mkdir)((0, path_1.dirname)(this.filePath), { recursive: true });
26
+ await (0, promises_1.writeFile)(this.filePath, JSON.stringify(value, null, 2), "utf8");
27
+ }
28
+ }
29
+ exports.JsonFileRepo = JsonFileRepo;
@@ -0,0 +1,21 @@
1
+ import { AgentIdentity, DirectoryState, PublicProfile } from "@silicaclaw/core";
2
+ import { JsonFileRepo } from "./jsonRepo";
3
+ export type LogEntry = {
4
+ id: string;
5
+ level: "info" | "warn" | "error";
6
+ message: string;
7
+ timestamp: number;
8
+ };
9
+ export declare class IdentityRepo extends JsonFileRepo<AgentIdentity | null> {
10
+ constructor(rootDir?: string);
11
+ }
12
+ export declare class ProfileRepo extends JsonFileRepo<PublicProfile | null> {
13
+ constructor(rootDir?: string);
14
+ }
15
+ export declare class CacheRepo extends JsonFileRepo<DirectoryState> {
16
+ constructor(rootDir?: string);
17
+ }
18
+ export declare class LogRepo extends JsonFileRepo<LogEntry[]> {
19
+ constructor(rootDir?: string);
20
+ append(entry: Omit<LogEntry, "id">): Promise<void>;
21
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LogRepo = exports.CacheRepo = exports.ProfileRepo = exports.IdentityRepo = void 0;
4
+ const path_1 = require("path");
5
+ const core_1 = require("@silicaclaw/core");
6
+ const jsonRepo_1 = require("./jsonRepo");
7
+ class IdentityRepo extends jsonRepo_1.JsonFileRepo {
8
+ constructor(rootDir = process.cwd()) {
9
+ super((0, path_1.resolve)(rootDir, "data", "identity.json"), () => null);
10
+ }
11
+ }
12
+ exports.IdentityRepo = IdentityRepo;
13
+ class ProfileRepo extends jsonRepo_1.JsonFileRepo {
14
+ constructor(rootDir = process.cwd()) {
15
+ super((0, path_1.resolve)(rootDir, "data", "profile.json"), () => null);
16
+ }
17
+ }
18
+ exports.ProfileRepo = ProfileRepo;
19
+ class CacheRepo extends jsonRepo_1.JsonFileRepo {
20
+ constructor(rootDir = process.cwd()) {
21
+ super((0, path_1.resolve)(rootDir, "data", "cache.json"), () => (0, core_1.createEmptyDirectoryState)());
22
+ }
23
+ }
24
+ exports.CacheRepo = CacheRepo;
25
+ class LogRepo extends jsonRepo_1.JsonFileRepo {
26
+ constructor(rootDir = process.cwd()) {
27
+ super((0, path_1.resolve)(rootDir, "data", "logs.json"), () => []);
28
+ }
29
+ async append(entry) {
30
+ const current = await this.get();
31
+ const next = [
32
+ {
33
+ id: `${entry.timestamp}-${Math.random().toString(36).slice(2, 8)}`,
34
+ ...entry,
35
+ },
36
+ ...current,
37
+ ].slice(0, 50);
38
+ await this.set(next);
39
+ }
40
+ }
41
+ exports.LogRepo = LogRepo;
@@ -0,0 +1,5 @@
1
+ import { SocialRuntimeConfig } from "@silicaclaw/core";
2
+ import { JsonFileRepo } from "./jsonRepo";
3
+ export declare class SocialRuntimeRepo extends JsonFileRepo<SocialRuntimeConfig> {
4
+ constructor(rootDir?: string);
5
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SocialRuntimeRepo = void 0;
4
+ const path_1 = require("path");
5
+ const jsonRepo_1 = require("./jsonRepo");
6
+ function emptyRuntime() {
7
+ return {
8
+ enabled: true,
9
+ public_enabled: false,
10
+ source_path: null,
11
+ last_loaded_at: 0,
12
+ social_found: false,
13
+ parse_error: null,
14
+ resolved_identity: null,
15
+ resolved_profile: null,
16
+ resolved_network: {
17
+ mode: "global-preview",
18
+ adapter: "relay-preview",
19
+ namespace: "silicaclaw.preview",
20
+ port: null,
21
+ signaling_url: "http://localhost:4510",
22
+ signaling_urls: [],
23
+ room: "silicaclaw-global-preview",
24
+ seed_peers: [],
25
+ bootstrap_hints: [],
26
+ bootstrap_sources: [],
27
+ },
28
+ resolved_discovery: {
29
+ discoverable: true,
30
+ allow_profile_broadcast: true,
31
+ allow_presence_broadcast: true,
32
+ },
33
+ visibility: {
34
+ show_display_name: true,
35
+ show_bio: true,
36
+ show_tags: true,
37
+ show_agent_id: true,
38
+ show_last_seen: true,
39
+ show_capabilities_summary: true,
40
+ },
41
+ openclaw: {
42
+ bind_existing_identity: true,
43
+ use_openclaw_profile_if_available: true,
44
+ },
45
+ };
46
+ }
47
+ class SocialRuntimeRepo extends jsonRepo_1.JsonFileRepo {
48
+ constructor(rootDir = process.cwd()) {
49
+ super((0, path_1.resolve)(rootDir, ".silicaclaw", "social.runtime.json"), emptyRuntime);
50
+ }
51
+ }
52
+ exports.SocialRuntimeRepo = SocialRuntimeRepo;
@@ -13,13 +13,13 @@ function emptyRuntime(): SocialRuntimeConfig {
13
13
  resolved_identity: null,
14
14
  resolved_profile: null,
15
15
  resolved_network: {
16
- mode: "lan",
17
- adapter: "real-preview",
16
+ mode: "global-preview",
17
+ adapter: "relay-preview",
18
18
  namespace: "silicaclaw.preview",
19
19
  port: null,
20
20
  signaling_url: "http://localhost:4510",
21
21
  signaling_urls: [],
22
- room: "silicaclaw-room",
22
+ room: "silicaclaw-global-preview",
23
23
  seed_peers: [],
24
24
  bootstrap_hints: [],
25
25
  bootstrap_sources: [],
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "extends": "../../tsconfig.base.json",
3
3
  "compilerOptions": {
4
- "outDir": "./dist"
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ "baseUrl": ".",
7
+ "paths": {
8
+ "@silicaclaw/core": ["../../node_modules/@silicaclaw/core/dist/index.d.ts"]
9
+ }
5
10
  },
6
11
  "include": ["src"]
7
12
  }