@silicaclaw/cli 2026.3.19-8 → 2026.3.20-1

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 (278) hide show
  1. package/CHANGELOG.md +134 -0
  2. package/DEMO_GUIDE.md +1 -1
  3. package/INSTALL.md +47 -13
  4. package/README.md +61 -19
  5. package/VERSION +1 -1
  6. package/apps/local-console/dist/apps/local-console/src/server.d.ts +51 -12
  7. package/apps/local-console/dist/apps/local-console/src/server.js +619 -183
  8. package/apps/local-console/dist/config/silicaclaw-defaults.json +19 -0
  9. package/apps/local-console/dist/packages/core/src/socialConfig.js +9 -5
  10. package/apps/local-console/dist/packages/network/src/realPreview.js +6 -2
  11. package/apps/local-console/dist/packages/network/src/relayPreview.js +8 -2
  12. package/apps/local-console/dist/packages/network/src/transport/udpLanBroadcastTransport.js +2 -1
  13. package/apps/local-console/dist/packages/network/src/webrtcPreview.js +5 -1
  14. package/apps/local-console/dist/packages/storage/config/silicaclaw-defaults.json +19 -0
  15. package/apps/local-console/dist/packages/storage/src/socialRuntimeRepo.js +8 -4
  16. package/apps/local-console/public/app/app.js +21 -1
  17. package/apps/local-console/public/app/events.js +40 -2
  18. package/apps/local-console/public/app/network.js +32 -3
  19. package/apps/local-console/public/app/overview.js +15 -1
  20. package/apps/local-console/public/app/shell.js +18 -34
  21. package/apps/local-console/public/app/social.js +207 -28
  22. package/apps/local-console/public/app/styles.css +182 -14
  23. package/apps/local-console/public/app/template.js +76 -31
  24. package/apps/local-console/public/app/translations.js +147 -51
  25. package/apps/local-console/src/server.ts +652 -189
  26. package/apps/public-explorer/dist/apps/public-explorer/src/server.d.ts +1 -0
  27. package/apps/public-explorer/dist/apps/public-explorer/src/server.js +41 -0
  28. package/apps/public-explorer/dist/config/silicaclaw-defaults.json +19 -0
  29. package/apps/public-explorer/public/app/app.js +22 -2
  30. package/apps/public-explorer/public/app/template.js +4 -4
  31. package/apps/public-explorer/public/app/translations.js +15 -15
  32. package/apps/public-explorer/src/server.ts +11 -1
  33. package/config/silicaclaw-defaults.json +19 -0
  34. package/dist/apps/local-console/src/server.d.ts +1 -0
  35. package/dist/apps/local-console/src/server.js +555 -0
  36. package/docs/NEW_USER_INSTALL.md +14 -10
  37. package/docs/NEW_USER_OPERATIONS.md +4 -4
  38. package/docs/OPENCLAW_BRIDGE.md +15 -0
  39. package/docs/OPENCLAW_BRIDGE_ZH.md +15 -0
  40. package/docs/RELEASE_CHECKLIST.md +95 -0
  41. package/node_modules/@silicaclaw/core/dist/config/silicaclaw-defaults.json +19 -0
  42. package/node_modules/@silicaclaw/core/dist/packages/core/src/crypto.d.ts +6 -0
  43. package/node_modules/@silicaclaw/core/dist/packages/core/src/crypto.js +50 -0
  44. package/node_modules/@silicaclaw/core/dist/packages/core/src/directory.d.ts +17 -0
  45. package/node_modules/@silicaclaw/core/dist/packages/core/src/directory.js +145 -0
  46. package/node_modules/@silicaclaw/core/dist/packages/core/src/identity.d.ts +2 -0
  47. package/node_modules/@silicaclaw/core/dist/packages/core/src/identity.js +18 -0
  48. package/node_modules/@silicaclaw/core/dist/packages/core/src/index.d.ts +12 -0
  49. package/node_modules/@silicaclaw/core/dist/packages/core/src/index.js +28 -0
  50. package/node_modules/@silicaclaw/core/dist/packages/core/src/indexing.d.ts +6 -0
  51. package/node_modules/@silicaclaw/core/dist/packages/core/src/indexing.js +43 -0
  52. package/node_modules/@silicaclaw/core/dist/packages/core/src/presence.d.ts +4 -0
  53. package/node_modules/@silicaclaw/core/dist/packages/core/src/presence.js +23 -0
  54. package/node_modules/@silicaclaw/core/dist/packages/core/src/profile.d.ts +4 -0
  55. package/node_modules/@silicaclaw/core/dist/packages/core/src/profile.js +39 -0
  56. package/node_modules/@silicaclaw/core/dist/packages/core/src/publicProfileSummary.d.ts +70 -0
  57. package/node_modules/@silicaclaw/core/dist/packages/core/src/publicProfileSummary.js +103 -0
  58. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialConfig.d.ts +100 -0
  59. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialConfig.js +300 -0
  60. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialMessage.d.ts +19 -0
  61. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialMessage.js +69 -0
  62. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialResolver.d.ts +46 -0
  63. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialResolver.js +237 -0
  64. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialTemplate.d.ts +2 -0
  65. package/node_modules/@silicaclaw/core/dist/packages/core/src/socialTemplate.js +90 -0
  66. package/node_modules/@silicaclaw/core/dist/packages/core/src/types.d.ts +59 -0
  67. package/node_modules/@silicaclaw/core/dist/packages/core/src/types.js +2 -0
  68. package/node_modules/@silicaclaw/core/src/socialConfig.ts +7 -5
  69. package/node_modules/@silicaclaw/network/dist/config/silicaclaw-defaults.json +19 -0
  70. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/messageEnvelope.d.ts +28 -0
  71. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/messageEnvelope.js +36 -0
  72. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/peerDiscovery.d.ts +43 -0
  73. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/peerDiscovery.js +2 -0
  74. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/topicCodec.d.ts +4 -0
  75. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/topicCodec.js +2 -0
  76. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/transport.d.ts +36 -0
  77. package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/transport.js +2 -0
  78. package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.d.ts +5 -0
  79. package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.js +24 -0
  80. package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonTopicCodec.d.ts +5 -0
  81. package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonTopicCodec.js +12 -0
  82. package/node_modules/@silicaclaw/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.d.ts +28 -0
  83. package/node_modules/@silicaclaw/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.js +144 -0
  84. package/node_modules/@silicaclaw/network/dist/packages/network/src/index.d.ts +14 -0
  85. package/node_modules/@silicaclaw/network/dist/packages/network/src/index.js +30 -0
  86. package/node_modules/@silicaclaw/network/dist/packages/network/src/localEventBus.d.ts +9 -0
  87. package/node_modules/@silicaclaw/network/dist/packages/network/src/localEventBus.js +47 -0
  88. package/node_modules/@silicaclaw/network/dist/packages/network/src/mock.d.ts +8 -0
  89. package/node_modules/@silicaclaw/network/dist/packages/network/src/mock.js +24 -0
  90. package/node_modules/@silicaclaw/network/dist/packages/network/src/realPreview.d.ts +105 -0
  91. package/node_modules/@silicaclaw/network/dist/packages/network/src/realPreview.js +331 -0
  92. package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.d.ts +166 -0
  93. package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.js +448 -0
  94. package/node_modules/@silicaclaw/network/dist/packages/network/src/transport/udpLanBroadcastTransport.d.ts +23 -0
  95. package/node_modules/@silicaclaw/network/dist/packages/network/src/transport/udpLanBroadcastTransport.js +154 -0
  96. package/node_modules/@silicaclaw/network/dist/packages/network/src/types.d.ts +6 -0
  97. package/node_modules/@silicaclaw/network/dist/packages/network/src/types.js +2 -0
  98. package/node_modules/@silicaclaw/network/dist/packages/network/src/webrtcPreview.d.ts +163 -0
  99. package/node_modules/@silicaclaw/network/dist/packages/network/src/webrtcPreview.js +848 -0
  100. package/node_modules/@silicaclaw/network/src/realPreview.ts +3 -2
  101. package/node_modules/@silicaclaw/network/src/relayPreview.ts +5 -2
  102. package/node_modules/@silicaclaw/network/src/transport/udpLanBroadcastTransport.ts +2 -1
  103. package/node_modules/@silicaclaw/network/src/webrtcPreview.ts +2 -1
  104. package/node_modules/@silicaclaw/storage/config/silicaclaw-defaults.json +19 -0
  105. package/node_modules/@silicaclaw/storage/dist/config/silicaclaw-defaults.json +19 -0
  106. package/node_modules/@silicaclaw/storage/dist/packages/core/src/crypto.d.ts +6 -0
  107. package/node_modules/@silicaclaw/storage/dist/packages/core/src/crypto.js +50 -0
  108. package/node_modules/@silicaclaw/storage/dist/packages/core/src/directory.d.ts +17 -0
  109. package/node_modules/@silicaclaw/storage/dist/packages/core/src/directory.js +145 -0
  110. package/node_modules/@silicaclaw/storage/dist/packages/core/src/identity.d.ts +2 -0
  111. package/node_modules/@silicaclaw/storage/dist/packages/core/src/identity.js +18 -0
  112. package/node_modules/@silicaclaw/storage/dist/packages/core/src/index.d.ts +12 -0
  113. package/node_modules/@silicaclaw/storage/dist/packages/core/src/index.js +28 -0
  114. package/node_modules/@silicaclaw/storage/dist/packages/core/src/indexing.d.ts +6 -0
  115. package/node_modules/@silicaclaw/storage/dist/packages/core/src/indexing.js +43 -0
  116. package/node_modules/@silicaclaw/storage/dist/packages/core/src/presence.d.ts +4 -0
  117. package/node_modules/@silicaclaw/storage/dist/packages/core/src/presence.js +23 -0
  118. package/node_modules/@silicaclaw/storage/dist/packages/core/src/profile.d.ts +4 -0
  119. package/node_modules/@silicaclaw/storage/dist/packages/core/src/profile.js +39 -0
  120. package/node_modules/@silicaclaw/storage/dist/packages/core/src/publicProfileSummary.d.ts +70 -0
  121. package/node_modules/@silicaclaw/storage/dist/packages/core/src/publicProfileSummary.js +103 -0
  122. package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialConfig.d.ts +100 -0
  123. package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialConfig.js +300 -0
  124. package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialMessage.d.ts +19 -0
  125. package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialMessage.js +69 -0
  126. package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialResolver.d.ts +46 -0
  127. package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialResolver.js +237 -0
  128. package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialTemplate.d.ts +2 -0
  129. package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialTemplate.js +90 -0
  130. package/node_modules/@silicaclaw/storage/dist/packages/core/src/types.d.ts +59 -0
  131. package/node_modules/@silicaclaw/storage/dist/packages/core/src/types.js +2 -0
  132. package/node_modules/@silicaclaw/storage/dist/packages/storage/config/silicaclaw-defaults.json +19 -0
  133. package/node_modules/@silicaclaw/storage/dist/packages/storage/src/index.d.ts +3 -0
  134. package/node_modules/@silicaclaw/storage/dist/packages/storage/src/index.js +19 -0
  135. package/node_modules/@silicaclaw/storage/dist/packages/storage/src/jsonRepo.d.ts +7 -0
  136. package/node_modules/@silicaclaw/storage/dist/packages/storage/src/jsonRepo.js +29 -0
  137. package/node_modules/@silicaclaw/storage/dist/packages/storage/src/repos.d.ts +61 -0
  138. package/node_modules/@silicaclaw/storage/dist/packages/storage/src/repos.js +67 -0
  139. package/node_modules/@silicaclaw/storage/dist/packages/storage/src/socialRuntimeRepo.d.ts +5 -0
  140. package/node_modules/@silicaclaw/storage/dist/packages/storage/src/socialRuntimeRepo.js +57 -0
  141. package/node_modules/@silicaclaw/storage/dist/socialRuntimeRepo.js +8 -4
  142. package/node_modules/@silicaclaw/storage/src/socialRuntimeRepo.ts +5 -4
  143. package/node_modules/@silicaclaw/storage/tsconfig.json +1 -6
  144. package/openclaw-skills/silicaclaw-bridge-setup/SKILL.md +147 -0
  145. package/openclaw-skills/silicaclaw-bridge-setup/VERSION +1 -0
  146. package/openclaw-skills/silicaclaw-bridge-setup/agents/openai.yaml +6 -0
  147. package/openclaw-skills/silicaclaw-bridge-setup/manifest.json +27 -0
  148. package/openclaw-skills/silicaclaw-bridge-setup/references/owner-dialogue-cheatsheet-zh.md +58 -0
  149. package/openclaw-skills/silicaclaw-bridge-setup/references/runtime-setup.md +43 -0
  150. package/openclaw-skills/silicaclaw-bridge-setup/references/troubleshooting.md +24 -0
  151. package/openclaw-skills/silicaclaw-broadcast/SKILL.md +132 -0
  152. package/openclaw-skills/silicaclaw-broadcast/VERSION +1 -1
  153. package/openclaw-skills/silicaclaw-broadcast/agents/openai.yaml +2 -2
  154. package/openclaw-skills/silicaclaw-broadcast/manifest.json +3 -2
  155. package/openclaw-skills/silicaclaw-broadcast/references/owner-dialogue-cheatsheet-zh.md +81 -0
  156. package/openclaw-skills/silicaclaw-owner-push/SKILL.md +217 -0
  157. package/openclaw-skills/silicaclaw-owner-push/VERSION +1 -0
  158. package/openclaw-skills/silicaclaw-owner-push/agents/openai.yaml +6 -0
  159. package/openclaw-skills/silicaclaw-owner-push/manifest.json +30 -0
  160. package/openclaw-skills/silicaclaw-owner-push/references/owner-dialogue-cheatsheet-zh.md +87 -0
  161. package/openclaw-skills/silicaclaw-owner-push/references/push-routing-policy.md +43 -0
  162. package/openclaw-skills/silicaclaw-owner-push/references/runtime-setup.md +41 -0
  163. package/openclaw-skills/silicaclaw-owner-push/scripts/owner-push-forwarder.mjs +214 -0
  164. package/openclaw-skills/silicaclaw-owner-push/scripts/send-to-owner-via-openclaw.mjs +69 -0
  165. package/package.json +7 -1
  166. package/packages/core/dist/config/silicaclaw-defaults.json +19 -0
  167. package/packages/core/dist/packages/core/src/crypto.d.ts +6 -0
  168. package/packages/core/dist/packages/core/src/crypto.js +50 -0
  169. package/packages/core/dist/packages/core/src/directory.d.ts +17 -0
  170. package/packages/core/dist/packages/core/src/directory.js +145 -0
  171. package/packages/core/dist/packages/core/src/identity.d.ts +2 -0
  172. package/packages/core/dist/packages/core/src/identity.js +18 -0
  173. package/packages/core/dist/packages/core/src/index.d.ts +12 -0
  174. package/packages/core/dist/packages/core/src/index.js +28 -0
  175. package/packages/core/dist/packages/core/src/indexing.d.ts +6 -0
  176. package/packages/core/dist/packages/core/src/indexing.js +43 -0
  177. package/packages/core/dist/packages/core/src/presence.d.ts +4 -0
  178. package/packages/core/dist/packages/core/src/presence.js +23 -0
  179. package/packages/core/dist/packages/core/src/profile.d.ts +4 -0
  180. package/packages/core/dist/packages/core/src/profile.js +39 -0
  181. package/packages/core/dist/packages/core/src/publicProfileSummary.d.ts +70 -0
  182. package/packages/core/dist/packages/core/src/publicProfileSummary.js +103 -0
  183. package/packages/core/dist/packages/core/src/socialConfig.d.ts +100 -0
  184. package/packages/core/dist/packages/core/src/socialConfig.js +300 -0
  185. package/packages/core/dist/packages/core/src/socialMessage.d.ts +19 -0
  186. package/packages/core/dist/packages/core/src/socialMessage.js +69 -0
  187. package/packages/core/dist/packages/core/src/socialResolver.d.ts +46 -0
  188. package/packages/core/dist/packages/core/src/socialResolver.js +237 -0
  189. package/packages/core/dist/packages/core/src/socialTemplate.d.ts +2 -0
  190. package/packages/core/dist/packages/core/src/socialTemplate.js +90 -0
  191. package/packages/core/dist/packages/core/src/types.d.ts +59 -0
  192. package/packages/core/dist/packages/core/src/types.js +2 -0
  193. package/packages/core/src/socialConfig.ts +7 -5
  194. package/packages/network/dist/config/silicaclaw-defaults.json +19 -0
  195. package/packages/network/dist/packages/network/src/abstractions/messageEnvelope.d.ts +28 -0
  196. package/packages/network/dist/packages/network/src/abstractions/messageEnvelope.js +36 -0
  197. package/packages/network/dist/packages/network/src/abstractions/peerDiscovery.d.ts +43 -0
  198. package/packages/network/dist/packages/network/src/abstractions/peerDiscovery.js +2 -0
  199. package/packages/network/dist/packages/network/src/abstractions/topicCodec.d.ts +4 -0
  200. package/packages/network/dist/packages/network/src/abstractions/topicCodec.js +2 -0
  201. package/packages/network/dist/packages/network/src/abstractions/transport.d.ts +36 -0
  202. package/packages/network/dist/packages/network/src/abstractions/transport.js +2 -0
  203. package/packages/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.d.ts +5 -0
  204. package/packages/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.js +24 -0
  205. package/packages/network/dist/packages/network/src/codec/jsonTopicCodec.d.ts +5 -0
  206. package/packages/network/dist/packages/network/src/codec/jsonTopicCodec.js +12 -0
  207. package/packages/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.d.ts +28 -0
  208. package/packages/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.js +144 -0
  209. package/packages/network/dist/packages/network/src/index.d.ts +14 -0
  210. package/packages/network/dist/packages/network/src/index.js +30 -0
  211. package/packages/network/dist/packages/network/src/localEventBus.d.ts +9 -0
  212. package/packages/network/dist/packages/network/src/localEventBus.js +47 -0
  213. package/packages/network/dist/packages/network/src/mock.d.ts +8 -0
  214. package/packages/network/dist/packages/network/src/mock.js +24 -0
  215. package/packages/network/dist/packages/network/src/realPreview.d.ts +105 -0
  216. package/packages/network/dist/packages/network/src/realPreview.js +331 -0
  217. package/packages/network/dist/packages/network/src/relayPreview.d.ts +166 -0
  218. package/packages/network/dist/packages/network/src/relayPreview.js +448 -0
  219. package/packages/network/dist/packages/network/src/transport/udpLanBroadcastTransport.d.ts +23 -0
  220. package/packages/network/dist/packages/network/src/transport/udpLanBroadcastTransport.js +154 -0
  221. package/packages/network/dist/packages/network/src/types.d.ts +6 -0
  222. package/packages/network/dist/packages/network/src/types.js +2 -0
  223. package/packages/network/dist/packages/network/src/webrtcPreview.d.ts +163 -0
  224. package/packages/network/dist/packages/network/src/webrtcPreview.js +848 -0
  225. package/packages/network/src/realPreview.ts +3 -2
  226. package/packages/network/src/relayPreview.ts +5 -2
  227. package/packages/network/src/transport/udpLanBroadcastTransport.ts +2 -1
  228. package/packages/network/src/webrtcPreview.ts +2 -1
  229. package/packages/storage/config/silicaclaw-defaults.json +19 -0
  230. package/packages/storage/dist/config/silicaclaw-defaults.json +19 -0
  231. package/packages/storage/dist/packages/core/src/crypto.d.ts +6 -0
  232. package/packages/storage/dist/packages/core/src/crypto.js +50 -0
  233. package/packages/storage/dist/packages/core/src/directory.d.ts +17 -0
  234. package/packages/storage/dist/packages/core/src/directory.js +145 -0
  235. package/packages/storage/dist/packages/core/src/identity.d.ts +2 -0
  236. package/packages/storage/dist/packages/core/src/identity.js +18 -0
  237. package/packages/storage/dist/packages/core/src/index.d.ts +12 -0
  238. package/packages/storage/dist/packages/core/src/index.js +28 -0
  239. package/packages/storage/dist/packages/core/src/indexing.d.ts +6 -0
  240. package/packages/storage/dist/packages/core/src/indexing.js +43 -0
  241. package/packages/storage/dist/packages/core/src/presence.d.ts +4 -0
  242. package/packages/storage/dist/packages/core/src/presence.js +23 -0
  243. package/packages/storage/dist/packages/core/src/profile.d.ts +4 -0
  244. package/packages/storage/dist/packages/core/src/profile.js +39 -0
  245. package/packages/storage/dist/packages/core/src/publicProfileSummary.d.ts +70 -0
  246. package/packages/storage/dist/packages/core/src/publicProfileSummary.js +103 -0
  247. package/packages/storage/dist/packages/core/src/socialConfig.d.ts +100 -0
  248. package/packages/storage/dist/packages/core/src/socialConfig.js +300 -0
  249. package/packages/storage/dist/packages/core/src/socialMessage.d.ts +19 -0
  250. package/packages/storage/dist/packages/core/src/socialMessage.js +69 -0
  251. package/packages/storage/dist/packages/core/src/socialResolver.d.ts +46 -0
  252. package/packages/storage/dist/packages/core/src/socialResolver.js +237 -0
  253. package/packages/storage/dist/packages/core/src/socialTemplate.d.ts +2 -0
  254. package/packages/storage/dist/packages/core/src/socialTemplate.js +90 -0
  255. package/packages/storage/dist/packages/core/src/types.d.ts +59 -0
  256. package/packages/storage/dist/packages/core/src/types.js +2 -0
  257. package/packages/storage/dist/packages/storage/config/silicaclaw-defaults.json +19 -0
  258. package/packages/storage/dist/packages/storage/src/index.d.ts +3 -0
  259. package/packages/storage/dist/packages/storage/src/index.js +19 -0
  260. package/packages/storage/dist/packages/storage/src/jsonRepo.d.ts +7 -0
  261. package/packages/storage/dist/packages/storage/src/jsonRepo.js +29 -0
  262. package/packages/storage/dist/packages/storage/src/repos.d.ts +61 -0
  263. package/packages/storage/dist/packages/storage/src/repos.js +67 -0
  264. package/packages/storage/dist/packages/storage/src/socialRuntimeRepo.d.ts +5 -0
  265. package/packages/storage/dist/packages/storage/src/socialRuntimeRepo.js +57 -0
  266. package/packages/storage/dist/socialRuntimeRepo.js +8 -4
  267. package/packages/storage/src/socialRuntimeRepo.ts +5 -4
  268. package/packages/storage/tsconfig.json +1 -6
  269. package/scripts/functional-check.mjs +35 -6
  270. package/scripts/install-openclaw-skill.mjs +9 -2
  271. package/scripts/openclaw-bridge-adapter.mjs +3 -1
  272. package/scripts/openclaw-bridge-client.mjs +3 -1
  273. package/scripts/openclaw-runtime-demo.mjs +3 -1
  274. package/scripts/quickstart.sh +14 -10
  275. package/scripts/release-pack.mjs +147 -0
  276. package/scripts/silicaclaw-cli.mjs +109 -47
  277. package/scripts/silicaclaw-gateway.mjs +329 -106
  278. package/scripts/validate-openclaw-skill.mjs +79 -21
