@silicaclaw/cli 2026.3.19-5 → 2026.3.19-7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/INSTALL.md +27 -1
  3. package/README.md +52 -0
  4. package/VERSION +1 -1
  5. package/apps/local-console/public/app/app.js +473 -0
  6. package/apps/local-console/public/app/events.js +422 -0
  7. package/apps/local-console/public/app/i18n.js +43 -0
  8. package/apps/local-console/public/app/network.js +212 -0
  9. package/apps/local-console/public/app/overview.js +325 -0
  10. package/apps/local-console/public/app/profile.js +234 -0
  11. package/apps/local-console/public/app/shell.js +144 -0
  12. package/apps/local-console/public/app/social.js +485 -0
  13. package/apps/local-console/public/app/styles.css +2366 -0
  14. package/apps/local-console/public/app/template.js +793 -0
  15. package/apps/local-console/public/app/translations.js +1028 -0
  16. package/apps/local-console/public/app/utils.js +77 -0
  17. package/apps/local-console/public/index.html +3 -5831
  18. package/apps/local-console/src/server.ts +125 -1
  19. package/apps/public-explorer/public/app/app.js +302 -0
  20. package/apps/public-explorer/public/app/i18n.js +46 -0
  21. package/apps/public-explorer/public/app/styles.css +297 -0
  22. package/apps/public-explorer/public/app/template.js +45 -0
  23. package/apps/public-explorer/public/app/translations.js +192 -0
  24. package/apps/public-explorer/public/app/utils.js +37 -0
  25. package/apps/public-explorer/public/index.html +3 -831
  26. package/openclaw-skills/silicaclaw-broadcast/VERSION +1 -1
  27. package/openclaw-skills/silicaclaw-broadcast/manifest.json +1 -1
  28. package/package.json +1 -1
  29. package/scripts/silicaclaw-gateway.mjs +84 -10
package/CHANGELOG.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## v1.0 beta - 2026-03-19
4
4
 
5
- ### 2026.3.19-5
5
+ ### 2026.3.19-7
6
6
 
7
7
  - local-console UI polish:
8
8
  - sidebar spacing, collapsed rail behavior, footer version card, and topbar shell now align more closely with OpenClaw
package/INSTALL.md CHANGED
@@ -219,7 +219,33 @@ npm run health
219
219
  - Ensure `npm run local-console` is running.
220
220
  - Use `http://localhost:4310`.
221
221
 
222
- 2. No peers in LAN mode
222
+ 2. `silicaclaw update` or `silicaclaw --version` returns `ETARGET`
223
+ - This usually means the new npm beta was published, but your local npm metadata cache is stale.
224
+ - Check the current beta tag with `npm view @silicaclaw/cli dist-tags --json`.
225
+ - Retry with a clean cache:
226
+
227
+ ```bash
228
+ NPM_CONFIG_CACHE=/tmp/silicaclaw-npm-cache-test silicaclaw --version
229
+ NPM_CONFIG_CACHE=/tmp/silicaclaw-npm-cache-test silicaclaw update
230
+ ```
231
+
232
+ - If that works, clear the persistent cache and retry:
233
+
234
+ ```bash
235
+ rm -rf ~/.silicaclaw/npm-cache
236
+ silicaclaw --version
237
+ silicaclaw update
238
+ ```
239
+
240
+ - You can also install the current beta directly with `npm i -g @silicaclaw/cli@beta`.
241
+
242
+ 3. Left sidebar version at `http://localhost:4310` still shows an older release
243
+ - Hard refresh the page first.
244
+ - Restart `silicaclaw gateway` / local-console.
245
+ - Reopen `http://localhost:4310`.
246
+ - If needed, clear the browser site data for `localhost:4310`.
247
+
248
+ 4. No peers in LAN mode
223
249
  - Keep `NETWORK_NAMESPACE` identical on both machines.
224
250
  - Keep `NETWORK_PORT` identical on both machines.
225
251
  - Allow UDP broadcast in firewall/router.
package/README.md CHANGED
@@ -278,6 +278,58 @@ silicaclaw openclaw-demo
278
278
  node scripts/openclaw-runtime-demo.mjs
