@silicaclaw/cli 2026.3.20-1 → 2026.3.20-10
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 +54 -0
- package/INSTALL.md +13 -7
- package/README.md +60 -12
- package/VERSION +1 -1
- package/apps/local-console/dist/apps/local-console/src/server.d.ts +129 -2
- package/apps/local-console/dist/apps/local-console/src/server.js +887 -91
- package/apps/local-console/dist/packages/core/src/index.d.ts +2 -0
- package/apps/local-console/dist/packages/core/src/index.js +2 -0
- package/apps/local-console/dist/packages/core/src/privateCrypto.d.ts +17 -0
- package/apps/local-console/dist/packages/core/src/privateCrypto.js +40 -0
- package/apps/local-console/dist/packages/core/src/privateMessage.d.ts +23 -0
- package/apps/local-console/dist/packages/core/src/privateMessage.js +74 -0
- package/apps/local-console/dist/packages/core/src/profile.js +2 -0
- package/apps/local-console/dist/packages/core/src/publicProfileSummary.d.ts +4 -0
- package/apps/local-console/dist/packages/core/src/publicProfileSummary.js +3 -0
- package/apps/local-console/dist/packages/core/src/types.d.ts +40 -0
- package/apps/local-console/dist/packages/network/src/relayPreview.d.ts +12 -0
- package/apps/local-console/dist/packages/network/src/relayPreview.js +108 -8
- package/apps/local-console/dist/packages/network/src/types.d.ts +4 -0
- package/apps/local-console/dist/packages/storage/src/repos.d.ts +13 -1
- package/apps/local-console/dist/packages/storage/src/repos.js +19 -1
- package/apps/local-console/public/app/app.js +465 -11
- package/apps/local-console/public/app/events.js +21 -0
- package/apps/local-console/public/app/network.js +144 -32
- package/apps/local-console/public/app/overview.js +60 -52
- package/apps/local-console/public/app/social.js +316 -93
- package/apps/local-console/public/app/styles.css +127 -1
- package/apps/local-console/public/app/template.js +121 -35
- package/apps/local-console/public/app/translations.js +430 -316
- package/apps/local-console/src/server.ts +1024 -89
- package/apps/public-explorer/public/app/template.js +2 -2
- package/apps/public-explorer/public/app/translations.js +36 -36
- package/docs/NEW_USER_OPERATIONS.md +5 -5
- package/docs/OPENCLAW_BRIDGE.md +7 -7
- package/docs/OPENCLAW_BRIDGE_ZH.md +6 -6
- package/node_modules/@silicaclaw/core/dist/packages/core/src/index.d.ts +2 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/index.js +2 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/privateCrypto.d.ts +17 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/privateCrypto.js +40 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/privateMessage.d.ts +23 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/privateMessage.js +74 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/profile.js +2 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/publicProfileSummary.d.ts +4 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/publicProfileSummary.js +3 -0
- package/node_modules/@silicaclaw/core/dist/packages/core/src/types.d.ts +40 -0
- package/node_modules/@silicaclaw/core/src/index.ts +2 -0
- package/node_modules/@silicaclaw/core/src/privateCrypto.ts +57 -0
- package/node_modules/@silicaclaw/core/src/privateMessage.ts +101 -0
- package/node_modules/@silicaclaw/core/src/profile.ts +2 -0
- package/node_modules/@silicaclaw/core/src/publicProfileSummary.ts +7 -0
- package/node_modules/@silicaclaw/core/src/types.ts +44 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.d.ts +12 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.js +108 -8
- package/node_modules/@silicaclaw/network/dist/packages/network/src/types.d.ts +4 -0
- package/node_modules/@silicaclaw/network/src/relayPreview.ts +120 -10
- package/node_modules/@silicaclaw/network/src/types.ts +2 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/index.d.ts +2 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/index.js +2 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/privateCrypto.d.ts +17 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/privateCrypto.js +40 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/privateMessage.d.ts +23 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/privateMessage.js +74 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/profile.js +2 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/publicProfileSummary.d.ts +4 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/publicProfileSummary.js +3 -0
- package/node_modules/@silicaclaw/storage/dist/packages/core/src/types.d.ts +40 -0
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/repos.d.ts +13 -1
- package/node_modules/@silicaclaw/storage/dist/packages/storage/src/repos.js +19 -1
- package/node_modules/@silicaclaw/storage/src/repos.ts +31 -1
- package/openclaw-skills/silicaclaw-bridge-setup/SKILL.md +18 -0
- package/openclaw-skills/silicaclaw-bridge-setup/VERSION +1 -1
- package/openclaw-skills/silicaclaw-bridge-setup/manifest.json +2 -2
- package/openclaw-skills/silicaclaw-broadcast/SKILL.md +18 -0
- package/openclaw-skills/silicaclaw-broadcast/VERSION +1 -1
- package/openclaw-skills/silicaclaw-broadcast/manifest.json +2 -2
- package/openclaw-skills/silicaclaw-network-config/SKILL.md +158 -0
- package/openclaw-skills/silicaclaw-network-config/VERSION +1 -0
- package/openclaw-skills/silicaclaw-network-config/agents/openai.yaml +6 -0
- package/openclaw-skills/silicaclaw-network-config/manifest.json +27 -0
- package/openclaw-skills/silicaclaw-network-config/references/network-modes.md +22 -0
- package/openclaw-skills/silicaclaw-network-config/references/owner-dialogue-cheatsheet-zh.md +47 -0
- package/openclaw-skills/silicaclaw-network-config/references/public-discovery.md +22 -0
- package/openclaw-skills/silicaclaw-owner-push/SKILL.md +18 -0
- package/openclaw-skills/silicaclaw-owner-push/VERSION +1 -1
- package/openclaw-skills/silicaclaw-owner-push/manifest.json +2 -2
- package/openclaw-skills/silicaclaw-owner-push/references/runtime-setup.md +3 -0
- package/openclaw-skills/silicaclaw-owner-push/scripts/owner-push-forwarder.mjs +151 -9
- package/package.json +1 -1
- package/packages/core/dist/packages/core/src/index.d.ts +2 -0
- package/packages/core/dist/packages/core/src/index.js +2 -0
- package/packages/core/dist/packages/core/src/privateCrypto.d.ts +17 -0
- package/packages/core/dist/packages/core/src/privateCrypto.js +40 -0
- package/packages/core/dist/packages/core/src/privateMessage.d.ts +23 -0
- package/packages/core/dist/packages/core/src/privateMessage.js +74 -0
- package/packages/core/dist/packages/core/src/profile.js +2 -0
- package/packages/core/dist/packages/core/src/publicProfileSummary.d.ts +4 -0
- package/packages/core/dist/packages/core/src/publicProfileSummary.js +3 -0
- package/packages/core/dist/packages/core/src/types.d.ts +40 -0
- package/packages/core/src/index.ts +2 -0
- package/packages/core/src/privateCrypto.ts +57 -0
- package/packages/core/src/privateMessage.ts +101 -0
- package/packages/core/src/profile.ts +2 -0
- package/packages/core/src/publicProfileSummary.ts +7 -0
- package/packages/core/src/types.ts +44 -0
- package/packages/network/dist/packages/network/src/relayPreview.d.ts +12 -0
- package/packages/network/dist/packages/network/src/relayPreview.js +108 -8
- package/packages/network/dist/packages/network/src/types.d.ts +4 -0
- package/packages/network/src/relayPreview.ts +120 -10
- package/packages/network/src/types.ts +2 -0
- package/packages/storage/dist/packages/core/src/index.d.ts +2 -0
- package/packages/storage/dist/packages/core/src/index.js +2 -0
- package/packages/storage/dist/packages/core/src/privateCrypto.d.ts +17 -0
- package/packages/storage/dist/packages/core/src/privateCrypto.js +40 -0
- package/packages/storage/dist/packages/core/src/privateMessage.d.ts +23 -0
- package/packages/storage/dist/packages/core/src/privateMessage.js +74 -0
- package/packages/storage/dist/packages/core/src/profile.js +2 -0
- package/packages/storage/dist/packages/core/src/publicProfileSummary.d.ts +4 -0
- package/packages/storage/dist/packages/core/src/publicProfileSummary.js +3 -0
- package/packages/storage/dist/packages/core/src/types.d.ts +40 -0
- package/packages/storage/dist/packages/storage/src/repos.d.ts +13 -1
- package/packages/storage/dist/packages/storage/src/repos.js +19 -1
- package/packages/storage/src/repos.ts +31 -1
- package/scripts/silicaclaw-cli.mjs +59 -6
- package/scripts/silicaclaw-gateway.mjs +108 -0
- package/scripts/validate-openclaw-skill.mjs +19 -0
|
@@ -13,6 +13,21 @@ export function createNetworkController({
|
|
|
13
13
|
room: "",
|
|
14
14
|
};
|
|
15
15
|
let quickConnectDefaults = { ...fallbackQuickConnectDefaults };
|
|
16
|
+
let lastNetworkRenderKey = "";
|
|
17
|
+
let lastPeersRenderKey = "";
|
|
18
|
+
let lastDiscoveryRenderKey = "";
|
|
19
|
+
|
|
20
|
+
function queueState(value) {
|
|
21
|
+
const n = Number(value || 0);
|
|
22
|
+
if (n >= 100) return { tone: "danger", label: t("labels.queueHigh") };
|
|
23
|
+
if (n >= 20) return { tone: "warn", label: t("labels.queueWatch") };
|
|
24
|
+
return { tone: "ok", label: t("labels.queueHealthy") };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function queueBadge(value) {
|
|
28
|
+
const state = queueState(value);
|
|
29
|
+
return `<span class="pill ${state.tone}">${Number(value || 0)} · ${state.label}</span>`;
|
|
30
|
+
}
|
|
16
31
|
|
|
17
32
|
async function refreshNetwork() {
|
|
18
33
|
const [cfg, sts, rtp] = await Promise.all([api("/api/network/config"), api("/api/network/stats"), api("/api/runtime/paths")]);
|
|
@@ -25,6 +40,10 @@ export function createNetworkController({
|
|
|
25
40
|
const transportStats = s.adapter_transport_stats || {};
|
|
26
41
|
const d = s.adapter_discovery_stats || {};
|
|
27
42
|
const dx = s.adapter_diagnostics_summary || {};
|
|
43
|
+
const runtimeDiag = s.runtime_diagnostics || {};
|
|
44
|
+
const runtimeMemory = runtimeDiag.memory_mib || {};
|
|
45
|
+
const runtimeDirectory = runtimeDiag.directory || {};
|
|
46
|
+
const runtimeSocial = runtimeDiag.social || {};
|
|
28
47
|
const ac = s.adapter_config || c.adapter_config || {};
|
|
29
48
|
quickConnectDefaults = {
|
|
30
49
|
signalingUrl: String(
|
|
@@ -59,7 +78,7 @@ export function createNetworkController({
|
|
|
59
78
|
heroRoomText: dx.room || "-",
|
|
60
79
|
pillAdapterText: `${t("labels.adapter")}: ${c.adapter || "-"}`,
|
|
61
80
|
});
|
|
62
|
-
|
|
81
|
+
const networkCardsHtml = [
|
|
63
82
|
[t("labels.adapter"), c.adapter],
|
|
64
83
|
[t("labels.namespace"), c.namespace || "-"],
|
|
65
84
|
[t("labels.port"), c.port ?? "-"],
|
|
@@ -75,12 +94,18 @@ export function createNetworkController({
|
|
|
75
94
|
[t("network.sent"), msg.broadcast_total ?? 0],
|
|
76
95
|
[t("network.peers"), p.total ?? 0],
|
|
77
96
|
[t("network.onlinePeers"), p.online ?? 0],
|
|
97
|
+
["RSS", runtimeMemory.rss ?? "-"],
|
|
98
|
+
["Heap", runtimeMemory.heap_used ?? "-"],
|
|
99
|
+
["Profiles", runtimeDirectory.profile_count ?? "-"],
|
|
100
|
+
["Index keys", runtimeDirectory.index_key_count ?? "-"],
|
|
101
|
+
["Messages", runtimeSocial.message_count ?? "-"],
|
|
102
|
+
["Observations", runtimeSocial.observation_count ?? "-"],
|
|
78
103
|
[t("network.activeWebrtcPeers"), dx.active_webrtc_peers ?? "-"],
|
|
79
104
|
[t("network.reconnectAttempts"), dx.reconnect_attempts_total ?? "-"],
|
|
80
105
|
[t("network.lastInbound"), ago(msg.last_message_at)],
|
|
81
106
|
[t("network.lastOutbound"), ago(msg.last_broadcast_at)],
|
|
82
107
|
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join("");
|
|
83
|
-
|
|
108
|
+
const networkSummaryHtml = [
|
|
84
109
|
[t("labels.mode"), describeCurrentMode(t, c.mode || "lan")],
|
|
85
110
|
[t("network.relayHealth"), relayHealth],
|
|
86
111
|
[t("network.currentRelay"), dx.signaling_url || "-"],
|
|
@@ -93,7 +118,7 @@ export function createNetworkController({
|
|
|
93
118
|
|
|
94
119
|
const comp = c.components || {};
|
|
95
120
|
const lim = c.limits || {};
|
|
96
|
-
|
|
121
|
+
const networkComponentsText = [
|
|
97
122
|
`demo_mode: ${c.demo_mode || "-"}`,
|
|
98
123
|
`transport: ${comp.transport || "-"}`,
|
|
99
124
|
`discovery: ${comp.discovery || "-"}`,
|
|
@@ -130,12 +155,39 @@ export function createNetworkController({
|
|
|
130
155
|
`last_discovery_event_at: ${dx.last_discovery_event_at ? new Date(dx.last_discovery_event_at).toISOString() : "-"}`,
|
|
131
156
|
].join("\n");
|
|
132
157
|
|
|
133
|
-
|
|
158
|
+
const networkConfigSnapshotText = toPrettyJson({
|
|
134
159
|
config: c,
|
|
135
160
|
adapter_config: ac,
|
|
136
161
|
runtime_paths: runtimePaths,
|
|
137
162
|
});
|
|
138
|
-
|
|
163
|
+
const networkStatsSnapshotText = toPrettyJson({ stats: s });
|
|
164
|
+
const renderKey = JSON.stringify({
|
|
165
|
+
adapter: c.adapter || "",
|
|
166
|
+
mode: c.mode || "",
|
|
167
|
+
namespace: c.namespace || "",
|
|
168
|
+
port: c.port ?? null,
|
|
169
|
+
signaling_url: dx.signaling_url || "",
|
|
170
|
+
room: dx.room || "",
|
|
171
|
+
relay_health: relayHealth,
|
|
172
|
+
last_poll_at: dx.last_poll_at || 0,
|
|
173
|
+
last_publish_at: dx.last_publish_at || 0,
|
|
174
|
+
last_error: dx.last_error || "",
|
|
175
|
+
msg_received_total: msg.received_total ?? 0,
|
|
176
|
+
msg_broadcast_total: msg.broadcast_total ?? 0,
|
|
177
|
+
peers_total: p.total ?? 0,
|
|
178
|
+
peers_online: p.online ?? 0,
|
|
179
|
+
reconnect_attempts_total: dx.reconnect_attempts_total ?? 0,
|
|
180
|
+
active_webrtc_peers: dx.active_webrtc_peers ?? 0,
|
|
181
|
+
});
|
|
182
|
+
if (renderKey === lastNetworkRenderKey) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
document.getElementById("networkCards").innerHTML = networkCardsHtml;
|
|
186
|
+
document.getElementById("networkSummaryList").innerHTML = networkSummaryHtml;
|
|
187
|
+
document.getElementById("networkComponents").textContent = networkComponentsText;
|
|
188
|
+
document.getElementById("networkConfigSnapshot").textContent = networkConfigSnapshotText;
|
|
189
|
+
document.getElementById("networkStatsSnapshot").textContent = networkStatsSnapshotText;
|
|
190
|
+
lastNetworkRenderKey = renderKey;
|
|
139
191
|
}
|
|
140
192
|
|
|
141
193
|
async function refreshPeers() {
|
|
@@ -143,8 +195,12 @@ export function createNetworkController({
|
|
|
143
195
|
const peers = peerRes.data || {};
|
|
144
196
|
const ds = statsRes.data?.adapter_discovery_stats || {};
|
|
145
197
|
const summary = peers.diagnostics_summary || {};
|
|
146
|
-
|
|
147
|
-
|
|
198
|
+
const peerItems = Array.isArray(peers.items) ? peers.items : [];
|
|
199
|
+
const relayQueueTotal = peerItems.reduce((sum, peer) => sum + Number(peer?.meta?.relay_queue_size || 0), 0);
|
|
200
|
+
const relayQueueMax = peerItems.reduce((max, peer) => Math.max(max, Number(peer?.meta?.relay_queue_size || 0)), 0);
|
|
201
|
+
const signalQueueTotal = peerItems.reduce((sum, peer) => sum + Number(peer?.meta?.signal_queue_size || 0), 0);
|
|
202
|
+
const signalQueueMax = peerItems.reduce((max, peer) => Math.max(max, Number(peer?.meta?.signal_queue_size || 0)), 0);
|
|
203
|
+
const peerCardsHtml = [
|
|
148
204
|
[t("network.total"), peers.total || 0],
|
|
149
205
|
[t("overview.online"), peers.online || 0],
|
|
150
206
|
[t("network.stale"), peers.stale || 0],
|
|
@@ -159,26 +215,28 @@ export function createNetworkController({
|
|
|
159
215
|
[t("network.seedPeers"), summary.seed_peers_count ?? 0],
|
|
160
216
|
[t("network.discoveryEvents"), summary.discovery_events_total ?? 0],
|
|
161
217
|
[t("network.activeWebrtcPeers"), summary.active_webrtc_peers ?? "-"],
|
|
218
|
+
["Relay queue", queueBadge(relayQueueTotal)],
|
|
219
|
+
["Max relay queue", queueBadge(relayQueueMax)],
|
|
220
|
+
["Signal queue", queueBadge(signalQueueTotal)],
|
|
221
|
+
["Max signal queue", queueBadge(signalQueueMax)],
|
|
162
222
|
[t("network.observeCalls"), ds.observe_calls || 0],
|
|
163
223
|
[t("network.heartbeats"), ds.heartbeat_sent || 0],
|
|
164
224
|
[t("network.peersAdded"), ds.peers_added || 0],
|
|
165
225
|
[t("network.peersRemoved"), ds.peers_removed || 0],
|
|
166
226
|
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join("");
|
|
227
|
+
const peerStatsText = toPrettyJson({
|
|
228
|
+
discovery_stats: ds,
|
|
229
|
+
diagnostics_summary: summary,
|
|
230
|
+
adapter_stats: statsRes.data?.adapter_stats || {},
|
|
231
|
+
});
|
|
167
232
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
discovery_stats: ds,
|
|
172
|
-
diagnostics_summary: summary,
|
|
173
|
-
});
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
document.getElementById("peerTableWrap").innerHTML = `
|
|
233
|
+
const peerTableHtml = !peers.items || !peers.items.length
|
|
234
|
+
? `<div class="empty-state">${t("network.noPeersDiscovered")}</div>`
|
|
235
|
+
: `
|
|
178
236
|
<table class="table">
|
|
179
|
-
<thead><tr><th>${t("network.peer")}</th><th>${t("network.status")}</th><th>${t("network.lastSeen")}</th><th>${t("network.staleSince")}</th><th>${t("network.messages")}</th><th>${t("network.firstSeen")}</th><th>${t("network.meta")}</th></tr></thead>
|
|
237
|
+
<thead><tr><th>${t("network.peer")}</th><th>${t("network.status")}</th><th>${t("network.lastSeen")}</th><th>${t("network.staleSince")}</th><th>${t("network.messages")}</th><th>${t("network.firstSeen")}</th><th>Relay Q</th><th>Signal Q</th><th>${t("network.meta")}</th></tr></thead>
|
|
180
238
|
<tbody>
|
|
181
|
-
${
|
|
239
|
+
${peerItems.map((peer) => `
|
|
182
240
|
<tr>
|
|
183
241
|
<td class="mono">${shortId(peer.peer_id)}</td>
|
|
184
242
|
<td class="${peer.status === "online" ? "online" : peer.status === "offline" ? "offline" : "stale"}">${peerStatusText(peer.status)}</td>
|
|
@@ -186,25 +244,67 @@ export function createNetworkController({
|
|
|
186
244
|
<td>${peer.stale_since_at ? ago(peer.stale_since_at) : "-"}</td>
|
|
187
245
|
<td>${peer.messages_seen || 0}</td>
|
|
188
246
|
<td>${new Date(peer.first_seen_at).toLocaleTimeString()}</td>
|
|
247
|
+
<td>${queueBadge(Number(peer?.meta?.relay_queue_size || 0))}</td>
|
|
248
|
+
<td>${queueBadge(Number(peer?.meta?.signal_queue_size || 0))}</td>
|
|
189
249
|
<td class="mono">${peer.meta ? JSON.stringify(peer.meta) : "-"}</td>
|
|
190
250
|
</tr>
|
|
191
251
|
`).join("")}
|
|
192
252
|
</tbody>
|
|
193
253
|
</table>
|
|
194
254
|
`;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
255
|
+
const renderKey = JSON.stringify({
|
|
256
|
+
total: peers.total || 0,
|
|
257
|
+
online: peers.online || 0,
|
|
258
|
+
stale: peers.stale || 0,
|
|
259
|
+
namespace: peers.namespace || "",
|
|
260
|
+
summary: {
|
|
261
|
+
signaling_url: summary.signaling_url || "",
|
|
262
|
+
room: summary.room || "",
|
|
263
|
+
last_join_at: summary.last_join_at || 0,
|
|
264
|
+
last_poll_at: summary.last_poll_at || 0,
|
|
265
|
+
last_publish_at: summary.last_publish_at || 0,
|
|
266
|
+
last_error: summary.last_error || "",
|
|
267
|
+
},
|
|
268
|
+
ds: {
|
|
269
|
+
observe_calls: ds.observe_calls || 0,
|
|
270
|
+
heartbeat_sent: ds.heartbeat_sent || 0,
|
|
271
|
+
peers_added: ds.peers_added || 0,
|
|
272
|
+
peers_removed: ds.peers_removed || 0,
|
|
273
|
+
},
|
|
274
|
+
queues: {
|
|
275
|
+
relay_total: relayQueueTotal,
|
|
276
|
+
relay_max: relayQueueMax,
|
|
277
|
+
signal_total: signalQueueTotal,
|
|
278
|
+
signal_max: signalQueueMax,
|
|
279
|
+
},
|
|
280
|
+
items: peerItems
|
|
281
|
+
? peerItems.map((peer) => [
|
|
282
|
+
peer.peer_id,
|
|
283
|
+
peer.status || "",
|
|
284
|
+
peer.last_seen_at || 0,
|
|
285
|
+
peer.stale_since_at || 0,
|
|
286
|
+
peer.messages_seen || 0,
|
|
287
|
+
peer.first_seen_at || 0,
|
|
288
|
+
Number(peer?.meta?.relay_queue_size || 0),
|
|
289
|
+
Number(peer?.meta?.signal_queue_size || 0),
|
|
290
|
+
peer.meta ? JSON.stringify(peer.meta) : "",
|
|
291
|
+
])
|
|
292
|
+
: [],
|
|
199
293
|
});
|
|
294
|
+
if (renderKey === lastPeersRenderKey) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
document.getElementById("peerCards").innerHTML = peerCardsHtml;
|
|
298
|
+
document.getElementById("peerTableWrap").innerHTML = peerTableHtml;
|
|
299
|
+
document.getElementById("peerStatsWrap").textContent = peerStatsText;
|
|
300
|
+
lastPeersRenderKey = renderKey;
|
|
200
301
|
}
|
|
201
302
|
|
|
202
303
|
async function refreshDiscovery() {
|
|
203
304
|
const eventsRes = await api("/api/discovery/events");
|
|
204
305
|
const payload = eventsRes.data || {};
|
|
205
306
|
const items = Array.isArray(payload.items) ? payload.items : [];
|
|
206
|
-
|
|
207
|
-
document.getElementById("discoveryCards").innerHTML = [
|
|
307
|
+
const discoveryCardsHtml = [
|
|
208
308
|
[t("labels.adapter"), payload.adapter || "-"],
|
|
209
309
|
[t("labels.namespace"), payload.namespace || "-"],
|
|
210
310
|
[t("network.eventsTotal"), payload.total ?? 0],
|
|
@@ -212,11 +312,9 @@ export function createNetworkController({
|
|
|
212
312
|
[t("network.signalingEndpoints"), (payload.signaling_endpoints || []).length || 0],
|
|
213
313
|
[t("network.seedPeers"), payload.seed_peers_count ?? 0],
|
|
214
314
|
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join("");
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
} else {
|
|
219
|
-
document.getElementById("discoveryEventList").innerHTML = items
|
|
315
|
+
const discoveryEventListHtml = !items.length
|
|
316
|
+
? `<div class="empty-state">${t("network.noDiscoveryEvents")}</div>`
|
|
317
|
+
: items
|
|
220
318
|
.slice()
|
|
221
319
|
.reverse()
|
|
222
320
|
.map((event) => `
|
|
@@ -227,9 +325,23 @@ export function createNetworkController({
|
|
|
227
325
|
</div>
|
|
228
326
|
`)
|
|
229
327
|
.join("");
|
|
328
|
+
const discoverySnapshotText = toPrettyJson(payload);
|
|
329
|
+
const renderKey = JSON.stringify({
|
|
330
|
+
adapter: payload.adapter || "",
|
|
331
|
+
namespace: payload.namespace || "",
|
|
332
|
+
total: payload.total ?? 0,
|
|
333
|
+
last_event_at: payload.last_event_at || 0,
|
|
334
|
+
signaling_endpoints: payload.signaling_endpoints || [],
|
|
335
|
+
seed_peers_count: payload.seed_peers_count ?? 0,
|
|
336
|
+
items: items.map((event) => [event.type || "", event.peer_id || "", event.endpoint || "", event.detail || "", event.at || 0]),
|
|
337
|
+
});
|
|
338
|
+
if (renderKey === lastDiscoveryRenderKey) {
|
|
339
|
+
return;
|
|
230
340
|
}
|
|
231
|
-
|
|
232
|
-
document.getElementById("
|
|
341
|
+
document.getElementById("discoveryCards").innerHTML = discoveryCardsHtml;
|
|
342
|
+
document.getElementById("discoveryEventList").innerHTML = discoveryEventListHtml;
|
|
343
|
+
document.getElementById("discoverySnapshot").textContent = discoverySnapshotText;
|
|
344
|
+
lastDiscoveryRenderKey = renderKey;
|
|
233
345
|
}
|
|
234
346
|
|
|
235
347
|
return {
|
|
@@ -7,6 +7,8 @@ export function createOverviewController({
|
|
|
7
7
|
t,
|
|
8
8
|
writeUiCache,
|
|
9
9
|
}) {
|
|
10
|
+
let lastAgentsRenderKey = "";
|
|
11
|
+
|
|
10
12
|
function renderOverviewGuide(overview, profile) {
|
|
11
13
|
const hasDisplayName = Boolean(String(profile?.display_name || overview?.display_name || "").trim());
|
|
12
14
|
const hasBio = Boolean(String(profile?.bio || "").trim());
|
|
@@ -64,12 +66,11 @@ export function createOverviewController({
|
|
|
64
66
|
setOverviewMode,
|
|
65
67
|
setVisibleRemotePublicCount,
|
|
66
68
|
}) {
|
|
67
|
-
const [overviewRes, discoveredRes, peerRes, profileRes,
|
|
69
|
+
const [overviewRes, discoveredRes, peerRes, profileRes, networkCfgRes, networkStatsRes] = await Promise.allSettled([
|
|
68
70
|
api("/api/overview"),
|
|
69
71
|
api("/api/search?q="),
|
|
70
72
|
api("/api/peers"),
|
|
71
73
|
api("/api/profile"),
|
|
72
|
-
api("/api/openclaw/bridge"),
|
|
73
74
|
api("/api/network/config"),
|
|
74
75
|
api("/api/network/stats"),
|
|
75
76
|
]);
|
|
@@ -80,40 +81,17 @@ export function createOverviewController({
|
|
|
80
81
|
const allProfiles = discoveredRes.status === "fulfilled" ? discoveredRes.value.data || [] : [];
|
|
81
82
|
const peers = peerRes.status === "fulfilled" ? peerRes.value.data || {} : {};
|
|
82
83
|
const currentProfile = profileRes.status === "fulfilled" ? profileRes.value.data || {} : {};
|
|
83
|
-
const bridge = bridgeRes.status === "fulfilled" ? bridgeRes.value.data || {} : {};
|
|
84
84
|
const networkCfg = networkCfgRes.status === "fulfilled" ? networkCfgRes.value.data || {} : {};
|
|
85
85
|
const networkStats = networkStatsRes.status === "fulfilled" ? networkStatsRes.value.data || {} : {};
|
|
86
|
-
const
|
|
87
|
-
const mergedById = new Map();
|
|
88
|
-
|
|
89
|
-
for (const agent of allProfiles) mergedById.set(agent.agent_id, agent);
|
|
90
|
-
|
|
91
|
-
for (const peer of peerItems) {
|
|
92
|
-
const existing = mergedById.get(peer.peer_id);
|
|
93
|
-
if (existing) {
|
|
94
|
-
if (peer.status && !existing.online) existing.online = peer.status === "online";
|
|
95
|
-
if (peer.last_seen_at && (!existing.updated_at || peer.last_seen_at > existing.updated_at)) {
|
|
96
|
-
existing.updated_at = peer.last_seen_at;
|
|
97
|
-
}
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
mergedById.set(peer.peer_id, {
|
|
101
|
-
agent_id: peer.peer_id,
|
|
102
|
-
display_name: shortId(peer.peer_id),
|
|
103
|
-
online: peer.status === "online",
|
|
104
|
-
updated_at: peer.last_seen_at || peer.first_seen_at || 0,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const all = Array.from(mergedById.values());
|
|
86
|
+
const all = Array.isArray(allProfiles) ? allProfiles.slice() : [];
|
|
109
87
|
const filtered = getOnlyShowOnline() ? all.filter((agent) => agent.online) : all;
|
|
110
88
|
setVisibleRemotePublicCount(all.filter((agent) => !agent.is_self && agent.online).length);
|
|
111
89
|
const totalAgentPages = Math.max(1, Math.ceil(filtered.length / 10));
|
|
112
90
|
let agentsPage = Math.min(Math.max(1, getAgentsPage()), totalAgentPages);
|
|
113
91
|
onPageChange(agentsPage);
|
|
114
92
|
const pagedAgents = filtered.slice((agentsPage - 1) * 10, agentsPage * 10);
|
|
115
|
-
const discoveredCount = Math.max(Number(o.discovered_count || 0),
|
|
116
|
-
const onlineCount = Math.max(Number(o.online_count || 0),
|
|
93
|
+
const discoveredCount = Math.max(Number(o.discovered_count || 0), all.length);
|
|
94
|
+
const onlineCount = Math.max(Number(o.online_count || 0), all.filter((agent) => agent.online).length);
|
|
117
95
|
const offlineCount = Math.max(0, discoveredCount - onlineCount);
|
|
118
96
|
|
|
119
97
|
const overviewCardsHtml = [
|
|
@@ -130,15 +108,15 @@ export function createOverviewController({
|
|
|
130
108
|
const snapshotHtml = `
|
|
131
109
|
<div class="snapshot-card">
|
|
132
110
|
<div class="snapshot-card__identity">
|
|
133
|
-
<div class="snapshot-card__label"
|
|
111
|
+
<div class="snapshot-card__label">${t("overview.snapshotCurrentNode")}</div>
|
|
134
112
|
<div class="snapshot-card__title">${escapeHtml(o.display_name || t("overview.unnamed"))}</div>
|
|
135
113
|
<div class="snapshot-card__subtle mono">${escapeHtml(o.agent_id || "-")}</div>
|
|
136
114
|
</div>
|
|
137
115
|
<div class="snapshot-card__grid">
|
|
138
|
-
<div class="snapshot-card__item"><div class="label"
|
|
139
|
-
<div class="snapshot-card__item"><div class="label"
|
|
140
|
-
<div class="snapshot-card__item"><div class="label"
|
|
141
|
-
<div class="snapshot-card__item"><div class="label"
|
|
116
|
+
<div class="snapshot-card__item"><div class="label">${t("overview.snapshotVersion")}</div><span class="value-inline">${escapeHtml(o.app_version || "-")}</span></div>
|
|
117
|
+
<div class="snapshot-card__item"><div class="label">${t("overview.snapshotPublic")}</div><span class="value-inline">${o.public_enabled ? t("common.on") : t("common.off")}</span></div>
|
|
118
|
+
<div class="snapshot-card__item"><div class="label">${t("overview.snapshotBroadcast")}</div><span class="value-inline">${o.broadcast_enabled ? t("common.on") : t("common.off")}</span></div>
|
|
119
|
+
<div class="snapshot-card__item"><div class="label">${t("overview.snapshotLastBroadcast")}</div><span class="value-inline">${escapeHtml(ago(o.last_broadcast_at))}</span></div>
|
|
142
120
|
</div>
|
|
143
121
|
</div>
|
|
144
122
|
`;
|
|
@@ -165,9 +143,10 @@ export function createOverviewController({
|
|
|
165
143
|
document.getElementById("pillBroadcast").textContent = pillBroadcastText;
|
|
166
144
|
document.getElementById("pillBroadcast").className = pillBroadcastClassName;
|
|
167
145
|
|
|
168
|
-
const
|
|
169
|
-
const
|
|
170
|
-
const
|
|
146
|
+
const openclaw = o.openclaw || {};
|
|
147
|
+
const openclawRunning = !!openclaw.running;
|
|
148
|
+
const openclawDetected = !!openclaw.detected || openclawRunning;
|
|
149
|
+
const skillInstalled = !!openclaw.skill_installed;
|
|
171
150
|
const globalMode = heroModeText === "global-preview";
|
|
172
151
|
const lastNetworkError = String(networkDiag.last_error || o.last_broadcast_error || "").trim();
|
|
173
152
|
const broadcastHealthy = o.broadcast_enabled && !lastNetworkError;
|
|
@@ -197,7 +176,7 @@ export function createOverviewController({
|
|
|
197
176
|
document.getElementById("homePriorityGrid").innerHTML = [
|
|
198
177
|
[t("overview.homeOpenClaw"), openclawRunning ? t("overview.homeRunning") : openclawDetected ? t("overview.homeInstalledOnly") : t("overview.homeStopped"), openclawRunning ? t("overview.homeMetaRunning") : t("overview.homeMetaNotRunning")],
|
|
199
178
|
[t("overview.homeGlobalMode"), globalMode ? t("overview.homeGlobalReady") : t("overview.homeNotGlobal"), globalMode ? t("overview.homeMetaGlobal") : t("overview.homeMetaNotGlobal")],
|
|
200
|
-
[t("overview.homeBroadcastHealth"), broadcastHealthy ? t("overview.homeHealthy") : t("overview.homeDegraded"), lastNetworkError ||
|
|
179
|
+
[t("overview.homeBroadcastHealth"), broadcastHealthy ? t("overview.homeHealthy") : t("overview.homeDegraded"), lastNetworkError || t("overview.lastBroadcastAgo", { value: ago(o.last_broadcast_at) })],
|
|
201
180
|
[t("overview.homePeers"), String(all.filter((agent) => !agent.is_self && agent.online).length), t("overview.homeMetaPeers", { online: String(onlineCount), discovered: String(discoveredCount) })],
|
|
202
181
|
].map(([label, value, meta]) => `
|
|
203
182
|
<div class="priority-card">
|
|
@@ -243,8 +222,17 @@ export function createOverviewController({
|
|
|
243
222
|
if (!filtered.length) {
|
|
244
223
|
const agentsCountHintText = t("overview.agentsZero");
|
|
245
224
|
const agentsWrapHtml = `<div class="label">${t("overview.noDiscoveredAgents")}</div>`;
|
|
246
|
-
|
|
247
|
-
|
|
225
|
+
const renderKey = JSON.stringify({
|
|
226
|
+
state: "empty",
|
|
227
|
+
hint: agentsCountHintText,
|
|
228
|
+
page: agentsPage,
|
|
229
|
+
onlineOnly: getOnlyShowOnline(),
|
|
230
|
+
});
|
|
231
|
+
if (renderKey !== lastAgentsRenderKey) {
|
|
232
|
+
document.getElementById("agentsCountHint").textContent = agentsCountHintText;
|
|
233
|
+
document.getElementById("agentsWrap").innerHTML = agentsWrapHtml;
|
|
234
|
+
lastAgentsRenderKey = renderKey;
|
|
235
|
+
}
|
|
248
236
|
writeUiCache("silicaclaw_ui_overview", {
|
|
249
237
|
overviewCardsHtml,
|
|
250
238
|
brandVersionText,
|
|
@@ -292,6 +280,9 @@ export function createOverviewController({
|
|
|
292
280
|
${renderTags(a)}
|
|
293
281
|
</div>
|
|
294
282
|
<div class="${a.online ? "online" : "offline"}">${a.online ? t("overview.online") : t("overview.offline")}</div>
|
|
283
|
+
<div class="agent-card__actions">
|
|
284
|
+
${!a.is_self ? `<button class="secondary" type="button" data-private-agent="${escapeHtml(a.agent_id)}" data-private-name="${escapeHtml(a.display_name || "")}" data-private-key="${escapeHtml(a.private_encryption_public_key || "")}" ${a.private_encryption_public_key ? "" : "disabled title=\"Private messaging unavailable for this agent yet\""}>${t("actions.messageAgentPrivately")}</button>` : ""}
|
|
285
|
+
</div>
|
|
295
286
|
<div class="agent-card__meta"><div class="agent-card__updated">${ago(a.updated_at)}</div></div>
|
|
296
287
|
</div>
|
|
297
288
|
`).join("")}
|
|
@@ -304,20 +295,37 @@ export function createOverviewController({
|
|
|
304
295
|
</div>
|
|
305
296
|
</div>
|
|
306
297
|
`;
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
298
|
+
const renderKey = JSON.stringify({
|
|
299
|
+
state: "list",
|
|
300
|
+
hint: agentsCountHintText,
|
|
301
|
+
page: agentsPage,
|
|
302
|
+
totalPages: totalAgentPages,
|
|
303
|
+
onlineOnly: getOnlyShowOnline(),
|
|
304
|
+
items: pagedAgents.map((agent) => [
|
|
305
|
+
agent.agent_id,
|
|
306
|
+
agent.updated_at,
|
|
307
|
+
agent.online ? 1 : 0,
|
|
308
|
+
agent.display_name || "",
|
|
309
|
+
agent.bio || "",
|
|
310
|
+
]),
|
|
320
311
|
});
|
|
312
|
+
if (renderKey !== lastAgentsRenderKey) {
|
|
313
|
+
document.getElementById("agentsCountHint").textContent = agentsCountHintText;
|
|
314
|
+
document.getElementById("agentsWrap").innerHTML = agentsWrapHtml;
|
|
315
|
+
document.getElementById("agentsPrevPageBtn")?.addEventListener("click", async () => {
|
|
316
|
+
if (agentsPage <= 1) return;
|
|
317
|
+
agentsPage -= 1;
|
|
318
|
+
onPageChange(agentsPage);
|
|
319
|
+
await refreshOverview({ getAgentsPage, getOnlyShowOnline, onPageChange, setOverviewMode, setVisibleRemotePublicCount });
|
|
320
|
+
});
|
|
321
|
+
document.getElementById("agentsNextPageBtn")?.addEventListener("click", async () => {
|
|
322
|
+
if (agentsPage >= totalAgentPages) return;
|
|
323
|
+
agentsPage += 1;
|
|
324
|
+
onPageChange(agentsPage);
|
|
325
|
+
await refreshOverview({ getAgentsPage, getOnlyShowOnline, onPageChange, setOverviewMode, setVisibleRemotePublicCount });
|
|
326
|
+
});
|
|
327
|
+
lastAgentsRenderKey = renderKey;
|
|
328
|
+
}
|
|
321
329
|
writeUiCache("silicaclaw_ui_overview", {
|
|
322
330
|
overviewCardsHtml,
|
|
323
331
|
brandVersionText,
|