@silicaclaw/cli 1.0.0-beta.0

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 (77) hide show
  1. package/ARCHITECTURE.md +137 -0
  2. package/CHANGELOG.md +411 -0
  3. package/DEMO_GUIDE.md +89 -0
  4. package/INSTALL.md +156 -0
  5. package/README.md +244 -0
  6. package/RELEASE_NOTES_v1.0.md +65 -0
  7. package/ROADMAP.md +48 -0
  8. package/SOCIAL_MD_SPEC.md +122 -0
  9. package/VERSION +1 -0
  10. package/apps/local-console/package.json +23 -0
  11. package/apps/local-console/public/assets/README.md +5 -0
  12. package/apps/local-console/public/assets/silicaclaw-logo.png +0 -0
  13. package/apps/local-console/public/index.html +1602 -0
  14. package/apps/local-console/src/server.ts +1656 -0
  15. package/apps/local-console/src/socialRoutes.ts +90 -0
  16. package/apps/local-console/tsconfig.json +7 -0
  17. package/apps/public-explorer/package.json +20 -0
  18. package/apps/public-explorer/public/assets/README.md +5 -0
  19. package/apps/public-explorer/public/assets/silicaclaw-logo.png +0 -0
  20. package/apps/public-explorer/public/index.html +483 -0
  21. package/apps/public-explorer/src/server.ts +32 -0
  22. package/apps/public-explorer/tsconfig.json +7 -0
  23. package/docs/QUICK_START.md +48 -0
  24. package/docs/assets/README.md +8 -0
  25. package/docs/assets/banner.svg +25 -0
  26. package/docs/assets/silicaclaw-logo.png +0 -0
  27. package/docs/assets/silicaclaw-og.png +0 -0
  28. package/docs/release/GITHUB_RELEASE_v1.0-beta.md +143 -0
  29. package/docs/screenshots/README.md +8 -0
  30. package/docs/screenshots/v0.3.1-explorer-search.svg +9 -0
  31. package/docs/screenshots/v0.3.1-machine-a-network.svg +9 -0
  32. package/docs/screenshots/v0.3.1-machine-b-peers.svg +9 -0
  33. package/docs/screenshots/v0.3.1-stale-transition.svg +9 -0
  34. package/openclaw.social.md.example +28 -0
  35. package/package.json +64 -0
  36. package/packages/core/package.json +13 -0
  37. package/packages/core/src/crypto.ts +55 -0
  38. package/packages/core/src/directory.ts +171 -0
  39. package/packages/core/src/identity.ts +14 -0
  40. package/packages/core/src/index.ts +11 -0
  41. package/packages/core/src/indexing.ts +42 -0
  42. package/packages/core/src/presence.ts +24 -0
  43. package/packages/core/src/profile.ts +39 -0
  44. package/packages/core/src/publicProfileSummary.ts +180 -0
  45. package/packages/core/src/socialConfig.ts +440 -0
  46. package/packages/core/src/socialResolver.ts +281 -0
  47. package/packages/core/src/socialTemplate.ts +97 -0
  48. package/packages/core/src/types.ts +43 -0
  49. package/packages/core/tsconfig.json +7 -0
  50. package/packages/network/package.json +10 -0
  51. package/packages/network/src/abstractions/messageEnvelope.ts +80 -0
  52. package/packages/network/src/abstractions/peerDiscovery.ts +49 -0
  53. package/packages/network/src/abstractions/topicCodec.ts +4 -0
  54. package/packages/network/src/abstractions/transport.ts +40 -0
  55. package/packages/network/src/codec/jsonMessageEnvelopeCodec.ts +22 -0
  56. package/packages/network/src/codec/jsonTopicCodec.ts +11 -0
  57. package/packages/network/src/discovery/heartbeatPeerDiscovery.ts +173 -0
  58. package/packages/network/src/index.ts +16 -0
  59. package/packages/network/src/localEventBus.ts +61 -0
  60. package/packages/network/src/mock.ts +27 -0
  61. package/packages/network/src/realPreview.ts +436 -0
  62. package/packages/network/src/transport/udpLanBroadcastTransport.ts +173 -0
  63. package/packages/network/src/types.ts +6 -0
  64. package/packages/network/src/webrtcPreview.ts +1052 -0
  65. package/packages/network/tsconfig.json +7 -0
  66. package/packages/storage/package.json +13 -0
  67. package/packages/storage/src/index.ts +3 -0
  68. package/packages/storage/src/jsonRepo.ts +25 -0
  69. package/packages/storage/src/repos.ts +46 -0
  70. package/packages/storage/src/socialRuntimeRepo.ts +51 -0
  71. package/packages/storage/tsconfig.json +7 -0
  72. package/scripts/functional-check.mjs +165 -0
  73. package/scripts/install-logo.sh +53 -0
  74. package/scripts/quickstart.sh +144 -0
  75. package/scripts/silicaclaw-cli.mjs +88 -0
  76. package/scripts/webrtc-signaling-server.mjs +249 -0
  77. package/social.md.example +30 -0
