@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
@@ -0,0 +1,288 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseFrontmatterObject = parseFrontmatterObject;
4
+ exports.extractFrontmatter = extractFrontmatter;
5
+ exports.normalizeSocialConfig = normalizeSocialConfig;
6
+ exports.getDefaultSocialConfig = getDefaultSocialConfig;
7
+ exports.generateDefaultSocialMdTemplate = generateDefaultSocialMdTemplate;
8
+ const DEFAULT_SOCIAL_CONFIG = {
9
+ enabled: true,
10
+ public_enabled: false,
11
+ identity: {
12
+ display_name: "",
13
+ bio: "",
14
+ avatar_url: "",
15
+ tags: [],
16
+ },
17
+ network: {
18
+ mode: "global-preview",
19
+ namespace: "silicaclaw.preview",
20
+ adapter: "relay-preview",
21
+ port: 44123,
22
+ signaling_url: "http://localhost:4510",
23
+ signaling_urls: [],
24
+ room: "silicaclaw-global-preview",
25
+ seed_peers: [],
26
+ bootstrap_hints: [],
27
+ },
28
+ 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
+ function parseScalar(value) {
47
+ const trimmed = value.trim();
48
+ if (trimmed === "[]")
49
+ return [];
50
+ if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
51
+ const inner = trimmed.slice(1, -1).trim();
52
+ if (!inner)
53
+ return [];
54
+ return inner
55
+ .split(",")
56
+ .map((item) => item.trim())
57
+ .map((item) => (item.startsWith('"') && item.endsWith('"')) || (item.startsWith("'") && item.endsWith("'"))
58
+ ? item.slice(1, -1)
59
+ : item)
60
+ .filter(Boolean);
61
+ }
62
+ if (trimmed === "true")
63
+ return true;
64
+ if (trimmed === "false")
65
+ return false;
66
+ if (trimmed === "null")
67
+ return null;
68
+ if (/^-?\d+(\.\d+)?$/.test(trimmed))
69
+ return Number(trimmed);
70
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
71
+ (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
72
+ return trimmed.slice(1, -1);
73
+ }
74
+ return trimmed;
75
+ }
76
+ function countIndent(line) {
77
+ let count = 0;
78
+ while (count < line.length && line[count] === " ")
79
+ count += 1;
80
+ return count;
81
+ }
82
+ function findNextSignificantLine(lines, start) {
83
+ for (let i = start; i < lines.length; i += 1) {
84
+ const raw = lines[i];
85
+ const trimmed = raw.trim();
86
+ if (!trimmed || trimmed.startsWith("#"))
87
+ continue;
88
+ return { line: trimmed, indent: countIndent(raw) };
89
+ }
90
+ return null;
91
+ }
92
+ function parseFrontmatterObject(frontmatter) {
93
+ const root = {};
94
+ const lines = frontmatter.replace(/\r\n/g, "\n").split("\n");
95
+ const stack = [{ indent: -1, value: root, kind: "object" }];
96
+ for (let i = 0; i < lines.length; i += 1) {
97
+ const raw = lines[i];
98
+ const trimmed = raw.trim();
99
+ if (!trimmed || trimmed.startsWith("#"))
100
+ continue;
101
+ const indent = countIndent(raw);
102
+ while (stack.length > 1 && indent <= stack[stack.length - 1].indent) {
103
+ stack.pop();
104
+ }
105
+ const current = stack[stack.length - 1];
106
+ if (trimmed.startsWith("- ")) {
107
+ if (current.kind !== "array") {
108
+ continue;
109
+ }
110
+ const itemRaw = trimmed.slice(2).trim();
111
+ if (!itemRaw) {
112
+ const child = {};
113
+ current.value.push(child);
114
+ stack.push({ indent, value: child, kind: "object" });
115
+ continue;
116
+ }
117
+ const keyValue = itemRaw.match(/^([A-Za-z0-9_]+):\s*(.*)$/);
118
+ if (keyValue) {
119
+ const child = {};
120
+ const key = keyValue[1];
121
+ const valueRaw = keyValue[2];
122
+ child[key] = valueRaw ? parseScalar(valueRaw) : "";
123
+ current.value.push(child);
124
+ continue;
125
+ }
126
+ current.value.push(parseScalar(itemRaw));
127
+ continue;
128
+ }
129
+ const match = trimmed.match(/^([A-Za-z0-9_]+):\s*(.*)$/);
130
+ if (!match || current.kind !== "object") {
131
+ continue;
132
+ }
133
+ const key = match[1];
134
+ const valueRaw = match[2];
135
+ const obj = current.value;
136
+ if (valueRaw) {
137
+ obj[key] = parseScalar(valueRaw);
138
+ continue;
139
+ }
140
+ const next = findNextSignificantLine(lines, i + 1);
141
+ const nextIsArray = Boolean(next && next.indent > indent && next.line.startsWith("- "));
142
+ if (nextIsArray) {
143
+ const arr = [];
144
+ obj[key] = arr;
145
+ stack.push({ indent, value: arr, kind: "array" });
146
+ continue;
147
+ }
148
+ const childObj = {};
149
+ obj[key] = childObj;
150
+ stack.push({ indent, value: childObj, kind: "object" });
151
+ }
152
+ return root;
153
+ }
154
+ function extractFrontmatter(content) {
155
+ const normalized = content.replace(/\r\n/g, "\n");
156
+ if (!normalized.startsWith("---\n")) {
157
+ return null;
158
+ }
159
+ const end = normalized.indexOf("\n---", 4);
160
+ if (end < 0) {
161
+ return null;
162
+ }
163
+ return normalized.slice(4, end).trim();
164
+ }
165
+ function asObject(value) {
166
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
167
+ return value;
168
+ }
169
+ return {};
170
+ }
171
+ function asBool(value, fallback) {
172
+ return typeof value === "boolean" ? value : fallback;
173
+ }
174
+ function asString(value, fallback) {
175
+ return typeof value === "string" ? value : fallback;
176
+ }
177
+ function asNumber(value, fallback) {
178
+ return Number.isFinite(value) ? Number(value) : fallback;
179
+ }
180
+ function asStringArray(value, fallback) {
181
+ if (!Array.isArray(value))
182
+ return fallback;
183
+ return value.map((item) => String(item).trim()).filter(Boolean);
184
+ }
185
+ function asAdapter(value, fallback) {
186
+ if (value === "mock" ||
187
+ value === "local-event-bus" ||
188
+ value === "real-preview" ||
189
+ value === "webrtc-preview" ||
190
+ value === "relay-preview") {
191
+ return value;
192
+ }
193
+ return fallback;
194
+ }
195
+ function asMode(value, fallback) {
196
+ if (value === "local" || value === "lan" || value === "global-preview") {
197
+ return value;
198
+ }
199
+ return fallback;
200
+ }
201
+ function adapterForMode(mode) {
202
+ if (mode === "local")
203
+ return "local-event-bus";
204
+ if (mode === "lan")
205
+ return "real-preview";
206
+ return "relay-preview";
207
+ }
208
+ function normalizeSocialConfig(input) {
209
+ const root = asObject(input);
210
+ const identity = asObject(root.identity);
211
+ const network = asObject(root.network);
212
+ const discovery = asObject(root.discovery);
213
+ const visibility = asObject(root.visibility);
214
+ const openclaw = asObject(root.openclaw);
215
+ const signalingUrl = asString(network.signaling_url, DEFAULT_SOCIAL_CONFIG.network.signaling_url);
216
+ const signalingUrls = asStringArray(network.signaling_urls, DEFAULT_SOCIAL_CONFIG.network.signaling_urls);
217
+ const mode = asMode(network.mode, DEFAULT_SOCIAL_CONFIG.network.mode);
218
+ return {
219
+ enabled: asBool(root.enabled, DEFAULT_SOCIAL_CONFIG.enabled),
220
+ public_enabled: asBool(root.public_enabled, DEFAULT_SOCIAL_CONFIG.public_enabled),
221
+ identity: {
222
+ display_name: asString(identity.display_name, DEFAULT_SOCIAL_CONFIG.identity.display_name),
223
+ bio: asString(identity.bio, DEFAULT_SOCIAL_CONFIG.identity.bio),
224
+ avatar_url: asString(identity.avatar_url, DEFAULT_SOCIAL_CONFIG.identity.avatar_url),
225
+ tags: asStringArray(identity.tags, DEFAULT_SOCIAL_CONFIG.identity.tags),
226
+ },
227
+ network: {
228
+ mode,
229
+ namespace: asString(network.namespace, DEFAULT_SOCIAL_CONFIG.network.namespace),
230
+ adapter: asAdapter(network.adapter, adapterForMode(mode)),
231
+ port: asNumber(network.port, DEFAULT_SOCIAL_CONFIG.network.port),
232
+ signaling_url: signalingUrl,
233
+ signaling_urls: signalingUrls.length > 0 ? signalingUrls : signalingUrl ? [signalingUrl] : [],
234
+ room: asString(network.room, DEFAULT_SOCIAL_CONFIG.network.room),
235
+ seed_peers: asStringArray(network.seed_peers, DEFAULT_SOCIAL_CONFIG.network.seed_peers),
236
+ bootstrap_hints: asStringArray(network.bootstrap_hints, DEFAULT_SOCIAL_CONFIG.network.bootstrap_hints),
237
+ },
238
+ discovery: {
239
+ discoverable: asBool(discovery.discoverable, DEFAULT_SOCIAL_CONFIG.discovery.discoverable),
240
+ allow_profile_broadcast: asBool(discovery.allow_profile_broadcast, DEFAULT_SOCIAL_CONFIG.discovery.allow_profile_broadcast),
241
+ allow_presence_broadcast: asBool(discovery.allow_presence_broadcast, DEFAULT_SOCIAL_CONFIG.discovery.allow_presence_broadcast),
242
+ },
243
+ visibility: {
244
+ show_display_name: asBool(visibility.show_display_name, DEFAULT_SOCIAL_CONFIG.visibility.show_display_name),
245
+ show_bio: asBool(visibility.show_bio, DEFAULT_SOCIAL_CONFIG.visibility.show_bio),
246
+ show_tags: asBool(visibility.show_tags, DEFAULT_SOCIAL_CONFIG.visibility.show_tags),
247
+ show_agent_id: asBool(visibility.show_agent_id, DEFAULT_SOCIAL_CONFIG.visibility.show_agent_id),
248
+ show_last_seen: asBool(visibility.show_last_seen, DEFAULT_SOCIAL_CONFIG.visibility.show_last_seen),
249
+ show_capabilities_summary: asBool(visibility.show_capabilities_summary, DEFAULT_SOCIAL_CONFIG.visibility.show_capabilities_summary),
250
+ },
251
+ openclaw: {
252
+ bind_existing_identity: asBool(openclaw.bind_existing_identity, DEFAULT_SOCIAL_CONFIG.openclaw.bind_existing_identity),
253
+ use_openclaw_profile_if_available: asBool(openclaw.use_openclaw_profile_if_available, DEFAULT_SOCIAL_CONFIG.openclaw.use_openclaw_profile_if_available),
254
+ },
255
+ };
256
+ }
257
+ function getDefaultSocialConfig() {
258
+ return JSON.parse(JSON.stringify(DEFAULT_SOCIAL_CONFIG));
259
+ }
260
+ function generateDefaultSocialMdTemplate(options = {}) {
261
+ const displayName = options.display_name?.trim() || "My OpenClaw Agent";
262
+ const bio = options.bio?.trim() || "Local AI agent running on this machine";
263
+ const tags = Array.isArray(options.tags) && options.tags.length > 0 ? options.tags : ["openclaw", "local-first"];
264
+ const mode = options.mode ?? "lan";
265
+ const publicEnabled = typeof options.public_enabled === "boolean" ? options.public_enabled : false;
266
+ return `---
267
+ enabled: true
268
+ public_enabled: ${publicEnabled}
269
+
270
+ identity:
271
+ display_name: ${JSON.stringify(displayName)}
272
+ bio: ${JSON.stringify(bio)}
273
+ tags:
274
+ ${tags.map((tag) => ` - ${tag}`).join("\n")}
275
+
276
+ network:
277
+ mode: ${JSON.stringify(mode)}
278
+
279
+ openclaw:
280
+ bind_existing_identity: true
281
+ use_openclaw_profile_if_available: true
282
+ ---
283
+
284
+ # social.md
285
+
286
+ This file configures how OpenClaw integrates with SilicaClaw.
287
+ `;
288
+ }
@@ -0,0 +1,46 @@
1
+ import { AgentIdentity, ProfileInput, PublicProfile } from "./types";
2
+ import { DefaultSocialTemplateOptions, SocialConfig, SocialLoadMeta } from "./socialConfig";
3
+ export type SocialFileLookup = {
4
+ found: boolean;
5
+ source_path: string | null;
6
+ content: string | null;
7
+ };
8
+ export type OpenClawIdentityLookup = {
9
+ identity: AgentIdentity | null;
10
+ source_path: string | null;
11
+ };
12
+ export type OpenClawProfileLookup = {
13
+ profile: Partial<PublicProfile> | null;
14
+ source_path: string | null;
15
+ };
16
+ export type LoadedSocialConfig = {
17
+ config: SocialConfig;
18
+ meta: SocialLoadMeta;
19
+ raw_frontmatter: Record<string, unknown> | null;
20
+ };
21
+ export type ResolvedIdentityResult = {
22
+ identity: AgentIdentity;
23
+ source: "silicaclaw-existing" | "openclaw-existing" | "silicaclaw-generated";
24
+ openclaw_source_path: string | null;
25
+ };
26
+ export declare function getSocialConfigSearchPaths(rootDir?: string, homeDir?: string): string[];
27
+ export declare function findSocialMd(rootDir?: string): SocialFileLookup;
28
+ export declare function loadSocialConfig(rootDir?: string): LoadedSocialConfig;
29
+ export declare function findOpenClawIdentity(rootDir?: string, homeDir?: string): OpenClawIdentityLookup;
30
+ export declare function findOpenClawProfile(rootDir?: string, homeDir?: string): OpenClawProfileLookup;
31
+ export declare function resolveIdentityWithSocial(args: {
32
+ socialConfig: SocialConfig;
33
+ existingIdentity: AgentIdentity | null;
34
+ generatedIdentity: AgentIdentity;
35
+ rootDir?: string;
36
+ }): ResolvedIdentityResult;
37
+ export declare function resolveProfileInputWithSocial(args: {
38
+ socialConfig: SocialConfig;
39
+ agentId: string;
40
+ existingProfile: PublicProfile | null;
41
+ rootDir?: string;
42
+ }): ProfileInput;
43
+ export declare function ensureDefaultSocialMd(rootDir?: string, options?: DefaultSocialTemplateOptions): {
44
+ path: string;
45
+ created: boolean;
46
+ };
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSocialConfigSearchPaths = getSocialConfigSearchPaths;
4
+ exports.findSocialMd = findSocialMd;
5
+ exports.loadSocialConfig = loadSocialConfig;
6
+ exports.findOpenClawIdentity = findOpenClawIdentity;
7
+ exports.findOpenClawProfile = findOpenClawProfile;
8
+ exports.resolveIdentityWithSocial = resolveIdentityWithSocial;
9
+ exports.resolveProfileInputWithSocial = resolveProfileInputWithSocial;
10
+ exports.ensureDefaultSocialMd = ensureDefaultSocialMd;
11
+ const fs_1 = require("fs");
12
+ const os_1 = require("os");
13
+ const path_1 = require("path");
14
+ const crypto_1 = require("./crypto");
15
+ const socialConfig_1 = require("./socialConfig");
16
+ function getSocialConfigSearchPaths(rootDir = process.cwd(), homeDir = (0, os_1.homedir)()) {
17
+ return [
18
+ (0, path_1.resolve)(rootDir, "social.md"),
19
+ (0, path_1.resolve)(rootDir, ".openclaw", "social.md"),
20
+ (0, path_1.resolve)(homeDir, ".openclaw", "social.md"),
21
+ ];
22
+ }
23
+ function findSocialMd(rootDir = process.cwd()) {
24
+ const candidates = getSocialConfigSearchPaths(rootDir);
25
+ for (const path of candidates) {
26
+ if (!(0, fs_1.existsSync)(path))
27
+ continue;
28
+ return {
29
+ found: true,
30
+ source_path: path,
31
+ content: (0, fs_1.readFileSync)(path, "utf8"),
32
+ };
33
+ }
34
+ return {
35
+ found: false,
36
+ source_path: null,
37
+ content: null,
38
+ };
39
+ }
40
+ function loadSocialConfig(rootDir = process.cwd()) {
41
+ const lookup = findSocialMd(rootDir);
42
+ if (!lookup.found || !lookup.content || !lookup.source_path) {
43
+ return {
44
+ config: (0, socialConfig_1.normalizeSocialConfig)({}),
45
+ meta: {
46
+ found: false,
47
+ source_path: null,
48
+ parse_error: null,
49
+ loaded_at: Date.now(),
50
+ },
51
+ raw_frontmatter: null,
52
+ };
53
+ }
54
+ try {
55
+ const frontmatter = (0, socialConfig_1.extractFrontmatter)(lookup.content);
56
+ if (!frontmatter) {
57
+ return {
58
+ config: (0, socialConfig_1.normalizeSocialConfig)({}),
59
+ meta: {
60
+ found: true,
61
+ source_path: lookup.source_path,
62
+ parse_error: "frontmatter_not_found",
63
+ loaded_at: Date.now(),
64
+ },
65
+ raw_frontmatter: null,
66
+ };
67
+ }
68
+ const parsed = (0, socialConfig_1.parseFrontmatterObject)(frontmatter);
69
+ return {
70
+ config: (0, socialConfig_1.normalizeSocialConfig)(parsed),
71
+ meta: {
72
+ found: true,
73
+ source_path: lookup.source_path,
74
+ parse_error: null,
75
+ loaded_at: Date.now(),
76
+ },
77
+ raw_frontmatter: parsed,
78
+ };
79
+ }
80
+ catch (error) {
81
+ return {
82
+ config: (0, socialConfig_1.normalizeSocialConfig)({}),
83
+ meta: {
84
+ found: true,
85
+ source_path: lookup.source_path,
86
+ parse_error: error instanceof Error ? error.message : "social_parse_failed",
87
+ loaded_at: Date.now(),
88
+ },
89
+ raw_frontmatter: null,
90
+ };
91
+ }
92
+ }
93
+ function readJson(path) {
94
+ if (!(0, fs_1.existsSync)(path))
95
+ return null;
96
+ try {
97
+ return JSON.parse((0, fs_1.readFileSync)(path, "utf8"));
98
+ }
99
+ catch {
100
+ return null;
101
+ }
102
+ }
103
+ function normalizeIdentity(input) {
104
+ if (typeof input !== "object" || input === null) {
105
+ return null;
106
+ }
107
+ const value = input;
108
+ if (typeof value.public_key !== "string" || typeof value.private_key !== "string") {
109
+ return null;
110
+ }
111
+ let agentId = typeof value.agent_id === "string" ? value.agent_id : "";
112
+ if (!agentId) {
113
+ try {
114
+ agentId = (0, crypto_1.hashPublicKey)((0, crypto_1.fromBase64)(value.public_key));
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
120
+ return {
121
+ agent_id: agentId,
122
+ public_key: value.public_key,
123
+ private_key: value.private_key,
124
+ created_at: Number.isFinite(value.created_at) ? Number(value.created_at) : Date.now(),
125
+ };
126
+ }
127
+ function findOpenClawIdentity(rootDir = process.cwd(), homeDir = (0, os_1.homedir)()) {
128
+ const candidates = [
129
+ (0, path_1.resolve)(rootDir, ".openclaw", "identity.json"),
130
+ (0, path_1.resolve)(rootDir, "identity.json"),
131
+ (0, path_1.resolve)(homeDir, ".openclaw", "identity.json"),
132
+ ];
133
+ for (const path of candidates) {
134
+ const parsed = readJson(path);
135
+ const identity = normalizeIdentity(parsed);
136
+ if (identity) {
137
+ return {
138
+ identity,
139
+ source_path: path,
140
+ };
141
+ }
142
+ }
143
+ return {
144
+ identity: null,
145
+ source_path: null,
146
+ };
147
+ }
148
+ function findOpenClawProfile(rootDir = process.cwd(), homeDir = (0, os_1.homedir)()) {
149
+ const candidates = [
150
+ (0, path_1.resolve)(rootDir, ".openclaw", "profile.json"),
151
+ (0, path_1.resolve)(rootDir, "profile.json"),
152
+ (0, path_1.resolve)(homeDir, ".openclaw", "profile.json"),
153
+ ];
154
+ for (const path of candidates) {
155
+ const parsed = readJson(path);
156
+ if (typeof parsed !== "object" || parsed === null)
157
+ continue;
158
+ const profile = parsed;
159
+ return {
160
+ source_path: path,
161
+ profile: {
162
+ display_name: typeof profile.display_name === "string" ? profile.display_name : "",
163
+ bio: typeof profile.bio === "string" ? profile.bio : "",
164
+ avatar_url: typeof profile.avatar_url === "string" ? profile.avatar_url : "",
165
+ tags: Array.isArray(profile.tags)
166
+ ? profile.tags.map((tag) => String(tag).trim()).filter(Boolean)
167
+ : [],
168
+ },
169
+ };
170
+ }
171
+ return {
172
+ profile: null,
173
+ source_path: null,
174
+ };
175
+ }
176
+ function resolveIdentityWithSocial(args) {
177
+ const { socialConfig, existingIdentity, generatedIdentity } = args;
178
+ if (socialConfig.openclaw.bind_existing_identity) {
179
+ const openclaw = findOpenClawIdentity(args.rootDir ?? process.cwd());
180
+ if (openclaw.identity) {
181
+ return {
182
+ identity: openclaw.identity,
183
+ source: "openclaw-existing",
184
+ openclaw_source_path: openclaw.source_path,
185
+ };
186
+ }
187
+ }
188
+ if (existingIdentity) {
189
+ return {
190
+ identity: existingIdentity,
191
+ source: "silicaclaw-existing",
192
+ openclaw_source_path: null,
193
+ };
194
+ }
195
+ return {
196
+ identity: generatedIdentity,
197
+ source: "silicaclaw-generated",
198
+ openclaw_source_path: null,
199
+ };
200
+ }
201
+ function resolveProfileInputWithSocial(args) {
202
+ const { socialConfig, agentId, existingProfile } = args;
203
+ const openclawProfile = socialConfig.openclaw.use_openclaw_profile_if_available
204
+ ? findOpenClawProfile(args.rootDir ?? process.cwd()).profile
205
+ : null;
206
+ const baseDisplayName = existingProfile?.display_name || "";
207
+ const baseBio = existingProfile?.bio || "";
208
+ const baseAvatarUrl = existingProfile?.avatar_url || "";
209
+ const baseTags = existingProfile?.tags || [];
210
+ // Preserve values saved from local-console first; only fall back to social/openclaw defaults
211
+ // when local profile fields are empty.
212
+ const displayName = baseDisplayName || socialConfig.identity.display_name || openclawProfile?.display_name || "";
213
+ const bio = baseBio || socialConfig.identity.bio || openclawProfile?.bio || "";
214
+ const avatarUrl = baseAvatarUrl || socialConfig.identity.avatar_url || openclawProfile?.avatar_url || "";
215
+ const tags = baseTags.length > 0
216
+ ? baseTags
217
+ : socialConfig.identity.tags.length > 0
218
+ ? socialConfig.identity.tags
219
+ : openclawProfile?.tags || [];
220
+ return {
221
+ agent_id: agentId,
222
+ display_name: displayName,
223
+ bio,
224
+ avatar_url: avatarUrl,
225
+ tags,
226
+ public_enabled: existingProfile?.public_enabled ?? socialConfig.public_enabled,
227
+ };
228
+ }
229
+ function ensureDefaultSocialMd(rootDir = process.cwd(), options = {}) {
230
+ const targetPath = (0, path_1.resolve)(rootDir, "social.md");
231
+ if ((0, fs_1.existsSync)(targetPath)) {
232
+ return { path: targetPath, created: false };
233
+ }
234
+ (0, fs_1.mkdirSync)(rootDir, { recursive: true });
235
+ (0, fs_1.writeFileSync)(targetPath, (0, socialConfig_1.generateDefaultSocialMdTemplate)(options), "utf8");
236
+ return { path: targetPath, created: true };
237
+ }
@@ -0,0 +1,2 @@
1
+ import { SocialRuntimeConfig } from "./socialConfig";
2
+ export declare function generateSocialMdTemplate(runtimeConfig: SocialRuntimeConfig | null | undefined): string;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateSocialMdTemplate = generateSocialMdTemplate;
4
+ function asBool(value, fallback) {
5
+ return typeof value === "boolean" ? value : fallback;
6
+ }
7
+ function asString(value, fallback) {
8
+ return typeof value === "string" ? value : fallback;
9
+ }
10
+ function asStringArray(value, fallback) {
11
+ if (!Array.isArray(value))
12
+ return fallback;
13
+ return value.map((item) => String(item).trim()).filter(Boolean);
14
+ }
15
+ function yamlString(input) {
16
+ return JSON.stringify(input ?? "");
17
+ }
18
+ function yamlStringList(values, indent = " ") {
19
+ if (!values.length) {
20
+ return `${indent}[]`;
21
+ }
22
+ return values.map((value) => `${indent}- ${yamlString(value)}`).join("\n");
23
+ }
24
+ function generateSocialMdTemplate(runtimeConfig) {
25
+ const enabled = asBool(runtimeConfig?.enabled, true);
26
+ const publicEnabled = asBool(runtimeConfig?.public_enabled, false);
27
+ const profile = runtimeConfig?.resolved_profile ?? null;
28
+ const network = runtimeConfig?.resolved_network ?? null;
29
+ const discovery = runtimeConfig?.resolved_discovery ?? null;
30
+ const visibility = runtimeConfig?.visibility ?? null;
31
+ const openclaw = runtimeConfig?.openclaw ?? null;
32
+ const displayName = asString(profile?.display_name, "");
33
+ const bio = asString(profile?.bio, "");
34
+ const tags = asStringArray(profile?.tags, ["openclaw", "local-first"]);
35
+ const mode = network?.mode === "local" || network?.mode === "lan" || network?.mode === "global-preview"
36
+ ? network.mode
37
+ : "lan";
38
+ const discoverable = asBool(discovery?.discoverable, true);
39
+ const allowProfileBroadcast = asBool(discovery?.allow_profile_broadcast, true);
40
+ const allowPresenceBroadcast = asBool(discovery?.allow_presence_broadcast, true);
41
+ const showDisplayName = asBool(visibility?.show_display_name, true);
42
+ const showBio = asBool(visibility?.show_bio, true);
43
+ const showTags = asBool(visibility?.show_tags, true);
44
+ const showAgentId = asBool(visibility?.show_agent_id, true);
45
+ const showLastSeen = asBool(visibility?.show_last_seen, true);
46
+ const showCapabilitiesSummary = asBool(visibility?.show_capabilities_summary, true);
47
+ const bindExistingIdentity = asBool(openclaw?.bind_existing_identity, true);
48
+ const useOpenClawProfile = asBool(openclaw?.use_openclaw_profile_if_available, true);
49
+ return `---
50
+ enabled: ${enabled}
51
+ public_enabled: ${publicEnabled}
52
+
53
+ identity:
54
+ display_name: ${yamlString(displayName)}
55
+ bio: ${yamlString(bio)}
56
+ tags:
57
+ ${yamlStringList(tags.map((tag) => asString(tag, "")), " ")}
58
+
59
+ network:
60
+ mode: ${yamlString(mode)}
61
+
62
+ discovery:
63
+ discoverable: ${discoverable}
64
+ allow_profile_broadcast: ${allowProfileBroadcast}
65
+ allow_presence_broadcast: ${allowPresenceBroadcast}
66
+
67
+ visibility:
68
+ show_display_name: ${showDisplayName}
69
+ show_bio: ${showBio}
70
+ show_tags: ${showTags}
71
+ show_agent_id: ${showAgentId}
72
+ show_last_seen: ${showLastSeen}
73
+ show_capabilities_summary: ${showCapabilitiesSummary}
74
+
75
+ openclaw:
76
+ bind_existing_identity: ${bindExistingIdentity}
77
+ use_openclaw_profile_if_available: ${useOpenClawProfile}
78
+ ---
79
+
80
+ # Social
81
+
82
+ Generated from current SilicaClaw runtime state.
83
+
84
+ - Save as \`social.md\` in your OpenClaw workspace.
85
+ - This export does not auto-overwrite any existing file.
86
+ - Advanced network fields are intentionally hidden in template and resolved in runtime.
87
+ `;
88
+ }