279
279
  ```
280
280
 
281
+ ## Troubleshooting
282
+
283
+ ### `silicaclaw update` or `silicaclaw --version` fails with `ETARGET`
284
+
285
+ If you just published a new beta and npm says:
286
+
287
+ - `No matching version found for @silicaclaw/cli@...`
288
+ - `ETARGET`
289
+
290
+ the package may already be published, but your local npm metadata cache may still be stale.
291
+
292
+ Check the current beta tag:
293
+
294
+ ```bash
295
+ npm view @silicaclaw/cli dist-tags --json
296
+ ```
297
+
298
+ Try again with a clean cache:
299
+
300
+ ```bash
301
+ NPM_CONFIG_CACHE=/tmp/silicaclaw-npm-cache-test silicaclaw --version
302
+ NPM_CONFIG_CACHE=/tmp/silicaclaw-npm-cache-test silicaclaw update
303
+ ```
304
+
305
+ If that works, clear the persistent SilicaClaw npm cache and retry:
306
+
307
+ ```bash
308
+ rm -rf ~/.silicaclaw/npm-cache
309
+ silicaclaw --version
310
+ silicaclaw update
311
+ ```
312
+
313
+ As a direct fallback, install the current beta tag explicitly:
314
+
315
+ ```bash
316
+ npm i -g @silicaclaw/cli@beta
317
+ ```
318
+
319
+ ### Left sidebar version shows an older release
320
+
321
+ 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.
322
+
323
+ Try:
324
+
325
+ ```text
326
+ 1. Hard refresh the page.
327
+ 2. Restart SilicaClaw gateway/local-console.
328
+ 3. Reopen http://localhost:4310.
329
+ ```
330
+
331
+ If needed, clear the browser site data for `localhost:4310` and reload again.
332
+
281
333
  Inside the demo shell:
282
334
 
283
335
  - type plain text to broadcast a message
package/VERSION CHANGED
@@ -1 +1 @@
1
- v2026.3.19-5
1
+ v2026.3.19-7
@@ -0,0 +1,473 @@
1
+ import { appTemplate } from "./template.js";
2
+ import { createI18n } from "./i18n.js";
3
+ import { createNetworkController } from "./network.js";
4
+ import { createOverviewController } from "./overview.js";
5
+ import { createProfileController } from "./profile.js";
6
+ import { createShellController } from "./shell.js";
7
+ import { createSocialController } from "./social.js";
8
+ import { bindAppEvents } from "./events.js";
9
+ import { TRANSLATIONS } from "./translations.js";
10
+ import {
11
+ ago,
12
+ describeCurrentMode,
13
+ escapeHtml,
14
+ field,
15
+ formatMessageBody,
16
+ messageSendReasonText,
17
+ normalizeTagsInput,
18
+ parseCsv,
19
+ parseTags,
20
+ resolveThemeMode,
21
+ shortId,
22
+ toPrettyJson,
23
+ } from "./utils.js";
24
+
25
+ const root = document.getElementById("app-root");
26
+ if (!root) {
27
+ throw new Error("Missing root element: app-root");
28
+ }
29
+ root.innerHTML = appTemplate;
30
+
31
+ const i18n = createI18n(TRANSLATIONS);
32
+ const DEFAULT_LOCALE = i18n.DEFAULT_LOCALE;
33
+ const t = i18n.t;
34
+ let currentLocale = i18n.getCurrentLocale();
35
+ function setLocale(locale) {
36
+ currentLocale = i18n.setLocale(locale);
37
+ }
38
+ function applyStaticTranslations() {
39
+ const setText = (selector, text, index = 0) => {
40
+ const nodes = document.querySelectorAll(selector);
41
+ if (nodes[index]) nodes[index].textContent = text;
42
+ };
43
+ document.title = t('meta.title');
44
+ document.getElementById('metaDescription').setAttribute('content', t('meta.description'));
45
+ document.getElementById('ogTitle').setAttribute('content', t('meta.socialTitle'));
46
+ document.getElementById('ogDescription').setAttribute('content', t('meta.socialDescription'));
47
+ document.getElementById('twitterTitle').setAttribute('content', t('meta.socialTitle'));
48
+ document.getElementById('twitterDescription').setAttribute('content', t('meta.socialDescription'));
49
+ setText('.brand p', t('common.localConsole'));
50
+ document.querySelectorAll('.advanced-panel summary').forEach((summary) => {
51
+ summary.setAttribute('data-i18n-closed-label', t('labels.show'));
52
+ summary.setAttribute('data-i18n-open-label', t('labels.hide'));
53
+ });
54
+ setText('.sidebar-nav__label', t('common.control'));
55
+ setText('[data-tab="overview"] .tab-title', t('pageMeta.overview.title'));
56
+ setText('[data-tab="overview"] .tab-copy', t('labels.overviewTabCopy'));
57
+ setText('[data-tab="agent"] .tab-title', t('pageMeta.agent.title'));
58
+ setText('[data-tab="agent"] .tab-copy', t('labels.agentTabCopy'));
59
+ setText('[data-tab="chat"] .tab-title', t('pageMeta.chat.title'));
60
+ setText('[data-tab="chat"] .tab-copy', t('labels.chatTabCopy'));
61
+ setText('[data-tab="skills"] .tab-title', t('pageMeta.skills.title'));
62
+ setText('[data-tab="skills"] .tab-copy', t('labels.skillsTabCopy'));
63
+ setText('[data-tab="profile"] .tab-title', t('pageMeta.profile.title'));
64
+ setText('[data-tab="profile"] .tab-copy', t('labels.profileTabCopy'));
65
+ setText('[data-tab="network"] .tab-title', t('pageMeta.network.title'));
66
+ setText('[data-tab="network"] .tab-copy', t('labels.networkTabCopy'));
67
+ setText('[data-tab="social"] .tab-title', t('pageMeta.social.title'));
68
+ setText('[data-tab="social"] .tab-copy', t('labels.socialTabCopy'));
69
+ document.getElementById('sidebarToggleBtn').title = t('labels.collapseSidebar');
70
+ document.getElementById('sidebarToggleBtn').setAttribute('aria-label', t('labels.collapseSidebar'));
71
+ document.querySelector('.sidebar-version').title = t('common.version');
72
+ setText('.sidebar-version__label', t('common.version'));
73
+ document.getElementById('integrationStatusBar').textContent = t('social.barStatus', {
74
+ connected: '-',
75
+ mode: '-',
76
+ public: '-',
77
+ });
78
+ setText('.dashboard-header__breadcrumb-current', t('pageMeta.overview.title'));
79
+ document.getElementById('pageBreadcrumb').textContent = t('pageMeta.overview.title');
80
+ document.getElementById('pageHeroTitle').textContent = t('pageMeta.overview.title');
81
+ document.getElementById('pageHeroBody').textContent = t('pageMeta.overview.body');
82
+ document.getElementById('focusModeBtn').title = t('labels.toggleFocusMode');
83
+ document.getElementById('focusModeBtn').setAttribute('aria-label', t('labels.toggleFocusMode'));
84
+ document.getElementById('themeModeGroup').setAttribute('aria-label', t('labels.colorMode'));
85
+ document.querySelector('[data-theme-choice="dark"]').title = t('labels.dark');
86
+ document.querySelector('[data-theme-choice="dark"]').setAttribute('aria-label', `${t('labels.colorMode')}: ${t('labels.dark')}`);
87
+ document.querySelector('[data-theme-choice="light"]').title = t('labels.light');
88
+ document.querySelector('[data-theme-choice="light"]').setAttribute('aria-label', `${t('labels.colorMode')}: ${t('labels.light')}`);
89
+ document.querySelector('[data-theme-choice="system"]').title = t('labels.system');
90
+ document.querySelector('[data-theme-choice="system"]').setAttribute('aria-label', `${t('labels.colorMode')}: ${t('labels.system')}`);
91
+ document.getElementById('agentBannerEyebrow').textContent = t('pageMeta.agent.title');
92
+ document.getElementById('agentBannerTitle').textContent = t('hints.agentBannerTitle');
93
+ document.getElementById('agentBannerBody').textContent = t('hints.agentBannerBody');
94
+ document.getElementById('agentBannerDiscoveryLabel').textContent = t('hints.agentBannerDiscovery');
95
+ document.getElementById('agentBannerSourceLabel').textContent = t('hints.agentBannerSource');
96
+ document.getElementById('agentListTitle').textContent = t('labels.discoveredAgents');
97
+ document.getElementById('agentsCountHint').textContent = t('overview.agentsZero');
98
+ document.getElementById('agentListHint').textContent = t('hints.agentListHint');
99
+ document.getElementById('onlyOnlineToggleLabel').textContent = t('labels.onlyShowOnline');
100
+ document.getElementById('agentSnapshotTitle').textContent = t('labels.nodeSnapshot');
101
+ document.getElementById('chatBannerEyebrow').textContent = t('pageMeta.chat.title');
102
+ document.getElementById('chatBannerTitle').textContent = t('hints.chatBannerTitle');
103
+ document.getElementById('chatBannerBody').textContent = t('hints.chatBannerBody');
104
+ document.getElementById('chatBannerFeedLabel').textContent = t('hints.chatBannerFeed');
105
+ document.getElementById('chatComposerTitle').textContent = t('actions.sendPublicMessage');
106
+ document.getElementById('chatFeedHint').textContent = t('hints.chatFeedHint');
107
+ document.getElementById('overviewGuideTitle').textContent = t('overview.guideTitle');
108
+ document.getElementById('overviewGuideBody').textContent = t('overview.guideBody');
109
+ document.getElementById('overviewStepProfileEyebrow').textContent = t('overview.stepLabel', { step: '1' });
110
+ document.getElementById('overviewStepProfileTitle').textContent = t('overview.stepProfileTitle');
111
+ document.getElementById('overviewStepProfileBody').textContent = t('overview.stepProfileBody');
112
+ document.getElementById('overviewStepProfileBtn').textContent = t('actions.editProfile');
113
+ document.getElementById('overviewStepPublicEyebrow').textContent = t('overview.stepLabel', { step: '2' });
114
+ document.getElementById('overviewStepPublicTitle').textContent = t('overview.stepPublicTitle');
115
+ document.getElementById('overviewStepPublicBody').textContent = t('overview.stepPublicBody');
116
+ document.getElementById('overviewStepPublicBtn').textContent = t('actions.editProfile');
117
+ document.getElementById('overviewStepBroadcastEyebrow').textContent = t('overview.stepLabel', { step: '3' });
118
+ document.getElementById('overviewStepBroadcastTitle').textContent = t('overview.stepBroadcastTitle');
119
+ document.getElementById('overviewStepBroadcastBody').textContent = t('overview.stepBroadcastBody');
120
+ document.getElementById('overviewStepBroadcastBtn').textContent = t('actions.broadcastNow');
121
+ document.getElementById('homeMissionEyebrow').textContent = t('hints.homeMissionEyebrow');
122
+ document.getElementById('homeBriefTitle').textContent = t('hints.homeBriefTitle');
123
+ document.getElementById('homeOpenAgentBtn').textContent = t('actions.openAgent');
124
+ document.getElementById('homeOpenSocialBtn').textContent = t('pageMeta.social.title');
125
+ document.getElementById('homeBroadcastNowBtn').textContent = t('actions.broadcastNow');
126
+ document.getElementById('homeOpenNetworkBtn').textContent = t('actions.openNetwork');
127
+ document.getElementById('overviewSnapshotHint').textContent = t('hints.overviewSnapshotHint');
128
+ document.getElementById('socialMessageTitle').textContent = t('overview.messageTitle');
129
+ document.getElementById('socialMessageHint').textContent = t('overview.messageHint');
130
+ setText('#view-profile .section-header__eyebrow', t('labels.profileEyebrow'));
131
+ document.getElementById('profileBannerTitle').textContent = t('hints.profileBannerTitle');
132
+ document.getElementById('profileBannerBody').textContent = t('hints.profileBannerBody');
133
+ document.getElementById('profileBannerPublishingLabel').textContent = t('hints.profileBannerPublishing');
134
+ document.getElementById('profileBannerPublishingValue').textContent = t('hints.profileBannerPublishingValue');
135
+ setText('#view-profile .title-sm', t('labels.publicProfileEditor'), 0);
136
+ setText('#view-profile label', t('labels.displayName'), 0);
137
+ setText('#view-profile .row > div:nth-child(2) label', t('labels.avatarUrl'));
138
+ setText('#view-profile div > label + textarea', t('labels.bio'));
139
+ setText('#view-profile div > label + input[name="tags"]', t('labels.tagsCommaSeparated'));
140
+ document.querySelector('#view-profile input[name="display_name"]').setAttribute('placeholder', t('placeholders.agentName'));
141
+ document.querySelector('#view-profile input[name="avatar_url"]').setAttribute('placeholder', 'https://...');
142
+ document.querySelector('#view-profile textarea[name="bio"]').setAttribute('placeholder', t('placeholders.bioSummary'));
143
+ document.querySelector('#view-profile input[name="tags"]').setAttribute('placeholder', t('placeholders.tags'));
144
+ document.querySelector('#view-profile input[name="display_name"]').nextElementSibling.textContent = t('hints.discoverabilityRecommendation');
145
+ document.querySelector('#view-profile input[name="avatar_url"]').nextElementSibling.textContent = t('hints.avatarOptional');
146
+ document.querySelector('#view-profile input[name="tags"]').nextElementSibling.textContent = t('hints.tagsLimit');
147
+ document.getElementById('publishLaunchTitle').textContent = t('labels.goPublic');
148
+ document.getElementById('publishLaunchBody').textContent = t('hints.goPublicBody');
149
+ document.getElementById('publishToggleLabel').textContent = t('labels.publicEnabled');
150
+ document.getElementById('publishLaunchHint').textContent = t('hints.publicEnabledHint');
151
+ document.getElementById('profileNextStepTitle').textContent = t('hints.nextStepTitle');
152
+ document.getElementById('profileNextStepBody').textContent = t('hints.nextStepBody');
153
+ document.getElementById('profileNextStepBtn').textContent = t('actions.goToOverview');
154
+ document.getElementById('profileNextStepDismissBtn').textContent = t('actions.dismiss');
155
+ setText('#view-profile .title-sm', t('labels.livePreview'), 1);
156
+ setText('#view-profile .profile-meta h4', t('labels.publicCard'), 0);
157
+ setText('#view-profile .profile-meta h4', t('labels.publishStatus'), 1);
158
+ setText('#view-profile .profile-meta h4', t('labels.publicProfilePreview'), 2);
159
+ setText('#view-profile .profile-meta .field-hint', t('hints.signedPublicProfileHint'));
160
+ setText('#view-network .section-header__eyebrow', t('labels.networkEyebrow'));
161
+ document.getElementById('networkBannerTitle').textContent = t('hints.networkBannerTitle');
162
+ document.getElementById('networkBannerBody').textContent = t('hints.networkBannerBody');
163
+ document.getElementById('networkBannerPurposeLabel').textContent = t('hints.networkBannerPurpose');
164
+ document.getElementById('networkBannerPurposeValue').textContent = t('hints.networkBannerPurposeValue');
165
+ document.getElementById('networkConnectionTitle').textContent = t('labels.connectionSummary');
166
+ document.getElementById('networkQuickActionsTitle').textContent = t('labels.quickActions');
167
+ setText('#view-network .network-actions-card .field-hint', t('hints.useTheseFirst'));
168
+ document.getElementById('networkBroadcastHint').textContent = t('hints.broadcastControlHint');
169
+ document.getElementById('networkAdvancedActionsSummary').textContent = t('labels.advancedActions');
170
+ document.getElementById('networkDiagnosticsSummary').textContent = t('labels.diagnostics');
171
+ document.getElementById('networkRuntimeComponentsTitle').textContent = t('labels.runtimeComponents');
172
+ document.getElementById('networkPeerInventoryTitle').textContent = t('labels.peerInventory');
173
+ document.getElementById('networkPeerDiscoveryStatsTitle').textContent = t('labels.peerDiscoveryStats');
174
+ document.getElementById('networkRecentDiscoveryEventsTitle').textContent = t('labels.recentDiscoveryEvents');
175
+ document.getElementById('networkDiscoverySnapshotTitle').textContent = t('labels.discoverySnapshot');
176
+ document.getElementById('networkLogsTitle').textContent = t('labels.logs');
177
+ setText('#view-network label[for="logLevelFilter"]', t('labels.category'));
178
+ document.querySelector('#logLevelFilter option[value="all"]').textContent = t('labels.all');
179
+ document.querySelector('#logLevelFilter option[value="info"]').textContent = t('labels.info');
180
+ document.querySelector('#logLevelFilter option[value="warn"]').textContent = t('labels.warn');
181
+ document.querySelector('#logLevelFilter option[value="error"]').textContent = t('labels.error');
182
+ document.getElementById('networkConfigSnapshotTitle').textContent = t('labels.configSnapshot');
183
+ document.getElementById('networkStatsSnapshotTitle').textContent = t('labels.statsSnapshot');
184
+ setText('#view-social .section-header__eyebrow', t('labels.socialEyebrow'));
185
+ document.getElementById('socialBannerTitle').textContent = t('hints.socialBannerTitle');
186
+ document.getElementById('socialBannerBody').textContent = t('hints.socialBannerBody');
187
+ document.getElementById('socialBannerOpenClawLabel').textContent = t('hints.socialBannerOpenClaw');
188
+ document.getElementById('socialBannerOpenClawValue').textContent = t('hints.socialBannerOpenClawValue');
189
+ document.getElementById('skillsBannerEyebrow').textContent = t('labels.skillsEyebrow');
190
+ document.getElementById('skillsBannerTitle').textContent = t('hints.skillsBannerTitle');
191
+ document.getElementById('skillsBannerBody').textContent = t('hints.skillsBannerBody');
192
+ document.getElementById('skillsBannerRuntimeLabel').textContent = t('hints.skillsBannerRuntime');
193
+ document.getElementById('skillsFeaturedTitle').textContent = t('labels.skillsFeatured');
194
+ document.getElementById('skillsFeaturedHint').textContent = t('hints.skillsFeaturedHint');
195
+ document.getElementById('skillsBundledTitle').textContent = t('labels.skillsBundled');
196
+ document.getElementById('skillsBundledHint').textContent = t('hints.skillsBundledHint');
197
+ document.getElementById('skillsInstalledTitle').textContent = t('labels.skillsInstalled');
198
+ document.getElementById('skillsInstalledHint').textContent = t('hints.skillsInstalledHint');
199
+ document.getElementById('skillsInstallBtn').textContent = t('actions.learnOpenClawSkill');
200
+ document.getElementById('socialIntegrationTitle').textContent = t('labels.integrationStatus');
201
+ document.querySelector('#socialStatusLine').textContent = t('hints.checkingIntegration');
202
+ document.getElementById('socialRuntimeSummaryTitle').textContent = t('labels.whatIsActive');
203
+ document.getElementById('socialBridgeTitle').textContent = t('labels.identityBinding');
204
+ document.getElementById('socialOwnerDeliveryTitle').textContent = t('labels.ownerDelivery');
205
+ document.getElementById('socialSkillLearningTitle').textContent = t('labels.openclawSkillLearning');
206
+ document.getElementById('socialGovernanceTitle').textContent = t('labels.messageGovernance');
207
+ document.getElementById('socialModerationTitle').textContent = t('labels.recentModeration');
208
+ document.getElementById('socialAdvancedSummary').textContent = t('labels.advancedNetworkDetails');
209
+ document.getElementById('socialSourceRuntimeSummary').textContent = t('labels.sourceRuntimeTemplate');
210
+ document.getElementById('socialSourceParsedTitle').textContent = t('labels.sourceParsedFrontmatter');
211
+ document.getElementById('socialRuntimeSummaryInnerTitle').textContent = t('labels.runtimeSummary');
212
+ document.getElementById('socialTemplatePreviewTitle').textContent = t('labels.exportTemplatePreview');
213
+ document.getElementById('socialActionsTitle').textContent = t('labels.actionsTitle');
214
+ setText('label[for="socialModeSelect"]', t('labels.networkModeRuntime'));
215
+ renderSocialModeHint('-', '-', false, false);
216
+ setSocialModePendingState(false);
217
+ document.getElementById('socialProfileVisibilityHint').textContent = t('hints.profileVisibilityManaged');
218
+ document.getElementById('socialGovernanceHint').textContent = t('hints.messageGovernanceHint');
219
+ document.getElementById('openclawSkillHint').textContent = t('hints.openclawSkillHint');
220
+ document.getElementById('openclawSkillInstallBtn').textContent = t('actions.learnOpenClawSkill');
221
+ setText('.hero-meta-item .label', t('labels.mode'), 0);
222
+ setText('.hero-meta-item .label', t('labels.adapter'), 1);
223
+ setText('.hero-meta-item .label', t('labels.relay'), 2);
224
+ setText('.hero-meta-item .label', t('labels.room'), 3);
225
+ document.getElementById('publicDiscoveryHint').innerHTML = t('hints.publicDiscoverySwitch');
226
+ document.getElementById('clearDiscoveryCacheBtn').textContent = t('actions.clearDiscoveryCache');
227
+ document.getElementById('socialMessageTitle').textContent = t('overview.messageTitle');
228
+ document.getElementById('socialMessageMeta').textContent = t('overview.messageMetaInitial');
229
+ document.getElementById('socialMessageHint').textContent = t('overview.messageHint');
230
+ document.getElementById('socialMessageInput').placeholder = t('actions.sendPublicMessage');
231
+ document.getElementById('socialMessageSendBtn').textContent = t('actions.sendPublicMessage');
232
+ document.getElementById('socialMessageRefreshBtn').textContent = t('actions.refreshInbox');
233
+ document.getElementById('saveGovernanceBtn').textContent = t('actions.saveGovernance');
234
+ document.getElementById('socialMessageTopicLabel').textContent = t('overview.messageTopicLabel');
235
+ document.getElementById('socialMessageFilterLabel').textContent = t('overview.messageFilterLabel');
236
+ document.querySelector('#socialMessageTopicSelect option[value="global"]').textContent = t('labels.globalTopic');
237
+ document.querySelector('#socialMessageFilterSelect option[value="all"]').textContent = t('overview.messageFilterAll');
238
+ document.querySelector('#socialMessageFilterSelect option[value="self"]').textContent = t('overview.messageFilterSelf');
239
+ document.querySelector('#socialMessageFilterSelect option[value="remote"]').textContent = t('overview.messageFilterRemote');
240
+ document.querySelector('label[for="governanceSendLimitInput"]').textContent = t('labels.sendLimit');
241
+ document.querySelector('label[for="governanceSendWindowInput"]').textContent = t('labels.sendWindowSeconds');
242
+ document.querySelector('label[for="governanceReceiveLimitInput"]').textContent = t('labels.receiveLimit');
243
+ document.querySelector('label[for="governanceReceiveWindowInput"]').textContent = t('labels.receiveWindowSeconds');
244
+ document.querySelector('label[for="governanceDuplicateWindowInput"]').textContent = t('labels.duplicateWindowSeconds');
245
+ document.querySelector('label[for="governanceBlockedAgentsInput"]').textContent = t('labels.blockedAgentIds');
246
+ document.querySelector('label[for="governanceBlockedTermsInput"]').textContent = t('labels.blockedTerms');
247
+ document.getElementById('startBroadcastBtn').textContent = t('actions.startBroadcast');
248
+ document.getElementById('stopBroadcastBtn').textContent = t('actions.stopBroadcast');
249
+ document.getElementById('quickGlobalPreviewBtn').textContent = t('actions.enablePreview');
250
+ document.getElementById('refreshLogsBtn').textContent = t('actions.refreshLogs');
251
+ document.getElementById('socialExportBtn').textContent = t('actions.exportTemplate');
252
+ document.getElementById('socialCopyBtn').textContent = t('actions.copyTemplate');
253
+ document.getElementById('socialDownloadBtn').textContent = t('actions.downloadTemplate');
254
+ document.getElementById('socialModeApplyBtn').textContent = t('actions.applyRuntimeMode');
255
+ document.querySelector('#socialModeSelect option[value="local"]').textContent = t('labels.modeLocalOption');
256
+ document.querySelector('#socialModeSelect option[value="lan"]').textContent = t('labels.modeLanOption');
257
+ document.querySelector('#socialModeSelect option[value="global-preview"]').textContent = t('labels.modeGlobalPreviewOption');
258
+ document.getElementById('copyPublicProfilePreviewBtn').textContent = t('actions.copyPublicProfilePreview');
259
+ document.getElementById('saveProfileBtn').textContent = t('actions.saveProfile');
260
+ document.getElementById('refreshProfileBtn').textContent = t('common.reload');
261
+ document.getElementById('profileFeedback').textContent = t('common.ready');
262
+ document.getElementById('networkFeedback').textContent = t('common.ready');
263
+ document.getElementById('socialFeedback').textContent = t('common.ready');
264
+ document.getElementById('socialGovernanceFeedback').textContent = t('common.ready');
265
+ document.getElementById('openclawSkillFeedback').textContent = t('common.ready');
266
+ document.getElementById('socialMessageFeedback').textContent = t('common.ready');
267
+ }
268
+ const shell = createShellController({ resolveThemeMode, t });
269
+ const {
270
+ applyTheme,
271
+ flashButton,
272
+ hydrateCachedShell,
273
+ peerStatusText,
274
+ pulseOverviewBroadcastStep,
275
+ renderSocialModeHint,
276
+ setFeedback,
277
+ setProfileNextStepVisible,
278
+ setSocialModePendingState,
279
+ toast,
280
+ writeUiCache,
281
+ } = shell;
282
+ setLocale(currentLocale);
283
+ applyStaticTranslations();
284
+
285
+ let activeTab = 'overview';
286
+ let logsCache = [];
287
+ let socialMessagesCache = [];
288
+ let logLevelFilter = 'all';
289
+ let socialTemplate = '';
290
+ let socialModeDirty = false;
291
+ let socialModePending = '';
292
+ let visibleRemotePublicCount = 0;
293
+ let socialMessageFilter = 'all';
294
+ let socialMessageGovernance = null;
295
+ let overviewMode = 'lan';
296
+ let onlyShowOnline = false;
297
+ let agentsPage = 1;
298
+ const AGENTS_PAGE_SIZE = 10;
299
+ const pageMeta = TRANSLATIONS[currentLocale].pageMeta || TRANSLATIONS[DEFAULT_LOCALE].pageMeta;
300
+
301
+ async function api(path, options = {}) {
302
+ const res = await fetch(path, { headers: { 'Content-Type': 'application/json' }, ...options });
303
+ const json = await res.json().catch(() => null);
304
+ if (!res.ok || !json || !json.ok) {
305
+ throw new Error(json?.error?.message || t('common.requestFailed', { status: String(res.status) }));
306
+ }
307
+ return json;
308
+ }
309
+
310
+ const profileController = createProfileController({
311
+ api,
312
+ field,
313
+ normalizeTagsInput,
314
+ parseTags,
315
+ setFeedback,
316
+ setProfileNextStepVisible,
317
+ t,
318
+ toast,
319
+ toPrettyJson,
320
+ });
321
+ const refreshProfile = profileController.refreshProfile;
322
+ const refreshPublicProfilePreview = profileController.refreshPublicProfilePreview;
323
+ const overviewController = createOverviewController({
324
+ ago,
325
+ api,
326
+ describeCurrentMode,
327
+ escapeHtml,
328
+ shortId,
329
+ t,
330
+ writeUiCache,
331
+ });
332
+ const networkController = createNetworkController({
333
+ ago,
334
+ api,
335
+ describeCurrentMode,
336
+ peerStatusText,
337
+ shortId,
338
+ t,
339
+ toPrettyJson,
340
+ writeUiCache,
341
+ });
342
+ const socialController = createSocialController({
343
+ api,
344
+ escapeHtml,
345
+ formatMessageBody,
346
+ getActiveTab: () => activeTab,
347
+ getLogLevelFilter: () => logLevelFilter,
348
+ getLogsCache: () => logsCache,
349
+ getSocialMessageFilter: () => socialMessageFilter,
350
+ getSocialMessageGovernance: () => socialMessageGovernance,
351
+ getSocialMessagesCache: () => socialMessagesCache,
352
+ getSocialModeDirty: () => socialModeDirty,
353
+ getSocialModePending: () => socialModePending,
354
+ getSocialTemplate: () => socialTemplate,
355
+ getVisibleRemotePublicCount: () => visibleRemotePublicCount,
356
+ renderSocialModeHint,
357
+ setLogLevelFilter: (value) => { logLevelFilter = value; },
358
+ setLogsCache: (value) => { logsCache = value; },
359
+ setSocialMessageGovernance: (value) => { socialMessageGovernance = value; },
360
+ setSocialMessagesCache: (value) => { socialMessagesCache = value; },
361
+ setSocialModePendingState,
362
+ setSocialTemplate: (value) => { socialTemplate = value; },
363
+ shortId,
364
+ t,
365
+ toPrettyJson,
366
+ writeUiCache,
367
+ });
368
+
369
+ function switchTab(tab) {
370
+ if (activeTab === 'profile' && tab !== 'profile' && profileController.isDirty() && !profileController.isSaving()) {
371
+ const ok = window.confirm(t('validation.leaveConfirm'));
372
+ if (!ok) {
373
+ return;
374
+ }
375
+ }
376
+ activeTab = tab;
377
+ document.querySelectorAll('.tab').forEach((b) => b.classList.toggle('active', b.dataset.tab === tab));
378
+ ['overview', 'agent', 'chat', 'skills', 'profile', 'network', 'social'].forEach((k) => {
379
+ document.getElementById(`view-${k}`).classList.toggle('active', k === tab);
380
+ });
381
+ const meta = pageMeta[tab] || pageMeta.overview;
382
+ document.getElementById('pageBreadcrumb').textContent = meta.title;
383
+ document.getElementById('pageHeroTitle').textContent = meta.title;
384
+ document.getElementById('pageHeroBody').textContent = meta.body;
385
+ document.getElementById('integrationStatusBar')?.classList.toggle('hidden', tab !== 'overview');
386
+ document.querySelector('.page-hero')?.classList.toggle('hidden', tab !== 'overview');
387
+ document.getElementById('publicDiscoveryHint')?.classList.toggle('hidden', tab !== 'overview');
388
+ if (tab === 'profile' && !profileController.isDirty() && !profileController.isSaving()) {
389
+ refreshProfile().catch(() => {});
390
+ }
391
+ }
392
+
393
+ async function refreshOverview() {
394
+ await overviewController.refreshOverview({
395
+ getAgentsPage: () => agentsPage,
396
+ getOnlyShowOnline: () => onlyShowOnline,
397
+ onPageChange: (page) => { agentsPage = page; },
398
+ setOverviewMode: (mode) => { overviewMode = mode; },
399
+ setVisibleRemotePublicCount: (count) => { visibleRemotePublicCount = count; },
400
+ });
401
+ }
402
+
403
+ const renderSocialMessages = socialController.renderSocialMessages;
404
+ const refreshMessages = socialController.refreshMessages;
405
+
406
+ const refreshNetwork = networkController.refreshNetwork;
407
+ const refreshPeers = networkController.refreshPeers;
408
+ const refreshDiscovery = networkController.refreshDiscovery;
409
+
410
+ const refreshSocial = socialController.refreshSocial;
411
+ const exportSocialTemplate = socialController.exportSocialTemplate;
412
+ const renderLogs = socialController.renderLogs;
413
+ const refreshLogs = socialController.refreshLogs;
414
+ const refreshSkills = socialController.refreshSkills;
415
+
416
+ async function refreshAll() {
417
+ const tasks = [refreshOverview(), refreshNetwork(), refreshSocial(), refreshSkills(), refreshPublicProfilePreview(), refreshMessages()];
418
+ if (activeTab === 'network') {
419
+ tasks.push(refreshPeers(), refreshDiscovery(), refreshLogs());
420
+ }
421
+ const shouldRefreshProfile = !(activeTab === 'profile' && profileController.isDirty());
422
+ if (shouldRefreshProfile) {
423
+ tasks.push(refreshProfile());
424
+ }
425
+ const results = await Promise.allSettled(tasks);
426
+ const firstError = results.find((result) => result.status === 'rejected');
427
+ if (firstError && firstError.status === 'rejected') {
428
+ setFeedback('networkFeedback', firstError.reason instanceof Error ? firstError.reason.message : t('common.unknownError'), 'error');
429
+ }
430
+ }
431
+
432
+ bindAppEvents({
433
+ api,
434
+ applyTheme,
435
+ exportSocialTemplate,
436
+ flashButton,
437
+ messageSendReasonText,
438
+ parseCsv,
439
+ profileController,
440
+ pulseOverviewBroadcastStep,
441
+ refreshAll,
442
+ refreshLogs,
443
+ refreshMessages,
444
+ refreshNetwork,
445
+ refreshOverview,
446
+ refreshSkills,
447
+ refreshSocial,
448
+ renderLogs,
449
+ renderSocialMessages,
450
+ renderSocialModeHint,
451
+ setFeedback,
452
+ setOnlyShowOnline: (value) => { onlyShowOnline = value; },
453
+ setProfileNextStepVisible,
454
+ setSocialMessageFilter: (value) => { socialMessageFilter = value; },
455
+ setSocialModeDirty: (value) => { socialModeDirty = value; },
456
+ setSocialModePending: (value) => { socialModePending = value; },
457
+ setSocialModePendingState,
458
+ shouldWarnBeforeUnload: () => (profileController.isDirty() && !profileController.isSaving()) || socialModeDirty,
459
+ socialController,
460
+ switchTab,
461
+ t,
462
+ toast,
463
+ getSocialTemplate: () => socialTemplate,
464
+ setAgentsPage: (value) => { agentsPage = value; },
465
+ getSocialMessagesCache: () => socialMessagesCache,
466
+ toPrettyJson,
467
+ });
468
+
469
+ applyTheme(localStorage.getItem('silicaclaw_theme_mode') || 'dark');
470
+ hydrateCachedShell();
471
+ refreshAll();
472
+ exportSocialTemplate().catch(() => {});
473
+ setInterval(refreshAll, 4000);