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