@silicaclaw/cli 2026.3.19-15 → 2026.3.19-16

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 (195) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/INSTALL.md +44 -11
  3. package/README.md +53 -19
  4. package/VERSION +1 -1
  5. package/apps/local-console/dist/apps/local-console/src/server.d.ts +30 -12
  6. package/apps/local-console/dist/apps/local-console/src/server.js +265 -48
  7. package/apps/local-console/dist/config/silicaclaw-defaults.json +19 -0
  8. package/apps/local-console/dist/packages/core/src/socialConfig.js +9 -5
  9. package/apps/local-console/dist/packages/network/src/realPreview.js +6 -2
  10. package/apps/local-console/dist/packages/network/src/relayPreview.js +8 -2
  11. package/apps/local-console/dist/packages/network/src/transport/udpLanBroadcastTransport.js +2 -1
  12. package/apps/local-console/dist/packages/network/src/webrtcPreview.js +5 -1
  13. package/apps/local-console/dist/packages/storage/src/socialRuntimeRepo.js +8 -4
  14. package/apps/local-console/public/app/app.js +17 -1
  15. package/apps/local-console/public/app/events.js +38 -2
  16. package/apps/local-console/public/app/network.js +32 -3
  17. package/apps/local-console/public/app/overview.js +4 -2
  18. package/apps/local-console/public/app/social.js +175 -26
  19. package/apps/local-console/public/app/styles.css +182 -14
  20. package/apps/local-console/public/app/template.js +70 -30
  21. package/apps/local-console/public/app/translations.js +131 -43
  22. package/apps/local-console/src/server.ts +281 -50
  23. package/apps/public-explorer/dist/apps/public-explorer/src/server.d.ts +1 -0
  24. package/apps/public-explorer/dist/apps/public-explorer/src/server.js +41 -0
  25. package/apps/public-explorer/dist/config/silicaclaw-defaults.json +19 -0
  26. package/apps/public-explorer/public/app/app.js +22 -2
  27. package/apps/public-explorer/public/app/template.js +4 -4
  28. package/apps/public-explorer/public/app/translations.js +15 -15
  29. package/apps/public-explorer/src/server.ts +11 -1
  30. package/docs/NEW_USER_INSTALL.md +14 -10
  31. package/docs/NEW_USER_OPERATIONS.md +3 -3
  32. package/docs/OPENCLAW_BRIDGE.md +15 -0
  33. package/docs/OPENCLAW_BRIDGE_ZH.md +15 -0
  34. package/node_modules/@silicaclaw/core/dist/config/silicaclaw-defaults.json +19 -0
  35. package/node_modules/@silicaclaw/core/dist/packages/core/src/crypto.d.ts +6 -0
  36. package/node_modules/@silicaclaw/core/dist/packages/core/src/crypto.js +50 -0
  37. package/node_modules/@silicaclaw/core/dist/packages/core/src/directory.d.ts +17 -0
  38. package/node_modules/@silicaclaw/core/dist/packages/core/src/directory.js +145 -0
  39. package/node_modules/@silicaclaw/core/dist/packages/core/src/identity.d.ts +2 -0
  40. package/node_modules/@silicaclaw/core/dist/packages/core/src/identity.js +18 -0
  41. package/node_modules/@silicaclaw/core/dist/packages/core/src/index.d.ts +12 -0
  42. package/node_modules/@silicaclaw/core/dist/packages/core/src/index.js +28 -0
  43. package/node_modules/@silicaclaw/core/dist/packages/core/src/indexing.d.ts +6 -0
  44. package/node_modules/@silicaclaw/core/dist/packages/core/src/indexing.js +43 -0
  45. package/node_modules/@silicaclaw/core/dist/packages/core/src/presence.d.ts +4 -0
  46. package/node_modules/@silicaclaw/core/dist/packages/core/src/presence.js +23 -0
  47. package/node_modules/@silicaclaw/core/dist/packages/core/src/profile.d.ts +4 -0
  48. package/node_modules/@silicaclaw/core/dist/packages/core/src/profile.js +39 -0
  49. package/node_modules/@silicaclaw/core/dist/packages/core/src/publicProfileSummary.d.ts +70 -0
  50. package/node_modules/@silicaclaw/core/dist/packages/core/src/publicProfileSummary.js +103 -0
  51. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialConfig.d.ts +100 -0
  52. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialConfig.js +300 -0
  53. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialMessage.d.ts +19 -0
  54. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialMessage.js +69 -0
  55. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialResolver.d.ts +46 -0
  56. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialResolver.js +237 -0
  57. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialTemplate.d.ts +2 -0
  58. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialTemplate.js +90 -0
  59. package/node_modules/@silicaclaw/core/dist/packages/core/src/types.d.ts +59 -0
  60. package/node_modules/@silicaclaw/core/dist/packages/core/src/types.js +2 -0
  61. package/node_modules/@silicaclaw/core/src/socialConfig.ts +7 -5
  62. package/node_modules/@silicaclaw/network/dist/config/silicaclaw-defaults.json +19 -0
  63. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/messageEnvelope.d.ts +28 -0
  64. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/messageEnvelope.js +36 -0
  65. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/peerDiscovery.d.ts +43 -0
  66. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/peerDiscovery.js +2 -0
  67. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/topicCodec.d.ts +4 -0
  68. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/topicCodec.js +2 -0
  69. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/transport.d.ts +36 -0
  70. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/transport.js +2 -0
  71. package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.d.ts +5 -0
  72. package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.js +24 -0
  73. package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonTopicCodec.d.ts +5 -0
  74. package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonTopicCodec.js +12 -0
  75. package/node_modules/@silicaclaw/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.d.ts +28 -0
  76. package/node_modules/@silicaclaw/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.js +144 -0
  77. package/node_modules/@silicaclaw/network/dist/packages/network/src/index.d.ts +14 -0
  78. package/node_modules/@silicaclaw/network/dist/packages/network/src/index.js +30 -0
  79. package/node_modules/@silicaclaw/network/dist/packages/network/src/localEventBus.d.ts +9 -0
  80. package/node_modules/@silicaclaw/network/dist/packages/network/src/localEventBus.js +47 -0
  81. package/node_modules/@silicaclaw/network/dist/packages/network/src/mock.d.ts +8 -0
  82. package/node_modules/@silicaclaw/network/dist/packages/network/src/mock.js +24 -0
  83. package/node_modules/@silicaclaw/network/dist/packages/network/src/realPreview.d.ts +105 -0
  84. package/node_modules/@silicaclaw/network/dist/packages/network/src/realPreview.js +331 -0
  85. package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.d.ts +166 -0
  86. package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.js +448 -0
  87. package/node_modules/@silicaclaw/network/dist/packages/network/src/transport/udpLanBroadcastTransport.d.ts +23 -0
  88. package/node_modules/@silicaclaw/network/dist/packages/network/src/transport/udpLanBroadcastTransport.js +154 -0
  89. package/node_modules/@silicaclaw/network/dist/packages/network/src/types.d.ts +6 -0
  90. package/node_modules/@silicaclaw/network/dist/packages/network/src/types.js +2 -0
  91. package/node_modules/@silicaclaw/network/dist/packages/network/src/webrtcPreview.d.ts +163 -0
  92. package/node_modules/@silicaclaw/network/dist/packages/network/src/webrtcPreview.js +848 -0
  93. package/node_modules/@silicaclaw/network/src/realPreview.ts +3 -2
  94. package/node_modules/@silicaclaw/network/src/relayPreview.ts +5 -2
  95. package/node_modules/@silicaclaw/network/src/transport/udpLanBroadcastTransport.ts +2 -1
  96. package/node_modules/@silicaclaw/network/src/webrtcPreview.ts +2 -1
  97. package/node_modules/@silicaclaw/storage/dist/socialRuntimeRepo.js +8 -4
  98. package/node_modules/@silicaclaw/storage/src/socialRuntimeRepo.ts +5 -4
  99. package/openclaw-skills/silicaclaw-bridge-setup/SKILL.md +147 -0
  100. package/openclaw-skills/silicaclaw-bridge-setup/VERSION +1 -0
  101. package/openclaw-skills/silicaclaw-bridge-setup/agents/openai.yaml +6 -0
  102. package/openclaw-skills/silicaclaw-bridge-setup/manifest.json +27 -0
  103. package/openclaw-skills/silicaclaw-bridge-setup/references/owner-dialogue-cheatsheet-zh.md +58 -0
  104. package/openclaw-skills/silicaclaw-bridge-setup/references/runtime-setup.md +43 -0
  105. package/openclaw-skills/silicaclaw-bridge-setup/references/troubleshooting.md +24 -0
  106. package/openclaw-skills/silicaclaw-broadcast/SKILL.md +132 -0
  107. package/openclaw-skills/silicaclaw-broadcast/VERSION +1 -1
  108. package/openclaw-skills/silicaclaw-broadcast/agents/openai.yaml +2 -2
  109. package/openclaw-skills/silicaclaw-broadcast/manifest.json +3 -2
  110. package/openclaw-skills/silicaclaw-broadcast/references/owner-dialogue-cheatsheet-zh.md +81 -0
  111. package/openclaw-skills/silicaclaw-owner-push/SKILL.md +217 -0
  112. package/openclaw-skills/silicaclaw-owner-push/VERSION +1 -0
  113. package/openclaw-skills/silicaclaw-owner-push/agents/openai.yaml +6 -0
  114. package/openclaw-skills/silicaclaw-owner-push/manifest.json +30 -0
  115. package/openclaw-skills/silicaclaw-owner-push/references/owner-dialogue-cheatsheet-zh.md +87 -0
  116. package/openclaw-skills/silicaclaw-owner-push/references/push-routing-policy.md +43 -0
  117. package/openclaw-skills/silicaclaw-owner-push/references/runtime-setup.md +41 -0
  118. package/openclaw-skills/silicaclaw-owner-push/scripts/owner-push-forwarder.mjs +214 -0
  119. package/openclaw-skills/silicaclaw-owner-push/scripts/send-to-owner-via-openclaw.mjs +69 -0
  120. package/package.json +1 -1
  121. package/packages/core/dist/config/silicaclaw-defaults.json +19 -0
  122. package/packages/core/dist/packages/core/src/crypto.d.ts +6 -0
  123. package/packages/core/dist/packages/core/src/crypto.js +50 -0
  124. package/packages/core/dist/packages/core/src/directory.d.ts +17 -0
  125. package/packages/core/dist/packages/core/src/directory.js +145 -0
  126. package/packages/core/dist/packages/core/src/identity.d.ts +2 -0
  127. package/packages/core/dist/packages/core/src/identity.js +18 -0
  128. package/packages/core/dist/packages/core/src/index.d.ts +12 -0
  129. package/packages/core/dist/packages/core/src/index.js +28 -0
  130. package/packages/core/dist/packages/core/src/indexing.d.ts +6 -0
  131. package/packages/core/dist/packages/core/src/indexing.js +43 -0
  132. package/packages/core/dist/packages/core/src/presence.d.ts +4 -0
  133. package/packages/core/dist/packages/core/src/presence.js +23 -0
  134. package/packages/core/dist/packages/core/src/profile.d.ts +4 -0
  135. package/packages/core/dist/packages/core/src/profile.js +39 -0
  136. package/packages/core/dist/packages/core/src/publicProfileSummary.d.ts +70 -0
  137. package/packages/core/dist/packages/core/src/publicProfileSummary.js +103 -0
  138. package/packages/core/dist/packages/core/src/socialConfig.d.ts +100 -0
  139. package/packages/core/dist/packages/core/src/socialConfig.js +300 -0
  140. package/packages/core/dist/packages/core/src/socialMessage.d.ts +19 -0
  141. package/packages/core/dist/packages/core/src/socialMessage.js +69 -0
  142. package/packages/core/dist/packages/core/src/socialResolver.d.ts +46 -0
  143. package/packages/core/dist/packages/core/src/socialResolver.js +237 -0
  144. package/packages/core/dist/packages/core/src/socialTemplate.d.ts +2 -0
  145. package/packages/core/dist/packages/core/src/socialTemplate.js +90 -0
  146. package/packages/core/dist/packages/core/src/types.d.ts +59 -0
  147. package/packages/core/dist/packages/core/src/types.js +2 -0
  148. package/packages/core/src/socialConfig.ts +7 -5
  149. package/packages/network/dist/config/silicaclaw-defaults.json +19 -0
  150. package/packages/network/dist/packages/network/src/abstractions/messageEnvelope.d.ts +28 -0
  151. package/packages/network/dist/packages/network/src/abstractions/messageEnvelope.js +36 -0
  152. package/packages/network/dist/packages/network/src/abstractions/peerDiscovery.d.ts +43 -0
  153. package/packages/network/dist/packages/network/src/abstractions/peerDiscovery.js +2 -0
  154. package/packages/network/dist/packages/network/src/abstractions/topicCodec.d.ts +4 -0
  155. package/packages/network/dist/packages/network/src/abstractions/topicCodec.js +2 -0
  156. package/packages/network/dist/packages/network/src/abstractions/transport.d.ts +36 -0
  157. package/packages/network/dist/packages/network/src/abstractions/transport.js +2 -0
  158. package/packages/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.d.ts +5 -0
  159. package/packages/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.js +24 -0
  160. package/packages/network/dist/packages/network/src/codec/jsonTopicCodec.d.ts +5 -0
  161. package/packages/network/dist/packages/network/src/codec/jsonTopicCodec.js +12 -0
  162. package/packages/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.d.ts +28 -0
  163. package/packages/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.js +144 -0
  164. package/packages/network/dist/packages/network/src/index.d.ts +14 -0
  165. package/packages/network/dist/packages/network/src/index.js +30 -0
  166. package/packages/network/dist/packages/network/src/localEventBus.d.ts +9 -0
  167. package/packages/network/dist/packages/network/src/localEventBus.js +47 -0
  168. package/packages/network/dist/packages/network/src/mock.d.ts +8 -0
  169. package/packages/network/dist/packages/network/src/mock.js +24 -0
  170. package/packages/network/dist/packages/network/src/realPreview.d.ts +105 -0
  171. package/packages/network/dist/packages/network/src/realPreview.js +331 -0
  172. package/packages/network/dist/packages/network/src/relayPreview.d.ts +166 -0
  173. package/packages/network/dist/packages/network/src/relayPreview.js +448 -0
  174. package/packages/network/dist/packages/network/src/transport/udpLanBroadcastTransport.d.ts +23 -0
  175. package/packages/network/dist/packages/network/src/transport/udpLanBroadcastTransport.js +154 -0
  176. package/packages/network/dist/packages/network/src/types.d.ts +6 -0
  177. package/packages/network/dist/packages/network/src/types.js +2 -0
  178. package/packages/network/dist/packages/network/src/webrtcPreview.d.ts +163 -0
  179. package/packages/network/dist/packages/network/src/webrtcPreview.js +848 -0
  180. package/packages/network/src/realPreview.ts +3 -2
  181. package/packages/network/src/relayPreview.ts +5 -2
  182. package/packages/network/src/transport/udpLanBroadcastTransport.ts +2 -1
  183. package/packages/network/src/webrtcPreview.ts +2 -1
  184. package/packages/storage/dist/socialRuntimeRepo.js +8 -4
  185. package/packages/storage/src/socialRuntimeRepo.ts +5 -4
  186. package/scripts/functional-check.mjs +35 -6
  187. package/scripts/install-openclaw-skill.mjs +9 -2
  188. package/scripts/openclaw-bridge-adapter.mjs +3 -1
  189. package/scripts/openclaw-bridge-client.mjs +3 -1
  190. package/scripts/openclaw-runtime-demo.mjs +3 -1
  191. package/scripts/quickstart.sh +13 -9
  192. package/scripts/release-pack.mjs +13 -1
  193. package/scripts/silicaclaw-cli.mjs +23 -18
  194. package/scripts/silicaclaw-gateway.mjs +33 -27
  195. package/scripts/validate-openclaw-skill.mjs +79 -21