@@ -1,14 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { spawn, spawnSync } from "node:child_process";
4
- import { existsSync, mkdirSync, openSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
+ import { cpSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
5
5
  import { homedir } from "node:os";
6
6
  import { dirname, join, resolve } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
+ import defaults from "../config/silicaclaw-defaults.json" with { type: "json" };
8
9
 
9
10
  const __filename = fileURLToPath(import.meta.url);
10
11
  const __dirname = dirname(__filename);
11
12
  const ROOT_DIR = resolve(__dirname, "..");
13
+ const LOCAL_CONSOLE_PORT = defaults.ports.local_console;
14
+ const DEFAULT_NETWORK_MODE = defaults.network.default_mode;
15
+ const DEFAULT_SIGNALING_URL = defaults.network.global_preview.relay_url;
16
+ const DEFAULT_ROOM = defaults.network.global_preview.room;
17
+ const LOCAL_CONSOLE_BASE_URL = defaults.bridge.api_base;
12
18
 
13
19
  const argv = process.argv.slice(2);
14
20
  const cmd = String(argv[0] || "help").toLowerCase();
@@ -48,7 +54,7 @@ function headline() {
48
54
  version = "unknown";
49
55
  }
50
56
  }
51
- console.log(`${paint("SilicaClaw", COLOR.bold, COLOR.orange)} ${paint(displayVersion(version), COLOR.dim)}`);
57
+ console.log(`${paint("🦀 SilicaClaw", COLOR.bold, COLOR.orange)} ${paint(displayVersion(version), COLOR.dim)}`);
52
58
  console.log(paint("Public identity and discovery for OpenClaw agents.", COLOR.dim));
53
59
  }
