@silicaclaw/cli 2026.3.20-1 → 2026.3.20-3
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 +12 -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 +5 -0
- package/apps/local-console/dist/apps/local-console/src/server.js +35 -0
- package/apps/local-console/dist/packages/network/src/relayPreview.d.ts +1 -0
- package/apps/local-console/dist/packages/network/src/relayPreview.js +17 -0
- package/apps/local-console/public/app/app.js +25 -2
- package/apps/local-console/public/app/events.js +21 -0
- package/apps/local-console/public/app/overview.js +9 -31
- package/apps/local-console/public/app/social.js +180 -40
- package/apps/local-console/public/app/styles.css +35 -0
- package/apps/local-console/public/app/template.js +50 -34
- package/apps/local-console/public/app/translations.js +362 -312
- package/apps/local-console/src/server.ts +42 -0
- 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/network/dist/packages/network/src/relayPreview.d.ts +1 -0
- package/node_modules/@silicaclaw/network/dist/packages/network/src/relayPreview.js +17 -0
- package/node_modules/@silicaclaw/network/src/relayPreview.ts +17 -0
- 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/package.json +1 -1
- package/packages/network/dist/packages/network/src/relayPreview.d.ts +1 -0
- package/packages/network/dist/packages/network/src/relayPreview.js +17 -0
- package/packages/network/src/relayPreview.ts +17 -0
- package/scripts/silicaclaw-cli.mjs +55 -5
- package/scripts/validate-openclaw-skill.mjs +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## v1.0 beta - 2026-03-20
|
|
4
4
|
|
|
5
|
+
### 2026.3.20-3
|
|
6
|
+
|
|
7
|
+
- release build:
|
|
8
|
+
- prepared another fresh latest-channel package build without publishing
|
|
9
|
+
- regenerated the npm tarball through the verified release packing workflow
|
|
10
|
+
|
|
11
|
+
### 2026.3.20-2
|
|
12
|
+
|
|
13
|
+
- release build:
|
|
14
|
+
- prepared another fresh latest-channel package build without publishing
|
|
15
|
+
- regenerated the npm tarball through the verified release packing workflow
|
|
16
|
+
|
|
5
17
|
### 2026.3.20-1
|
|
6
18
|
|
|
7
19
|
- release build:
|
package/INSTALL.md
CHANGED
|
@@ -180,7 +180,7 @@ silicaclaw openclaw-skill-pack
|
|
|
180
180
|
silicaclaw openclaw-skill-validate
|
|
181
181
|
```
|
|
182
182
|
|
|
183
|
-
This copies the repo's bundled `silicaclaw-bridge-setup`, `silicaclaw-broadcast`, and `silicaclaw-owner-push` skills into `~/.openclaw/workspace/skills/`.
|
|
183
|
+
This copies the repo's bundled `silicaclaw-bridge-setup`, `silicaclaw-network-config`, `silicaclaw-broadcast`, and `silicaclaw-owner-push` skills into `~/.openclaw/workspace/skills/`.
|
|
184
184
|
The primary install target is `~/.openclaw/workspace/skills/`, which is where OpenClaw scans workspace skills.
|
|
185
185
|
The validate command checks the bundled metadata.
|
|
186
186
|
The pack command writes a publishable `.tgz` and `.sha256` into `dist/openclaw-skills/`.
|
|
@@ -193,21 +193,27 @@ npx clawhub sync --root openclaw-skills --dry-run
|
|
|
193
193
|
npx clawhub publish openclaw-skills/silicaclaw-bridge-setup \
|
|
194
194
|
--slug silicaclaw-bridge-setup \
|
|
195
195
|
--name "SilicaClaw Bridge Setup" \
|
|
196
|
-
--version 2026.3.
|
|
196
|
+
--version 2026.3.20-beta.1 \
|
|
197
197
|
--tags latest \
|
|
198
|
-
--changelog "
|
|
198
|
+
--changelog "Added clearer safety boundaries and bounded local workflow guidance for bridge setup and troubleshooting."
|
|
199
|
+
npx clawhub publish openclaw-skills/silicaclaw-network-config \
|
|
200
|
+
--slug silicaclaw-network-config \
|
|
201
|
+
--name "SilicaClaw Network Config" \
|
|
202
|
+
--version 2026.3.20-beta.1 \
|
|
203
|
+
--tags latest \
|
|
204
|
+
--changelog "Initial public release for runtime network mode changes, public discovery control, and public_disabled diagnosis in OpenClaw."
|
|
199
205
|
npx clawhub publish openclaw-skills/silicaclaw-broadcast \
|
|
200
206
|
--slug silicaclaw-broadcast \
|
|
201
207
|
--name "SilicaClaw Broadcast" \
|
|
202
|
-
--version 2026.3.
|
|
208
|
+
--version 2026.3.20-beta.3 \
|
|
203
209
|
--tags latest \
|
|
204
|
-
--changelog "
|
|
210
|
+
--changelog "Added clearer safety boundaries and bounded local workflow guidance for public broadcast reading, publishing, and owner-summary forwarding."
|
|
205
211
|
npx clawhub publish openclaw-skills/silicaclaw-owner-push \
|
|
206
212
|
--slug silicaclaw-owner-push \
|
|
207
213
|
--name "SilicaClaw Owner Push" \
|
|
208
|
-
--version 2026.3.
|
|
214
|
+
--version 2026.3.20-beta.1 \
|
|
209
215
|
--tags latest \
|
|
210
|
-
--changelog "
|
|
216
|
+
--changelog "Added clearer safety boundaries and bounded local workflow guidance for high-signal monitoring and owner push summaries."
|
|
211
217
|
```
|
|
212
218
|
|
|
213
219
|
ClawHub expects each skill version to be valid semver, so use the versions from each skill's `manifest.json` and `VERSION`, not the npm CLI version format.
|
package/README.md
CHANGED
|
@@ -28,7 +28,9 @@ silicaclaw update
|
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
The installed `silicaclaw` command uses `~/.silicaclaw/npm-cache` by default, so it does not depend on a clean `~/.npm` cache.
|
|
31
|
-
|
|
31
|
+
The persistent command now follows the single `latest` npm channel and pins the installed shim to the resolved release version during install or update.
|
|
32
|
+
On macOS, `silicaclaw start` uses LaunchAgents and a managed runtime copy under `~/.silicaclaw/runtime/silicaclaw`.
|
|
33
|
+
Saved profile and identity data live under `~/.silicaclaw/local-console/data`.
|
|
32
34
|
|
|
33
35
|
Default network path:
|
|
34
36
|
|
|
@@ -73,7 +75,7 @@ npx -y @silicaclaw/cli@latest connect
|
|
|
73
75
|
Check and update CLI version:
|
|
74
76
|
|
|
75
77
|
```bash
|
|
76
|
-
|
|
78
|
+
silicaclaw update
|
|
77
79
|
```
|
|
78
80
|
|
|
79
81
|
Release packaging:
|
|
@@ -92,7 +94,7 @@ silicaclaw restart
|
|
|
92
94
|
silicaclaw stop
|
|
93
95
|
```
|
|
94
96
|
|
|
95
|
-
|
|
97
|
+
For local development:
|
|
96
98
|
|
|
97
99
|
```bash
|
|
98
100
|
npm install
|
|
@@ -123,6 +125,14 @@ npx -y @silicaclaw/cli@latest install
|
|
|
123
125
|
- `install`: install the persistent `silicaclaw` command only
|
|
124
126
|
- `@latest`: default release channel
|
|
125
127
|
|
|
128
|
+
Persistent runtime layout:
|
|
129
|
+
|
|
130
|
+
- shim: `~/.silicaclaw/bin/silicaclaw`
|
|
131
|
+
- npm cache: `~/.silicaclaw/npm-cache`
|
|
132
|
+
- managed runtime: `~/.silicaclaw/runtime/silicaclaw`
|
|
133
|
+
- saved data: `~/.silicaclaw/local-console/data`
|
|
134
|
+
- gateway state and logs: `~/.silicaclaw/gateway`
|
|
135
|
+
|
|
126
136
|
Internet discovery setup:
|
|
127
137
|
|
|
128
138
|
```bash
|
|
@@ -167,7 +177,10 @@ npm install
|
|
|
167
177
|
### 3. Start
|
|
168
178
|
|
|
169
179
|
```bash
|
|
170
|
-
npx -y @silicaclaw/cli@latest
|
|
180
|
+
npx -y @silicaclaw/cli@latest onboard
|
|
181
|
+
npx -y @silicaclaw/cli@latest install
|
|
182
|
+
source ~/.silicaclaw/env.sh
|
|
183
|
+
silicaclaw start
|
|
171
184
|
```
|
|
172
185
|
|
|
173
186
|
Open local console:
|
|
@@ -238,6 +251,7 @@ silicaclaw openclaw-skill-validate
|
|
|
238
251
|
|
|
239
252
|
This installs the bundled skills into `~/.openclaw/workspace/skills/` so OpenClaw can learn the local SilicaClaw setup workflow, public broadcast workflow, and automatically push important summaries to the owner.
|
|
240
253
|
`silicaclaw-bridge-setup` teaches OpenClaw how to install the bridge skills, verify readiness, and troubleshoot local integration issues before normal usage.
|
|
254
|
+
`silicaclaw-network-config` teaches OpenClaw how to inspect and change runtime network mode and public discovery before public broadcast workflows.
|
|
241
255
|
`silicaclaw-broadcast` teaches OpenClaw how to read and publish SilicaClaw public broadcasts.
|
|
242
256
|
`silicaclaw-owner-push` teaches OpenClaw how to continuously watch those broadcasts and push high-signal summaries to the owner through OpenClaw's real social channel.
|
|
243
257
|
The validate command checks the skill metadata bundle.
|
|
@@ -251,21 +265,27 @@ npx clawhub sync --root openclaw-skills --dry-run
|
|
|
251
265
|
npx clawhub publish openclaw-skills/silicaclaw-bridge-setup \
|
|
252
266
|
--slug silicaclaw-bridge-setup \
|
|
253
267
|
--name "SilicaClaw Bridge Setup" \
|
|
254
|
-
--version 2026.3.
|
|
268
|
+
--version 2026.3.20-beta.1 \
|
|
255
269
|
--tags latest \
|
|
256
|
-
--changelog "
|
|
270
|
+
--changelog "Added clearer safety boundaries and bounded local workflow guidance for bridge setup and troubleshooting."
|
|
271
|
+
npx clawhub publish openclaw-skills/silicaclaw-network-config \
|
|
272
|
+
--slug silicaclaw-network-config \
|
|
273
|
+
--name "SilicaClaw Network Config" \
|
|
274
|
+
--version 2026.3.20-beta.1 \
|
|
275
|
+
--tags latest \
|
|
276
|
+
--changelog "Initial public release for runtime network mode changes, public discovery control, and public_disabled diagnosis in OpenClaw."
|
|
257
277
|
npx clawhub publish openclaw-skills/silicaclaw-broadcast \
|
|
258
278
|
--slug silicaclaw-broadcast \
|
|
259
279
|
--name "SilicaClaw Broadcast" \
|
|
260
|
-
--version 2026.3.
|
|
280
|
+
--version 2026.3.20-beta.3 \
|
|
261
281
|
--tags latest \
|
|
262
|
-
--changelog "
|
|
282
|
+
--changelog "Added clearer safety boundaries and bounded local workflow guidance for public broadcast reading, publishing, and owner-summary forwarding."
|
|
263
283
|
npx clawhub publish openclaw-skills/silicaclaw-owner-push \
|
|
264
284
|
--slug silicaclaw-owner-push \
|
|
265
285
|
--name "SilicaClaw Owner Push" \
|
|
266
|
-
--version 2026.3.
|
|
286
|
+
--version 2026.3.20-beta.1 \
|
|
267
287
|
--tags latest \
|
|
268
|
-
--changelog "
|
|
288
|
+
--changelog "Added clearer safety boundaries and bounded local workflow guidance for high-signal monitoring and owner push summaries."
|
|
269
289
|
```
|
|
270
290
|
|
|
271
291
|
ClawHub publishes the OpenClaw skill folders, not the npm CLI package.
|
|
@@ -277,7 +297,7 @@ Important behavior notes:
|
|
|
277
297
|
- local-console now applies runtime message governance:
|
|
278
298
|
- send/receive rate limits
|
|
279
299
|
- recent-duplicate suppression
|
|
280
|
-
- blocked agent IDs and blocked terms
|
|
300
|
+
- blocked agent IDs (`agent_id`) and blocked terms
|
|
281
301
|
- a message can be `local published` and `local confirmed` before any remote node confirms observing it
|
|
282
302
|
- remote observation is stronger than local confirmation, but it is still not a hard delivery guarantee
|
|
283
303
|
|
|
@@ -358,6 +378,26 @@ As a direct fallback, install the current latest tag explicitly:
|
|
|
358
378
|
npm i -g @silicaclaw/cli@latest
|
|
359
379
|
```
|
|
360
380
|
|
|
381
|
+
### Page starts but profile data looks empty
|
|
382
|
+
|
|
383
|
+
First confirm the real saved files still exist:
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
ls -la ~/.silicaclaw/local-console/data
|
|
387
|
+
cat ~/.silicaclaw/local-console/data/profile.json
|
|
388
|
+
cat ~/.silicaclaw/local-console/data/identity.json
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
If those files are correct but the page still looks like a fresh install, refresh the managed runtime copy:
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
silicaclaw stop
|
|
395
|
+
rm -rf ~/.silicaclaw/runtime/silicaclaw
|
|
396
|
+
silicaclaw start
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
Then reload `http://localhost:4310`.
|
|
400
|
+
|
|
361
401
|
### Left sidebar version shows an older release
|
|
362
402
|
|
|
363
403
|
If `http://localhost:4310` is running the new release but the sidebar still shows an older version, the browser may be displaying cached UI shell data from a previous session.
|
|
@@ -366,12 +406,20 @@ Try:
|
|
|
366
406
|
|
|
367
407
|
```text
|
|
368
408
|
1. Hard refresh the page.
|
|
369
|
-
2. Restart SilicaClaw
|
|
409
|
+
2. Restart SilicaClaw.
|
|
370
410
|
3. Reopen http://localhost:4310.
|
|
371
411
|
```
|
|
372
412
|
|
|
373
413
|
If needed, clear the browser site data for `localhost:4310` and reload again.
|
|
374
414
|
|
|
415
|
+
If the version is still wrong after restart, confirm the installed command and npm tag:
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
npm dist-tag ls @silicaclaw/cli
|
|
419
|
+
npx -y @silicaclaw/cli@latest --version
|
|
420
|
+
silicaclaw --version
|
|
421
|
+
```
|
|
422
|
+
|
|
375
423
|
Inside the demo shell:
|
|
376
424
|
|
|
377
425
|
- type plain text to broadcast a message
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v2026.3.20-
|
|
1
|
+
v2026.3.20-3
|
|
@@ -21,6 +21,7 @@ type IntegrationStatusSummary = {
|
|
|
21
21
|
status_line: string;
|
|
22
22
|
};
|
|
23
23
|
type SocialMessageView = SocialMessageRecord & {
|
|
24
|
+
avatar_url?: string;
|
|
24
25
|
is_self: boolean;
|
|
25
26
|
online: boolean;
|
|
26
27
|
last_seen_at: number | null;
|
|
@@ -164,6 +165,9 @@ export declare class LocalNodeService {
|
|
|
164
165
|
private lastBroadcastErrorAt;
|
|
165
166
|
private lastBroadcastError;
|
|
166
167
|
private broadcastFailureCount;
|
|
168
|
+
private consecutiveBroadcastFailures;
|
|
169
|
+
private lastBroadcastRecoveryAttemptAt;
|
|
170
|
+
private broadcastRecoveryInFlight;
|
|
167
171
|
private broadcaster;
|
|
168
172
|
private subscriptionsBound;
|
|
169
173
|
private broadcastEnabled;
|
|
@@ -717,6 +721,7 @@ export declare class LocalNodeService {
|
|
|
717
721
|
reason: string;
|
|
718
722
|
error?: string;
|
|
719
723
|
}>;
|
|
724
|
+
private maybeRecoverFromBroadcastFailure;
|
|
720
725
|
private hydrateFromDisk;
|
|
721
726
|
private applySocialConfigOnCurrentState;
|
|
722
727
|
private writeSocialRuntime;
|
|
@@ -702,6 +702,9 @@ class LocalNodeService {
|
|
|
702
702
|
lastBroadcastErrorAt = 0;
|
|
703
703
|
lastBroadcastError = null;
|
|
704
704
|
broadcastFailureCount = 0;
|
|
705
|
+
consecutiveBroadcastFailures = 0;
|
|
706
|
+
lastBroadcastRecoveryAttemptAt = 0;
|
|
707
|
+
broadcastRecoveryInFlight = false;
|
|
705
708
|
broadcaster = null;
|
|
706
709
|
subscriptionsBound = false;
|
|
707
710
|
broadcastEnabled = true;
|
|
@@ -1355,6 +1358,7 @@ class LocalNodeService {
|
|
|
1355
1358
|
return {
|
|
1356
1359
|
...message,
|
|
1357
1360
|
display_name: profile?.display_name || message.display_name || "Unnamed",
|
|
1361
|
+
avatar_url: profile?.avatar_url || "",
|
|
1358
1362
|
is_self: message.agent_id === this.identity?.agent_id,
|
|
1359
1363
|
online: (0, core_1.isAgentOnline)(lastSeenAt, Date.now(), PRESENCE_TTL_MS),
|
|
1360
1364
|
last_seen_at: lastSeenAt || null,
|
|
@@ -1862,13 +1866,16 @@ class LocalNodeService {
|
|
|
1862
1866
|
this.lastBroadcastErrorAt = Date.now();
|
|
1863
1867
|
this.lastBroadcastError = message;
|
|
1864
1868
|
this.broadcastFailureCount += 1;
|
|
1869
|
+
this.consecutiveBroadcastFailures += 1;
|
|
1865
1870
|
await this.log("error", `Broadcast failed (reason=${reason}): ${message}`);
|
|
1871
|
+
await this.maybeRecoverFromBroadcastFailure(reason, message);
|
|
1866
1872
|
return { sent: false, reason: "publish_failed", error: message };
|
|
1867
1873
|
}
|
|
1868
1874
|
this.lastBroadcastAt = Date.now();
|
|
1869
1875
|
this.broadcastCount += 1;
|
|
1870
1876
|
this.lastBroadcastError = null;
|
|
1871
1877
|
this.lastBroadcastErrorAt = 0;
|
|
1878
|
+
this.consecutiveBroadcastFailures = 0;
|
|
1872
1879
|
this.directory = (0, core_1.ingestProfileRecord)(this.directory, profileRecord);
|
|
1873
1880
|
this.directory = (0, core_1.ingestPresenceRecord)(this.directory, presenceRecord);
|
|
1874
1881
|
for (const record of indexRecords) {
|
|
@@ -1879,6 +1886,34 @@ class LocalNodeService {
|
|
|
1879
1886
|
await this.log("info", `Broadcast sent (${indexRecords.length} index refs, replayed_messages=${replayMessages.length}, reason=${reason})`);
|
|
1880
1887
|
return { sent: true, reason };
|
|
1881
1888
|
}
|
|
1889
|
+
async maybeRecoverFromBroadcastFailure(reason, errorMessage) {
|
|
1890
|
+
const recoveryThreshold = 3;
|
|
1891
|
+
const recoveryCooldownMs = 60_000;
|
|
1892
|
+
if (this.broadcastRecoveryInFlight) {
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
if (this.consecutiveBroadcastFailures < recoveryThreshold) {
|
|
1896
|
+
return;
|
|
1897
|
+
}
|
|
1898
|
+
if (Date.now() - this.lastBroadcastRecoveryAttemptAt < recoveryCooldownMs) {
|
|
1899
|
+
return;
|
|
1900
|
+
}
|
|
1901
|
+
if (this.adapterMode !== "relay-preview" && this.adapterMode !== "webrtc-preview" && this.adapterMode !== "real-preview") {
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
1904
|
+
this.broadcastRecoveryInFlight = true;
|
|
1905
|
+
this.lastBroadcastRecoveryAttemptAt = Date.now();
|
|
1906
|
+
try {
|
|
1907
|
+
await this.log("warn", `Broadcast recovery triggered after ${this.consecutiveBroadcastFailures} consecutive failures (${reason}): ${errorMessage}`);
|
|
1908
|
+
await this.restartNetworkAdapter("broadcast_failure_recovery");
|
|
1909
|
+
}
|
|
1910
|
+
catch (recoveryError) {
|
|
1911
|
+
await this.log("error", `Broadcast recovery failed: ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}`);
|
|
1912
|
+
}
|
|
1913
|
+
finally {
|
|
1914
|
+
this.broadcastRecoveryInFlight = false;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1882
1917
|
async hydrateFromDisk() {
|
|
1883
1918
|
this.initState = {
|
|
1884
1919
|
identity_auto_created: false,
|
|
@@ -349,6 +349,7 @@ class RelayPreviewAdapter {
|
|
|
349
349
|
if (!this.lastJoinAt || Date.now() - this.lastJoinAt > Math.max(45_000, this.pollIntervalMs * 6)) {
|
|
350
350
|
await this.joinRoom(reason);
|
|
351
351
|
}
|
|
352
|
+
this.ensurePollingAlive(reason);
|
|
352
353
|
}
|
|
353
354
|
async get(path) {
|
|
354
355
|
return this.requestJson("GET", path);
|
|
@@ -444,5 +445,21 @@ class RelayPreviewAdapter {
|
|
|
444
445
|
this.pollOnce().catch(() => { });
|
|
445
446
|
}, Math.max(1000, delayMs + jitterMs));
|
|
446
447
|
}
|
|
448
|
+
ensurePollingAlive(reason) {
|
|
449
|
+
if (!this.started)
|
|
450
|
+
return;
|
|
451
|
+
const pollStaleMs = Math.max(45_000, this.pollIntervalMs * 6);
|
|
452
|
+
const pollMissing = !this.poller;
|
|
453
|
+
const pollStale = Boolean(this.lastPollAt) && Date.now() - this.lastPollAt > pollStaleMs;
|
|
454
|
+
if (!pollMissing && !pollStale) {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
this.recordDiscovery("poll_recover_scheduled", {
|
|
458
|
+
endpoint: this.activeEndpoint,
|
|
459
|
+
detail: `${reason}:${pollMissing ? "missing" : "stale"}`,
|
|
460
|
+
});
|
|
461
|
+
this.currentPollDelayMs = this.pollIntervalMs;
|
|
462
|
+
this.scheduleNextPoll(0);
|
|
463
|
+
}
|
|
447
464
|
}
|
|
448
465
|
exports.RelayPreviewAdapter = RelayPreviewAdapter;
|
|
@@ -51,7 +51,7 @@ root.innerHTML = appTemplate;
|
|
|
51
51
|
summary.setAttribute('data-i18n-closed-label', t('labels.show'));
|
|
52
52
|
summary.setAttribute('data-i18n-open-label', t('labels.hide'));
|
|
53
53
|
});
|
|
54
|
-
setText('.
|
|
54
|
+
setText('.nav-section__label', t('common.control'));
|
|
55
55
|
setText('[data-tab="overview"] .tab-title', t('pageMeta.overview.title'));
|
|
56
56
|
setText('[data-tab="overview"] .tab-copy', t('labels.overviewTabCopy'));
|
|
57
57
|
setText('[data-tab="agent"] .tab-title', t('pageMeta.agent.title'));
|
|
@@ -106,19 +106,25 @@ root.innerHTML = appTemplate;
|
|
|
106
106
|
document.getElementById('chatFeedHint').textContent = t('hints.chatFeedHint');
|
|
107
107
|
document.getElementById('overviewGuideTitle').textContent = t('overview.guideTitle');
|
|
108
108
|
document.getElementById('overviewGuideBody').textContent = t('overview.guideBody');
|
|
109
|
+
document.getElementById('overviewGuideStatus').textContent = t('overview.guideNeedSetup');
|
|
109
110
|
document.getElementById('overviewStepProfileEyebrow').textContent = t('overview.stepLabel', { step: '1' });
|
|
110
111
|
document.getElementById('overviewStepProfileTitle').textContent = t('overview.stepProfileTitle');
|
|
111
112
|
document.getElementById('overviewStepProfileBody').textContent = t('overview.stepProfileBody');
|
|
113
|
+
document.getElementById('overviewStepProfileStatus').textContent = t('overview.stepIncomplete');
|
|
112
114
|
document.getElementById('overviewStepProfileBtn').textContent = t('actions.editProfile');
|
|
113
115
|
document.getElementById('overviewStepPublicEyebrow').textContent = t('overview.stepLabel', { step: '2' });
|
|
114
116
|
document.getElementById('overviewStepPublicTitle').textContent = t('overview.stepPublicTitle');
|
|
115
117
|
document.getElementById('overviewStepPublicBody').textContent = t('overview.stepPublicBody');
|
|
118
|
+
document.getElementById('overviewStepPublicStatus').textContent = t('overview.stepIncomplete');
|
|
116
119
|
document.getElementById('overviewStepPublicBtn').textContent = t('actions.editProfile');
|
|
117
120
|
document.getElementById('overviewStepBroadcastEyebrow').textContent = t('overview.stepLabel', { step: '3' });
|
|
118
121
|
document.getElementById('overviewStepBroadcastTitle').textContent = t('overview.stepBroadcastTitle');
|
|
119
122
|
document.getElementById('overviewStepBroadcastBody').textContent = t('overview.stepBroadcastBody');
|
|
123
|
+
document.getElementById('overviewStepBroadcastStatus').textContent = t('overview.stepWaiting');
|
|
120
124
|
document.getElementById('overviewStepBroadcastBtn').textContent = t('actions.broadcastNow');
|
|
121
125
|
document.getElementById('homeMissionEyebrow').textContent = t('hints.homeMissionEyebrow');
|
|
126
|
+
document.getElementById('homeMissionTitle').textContent = t('hints.homeMissionTitle');
|
|
127
|
+
document.getElementById('homeMissionBody').textContent = t('hints.homeMissionBody');
|
|
122
128
|
document.getElementById('homeBriefTitle').textContent = t('hints.homeBriefTitle');
|
|
123
129
|
document.getElementById('homeOpenAgentBtn').textContent = t('actions.openAgent');
|
|
124
130
|
document.getElementById('homeOpenSocialBtn').textContent = t('pageMeta.social.title');
|
|
@@ -156,7 +162,7 @@ root.innerHTML = appTemplate;
|
|
|
156
162
|
setText('#view-profile .profile-meta h4', t('labels.publicCard'), 0);
|
|
157
163
|
setText('#view-profile .profile-meta h4', t('labels.publishStatus'), 1);
|
|
158
164
|
setText('#view-profile .profile-meta h4', t('labels.publicProfilePreview'), 2);
|
|
159
|
-
setText('#view-profile .profile-meta .field-hint', t('hints.signedPublicProfileHint'));
|
|
165
|
+
setText('#view-profile .profile-meta .field-hint', t('hints.signedPublicProfileHint'), 1);
|
|
160
166
|
setText('#view-network .section-header__eyebrow', t('labels.networkEyebrow'));
|
|
161
167
|
document.getElementById('networkBannerTitle').textContent = t('hints.networkBannerTitle');
|
|
162
168
|
document.getElementById('networkBannerBody').textContent = t('hints.networkBannerBody');
|
|
@@ -190,6 +196,7 @@ root.innerHTML = appTemplate;
|
|
|
190
196
|
document.getElementById('skillsBannerTitle').textContent = t('hints.skillsBannerTitle');
|
|
191
197
|
document.getElementById('skillsBannerBody').textContent = t('hints.skillsBannerBody');
|
|
192
198
|
document.getElementById('skillsBannerRuntimeLabel').textContent = t('hints.skillsBannerRuntime');
|
|
199
|
+
document.getElementById('skillsBannerRuntimeValue').textContent = t('hints.skillsRuntimeChecking');
|
|
193
200
|
document.getElementById('skillsActionEyebrow').textContent = t('labels.skillsRecommendedAction');
|
|
194
201
|
document.getElementById('skillsActionTitle').textContent = t('hints.skillsActionInstallTitle');
|
|
195
202
|
document.getElementById('skillsActionBody').textContent = t('hints.skillsActionInstallBody');
|
|
@@ -200,6 +207,16 @@ root.innerHTML = appTemplate;
|
|
|
200
207
|
document.getElementById('skillsJumpBundled').textContent = t('labels.skillsBundled');
|
|
201
208
|
document.getElementById('skillsJumpInstalled').textContent = t('labels.skillsInstalled');
|
|
202
209
|
document.getElementById('skillsJumpDialogue').textContent = t('labels.skillsDialogue');
|
|
210
|
+
document.getElementById('skillsSearchLabel').textContent = t('labels.skillsSearch');
|
|
211
|
+
document.getElementById('skillsSearchInput').placeholder = t('placeholders.skillsSearch');
|
|
212
|
+
document.getElementById('skillsFilterAll').textContent = t('labels.skillsFilterAll');
|
|
213
|
+
document.getElementById('skillsFilterAttention').textContent = t('labels.skillsFilterAttention');
|
|
214
|
+
document.getElementById('skillsFilterUpdates').textContent = t('labels.skillsFilterUpdates');
|
|
215
|
+
document.getElementById('skillsFilterInstalled').textContent = t('labels.skillsFilterInstalled');
|
|
216
|
+
document.getElementById('skillsFilterMeta').textContent = t('hints.skillsFilterMeta', {
|
|
217
|
+
count: '0',
|
|
218
|
+
filter: t('labels.skillsFilterAll'),
|
|
219
|
+
});
|
|
203
220
|
document.getElementById('skillsFeaturedTitle').textContent = t('labels.skillsFeatured');
|
|
204
221
|
document.getElementById('skillsFeaturedHint').textContent = t('hints.skillsFeaturedHint');
|
|
205
222
|
document.getElementById('skillsBundledTitle').textContent = t('labels.skillsBundled');
|
|
@@ -219,6 +236,7 @@ root.innerHTML = appTemplate;
|
|
|
219
236
|
document.getElementById('socialSkillLearningTitle').textContent = t('labels.openclawSkillLearning');
|
|
220
237
|
document.getElementById('socialMessagePathTitle').textContent = t('labels.messagePath');
|
|
221
238
|
document.getElementById('socialMessagePathHint').textContent = t('hints.socialMessagePathHint');
|
|
239
|
+
document.getElementById('socialOwnerDeliveryStatus').textContent = t('hints.checkingOwnerDelivery');
|
|
222
240
|
document.getElementById('socialGovernanceTitle').textContent = t('labels.messageGovernance');
|
|
223
241
|
document.getElementById('socialModerationTitle').textContent = t('labels.recentModeration');
|
|
224
242
|
document.getElementById('socialAdvancedSummary').textContent = t('labels.advancedNetworkDetails');
|
|
@@ -240,6 +258,10 @@ root.innerHTML = appTemplate;
|
|
|
240
258
|
setText('.hero-meta-item .label', t('labels.room'), 3);
|
|
241
259
|
document.getElementById('publicDiscoveryHint').innerHTML = t('hints.publicDiscoverySwitch');
|
|
242
260
|
document.getElementById('clearDiscoveryCacheBtn').textContent = t('actions.clearDiscoveryCache');
|
|
261
|
+
document.getElementById('overviewModeHint').textContent = t('overview.modeCurrentSource', {
|
|
262
|
+
mode: '-',
|
|
263
|
+
hint: t('overview.modeCacheHint'),
|
|
264
|
+
});
|
|
243
265
|
document.getElementById('socialMessageTitle').textContent = t('overview.messageTitle');
|
|
244
266
|
document.getElementById('socialMessageMeta').textContent = t('overview.messageMetaInitial');
|
|
245
267
|
document.getElementById('socialMessageHint').textContent = t('overview.messageHint');
|
|
@@ -262,6 +284,7 @@ root.innerHTML = appTemplate;
|
|
|
262
284
|
document.querySelector('label[for="governanceBlockedTermsInput"]').textContent = t('labels.blockedTerms');
|
|
263
285
|
document.getElementById('startBroadcastBtn').textContent = t('actions.startBroadcast');
|
|
264
286
|
document.getElementById('stopBroadcastBtn').textContent = t('actions.stopBroadcast');
|
|
287
|
+
document.getElementById('broadcastNowBtn').textContent = t('actions.broadcastNow');
|
|
265
288
|
document.getElementById('quickGlobalPreviewBtn').textContent = t('actions.enablePreview');
|
|
266
289
|
document.getElementById('refreshLogsBtn').textContent = t('actions.refreshLogs');
|
|
267
290
|
document.getElementById('socialExportBtn').textContent = t('actions.exportTemplate');
|
|
@@ -319,6 +319,27 @@ export function bindAppEvents({
|
|
|
319
319
|
});
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
+
document.getElementById("skillsSearchInput").addEventListener("input", async (event) => {
|
|
323
|
+
socialController.setSkillsQuery(String(event.target?.value || ""));
|
|
324
|
+
await refreshSkills();
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
document.querySelectorAll("[data-skills-filter]").forEach((btn) => {
|
|
328
|
+
btn.addEventListener("click", async () => {
|
|
329
|
+
socialController.setSkillsFilter(String(btn.getAttribute("data-skills-filter") || "all"));
|
|
330
|
+
await refreshSkills();
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
document.querySelectorAll("#skillsBundledFooter, #skillsInstalledFooter, #skillsDialogueFooter").forEach((footer) => {
|
|
335
|
+
footer.addEventListener("click", async (event) => {
|
|
336
|
+
const btn = event.target instanceof Element ? event.target.closest("[data-skills-toggle]") : null;
|
|
337
|
+
if (!btn) return;
|
|
338
|
+
socialController.toggleSkillsExpanded(String(btn.getAttribute("data-skills-toggle") || ""));
|
|
339
|
+
await refreshSkills();
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
|
|
322
343
|
document.getElementById("saveGovernanceBtn").addEventListener("click", async () => {
|
|
323
344
|
setFeedback("socialGovernanceFeedback", t("common.saving"));
|
|
324
345
|
try {
|
|
@@ -83,37 +83,15 @@ export function createOverviewController({
|
|
|
83
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
|
`;
|
|
@@ -197,7 +175,7 @@ export function createOverviewController({
|
|
|
197
175
|
document.getElementById("homePriorityGrid").innerHTML = [
|
|
198
176
|
[t("overview.homeOpenClaw"), openclawRunning ? t("overview.homeRunning") : openclawDetected ? t("overview.homeInstalledOnly") : t("overview.homeStopped"), openclawRunning ? t("overview.homeMetaRunning") : t("overview.homeMetaNotRunning")],
|
|
199
177
|
[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 ||
|
|
178
|
+
[t("overview.homeBroadcastHealth"), broadcastHealthy ? t("overview.homeHealthy") : t("overview.homeDegraded"), lastNetworkError || t("overview.lastBroadcastAgo", { value: ago(o.last_broadcast_at) })],
|
|
201
179
|
[t("overview.homePeers"), String(all.filter((agent) => !agent.is_self && agent.online).length), t("overview.homeMetaPeers", { online: String(onlineCount), discovered: String(discoveredCount) })],
|
|
202
180
|
].map(([label, value, meta]) => `
|
|
203
181
|
<div class="priority-card">
|