@@ -0,0 +1,42 @@
1
+ import { IndexRefRecord, PublicProfile } from "./types";
2
+
3
+ export function normalizeTag(tag: string): string {
4
+ return tag.trim().toLowerCase();
5
+ }
6
+
7
+ export function buildTagIndexKeys(tags: string[]): string[] {
8
+ return tags
9
+ .map(normalizeTag)
10
+ .filter(Boolean)
11
+ .map((tag) => `tag:${tag}`);
12
+ }
13
+
14
+ export function buildNamePrefixKeys(displayName: string): string[] {
15
+ const normalized = displayName.trim().toLowerCase().replace(/\s+/g, " ");
16
+ const collapsed = normalized.replace(/[^a-z0-9]+/g, "");
17
+ const source = collapsed || normalized.replace(/\s+/g, "");
18
+ const keys: string[] = [];
19
+ for (let i = 1; i <= source.length; i += 1) {
20
+ keys.push(`name:${source.slice(0, i)}`);
21
+ }
22
+ return keys;
23
+ }
24
+
25
+ export function buildIndexKeys(profile: PublicProfile): string[] {
26
+ const keys = new Set<string>();
27
+ for (const key of buildTagIndexKeys(profile.tags)) {
28
+ keys.add(key);
29
+ }
30
+ for (const key of buildNamePrefixKeys(profile.display_name)) {
31
+ keys.add(key);
32
+ }
33
+ return Array.from(keys);
34
+ }
35
+
36
+ export function buildIndexRecords(profile: PublicProfile): IndexRefRecord[] {
37
+ return buildIndexKeys(profile).map((key) => ({
38
+ type: "index",
39
+ key,
40
+ agent_id: profile.agent_id,
41
+ }));
42
+ }
@@ -0,0 +1,24 @@
1
+ import { AgentIdentity } from "./types";
2
+ import { signPayload, verifyPayload } from "./crypto";
3
+ import { PresenceRecord } from "./types";
4
+
5
+ function unsignedPresence(record: PresenceRecord): Omit<PresenceRecord, "signature"> {
6
+ const { signature: _signature, ...rest } = record;
7
+ return rest;
8
+ }
9
+
10
+ export function signPresence(identity: AgentIdentity, timestamp = Date.now()): PresenceRecord {
11
+ const payload = {
12
+ type: "presence" as const,
13
+ agent_id: identity.agent_id,
14
+ timestamp,
15
+ };
16
+ return {
17
+ ...payload,
18
+ signature: signPayload(payload, identity.private_key),
19
+ };
20
+ }
21
+
22
+ export function verifyPresence(record: PresenceRecord, publicKey: string): boolean {
23
+ return verifyPayload(unsignedPresence(record), record.signature, publicKey);
24
+ }
@@ -0,0 +1,39 @@
1
+ import { signPayload, verifyPayload } from "./crypto";
2
+ import { AgentIdentity, ProfileInput, PublicProfile } from "./types";
3
+
4
+ function payloadWithoutSignature(profile: PublicProfile): Omit<PublicProfile, "signature"> {
5
+ const { signature: _signature, ...payload } = profile;
6
+ return payload;
7
+ }
8
+
9
+ export function signProfile(input: ProfileInput, identity: AgentIdentity): PublicProfile {
10
+ const unsigned: Omit<PublicProfile, "signature"> = {
11
+ agent_id: input.agent_id,
12
+ display_name: input.display_name,
13
+ bio: input.bio,
14
+ tags: input.tags,
15
+ avatar_url: input.avatar_url,
16
+ public_enabled: input.public_enabled,
17
+ updated_at: Date.now(),
18
+ };
19
+ const signature = signPayload(unsigned, identity.private_key);
20
+ return {
21
+ ...unsigned,
22
+ signature,
23
+ };
24
+ }
25
+
26
+ export function verifyProfile(profile: PublicProfile, publicKey: string): boolean {
27
+ return verifyPayload(payloadWithoutSignature(profile), profile.signature, publicKey);
28
+ }
29
+
30
+ export function createDefaultProfileInput(agentId: string): ProfileInput {
31
+ return {
32
+ agent_id: agentId,
33
+ display_name: "",
34
+ bio: "",
35
+ tags: [],
36
+ avatar_url: "",
37
+ public_enabled: false,
38
+ };
39
+ }
@@ -0,0 +1,180 @@
1
+ import { PublicProfile } from "./types";
2
+
3
+ export type CapabilityKey = "browser" | "computer" | "research" | "openclaw";
4
+
5
+ export type ProfileVisibility = {
6
+ show_tags: boolean;
7
+ show_last_seen: boolean;
8
+ show_capabilities_summary: boolean;
9
+ };
10
+
11
+ export type PublicProfileSummary = {
12
+ agent_id: string;
13
+ display_name: string;
14
+ bio: string;
15
+ avatar_url?: string;
16
+ public_enabled: boolean;
17
+ updated_at: number;
18
+ online: boolean;
19
+ last_seen_at: number | null;
20
+ tags: string[];
21
+ network_mode: string;
22
+ openclaw_bound: boolean;
23
+ capabilities_summary: string[];
24
+ profile_version: string;
25
+ public_key_fingerprint: string | null;
26
+ profile_updated_at: number;
27
+ presence_seen_at: number | null;
28
+ freshness_status: "live" | "recently_seen" | "stale";
29
+ verified_profile: boolean;
30
+ verified_presence_recent: boolean;
31
+ verification_status: "verified" | "stale" | "unverified";
32
+ signed_claims: {
33
+ display_name: string;
34
+ bio: string;
35
+ avatar_url?: string;
36
+ tags: string[];
37
+ public_enabled: boolean;
38
+ profile_version: string;
39
+ profile_updated_at: number;
40
+ public_key_fingerprint: string | null;
41
+ verified_profile: boolean;
42
+ };
43
+ observed_state: {
44
+ online: boolean;
45
+ freshness_status: "live" | "recently_seen" | "stale";
46
+ presence_seen_at: number | null;
47
+ verified_presence_recent: boolean;
48
+ };
49
+ integration_metadata: {
50
+ network_mode: string;
51
+ openclaw_bound: boolean;
52
+ verification_status: "verified" | "stale" | "unverified";
53
+ };
54
+ public_visibility: {
55
+ visible_fields: string[];
56
+ hidden_fields: string[];
57
+ };
58
+ visibility: ProfileVisibility;
59
+ };
60
+
61
+ const DEFAULT_VISIBILITY: ProfileVisibility = {
62
+ show_tags: true,
63
+ show_last_seen: true,
64
+ show_capabilities_summary: true,
65
+ };
66
+
67
+ const CAPABILITY_KEYS: CapabilityKey[] = ["browser", "computer", "research", "openclaw"];
68
+
69
+ export function deriveCapabilitiesSummary(tags: string[]): string[] {
70
+ const normalized = new Set(tags.map((tag) => String(tag).trim().toLowerCase()).filter(Boolean));
71
+ return CAPABILITY_KEYS.filter((key) => normalized.has(key));
72
+ }
73
+
74
+ export function buildPublicProfileSummary(args: {
75
+ profile: PublicProfile;
76
+ online: boolean;
77
+ last_seen_at: number | null;
78
+ network_mode?: string;
79
+ openclaw_bound?: boolean;
80
+ visibility?: Partial<ProfileVisibility>;
81
+ profile_version?: string;
82
+ public_key_fingerprint?: string | null;
83
+ verified_profile?: boolean;
84
+ now?: number;
85
+ presence_ttl_ms?: number;
86
+ }): PublicProfileSummary {
87
+ const visibility: ProfileVisibility = {
88
+ show_tags:
89
+ typeof args.visibility?.show_tags === "boolean"
90
+ ? args.visibility.show_tags
91
+ : DEFAULT_VISIBILITY.show_tags,
92
+ show_last_seen:
93
+ typeof args.visibility?.show_last_seen === "boolean"
94
+ ? args.visibility.show_last_seen
95
+ : DEFAULT_VISIBILITY.show_last_seen,
96
+ show_capabilities_summary:
97
+ typeof args.visibility?.show_capabilities_summary === "boolean"
98
+ ? args.visibility.show_capabilities_summary
99
+ : DEFAULT_VISIBILITY.show_capabilities_summary,
100
+ };
101
+
102
+ const tags = visibility.show_tags ? args.profile.tags : [];
103
+ const capabilities = visibility.show_capabilities_summary ? deriveCapabilitiesSummary(args.profile.tags) : [];
104
+ const now = Number.isFinite(args.now) ? Number(args.now) : Date.now();
105
+ const ttl = Number.isFinite(args.presence_ttl_ms) ? Number(args.presence_ttl_ms) : 30_000;
106
+ const age = args.last_seen_at ? Math.max(0, now - args.last_seen_at) : Number.POSITIVE_INFINITY;
107
+ const freshness_status: "live" | "recently_seen" | "stale" =
108
+ age <= ttl ? "live" : age <= ttl * 3 ? "recently_seen" : "stale";
109
+ const verified_profile = Boolean(args.verified_profile);
110
+ const verified_presence_recent = freshness_status !== "stale" && Boolean(args.last_seen_at);
111
+ const verification_status: "verified" | "stale" | "unverified" = !verified_profile
112
+ ? "unverified"
113
+ : verified_presence_recent
114
+ ? "verified"
115
+ : "stale";
116
+ const visible_fields = [
117
+ "display_name",
118
+ "bio",
119
+ "public_enabled",
120
+ "profile_updated_at",
121
+ visibility.show_tags ? "tags" : "",
122
+ visibility.show_last_seen ? "presence_seen_at" : "",
123
+ visibility.show_capabilities_summary ? "capabilities_summary" : "",
124
+ ].filter((field): field is string => Boolean(field));
125
+ const hidden_fields = [
126
+ visibility.show_tags ? "" : "tags",
127
+ visibility.show_last_seen ? "" : "presence_seen_at",
128
+ visibility.show_capabilities_summary ? "" : "capabilities_summary",
129
+ ].filter((field): field is string => Boolean(field));
130
+
131
+ return {
132
+ agent_id: args.profile.agent_id,
133
+ display_name: args.profile.display_name,
134
+ bio: args.profile.bio,
135
+ avatar_url: args.profile.avatar_url,
136
+ public_enabled: args.profile.public_enabled,
137
+ updated_at: args.profile.updated_at,
138
+ online: args.online,
139
+ last_seen_at: visibility.show_last_seen ? args.last_seen_at : null,
140
+ tags,
141
+ network_mode: args.network_mode ?? "unknown",
142
+ openclaw_bound: Boolean(args.openclaw_bound),
143
+ capabilities_summary: capabilities,
144
+ profile_version: args.profile_version ?? "v1",
145
+ public_key_fingerprint: args.public_key_fingerprint ?? null,
146
+ profile_updated_at: args.profile.updated_at,
147
+ presence_seen_at: visibility.show_last_seen ? args.last_seen_at : null,
148
+ freshness_status,
149
+ verified_profile,
150
+ verified_presence_recent,
151
+ verification_status,
152
+ signed_claims: {
153
+ display_name: args.profile.display_name,
154
+ bio: args.profile.bio,
155
+ avatar_url: args.profile.avatar_url,
156
+ tags,
157
+ public_enabled: args.profile.public_enabled,
158
+ profile_version: args.profile_version ?? "v1",
159
+ profile_updated_at: args.profile.updated_at,
160
+ public_key_fingerprint: args.public_key_fingerprint ?? null,
161
+ verified_profile,
162
+ },
163
+ observed_state: {
164
+ online: args.online,
165
+ freshness_status,
166
+ presence_seen_at: visibility.show_last_seen ? args.last_seen_at : null,
167
+ verified_presence_recent,
168
+ },
169
+ integration_metadata: {
170
+ network_mode: args.network_mode ?? "unknown",
171
+ openclaw_bound: Boolean(args.openclaw_bound),
172
+ verification_status,
173
+ },
174
+ public_visibility: {
175
+ visible_fields,
176
+ hidden_fields,
177
+ },
178
+ visibility,
179
+ };
180
+ }