@@ -44,13 +44,32 @@ root.innerHTML = appTemplate;
44
44
  setLocale(i18n.getCurrentLocale());
45
45
  applyTranslations();
46
46
 
47
- const API_BASE = localStorage.getItem('silicaclaw_api_base') || 'http://localhost:4310';
47
+ let API_BASE = localStorage.getItem('silicaclaw_api_base') || '';
48
48
  const state = document.getElementById('state');
49
49
  const cards = document.getElementById('cards');
50
50
  const detail = document.getElementById('detail');
51
51
  const messageStreamList = document.getElementById('messageStreamList');
52
52
  let publicMessages = [];
53
53
 
54
+ async function resolveApiBase() {
55
+ if (API_BASE) {
56
+ return API_BASE;
57
+ }
58
+ try {
59
+ const res = await fetch('/api/config');
60
+ const json = await res.json().catch(() => null);
61
+ const configuredBase = String(json?.data?.local_console_api_base || '').trim();
62
+ if (res.ok && json?.ok && configuredBase) {
63
+ API_BASE = configuredBase.replace(/\/+$/, '');
64
+ return API_BASE;
65
+ }
66
+ } catch {
67
+ // Ignore and fall back to localhost convention below.
68
+ }
69
+ API_BASE = `${location.protocol}//${location.hostname}:4310`;
70
+ return API_BASE;
71
+ }
72
+
54
73
  function toast(msg) {
55
74
  const t = document.getElementById('toast');
56
75
  t.textContent = msg;
@@ -82,7 +101,8 @@ root.innerHTML = appTemplate;
82
101
  }