54
60
 
@@ -114,9 +120,17 @@ function detectAppDir() {
114
120
  return ROOT_DIR;
115
121
  }
116
122
 
123
+ function detectWorkspaceDir() {
124
+ const envDir = process.env.SILICACLAW_WORKSPACE_DIR;
125
+ if (envDir) return resolve(envDir);
126
+ return resolve(process.cwd());
127
+ }
128
+
117
129
  const APP_DIR = detectAppDir();
130
+ const WORKSPACE_DIR = detectWorkspaceDir();
118
131
  const LOCAL_CONSOLE_DIR = join(APP_DIR, "apps", "local-console");
119
- const STATE_DIR = join(APP_DIR, ".silicaclaw", "gateway");
132
+ const STATE_DIR = join(homedir(), ".silicaclaw", "gateway");
133
+ const MANAGED_RUNTIME_DIR = join(homedir(), ".silicaclaw", "runtime", "silicaclaw");
120
134
  const CONSOLE_PID_FILE = join(STATE_DIR, "local-console.pid");
121
135
  const CONSOLE_LOG_FILE = join(STATE_DIR, "local-console.log");
122
136
  const SIGNALING_PID_FILE = join(STATE_DIR, "signaling.pid");
@@ -134,6 +148,10 @@ function ensureLaunchAgentsDir() {
134
148
  mkdirSync(LAUNCH_AGENTS_DIR, { recursive: true });
135
149
  }
