@silicaclaw/cli 2026.3.20-2 → 2026.3.20-4
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 +39 -0
- package/apps/local-console/dist/apps/local-console/src/server.js +220 -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 +274 -3
- package/apps/local-console/public/app/events.js +21 -0
- package/apps/local-console/public/app/network.js +111 -30
- package/apps/local-console/public/app/overview.js +49 -21
- package/apps/local-console/public/app/social.js +315 -93
- package/apps/local-console/public/app/styles.css +86 -0
- package/apps/local-console/public/app/template.js +56 -35
- package/apps/local-console/public/app/translations.js +394 -312
- package/apps/local-console/src/server.ts +251 -1
- 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/openclaw-skills/silicaclaw-owner-push/references/runtime-setup.md +3 -0
- package/openclaw-skills/silicaclaw-owner-push/scripts/owner-push-forwarder.mjs +67 -8
- 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 +4 -1
- package/scripts/silicaclaw-gateway.mjs +108 -0
- package/scripts/validate-openclaw-skill.mjs +19 -0
|
@@ -24,6 +24,134 @@ export function createSocialController({
|
|
|
24
24
|
toPrettyJson,
|
|
25
25
|
writeUiCache,
|
|
26
26
|
}) {
|
|
27
|
+
const SKILLS_SECTION_LIMIT = 4;
|
|
28
|
+
const SKILLS_DIALOGUE_LIMIT = 1;
|
|
29
|
+
let lastMessagesRenderKey = "";
|
|
30
|
+
let lastLogsRenderKey = "";
|
|
31
|
+
const sectionRenderCache = new Map();
|
|
32
|
+
let skillsQuery = "";
|
|
33
|
+
let skillsFilter = "all";
|
|
34
|
+
const skillsExpanded = {
|
|
35
|
+
bundled: false,
|
|
36
|
+
installed: false,
|
|
37
|
+
dialogue: false,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function skillModeLabel(mode) {
|
|
41
|
+
if (mode === "workspace") return t("labels.skillsModeWorkspace");
|
|
42
|
+
if (mode === "legacy") return t("labels.skillsModeLegacy");
|
|
43
|
+
if (mode === "bundled") return t("labels.skillsModeBundled");
|
|
44
|
+
if (mode === "installed") return t("labels.skillsModeInstalled");
|
|
45
|
+
return mode ? String(mode) : t("labels.skillsModeGeneric");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function normalizeSkillSearchText(value) {
|
|
49
|
+
return String(value || "").trim().toLowerCase();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function setSkillsQuery(value) {
|
|
53
|
+
skillsQuery = normalizeSkillSearchText(value);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function setSkillsFilter(value) {
|
|
57
|
+
const next = String(value || "").trim();
|
|
58
|
+
skillsFilter = ["all", "attention", "updates", "installed"].includes(next) ? next : "all";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function toggleSkillsExpanded(section) {
|
|
62
|
+
if (!(section in skillsExpanded)) return;
|
|
63
|
+
skillsExpanded[section] = !skillsExpanded[section];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function skillMatchesSearch(skill) {
|
|
67
|
+
if (!skillsQuery) return true;
|
|
68
|
+
const haystack = [
|
|
69
|
+
skill.display_name,
|
|
70
|
+
skill.name,
|
|
71
|
+
skill.description,
|
|
72
|
+
skill.version,
|
|
73
|
+
...(Array.isArray(skill.capabilities) ? skill.capabilities : []),
|
|
74
|
+
...(Array.isArray(skill.owner_dialogue_examples_zh) ? skill.owner_dialogue_examples_zh : []),
|
|
75
|
+
].map((item) => normalizeSkillSearchText(item)).join(" ");
|
|
76
|
+
return haystack.includes(skillsQuery);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function skillMatchesFilter(skill, section) {
|
|
80
|
+
if (skillsFilter === "all") return true;
|
|
81
|
+
if (skillsFilter === "updates") return Boolean(skill.update_available);
|
|
82
|
+
if (skillsFilter === "installed") {
|
|
83
|
+
return section === "installed" ? true : Boolean(skill.installed_in_openclaw);
|
|
84
|
+
}
|
|
85
|
+
if (skillsFilter === "attention") {
|
|
86
|
+
return section === "installed"
|
|
87
|
+
? Boolean(skill.update_available)
|
|
88
|
+
: Boolean(skill.update_available || !skill.installed_in_openclaw);
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function renderSkillsSectionFooter({ footerId, section, totalCount, visibleCount, limit }) {
|
|
94
|
+
const footer = document.getElementById(footerId);
|
|
95
|
+
if (!footer) return;
|
|
96
|
+
if (totalCount <= limit) {
|
|
97
|
+
footer.innerHTML = "";
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const expanded = skillsExpanded[section];
|
|
101
|
+
const hiddenCount = Math.max(totalCount - visibleCount, 0);
|
|
102
|
+
footer.innerHTML = `
|
|
103
|
+
<button class="secondary skills-section__toggle" type="button" data-skills-toggle="${section}">
|
|
104
|
+
${expanded ? t("actions.showLess") : t("actions.showMoreCount", { count: String(hiddenCount) })}
|
|
105
|
+
</button>
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function renderFilteredSkillCards({ skills, section, gridId, footerId, renderer, limit }) {
|
|
110
|
+
const filtered = skills.filter((skill) => skillMatchesSearch(skill) && skillMatchesFilter(skill, section));
|
|
111
|
+
const expanded = skillsExpanded[section];
|
|
112
|
+
const visible = expanded ? filtered : filtered.slice(0, limit);
|
|
113
|
+
document.getElementById(gridId).innerHTML = visible.length
|
|
114
|
+
? visible.map((skill) => renderer(skill)).join("")
|
|
115
|
+
: `<div class="skills-empty">${t("hints.skillsNoFilterMatch")}</div>`;
|
|
116
|
+
renderSkillsSectionFooter({
|
|
117
|
+
footerId,
|
|
118
|
+
section,
|
|
119
|
+
totalCount: filtered.length,
|
|
120
|
+
visibleCount: visible.length,
|
|
121
|
+
limit,
|
|
122
|
+
});
|
|
123
|
+
return filtered.length;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function renderSkillsFilterMeta({ bundledCount, installedCount, dialogueCount }) {
|
|
127
|
+
const matchedTotal = bundledCount + installedCount + dialogueCount;
|
|
128
|
+
const filterLabel = t(`labels.skillsFilter${skillsFilter.charAt(0).toUpperCase()}${skillsFilter.slice(1)}`);
|
|
129
|
+
document.getElementById("skillsFilterMeta").textContent = t("hints.skillsFilterMeta", {
|
|
130
|
+
count: String(matchedTotal),
|
|
131
|
+
filter: filterLabel,
|
|
132
|
+
});
|
|
133
|
+
document.querySelectorAll("[data-skills-filter]").forEach((btn) => {
|
|
134
|
+
btn.classList.toggle("active", btn.getAttribute("data-skills-filter") === skillsFilter);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function setCachedContent(id, value, mode = "html") {
|
|
139
|
+
const cacheKey = `${mode}:${id}`;
|
|
140
|
+
if (sectionRenderCache.get(cacheKey) === value) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const el = document.getElementById(id);
|
|
144
|
+
if (!el) return;
|
|
145
|
+
if (mode === "text") {
|
|
146
|
+
el.textContent = value;
|
|
147
|
+
} else if (mode === "class") {
|
|
148
|
+
el.className = value;
|
|
149
|
+
} else {
|
|
150
|
+
el.innerHTML = value;
|
|
151
|
+
}
|
|
152
|
+
sectionRenderCache.set(cacheKey, value);
|
|
153
|
+
}
|
|
154
|
+
|
|
27
155
|
function renderSocialMessages() {
|
|
28
156
|
const listEl = document.getElementById("socialMessageList");
|
|
29
157
|
const metaEl = document.getElementById("socialMessageMeta");
|
|
@@ -37,10 +165,16 @@ export function createSocialController({
|
|
|
37
165
|
seconds: String(Math.floor((governance.send_limit?.window_ms || 60000) / 1000)),
|
|
38
166
|
})}`
|
|
39
167
|
: t("overview.messageHint");
|
|
40
|
-
hintEl.textContent = governanceHint;
|
|
41
168
|
if (!socialMessagesCache.length) {
|
|
42
|
-
|
|
43
|
-
|
|
169
|
+
const nextMeta = t("overview.noMessagesMeta");
|
|
170
|
+
const nextHtml = `<div class="empty-state">${t("overview.noMessagesEmpty")}</div>`;
|
|
171
|
+
const renderKey = JSON.stringify({ hint: governanceHint, meta: nextMeta, html: nextHtml });
|
|
172
|
+
if (renderKey !== lastMessagesRenderKey) {
|
|
173
|
+
hintEl.textContent = governanceHint;
|
|
174
|
+
metaEl.textContent = nextMeta;
|
|
175
|
+
listEl.innerHTML = nextHtml;
|
|
176
|
+
lastMessagesRenderKey = renderKey;
|
|
177
|
+
}
|
|
44
178
|
return;
|
|
45
179
|
}
|
|
46
180
|
|
|
@@ -59,16 +193,28 @@ export function createSocialController({
|
|
|
59
193
|
seconds: String(Math.floor((governance.send_limit?.window_ms || 60000) / 1000)),
|
|
60
194
|
})}`
|
|
61
195
|
: "";
|
|
62
|
-
|
|
196
|
+
const nextMeta = `${baseMeta}${governanceMeta}`;
|
|
63
197
|
|
|
64
198
|
if (!filteredMessages.length) {
|
|
65
|
-
|
|
199
|
+
const nextHtml = `<div class="empty-state">${t("overview.noMessagesEmpty")}</div>`;
|
|
200
|
+
const renderKey = JSON.stringify({ hint: governanceHint, meta: nextMeta, html: nextHtml });
|
|
201
|
+
if (renderKey !== lastMessagesRenderKey) {
|
|
202
|
+
hintEl.textContent = governanceHint;
|
|
203
|
+
metaEl.textContent = nextMeta;
|
|
204
|
+
listEl.innerHTML = nextHtml;
|
|
205
|
+
lastMessagesRenderKey = renderKey;
|
|
206
|
+
}
|
|
66
207
|
return;
|
|
67
208
|
}
|
|
68
209
|
|
|
69
|
-
|
|
210
|
+
const nextHtml = filteredMessages
|
|
70
211
|
.map((item) => {
|
|
71
212
|
const visibleRemoteCount = getVisibleRemotePublicCount();
|
|
213
|
+
const avatarUrl = String(item.avatar_url || "").trim();
|
|
214
|
+
const displayName = String(item.display_name || t("overview.unnamed")).trim() || t("overview.unnamed");
|
|
215
|
+
const avatar = avatarUrl
|
|
216
|
+
? `<img class="agent-card__avatar" src="${escapeHtml(avatarUrl)}" alt="${escapeHtml(displayName)}" loading="lazy" />`
|
|
217
|
+
: `<div class="agent-card__avatar-fallback">${escapeHtml((displayName[0] || "?").toUpperCase())}</div>`;
|
|
72
218
|
const selfStatusChips = item.is_self
|
|
73
219
|
? `
|
|
74
220
|
<span class="tag-chip" style="margin-left:8px;">${t("overview.selfMessagePublished")}</span>
|
|
@@ -101,14 +247,17 @@ export function createSocialController({
|
|
|
101
247
|
return `
|
|
102
248
|
<div class="log-item">
|
|
103
249
|
<div style="display:flex; align-items:center; justify-content:space-between; gap:12px;">
|
|
104
|
-
<div>
|
|
105
|
-
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
250
|
+
<div style="display:flex; align-items:flex-start; gap:10px; min-width:0;">
|
|
251
|
+
${avatar}
|
|
252
|
+
<div style="min-width:0;">
|
|
253
|
+
<strong>${escapeHtml(displayName)}</strong>
|
|
254
|
+
<span class="mono" style="color:#90a2c3; margin-left:8px;">${escapeHtml(shortId(item.agent_id || ""))}</span>
|
|
255
|
+
<span class="tag-chip" style="margin-left:8px;">${escapeHtml(item.topic || t("labels.globalTopic"))}</span>
|
|
256
|
+
${item.is_self ? `<span class="tag-chip" style="margin-left:8px;">${t("overview.messageFilterSelf")}</span>` : ""}
|
|
257
|
+
<span class="tag-chip" style="margin-left:8px;">${item.online ? t("overview.online") : t("overview.offline")}</span>
|
|
258
|
+
${observationChip}
|
|
259
|
+
${selfStatusChips}
|
|
260
|
+
</div>
|
|
112
261
|
</div>
|
|
113
262
|
<div class="mono" style="color:#90a2c3;">${new Date(item.created_at).toLocaleString()}</div>
|
|
114
263
|
</div>
|
|
@@ -118,6 +267,25 @@ export function createSocialController({
|
|
|
118
267
|
`;
|
|
119
268
|
})
|
|
120
269
|
.join("");
|
|
270
|
+
const renderKey = JSON.stringify({
|
|
271
|
+
hint: governanceHint,
|
|
272
|
+
meta: nextMeta,
|
|
273
|
+
filter: socialMessageFilter,
|
|
274
|
+
messages: filteredMessages.map((item) => [
|
|
275
|
+
item.message_id,
|
|
276
|
+
item.updated_at || item.created_at,
|
|
277
|
+
item.remote_observation_count || 0,
|
|
278
|
+
item.online ? 1 : 0,
|
|
279
|
+
]),
|
|
280
|
+
visibleRemoteCount: getVisibleRemotePublicCount(),
|
|
281
|
+
});
|
|
282
|
+
if (renderKey === lastMessagesRenderKey) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
hintEl.textContent = governanceHint;
|
|
286
|
+
metaEl.textContent = nextMeta;
|
|
287
|
+
listEl.innerHTML = nextHtml;
|
|
288
|
+
lastMessagesRenderKey = renderKey;
|
|
121
289
|
}
|
|
122
290
|
|
|
123
291
|
async function refreshMessages() {
|
|
@@ -162,19 +330,29 @@ export function createSocialController({
|
|
|
162
330
|
const publicDiscoveryText = status.public_enabled ? t("social.publicDiscoveryEnabled") : t("social.publicDiscoveryDisabled");
|
|
163
331
|
|
|
164
332
|
const namespaceText = `${status.connected_to_silicaclaw ? t("social.connectedToSilicaClaw") : t("social.notConnected")} · ${publicDiscoveryText} · ${t("social.mode")} ${mode}`;
|
|
165
|
-
|
|
166
|
-
|
|
333
|
+
setCachedContent("socialStatusLine", summaryLine, "text");
|
|
334
|
+
setCachedContent("socialStatusSubline", namespaceText, "text");
|
|
167
335
|
const bar = document.getElementById("integrationStatusBar");
|
|
168
|
-
|
|
169
|
-
|
|
336
|
+
const barClassName = `integration-strip ${status.connected_to_silicaclaw && status.public_enabled ? "ok" : "warn"}${getActiveTab() === "overview" ? "" : " hidden"}`;
|
|
337
|
+
const barText = t("social.barStatus", {
|
|
170
338
|
connected: status.connected_to_silicaclaw ? t("common.yes") : t("common.no"),
|
|
171
339
|
mode,
|
|
172
340
|
public: status.public_enabled ? t("common.on") : t("common.off"),
|
|
173
341
|
});
|
|
174
|
-
|
|
342
|
+
if (bar.className !== barClassName) {
|
|
343
|
+
bar.className = barClassName;
|
|
344
|
+
}
|
|
345
|
+
if (bar.textContent !== barText) {
|
|
346
|
+
bar.textContent = barText;
|
|
347
|
+
}
|
|
348
|
+
const brandStatusDot = document.getElementById("brandStatusDot");
|
|
349
|
+
const brandStatusClassName = `sidebar-version__status ${status.connected_to_silicaclaw ? "ok" : "warn"}`;
|
|
350
|
+
if (brandStatusDot.className !== brandStatusClassName) {
|
|
351
|
+
brandStatusDot.className = brandStatusClassName;
|
|
352
|
+
}
|
|
175
353
|
writeUiCache("silicaclaw_ui_social", {
|
|
176
|
-
integrationStatusText:
|
|
177
|
-
integrationStatusClassName:
|
|
354
|
+
integrationStatusText: barText,
|
|
355
|
+
integrationStatusClassName: barClassName,
|
|
178
356
|
socialStatusLineText: summaryLine,
|
|
179
357
|
socialStatusSublineText: namespaceText,
|
|
180
358
|
});
|
|
@@ -182,14 +360,14 @@ export function createSocialController({
|
|
|
182
360
|
if (!status.configured && status.configured_reason) reasons.push(t("social.configuredReason", { reason: status.configured_reason }));
|
|
183
361
|
if (!status.running && status.running_reason) reasons.push(t("social.runningReason", { reason: status.running_reason }));
|
|
184
362
|
if (!status.discoverable && status.discoverable_reason) reasons.push(t("social.discoverableReasonFull", { reason: status.discoverable_reason }));
|
|
185
|
-
|
|
363
|
+
setCachedContent("socialStateHint", reasons.length ? reasons.join(" · ") : t("hints.allIntegrationChecksPassed"), "text");
|
|
186
364
|
const modeSelect = document.getElementById("socialModeSelect");
|
|
187
365
|
const displayedSelectedMode = getSocialModeDirty() && getSocialModePending() ? getSocialModePending() : selectedMode;
|
|
188
366
|
if (modeSelect && displayedSelectedMode !== "-") modeSelect.value = displayedSelectedMode;
|
|
189
367
|
renderSocialModeHint(displayedSelectedMode, mode, !!social.network_requires_restart, getSocialModeDirty());
|
|
190
368
|
setSocialModePendingState(getSocialModeDirty());
|
|
191
369
|
|
|
192
|
-
|
|
370
|
+
setCachedContent("socialPrimaryCards", [
|
|
193
371
|
[t("social.configured"), status.configured ? t("common.yes") : t("common.no")],
|
|
194
372
|
[t("social.running"), status.running ? t("common.yes") : t("common.no")],
|
|
195
373
|
[t("social.discoverable"), discoverable ? t("common.yes") : t("common.no")],
|
|
@@ -197,9 +375,9 @@ export function createSocialController({
|
|
|
197
375
|
[t("social.networkMode"), mode],
|
|
198
376
|
[t("labels.adapter"), effectiveAdapter],
|
|
199
377
|
[t("social.discoverableReason"), status.discoverable_reason || "-"],
|
|
200
|
-
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join("");
|
|
378
|
+
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join(""));
|
|
201
379
|
|
|
202
|
-
|
|
380
|
+
setCachedContent("socialIntegrationCards", [
|
|
203
381
|
[t("social.connected"), bridge.connected_to_silicaclaw ? t("common.yes") : t("common.no")],
|
|
204
382
|
[t("social.messageBroadcast"), bridge.message_broadcast_enabled ? t("common.on") : t("common.off")],
|
|
205
383
|
[t("social.displayName"), status.display_name || t("overview.unnamed")],
|
|
@@ -207,9 +385,9 @@ export function createSocialController({
|
|
|
207
385
|
[t("social.socialFound"), summary.social_md_found ? t("common.yes") : t("common.no")],
|
|
208
386
|
[t("social.socialSource"), summary.social_md_source_path || "-"],
|
|
209
387
|
[t("social.reuseOpenClawIdentity"), summary.reused_openclaw_identity ? t("common.yes") : t("common.no")],
|
|
210
|
-
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join("");
|
|
388
|
+
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join(""));
|
|
211
389
|
|
|
212
|
-
|
|
390
|
+
setCachedContent("socialMessagePathCards", [
|
|
213
391
|
[t("social.messageBroadcast"), bridge.message_broadcast_enabled ? t("common.on") : t("common.off")],
|
|
214
392
|
[t("social.publicDiscovery"), status.public_enabled ? t("common.on") : t("common.off")],
|
|
215
393
|
[t("social.namespace"), effectiveNamespace],
|
|
@@ -218,7 +396,7 @@ export function createSocialController({
|
|
|
218
396
|
[t("network.lastPoll"), networkDiag.last_poll_at ? new Date(networkDiag.last_poll_at).toLocaleTimeString() : "-"],
|
|
219
397
|
[t("network.lastPublish"), networkDiag.last_publish_at ? new Date(networkDiag.last_publish_at).toLocaleTimeString() : "-"],
|
|
220
398
|
[t("network.lastError"), networkDiag.last_error || t("network.none")],
|
|
221
|
-
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${escapeHtml(String(v))}</div></div>`).join("");
|
|
399
|
+
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${escapeHtml(String(v))}</div></div>`).join(""));
|
|
222
400
|
|
|
223
401
|
const skillLearning = bridge.skill_learning || {};
|
|
224
402
|
const ownerDelivery = bridge.owner_delivery || {};
|
|
@@ -246,21 +424,21 @@ export function createSocialController({
|
|
|
246
424
|
ownerDeliveryHeadline = t("feedback.openclawRoleNotRunning");
|
|
247
425
|
ownerDeliveryBody = ownerDelivery.reason || "-";
|
|
248
426
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
427
|
+
setCachedContent("socialOwnerDeliveryStatus", `feedback ${ownerDeliveryTone}`, "class");
|
|
428
|
+
setCachedContent("socialOwnerDeliveryStatus", ownerDeliveryHeadline, "text");
|
|
429
|
+
setCachedContent("socialOwnerDeliverySubline", [
|
|
252
430
|
`${t("social.broadcastReadable")}: ${ownerDelivery.bridge_messages_readable ? t("common.yes") : t("common.no")}`,
|
|
253
431
|
`${t("social.ownerForwardCommand")}: ${ownerDelivery.forward_command_configured ? t("common.yes") : t("common.no")}`,
|
|
254
432
|
`${t("social.ownerForwardReady")}: ${ownerDelivery.ready ? t("common.yes") : t("common.no")}`,
|
|
255
|
-
].join(" · ");
|
|
256
|
-
|
|
257
|
-
|
|
433
|
+
].join(" · "), "text");
|
|
434
|
+
setCachedContent("socialOwnerDeliveryReason", ownerDeliveryBody, "text");
|
|
435
|
+
setCachedContent("socialCapabilityCards", [
|
|
258
436
|
[t("socialCapability.publicBroadcast"), bridge.message_broadcast_enabled ? t("common.yes") : t("common.no")],
|
|
259
437
|
[t("socialCapability.monitorBroadcasts"), ownerDelivery.bridge_messages_readable ? t("common.yes") : t("common.no")],
|
|
260
438
|
[t("socialCapability.autoPushToOwner"), ownerDelivery.ready ? t("common.yes") : t("common.no")],
|
|
261
439
|
[t("socialCapability.ownerPrivateBoundary"), t("socialCapability.ownerPrivateBoundaryValue")],
|
|
262
|
-
].map(([k, v]) => `<div class="card"><div class="label">${escapeHtml(String(k))}</div><div class="value" style="font-size:17px;">${escapeHtml(String(v))}</div></div>`).join("");
|
|
263
|
-
|
|
440
|
+
].map(([k, v]) => `<div class="card"><div class="label">${escapeHtml(String(k))}</div><div class="value" style="font-size:17px;">${escapeHtml(String(v))}</div></div>`).join(""));
|
|
441
|
+
setCachedContent("openclawSkillCards", [
|
|
264
442
|
[t("social.openclawInstalled"), openclawDetected ? t("common.yes") : t("common.no")],
|
|
265
443
|
[t("social.running"), openclawRunning ? t("common.yes") : t("common.no")],
|
|
266
444
|
[t("social.skillInstalled"), skillInstalled ? t("common.yes") : t("common.no")],
|
|
@@ -271,13 +449,13 @@ export function createSocialController({
|
|
|
271
449
|
[t("social.openclawGateway"), bridge.openclaw_runtime?.gateway_url || "-"],
|
|
272
450
|
[t("social.installMode"), skillLearning.install_mode || "-"],
|
|
273
451
|
[t("social.installedPath"), skillInstalled ? installedSkillPath : "-"],
|
|
274
|
-
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${escapeHtml(v)}</div></div>`).join("");
|
|
275
|
-
|
|
452
|
+
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${escapeHtml(v)}</div></div>`).join(""));
|
|
453
|
+
setCachedContent("openclawSkillPath", ownerDelivery.forward_command
|
|
276
454
|
? `${ownerDelivery.forward_command}${ownerDelivery.owner_channel ? ` · ${ownerDelivery.owner_channel}` : ""}${ownerDelivery.owner_target ? ` · ${ownerDelivery.owner_target}` : ""}`
|
|
277
455
|
: skillInstalled
|
|
278
456
|
? installedSkillPath
|
|
279
|
-
: `${installAction.recommended_command || "-"}${bridge.openclaw_runtime?.gateway_url ? ` · detect ${bridge.openclaw_runtime.gateway_url}` : ""}
|
|
280
|
-
|
|
457
|
+
: `${installAction.recommended_command || "-"}${bridge.openclaw_runtime?.gateway_url ? ` · detect ${bridge.openclaw_runtime.gateway_url}` : ""}`, "text");
|
|
458
|
+
setCachedContent("openclawSkillHint", !openclawDetected
|
|
281
459
|
? t("feedback.openclawRoleBroadcasterOnly")
|
|
282
460
|
: !openclawRunning
|
|
283
461
|
? t("feedback.openclawRoleNotRunning")
|
|
@@ -285,11 +463,11 @@ export function createSocialController({
|
|
|
285
463
|
? t("feedback.openclawRoleReadyToLearn")
|
|
286
464
|
: ownerDelivery.ready
|
|
287
465
|
? t("feedback.openclawRoleOwnerReady")
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
: t("feedback.openclawRoleLearned");
|
|
466
|
+
: ownerDelivery.bridge_messages_readable && !ownerDelivery.forward_command_configured
|
|
467
|
+
? t("feedback.openclawRoleLearningOnly")
|
|
468
|
+
: ownerDelivery.bridge_messages_readable
|
|
469
|
+
? t("feedback.openclawRoleNeedsOwnerRoute")
|
|
470
|
+
: t("feedback.openclawRoleLearned"), "text");
|
|
293
471
|
const skillInstallBtn = document.getElementById("openclawSkillInstallBtn");
|
|
294
472
|
skillInstallBtn.textContent = !openclawDetected
|
|
295
473
|
? t("actions.openclawNotInstalled")
|
|
@@ -310,33 +488,33 @@ export function createSocialController({
|
|
|
310
488
|
document.getElementById("governanceDuplicateWindowInput").value = String(Math.floor((policy.duplicate_window_ms ?? 180000) / 1000));
|
|
311
489
|
document.getElementById("governanceBlockedAgentsInput").value = blockedAgentIds.join(", ");
|
|
312
490
|
document.getElementById("governanceBlockedTermsInput").value = blockedTerms.join(", ");
|
|
313
|
-
|
|
491
|
+
setCachedContent("socialGovernanceCards", [
|
|
314
492
|
[t("labels.sendLimit"), `${policy.send_limit?.max ?? "-"} / ${Math.floor((policy.send_limit?.window_ms ?? 60000) / 1000)}s`],
|
|
315
493
|
[t("labels.receiveLimit"), `${policy.receive_limit?.max ?? "-"} / ${Math.floor((policy.receive_limit?.window_ms ?? 60000) / 1000)}s`],
|
|
316
494
|
[t("labels.duplicateWindowSeconds"), `${Math.floor((policy.duplicate_window_ms ?? 0) / 1000)}s`],
|
|
317
495
|
[t("labels.blockedAgentIds"), blockedAgentIds.length],
|
|
318
496
|
[t("labels.blockedTerms"), blockedTerms.length],
|
|
319
|
-
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join("");
|
|
497
|
+
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join(""));
|
|
320
498
|
|
|
321
499
|
const moderationEvents = Array.isArray(governance.recent_events) ? governance.recent_events : [];
|
|
322
|
-
|
|
500
|
+
setCachedContent("socialModerationList", moderationEvents.length === 0
|
|
323
501
|
? `<div class="empty-state">${t("network.noModerationEvents")}</div>`
|
|
324
502
|
: moderationEvents.map((event) => `
|
|
325
503
|
<div class="log-item">
|
|
326
504
|
<div class="log-${event.level || "warn"}">[${String(event.level || "warn").toUpperCase()}] ${escapeHtml(event.message || "-")}</div>
|
|
327
505
|
<div class="mono" style="color:#90a2c3;">${new Date(event.timestamp).toLocaleString()}</div>
|
|
328
506
|
</div>
|
|
329
|
-
`).join("");
|
|
507
|
+
`).join(""));
|
|
330
508
|
|
|
331
|
-
|
|
509
|
+
setCachedContent("socialAdvancedCards", [
|
|
332
510
|
[t("labels.adapter"), effectiveAdapter],
|
|
333
511
|
[t("social.namespace"), effectiveNamespace],
|
|
334
512
|
[t("labels.room"), effectiveRoom],
|
|
335
513
|
[t("social.bridgeStatus"), bridge.connected_to_silicaclaw ? t("common.yes") : t("common.no")],
|
|
336
514
|
[t("social.messageBroadcast"), bridge.message_broadcast_enabled ? t("common.on") : t("common.off")],
|
|
337
515
|
[t("social.restartRequired"), social.network_requires_restart ? t("common.yes") : t("common.no")],
|
|
338
|
-
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join("");
|
|
339
|
-
|
|
516
|
+
].map(([k, v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join(""));
|
|
517
|
+
setCachedContent("socialAdvancedWrap", toPrettyJson({
|
|
340
518
|
effective_runtime: {
|
|
341
519
|
mode: effectiveMode,
|
|
342
520
|
adapter: effectiveAdapter,
|
|
@@ -358,17 +536,17 @@ export function createSocialController({
|
|
|
358
536
|
social_md_found: summary.social_md_found,
|
|
359
537
|
social_md_source_path: summary.social_md_source_path,
|
|
360
538
|
},
|
|
361
|
-
});
|
|
539
|
+
}), "text");
|
|
362
540
|
|
|
363
|
-
|
|
541
|
+
setCachedContent("socialSourceWrap", toPrettyJson({
|
|
364
542
|
found: social.found,
|
|
365
543
|
source_path: social.source_path,
|
|
366
544
|
parse_error: social.parse_error,
|
|
367
|
-
});
|
|
368
|
-
|
|
545
|
+
}), "text");
|
|
546
|
+
setCachedContent("socialRawWrap", toPrettyJson({
|
|
369
547
|
raw_frontmatter: social.raw_frontmatter || null,
|
|
370
|
-
});
|
|
371
|
-
|
|
548
|
+
}), "text");
|
|
549
|
+
setCachedContent("socialRuntimeWrap", toPrettyJson(runtime), "text");
|
|
372
550
|
}
|
|
373
551
|
|
|
374
552
|
async function exportSocialTemplate() {
|
|
@@ -383,23 +561,43 @@ export function createSocialController({
|
|
|
383
561
|
const logLevelFilter = getLogLevelFilter();
|
|
384
562
|
const el = document.getElementById("logList");
|
|
385
563
|
if (!logsCache.length) {
|
|
386
|
-
|
|
564
|
+
const nextHtml = `<div class="empty-state">${t("network.noLogsYet")}</div>`;
|
|
565
|
+
if (nextHtml !== lastLogsRenderKey) {
|
|
566
|
+
el.innerHTML = nextHtml;
|
|
567
|
+
lastLogsRenderKey = nextHtml;
|
|
568
|
+
}
|
|
387
569
|
return;
|
|
388
570
|
}
|
|
389
571
|
const filtered = logLevelFilter === "all" ? logsCache : logsCache.filter((item) => String(item.level || "").toLowerCase() === logLevelFilter);
|
|
390
572
|
if (!filtered.length) {
|
|
391
|
-
|
|
573
|
+
const nextHtml = `<div class="empty-state">${t("network.noLogsForLevel", { level: logLevelFilter })}</div>`;
|
|
574
|
+
if (nextHtml !== lastLogsRenderKey) {
|
|
575
|
+
el.innerHTML = nextHtml;
|
|
576
|
+
lastLogsRenderKey = nextHtml;
|
|
577
|
+
}
|
|
392
578
|
return;
|
|
393
579
|
}
|
|
394
|
-
|
|
580
|
+
const nextHtml = filtered.map((item) => `
|
|
395
581
|
<div class="log-item">
|
|
396
582
|
<div class="log-${item.level}">[${String(item.level).toUpperCase()}] ${item.message}</div>
|
|
397
583
|
<div class="mono" style="color:#90a2c3;">${new Date(item.timestamp).toLocaleString()}</div>
|
|
398
584
|
</div>
|
|
399
585
|
`).join("");
|
|
586
|
+
const renderKey = JSON.stringify({
|
|
587
|
+
level: logLevelFilter,
|
|
588
|
+
items: filtered.map((item) => [item.timestamp, item.level, item.message]),
|
|
589
|
+
});
|
|
590
|
+
if (renderKey === lastLogsRenderKey) {
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
el.innerHTML = nextHtml;
|
|
594
|
+
lastLogsRenderKey = renderKey;
|
|
400
595
|
}
|
|
401
596
|
|
|
402
597
|
async function refreshLogs() {
|
|
598
|
+
if (getActiveTab() !== "network") {
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
403
601
|
setLogsCache((await api("/api/logs")).data || []);
|
|
404
602
|
renderLogs();
|
|
405
603
|
}
|
|
@@ -425,8 +623,8 @@ export function createSocialController({
|
|
|
425
623
|
<div class="skill-card">
|
|
426
624
|
<div class="skill-card__top">
|
|
427
625
|
<div>
|
|
428
|
-
<div class="skill-card__eyebrow">${escapeHtml(options.eyebrow || skill.install_mode || "skill")}</div>
|
|
429
|
-
<div class="skill-card__title">${escapeHtml(skill.display_name || skill.name || "
|
|
626
|
+
<div class="skill-card__eyebrow">${escapeHtml(skillModeLabel(options.eyebrow || skill.install_mode || "skill"))}</div>
|
|
627
|
+
<div class="skill-card__title">${escapeHtml(skill.display_name || skill.name || t("labels.skillsModeGeneric"))}</div>
|
|
430
628
|
</div>
|
|
431
629
|
<div class="skill-card__version mono">${escapeHtml(versionText)}</div>
|
|
432
630
|
</div>
|
|
@@ -476,7 +674,7 @@ export function createSocialController({
|
|
|
476
674
|
<div class="skill-card">
|
|
477
675
|
<div class="skill-card__top">
|
|
478
676
|
<div>
|
|
479
|
-
<div class="skill-card__eyebrow">${escapeHtml(skill.display_name || skill.name || "
|
|
677
|
+
<div class="skill-card__eyebrow">${escapeHtml(skill.display_name || skill.name || t("labels.skillsModeGeneric"))}</div>
|
|
480
678
|
<div class="skill-card__title">${escapeHtml(t("labels.skillsDialogueExamples"))}</div>
|
|
481
679
|
</div>
|
|
482
680
|
<div class="skill-card__version mono">${escapeHtml(skill.version || "-")}</div>
|
|
@@ -604,36 +802,57 @@ export function createSocialController({
|
|
|
604
802
|
`).join("")
|
|
605
803
|
: `<div class="skills-empty">${t("hints.skillsNoBundled")}</div>`;
|
|
606
804
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
805
|
+
const bundledMatchCount = renderFilteredSkillCards({
|
|
806
|
+
skills: bundledSorted,
|
|
807
|
+
section: "bundled",
|
|
808
|
+
gridId: "skillsBundledGrid",
|
|
809
|
+
footerId: "skillsBundledFooter",
|
|
810
|
+
limit: SKILLS_SECTION_LIMIT,
|
|
811
|
+
renderer: (skill) => renderSkillCard(skill, {
|
|
812
|
+
eyebrow: skill.install_mode === "workspace" || skill.install_mode === "legacy" ? skill.install_mode : "bundled",
|
|
813
|
+
statusText: skill.update_available
|
|
814
|
+
? t("labels.skillsUpdateAvailable")
|
|
815
|
+
: skill.installed_in_openclaw
|
|
816
|
+
? `${t("labels.skillsStatus")}: ${t("common.yes")}`
|
|
817
|
+
: t("hints.skillsNotInstalled"),
|
|
818
|
+
installable: true,
|
|
819
|
+
updateAvailable: skill.update_available,
|
|
820
|
+
installedVersion: skill.installed_version,
|
|
821
|
+
bundledVersion: skill.version,
|
|
822
|
+
}),
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
const installedMatchCount = renderFilteredSkillCards({
|
|
826
|
+
skills: installedSorted,
|
|
827
|
+
section: "installed",
|
|
828
|
+
gridId: "skillsInstalledGrid",
|
|
829
|
+
footerId: "skillsInstalledFooter",
|
|
830
|
+
limit: SKILLS_SECTION_LIMIT,
|
|
831
|
+
renderer: (skill) => renderSkillCard(skill, {
|
|
832
|
+
eyebrow: skill.install_mode || "installed",
|
|
833
|
+
statusText: skill.update_available
|
|
834
|
+
? t("labels.skillsUpdateAvailable")
|
|
835
|
+
: `${t("labels.skillsStatus")}: ${escapeHtml(skillModeLabel(skill.install_mode || "installed"))}`,
|
|
836
|
+
updateAvailable: skill.update_available,
|
|
837
|
+
installedVersion: skill.version,
|
|
838
|
+
bundledVersion: skill.bundled_version,
|
|
839
|
+
}),
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
const dialogueMatchCount = renderFilteredSkillCards({
|
|
843
|
+
skills: featuredSkills,
|
|
844
|
+
section: "dialogue",
|
|
845
|
+
gridId: "skillsDialogueGrid",
|
|
846
|
+
footerId: "skillsDialogueFooter",
|
|
847
|
+
limit: SKILLS_DIALOGUE_LIMIT,
|
|
848
|
+
renderer: (skill) => renderDialogueCard(skill),
|
|
849
|
+
});
|
|
621
850
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
: `${t("labels.skillsStatus")}: ${escapeHtml(String(skill.install_mode || "-"))}`,
|
|
628
|
-
updateAvailable: skill.update_available,
|
|
629
|
-
installedVersion: skill.version,
|
|
630
|
-
bundledVersion: skill.bundled_version,
|
|
631
|
-
})).join("")
|
|
632
|
-
: `<div class="skills-empty">${t("hints.skillsNoInstalled")}</div>`;
|
|
633
|
-
|
|
634
|
-
document.getElementById("skillsDialogueGrid").innerHTML = featuredSkills.length
|
|
635
|
-
? featuredSkills.map((skill) => renderDialogueCard(skill)).join("")
|
|
636
|
-
: `<div class="skills-empty">${t("hints.skillsNoDialogueExamples")}</div>`;
|
|
851
|
+
renderSkillsFilterMeta({
|
|
852
|
+
bundledCount: bundledMatchCount,
|
|
853
|
+
installedCount: installedMatchCount,
|
|
854
|
+
dialogueCount: dialogueMatchCount,
|
|
855
|
+
});
|
|
637
856
|
|
|
638
857
|
const installBtn = document.getElementById("skillsInstallBtn");
|
|
639
858
|
installBtn.textContent = !openclawDetected
|
|
@@ -659,6 +878,9 @@ export function createSocialController({
|
|
|
659
878
|
refreshSocial,
|
|
660
879
|
renderLogs,
|
|
661
880
|
renderSocialMessages,
|
|
881
|
+
setSkillsFilter,
|
|
882
|
+
setSkillsQuery,
|
|
662
883
|
setLogLevelFilter,
|
|
884
|
+
toggleSkillsExpanded,
|
|
663
885
|
};
|
|
664
886
|
}
|