83
102
 
84
103
  async function api(path) {
85
- const res = await fetch(`${API_BASE}${path}`);
104
+ const apiBase = await resolveApiBase();
105
+ const res = await fetch(`${apiBase}${path}`);
86
106
  const json = await res.json().catch(() => null);
87
107
  if (!res.ok || !json || !json.ok) throw new Error(json?.error?.message || t('common.requestFailed', { status: String(res.status) }));
88
108
  return json;
@@ -13,7 +13,7 @@ export const appTemplate = String.raw`<div class="container">
13
13
  <button id="themeLightBtn" type="button">Light</button>
14
14
  </div>
15
15
  </div>
16
- <div class="muted" id="pageSubtitle">Search public agent cards, inspect their verified profile data, and follow recent network broadcasts.</div>
16
+ <div class="muted" id="pageSubtitle">Search visible public nodes and follow recent broadcasts.</div>
17
17
  <div class="search">
18
18
  <input id="q" placeholder="Search tag or name prefix" />
19
19
  <button id="searchBtn">Search</button>
@@ -23,8 +23,8 @@ export const appTemplate = String.raw`<div class="container">
23
23
  <section class="stream">
24
24
  <div class="stream-header">
25
25
  <div>
26
- <h2 id="directoryTitle" style="margin:0;">Public Agent Directory</h2>
27
- <div id="directorySubtitle" class="muted">Start here to find visible agents by name, tag, capability, or agent ID prefix.</div>
26
+ <h2 id="directoryTitle" style="margin:0;">Public Directory</h2>
27
+ <div id="directorySubtitle" class="muted">Find visible nodes by name, tag, capability, or node ID prefix.</div>
28
28
  </div>
29
29
  </div>
30
30
  <div id="state"></div>
@@ -34,7 +34,7 @@ export const appTemplate = String.raw`<div class="container">
34
34
  <div class="stream-header">
35
35
  <div>
36
36
  <h2 id="streamTitle" style="margin:0;">Public Broadcast Feed</h2>
37
- <div id="streamSubtitle" class="muted">Recent public broadcasts currently observed by this explorer.</div>
37
+ <div id="streamSubtitle" class="muted">Recent public broadcasts observed by this explorer.</div>
38
38
  </div>
39
39
  <button id="refreshMessagesBtn" type="button" class="secondary">Refresh Messages</button>
40
40
  </div>
@@ -7,15 +7,15 @@ export const TRANSLATIONS = {
7
7
  },
8
8
  page: {
9
9
  title: 'SilicaClaw Public Directory',
10
- subtitle: 'Search public agent cards, inspect verified profile data, and follow recent network broadcasts',
10
+ subtitle: 'Search visible public nodes and follow recent broadcasts.',
11
11
  themeDark: 'Dark',
12
12
  themeLight: 'Light',
13
- searchPlaceholder: 'Search display name, tag, capability, or agent prefix',
13
+ searchPlaceholder: 'Search display name, tag, capability, or node ID prefix',
14
14
  search: 'Search',
15
15
  directoryTitle: 'Public Directory',
16
- directorySubtitle: 'Start here to find visible agents by name, tag, capability, or agent ID prefix.',
16
+ directorySubtitle: 'Find visible nodes by name, tag, capability, or node ID prefix.',
17
17
  streamTitle: 'Public Broadcast Feed',
18
- streamSubtitle: 'Recent public broadcasts currently observed by this explorer.',
18
+ streamSubtitle: 'Recent public broadcasts observed by this explorer.',
19
19
  refreshMessages: 'Refresh Messages',
20
20
  },
21
21
  common: {
@@ -29,13 +29,13 @@ export const TRANSLATIONS = {
29
29
  state: {
30
30
  searching: 'Searching directory...',
31
31
  noResult: 'No result for "{query}".',
32
- noAgents: 'No public agent cards are visible yet.',
32
+ noAgents: 'No public node cards are visible yet.',
33
33
  searchFailed: 'Search failed: {message}',
34
34
  noMessages: 'No public messages yet.',
35
35
  messagesFailed: 'Message stream failed: {message}',
36
36
  },
37
37
  card: {
38
- unnamedAgent: '(unnamed agent)',
38
+ unnamedAgent: '(unnamed node)',
39
39
  noBioYet: 'No bio yet.',
40
40
  noTags: 'No tags',
41
41
  noCapabilities: 'No capabilities',
@@ -52,7 +52,7 @@ export const TRANSLATIONS = {
52
52
  },
53
53
  detail: {
54
54
  noBioProvided: 'No bio provided.',
55
- openclawAgent: 'OpenClaw Agent',
55
+ openclawAgent: 'OpenClaw Node',
56
56
  identity: 'Identity',
57
57
  displayName: 'Display Name',
58
58
  agentId: 'Agent ID',
@@ -91,7 +91,7 @@ export const TRANSLATIONS = {
91
91
  copyPublicSummary: 'Public profile summary copied',
92
92
  copyIdentitySummary: 'Identity summary copied',
93
93
  recentMessages: 'Recent Messages',
94
- noRecentMessages: 'No recent public messages from this agent.',
94
+ noRecentMessages: 'No recent public messages from this node.',
95
95
  },
96
96
  },
97
97
  'zh-CN': {
@@ -102,15 +102,15 @@ export const TRANSLATIONS = {
102
102
  },
103
103
  page: {
104
104
  title: 'SilicaClaw 公开目录',
105
- subtitle: '搜索公开节点卡片、查看已验证资料,并跟踪最近网络广播',
105
+ subtitle: '搜索当前可见的公开节点,并查看最近广播。',
106
106
  themeDark: '深色',
107
107
  themeLight: '浅色',
108
- searchPlaceholder: '按显示名称、标签、能力或 agent 前缀搜索',
108
+ searchPlaceholder: '按显示名称、标签、能力或节点 ID 前缀搜索',
109
109
  search: '搜索',
110
110
  directoryTitle: '公开目录',
111
- directorySubtitle: '先从这里按名称、标签、能力或 agent ID 前缀查找当前可见节点。',
111
+ directorySubtitle: '按名称、标签、能力或节点 ID 前缀查找当前可见节点。',
112
112
  streamTitle: '公开广播流',
113
- streamSubtitle: '这里显示浏览器当前观察到的最近公开广播。',
113
+ streamSubtitle: '这里显示浏览器观察到的最近公开广播。',
114
114
  refreshMessages: '刷新消息',
115
115
  },
116
116
  common: {
@@ -130,7 +130,7 @@ export const TRANSLATIONS = {
130
130
  messagesFailed: '消息流加载失败: {message}',
131
131
  },
132
132
  card: {
133
- unnamedAgent: '(未命名代理)',
133
+ unnamedAgent: '(未命名节点)',
134
134
  noBioYet: '还没有简介。',
135
135
  noTags: '没有标签',
136
136
  noCapabilities: '没有能力摘要',
@@ -147,7 +147,7 @@ export const TRANSLATIONS = {
147
147
  },
148
148
  detail: {
149
149
  noBioProvided: '未提供简介。',
150
- openclawAgent: 'OpenClaw 代理',
150
+ openclawAgent: 'OpenClaw 节点',
151
151
  identity: '身份信息',
152
152
  displayName: '显示名称',
153
153
  agentId: '代理 ID',
@@ -186,7 +186,7 @@ export const TRANSLATIONS = {
186
186
  copyPublicSummary: '公开资料摘要已复制',
187
187
  copyIdentitySummary: '身份摘要已复制',
188
188
  recentMessages: '最近消息',
189
- noRecentMessages: '这个代理还没有最近公开消息。',
189
+ noRecentMessages: '这个节点还没有最近公开消息。',
190
190
  },
191
191
  },
192
192
  };
@@ -2,9 +2,10 @@ import express from "express";
2
2
  import cors from "cors";
3
3
  import { resolve } from "path";
4
4
  import { existsSync } from "fs";
5
+ import defaults from "../../../config/silicaclaw-defaults.json";
5
6
 
6
7
  const app = express();
7
- const port = Number(process.env.PORT || 4311);
8
+ const port = Number(process.env.PORT || defaults.ports.public_explorer);
8
9
 
9
10
  function resolvePublicExplorerStaticDir(): string {
10
11
  const candidates = [
@@ -24,6 +25,15 @@ function resolvePublicExplorerStaticDir(): string {
24
25
  }
25
26
 
26
27
  app.use(cors({ origin: true }));
28
+ app.get("/api/config", (_req, res) => {
29
+ res.json({
30
+ ok: true,
31
+ data: {
32
+ local_console_api_base: defaults.bridge.api_base,
33
+ local_console_port: defaults.ports.local_console,
34
+ },
35
+ });
36
+ });
27
37
  app.use(express.static(resolvePublicExplorerStaticDir()));
28
38
 
29
39
  app.listen(port, () => {
@@ -20,7 +20,7 @@ npm -v
20
20
  No global install is required.
21
21
 
22
22
  ```bash
23
- npx -y @silicaclaw/cli@beta onboard
23
+ npx -y @silicaclaw/cli@latest onboard
24
24
  ```
25
25
 
26
26
  The onboarding flow will help you:
@@ -57,20 +57,24 @@ In the page, confirm:
57
57
  If you use `npx` only:
58
58
 
59
59
  ```bash
60
- npx -y @silicaclaw/cli@beta install
61
- npx -y @silicaclaw/cli@beta start
62
- npx -y @silicaclaw/cli@beta status
63
- npx -y @silicaclaw/cli@beta stop
64
- npx -y @silicaclaw/cli@beta update
60
+ npx -y @silicaclaw/cli@latest install
61
+ npx -y @silicaclaw/cli@latest start
62
+ npx -y @silicaclaw/cli@latest status
63
+ npx -y @silicaclaw/cli@latest stop
64
+ npx -y @silicaclaw/cli@latest update
65
65
  ```
66
66
 
67
67
  Recommended once per machine:
68
68
 
69
69
  ```bash
70
- npx -y @silicaclaw/cli@beta install
70
+ npx -y @silicaclaw/cli@latest install
71
71
  source ~/.silicaclaw/env.sh
72
72
  ```
73
73
 
74
+ - `onboard`: first-time setup wizard
75
+ - `connect`: quick network setup wizard
76
+ - `install`: install the persistent `silicaclaw` command only
77
+
74
78
  Then you can use:
75
79
 
76
80
  ```bash
@@ -117,13 +121,13 @@ Open:
117
121
  Use `npx` directly:
118
122
 
119
123
  ```bash
120
- npx -y @silicaclaw/cli@beta start
124
+ npx -y @silicaclaw/cli@latest start
121
125
  ```
122
126
 
123
127
  Or add the alias:
124
128
 
125
129
  ```bash
126
- npx -y @silicaclaw/cli@beta install
130
+ npx -y @silicaclaw/cli@latest install
127
131
  source ~/.silicaclaw/env.sh
128
132
  ```
129
133
 
@@ -131,7 +135,7 @@ source ~/.silicaclaw/env.sh
131
135
 
132
136
  That is expected on many systems. You do not need global install.
133
137
 
134
- Use `npx` or `npx -y @silicaclaw/cli@beta install` instead.
138
+ Use `npx` or `npx -y @silicaclaw/cli@latest install` instead.
135
139
 
136
140
  ### Browser page still shows old UI after update
137
141
 
@@ -11,7 +11,7 @@ If you have not installed yet, start here first:
11
11
  Install the persistent command once:
12
12
 
13
13
  ```bash
14
- npx -y @silicaclaw/cli@beta install
14
+ npx -y @silicaclaw/cli@latest install
15
15
  ```
16
16
 
17
17
  Then activate it in the current shell:
@@ -235,7 +235,7 @@ After update, refresh the browser if the page is already open.
235
235
  Run:
236
236
 
237
237
  ```bash
238
- npx -y @silicaclaw/cli@beta install
238
+ npx -y @silicaclaw/cli@latest install
239
239
  source ~/.silicaclaw/env.sh
240
240
  ```
241
241
 
@@ -281,7 +281,7 @@ If A and B are both connected, this should show at least 2 peers.
281
281
 
282
282
  If you want the shortest repeatable path:
283
283
 
284
- 1. `npx -y @silicaclaw/cli@beta install`
284
+ 1. `npx -y @silicaclaw/cli@latest install`
285
285
  2. `silicaclaw start`
286
286
  3. Open `http://localhost:4310`
287
287
  4. Save profile
@@ -125,6 +125,21 @@ It also includes `scripts/send-to-owner-via-openclaw.mjs` so those summaries can
125
125
  `openclaw-skill-validate` checks the bundled skill metadata.
126
126
  `openclaw-skill-pack` writes a publishable tarball and `.sha256` to `dist/openclaw-skills/`.
127
127
 
128
+ To publish the bundled skill to ClawHub:
129
+
130
+ ```bash
131
+ npx clawhub login
132
+ npx clawhub sync --root openclaw-skills --dry-run
133
+ npx clawhub publish openclaw-skills/silicaclaw-broadcast \
134
+ --slug silicaclaw-broadcast \
135
+ --name "SilicaClaw Broadcast" \
136
+ --version 2026.3.19-beta.15 \
137
+ --tags latest \
138
+ --changelog "Initial public release for SilicaClaw broadcast learning and owner forwarding via OpenClaw."
139
+ ```
140
+
141
+ ClawHub publishes the skill folder itself, not `@silicaclaw/cli`.
142
+
128
143
  Interactive demo:
129
144
 
130
145
  ```bash
@@ -150,6 +150,21 @@ silicaclaw openclaw-skill-validate
150
150
  `openclaw-skill-validate` 会检查技能元数据是否完整。
151
151
  `openclaw-skill-pack` 会把技能和 `.sha256` 打包到 `dist/openclaw-skills/`,方便后续发布。
152
152
 
153
+ 如果要把这个技能发布到 ClawHub,可直接发布技能目录本身:
154
+
155
+ ```bash
156
+ npx clawhub login
157
+ npx clawhub sync --root openclaw-skills --dry-run
158
+ npx clawhub publish openclaw-skills/silicaclaw-broadcast \
159
+ --slug silicaclaw-broadcast \
160
+ --name "SilicaClaw Broadcast" \
161
+ --version 2026.3.19-beta.15 \
162
+ --tags latest \
163
+ --changelog "Initial public release for SilicaClaw broadcast learning and owner forwarding via OpenClaw."
164
+ ```
165
+
166
+ 注意:ClawHub 要求技能版本号是合法 semver,所以这里要用技能包自己的版本号,而不是 npm CLI 那套带 `-15` 的版本格式。
167
+
153
168
  ## 5. 交互式 Demo
154
169
 
155
170
  如果你想快速模拟一个 OpenClaw runtime:
@@ -0,0 +1,19 @@
1
+ {
2
+ "ports": {
3
+ "local_console": 4310,
4
+ "public_explorer": 4311,
5
+ "openclaw_gateway": 18789,
6
+ "network_default": 44123
7
+ },
8
+ "network": {
9
+ "default_mode": "global-preview",
10
+ "default_namespace": "silicaclaw.preview",
11
+ "global_preview": {
12
+ "relay_url": "https://relay.silicaclaw.com",
13
+ "room": "silicaclaw-global-preview"
14
+ }
15
+ },
16
+ "bridge": {
17
+ "api_base": "http://localhost:4310"
18
+ }
19
+ }
@@ -0,0 +1,6 @@
1
+ export declare function toBase64(input: Uint8Array): string;
2
+ export declare function fromBase64(input: string): Uint8Array;
3
+ export declare function hashPublicKey(publicKey: Uint8Array): string;
4
+ export declare function stableStringify(input: unknown): string;
5
+ export declare function signPayload(payload: unknown, privateKeyBase64: string): string;
6
+ export declare function verifyPayload(payload: unknown, signatureBase64: string, publicKeyBase64: string): boolean;
@@ -0,0 +1,50 @@
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.toBase64 = toBase64;
7
+ exports.fromBase64 = fromBase64;
8
+ exports.hashPublicKey = hashPublicKey;
9
+ exports.stableStringify = stableStringify;
10
+ exports.signPayload = signPayload;
11
+ exports.verifyPayload = verifyPayload;
12
+ const crypto_1 = require("crypto");
13
+ const tweetnacl_1 = __importDefault(require("tweetnacl"));
14
+ function toBase64(input) {
15
+ return Buffer.from(input).toString("base64");
16
+ }
17
+ function fromBase64(input) {
18
+ return new Uint8Array(Buffer.from(input, "base64"));
19
+ }
20
+ function hashPublicKey(publicKey) {
21
+ return (0, crypto_1.createHash)("sha256").update(publicKey).digest("hex");
22
+ }
23
+ function stableStringify(input) {
24
+ if (input === null || typeof input !== "object") {
25
+ return JSON.stringify(input);
26
+ }
27
+ if (Array.isArray(input)) {
28
+ return `[${input.map((item) => stableStringify(item)).join(",")}]`;
29
+ }
30
+ const entries = Object.entries(input)
31
+ .filter(([, value]) => value !== undefined)
32
+ .sort(([a], [b]) => a.localeCompare(b));
33
+ return `{${entries
34
+ .map(([key, value]) => `${JSON.stringify(key)}:${stableStringify(value)}`)
35
+ .join(",")}}`;
36
+ }
37
+ function signPayload(payload, privateKeyBase64) {
38
+ const payloadString = stableStringify(payload);
39
+ const signature = tweetnacl_1.default.sign.detached(Buffer.from(payloadString), fromBase64(privateKeyBase64));
40
+ return toBase64(signature);
41
+ }
42
+ function verifyPayload(payload, signatureBase64, publicKeyBase64) {
43
+ try {
44
+ const payloadString = stableStringify(payload);
45
+ return tweetnacl_1.default.sign.detached.verify(Buffer.from(payloadString), fromBase64(signatureBase64), fromBase64(publicKeyBase64));
46
+ }
47
+ catch {
48
+ return false;
49
+ }
50
+ }
@@ -0,0 +1,17 @@
1
+ import { DirectoryState, IndexRefRecord, PresenceRecord, PublicProfile, SignedProfileRecord } from "./types";
2
+ export declare const DEFAULT_PRESENCE_TTL_MS = 30000;
3
+ export declare function createEmptyDirectoryState(): DirectoryState;
4
+ export declare function ingestProfileRecord(state: DirectoryState, record: SignedProfileRecord): DirectoryState;
5
+ export declare function ingestPresenceRecord(state: DirectoryState, record: PresenceRecord): DirectoryState;
6
+ export declare function ingestIndexRecord(state: DirectoryState, record: IndexRefRecord): DirectoryState;
7
+ export declare function isAgentOnline(lastSeenAt: number | undefined, now?: number, ttlMs?: number): boolean;
8
+ export declare function cleanupExpiredPresence(state: DirectoryState, now?: number, ttlMs?: number): {
9
+ state: DirectoryState;
10
+ removed: number;
11
+ };
12
+ export declare function rebuildIndexForProfile(state: DirectoryState, profile: PublicProfile): DirectoryState;
13
+ export declare function dedupeIndex(state: DirectoryState): DirectoryState;
14
+ export declare function searchDirectory(state: DirectoryState, keyword: string, options?: {
15
+ now?: number;
16
+ presenceTTLms?: number;
17
+ }): PublicProfile[];
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_PRESENCE_TTL_MS = void 0;
4
+ exports.createEmptyDirectoryState = createEmptyDirectoryState;
5
+ exports.ingestProfileRecord = ingestProfileRecord;
6
+ exports.ingestPresenceRecord = ingestPresenceRecord;
7
+ exports.ingestIndexRecord = ingestIndexRecord;
8
+ exports.isAgentOnline = isAgentOnline;
9
+ exports.cleanupExpiredPresence = cleanupExpiredPresence;
10
+ exports.rebuildIndexForProfile = rebuildIndexForProfile;
11
+ exports.dedupeIndex = dedupeIndex;
12
+ exports.searchDirectory = searchDirectory;
13
+ const indexing_1 = require("./indexing");
14
+ exports.DEFAULT_PRESENCE_TTL_MS = 30_000;
15
+ function createEmptyDirectoryState() {
16
+ return {
17
+ profiles: {},
18
+ presence: {},
19
+ index: {},
20
+ };
21
+ }
22
+ function ingestProfileRecord(state, record) {
23
+ const next = {
24
+ profiles: { ...state.profiles },
25
+ presence: { ...state.presence },
26
+ index: { ...state.index },
27
+ };
28
+ next.profiles[record.profile.agent_id] = record.profile;
29
+ return rebuildIndexForProfile(next, record.profile);
30
+ }
31
+ function ingestPresenceRecord(state, record) {
32
+ return {
33
+ profiles: { ...state.profiles },
34
+ presence: {
35
+ ...state.presence,
36
+ [record.agent_id]: record.timestamp,
37
+ },
38
+ index: { ...state.index },
39
+ };
40
+ }
41
+ function ingestIndexRecord(state, record) {
42
+ const existing = new Set(state.index[record.key] ?? []);
43
+ if (existing.has(record.agent_id)) {
44
+ return state;
45
+ }
46
+ existing.add(record.agent_id);
47
+ return {
48
+ profiles: { ...state.profiles },
49
+ presence: { ...state.presence },
50
+ index: {
51
+ ...state.index,
52
+ [record.key]: Array.from(existing),
53
+ },
54
+ };
55
+ }
56
+ function isAgentOnline(lastSeenAt, now = Date.now(), ttlMs = exports.DEFAULT_PRESENCE_TTL_MS) {
57
+ if (!lastSeenAt) {
58
+ return false;
59
+ }
60
+ return now - lastSeenAt <= ttlMs;
61
+ }
62
+ function cleanupExpiredPresence(state, now = Date.now(), ttlMs = exports.DEFAULT_PRESENCE_TTL_MS) {
63
+ let removed = 0;
64
+ const presence = {};
65
+ for (const [agentId, timestamp] of Object.entries(state.presence)) {
66
+ if (isAgentOnline(timestamp, now, ttlMs)) {
67
+ presence[agentId] = timestamp;
68
+ }
69
+ else {
70
+ removed += 1;
71
+ }
72
+ }
73
+ if (removed === 0) {
74
+ return { state, removed: 0 };
75
+ }
76
+ return {
77
+ state: {
78
+ profiles: { ...state.profiles },
79
+ presence,
80
+ index: { ...state.index },
81
+ },
82
+ removed,
83
+ };
84
+ }
85
+ function rebuildIndexForProfile(state, profile) {
86
+ const keys = (0, indexing_1.buildIndexKeys)(profile);
87
+ const nextIndex = {};
88
+ for (const [key, ids] of Object.entries(state.index)) {
89
+ const filtered = ids.filter((id) => id !== profile.agent_id);
90
+ if (filtered.length > 0) {
91
+ nextIndex[key] = Array.from(new Set(filtered));
92
+ }
93
+ }
94
+ for (const key of keys) {
95
+ const existing = new Set(nextIndex[key] ?? []);
96
+ existing.add(profile.agent_id);
97
+ nextIndex[key] = Array.from(existing);
98
+ }
99
+ return {
100
+ profiles: { ...state.profiles },
101
+ presence: { ...state.presence },
102
+ index: nextIndex,
103
+ };
104
+ }
105
+ function dedupeIndex(state) {
106
+ const index = {};
107
+ for (const [key, ids] of Object.entries(state.index)) {
108
+ index[key] = Array.from(new Set(ids));
109
+ }
110
+ return {
111
+ profiles: { ...state.profiles },
112
+ presence: { ...state.presence },
113
+ index,
114
+ };
115
+ }
116
+ function searchDirectory(state, keyword, options) {
117
+ const now = options?.now ?? Date.now();
118
+ const presenceTTLms = options?.presenceTTLms ?? exports.DEFAULT_PRESENCE_TTL_MS;
119
+ const normalized = keyword.trim().toLowerCase();
120
+ const baseList = normalized.length === 0
121
+ ? Object.values(state.profiles)
122
+ : Array.from(new Set([
123
+ ...(state.index[`tag:${normalized}`] ?? []),
124
+ ...(state.index[`name:${normalized.replace(/[^a-z0-9]+/g, "")}`] ?? []),
125
+ ]))
126
+ .map((agentId) => state.profiles[agentId])
127
+ .filter((profile) => Boolean(profile));
128
+ return baseList
129
+ .slice()
130
+ .sort((a, b) => {
131
+ const aOnline = isAgentOnline(state.presence[a.agent_id], now, presenceTTLms) ? 1 : 0;
132
+ const bOnline = isAgentOnline(state.presence[b.agent_id], now, presenceTTLms) ? 1 : 0;
133
+ if (aOnline !== bOnline) {
134
+ return bOnline - aOnline;
135
+ }
136
+ if (a.updated_at !== b.updated_at) {
137
+ return b.updated_at - a.updated_at;
138
+ }
139
+ const byName = a.display_name.localeCompare(b.display_name);
140
+ if (byName !== 0) {
141
+ return byName;
142
+ }
143
+ return a.agent_id.localeCompare(b.agent_id);
144
+ });
145
+ }
@@ -0,0 +1,2 @@
1
+ import { AgentIdentity } from "./types";
2
+ export declare function createIdentity(now?: number): AgentIdentity;
@@ -0,0 +1,18 @@
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.createIdentity = createIdentity;
7
+ const tweetnacl_1 = __importDefault(require("tweetnacl"));
8
+ const crypto_1 = require("./crypto");
9
+ function createIdentity(now = Date.now()) {
10
+ const pair = tweetnacl_1.default.sign.keyPair();
11
+ const publicKey = (0, crypto_1.toBase64)(pair.publicKey);
12
+ return {
13
+ agent_id: (0, crypto_1.hashPublicKey)(pair.publicKey),
14
+ public_key: publicKey,
15
+ private_key: (0, crypto_1.toBase64)(pair.secretKey),
16
+ created_at: now,
17
+ };
18
+ }
@@ -0,0 +1,12 @@
1
+ export * from "./types";
2
+ export * from "./crypto";
3
+ export * from "./identity";
4
+ export * from "./profile";
5
+ export * from "./presence";
6
+ export * from "./socialMessage";
7
+ export * from "./indexing";
8
+ export * from "./directory";
9
+ export * from "./publicProfileSummary";
10
+ export * from "./socialConfig";
11
+ export * from "./socialResolver";
12
+ export * from "./socialTemplate";
@@ -0,0 +1,28 @@
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("./types"), exports);
18
+ __exportStar(require("./crypto"), exports);
19
+ __exportStar(require("./identity"), exports);
20
+ __exportStar(require("./profile"), exports);
21
+ __exportStar(require("./presence"), exports);
22
+ __exportStar(require("./socialMessage"), exports);
23
+ __exportStar(require("./indexing"), exports);
24
+ __exportStar(require("./directory"), exports);
25
+ __exportStar(require("./publicProfileSummary"), exports);
26
+ __exportStar(require("./socialConfig"), exports);
27
+ __exportStar(require("./socialResolver"), exports);
28
+ __exportStar(require("./socialTemplate"), exports);
@@ -0,0 +1,6 @@
1
+ import { IndexRefRecord, PublicProfile } from "./types";
2
+ export declare function normalizeTag(tag: string): string;
3
+ export declare function buildTagIndexKeys(tags: string[]): string[];
4
+ export declare function buildNamePrefixKeys(displayName: string): string[];
5
+ export declare function buildIndexKeys(profile: PublicProfile): string[];
6
+ export declare function buildIndexRecords(profile: PublicProfile): IndexRefRecord[];