@silicaclaw/cli 2026.3.19-9 → 2026.3.20-2
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.
- package/CHANGELOG.md +134 -0
- package/DEMO_GUIDE.md +1 -1
- package/INSTALL.md +47 -13
- package/README.md +54 -19
- package/VERSION +1 -1
- package/apps/local-console/dist/apps/local-console/src/server.d.ts +51 -12
- package/apps/local-console/dist/apps/local-console/src/server.js +619 -183
- package/apps/local-console/dist/config/silicaclaw-defaults.json +19 -0
- package/apps/local-console/dist/packages/core/src/socialConfig.js +9 -5
- package/apps/local-console/dist/packages/network/src/realPreview.js +6 -2
- package/apps/local-console/dist/packages/network/src/relayPreview.js +8 -2
- package/apps/local-console/dist/packages/network/src/transport/udpLanBroadcastTransport.js +2 -1
- package/apps/local-console/dist/packages/network/src/webrtcPreview.js +5 -1
- package/apps/local-console/dist/packages/storage/config/silicaclaw-defaults.json +19 -0
- package/apps/local-console/dist/packages/storage/src/socialRuntimeRepo.js +8 -4
- package/apps/local-console/public/app/app.js +21 -1
- package/apps/local-console/public/app/events.js +40 -2
- package/apps/local-console/public/app/network.js +32 -3
- package/apps/local-console/public/app/overview.js +18 -26
- package/apps/local-console/public/app/shell.js +18 -34
- package/apps/local-console/public/app/social.js +207 -28
- package/apps/local-console/public/app/styles.css +182 -14
- package/apps/local-console/public/app/template.js +76 -31
- package/apps/local-console/public/app/translations.js +147 -51
- package/apps/local-console/src/server.ts +652 -189
- package/apps/public-explorer/dist/apps/public-explorer/src/server.d.ts +1 -0
- package/apps/public-explorer/dist/apps/public-explorer/src/server.js +41 -0
- package/apps/public-explorer/dist/config/silicaclaw-defaults.json +19 -0
- package/apps/public-explorer/public/app/app.js +22 -2
- package/apps/public-explorer/public/app/template.js +4 -4
- package/apps/public-explorer/public/app/translations.js +15 -15
- package/apps/public-explorer/src/server.ts +11 -1
- package/config/silicaclaw-defaults.json +19 -0
- package/dist/apps/local-console/src/server.d.ts +1 -0
- package/dist/apps/local-console/src/server.js +555 -0
- package/docs/NEW_USER_INSTALL.md +14 -10
- package/docs/NEW_USER_OPERATIONS.md +4 -4
- package/docs/OPENCLAW_BRIDGE.md +15 -0
- package/docs/OPENCLAW_BRIDGE_ZH.md +15 -0
- package/docs/RELEASE_CHECKLIST.md +95 -0
- package/node_modules/@silicaclaw/core/dist/config/silicaclaw-defaults.json +19 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/crypto.d.ts +6 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/crypto.js +50 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/directory.d.ts +17 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/directory.js +145 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/identity.d.ts +2 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/identity.js +18 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/index.d.ts +12 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/index.js +28 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/indexing.d.ts +6 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/indexing.js +43 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/presence.d.ts +4 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/presence.js +23 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/profile.d.ts +4 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/profile.js +39 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/publicProfileSummary.d.ts +70 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/publicProfileSummary.js +103 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/socialConfig.d.ts +100 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/socialConfig.js +300 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/socialMessage.d.ts +19 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/socialMessage.js +69 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/socialResolver.d.ts +46 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/socialResolver.js +237 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/socialTemplate.d.ts +2 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/socialTemplate.js +90 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/types.d.ts +59 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/types.js +2 -0
- package/node_modules/@silicaclaw/core/src/socialConfig.ts +7 -5
- package/node_modules/@silicaclaw/network/dist/config/silicaclaw-defaults.json +19 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/messageEnvelope.d.ts +28 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/messageEnvelope.js +36 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/peerDiscovery.d.ts +43 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/peerDiscovery.js +2 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/topicCodec.d.ts +4 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/topicCodec.js +2 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/transport.d.ts +36 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/abstractions/transport.js +2 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.d.ts +5 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.js +24 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonTopicCodec.d.ts +5 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/codec/jsonTopicCodec.js +12 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.d.ts +28 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.js +144 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/index.d.ts +14 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/index.js +30 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/localEventBus.d.ts +9 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/localEventBus.js +47 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/mock.d.ts +8 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/mock.js +24 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/realPreview.d.ts +105 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/realPreview.js +331 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.d.ts +166 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.js +448 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/transport/udpLanBroadcastTransport.d.ts +23 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/transport/udpLanBroadcastTransport.js +154 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/types.d.ts +6 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/types.js +2 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/webrtcPreview.d.ts +163 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/webrtcPreview.js +848 -0
- package/node_modules/@silicaclaw/network/src/realPreview.ts +3 -2
- package/node_modules/@silicaclaw/network/src/relayPreview.ts +5 -2
- package/node_modules/@silicaclaw/network/src/transport/udpLanBroadcastTransport.ts +2 -1
- package/node_modules/@silicaclaw/network/src/webrtcPreview.ts +2 -1
- package/node_modules/@silicaclaw/storage/config/silicaclaw-defaults.json +19 -0
- package/node_modules/@silicaclaw/storage/dist/config/silicaclaw-defaults.json +19 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/crypto.d.ts +6 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/crypto.js +50 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/directory.d.ts +17 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/directory.js +145 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/identity.d.ts +2 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/identity.js +18 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/index.d.ts +12 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/index.js +28 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/indexing.d.ts +6 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/indexing.js +43 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/presence.d.ts +4 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/presence.js +23 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/profile.d.ts +4 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/profile.js +39 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/publicProfileSummary.d.ts +70 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/publicProfileSummary.js +103 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialConfig.d.ts +100 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialConfig.js +300 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialMessage.d.ts +19 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialMessage.js +69 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialResolver.d.ts +46 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialResolver.js +237 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialTemplate.d.ts +2 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/socialTemplate.js +90 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/types.d.ts +59 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/types.js +2 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/config/silicaclaw-defaults.json +19 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/index.d.ts +3 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/index.js +19 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/jsonRepo.d.ts +7 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/jsonRepo.js +29 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/repos.d.ts +61 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/repos.js +67 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/socialRuntimeRepo.d.ts +5 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/socialRuntimeRepo.js +57 -0
- package/node_modules/@silicaclaw/storage/dist/socialRuntimeRepo.js +8 -4
- package/node_modules/@silicaclaw/storage/src/socialRuntimeRepo.ts +5 -4
- package/node_modules/@silicaclaw/storage/tsconfig.json +1 -6
- package/openclaw-skills/silicaclaw-bridge-setup/SKILL.md +147 -0
- package/openclaw-skills/silicaclaw-bridge-setup/VERSION +1 -0
- package/openclaw-skills/silicaclaw-bridge-setup/agents/openai.yaml +6 -0
- package/openclaw-skills/silicaclaw-bridge-setup/manifest.json +27 -0
- package/openclaw-skills/silicaclaw-bridge-setup/references/owner-dialogue-cheatsheet-zh.md +58 -0
- package/openclaw-skills/silicaclaw-bridge-setup/references/runtime-setup.md +43 -0
- package/openclaw-skills/silicaclaw-bridge-setup/references/troubleshooting.md +24 -0
- package/openclaw-skills/silicaclaw-broadcast/SKILL.md +132 -0
- package/openclaw-skills/silicaclaw-broadcast/VERSION +1 -1
- package/openclaw-skills/silicaclaw-broadcast/agents/openai.yaml +2 -2
- package/openclaw-skills/silicaclaw-broadcast/manifest.json +3 -2
- package/openclaw-skills/silicaclaw-broadcast/references/owner-dialogue-cheatsheet-zh.md +81 -0
- package/openclaw-skills/silicaclaw-owner-push/SKILL.md +217 -0
- package/openclaw-skills/silicaclaw-owner-push/VERSION +1 -0
- package/openclaw-skills/silicaclaw-owner-push/agents/openai.yaml +6 -0
- package/openclaw-skills/silicaclaw-owner-push/manifest.json +30 -0
- package/openclaw-skills/silicaclaw-owner-push/references/owner-dialogue-cheatsheet-zh.md +87 -0
- package/openclaw-skills/silicaclaw-owner-push/references/push-routing-policy.md +43 -0
- package/openclaw-skills/silicaclaw-owner-push/references/runtime-setup.md +41 -0
- package/openclaw-skills/silicaclaw-owner-push/scripts/owner-push-forwarder.mjs +214 -0
- package/openclaw-skills/silicaclaw-owner-push/scripts/send-to-owner-via-openclaw.mjs +69 -0
- package/package.json +5 -1
- package/packages/core/dist/config/silicaclaw-defaults.json +19 -0
- package/packages/core/dist/packages/core/src/crypto.d.ts +6 -0
- package/packages/core/dist/packages/core/src/crypto.js +50 -0
- package/packages/core/dist/packages/core/src/directory.d.ts +17 -0
- package/packages/core/dist/packages/core/src/directory.js +145 -0
- package/packages/core/dist/packages/core/src/identity.d.ts +2 -0
- package/packages/core/dist/packages/core/src/identity.js +18 -0
- package/packages/core/dist/packages/core/src/index.d.ts +12 -0
- package/packages/core/dist/packages/core/src/index.js +28 -0
- package/packages/core/dist/packages/core/src/indexing.d.ts +6 -0
- package/packages/core/dist/packages/core/src/indexing.js +43 -0
- package/packages/core/dist/packages/core/src/presence.d.ts +4 -0
- package/packages/core/dist/packages/core/src/presence.js +23 -0
- package/packages/core/dist/packages/core/src/profile.d.ts +4 -0
- package/packages/core/dist/packages/core/src/profile.js +39 -0
- package/packages/core/dist/packages/core/src/publicProfileSummary.d.ts +70 -0
- package/packages/core/dist/packages/core/src/publicProfileSummary.js +103 -0
- package/packages/core/dist/packages/core/src/socialConfig.d.ts +100 -0
- package/packages/core/dist/packages/core/src/socialConfig.js +300 -0
- package/packages/core/dist/packages/core/src/socialMessage.d.ts +19 -0
- package/packages/core/dist/packages/core/src/socialMessage.js +69 -0
- package/packages/core/dist/packages/core/src/socialResolver.d.ts +46 -0
- package/packages/core/dist/packages/core/src/socialResolver.js +237 -0
- package/packages/core/dist/packages/core/src/socialTemplate.d.ts +2 -0
- package/packages/core/dist/packages/core/src/socialTemplate.js +90 -0
- package/packages/core/dist/packages/core/src/types.d.ts +59 -0
- package/packages/core/dist/packages/core/src/types.js +2 -0
- package/packages/core/src/socialConfig.ts +7 -5
- package/packages/network/dist/config/silicaclaw-defaults.json +19 -0
- package/packages/network/dist/packages/network/src/abstractions/messageEnvelope.d.ts +28 -0
- package/packages/network/dist/packages/network/src/abstractions/messageEnvelope.js +36 -0
- package/packages/network/dist/packages/network/src/abstractions/peerDiscovery.d.ts +43 -0
- package/packages/network/dist/packages/network/src/abstractions/peerDiscovery.js +2 -0
- package/packages/network/dist/packages/network/src/abstractions/topicCodec.d.ts +4 -0
- package/packages/network/dist/packages/network/src/abstractions/topicCodec.js +2 -0
- package/packages/network/dist/packages/network/src/abstractions/transport.d.ts +36 -0
- package/packages/network/dist/packages/network/src/abstractions/transport.js +2 -0
- package/packages/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.d.ts +5 -0
- package/packages/network/dist/packages/network/src/codec/jsonMessageEnvelopeCodec.js +24 -0
- package/packages/network/dist/packages/network/src/codec/jsonTopicCodec.d.ts +5 -0
- package/packages/network/dist/packages/network/src/codec/jsonTopicCodec.js +12 -0
- package/packages/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.d.ts +28 -0
- package/packages/network/dist/packages/network/src/discovery/heartbeatPeerDiscovery.js +144 -0
- package/packages/network/dist/packages/network/src/index.d.ts +14 -0
- package/packages/network/dist/packages/network/src/index.js +30 -0
- package/packages/network/dist/packages/network/src/localEventBus.d.ts +9 -0
- package/packages/network/dist/packages/network/src/localEventBus.js +47 -0
- package/packages/network/dist/packages/network/src/mock.d.ts +8 -0
- package/packages/network/dist/packages/network/src/mock.js +24 -0
- package/packages/network/dist/packages/network/src/realPreview.d.ts +105 -0
- package/packages/network/dist/packages/network/src/realPreview.js +331 -0
- package/packages/network/dist/packages/network/src/relayPreview.d.ts +166 -0
- package/packages/network/dist/packages/network/src/relayPreview.js +448 -0
- package/packages/network/dist/packages/network/src/transport/udpLanBroadcastTransport.d.ts +23 -0
- package/packages/network/dist/packages/network/src/transport/udpLanBroadcastTransport.js +154 -0
- package/packages/network/dist/packages/network/src/types.d.ts +6 -0
- package/packages/network/dist/packages/network/src/types.js +2 -0
- package/packages/network/dist/packages/network/src/webrtcPreview.d.ts +163 -0
- package/packages/network/dist/packages/network/src/webrtcPreview.js +848 -0
- package/packages/network/src/realPreview.ts +3 -2
- package/packages/network/src/relayPreview.ts +5 -2
- package/packages/network/src/transport/udpLanBroadcastTransport.ts +2 -1
- package/packages/network/src/webrtcPreview.ts +2 -1
- package/packages/storage/config/silicaclaw-defaults.json +19 -0
- package/packages/storage/dist/config/silicaclaw-defaults.json +19 -0
- package/packages/storage/dist/packages/core/src/crypto.d.ts +6 -0
- package/packages/storage/dist/packages/core/src/crypto.js +50 -0
- package/packages/storage/dist/packages/core/src/directory.d.ts +17 -0
- package/packages/storage/dist/packages/core/src/directory.js +145 -0
- package/packages/storage/dist/packages/core/src/identity.d.ts +2 -0
- package/packages/storage/dist/packages/core/src/identity.js +18 -0
- package/packages/storage/dist/packages/core/src/index.d.ts +12 -0
- package/packages/storage/dist/packages/core/src/index.js +28 -0
- package/packages/storage/dist/packages/core/src/indexing.d.ts +6 -0
- package/packages/storage/dist/packages/core/src/indexing.js +43 -0
- package/packages/storage/dist/packages/core/src/presence.d.ts +4 -0
- package/packages/storage/dist/packages/core/src/presence.js +23 -0
- package/packages/storage/dist/packages/core/src/profile.d.ts +4 -0
- package/packages/storage/dist/packages/core/src/profile.js +39 -0
- package/packages/storage/dist/packages/core/src/publicProfileSummary.d.ts +70 -0
- package/packages/storage/dist/packages/core/src/publicProfileSummary.js +103 -0
- package/packages/storage/dist/packages/core/src/socialConfig.d.ts +100 -0
- package/packages/storage/dist/packages/core/src/socialConfig.js +300 -0
- package/packages/storage/dist/packages/core/src/socialMessage.d.ts +19 -0
- package/packages/storage/dist/packages/core/src/socialMessage.js +69 -0
- package/packages/storage/dist/packages/core/src/socialResolver.d.ts +46 -0
- package/packages/storage/dist/packages/core/src/socialResolver.js +237 -0
- package/packages/storage/dist/packages/core/src/socialTemplate.d.ts +2 -0
- package/packages/storage/dist/packages/core/src/socialTemplate.js +90 -0
- package/packages/storage/dist/packages/core/src/types.d.ts +59 -0
- package/packages/storage/dist/packages/core/src/types.js +2 -0
- package/packages/storage/dist/packages/storage/config/silicaclaw-defaults.json +19 -0
- package/packages/storage/dist/packages/storage/src/index.d.ts +3 -0
- package/packages/storage/dist/packages/storage/src/index.js +19 -0
- package/packages/storage/dist/packages/storage/src/jsonRepo.d.ts +7 -0
- package/packages/storage/dist/packages/storage/src/jsonRepo.js +29 -0
- package/packages/storage/dist/packages/storage/src/repos.d.ts +61 -0
- package/packages/storage/dist/packages/storage/src/repos.js +67 -0
- package/packages/storage/dist/packages/storage/src/socialRuntimeRepo.d.ts +5 -0
- package/packages/storage/dist/packages/storage/src/socialRuntimeRepo.js +57 -0
- package/packages/storage/dist/socialRuntimeRepo.js +8 -4
- package/packages/storage/src/socialRuntimeRepo.ts +5 -4
- package/packages/storage/tsconfig.json +1 -6
- package/scripts/functional-check.mjs +35 -6
- package/scripts/install-openclaw-skill.mjs +9 -2
- package/scripts/openclaw-bridge-adapter.mjs +3 -1
- package/scripts/openclaw-bridge-client.mjs +3 -1
- package/scripts/openclaw-runtime-demo.mjs +3 -1
- package/scripts/quickstart.sh +14 -10
- package/scripts/release-pack.mjs +59 -1
- package/scripts/silicaclaw-cli.mjs +162 -50
- package/scripts/silicaclaw-gateway.mjs +302 -84
- package/scripts/validate-openclaw-skill.mjs +79 -21
|
@@ -13,6 +13,7 @@ const fs_1 = require("fs");
|
|
|
13
13
|
const crypto_1 = require("crypto");
|
|
14
14
|
const os_1 = require("os");
|
|
15
15
|
const util_1 = require("util");
|
|
16
|
+
const silicaclaw_defaults_json_1 = __importDefault(require("../../../config/silicaclaw-defaults.json"));
|
|
16
17
|
const core_1 = require("@silicaclaw/core");
|
|
17
18
|
const network_1 = require("@silicaclaw/network");
|
|
18
19
|
const storage_1 = require("@silicaclaw/storage");
|
|
@@ -27,16 +28,22 @@ const NETWORK_MAX_PAST_DRIFT_MS = Number(process.env.NETWORK_MAX_PAST_DRIFT_MS |
|
|
|
27
28
|
const NETWORK_HEARTBEAT_INTERVAL_MS = Number(process.env.NETWORK_HEARTBEAT_INTERVAL_MS || 12_000);
|
|
28
29
|
const NETWORK_PEER_STALE_AFTER_MS = Number(process.env.NETWORK_PEER_STALE_AFTER_MS || 45_000);
|
|
29
30
|
const OPENCLAW_GATEWAY_HOST = "127.0.0.1";
|
|
30
|
-
const
|
|
31
|
+
const DEFAULT_NETWORK_MODE = silicaclaw_defaults_json_1.default.network.default_mode;
|
|
32
|
+
const DEFAULT_NETWORK_NAMESPACE = silicaclaw_defaults_json_1.default.network.default_namespace;
|
|
33
|
+
const DEFAULT_NETWORK_PORT = silicaclaw_defaults_json_1.default.ports.network_default;
|
|
34
|
+
const DEFAULT_GLOBAL_SIGNALING_URL = silicaclaw_defaults_json_1.default.network.global_preview.relay_url;
|
|
35
|
+
const DEFAULT_GLOBAL_ROOM = silicaclaw_defaults_json_1.default.network.global_preview.room;
|
|
36
|
+
const DEFAULT_BRIDGE_API_BASE = silicaclaw_defaults_json_1.default.bridge.api_base;
|
|
37
|
+
const OPENCLAW_GATEWAY_PORT = silicaclaw_defaults_json_1.default.ports.openclaw_gateway;
|
|
31
38
|
const OPENCLAW_GATEWAY_URL = `http://${OPENCLAW_GATEWAY_HOST}:${OPENCLAW_GATEWAY_PORT}/`;
|
|
32
39
|
const NETWORK_PEER_REMOVE_AFTER_MS = Number(process.env.NETWORK_PEER_REMOVE_AFTER_MS || 180_000);
|
|
33
40
|
const NETWORK_UDP_BIND_ADDRESS = process.env.NETWORK_UDP_BIND_ADDRESS || "0.0.0.0";
|
|
34
41
|
const NETWORK_UDP_BROADCAST_ADDRESS = process.env.NETWORK_UDP_BROADCAST_ADDRESS || "255.255.255.255";
|
|
35
42
|
const NETWORK_PEER_ID = process.env.NETWORK_PEER_ID;
|
|
36
43
|
const NETWORK_MODE = process.env.NETWORK_MODE || "";
|
|
37
|
-
const WEBRTC_SIGNALING_URL = process.env.WEBRTC_SIGNALING_URL ||
|
|
44
|
+
const WEBRTC_SIGNALING_URL = process.env.WEBRTC_SIGNALING_URL || DEFAULT_GLOBAL_SIGNALING_URL;
|
|
38
45
|
const WEBRTC_SIGNALING_URLS = process.env.WEBRTC_SIGNALING_URLS || "";
|
|
39
|
-
const WEBRTC_ROOM = process.env.WEBRTC_ROOM ||
|
|
46
|
+
const WEBRTC_ROOM = process.env.WEBRTC_ROOM || DEFAULT_GLOBAL_ROOM;
|
|
40
47
|
const WEBRTC_SEED_PEERS = process.env.WEBRTC_SEED_PEERS || "";
|
|
41
48
|
const WEBRTC_BOOTSTRAP_HINTS = process.env.WEBRTC_BOOTSTRAP_HINTS || "";
|
|
42
49
|
const PROFILE_VERSION = "v0.9";
|
|
@@ -53,6 +60,8 @@ const SOCIAL_MESSAGE_DUPLICATE_WINDOW_MS = Number(process.env.SOCIAL_MESSAGE_DUP
|
|
|
53
60
|
const SOCIAL_MESSAGE_MAX_FUTURE_MS = Number(process.env.SOCIAL_MESSAGE_MAX_FUTURE_MS || 30_000);
|
|
54
61
|
const SOCIAL_MESSAGE_MAX_AGE_MS = Number(process.env.SOCIAL_MESSAGE_MAX_AGE_MS || 15 * 60_000);
|
|
55
62
|
const SOCIAL_MESSAGE_OBSERVATION_HISTORY_LIMIT = Number(process.env.SOCIAL_MESSAGE_OBSERVATION_HISTORY_LIMIT || 500);
|
|
63
|
+
const SOCIAL_MESSAGE_REPLAY_WINDOW_MS = Number(process.env.SOCIAL_MESSAGE_REPLAY_WINDOW_MS || 10 * 60_000);
|
|
64
|
+
const SOCIAL_MESSAGE_REPLAY_MAX_PER_BROADCAST = Number(process.env.SOCIAL_MESSAGE_REPLAY_MAX_PER_BROADCAST || 3);
|
|
56
65
|
const SOCIAL_MESSAGE_BLOCKED_AGENT_IDS = new Set(dedupeStrings(parseListEnv(process.env.SOCIAL_MESSAGE_BLOCKED_AGENT_IDS || "")));
|
|
57
66
|
const SOCIAL_MESSAGE_BLOCKED_TERMS = dedupeStrings(parseListEnv(process.env.SOCIAL_MESSAGE_BLOCKED_TERMS || ""))
|
|
58
67
|
.map((term) => term.trim().toLowerCase())
|
|
@@ -60,25 +69,70 @@ const SOCIAL_MESSAGE_BLOCKED_TERMS = dedupeStrings(parseListEnv(process.env.SOCI
|
|
|
60
69
|
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
61
70
|
const OPENCLAW_SKILL_NAME = "silicaclaw-broadcast";
|
|
62
71
|
function readWorkspaceVersion(workspaceRoot) {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
const candidates = [
|
|
73
|
+
workspaceRoot,
|
|
74
|
+
process.cwd(),
|
|
75
|
+
(0, path_1.resolve)(__dirname, "..", "..", ".."),
|
|
76
|
+
(0, path_1.resolve)(__dirname, "..", "..", "..", ".."),
|
|
77
|
+
].filter((dir, index, list) => dir && list.indexOf(dir) === index);
|
|
78
|
+
for (const candidate of candidates) {
|
|
79
|
+
const pkgFile = (0, path_1.resolve)(candidate, "package.json");
|
|
80
|
+
if ((0, fs_1.existsSync)(pkgFile)) {
|
|
81
|
+
try {
|
|
82
|
+
const pkg = JSON.parse((0, fs_1.readFileSync)(pkgFile, "utf8"));
|
|
83
|
+
if (pkg.version && (pkg.name === "@silicaclaw/cli" || (0, fs_1.existsSync)((0, path_1.resolve)(candidate, "apps", "local-console")))) {
|
|
84
|
+
return String(pkg.version);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// ignore
|
|
89
|
+
}
|
|
69
90
|
}
|
|
70
|
-
|
|
71
|
-
|
|
91
|
+
const versionFile = (0, path_1.resolve)(candidate, "VERSION");
|
|
92
|
+
if ((0, fs_1.existsSync)(versionFile)) {
|
|
93
|
+
const raw = (0, fs_1.readFileSync)(versionFile, "utf8").trim();
|
|
94
|
+
if (raw)
|
|
95
|
+
return raw;
|
|
72
96
|
}
|
|
73
97
|
}
|
|
74
|
-
const versionFile = (0, path_1.resolve)(workspaceRoot, "VERSION");
|
|
75
|
-
if ((0, fs_1.existsSync)(versionFile)) {
|
|
76
|
-
const raw = (0, fs_1.readFileSync)(versionFile, "utf8").trim();
|
|
77
|
-
if (raw)
|
|
78
|
-
return raw;
|
|
79
|
-
}
|
|
80
98
|
return "unknown";
|
|
81
99
|
}
|
|
100
|
+
function normalizeVersionText(value) {
|
|
101
|
+
const text = String(value || "").trim();
|
|
102
|
+
return text.startsWith("v") ? text.slice(1) : text;
|
|
103
|
+
}
|
|
104
|
+
function tokenizeVersion(value) {
|
|
105
|
+
return normalizeVersionText(value)
|
|
106
|
+
.split(/[^0-9A-Za-z]+/)
|
|
107
|
+
.map((token) => token.trim())
|
|
108
|
+
.filter(Boolean)
|
|
109
|
+
.map((token) => (/^\d+$/.test(token) ? Number(token) : token.toLowerCase()));
|
|
110
|
+
}
|
|
111
|
+
function compareVersionTokens(left, right) {
|
|
112
|
+
const leftTokens = tokenizeVersion(left);
|
|
113
|
+
const rightTokens = tokenizeVersion(right);
|
|
114
|
+
const maxLength = Math.max(leftTokens.length, rightTokens.length);
|
|
115
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
116
|
+
const leftToken = leftTokens[index];
|
|
117
|
+
const rightToken = rightTokens[index];
|
|
118
|
+
if (leftToken === undefined && rightToken === undefined)
|
|
119
|
+
return 0;
|
|
120
|
+
if (leftToken === undefined)
|
|
121
|
+
return -1;
|
|
122
|
+
if (rightToken === undefined)
|
|
123
|
+
return 1;
|
|
124
|
+
if (typeof leftToken === "number" && typeof rightToken === "number") {
|
|
125
|
+
if (leftToken !== rightToken)
|
|
126
|
+
return leftToken > rightToken ? 1 : -1;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const leftText = String(leftToken);
|
|
130
|
+
const rightText = String(rightToken);
|
|
131
|
+
if (leftText !== rightText)
|
|
132
|
+
return leftText.localeCompare(rightText);
|
|
133
|
+
}
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
82
136
|
function resolveWorkspaceRoot(cwd = process.cwd()) {
|
|
83
137
|
if ((0, fs_1.existsSync)((0, path_1.resolve)(cwd, "apps", "local-console", "package.json"))) {
|
|
84
138
|
return cwd;
|
|
@@ -89,13 +143,43 @@ function resolveWorkspaceRoot(cwd = process.cwd()) {
|
|
|
89
143
|
}
|
|
90
144
|
return cwd;
|
|
91
145
|
}
|
|
146
|
+
function resolveProjectRoot(appRoot, cwd = process.cwd()) {
|
|
147
|
+
const envAppRoot = String(process.env.SILICACLAW_APP_DIR || "").trim();
|
|
148
|
+
if (envAppRoot &&
|
|
149
|
+
(0, fs_1.existsSync)((0, path_1.resolve)(envAppRoot, "apps", "local-console", "package.json")) &&
|
|
150
|
+
(0, fs_1.existsSync)((0, path_1.resolve)(envAppRoot, "package.json"))) {
|
|
151
|
+
return (0, path_1.resolve)(envAppRoot);
|
|
152
|
+
}
|
|
153
|
+
const envRoot = String(process.env.SILICACLAW_WORKSPACE_DIR || "").trim();
|
|
154
|
+
if (envRoot) {
|
|
155
|
+
return (0, path_1.resolve)(envRoot);
|
|
156
|
+
}
|
|
157
|
+
if ((0, fs_1.existsSync)((0, path_1.resolve)(appRoot, "apps", "local-console", "package.json")) &&
|
|
158
|
+
(0, fs_1.existsSync)((0, path_1.resolve)(appRoot, "package.json"))) {
|
|
159
|
+
return appRoot;
|
|
160
|
+
}
|
|
161
|
+
if (!(0, fs_1.existsSync)((0, path_1.resolve)(cwd, "apps", "local-console", "package.json"))) {
|
|
162
|
+
return (0, path_1.resolve)(cwd);
|
|
163
|
+
}
|
|
164
|
+
return appRoot;
|
|
165
|
+
}
|
|
92
166
|
function resolveStorageRoot(workspaceRoot, cwd = process.cwd()) {
|
|
167
|
+
const home = process.env.HOME || (0, os_1.homedir)();
|
|
168
|
+
if (home) {
|
|
169
|
+
return (0, path_1.resolve)(home, ".silicaclaw", "local-console");
|
|
170
|
+
}
|
|
93
171
|
const appRoot = (0, path_1.resolve)(workspaceRoot, "apps", "local-console");
|
|
94
172
|
if ((0, fs_1.existsSync)((0, path_1.resolve)(appRoot, "package.json"))) {
|
|
95
173
|
return appRoot;
|
|
96
174
|
}
|
|
97
175
|
return cwd;
|
|
98
176
|
}
|
|
177
|
+
function defaultOpenClawSourceDir(rootDir) {
|
|
178
|
+
if ((0, fs_1.existsSync)((0, path_1.resolve)(rootDir, "openclaw.mjs")) || (0, fs_1.existsSync)((0, path_1.resolve)(rootDir, "package.json"))) {
|
|
179
|
+
return rootDir;
|
|
180
|
+
}
|
|
181
|
+
return (0, path_1.resolve)(rootDir, "..", "openclaw");
|
|
182
|
+
}
|
|
99
183
|
function resolveExecutableInPath(binName) {
|
|
100
184
|
const pathValue = String(process.env.PATH || "").trim();
|
|
101
185
|
if (!pathValue)
|
|
@@ -162,6 +246,54 @@ function summarizeSkillReadme(filePath) {
|
|
|
162
246
|
return "";
|
|
163
247
|
}
|
|
164
248
|
}
|
|
249
|
+
function readDialogueCheatsheetPreview(filePath, limit = 6) {
|
|
250
|
+
if (!filePath || !(0, fs_1.existsSync)(filePath))
|
|
251
|
+
return [];
|
|
252
|
+
try {
|
|
253
|
+
return (0, fs_1.readFileSync)(filePath, "utf8")
|
|
254
|
+
.split(/\r?\n/)
|
|
255
|
+
.map((line) => line.trim())
|
|
256
|
+
.filter((line) => line.startsWith("- "))
|
|
257
|
+
.map((line) => line.slice(2).trim())
|
|
258
|
+
.filter(Boolean)
|
|
259
|
+
.slice(0, limit);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return [];
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function readDialogueCheatsheetSections(filePath, maxSections = 3, maxItemsPerSection = 5) {
|
|
266
|
+
if (!filePath || !(0, fs_1.existsSync)(filePath))
|
|
267
|
+
return [];
|
|
268
|
+
try {
|
|
269
|
+
const lines = (0, fs_1.readFileSync)(filePath, "utf8").split(/\r?\n/);
|
|
270
|
+
const sections = [];
|
|
271
|
+
let current = null;
|
|
272
|
+
for (const rawLine of lines) {
|
|
273
|
+
const line = rawLine.trim();
|
|
274
|
+
if (line.startsWith("## ")) {
|
|
275
|
+
if (current && current.items.length)
|
|
276
|
+
sections.push(current);
|
|
277
|
+
current = { title: line.slice(3).trim(), items: [] };
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
if (line.startsWith("- ")) {
|
|
281
|
+
if (!current) {
|
|
282
|
+
current = { title: "Examples", items: [] };
|
|
283
|
+
}
|
|
284
|
+
if (current.items.length < maxItemsPerSection) {
|
|
285
|
+
current.items.push(line.slice(2).trim());
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (current && current.items.length)
|
|
290
|
+
sections.push(current);
|
|
291
|
+
return sections.slice(0, maxSections);
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
return [];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
165
297
|
function detectOpenClawInstallation(workspaceRoot) {
|
|
166
298
|
const workspaceDir = (0, path_1.resolve)(workspaceRoot, ".openclaw");
|
|
167
299
|
const homeDir = (0, path_1.resolve)(process.env.HOME || "", ".openclaw");
|
|
@@ -206,7 +338,7 @@ function detectOpenClawInstallation(workspaceRoot) {
|
|
|
206
338
|
}
|
|
207
339
|
function readOpenClawConfiguredGateway(workspaceRoot) {
|
|
208
340
|
const configuredSourceDir = String(process.env.OPENCLAW_SOURCE_DIR || "").trim();
|
|
209
|
-
const defaultSourceDir = (
|
|
341
|
+
const defaultSourceDir = defaultOpenClawSourceDir(workspaceRoot);
|
|
210
342
|
const sourceDir = configuredSourceDir || defaultSourceDir;
|
|
211
343
|
const homeDir = (0, path_1.resolve)(process.env.HOME || "", ".openclaw");
|
|
212
344
|
const explicitConfigPath = String(process.env.OPENCLAW_CONFIG_PATH || "").trim();
|
|
@@ -384,7 +516,7 @@ function detectOwnerDeliveryStatus(params) {
|
|
|
384
516
|
const ownerAccount = String(process.env.OPENCLAW_OWNER_ACCOUNT || "").trim();
|
|
385
517
|
const explicitOpenClawBin = String(process.env.OPENCLAW_BIN || "").trim();
|
|
386
518
|
const configuredSourceDir = String(process.env.OPENCLAW_SOURCE_DIR || "").trim();
|
|
387
|
-
const defaultSourceDir = (
|
|
519
|
+
const defaultSourceDir = defaultOpenClawSourceDir(params.workspaceRoot);
|
|
388
520
|
const openclawSourceDir = configuredSourceDir || defaultSourceDir;
|
|
389
521
|
const openclawSourceEntry = existingPathOrNull((0, path_1.resolve)(openclawSourceDir, "openclaw.mjs"));
|
|
390
522
|
const openclawCommandResolvable = Boolean(explicitOpenClawBin || resolveExecutableInPath("openclaw") || openclawSourceEntry);
|
|
@@ -450,11 +582,18 @@ function hasMeaningfulJson(filePath) {
|
|
|
450
582
|
return false;
|
|
451
583
|
}
|
|
452
584
|
}
|
|
453
|
-
function migrateLegacyDataIfNeeded(
|
|
454
|
-
const
|
|
585
|
+
function migrateLegacyDataIfNeeded(appRoot, projectRoot, storageRoot) {
|
|
586
|
+
const homeDir = process.env.HOME || (0, os_1.homedir)();
|
|
587
|
+
const legacyNpxAppRoots = collectLegacyNpxAppRoots(homeDir);
|
|
455
588
|
const targetDataDir = (0, path_1.resolve)(storageRoot, "data");
|
|
456
|
-
|
|
457
|
-
|
|
589
|
+
const legacyDataDirs = [
|
|
590
|
+
(0, path_1.resolve)(appRoot, "data"),
|
|
591
|
+
(0, path_1.resolve)(appRoot, "apps", "local-console", "data"),
|
|
592
|
+
(0, path_1.resolve)(projectRoot, "data"),
|
|
593
|
+
(0, path_1.resolve)(projectRoot, "apps", "local-console", "data"),
|
|
594
|
+
(0, path_1.resolve)(process.cwd(), "data"),
|
|
595
|
+
...legacyNpxAppRoots.map((root) => (0, path_1.resolve)(root, "apps", "local-console", "data")),
|
|
596
|
+
].filter((dir, index, list) => list.indexOf(dir) === index && dir !== targetDataDir);
|
|
458
597
|
const files = [
|
|
459
598
|
"identity.json",
|
|
460
599
|
"profile.json",
|
|
@@ -464,17 +603,70 @@ function migrateLegacyDataIfNeeded(workspaceRoot, storageRoot) {
|
|
|
464
603
|
"social-message-observations.json",
|
|
465
604
|
];
|
|
466
605
|
for (const file of files) {
|
|
467
|
-
const src = (0, path_1.resolve)(legacyDataDir, file);
|
|
468
606
|
const dst = (0, path_1.resolve)(targetDataDir, file);
|
|
469
|
-
if (
|
|
607
|
+
if (hasMeaningfulJson(dst))
|
|
470
608
|
continue;
|
|
609
|
+
for (const legacyDataDir of legacyDataDirs) {
|
|
610
|
+
const src = (0, path_1.resolve)(legacyDataDir, file);
|
|
611
|
+
if (!(0, fs_1.existsSync)(src))
|
|
612
|
+
continue;
|
|
613
|
+
if (!hasMeaningfulJson(src))
|
|
614
|
+
continue;
|
|
615
|
+
(0, fs_1.mkdirSync)(targetDataDir, { recursive: true });
|
|
616
|
+
(0, fs_1.copyFileSync)(src, dst);
|
|
617
|
+
break;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
const targetDotDir = (0, path_1.resolve)(storageRoot, ".silicaclaw");
|
|
621
|
+
const legacyDotDirs = [
|
|
622
|
+
(0, path_1.resolve)(appRoot, ".silicaclaw"),
|
|
623
|
+
(0, path_1.resolve)(appRoot, "apps", "local-console", ".silicaclaw"),
|
|
624
|
+
(0, path_1.resolve)(projectRoot, ".silicaclaw"),
|
|
625
|
+
(0, path_1.resolve)(projectRoot, "apps", "local-console", ".silicaclaw"),
|
|
626
|
+
(0, path_1.resolve)(process.cwd(), ".silicaclaw"),
|
|
627
|
+
...legacyNpxAppRoots.map((root) => (0, path_1.resolve)(root, "apps", "local-console", ".silicaclaw")),
|
|
628
|
+
].filter((dir, index, list) => list.indexOf(dir) === index && dir !== targetDotDir);
|
|
629
|
+
const dotFiles = ["social.runtime.json", "social.message-governance.json"];
|
|
630
|
+
for (const file of dotFiles) {
|
|
631
|
+
const dst = (0, path_1.resolve)(targetDotDir, file);
|
|
471
632
|
if (hasMeaningfulJson(dst))
|
|
472
633
|
continue;
|
|
473
|
-
|
|
634
|
+
for (const legacyDotDir of legacyDotDirs) {
|
|
635
|
+
const src = (0, path_1.resolve)(legacyDotDir, file);
|
|
636
|
+
if (!(0, fs_1.existsSync)(src))
|
|
637
|
+
continue;
|
|
638
|
+
if (!hasMeaningfulJson(src))
|
|
639
|
+
continue;
|
|
640
|
+
(0, fs_1.mkdirSync)(targetDotDir, { recursive: true });
|
|
641
|
+
(0, fs_1.copyFileSync)(src, dst);
|
|
642
|
+
break;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
function collectLegacyNpxAppRoots(homeDir) {
|
|
647
|
+
const cacheRoots = [
|
|
648
|
+
(0, path_1.resolve)(homeDir, ".silicaclaw", "npm-cache", "_npx"),
|
|
649
|
+
(0, path_1.resolve)(homeDir, ".npm", "_npx"),
|
|
650
|
+
];
|
|
651
|
+
const roots = [];
|
|
652
|
+
for (const cacheRoot of cacheRoots) {
|
|
653
|
+
if (!(0, fs_1.existsSync)(cacheRoot))
|
|
654
|
+
continue;
|
|
655
|
+
let entries = [];
|
|
656
|
+
try {
|
|
657
|
+
entries = (0, fs_1.readdirSync)(cacheRoot);
|
|
658
|
+
}
|
|
659
|
+
catch {
|
|
474
660
|
continue;
|
|
475
|
-
|
|
476
|
-
(
|
|
661
|
+
}
|
|
662
|
+
for (const entry of entries) {
|
|
663
|
+
const candidate = (0, path_1.resolve)(cacheRoot, entry, "node_modules", "@silicaclaw", "cli");
|
|
664
|
+
if (!(0, fs_1.existsSync)((0, path_1.resolve)(candidate, "apps", "local-console")))
|
|
665
|
+
continue;
|
|
666
|
+
roots.push(candidate);
|
|
667
|
+
}
|
|
477
668
|
}
|
|
669
|
+
return Array.from(new Set(roots));
|
|
478
670
|
}
|
|
479
671
|
function parseListEnv(raw) {
|
|
480
672
|
return raw
|
|
@@ -487,6 +679,7 @@ function dedupeStrings(values) {
|
|
|
487
679
|
}
|
|
488
680
|
class LocalNodeService {
|
|
489
681
|
workspaceRoot;
|
|
682
|
+
projectRoot;
|
|
490
683
|
storageRoot;
|
|
491
684
|
identityRepo;
|
|
492
685
|
profileRepo;
|
|
@@ -524,7 +717,7 @@ class LocalNodeService {
|
|
|
524
717
|
};
|
|
525
718
|
network;
|
|
526
719
|
adapterMode;
|
|
527
|
-
networkMode =
|
|
720
|
+
networkMode = DEFAULT_NETWORK_MODE;
|
|
528
721
|
networkNamespace;
|
|
529
722
|
networkPort;
|
|
530
723
|
socialConfig;
|
|
@@ -537,16 +730,21 @@ class LocalNodeService {
|
|
|
537
730
|
resolvedIdentitySource = "silicaclaw-existing";
|
|
538
731
|
resolvedOpenClawIdentityPath = null;
|
|
539
732
|
webrtcSignalingUrls = [];
|
|
540
|
-
webrtcRoom =
|
|
733
|
+
webrtcRoom = DEFAULT_GLOBAL_ROOM;
|
|
541
734
|
webrtcSeedPeers = [];
|
|
542
735
|
webrtcBootstrapHints = [];
|
|
543
736
|
webrtcBootstrapSources = [];
|
|
737
|
+
networkStarted = false;
|
|
738
|
+
networkStartupError = null;
|
|
739
|
+
networkReconnectTimer = null;
|
|
740
|
+
networkReconnectDelayMs = 5_000;
|
|
544
741
|
appVersion = "unknown";
|
|
545
742
|
constructor(options) {
|
|
546
743
|
this.workspaceRoot = options?.workspaceRoot || resolveWorkspaceRoot();
|
|
744
|
+
this.projectRoot = options?.projectRoot || resolveProjectRoot(this.workspaceRoot);
|
|
547
745
|
this.storageRoot = options?.storageRoot || resolveStorageRoot(this.workspaceRoot);
|
|
548
746
|
this.appVersion = readWorkspaceVersion(this.workspaceRoot);
|
|
549
|
-
migrateLegacyDataIfNeeded(this.workspaceRoot, this.storageRoot);
|
|
747
|
+
migrateLegacyDataIfNeeded(this.workspaceRoot, this.projectRoot, this.storageRoot);
|
|
550
748
|
this.identityRepo = new storage_1.IdentityRepo(this.storageRoot);
|
|
551
749
|
this.profileRepo = new storage_1.ProfileRepo(this.storageRoot);
|
|
552
750
|
this.cacheRepo = new storage_1.CacheRepo(this.storageRoot);
|
|
@@ -556,16 +754,16 @@ class LocalNodeService {
|
|
|
556
754
|
this.socialMessageObservationRepo = new storage_1.SocialMessageObservationRepo(this.storageRoot);
|
|
557
755
|
this.socialRuntimeRepo = new storage_1.SocialRuntimeRepo(this.storageRoot);
|
|
558
756
|
this.messageGovernance = this.defaultMessageGovernance();
|
|
559
|
-
let loadedSocial = (0, core_1.loadSocialConfig)(this.
|
|
757
|
+
let loadedSocial = (0, core_1.loadSocialConfig)(this.projectRoot);
|
|
560
758
|
if (!loadedSocial.meta.found) {
|
|
561
|
-
(0, core_1.ensureDefaultSocialMd)(this.
|
|
759
|
+
(0, core_1.ensureDefaultSocialMd)(this.projectRoot, {
|
|
562
760
|
display_name: this.getDefaultDisplayName(),
|
|
563
761
|
bio: "Local AI agent connected to SilicaClaw",
|
|
564
762
|
tags: ["openclaw", "local-first"],
|
|
565
|
-
mode:
|
|
763
|
+
mode: DEFAULT_NETWORK_MODE,
|
|
566
764
|
public_enabled: false,
|
|
567
765
|
});
|
|
568
|
-
loadedSocial = (0, core_1.loadSocialConfig)(this.
|
|
766
|
+
loadedSocial = (0, core_1.loadSocialConfig)(this.projectRoot);
|
|
569
767
|
this.initState.social_auto_created = true;
|
|
570
768
|
}
|
|
571
769
|
this.socialConfig = loadedSocial.config;
|
|
@@ -573,8 +771,8 @@ class LocalNodeService {
|
|
|
573
771
|
this.socialFound = loadedSocial.meta.found;
|
|
574
772
|
this.socialParseError = loadedSocial.meta.parse_error;
|
|
575
773
|
this.socialRawFrontmatter = loadedSocial.raw_frontmatter;
|
|
576
|
-
this.networkNamespace = this.socialConfig.network.namespace || process.env.NETWORK_NAMESPACE ||
|
|
577
|
-
this.networkPort = Number(this.socialConfig.network.port || process.env.NETWORK_PORT ||
|
|
774
|
+
this.networkNamespace = this.socialConfig.network.namespace || process.env.NETWORK_NAMESPACE || DEFAULT_NETWORK_NAMESPACE;
|
|
775
|
+
this.networkPort = Number(this.socialConfig.network.port || process.env.NETWORK_PORT || DEFAULT_NETWORK_PORT);
|
|
578
776
|
this.applyResolvedNetworkConfig();
|
|
579
777
|
const resolved = this.buildNetworkAdapter();
|
|
580
778
|
this.network = resolved.adapter;
|
|
@@ -584,24 +782,18 @@ class LocalNodeService {
|
|
|
584
782
|
async start() {
|
|
585
783
|
await this.hydrateFromDisk();
|
|
586
784
|
this.bindNetworkSubscriptions();
|
|
587
|
-
await this.
|
|
588
|
-
await this.log("info", `Local node started (${this.adapterMode}, mode=${this.networkMode}, signaling=${this.webrtcSignalingUrls[0] || "-"}, room=${this.webrtcRoom})`);
|
|
589
|
-
if (this.profile?.public_enabled && this.broadcastEnabled) {
|
|
590
|
-
try {
|
|
591
|
-
await this.broadcastNow("adapter_start");
|
|
592
|
-
}
|
|
593
|
-
catch (error) {
|
|
594
|
-
await this.log("warn", `Initial broadcast failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
this.startBroadcastLoop();
|
|
785
|
+
await this.startNetworkAdapterWithRetry("adapter_start");
|
|
598
786
|
}
|
|
599
787
|
async stop() {
|
|
788
|
+
this.clearNetworkReconnectTimer();
|
|
600
789
|
if (this.broadcaster) {
|
|
601
790
|
clearInterval(this.broadcaster);
|
|
602
791
|
this.broadcaster = null;
|
|
603
792
|
}
|
|
604
|
-
|
|
793
|
+
if (this.networkStarted) {
|
|
794
|
+
await this.network.stop();
|
|
795
|
+
}
|
|
796
|
+
this.networkStarted = false;
|
|
605
797
|
}
|
|
606
798
|
ensureLocalDirectoryBaseline() {
|
|
607
799
|
if (this.profile) {
|
|
@@ -614,10 +806,8 @@ class LocalNodeService {
|
|
|
614
806
|
}
|
|
615
807
|
}
|
|
616
808
|
getOverview() {
|
|
617
|
-
this.
|
|
618
|
-
|
|
619
|
-
const profiles = Object.values(this.directory.profiles);
|
|
620
|
-
const onlineCount = profiles.filter((profile) => (0, core_1.isAgentOnline)(this.directory.presence[profile.agent_id], Date.now(), PRESENCE_TTL_MS)).length;
|
|
809
|
+
const discovered = this.search("");
|
|
810
|
+
const onlineCount = discovered.filter((profile) => profile.online).length;
|
|
621
811
|
return {
|
|
622
812
|
app_version: this.appVersion,
|
|
623
813
|
agent_id: this.identity?.agent_id ?? "",
|
|
@@ -627,9 +817,9 @@ class LocalNodeService {
|
|
|
627
817
|
last_broadcast_error_at: this.lastBroadcastErrorAt,
|
|
628
818
|
last_broadcast_error: this.lastBroadcastError,
|
|
629
819
|
broadcast_failure_count: this.broadcastFailureCount,
|
|
630
|
-
discovered_count:
|
|
820
|
+
discovered_count: discovered.length,
|
|
631
821
|
online_count: onlineCount,
|
|
632
|
-
offline_count: Math.max(0,
|
|
822
|
+
offline_count: Math.max(0, discovered.length - onlineCount),
|
|
633
823
|
init_state: this.initState,
|
|
634
824
|
presence_ttl_ms: PRESENCE_TTL_MS,
|
|
635
825
|
onboarding: this.getOnboardingSummary(),
|
|
@@ -650,7 +840,9 @@ class LocalNodeService {
|
|
|
650
840
|
};
|
|
651
841
|
}
|
|
652
842
|
getNetworkSummary() {
|
|
653
|
-
const
|
|
843
|
+
const network = this.getResolvedRealtimeNetworkSummary();
|
|
844
|
+
const diagnostics = network.diagnostics;
|
|
845
|
+
const relayCapable = this.adapterMode === "webrtc-preview" || this.adapterMode === "relay-preview";
|
|
654
846
|
const peerCount = diagnostics?.peers.total ?? 0;
|
|
655
847
|
return {
|
|
656
848
|
status: "running",
|
|
@@ -677,29 +869,33 @@ class LocalNodeService {
|
|
|
677
869
|
real_preview_stats: diagnostics?.stats ?? null,
|
|
678
870
|
real_preview_transport_stats: diagnostics?.transport_stats ?? null,
|
|
679
871
|
real_preview_discovery_stats: diagnostics?.discovery_stats ?? null,
|
|
680
|
-
webrtc_preview:
|
|
872
|
+
webrtc_preview: relayCapable
|
|
681
873
|
? {
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
874
|
+
started: this.networkStarted,
|
|
875
|
+
startup_error: this.networkStartupError,
|
|
876
|
+
signaling_url: network.signaling_url,
|
|
877
|
+
signaling_endpoints: network.signaling_endpoints,
|
|
878
|
+
room: network.room,
|
|
879
|
+
bootstrap_sources: network.bootstrap_sources,
|
|
880
|
+
seed_peers_count: network.seed_peers_count,
|
|
881
|
+
discovery_events_total: diagnostics?.discovery_events_total ?? 0,
|
|
882
|
+
last_discovery_event_at: diagnostics?.last_discovery_event_at ?? 0,
|
|
883
|
+
active_webrtc_peers: diagnostics?.active_webrtc_peers ?? 0,
|
|
884
|
+
reconnect_attempts_total: diagnostics?.reconnect_attempts_total ?? 0,
|
|
885
|
+
last_join_at: diagnostics?.last_join_at ?? 0,
|
|
886
|
+
last_poll_at: diagnostics?.last_poll_at ?? 0,
|
|
887
|
+
last_publish_at: diagnostics?.last_publish_at ?? 0,
|
|
888
|
+
last_peer_refresh_at: diagnostics?.last_peer_refresh_at ?? 0,
|
|
889
|
+
last_error_at: diagnostics?.last_error_at ?? 0,
|
|
890
|
+
last_error: diagnostics?.last_error ?? null,
|
|
697
891
|
}
|
|
698
892
|
: null,
|
|
699
893
|
};
|
|
700
894
|
}
|
|
701
895
|
getNetworkConfig() {
|
|
702
|
-
const
|
|
896
|
+
const network = this.getResolvedRealtimeNetworkSummary();
|
|
897
|
+
const diagnostics = network.diagnostics;
|
|
898
|
+
const relayCapable = this.adapterMode === "webrtc-preview" || this.adapterMode === "relay-preview";
|
|
703
899
|
return {
|
|
704
900
|
adapter: this.adapterMode,
|
|
705
901
|
mode: this.networkMode,
|
|
@@ -713,23 +909,25 @@ class LocalNodeService {
|
|
|
713
909
|
},
|
|
714
910
|
limits: diagnostics?.limits ?? null,
|
|
715
911
|
adapter_config: diagnostics?.config ?? null,
|
|
716
|
-
adapter_extra:
|
|
912
|
+
adapter_extra: relayCapable
|
|
717
913
|
? {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
914
|
+
started: this.networkStarted,
|
|
915
|
+
startup_error: this.networkStartupError,
|
|
916
|
+
signaling_url: network.signaling_url,
|
|
917
|
+
signaling_endpoints: network.signaling_endpoints,
|
|
918
|
+
room: network.room,
|
|
919
|
+
bootstrap_sources: network.bootstrap_sources,
|
|
920
|
+
seed_peers_count: network.seed_peers_count,
|
|
921
|
+
discovery_events_total: diagnostics?.discovery_events_total ?? 0,
|
|
922
|
+
last_discovery_event_at: diagnostics?.last_discovery_event_at ?? 0,
|
|
923
|
+
connection_states_summary: diagnostics?.connection_states_summary ?? null,
|
|
924
|
+
datachannel_states_summary: diagnostics?.datachannel_states_summary ?? null,
|
|
925
|
+
last_join_at: diagnostics?.last_join_at ?? 0,
|
|
926
|
+
last_poll_at: diagnostics?.last_poll_at ?? 0,
|
|
927
|
+
last_publish_at: diagnostics?.last_publish_at ?? 0,
|
|
928
|
+
last_peer_refresh_at: diagnostics?.last_peer_refresh_at ?? 0,
|
|
929
|
+
last_error_at: diagnostics?.last_error_at ?? 0,
|
|
930
|
+
last_error: diagnostics?.last_error ?? null,
|
|
733
931
|
}
|
|
734
932
|
: null,
|
|
735
933
|
env: {
|
|
@@ -756,13 +954,15 @@ class LocalNodeService {
|
|
|
756
954
|
demo_mode: this.adapterMode === "real-preview"
|
|
757
955
|
? "lan-preview"
|
|
758
956
|
: this.adapterMode === "webrtc-preview" || this.adapterMode === "relay-preview"
|
|
759
|
-
? "
|
|
957
|
+
? "global-preview"
|
|
760
958
|
: "local-process",
|
|
761
959
|
mode_explainer: this.getModeExplainer(),
|
|
762
960
|
};
|
|
763
961
|
}
|
|
764
962
|
getNetworkStats() {
|
|
765
|
-
const
|
|
963
|
+
const network = this.getResolvedRealtimeNetworkSummary();
|
|
964
|
+
const diagnostics = network.diagnostics;
|
|
965
|
+
const relayCapable = this.adapterMode === "webrtc-preview" || this.adapterMode === "relay-preview";
|
|
766
966
|
const peers = diagnostics?.peers?.items ?? [];
|
|
767
967
|
const online = peers.filter((peer) => peer.status === "online").length;
|
|
768
968
|
return {
|
|
@@ -788,33 +988,36 @@ class LocalNodeService {
|
|
|
788
988
|
adapter_stats: diagnostics?.stats ?? null,
|
|
789
989
|
adapter_transport_stats: diagnostics?.transport_stats ?? null,
|
|
790
990
|
adapter_discovery_stats: diagnostics?.discovery_stats ?? null,
|
|
791
|
-
adapter_diagnostics_summary: diagnostics
|
|
991
|
+
adapter_diagnostics_summary: relayCapable || diagnostics
|
|
792
992
|
? {
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
993
|
+
started: this.networkStarted,
|
|
994
|
+
startup_error: this.networkStartupError,
|
|
995
|
+
signaling_url: network.signaling_url,
|
|
996
|
+
signaling_endpoints: network.signaling_endpoints,
|
|
997
|
+
room: network.room,
|
|
998
|
+
bootstrap_sources: network.bootstrap_sources,
|
|
999
|
+
seed_peers_count: network.seed_peers_count,
|
|
1000
|
+
discovery_events_total: diagnostics?.discovery_events_total ?? 0,
|
|
1001
|
+
last_discovery_event_at: diagnostics?.last_discovery_event_at ?? 0,
|
|
1002
|
+
connection_states_summary: diagnostics?.connection_states_summary ?? null,
|
|
1003
|
+
datachannel_states_summary: diagnostics?.datachannel_states_summary ?? null,
|
|
1004
|
+
signaling_messages_sent_total: diagnostics?.signaling_messages_sent_total ?? null,
|
|
1005
|
+
signaling_messages_received_total: diagnostics?.signaling_messages_received_total ?? null,
|
|
1006
|
+
reconnect_attempts_total: diagnostics?.reconnect_attempts_total ?? null,
|
|
1007
|
+
active_webrtc_peers: diagnostics?.active_webrtc_peers ?? null,
|
|
1008
|
+
last_join_at: diagnostics?.last_join_at ?? 0,
|
|
1009
|
+
last_poll_at: diagnostics?.last_poll_at ?? 0,
|
|
1010
|
+
last_publish_at: diagnostics?.last_publish_at ?? 0,
|
|
1011
|
+
last_peer_refresh_at: diagnostics?.last_peer_refresh_at ?? 0,
|
|
1012
|
+
last_error_at: diagnostics?.last_error_at ?? 0,
|
|
1013
|
+
last_error: diagnostics?.last_error ?? null,
|
|
812
1014
|
}
|
|
813
1015
|
: null,
|
|
814
1016
|
};
|
|
815
1017
|
}
|
|
816
1018
|
getPeersSummary() {
|
|
817
|
-
const
|
|
1019
|
+
const network = this.getResolvedRealtimeNetworkSummary();
|
|
1020
|
+
const diagnostics = network.diagnostics;
|
|
818
1021
|
if (!diagnostics) {
|
|
819
1022
|
return {
|
|
820
1023
|
adapter: this.adapterMode,
|
|
@@ -837,11 +1040,13 @@ class LocalNodeService {
|
|
|
837
1040
|
components: diagnostics.components,
|
|
838
1041
|
limits: diagnostics.limits,
|
|
839
1042
|
diagnostics_summary: {
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
1043
|
+
started: this.networkStarted,
|
|
1044
|
+
startup_error: this.networkStartupError,
|
|
1045
|
+
signaling_url: network.signaling_url,
|
|
1046
|
+
signaling_endpoints: network.signaling_endpoints,
|
|
1047
|
+
room: network.room,
|
|
1048
|
+
bootstrap_sources: network.bootstrap_sources,
|
|
1049
|
+
seed_peers_count: network.seed_peers_count,
|
|
845
1050
|
discovery_events_total: diagnostics.discovery_events_total ?? 0,
|
|
846
1051
|
last_discovery_event_at: diagnostics.last_discovery_event_at ?? 0,
|
|
847
1052
|
connection_states_summary: diagnostics.connection_states_summary ?? null,
|
|
@@ -885,11 +1090,12 @@ class LocalNodeService {
|
|
|
885
1090
|
getRuntimePaths() {
|
|
886
1091
|
return {
|
|
887
1092
|
workspace_root: this.workspaceRoot,
|
|
1093
|
+
project_root: this.projectRoot,
|
|
888
1094
|
storage_root: this.storageRoot,
|
|
889
1095
|
data_dir: (0, path_1.resolve)(this.storageRoot, "data"),
|
|
890
1096
|
social_runtime_path: (0, path_1.resolve)(this.storageRoot, ".silicaclaw", "social.runtime.json"),
|
|
891
1097
|
local_console_public_dir: (0, path_1.resolve)(this.workspaceRoot, "apps", "local-console", "public"),
|
|
892
|
-
social_lookup_paths: (0, core_1.getSocialConfigSearchPaths)(this.
|
|
1098
|
+
social_lookup_paths: (0, core_1.getSocialConfigSearchPaths)(this.projectRoot),
|
|
893
1099
|
social_source_path: this.socialSourcePath,
|
|
894
1100
|
};
|
|
895
1101
|
}
|
|
@@ -925,9 +1131,10 @@ class LocalNodeService {
|
|
|
925
1131
|
}
|
|
926
1132
|
getIntegrationStatus() {
|
|
927
1133
|
const runtimeGenerated = Boolean(this.socialRuntime && this.socialRuntime.last_loaded_at > 0);
|
|
928
|
-
const
|
|
929
|
-
const
|
|
930
|
-
const
|
|
1134
|
+
const runtimeReady = this.socialFound && runtimeGenerated && !this.socialParseError;
|
|
1135
|
+
const connected = runtimeReady && this.networkStarted;
|
|
1136
|
+
const configured = runtimeReady && this.socialConfig.enabled;
|
|
1137
|
+
const running = configured && this.broadcastEnabled && this.networkStarted;
|
|
931
1138
|
const publicEnabled = Boolean(this.profile?.public_enabled);
|
|
932
1139
|
const discoveryEnabled = this.socialConfig.discovery.discoverable &&
|
|
933
1140
|
this.socialConfig.discovery.allow_profile_broadcast &&
|
|
@@ -946,9 +1153,13 @@ class LocalNodeService {
|
|
|
946
1153
|
? "running"
|
|
947
1154
|
: !configured
|
|
948
1155
|
? "not configured"
|
|
949
|
-
:
|
|
950
|
-
? "
|
|
951
|
-
:
|
|
1156
|
+
: this.networkReconnectTimer
|
|
1157
|
+
? "reconnecting to relay"
|
|
1158
|
+
: this.networkStartupError
|
|
1159
|
+
? this.networkStartupError
|
|
1160
|
+
: !this.broadcastEnabled
|
|
1161
|
+
? "broadcast paused"
|
|
1162
|
+
: "not running";
|
|
952
1163
|
const discoverableReason = discoverable
|
|
953
1164
|
? "discoverable"
|
|
954
1165
|
: !running
|
|
@@ -987,20 +1198,32 @@ class LocalNodeService {
|
|
|
987
1198
|
};
|
|
988
1199
|
}
|
|
989
1200
|
async setNetworkModeRuntime(mode) {
|
|
990
|
-
const
|
|
1201
|
+
const before = {
|
|
1202
|
+
mode: this.networkMode,
|
|
1203
|
+
adapter: this.adapterMode,
|
|
1204
|
+
namespace: this.networkNamespace,
|
|
1205
|
+
port: this.networkPort,
|
|
1206
|
+
};
|
|
991
1207
|
if (mode !== "local" && mode !== "lan" && mode !== "global-preview") {
|
|
992
1208
|
throw new Error("invalid_network_mode");
|
|
993
1209
|
}
|
|
994
1210
|
this.socialConfig.network.mode = mode;
|
|
995
1211
|
this.socialConfig.network.adapter = this.adapterForMode(mode);
|
|
996
1212
|
this.applyResolvedNetworkConfig();
|
|
997
|
-
|
|
1213
|
+
const needsRestart = before.mode !== this.networkMode ||
|
|
1214
|
+
before.adapter !== this.socialConfig.network.adapter ||
|
|
1215
|
+
before.namespace !== this.networkNamespace ||
|
|
1216
|
+
(before.port ?? null) !== (this.networkPort ?? null);
|
|
1217
|
+
if (needsRestart) {
|
|
1218
|
+
await this.restartNetworkAdapter("set_network_mode_runtime");
|
|
1219
|
+
}
|
|
1220
|
+
this.socialNetworkRequiresRestart = false;
|
|
998
1221
|
await this.writeSocialRuntime();
|
|
999
1222
|
return {
|
|
1000
1223
|
mode: this.networkMode,
|
|
1001
|
-
adapter: this.
|
|
1002
|
-
network_requires_restart:
|
|
1003
|
-
note: "Runtime mode updated. Existing social.md is unchanged.",
|
|
1224
|
+
adapter: this.adapterMode,
|
|
1225
|
+
network_requires_restart: false,
|
|
1226
|
+
note: "Runtime mode updated and adapter restarted. Existing social.md is unchanged.",
|
|
1004
1227
|
};
|
|
1005
1228
|
}
|
|
1006
1229
|
async quickConnectGlobalPreview(options) {
|
|
@@ -1013,7 +1236,7 @@ class LocalNodeService {
|
|
|
1013
1236
|
this.socialConfig.network.adapter = "relay-preview";
|
|
1014
1237
|
this.socialConfig.network.signaling_url = signalingUrl;
|
|
1015
1238
|
this.socialConfig.network.signaling_urls = [signalingUrl];
|
|
1016
|
-
this.socialConfig.network.room = room ||
|
|
1239
|
+
this.socialConfig.network.room = room || DEFAULT_GLOBAL_ROOM;
|
|
1017
1240
|
this.applyResolvedNetworkConfig();
|
|
1018
1241
|
await this.restartNetworkAdapter("quick_connect_global_preview");
|
|
1019
1242
|
this.socialNetworkRequiresRestart = false;
|
|
@@ -1035,7 +1258,7 @@ class LocalNodeService {
|
|
|
1035
1258
|
namespace: this.networkNamespace,
|
|
1036
1259
|
port: this.networkPort,
|
|
1037
1260
|
};
|
|
1038
|
-
const loaded = (0, core_1.loadSocialConfig)(this.
|
|
1261
|
+
const loaded = (0, core_1.loadSocialConfig)(this.projectRoot);
|
|
1039
1262
|
this.socialConfig = loaded.config;
|
|
1040
1263
|
this.socialSourcePath = loaded.meta.source_path;
|
|
1041
1264
|
this.socialFound = loaded.meta.found;
|
|
@@ -1054,11 +1277,15 @@ class LocalNodeService {
|
|
|
1054
1277
|
before.adapter !== after.adapter ||
|
|
1055
1278
|
before.namespace !== after.namespace ||
|
|
1056
1279
|
(before.port ?? null) !== (after.port ?? null);
|
|
1280
|
+
if (this.socialNetworkRequiresRestart) {
|
|
1281
|
+
await this.restartNetworkAdapter("reload_social_config");
|
|
1282
|
+
this.socialNetworkRequiresRestart = false;
|
|
1283
|
+
}
|
|
1057
1284
|
await this.writeSocialRuntime();
|
|
1058
1285
|
return this.getSocialConfigView();
|
|
1059
1286
|
}
|
|
1060
1287
|
async generateDefaultSocialMd() {
|
|
1061
|
-
const result = (0, core_1.ensureDefaultSocialMd)(this.
|
|
1288
|
+
const result = (0, core_1.ensureDefaultSocialMd)(this.projectRoot, {
|
|
1062
1289
|
display_name: this.getDefaultDisplayName(),
|
|
1063
1290
|
bio: "Local AI agent connected to SilicaClaw",
|
|
1064
1291
|
tags: ["openclaw", "local-first"],
|
|
@@ -1082,10 +1309,11 @@ class LocalNodeService {
|
|
|
1082
1309
|
search(keyword) {
|
|
1083
1310
|
this.ensureLocalDirectoryBaseline();
|
|
1084
1311
|
this.compactCacheInMemory();
|
|
1085
|
-
|
|
1312
|
+
const directMatches = (0, core_1.searchDirectory)(this.directory, keyword, { presenceTTLms: PRESENCE_TTL_MS }).map((profile) => {
|
|
1086
1313
|
const lastSeenAt = this.directory.presence[profile.agent_id] ?? 0;
|
|
1087
1314
|
return this.toPublicProfileSummary(profile, { last_seen_at: lastSeenAt });
|
|
1088
1315
|
});
|
|
1316
|
+
return this.mergeMessageOnlyAgentSummaries(directMatches, keyword);
|
|
1089
1317
|
}
|
|
1090
1318
|
getPublicProfilePreview() {
|
|
1091
1319
|
if (!this.profile) {
|
|
@@ -1147,11 +1375,11 @@ class LocalNodeService {
|
|
|
1147
1375
|
}
|
|
1148
1376
|
getOpenClawBridgeStatus() {
|
|
1149
1377
|
const integration = this.getIntegrationStatus();
|
|
1150
|
-
const openclawInstallation = detectOpenClawInstallation(this.
|
|
1151
|
-
const openclawRuntime = detectOpenClawRuntime(this.
|
|
1378
|
+
const openclawInstallation = detectOpenClawInstallation(this.projectRoot);
|
|
1379
|
+
const openclawRuntime = detectOpenClawRuntime(this.projectRoot);
|
|
1152
1380
|
const skillInstallation = detectOpenClawSkillInstallation();
|
|
1153
1381
|
const ownerDelivery = detectOwnerDeliveryStatus({
|
|
1154
|
-
workspaceRoot: this.
|
|
1382
|
+
workspaceRoot: this.projectRoot,
|
|
1155
1383
|
connectedToSilicaclaw: integration.connected_to_silicaclaw,
|
|
1156
1384
|
openclawRunning: openclawRuntime.running,
|
|
1157
1385
|
skillInstalled: skillInstallation.installed,
|
|
@@ -1213,11 +1441,15 @@ class LocalNodeService {
|
|
|
1213
1441
|
},
|
|
1214
1442
|
};
|
|
1215
1443
|
}
|
|
1216
|
-
async installOpenClawSkill() {
|
|
1444
|
+
async installOpenClawSkill(skillName) {
|
|
1217
1445
|
const scriptPath = (0, path_1.resolve)(this.workspaceRoot, "scripts", "install-openclaw-skill.mjs");
|
|
1218
|
-
const
|
|
1446
|
+
const args = [scriptPath];
|
|
1447
|
+
if (skillName) {
|
|
1448
|
+
args.push(`--skill=${skillName}`);
|
|
1449
|
+
}
|
|
1450
|
+
const { stdout } = await execFileAsync(process.execPath, args, {
|
|
1219
1451
|
cwd: this.workspaceRoot,
|
|
1220
|
-
env: process.env,
|
|
1452
|
+
env: { ...process.env, SILICACLAW_WORKSPACE_DIR: this.projectRoot },
|
|
1221
1453
|
maxBuffer: 1024 * 1024,
|
|
1222
1454
|
});
|
|
1223
1455
|
const parsed = JSON.parse(String(stdout || "{}"));
|
|
@@ -1239,11 +1471,11 @@ class LocalNodeService {
|
|
|
1239
1471
|
const homeDir = (0, path_1.resolve)(process.env.HOME || "", ".openclaw");
|
|
1240
1472
|
const workspaceSkillDir = (0, path_1.resolve)(homeDir, "workspace", "skills");
|
|
1241
1473
|
const legacySkillDir = (0, path_1.resolve)(homeDir, "skills");
|
|
1242
|
-
const openclawSourceDir = (
|
|
1243
|
-
const openclawRuntime = detectOpenClawRuntime(this.
|
|
1474
|
+
const openclawSourceDir = defaultOpenClawSourceDir(this.projectRoot);
|
|
1475
|
+
const openclawRuntime = detectOpenClawRuntime(this.projectRoot);
|
|
1244
1476
|
return {
|
|
1245
|
-
bridge_api_base:
|
|
1246
|
-
openclaw_detected: detectOpenClawInstallation(this.
|
|
1477
|
+
bridge_api_base: DEFAULT_BRIDGE_API_BASE,
|
|
1478
|
+
openclaw_detected: detectOpenClawInstallation(this.projectRoot).detected,
|
|
1247
1479
|
openclaw_running: openclawRuntime.running,
|
|
1248
1480
|
openclaw_gateway_host: OPENCLAW_GATEWAY_HOST,
|
|
1249
1481
|
openclaw_gateway_port: openclawRuntime.configured_gateway_port,
|
|
@@ -1252,7 +1484,7 @@ class LocalNodeService {
|
|
|
1252
1484
|
openclaw_workspace_skill_dir: workspaceSkillDir,
|
|
1253
1485
|
openclaw_legacy_skill_dir: legacySkillDir,
|
|
1254
1486
|
silicaclaw_env_template_path: (0, path_1.resolve)(this.workspaceRoot, "openclaw-owner-forward.env.example"),
|
|
1255
|
-
recommended_skill_name: "silicaclaw-
|
|
1487
|
+
recommended_skill_name: "silicaclaw-bridge-setup",
|
|
1256
1488
|
recommended_install_command: "silicaclaw openclaw-skill-install",
|
|
1257
1489
|
recommended_owner_forward_env: {
|
|
1258
1490
|
OPENCLAW_SOURCE_DIR: openclawSourceDir,
|
|
@@ -1270,6 +1502,7 @@ class LocalNodeService {
|
|
|
1270
1502
|
].join(" "),
|
|
1271
1503
|
notes: [
|
|
1272
1504
|
"Install and maintain the skill from SilicaClaw; do not edit OpenClaw core source for this integration.",
|
|
1505
|
+
"Use silicaclaw-bridge-setup first when OpenClaw still needs local install, readiness checks, or troubleshooting guidance.",
|
|
1273
1506
|
"OpenClaw learns broadcasts via the installed skill under ~/.openclaw/workspace/skills/.",
|
|
1274
1507
|
"Runtime detection prefers the actual OpenClaw gateway listener port, then falls back to OpenClaw's own openclaw.json gateway.port.",
|
|
1275
1508
|
"Owner delivery runs through OpenClaw's own message channel stack after the skill forwards a summary.",
|
|
@@ -1288,6 +1521,12 @@ class LocalNodeService {
|
|
|
1288
1521
|
const skillPath = (0, path_1.resolve)(dir.path, "SKILL.md");
|
|
1289
1522
|
const versionPath = (0, path_1.resolve)(dir.path, "VERSION");
|
|
1290
1523
|
const manifest = readJsonFileSafe(manifestPath);
|
|
1524
|
+
const references = (manifest?.references && typeof manifest.references === "object")
|
|
1525
|
+
? manifest.references
|
|
1526
|
+
: null;
|
|
1527
|
+
const ownerDialogueCheatsheetPath = references?.owner_dialogue_cheatsheet_zh
|
|
1528
|
+
? (0, path_1.resolve)(dir.path, String(references.owner_dialogue_cheatsheet_zh))
|
|
1529
|
+
: null;
|
|
1291
1530
|
const name = String(manifest?.name || dir.name);
|
|
1292
1531
|
const capabilities = Array.isArray(manifest?.capabilities)
|
|
1293
1532
|
? manifest.capabilities.map((item) => String(item))
|
|
@@ -1307,6 +1546,9 @@ class LocalNodeService {
|
|
|
1307
1546
|
skill_path: (0, fs_1.existsSync)(skillPath) ? skillPath : null,
|
|
1308
1547
|
capabilities,
|
|
1309
1548
|
transport: manifest?.transport || null,
|
|
1549
|
+
owner_dialogue_cheatsheet_path: ownerDialogueCheatsheetPath && (0, fs_1.existsSync)(ownerDialogueCheatsheetPath) ? ownerDialogueCheatsheetPath : null,
|
|
1550
|
+
owner_dialogue_examples_zh: ownerDialogueCheatsheetPath ? readDialogueCheatsheetPreview(ownerDialogueCheatsheetPath) : [],
|
|
1551
|
+
owner_dialogue_sections_zh: ownerDialogueCheatsheetPath ? readDialogueCheatsheetSections(ownerDialogueCheatsheetPath) : [],
|
|
1310
1552
|
installed_in_openclaw: installedInWorkspace || installedInLegacy,
|
|
1311
1553
|
install_mode: installedInWorkspace ? "workspace" : installedInLegacy ? "legacy" : "not_installed",
|
|
1312
1554
|
installed_path: installedInWorkspace ? installedWorkspacePath : installedInLegacy ? installedLegacyPath : null,
|
|
@@ -1320,6 +1562,12 @@ class LocalNodeService {
|
|
|
1320
1562
|
const skillPath = (0, path_1.resolve)(dir.path, "SKILL.md");
|
|
1321
1563
|
const versionPath = (0, path_1.resolve)(dir.path, "VERSION");
|
|
1322
1564
|
const manifest = readJsonFileSafe(manifestPath);
|
|
1565
|
+
const references = (manifest?.references && typeof manifest.references === "object")
|
|
1566
|
+
? manifest.references
|
|
1567
|
+
: null;
|
|
1568
|
+
const ownerDialogueCheatsheetPath = references?.owner_dialogue_cheatsheet_zh
|
|
1569
|
+
? (0, path_1.resolve)(dir.path, String(references.owner_dialogue_cheatsheet_zh))
|
|
1570
|
+
: null;
|
|
1323
1571
|
return {
|
|
1324
1572
|
key: `${dir.install_mode}:${dir.name}`,
|
|
1325
1573
|
name: String(manifest?.name || dir.name),
|
|
@@ -1331,9 +1579,37 @@ class LocalNodeService {
|
|
|
1331
1579
|
manifest_path: (0, fs_1.existsSync)(manifestPath) ? manifestPath : null,
|
|
1332
1580
|
skill_path: (0, fs_1.existsSync)(skillPath) ? skillPath : null,
|
|
1333
1581
|
capabilities: Array.isArray(manifest?.capabilities) ? manifest.capabilities.map((item) => String(item)) : [],
|
|
1582
|
+
owner_dialogue_cheatsheet_path: ownerDialogueCheatsheetPath && (0, fs_1.existsSync)(ownerDialogueCheatsheetPath) ? ownerDialogueCheatsheetPath : null,
|
|
1583
|
+
owner_dialogue_examples_zh: ownerDialogueCheatsheetPath ? readDialogueCheatsheetPreview(ownerDialogueCheatsheetPath) : [],
|
|
1584
|
+
owner_dialogue_sections_zh: ownerDialogueCheatsheetPath ? readDialogueCheatsheetSections(ownerDialogueCheatsheetPath) : [],
|
|
1334
1585
|
bundled_source_path: bundledSkills.find((item) => item.name === String(manifest?.name || dir.name))?.source_path || null,
|
|
1335
1586
|
};
|
|
1336
1587
|
});
|
|
1588
|
+
const installedSkillVersions = new Map(installedSkills.map((item) => [item.name, item.version]));
|
|
1589
|
+
const bundledSkillsWithUpdateState = bundledSkills.map((skill) => {
|
|
1590
|
+
const installedVersion = installedSkillVersions.get(skill.name) || "";
|
|
1591
|
+
const updateAvailable = Boolean(skill.installed_in_openclaw &&
|
|
1592
|
+
installedVersion &&
|
|
1593
|
+
skill.version &&
|
|
1594
|
+
compareVersionTokens(installedVersion, skill.version) < 0);
|
|
1595
|
+
return {
|
|
1596
|
+
...skill,
|
|
1597
|
+
installed_version: installedVersion || null,
|
|
1598
|
+
update_available: updateAvailable,
|
|
1599
|
+
};
|
|
1600
|
+
});
|
|
1601
|
+
const bundledSkillVersions = new Map(bundledSkillsWithUpdateState.map((item) => [item.name, item.version]));
|
|
1602
|
+
const installedSkillsWithUpdateState = installedSkills.map((skill) => {
|
|
1603
|
+
const bundledVersion = bundledSkillVersions.get(skill.name) || "";
|
|
1604
|
+
const updateAvailable = Boolean(bundledVersion &&
|
|
1605
|
+
skill.version &&
|
|
1606
|
+
compareVersionTokens(skill.version, bundledVersion) < 0);
|
|
1607
|
+
return {
|
|
1608
|
+
...skill,
|
|
1609
|
+
bundled_version: bundledVersion || null,
|
|
1610
|
+
update_available: updateAvailable,
|
|
1611
|
+
};
|
|
1612
|
+
});
|
|
1337
1613
|
return {
|
|
1338
1614
|
openclaw: {
|
|
1339
1615
|
detected: bridge.openclaw_installation.detected,
|
|
@@ -1344,13 +1620,14 @@ class LocalNodeService {
|
|
|
1344
1620
|
legacy_install_root: legacyInstallRoot,
|
|
1345
1621
|
},
|
|
1346
1622
|
summary: {
|
|
1347
|
-
bundled_count:
|
|
1348
|
-
installed_count:
|
|
1349
|
-
installed_bundled_count:
|
|
1623
|
+
bundled_count: bundledSkillsWithUpdateState.length,
|
|
1624
|
+
installed_count: installedSkillsWithUpdateState.length,
|
|
1625
|
+
installed_bundled_count: bundledSkillsWithUpdateState.filter((item) => item.installed_in_openclaw).length,
|
|
1626
|
+
update_available_count: bundledSkillsWithUpdateState.filter((item) => item.update_available).length,
|
|
1350
1627
|
},
|
|
1351
1628
|
install_action: bridge.skill_learning.install_action,
|
|
1352
|
-
bundled_skills:
|
|
1353
|
-
installed_skills:
|
|
1629
|
+
bundled_skills: bundledSkillsWithUpdateState,
|
|
1630
|
+
installed_skills: installedSkillsWithUpdateState,
|
|
1354
1631
|
};
|
|
1355
1632
|
}
|
|
1356
1633
|
getRuntimeMessageGovernance() {
|
|
@@ -1569,12 +1846,16 @@ class LocalNodeService {
|
|
|
1569
1846
|
};
|
|
1570
1847
|
const presenceRecord = (0, core_1.signPresence)(this.identity, Date.now());
|
|
1571
1848
|
const indexRecords = (0, core_1.buildIndexRecords)(this.profile);
|
|
1849
|
+
const replayMessages = this.getReplayableSelfSocialMessages();
|
|
1572
1850
|
try {
|
|
1573
1851
|
await this.publish("profile", profileRecord);
|
|
1574
1852
|
await this.publish("presence", presenceRecord);
|
|
1575
1853
|
for (const record of indexRecords) {
|
|
1576
1854
|
await this.publish("index", record);
|
|
1577
1855
|
}
|
|
1856
|
+
for (const message of replayMessages) {
|
|
1857
|
+
await this.publish(SOCIAL_MESSAGE_TOPIC, message);
|
|
1858
|
+
}
|
|
1578
1859
|
}
|
|
1579
1860
|
catch (error) {
|
|
1580
1861
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1595,7 +1876,7 @@ class LocalNodeService {
|
|
|
1595
1876
|
}
|
|
1596
1877
|
this.compactCacheInMemory();
|
|
1597
1878
|
await this.persistCache();
|
|
1598
|
-
await this.log("info", `Broadcast sent (${indexRecords.length} index refs, reason=${reason})`);
|
|
1879
|
+
await this.log("info", `Broadcast sent (${indexRecords.length} index refs, replayed_messages=${replayMessages.length}, reason=${reason})`);
|
|
1599
1880
|
return { sent: true, reason };
|
|
1600
1881
|
}
|
|
1601
1882
|
async hydrateFromDisk() {
|
|
@@ -1613,7 +1894,7 @@ class LocalNodeService {
|
|
|
1613
1894
|
socialConfig: this.socialConfig,
|
|
1614
1895
|
existingIdentity,
|
|
1615
1896
|
generatedIdentity: (0, core_1.createIdentity)(),
|
|
1616
|
-
rootDir: this.
|
|
1897
|
+
rootDir: this.projectRoot,
|
|
1617
1898
|
});
|
|
1618
1899
|
this.identity = resolvedIdentity.identity;
|
|
1619
1900
|
this.resolvedIdentitySource = resolvedIdentity.source;
|
|
@@ -1631,7 +1912,7 @@ class LocalNodeService {
|
|
|
1631
1912
|
socialConfig: this.socialConfig,
|
|
1632
1913
|
agentId: this.identity.agent_id,
|
|
1633
1914
|
existingProfile: existingProfile && existingProfile.agent_id === this.identity.agent_id ? existingProfile : null,
|
|
1634
|
-
rootDir: this.
|
|
1915
|
+
rootDir: this.projectRoot,
|
|
1635
1916
|
});
|
|
1636
1917
|
this.profile = (0, core_1.signProfile)(profileInput, this.identity);
|
|
1637
1918
|
if (!existingProfile || existingProfile.agent_id !== this.identity.agent_id) {
|
|
@@ -1639,7 +1920,7 @@ class LocalNodeService {
|
|
|
1639
1920
|
await this.log("info", "profile.json missing/invalid, initialized from social/default profile");
|
|
1640
1921
|
}
|
|
1641
1922
|
await this.profileRepo.set(this.profile);
|
|
1642
|
-
this.directory = (0, core_1.
|
|
1923
|
+
this.directory = (0, core_1.createEmptyDirectoryState)();
|
|
1643
1924
|
this.messageGovernance = {
|
|
1644
1925
|
...this.defaultMessageGovernance(),
|
|
1645
1926
|
...(await this.socialMessageGovernanceRepo.get()),
|
|
@@ -1660,7 +1941,7 @@ class LocalNodeService {
|
|
|
1660
1941
|
socialConfig: this.socialConfig,
|
|
1661
1942
|
agentId: this.identity.agent_id,
|
|
1662
1943
|
existingProfile: this.profile,
|
|
1663
|
-
rootDir: this.
|
|
1944
|
+
rootDir: this.projectRoot,
|
|
1664
1945
|
});
|
|
1665
1946
|
const nextProfile = (0, core_1.signProfile)(nextProfileInput, this.identity);
|
|
1666
1947
|
this.profile = nextProfile;
|
|
@@ -1765,6 +2046,10 @@ class LocalNodeService {
|
|
|
1765
2046
|
await this.log("warn", `Rejected social message with invalid signature (${record.message_id.slice(0, 10)})`);
|
|
1766
2047
|
return;
|
|
1767
2048
|
}
|
|
2049
|
+
if (this.hasSocialMessage(record.message_id)) {
|
|
2050
|
+
await this.publishObservationForMessage(record);
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
1768
2053
|
const governanceReason = this.getIncomingSocialMessageRejectionReason(record);
|
|
1769
2054
|
if (governanceReason) {
|
|
1770
2055
|
await this.log("warn", `Rejected social message (${record.message_id.slice(0, 10)}): ${governanceReason}`);
|
|
@@ -1800,7 +2085,7 @@ class LocalNodeService {
|
|
|
1800
2085
|
if (this.broadcaster) {
|
|
1801
2086
|
clearInterval(this.broadcaster);
|
|
1802
2087
|
}
|
|
1803
|
-
if (!this.broadcastEnabled) {
|
|
2088
|
+
if (!this.broadcastEnabled || !this.networkStarted) {
|
|
1804
2089
|
return;
|
|
1805
2090
|
}
|
|
1806
2091
|
this.broadcaster = setInterval(async () => {
|
|
@@ -1912,6 +2197,7 @@ class LocalNodeService {
|
|
|
1912
2197
|
};
|
|
1913
2198
|
}
|
|
1914
2199
|
async restartNetworkAdapter(reason) {
|
|
2200
|
+
this.clearNetworkReconnectTimer();
|
|
1915
2201
|
const previous = this.network;
|
|
1916
2202
|
try {
|
|
1917
2203
|
await previous.stop();
|
|
@@ -1923,13 +2209,52 @@ class LocalNodeService {
|
|
|
1923
2209
|
this.network = next.adapter;
|
|
1924
2210
|
this.adapterMode = next.mode;
|
|
1925
2211
|
this.networkPort = next.port;
|
|
1926
|
-
|
|
2212
|
+
this.subscriptionsBound = false;
|
|
1927
2213
|
this.bindNetworkSubscriptions();
|
|
1928
|
-
this.
|
|
1929
|
-
|
|
1930
|
-
|
|
2214
|
+
await this.startNetworkAdapterWithRetry(reason);
|
|
2215
|
+
}
|
|
2216
|
+
clearNetworkReconnectTimer() {
|
|
2217
|
+
if (this.networkReconnectTimer) {
|
|
2218
|
+
clearTimeout(this.networkReconnectTimer);
|
|
2219
|
+
this.networkReconnectTimer = null;
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
async startNetworkAdapterWithRetry(reason) {
|
|
2223
|
+
this.clearNetworkReconnectTimer();
|
|
2224
|
+
try {
|
|
2225
|
+
await this.network.start();
|
|
2226
|
+
this.networkStarted = true;
|
|
2227
|
+
this.networkStartupError = null;
|
|
2228
|
+
this.networkReconnectDelayMs = 5_000;
|
|
2229
|
+
await this.log("info", `Local node started (${this.adapterMode}, mode=${this.networkMode}, signaling=${this.webrtcSignalingUrls[0] || "-"}, room=${this.webrtcRoom})`);
|
|
2230
|
+
this.startBroadcastLoop();
|
|
2231
|
+
if (this.broadcastEnabled && this.profile?.public_enabled) {
|
|
2232
|
+
try {
|
|
2233
|
+
await this.broadcastNow(reason);
|
|
2234
|
+
}
|
|
2235
|
+
catch (error) {
|
|
2236
|
+
await this.log("warn", `Initial broadcast failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
catch (error) {
|
|
2241
|
+
this.networkStarted = false;
|
|
2242
|
+
this.networkStartupError = error instanceof Error ? error.message : String(error);
|
|
2243
|
+
await this.log("warn", `Network start failed (${this.adapterMode}, mode=${this.networkMode}): ${this.networkStartupError}`);
|
|
2244
|
+
this.scheduleNetworkReconnect();
|
|
1931
2245
|
}
|
|
1932
2246
|
}
|
|
2247
|
+
scheduleNetworkReconnect() {
|
|
2248
|
+
if (this.networkReconnectTimer) {
|
|
2249
|
+
return;
|
|
2250
|
+
}
|
|
2251
|
+
const delayMs = this.networkReconnectDelayMs;
|
|
2252
|
+
this.networkReconnectTimer = setTimeout(() => {
|
|
2253
|
+
this.networkReconnectTimer = null;
|
|
2254
|
+
void this.startNetworkAdapterWithRetry("adapter_reconnect");
|
|
2255
|
+
}, delayMs);
|
|
2256
|
+
this.networkReconnectDelayMs = Math.min(30_000, Math.max(5_000, Math.floor(delayMs * 1.5)));
|
|
2257
|
+
}
|
|
1933
2258
|
compactCacheInMemory() {
|
|
1934
2259
|
const cleaned = (0, core_1.cleanupExpiredPresence)(this.directory, Date.now(), PRESENCE_TTL_MS);
|
|
1935
2260
|
this.directory = (0, core_1.dedupeIndex)(cleaned.state);
|
|
@@ -1940,7 +2265,22 @@ class LocalNodeService {
|
|
|
1940
2265
|
this.publishedByTopic[topic] = (this.publishedByTopic[topic] ?? 0) + 1;
|
|
1941
2266
|
}
|
|
1942
2267
|
async persistCache() {
|
|
1943
|
-
|
|
2268
|
+
const persisted = (0, core_1.createEmptyDirectoryState)();
|
|
2269
|
+
if (this.profile) {
|
|
2270
|
+
const selfProfileRecord = {
|
|
2271
|
+
type: "profile",
|
|
2272
|
+
profile: this.profile,
|
|
2273
|
+
};
|
|
2274
|
+
this.directory = (0, core_1.ingestProfileRecord)(this.directory, selfProfileRecord);
|
|
2275
|
+
persisted.profiles[this.profile.agent_id] = this.profile;
|
|
2276
|
+
const selfLastSeenAt = this.directory.presence[this.profile.agent_id];
|
|
2277
|
+
if (typeof selfLastSeenAt === "number" && Number.isFinite(selfLastSeenAt)) {
|
|
2278
|
+
persisted.presence[this.profile.agent_id] = selfLastSeenAt;
|
|
2279
|
+
}
|
|
2280
|
+
const indexed = (0, core_1.rebuildIndexForProfile)(persisted, this.profile);
|
|
2281
|
+
persisted.index = indexed.index;
|
|
2282
|
+
}
|
|
2283
|
+
await this.cacheRepo.set(persisted);
|
|
1944
2284
|
}
|
|
1945
2285
|
async persistSocialMessages() {
|
|
1946
2286
|
await this.socialMessageRepo.set(this.socialMessages);
|
|
@@ -1961,6 +2301,18 @@ class LocalNodeService {
|
|
|
1961
2301
|
}
|
|
1962
2302
|
return this.network.getDiagnostics();
|
|
1963
2303
|
}
|
|
2304
|
+
getResolvedRealtimeNetworkSummary() {
|
|
2305
|
+
const diagnostics = this.getAdapterDiagnostics();
|
|
2306
|
+
const relayCapable = this.adapterMode === "webrtc-preview" || this.adapterMode === "relay-preview";
|
|
2307
|
+
return {
|
|
2308
|
+
diagnostics,
|
|
2309
|
+
signaling_url: diagnostics?.signaling_url ?? (relayCapable ? this.webrtcSignalingUrls[0] ?? null : null),
|
|
2310
|
+
signaling_endpoints: diagnostics?.signaling_endpoints ?? (relayCapable ? this.webrtcSignalingUrls : []),
|
|
2311
|
+
room: diagnostics?.room ?? (relayCapable ? this.webrtcRoom : null),
|
|
2312
|
+
bootstrap_sources: diagnostics?.bootstrap_sources ?? (relayCapable ? this.webrtcBootstrapSources : []),
|
|
2313
|
+
seed_peers_count: diagnostics?.seed_peers_count ?? this.webrtcSeedPeers.length,
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
1964
2316
|
toPublicProfileSummary(profile, options) {
|
|
1965
2317
|
const lastSeenAt = options?.last_seen_at ?? this.directory.presence[profile.agent_id] ?? 0;
|
|
1966
2318
|
const online = (0, core_1.isAgentOnline)(lastSeenAt, Date.now(), PRESENCE_TTL_MS);
|
|
@@ -1996,6 +2348,62 @@ class LocalNodeService {
|
|
|
1996
2348
|
presence_ttl_ms: PRESENCE_TTL_MS,
|
|
1997
2349
|
});
|
|
1998
2350
|
}
|
|
2351
|
+
mergeMessageOnlyAgentSummaries(summaries, keyword) {
|
|
2352
|
+
const normalizedKeyword = String(keyword || "").trim().toLowerCase();
|
|
2353
|
+
const knownAgentIds = new Set(summaries.map((item) => item.agent_id));
|
|
2354
|
+
const messageOnly = [];
|
|
2355
|
+
for (const message of this.socialMessages) {
|
|
2356
|
+
if (!message?.agent_id || knownAgentIds.has(message.agent_id)) {
|
|
2357
|
+
continue;
|
|
2358
|
+
}
|
|
2359
|
+
const displayName = String(message.display_name || "Unnamed").trim() || "Unnamed";
|
|
2360
|
+
if (normalizedKeyword) {
|
|
2361
|
+
const haystacks = [
|
|
2362
|
+
displayName.toLowerCase(),
|
|
2363
|
+
message.agent_id.toLowerCase(),
|
|
2364
|
+
String(message.topic || "").toLowerCase(),
|
|
2365
|
+
];
|
|
2366
|
+
if (!haystacks.some((value) => value.includes(normalizedKeyword))) {
|
|
2367
|
+
continue;
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
knownAgentIds.add(message.agent_id);
|
|
2371
|
+
messageOnly.push((0, core_1.buildPublicProfileSummary)({
|
|
2372
|
+
profile: {
|
|
2373
|
+
agent_id: message.agent_id,
|
|
2374
|
+
display_name: displayName,
|
|
2375
|
+
bio: "Seen from signed public message. Profile/presence not synced yet.",
|
|
2376
|
+
tags: ["message-only"],
|
|
2377
|
+
avatar_url: "",
|
|
2378
|
+
public_enabled: true,
|
|
2379
|
+
updated_at: message.created_at,
|
|
2380
|
+
signature: "",
|
|
2381
|
+
},
|
|
2382
|
+
online: false,
|
|
2383
|
+
last_seen_at: null,
|
|
2384
|
+
network_mode: "unknown",
|
|
2385
|
+
openclaw_bound: false,
|
|
2386
|
+
profile_version: PROFILE_VERSION,
|
|
2387
|
+
public_key_fingerprint: null,
|
|
2388
|
+
verified_profile: false,
|
|
2389
|
+
now: Date.now(),
|
|
2390
|
+
presence_ttl_ms: PRESENCE_TTL_MS,
|
|
2391
|
+
}));
|
|
2392
|
+
}
|
|
2393
|
+
return [...summaries, ...messageOnly].sort((a, b) => {
|
|
2394
|
+
if (a.online !== b.online) {
|
|
2395
|
+
return a.online ? -1 : 1;
|
|
2396
|
+
}
|
|
2397
|
+
if (a.updated_at !== b.updated_at) {
|
|
2398
|
+
return b.updated_at - a.updated_at;
|
|
2399
|
+
}
|
|
2400
|
+
const byName = a.display_name.localeCompare(b.display_name);
|
|
2401
|
+
if (byName !== 0) {
|
|
2402
|
+
return byName;
|
|
2403
|
+
}
|
|
2404
|
+
return a.agent_id.localeCompare(b.agent_id);
|
|
2405
|
+
});
|
|
2406
|
+
}
|
|
1999
2407
|
fingerprintPublicKey(publicKey) {
|
|
2000
2408
|
const digest = (0, crypto_1.createHash)("sha256").update(publicKey, "utf8").digest("hex");
|
|
2001
2409
|
return `${digest.slice(0, 12)}:${digest.slice(-8)}`;
|
|
@@ -2003,6 +2411,22 @@ class LocalNodeService {
|
|
|
2003
2411
|
getOnboardingSummary() {
|
|
2004
2412
|
const summary = this.getIntegrationSummary();
|
|
2005
2413
|
const publicEnabled = Boolean(this.profile?.public_enabled);
|
|
2414
|
+
const nextSteps = [];
|
|
2415
|
+
if (!String(this.profile?.display_name || "").trim()) {
|
|
2416
|
+
nextSteps.push("Update display name in Profile page");
|
|
2417
|
+
}
|
|
2418
|
+
if (!publicEnabled) {
|
|
2419
|
+
nextSteps.push("Enable Public Enabled in Profile");
|
|
2420
|
+
}
|
|
2421
|
+
if (!summary.running) {
|
|
2422
|
+
nextSteps.push("Start broadcast in Network");
|
|
2423
|
+
}
|
|
2424
|
+
if (!summary.discoverable) {
|
|
2425
|
+
nextSteps.push("Announce node once after the network is running");
|
|
2426
|
+
}
|
|
2427
|
+
if (nextSteps.length === 0) {
|
|
2428
|
+
nextSteps.push("Node is public and discoverable");
|
|
2429
|
+
}
|
|
2006
2430
|
return {
|
|
2007
2431
|
first_run: Boolean(this.initState.social_auto_created ||
|
|
2008
2432
|
this.initState.identity_auto_created ||
|
|
@@ -2012,10 +2436,7 @@ class LocalNodeService {
|
|
|
2012
2436
|
mode: this.networkMode,
|
|
2013
2437
|
public_enabled: publicEnabled,
|
|
2014
2438
|
can_enable_public_discovery: !publicEnabled,
|
|
2015
|
-
next_steps:
|
|
2016
|
-
"Update display name in Profile page",
|
|
2017
|
-
"Export social.md from Social Config",
|
|
2018
|
-
],
|
|
2439
|
+
next_steps: nextSteps,
|
|
2019
2440
|
};
|
|
2020
2441
|
}
|
|
2021
2442
|
getDefaultDisplayName() {
|
|
@@ -2038,7 +2459,7 @@ class LocalNodeService {
|
|
|
2038
2459
|
};
|
|
2039
2460
|
}
|
|
2040
2461
|
return {
|
|
2041
|
-
mode:
|
|
2462
|
+
mode: DEFAULT_NETWORK_MODE,
|
|
2042
2463
|
short_label: "Relay preview",
|
|
2043
2464
|
summary: "Uses the public relay preview room so public nodes can find each other across the internet.",
|
|
2044
2465
|
};
|
|
@@ -2066,12 +2487,12 @@ class LocalNodeService {
|
|
|
2066
2487
|
const resolvedMode = this.socialConfig.network.mode ||
|
|
2067
2488
|
(modeEnv === "local" || modeEnv === "lan" || modeEnv === "global-preview"
|
|
2068
2489
|
? modeEnv
|
|
2069
|
-
:
|
|
2490
|
+
: DEFAULT_NETWORK_MODE);
|
|
2070
2491
|
this.networkMode = resolvedMode;
|
|
2071
|
-
this.networkNamespace = this.socialConfig.network.namespace || process.env.NETWORK_NAMESPACE ||
|
|
2072
|
-
this.networkPort = Number(this.socialConfig.network.port || process.env.NETWORK_PORT ||
|
|
2073
|
-
const builtInGlobalSignalingUrls = [
|
|
2074
|
-
const builtInGlobalRoom =
|
|
2492
|
+
this.networkNamespace = this.socialConfig.network.namespace || process.env.NETWORK_NAMESPACE || DEFAULT_NETWORK_NAMESPACE;
|
|
2493
|
+
this.networkPort = Number(this.socialConfig.network.port || process.env.NETWORK_PORT || DEFAULT_NETWORK_PORT);
|
|
2494
|
+
const builtInGlobalSignalingUrls = [DEFAULT_GLOBAL_SIGNALING_URL];
|
|
2495
|
+
const builtInGlobalRoom = DEFAULT_GLOBAL_ROOM;
|
|
2075
2496
|
const signalingUrlsSocial = dedupeStrings(this.socialConfig.network.signaling_urls || []);
|
|
2076
2497
|
const signalingUrlSocial = String(this.socialConfig.network.signaling_url || "").trim();
|
|
2077
2498
|
const signalingUrlsEnv = dedupeStrings(parseListEnv(WEBRTC_SIGNALING_URLS));
|
|
@@ -2099,22 +2520,22 @@ class LocalNodeService {
|
|
|
2099
2520
|
signalingSource = "built-in-defaults:global-preview.signaling_urls";
|
|
2100
2521
|
}
|
|
2101
2522
|
else {
|
|
2102
|
-
signalingUrls = [
|
|
2103
|
-
signalingSource =
|
|
2523
|
+
signalingUrls = [DEFAULT_GLOBAL_SIGNALING_URL];
|
|
2524
|
+
signalingSource = `default:${DEFAULT_GLOBAL_SIGNALING_URL}`;
|
|
2104
2525
|
}
|
|
2105
2526
|
const roomSocial = String(this.socialConfig.network.room || "").trim();
|
|
2106
2527
|
const roomEnv = String(WEBRTC_ROOM || "").trim();
|
|
2107
2528
|
const room = roomSocial ||
|
|
2108
2529
|
roomEnv ||
|
|
2109
2530
|
(this.networkMode === "global-preview" ? builtInGlobalRoom : "") ||
|
|
2110
|
-
|
|
2531
|
+
DEFAULT_GLOBAL_ROOM;
|
|
2111
2532
|
const roomSource = roomSocial
|
|
2112
2533
|
? "social.md:network.room"
|
|
2113
2534
|
: roomEnv
|
|
2114
2535
|
? "env:WEBRTC_ROOM"
|
|
2115
2536
|
: this.networkMode === "global-preview"
|
|
2116
2537
|
? "built-in-defaults:global-preview.room"
|
|
2117
|
-
:
|
|
2538
|
+
: `default:${DEFAULT_GLOBAL_ROOM}`;
|
|
2118
2539
|
const seedPeersSocial = dedupeStrings(this.socialConfig.network.seed_peers || []);
|
|
2119
2540
|
const seedPeersEnv = dedupeStrings(parseListEnv(WEBRTC_SEED_PEERS));
|
|
2120
2541
|
const seedPeers = seedPeersSocial.length > 0 ? seedPeersSocial : seedPeersEnv;
|
|
@@ -2162,6 +2583,20 @@ class LocalNodeService {
|
|
|
2162
2583
|
const normalized = String(body || "").toLowerCase();
|
|
2163
2584
|
return this.messageGovernance.blocked_terms.some((term) => normalized.includes(term));
|
|
2164
2585
|
}
|
|
2586
|
+
hasSocialMessage(messageId) {
|
|
2587
|
+
return this.socialMessages.some((item) => item.message_id === messageId);
|
|
2588
|
+
}
|
|
2589
|
+
getReplayableSelfSocialMessages(now = Date.now()) {
|
|
2590
|
+
const maxCount = Math.max(0, SOCIAL_MESSAGE_REPLAY_MAX_PER_BROADCAST);
|
|
2591
|
+
if (!this.identity || maxCount === 0) {
|
|
2592
|
+
return [];
|
|
2593
|
+
}
|
|
2594
|
+
return this.socialMessages
|
|
2595
|
+
.filter((item) => (item.agent_id === this.identity?.agent_id &&
|
|
2596
|
+
now - item.created_at <= SOCIAL_MESSAGE_REPLAY_WINDOW_MS))
|
|
2597
|
+
.sort((a, b) => a.created_at - b.created_at)
|
|
2598
|
+
.slice(-maxCount);
|
|
2599
|
+
}
|
|
2165
2600
|
hasRecentDuplicateMessage(agentId, body, topic, now = Date.now()) {
|
|
2166
2601
|
return this.socialMessages.some((item) => (item.agent_id === agentId &&
|
|
2167
2602
|
item.topic === topic &&
|
|
@@ -2441,18 +2876,17 @@ function renderBootstrapScript(payload) {
|
|
|
2441
2876
|
if (data.pillBroadcastClassName) pillBroadcast.className = data.pillBroadcastClassName;
|
|
2442
2877
|
}
|
|
2443
2878
|
setHtml('overviewCards', data.overviewCardsHtml || '');
|
|
2444
|
-
setText('agentsCountHint', data.agentsCountHintText || '0
|
|
2445
|
-
setHtml('agentsWrap', data.agentsWrapHtml || '<div class="label">No discovered
|
|
2879
|
+
setText('agentsCountHint', data.agentsCountHintText || '0 nodes');
|
|
2880
|
+
setHtml('agentsWrap', data.agentsWrapHtml || '<div class="label">No discovered nodes yet.</div>');
|
|
2446
2881
|
})();
|
|
2447
2882
|
</script>`;
|
|
2448
2883
|
}
|
|
2449
2884
|
async function main() {
|
|
2450
2885
|
const app = (0, express_1.default)();
|
|
2451
|
-
const port = Number(process.env.PORT ||
|
|
2886
|
+
const port = Number(process.env.PORT || silicaclaw_defaults_json_1.default.ports.local_console);
|
|
2452
2887
|
const staticDir = resolveLocalConsoleStaticDir();
|
|
2453
2888
|
const staticIndexFile = (0, path_1.resolve)(staticDir, "index.html");
|
|
2454
2889
|
const node = new LocalNodeService();
|
|
2455
|
-
await node.start();
|
|
2456
2890
|
app.use((0, cors_1.default)({ origin: true }));
|
|
2457
2891
|
app.use(express_1.default.json());
|
|
2458
2892
|
app.get("/api/identity", (_req, res) => {
|
|
@@ -2591,9 +3025,10 @@ async function main() {
|
|
|
2591
3025
|
message: result.sent ? "OpenClaw bridge message published" : `OpenClaw bridge message skipped: ${result.reason}`,
|
|
2592
3026
|
});
|
|
2593
3027
|
}));
|
|
2594
|
-
app.post("/api/openclaw/bridge/skill-install", asyncRoute(async (
|
|
3028
|
+
app.post("/api/openclaw/bridge/skill-install", asyncRoute(async (req, res) => {
|
|
2595
3029
|
try {
|
|
2596
|
-
const
|
|
3030
|
+
const skillName = String(req.body?.skill_name || "").trim();
|
|
3031
|
+
const result = await node.installOpenClawSkill(skillName || undefined);
|
|
2597
3032
|
sendOk(res, result, {
|
|
2598
3033
|
message: "OpenClaw skill installed",
|
|
2599
3034
|
});
|
|
@@ -2622,7 +3057,7 @@ async function main() {
|
|
|
2622
3057
|
const agentId = req.params.agentId;
|
|
2623
3058
|
const profile = state.profiles[agentId];
|
|
2624
3059
|
if (!profile) {
|
|
2625
|
-
sendError(res, 404, "AGENT_NOT_FOUND", "
|
|
3060
|
+
sendError(res, 404, "AGENT_NOT_FOUND", "Node not found", { agent_id: agentId });
|
|
2626
3061
|
return;
|
|
2627
3062
|
}
|
|
2628
3063
|
const lastSeenAt = state.presence[agentId] ?? 0;
|
|
@@ -2652,7 +3087,7 @@ async function main() {
|
|
|
2652
3087
|
.map(([k, v]) => `<div class="card"><div class="label">${escapeHtml(String(k))}</div><div class="value">${escapeHtml(String(v))}</div></div>`)
|
|
2653
3088
|
.join("");
|
|
2654
3089
|
const agentsWrapHtml = discovered.length === 0
|
|
2655
|
-
? `<div class="label">No discovered
|
|
3090
|
+
? `<div class="label">No discovered nodes yet.</div>`
|
|
2656
3091
|
: `
|
|
2657
3092
|
<table class="table">
|
|
2658
3093
|
<thead><tr><th>Name</th><th>Agent ID</th><th>Status</th><th>Updated</th></tr></thead>
|
|
@@ -2686,7 +3121,7 @@ async function main() {
|
|
|
2686
3121
|
pillBroadcastText: overview.broadcast_enabled ? "broadcast: running" : "broadcast: paused",
|
|
2687
3122
|
pillBroadcastClassName: `pill ${overview.broadcast_enabled ? "ok" : "warn"}`,
|
|
2688
3123
|
overviewCardsHtml,
|
|
2689
|
-
agentsCountHintText: `${discovered.length}
|
|
3124
|
+
agentsCountHintText: `${discovered.length} nodes discovered`,
|
|
2690
3125
|
agentsWrapHtml,
|
|
2691
3126
|
integrationStatusText: `Connected to SilicaClaw: ${integration.connected_to_silicaclaw ? "yes" : "no"} · Network mode: ${integration.network_mode || "-"} · Public discovery: ${integration.public_enabled ? "enabled" : "disabled"}`,
|
|
2692
3127
|
integrationStatusClassName: `integration-strip ${integration.connected_to_silicaclaw && integration.public_enabled ? "ok" : "warn"}`,
|
|
@@ -2707,6 +3142,7 @@ async function main() {
|
|
|
2707
3142
|
// eslint-disable-next-line no-console
|
|
2708
3143
|
console.log(`SilicaClaw local-console running: http://localhost:${port}`);
|
|
2709
3144
|
});
|
|
3145
|
+
await node.start();
|
|
2710
3146
|
process.on("SIGINT", async () => {
|
|
2711
3147
|
await node.stop();
|
|
2712
3148
|
process.exit(0);
|