@silicaclaw/cli 2026.3.19-9 → 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 +128 -0
  2. package/DEMO_GUIDE.md +1 -1
  3. package/INSTALL.md +47 -13
  4. package/README.md +54 -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 +5 -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 +59 -1
  276. package/scripts/silicaclaw-cli.mjs +109 -47
  277. package/scripts/silicaclaw-gateway.mjs +302 -84
  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,10 +798,10 @@ 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
807
  const { host, port } = parseUrlHostPort(signalingUrl);
@@ -676,32 +811,34 @@ async function startAll() {
676
811
  (host === "localhost" || host === "127.0.0.1");
677
812
 
678
813
  if (isLaunchdPlatform()) {
679
- const npmPath = resolveCommandPath("npm");
680
- const signalingEntry = resolve(APP_DIR, "scripts", "webrtc-signaling-server.mjs");
681
- 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);
682
817
  await drainOwnedListener(4510, "signaling", 5000);
683
818
  const baseEnv = {
684
819
  NETWORK_ADAPTER: adapter,
685
820
  NETWORK_MODE: mode,
686
821
  WEBRTC_SIGNALING_URL: signalingUrl,
687
822
  WEBRTC_ROOM: room,
823
+ SILICACLAW_APP_DIR: managedAppDir,
824
+ SILICACLAW_WORKSPACE_DIR: WORKSPACE_DIR,
688
825
  PATH: process.env.PATH || "/usr/bin:/bin:/usr/sbin:/sbin",
689
826
  HOME: process.env.HOME || homedir(),
690
827
  };
691
828
 
692
- installLaunchAgent({
829
+ ensureLaunchAgent({
693
830
  label: LOCAL_CONSOLE_LABEL,
694
- programArguments: [npmPath, "run", "--workspace", "@silicaclaw/local-console", "start"],
695
- workingDirectory: APP_DIR,
831
+ programArguments: localConsoleProgramArguments(managedAppDir),
832
+ workingDirectory: managedAppDir,
696
833
  logFile: CONSOLE_LOG_FILE,
697
834
  environment: baseEnv,
698
835
  });
699
836
 
700
837
  if (shouldAutoStartSignaling) {
701
- installLaunchAgent({
838
+ ensureLaunchAgent({
702
839
  label: SIGNALING_LABEL,
703
840
  programArguments: [process.execPath, signalingEntry],
704
- workingDirectory: APP_DIR,
841
+ workingDirectory: managedAppDir,
705
842
  logFile: SIGNALING_LOG_FILE,
706
843
  environment: {
707
844
  PATH: baseEnv.PATH,
@@ -715,6 +852,8 @@ async function startAll() {
715
852
 
716
853
  writeState({
717
854
  app_dir: APP_DIR,
855
+ managed_app_dir: managedAppDir,
856
+ workspace_dir: WORKSPACE_DIR,
718
857
  mode,
719
858
  adapter,
720
859
  signaling_url: signalingUrl,
@@ -726,7 +865,7 @@ async function startAll() {
726
865
 
727
866
  const currentLocalPid = readPid(CONSOLE_PID_FILE);
728
867
  const currentSigPid = readPid(SIGNALING_PID_FILE);
729
- const currentListener = listeningProcessOnPort(4310);
868
+ const currentListener = listeningProcessOnPort(LOCAL_CONSOLE_PORT);
730
869
  if (currentListener && isOwnedListener(currentListener, "local-console") && !isRunning(currentLocalPid)) {
731
870
  writeFileSync(CONSOLE_PID_FILE, String(currentListener.pid));
732
871
  }
@@ -734,16 +873,18 @@ async function startAll() {
734
873
  let localPid = readPid(CONSOLE_PID_FILE);
735
874
  if (!isRunning(localPid)) {
736
875
  removeFileIfExists(CONSOLE_PID_FILE);
737
- await drainOwnedListener(4310, "local-console", 8000);
738
- const remainingLocalListener = listeningProcessOnPort(4310);
876
+ await drainOwnedListener(LOCAL_CONSOLE_PORT, "local-console", 8000);
877
+ const remainingLocalListener = listeningProcessOnPort(LOCAL_CONSOLE_PORT);
739
878
  if (remainingLocalListener) {
740
- throw new Error(`port 4310 is occupied by pid=${remainingLocalListener.pid}`);
879
+ throw new Error(`port ${LOCAL_CONSOLE_PORT} is occupied by pid=${remainingLocalListener.pid}`);
741
880
  }
742
881
  const env = {
743
882
  NETWORK_ADAPTER: adapter,
744
883
  NETWORK_MODE: mode,
745
884
  WEBRTC_SIGNALING_URL: signalingUrl,
746
885
  WEBRTC_ROOM: room,
886
+ SILICACLAW_APP_DIR: APP_DIR,
887
+ SILICACLAW_WORKSPACE_DIR: WORKSPACE_DIR,
747
888
  };
748
889
  localPid = spawnBackground(
749
890
  process.execPath,
@@ -771,6 +912,7 @@ async function startAll() {
771
912
 
772
913
  writeState({
773
914
  app_dir: APP_DIR,
915
+ workspace_dir: WORKSPACE_DIR,
774
916
  mode,
775
917
  adapter,
776
918
  signaling_url: signalingUrl,
@@ -780,6 +922,81 @@ async function startAll() {
780
922
  return { localPid, signalingPid: shouldAutoStartSignaling ? signalingPid : null };
781
923
  }
782
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
+
783
1000
  async function main() {
784
1001
  if (cmd === "help" || cmd === "-h" || cmd === "--help") {
785
1002
  printHelp();
@@ -795,14 +1012,15 @@ async function main() {
795
1012
  }
796
1013
  if (cmd === "start") {
797
1014
  await startAll();
798
- const listener = await waitForCurrentAppListener(4310, "local-console", 15000);
799
- 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) {
800
1018
  headline();
801
1019
  console.log("");
802
1020
  kv("Status", paint("failed to start", COLOR.red));
803
1021
  if (listener) {
804
- kv("Conflict", `port 4310 is occupied by pid=${listener.pid}`);
805
- 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`);
806
1024
  }
807
1025
  const recent = tailText(CONSOLE_LOG_FILE, 18);
808
1026
  if (recent) {
@@ -822,16 +1040,16 @@ async function main() {
822
1040
  return;
823
1041
  }
824
1042
  if (cmd === "restart") {
825
- await stopAll();
826
- await startAll();
827
- const listener = await waitForCurrentAppListener(4310, "local-console", 15000);
828
- 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) {
829
1047
  headline();
830
1048
  console.log("");
831
1049
  kv("Status", paint("failed to restart", COLOR.red));
832
1050
  if (listener) {
833
- kv("Conflict", `port 4310 is occupied by pid=${listener.pid}`);
834
- 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`);
835
1053
  }
836
1054
  const recent = tailText(CONSOLE_LOG_FILE, 18);
837
1055
  if (recent) {