136
150
 
151
+ function ensureManagedRuntimeDir() {
152
+ mkdirSync(MANAGED_RUNTIME_DIR, { recursive: true });
153
+ }
154
+
137
155
  function readPid(file) {
138
156
  if (!existsSync(file)) return null;
139
157
  const text = String(readFileSync(file, "utf8")).trim();
@@ -155,6 +173,51 @@ function removeFileIfExists(path) {
155
173
  if (existsSync(path)) rmSync(path, { force: true });
156
174
  }
157
175
 
176
+ function syncManagedRuntime() {
177
+ if (resolve(APP_DIR) === resolve(MANAGED_RUNTIME_DIR)) return MANAGED_RUNTIME_DIR;
178
+
179
+ ensureManagedRuntimeDir();
180
+ const entries = [
181
+ "config",
182
+ "scripts",
183
+ "apps/local-console/dist",
184
+ "apps/local-console/package.json",
185
+ "apps/local-console/public",
186
+ "apps/public-explorer/dist",
187
+ "apps/public-explorer/package.json",
188
+ "apps/public-explorer/public",
189
+ "social.md",
190
+ ".openclaw",
191
+ "package.json",
192
+ "package-lock.json",
193
+ "VERSION",
194
+ "node_modules",
195
+ ];
196
+
197
+ for (const rel of entries) {
198
+ const src = resolve(APP_DIR, rel);
199
+ if (!existsSync(src)) continue;
200
+ const dst = resolve(MANAGED_RUNTIME_DIR, rel);
201
+ rmSync(dst, { recursive: true, force: true });
202
+ cpSync(src, dst, {
203
+ recursive: true,
204
+ force: true,
205
+ dereference: rel === "node_modules",
206
+ });
207
+ }
208
+
209
+ const manifest = {
210
+ source_app_dir: APP_DIR,
211
+ synced_at: Date.now(),
212
+ version: readJson(resolve(APP_DIR, "package.json"))?.version || null,
213
+ dist_server_mtime: existsSync(resolve(APP_DIR, "apps", "local-console", "dist", "apps", "local-console", "src", "server.js"))
214
+ ? statSync(resolve(APP_DIR, "apps", "local-console", "dist", "apps", "local-console", "src", "server.js")).mtimeMs
215
+ : null,
216
+ };
217
+ writeFileSync(resolve(MANAGED_RUNTIME_DIR, ".silicaclaw-runtime.json"), JSON.stringify(manifest, null, 2));
218
+ return MANAGED_RUNTIME_DIR;
219
+ }
220
+
158
221
  async function stopPid(pid, name) {
159
222
  if (!pid || !isRunning(pid)) return;
160
223
  try {
@@ -243,25 +306,34 @@ function runLaunchctl(args) {
243
306
  });
244
307
  }
245
308
 
246
- function resolveCommandPath(command) {
247
- const result = spawnSync("which", [command], {
248
- encoding: "utf8",
249
- stdio: ["ignore", "pipe", "ignore"],
250
- });
251
- if ((result.status ?? 1) === 0) {
252
- const value = String(result.stdout || "").trim();
253
- if (value) return value;
254
- }
255
- return command;
309
+ function launchServiceTarget(label) {
310
+ return `${launchdDomain()}/${label}`;
311
+ }
312
+
313
+ function isLaunchctlNotLoadedResult(result) {
314
+ const text = `${result?.stdout || ""}\n${result?.stderr || ""}`.toLowerCase();
315
+ return (
316
+ text.includes("could not find service") ||
317
+ text.includes("service not found") ||
318
+ text.includes("bad request") ||
319
+ text.includes("not loaded")
320
+ );
321
+ }
322
+
323
+ function localConsoleProgramArguments(appDir = APP_DIR) {
324
+ return [
325
+ process.execPath,
326
+ resolve(appDir, "apps", "local-console", "dist", "apps", "local-console", "src", "server.js"),
327
+ ];
256
328
  }
257
329
 
258
330
  function isLaunchAgentLoaded(label) {
259
- const result = runLaunchctl(["print", `${launchdDomain()}/${label}`]);
331
+ const result = runLaunchctl(["print", launchServiceTarget(label)]);
260
332
  return (result.status ?? 1) === 0;
261
333
  }
262
334
 
263
335
  function readLaunchAgentRuntime(label) {
264
- const result = runLaunchctl(["print", `${launchdDomain()}/${label}`]);
336
+ const result = runLaunchctl(["print", launchServiceTarget(label)]);
265
337
  if ((result.status ?? 1) !== 0) return { loaded: false, pid: null };
266
338
  const text = `${result.stdout || ""}\n${result.stderr || ""}`;
267
339
  const pidMatch = text.match(/pid = (\d+)/);
@@ -271,7 +343,47 @@ function readLaunchAgentRuntime(label) {
271
343
  };
272
344
  }
273
345
 
274
- function installLaunchAgent({ label, programArguments, workingDirectory, logFile, environment }) {
346
+ function writeLaunchAgentPlistIfChanged(plistPath, plist) {
347
+ const current = existsSync(plistPath) ? String(readFileSync(plistPath, "utf8")) : null;
348
+ if (current === plist) return false;
349
+ writeFileSync(plistPath, plist, "utf8");
350
+ return true;
351
+ }
352
+
353
+ function bootstrapLaunchAgent(label, plistPath) {
354
+ const result = runLaunchctl(["bootstrap", launchdDomain(), plistPath]);
355
+ if ((result.status ?? 1) !== 0) {
356
+ const detail = String(result.stderr || result.stdout || "launchctl bootstrap failed").trim();
357
+ throw new Error(detail);
358
+ }
359
+ }
360
+
361
+ function startLaunchAgent(label, plistPath) {
362
+ const result = runLaunchctl(["start", launchServiceTarget(label)]);
363
+ if ((result.status ?? 1) === 0) return;
364
+ if (!isLaunchctlNotLoadedResult(result)) {
365
+ const detail = String(result.stderr || result.stdout || "launchctl start failed").trim();
366
+ throw new Error(detail);
367
+ }
368
+ bootstrapLaunchAgent(label, plistPath);
369
+ }
370
+
371
+ function restartLaunchAgent(label, plistPath) {
372
+ const result = runLaunchctl(["kickstart", "-k", launchServiceTarget(label)]);
373
+ if ((result.status ?? 1) === 0) return;
374
+ if (!isLaunchctlNotLoadedResult(result)) {
375
+ const detail = String(result.stderr || result.stdout || "launchctl kickstart failed").trim();
376
+ throw new Error(detail);
377
+ }
378
+ bootstrapLaunchAgent(label, plistPath);
379
+ const retry = runLaunchctl(["kickstart", "-k", launchServiceTarget(label)]);
380
+ if ((retry.status ?? 1) !== 0) {
381
+ const detail = String(retry.stderr || retry.stdout || "launchctl kickstart failed").trim();
382
+ throw new Error(detail);
383
+ }
384
+ }
385
+
386
+ function ensureLaunchAgent({ label, programArguments, workingDirectory, logFile, environment }) {
275
387
  ensureLaunchAgentsDir();
276
388
  ensureStateDir();
277
389
  const plistPath = launchAgentPlistPath(label);
@@ -283,17 +395,23 @@ function installLaunchAgent({ label, programArguments, workingDirectory, logFile
283
395
  stderrPath: logFile,
284
396
  environment,
285
397
  });
286
- writeFileSync(plistPath, plist, "utf8");
287
-
288
- if (isLaunchAgentLoaded(label)) {
289
- runLaunchctl(["bootout", launchdDomain(), plistPath]);
398
+ const changed = writeLaunchAgentPlistIfChanged(plistPath, plist);
399
+ const loaded = isLaunchAgentLoaded(label);
400
+
401
+ if (changed && loaded) {
402
+ const bootout = runLaunchctl(["bootout", launchdDomain(), plistPath]);
403
+ if ((bootout.status ?? 1) !== 0 && !isLaunchctlNotLoadedResult(bootout)) {
404
+ const detail = String(bootout.stderr || bootout.stdout || "launchctl bootout failed").trim();
405
+ throw new Error(detail);
406
+ }
407
+ bootstrapLaunchAgent(label, plistPath);
408
+ return { changed: true, loaded: true, plistPath };
290
409
  }
291
410
 
292
- const result = runLaunchctl(["bootstrap", launchdDomain(), plistPath]);
293
- if ((result.status ?? 1) !== 0) {
294
- const detail = String(result.stderr || result.stdout || "launchctl bootstrap failed").trim();
295
- throw new Error(detail);
411
+ if (!loaded) {
412
+ bootstrapLaunchAgent(label, plistPath);
296
413
  }
414
+ return { changed, loaded, plistPath };
297
415
  }
298
416
 
299
417
  function stopLaunchAgent(label) {
@@ -357,10 +475,11 @@ function launchdStatusPayload() {
357
475
  const state = readState();
358
476
  const localRuntime = readLaunchAgentRuntime(LOCAL_CONSOLE_LABEL);
359
477
  const signalingRuntime = readLaunchAgentRuntime(SIGNALING_LABEL);
360
- const localListener = listeningProcessOnPort(4310);
478
+ const localListener = listeningProcessOnPort(LOCAL_CONSOLE_PORT);
361
479
  const signalingListener = listeningProcessOnPort(4510);
362
480
  return {
363
481
  app_dir: APP_DIR,
482
+ workspace_dir: WORKSPACE_DIR,
364
483
  mode: state?.mode || "unknown",
365
484
  adapter: state?.adapter || "unknown",
366
485
  service_manager: "launchd",
@@ -391,10 +510,12 @@ function buildStatusPayload() {
391
510
  const localPid = readPid(CONSOLE_PID_FILE);
392
511
  const sigPid = readPid(SIGNALING_PID_FILE);
393
512
  const state = readState();
394
- const localListener = listeningProcessOnPort(4310);
513
+ const localListener = listeningProcessOnPort(LOCAL_CONSOLE_PORT);
395
514
  const signalingListener = listeningProcessOnPort(4510);
396
515
  return {
397
516
  app_dir: APP_DIR,
517
+ managed_app_dir: state?.managed_app_dir || null,
518
+ workspace_dir: state?.workspace_dir || WORKSPACE_DIR,
398
519
  mode: state?.mode || "unknown",
399
520
  adapter: state?.adapter || "unknown",
400
521
  local_console: {
@@ -428,10 +549,10 @@ function showStatusHuman() {
428
549
  : `${paint("stopped", COLOR.dim)} · ${payload.mode}`
429
550
  );
430
551
  if (payload.mode === "global-preview") {
431
- kv("Relay", payload.signaling.url || "https://relay.silicaclaw.com");
432
- kv("Room", payload.signaling.room || "silicaclaw-global-preview");
552
+ kv("Relay", payload.signaling.url || DEFAULT_SIGNALING_URL);
553
+ kv("Room", payload.signaling.room || DEFAULT_ROOM);
433
554
  }
434
- if (payload.local_console.running) kv("Open", "http://localhost:4310");
555
+ if (payload.local_console.running) kv("Open", LOCAL_CONSOLE_BASE_URL);
435
556
  return payload;
436
557
  }
437
558
 
@@ -440,10 +561,10 @@ function printConnectionSummary(status, verb = "Started") {
440
561
  headline();
441
562
  console.log("");
442
563
  kv("Status", `${verb.toLowerCase()} · ${status.mode}`);
443
- kv("Console", `http://localhost:4310`);
564
+ kv("Console", LOCAL_CONSOLE_BASE_URL);
444
565
  if (status.mode === "global-preview") {
445
- const signalingUrl = status?.signaling?.url || "https://relay.silicaclaw.com";
446
- const room = status?.signaling?.room || "silicaclaw-global-preview";
566
+ const signalingUrl = status?.signaling?.url || DEFAULT_SIGNALING_URL;
567
+ const room = status?.signaling?.room || DEFAULT_ROOM;
447
568
  kv("Relay", signalingUrl);
448
569
  kv("Room", room);
449
570
  }
@@ -476,6 +597,22 @@ function normalizePathForMatch(value) {
476
597
  return String(value || "").replace(/\\/g, "/");
477
598
  }
478
599
 
600
+ function isLocalConsoleCommand(command) {
601
+ const text = normalizePathForMatch(command).toLowerCase();
602
+ return (
603
+ text.includes("@silicaclaw/local-console") ||
604
+ text.includes("npm run --workspace @silicaclaw/local-console start") ||
605
+ text.includes("/apps/local-console/") ||
606
+ text.includes("dist/apps/local-console/src/server.js") ||
607
+ text.includes("src/server.ts")
608
+ );
609
+ }
610
+
611
+ function isSignalingCommand(command) {
612
+ const text = normalizePathForMatch(command).toLowerCase();
613
+ return text.includes("webrtc-signaling-server.mjs") || text.includes("npm run webrtc-signaling");
614
+ }
615
+
479
616
  function sleep(ms) {
480
617
  return new Promise((resolve) => setTimeout(resolve, ms));
481
618
  }
@@ -502,6 +639,20 @@ async function waitForCurrentAppListener(port, kind, timeoutMs = 5000) {
502
639
  return lastListener;
503
640
  }
504
641
 
642
+ async function waitForLocalConsoleHealth(timeoutMs = 8000) {
643
+ const startedAt = Date.now();
644
+ while (Date.now() - startedAt < timeoutMs) {
645
+ try {
646
+ const response = await fetch(`${LOCAL_CONSOLE_BASE_URL}/api/health`);
647
+ if (response.ok) return true;
648
+ } catch {
649
+ // ignore transient startup failures
650
+ }
651
+ await sleep(250);
652
+ }
653
+ return false;
654
+ }
655
+
505
656
  async function waitForPortToClear(port, timeoutMs = 5000) {
506
657
  const startedAt = Date.now();
507
658
  while (Date.now() - startedAt < timeoutMs) {
@@ -520,40 +671,24 @@ function tailText(file, lines = 20) {
520
671
 
521
672
  function isOwnedListener(listener, kind) {
522
673
  if (!listener?.command) return false;
523
- const command = normalizePathForMatch(listener.command).toLowerCase();
524
- const appDir = normalizePathForMatch(APP_DIR).toLowerCase();
525
- const rootDir = normalizePathForMatch(ROOT_DIR).toLowerCase();
526
- const inWorkspace = command.includes(appDir) || command.includes(rootDir);
527
- if (!inWorkspace) return false;
674
+ const command = listener.command;
528
675
  if (kind === "local-console") {
529
- return (
530
- command.includes("@silicaclaw/local-console") ||
531
- command.includes("/apps/local-console/") ||
532
- command.includes("src/server.ts") ||
533
- command.includes("dist/server.js")
534
- );
676
+ return isLocalConsoleCommand(command);
535
677
  }
536
678
  if (kind === "signaling") {
537
- return command.includes("webrtc-signaling-server.mjs") || command.includes("npm run webrtc-signaling");
679
+ return isSignalingCommand(command);
538
680
  }
539
681
  return false;
540
682
  }
541
683
 
542
684
  function isCurrentAppListener(listener, kind) {
543
685
  if (!listener?.command) return false;
544
- const command = normalizePathForMatch(listener.command).toLowerCase();
545
- const appDir = normalizePathForMatch(APP_DIR).toLowerCase();
546
- if (!command.includes(appDir)) return false;
686
+ const command = listener.command;
547
687
  if (kind === "local-console") {
548
- return (
549
- command.includes("@silicaclaw/local-console") ||
550
- command.includes("/apps/local-console/") ||
551
- command.includes("src/server.ts") ||
552
- command.includes("dist/server.js")
553
- );
688
+ return isLocalConsoleCommand(command);
554
689
  }
555
690
  if (kind === "signaling") {
556
- return command.includes("webrtc-signaling-server.mjs") || command.includes("npm run webrtc-signaling");
691
+ return isSignalingCommand(command);
557
692
  }
558
693
  return false;
559
694
  }
@@ -592,7 +727,7 @@ async function drainOwnedListener(port, kind, timeoutMs = 5000) {
592
727
  }
593
728
 
594
729
  function printStopSummary() {
595
- const localListener = listeningProcessOnPort(4310);
730
+ const localListener = listeningProcessOnPort(LOCAL_CONSOLE_PORT);
596
731
  const signalingListener = listeningProcessOnPort(4510);
597
732
  headline();
598
733
  console.log("");
@@ -602,9 +737,9 @@ function printStopSummary() {
602
737
  } else {
603
738
  kv("Console", `${paint("still busy", COLOR.yellow)} (pid=${localListener.pid})`);
604
739
  if (isOwnedListener(localListener, "local-console")) {
605
- kv("Hint", "an older SilicaClaw local-console process is still holding port 4310");
740
+ kv("Hint", `an older SilicaClaw local-console process is still holding port ${LOCAL_CONSOLE_PORT}`);
606
741
  }
607
- kv("Inspect", "lsof -nP -iTCP:4310 -sTCP:LISTEN");
742
+ kv("Inspect", `lsof -nP -iTCP:${LOCAL_CONSOLE_PORT} -sTCP:LISTEN`);
608
743
  kv("Stop pid", `kill ${localListener.pid}`);
609
744
  }
610
745
  if (!signalingListener) {
@@ -636,7 +771,7 @@ async function stopAll() {
636
771
  if (isLaunchdPlatform()) {
637
772
  stopLaunchAgent(LOCAL_CONSOLE_LABEL);
638
773
  stopLaunchAgent(SIGNALING_LABEL);
639
- await drainOwnedListener(4310, "local-console", 8000);
774
+ await drainOwnedListener(LOCAL_CONSOLE_PORT, "local-console", 8000);
640
775
  await drainOwnedListener(4510, "signaling", 5000);
641
776
  removeFileIfExists(CONSOLE_PID_FILE);
642
777
  removeFileIfExists(SIGNALING_PID_FILE);
@@ -650,7 +785,7 @@ async function stopAll() {
650
785
  const sigPid = readPid(SIGNALING_PID_FILE);
651
786
  await stopPid(localPid, "local-console");
652
787
  await stopPid(sigPid, "signaling");
653
- await drainOwnedListener(4310, "local-console", 5000);
788
+ await drainOwnedListener(LOCAL_CONSOLE_PORT, "local-console", 5000);
654
789
  await drainOwnedListener(4510, "signaling", 5000);
655
790
  removeFileIfExists(CONSOLE_PID_FILE);
656
791
  removeFileIfExists(SIGNALING_PID_FILE);
@@ -663,38 +798,12 @@ async function stopAll() {
663
798
  async function startAll() {
664
799
  ensureStateDir();
665
800
 
666
- const mode = parseMode(parseFlag("mode", process.env.NETWORK_MODE || "global-preview"));
801
+ const mode = parseMode(parseFlag("mode", process.env.NETWORK_MODE || DEFAULT_NETWORK_MODE));
667
802
  const adapter = adapterForMode(mode);
668
- const signalingUrl = parseFlag("signaling-url", process.env.WEBRTC_SIGNALING_URL || "https://relay.silicaclaw.com");
669
- const room = parseFlag("room", process.env.WEBRTC_ROOM || "silicaclaw-global-preview");
803
+ const signalingUrl = parseFlag("signaling-url", process.env.WEBRTC_SIGNALING_URL || DEFAULT_SIGNALING_URL);
804
+ const room = parseFlag("room", process.env.WEBRTC_ROOM || DEFAULT_ROOM);
670
805
  const shouldDisableSignaling = hasFlag("no-signaling");
671
806
 
672
- const currentLocalPid = readPid(CONSOLE_PID_FILE);
673
- const currentSigPid = readPid(SIGNALING_PID_FILE);
674
- const currentListener = listeningProcessOnPort(4310);
675
- if (currentListener && isOwnedListener(currentListener, "local-console") && !isRunning(currentLocalPid)) {
676
- writeFileSync(CONSOLE_PID_FILE, String(currentListener.pid));
677
- }
678
-
679
- let localPid = readPid(CONSOLE_PID_FILE);
680
- if (!isRunning(localPid)) {
681
- removeFileIfExists(CONSOLE_PID_FILE);
682
- const env = {
683
- NETWORK_ADAPTER: adapter,
684
- NETWORK_MODE: mode,
685
- WEBRTC_SIGNALING_URL: signalingUrl,
686
- WEBRTC_ROOM: room,
687
- };
688
- localPid = spawnBackground(
689
- process.execPath,
690
- ["dist/apps/local-console/src/server.js"],
691
- env,
692
- CONSOLE_LOG_FILE,
693
- CONSOLE_PID_FILE,
694
- LOCAL_CONSOLE_DIR,
695
- );
696
- }
697
-
698
807
  const { host, port } = parseUrlHostPort(signalingUrl);
699
808
  const shouldAutoStartSignaling =
700
809
  mode === "global-preview" &&
@@ -702,32 +811,34 @@ async function startAll() {
702
811
  (host === "localhost" || host === "127.0.0.1");
703
812
 
704
813
  if (isLaunchdPlatform()) {
705
- const npmPath = resolveCommandPath("npm");
706
- const signalingEntry = resolve(APP_DIR, "scripts", "webrtc-signaling-server.mjs");
707
- await drainOwnedListener(4310, "local-console", 8000);
814
+ const managedAppDir = syncManagedRuntime();
815
+ const signalingEntry = resolve(managedAppDir, "scripts", "webrtc-signaling-server.mjs");
816
+ await drainOwnedListener(LOCAL_CONSOLE_PORT, "local-console", 8000);
708
817
  await drainOwnedListener(4510, "signaling", 5000);
709
818
  const baseEnv = {
710
819
  NETWORK_ADAPTER: adapter,
711
820
  NETWORK_MODE: mode,
712
821
  WEBRTC_SIGNALING_URL: signalingUrl,
713
822
  WEBRTC_ROOM: room,
823
+ SILICACLAW_APP_DIR: managedAppDir,
824
+ SILICACLAW_WORKSPACE_DIR: WORKSPACE_DIR,
714
825
  PATH: process.env.PATH || "/usr/bin:/bin:/usr/sbin:/sbin",
715
826
  HOME: process.env.HOME || homedir(),
716
827
  };
717
828
 
718
- installLaunchAgent({
829
+ ensureLaunchAgent({
719
830
  label: LOCAL_CONSOLE_LABEL,
720
- programArguments: [npmPath, "run", "--workspace", "@silicaclaw/local-console", "start"],
721
- workingDirectory: APP_DIR,
831
+ programArguments: localConsoleProgramArguments(managedAppDir),
832
+ workingDirectory: managedAppDir,
722
833
  logFile: CONSOLE_LOG_FILE,
723
834
  environment: baseEnv,
724
835
  });
725
836
 
726
837
  if (shouldAutoStartSignaling) {
727
- installLaunchAgent({
838
+ ensureLaunchAgent({
728
839
  label: SIGNALING_LABEL,
729
840
  programArguments: [process.execPath, signalingEntry],
730
- workingDirectory: APP_DIR,
841
+ workingDirectory: managedAppDir,
731
842
  logFile: SIGNALING_LOG_FILE,
732
843
  environment: {
733
844
  PATH: baseEnv.PATH,
@@ -741,6 +852,8 @@ async function startAll() {
741
852
 
742
853
  writeState({
743
854
  app_dir: APP_DIR,
855
+ managed_app_dir: managedAppDir,
856
+ workspace_dir: WORKSPACE_DIR,
744
857
  mode,
745
858
  adapter,
746
859
  signaling_url: signalingUrl,
@@ -750,6 +863,39 @@ async function startAll() {
750
863
  return { localPid: null, signalingPid: null };
751
864
  }
752
865
 
866
+ const currentLocalPid = readPid(CONSOLE_PID_FILE);
867
+ const currentSigPid = readPid(SIGNALING_PID_FILE);
868
+ const currentListener = listeningProcessOnPort(LOCAL_CONSOLE_PORT);
869
+ if (currentListener && isOwnedListener(currentListener, "local-console") && !isRunning(currentLocalPid)) {
870
+ writeFileSync(CONSOLE_PID_FILE, String(currentListener.pid));
871
+ }
872
+
873
+ let localPid = readPid(CONSOLE_PID_FILE);
874
+ if (!isRunning(localPid)) {
875
+ removeFileIfExists(CONSOLE_PID_FILE);
876
+ await drainOwnedListener(LOCAL_CONSOLE_PORT, "local-console", 8000);
877
+ const remainingLocalListener = listeningProcessOnPort(LOCAL_CONSOLE_PORT);
878
+ if (remainingLocalListener) {
879
+ throw new Error(`port ${LOCAL_CONSOLE_PORT} is occupied by pid=${remainingLocalListener.pid}`);
880
+ }
881
+ const env = {
882
+ NETWORK_ADAPTER: adapter,
883
+ NETWORK_MODE: mode,
884
+ WEBRTC_SIGNALING_URL: signalingUrl,
885
+ WEBRTC_ROOM: room,
886
+ SILICACLAW_APP_DIR: APP_DIR,
887
+ SILICACLAW_WORKSPACE_DIR: WORKSPACE_DIR,
888
+ };
889
+ localPid = spawnBackground(
890
+ process.execPath,
891
+ ["dist/apps/local-console/src/server.js"],
892
+ env,
893
+ CONSOLE_LOG_FILE,
894
+ CONSOLE_PID_FILE,
895
+ LOCAL_CONSOLE_DIR,
896
+ );
897
+ }
898
+
753
899
  let signalingPid = currentSigPid;
754
900
  if (shouldAutoStartSignaling) {
755
901
  if (!isRunning(currentSigPid)) {
@@ -766,6 +912,7 @@ async function startAll() {
766
912
 
767
913
  writeState({
768
914
  app_dir: APP_DIR,
915
+ workspace_dir: WORKSPACE_DIR,
769
916
  mode,
770
917
  adapter,
771
918
  signaling_url: signalingUrl,
@@ -775,6 +922,81 @@ async function startAll() {
775
922
  return { localPid, signalingPid: shouldAutoStartSignaling ? signalingPid : null };
776
923
  }
777
924
 
925
+ async function restartAll() {
926
+ if (!isLaunchdPlatform()) {
927
+ await stopAll();
928
+ await startAll();
929
+ return;
930
+ }
931
+
932
+ ensureStateDir();
933
+
934
+ const mode = parseMode(parseFlag("mode", process.env.NETWORK_MODE || DEFAULT_NETWORK_MODE));
935
+ const adapter = adapterForMode(mode);
936
+ const signalingUrl = parseFlag("signaling-url", process.env.WEBRTC_SIGNALING_URL || DEFAULT_SIGNALING_URL);
937
+ const room = parseFlag("room", process.env.WEBRTC_ROOM || DEFAULT_ROOM);
938
+ const shouldDisableSignaling = hasFlag("no-signaling");
939
+ const { host, port } = parseUrlHostPort(signalingUrl);
940
+ const shouldAutoStartSignaling =
941
+ mode === "global-preview" &&
942
+ !shouldDisableSignaling &&
943
+ (host === "localhost" || host === "127.0.0.1");
944
+
945
+ const managedAppDir = syncManagedRuntime();
946
+ const signalingEntry = resolve(managedAppDir, "scripts", "webrtc-signaling-server.mjs");
947
+ const baseEnv = {
948
+ NETWORK_ADAPTER: adapter,
949
+ NETWORK_MODE: mode,
950
+ WEBRTC_SIGNALING_URL: signalingUrl,
951
+ WEBRTC_ROOM: room,
952
+ SILICACLAW_APP_DIR: managedAppDir,
953
+ SILICACLAW_WORKSPACE_DIR: WORKSPACE_DIR,
954
+ PATH: process.env.PATH || "/usr/bin:/bin:/usr/sbin:/sbin",
955
+ HOME: process.env.HOME || homedir(),
956
+ };
957
+
958
+ const localConsoleService = ensureLaunchAgent({
959
+ label: LOCAL_CONSOLE_LABEL,
960
+ programArguments: localConsoleProgramArguments(managedAppDir),
961
+ workingDirectory: managedAppDir,
962
+ logFile: CONSOLE_LOG_FILE,
963
+ environment: baseEnv,
964
+ });
965
+ if (!localConsoleService.changed) {
966
+ restartLaunchAgent(LOCAL_CONSOLE_LABEL, localConsoleService.plistPath);
967
+ }
968
+
969
+ if (shouldAutoStartSignaling) {
970
+ const signalingService = ensureLaunchAgent({
971
+ label: SIGNALING_LABEL,
972
+ programArguments: [process.execPath, signalingEntry],
973
+ workingDirectory: managedAppDir,
974
+ logFile: SIGNALING_LOG_FILE,
975
+ environment: {
976
+ PATH: baseEnv.PATH,
977
+ HOME: baseEnv.HOME,
978
+ PORT: String(port),
979
+ },
980
+ });
981
+ if (!signalingService.changed) {
982
+ restartLaunchAgent(SIGNALING_LABEL, signalingService.plistPath);
983
+ }
984
+ } else {
985
+ uninstallLaunchAgent(SIGNALING_LABEL);
986
+ }
987
+
988
+ writeState({
989
+ app_dir: APP_DIR,
990
+ managed_app_dir: managedAppDir,
991
+ workspace_dir: WORKSPACE_DIR,
992
+ mode,
993
+ adapter,
994
+ signaling_url: signalingUrl,
995
+ room,
996
+ updated_at: Date.now(),
997
+ });
998
+ }
999
+
778
1000
  async function main() {
779
1001
  if (cmd === "help" || cmd === "-h" || cmd === "--help") {
780
1002
  printHelp();
@@ -790,14 +1012,15 @@ async function main() {
790
1012
  }
791
1013
  if (cmd === "start") {
792
1014
  await startAll();
793
- const listener = await waitForCurrentAppListener(4310, "local-console", 15000);
794
- if (!listener || !isCurrentAppListener(listener, "local-console")) {
1015
+ const listener = await waitForCurrentAppListener(LOCAL_CONSOLE_PORT, "local-console", 15000);
1016
+ const healthy = listener ? await waitForLocalConsoleHealth(8000) : false;
1017
+ if (!listener || !isCurrentAppListener(listener, "local-console") || !healthy) {
795
1018
  headline();
796
1019
  console.log("");
797
1020
  kv("Status", paint("failed to start", COLOR.red));
798
1021
  if (listener) {
799
- kv("Conflict", `port 4310 is occupied by pid=${listener.pid}`);
800
- kv("Inspect", "lsof -nP -iTCP:4310 -sTCP:LISTEN");
1022
+ kv("Conflict", `port ${LOCAL_CONSOLE_PORT} is occupied by pid=${listener.pid}`);
1023
+ kv("Inspect", `lsof -nP -iTCP:${LOCAL_CONSOLE_PORT} -sTCP:LISTEN`);
801
1024
  }
802
1025
  const recent = tailText(CONSOLE_LOG_FILE, 18);
803
1026
  if (recent) {
@@ -817,16 +1040,16 @@ async function main() {
817
1040
  return;
818
1041
  }
819
1042
  if (cmd === "restart") {
820
- await stopAll();
821
- await startAll();
822
- const listener = await waitForCurrentAppListener(4310, "local-console", 15000);
823
- if (!listener || !isCurrentAppListener(listener, "local-console")) {
1043
+ await restartAll();
1044
+ const listener = await waitForCurrentAppListener(LOCAL_CONSOLE_PORT, "local-console", 15000);
1045
+ const healthy = listener ? await waitForLocalConsoleHealth(8000) : false;
1046
+ if (!listener || !isCurrentAppListener(listener, "local-console") || !healthy) {
824
1047
  headline();
825
1048
  console.log("");
826
1049
  kv("Status", paint("failed to restart", COLOR.red));
827
1050
  if (listener) {
828
- kv("Conflict", `port 4310 is occupied by pid=${listener.pid}`);
829
- kv("Inspect", "lsof -nP -iTCP:4310 -sTCP:LISTEN");
1051
+ kv("Conflict", `port ${LOCAL_CONSOLE_PORT} is occupied by pid=${listener.pid}`);
1052
+ kv("Inspect", `lsof -nP -iTCP:${LOCAL_CONSOLE_PORT} -sTCP:LISTEN`);
830
1053
  }
831
1054
  const recent = tailText(CONSOLE_LOG_FILE, 18);
832
1055
  if (recent) {