@silicaclaw/cli 2026.3.18-4 → 2026.3.19-2

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 (63) hide show
  1. package/ARCHITECTURE.md +15 -0
  2. package/CHANGELOG.md +17 -2
  3. package/INSTALL.md +35 -0
  4. package/README.md +119 -10
  5. package/RELEASE_NOTES_v1.0.md +29 -2
  6. package/SOCIAL_MD_SPEC.md +2 -0
  7. package/VERSION +1 -1
  8. package/apps/local-console/public/index.html +2297 -231
  9. package/apps/local-console/src/server.ts +1120 -24
  10. package/apps/local-console/src/socialRoutes.ts +21 -0
  11. package/apps/public-explorer/public/index.html +190 -43
  12. package/docs/NEW_USER_OPERATIONS.md +35 -5
  13. package/docs/OPENCLAW_BRIDGE.md +449 -0
  14. package/docs/OPENCLAW_BRIDGE_ZH.md +445 -0
  15. package/docs/QUICK_START.md +20 -1
  16. package/docs/release/ANNOUNCEMENT_v1.0-beta.md +68 -0
  17. package/docs/release/FINAL_RELEASE_SUMMARY_v1.0-beta.md +112 -0
  18. package/docs/release/GITHUB_RELEASE_v1.0-beta.md +16 -16
  19. package/docs/release/RELEASE_COPY_v1.0-beta.md +102 -0
  20. package/openclaw-skills/silicaclaw-broadcast/SKILL.md +89 -0
  21. package/openclaw-skills/silicaclaw-broadcast/VERSION +1 -0
  22. package/openclaw-skills/silicaclaw-broadcast/agents/openai.yaml +6 -0
  23. package/openclaw-skills/silicaclaw-broadcast/manifest.json +34 -0
  24. package/openclaw-skills/silicaclaw-broadcast/references/computer-control-via-openclaw.md +41 -0
  25. package/openclaw-skills/silicaclaw-broadcast/references/owner-dispatch-adapter.md +81 -0
  26. package/openclaw-skills/silicaclaw-broadcast/references/owner-forwarding-policy.md +48 -0
  27. package/openclaw-skills/silicaclaw-broadcast/scripts/bridge-client.mjs +59 -0
  28. package/openclaw-skills/silicaclaw-broadcast/scripts/owner-dispatch-adapter-demo.mjs +12 -0
  29. package/openclaw-skills/silicaclaw-broadcast/scripts/owner-forwarder-demo.mjs +111 -0
  30. package/openclaw-skills/silicaclaw-broadcast/scripts/send-to-owner-via-openclaw.mjs +69 -0
  31. package/openclaw.social.md.example +6 -0
  32. package/package.json +2 -1
  33. package/packages/core/dist/index.d.ts +1 -0
  34. package/packages/core/dist/index.js +1 -0
  35. package/packages/core/dist/socialConfig.d.ts +1 -0
  36. package/packages/core/dist/socialConfig.js +9 -1
  37. package/packages/core/dist/socialMessage.d.ts +19 -0
  38. package/packages/core/dist/socialMessage.js +69 -0
  39. package/packages/core/dist/socialTemplate.js +3 -1
  40. package/packages/core/dist/types.d.ts +22 -0
  41. package/packages/core/src/index.ts +1 -0
  42. package/packages/core/src/socialConfig.ts +13 -1
  43. package/packages/core/src/socialMessage.ts +86 -0
  44. package/packages/core/src/socialTemplate.ts +3 -1
  45. package/packages/core/src/types.ts +24 -0
  46. package/packages/network/dist/relayPreview.js +16 -4
  47. package/packages/network/src/relayPreview.ts +17 -4
  48. package/packages/storage/dist/repos.d.ts +40 -0
  49. package/packages/storage/dist/repos.js +27 -1
  50. package/packages/storage/dist/socialRuntimeRepo.js +1 -0
  51. package/packages/storage/src/repos.ts +60 -0
  52. package/packages/storage/src/socialRuntimeRepo.ts +1 -0
  53. package/packages/storage/tsconfig.json +1 -1
  54. package/scripts/functional-check.mjs +85 -2
  55. package/scripts/install-openclaw-skill.mjs +54 -0
  56. package/scripts/openclaw-bridge-adapter.mjs +89 -0
  57. package/scripts/openclaw-bridge-client.mjs +223 -0
  58. package/scripts/openclaw-runtime-demo.mjs +202 -0
  59. package/scripts/pack-openclaw-skill.mjs +58 -0
  60. package/scripts/silicaclaw-cli.mjs +30 -0
  61. package/scripts/silicaclaw-gateway.mjs +215 -0
  62. package/scripts/validate-openclaw-skill.mjs +74 -0
  63. package/social.md.example +6 -0
@@ -377,7 +377,7 @@
377
377
  flex: 1;
378
378
  overflow-y: auto;
379
379
  overflow-x: hidden;
380
- padding: 0;
380
+ padding: 0 2px;
381
381
  }
382
382
  .sidebar-nav::-webkit-scrollbar {
383
383
  display: none;
@@ -473,6 +473,17 @@
473
473
  inset 0 1px 0 color-mix(in srgb, white 10%, transparent),
474
474
  0 10px 18px color-mix(in srgb, black 8%, transparent);
475
475
  }
476
+ .nav button.active::before {
477
+ content: "";
478
+ position: absolute;
479
+ left: 8px;
480
+ top: 9px;
481
+ bottom: 9px;
482
+ width: 3px;
483
+ border-radius: 999px;
484
+ background: color-mix(in srgb, var(--accent) 86%, transparent);
485
+ box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 28%, transparent);
486
+ }
476
487
  .nav button.active .tab-icon {
477
488
  opacity: 1;
478
489
  color: var(--accent);
@@ -656,7 +667,7 @@
656
667
  flex: 1 1 auto;
657
668
  min-height: 0;
658
669
  overflow: auto;
659
- padding: 10px 18px 18px;
670
+ padding: 14px 22px 28px;
660
671
  }
661
672
  .status-row {
662
673
  display: flex;
@@ -665,6 +676,11 @@
665
676
  align-items: center;
666
677
  flex-shrink: 0;
667
678
  min-width: max-content;
679
+ overflow-x: auto;
680
+ scrollbar-width: none;
681
+ }
682
+ .status-row::-webkit-scrollbar {
683
+ display: none;
668
684
  }
669
685
  .topbar-status {
670
686
  display: flex;
@@ -783,6 +799,7 @@
783
799
  }
784
800
  .pill.ok { color: var(--ok); border-color: rgba(34, 197, 94, 0.45); background: rgba(34, 197, 94, 0.08); }
785
801
  .pill.warn { color: var(--warn); border-color: rgba(245, 158, 11, 0.45); background: rgba(245, 158, 11, 0.08); }
802
+ .pill.danger { color: var(--danger); border-color: rgba(239, 68, 68, 0.42); background: rgba(239, 68, 68, 0.08); }
786
803
 
787
804
  .notice {
788
805
  display: none;
@@ -815,6 +832,9 @@
815
832
  .integration-strip.warn {
816
833
  border-color: rgba(245, 158, 11, 0.35);
817
834
  }
835
+ .integration-strip.hidden {
836
+ display: none;
837
+ }
818
838
  .page-hero {
819
839
  display: grid;
820
840
  grid-template-columns: minmax(0, 1fr) 440px;
@@ -822,6 +842,12 @@
822
842
  gap: 6px;
823
843
  margin-bottom: 4px;
824
844
  }
845
+ .page-hero.hidden {
846
+ display: none;
847
+ }
848
+ #publicDiscoveryHint.hidden {
849
+ display: none !important;
850
+ }
825
851
  .hero-copy {
826
852
  display: flex;
827
853
  align-items: center;
@@ -872,7 +898,256 @@
872
898
  .view { display: none; }
873
899
  .view.active {
874
900
  display: grid;
875
- gap: 6px;
901
+ gap: 10px;
902
+ }
903
+ .view-shell {
904
+ display: grid;
905
+ gap: 10px;
906
+ width: min(100%, 1560px);
907
+ margin: 0 auto;
908
+ }
909
+ .page-banner {
910
+ display: grid;
911
+ grid-template-columns: minmax(0, 1.15fr) minmax(280px, 0.85fr);
912
+ gap: 10px;
913
+ align-items: stretch;
914
+ }
915
+ .page-banner__main,
916
+ .page-banner__side {
917
+ border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
918
+ border-radius: 18px;
919
+ background:
920
+ linear-gradient(180deg, color-mix(in srgb, var(--card-strong) 98%, transparent), color-mix(in srgb, var(--card-soft) 96%, transparent));
921
+ box-shadow:
922
+ inset 0 1px 0 color-mix(in srgb, white 4%, transparent),
923
+ 0 12px 28px color-mix(in srgb, black 10%, transparent);
924
+ }
925
+ .page-banner__main {
926
+ padding: 16px 18px;
927
+ }
928
+ .page-banner__eyebrow {
929
+ margin: 0 0 6px;
930
+ color: var(--muted);
931
+ font-size: 11px;
932
+ font-weight: 800;
933
+ letter-spacing: 0.08em;
934
+ text-transform: uppercase;
935
+ }
936
+ .page-banner__title {
937
+ margin: 0;
938
+ color: var(--text-strong);
939
+ font-size: 22px;
940
+ letter-spacing: -0.04em;
941
+ line-height: 1.08;
942
+ }
943
+ .page-banner__body {
944
+ margin: 8px 0 0;
945
+ color: var(--muted);
946
+ font-size: 13px;
947
+ line-height: 1.6;
948
+ max-width: 68ch;
949
+ }
950
+ .page-banner__side {
951
+ display: grid;
952
+ gap: 8px;
953
+ padding: 12px;
954
+ }
955
+ .page-banner__meta {
956
+ border: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
957
+ border-radius: 14px;
958
+ background: color-mix(in srgb, var(--panel) 88%, transparent);
959
+ padding: 10px 12px;
960
+ }
961
+ .page-banner__meta-label {
962
+ color: var(--muted);
963
+ font-size: 11px;
964
+ font-weight: 700;
965
+ letter-spacing: 0.07em;
966
+ text-transform: uppercase;
967
+ }
968
+ .page-banner__meta-value {
969
+ margin-top: 6px;
970
+ color: var(--text);
971
+ font-size: 13px;
972
+ line-height: 1.5;
973
+ }
974
+ .page-section-grid {
975
+ display: grid;
976
+ gap: 10px;
977
+ }
978
+ .page-section-grid.two-col {
979
+ grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.95fr);
980
+ align-items: start;
981
+ }
982
+ .page-column {
983
+ display: grid;
984
+ gap: 10px;
985
+ }
986
+ .overview-home {
987
+ display: grid;
988
+ grid-template-columns: minmax(0, 1.35fr) minmax(320px, 0.95fr);
989
+ gap: 10px;
990
+ }
991
+ .mission-card {
992
+ position: relative;
993
+ overflow: hidden;
994
+ border: 1px solid color-mix(in srgb, var(--border-strong) 70%, transparent);
995
+ border-radius: 20px;
996
+ background:
997
+ radial-gradient(520px 220px at 0% 0%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 62%),
998
+ linear-gradient(180deg, color-mix(in srgb, var(--card-strong) 98%, transparent), color-mix(in srgb, var(--card-soft) 96%, transparent));
999
+ padding: 18px;
1000
+ box-shadow:
1001
+ inset 0 1px 0 color-mix(in srgb, white 6%, transparent),
1002
+ 0 14px 34px color-mix(in srgb, black 14%, transparent);
1003
+ }
1004
+ .mission-card::after {
1005
+ content: "";
1006
+ position: absolute;
1007
+ inset: auto -80px -120px auto;
1008
+ width: 220px;
1009
+ height: 220px;
1010
+ border-radius: 999px;
1011
+ background: color-mix(in srgb, var(--accent) 14%, transparent);
1012
+ filter: blur(24px);
1013
+ pointer-events: none;
1014
+ }
1015
+ .mission-card__eyebrow {
1016
+ display: inline-flex;
1017
+ align-items: center;
1018
+ gap: 8px;
1019
+ margin-bottom: 12px;
1020
+ color: color-mix(in srgb, var(--accent) 74%, white 12%);
1021
+ font-size: 11px;
1022
+ font-weight: 800;
1023
+ letter-spacing: 0.12em;
1024
+ text-transform: uppercase;
1025
+ }
1026
+ .mission-card__title {
1027
+ margin: 0;
1028
+ font-size: 28px;
1029
+ line-height: 1.05;
1030
+ letter-spacing: -0.05em;
1031
+ color: var(--text-strong);
1032
+ max-width: 14ch;
1033
+ }
1034
+ .mission-card__body {
1035
+ margin: 12px 0 0;
1036
+ max-width: 64ch;
1037
+ color: var(--text);
1038
+ font-size: 14px;
1039
+ line-height: 1.65;
1040
+ }
1041
+ .mission-card__status {
1042
+ display: flex;
1043
+ flex-wrap: wrap;
1044
+ gap: 8px;
1045
+ margin-top: 16px;
1046
+ }
1047
+ .mission-status-pill {
1048
+ display: inline-flex;
1049
+ align-items: center;
1050
+ gap: 8px;
1051
+ min-height: 34px;
1052
+ padding: 7px 12px;
1053
+ border-radius: 999px;
1054
+ border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
1055
+ background: color-mix(in srgb, var(--bg-elevated) 76%, transparent);
1056
+ color: var(--text);
1057
+ font-size: 12px;
1058
+ font-weight: 600;
1059
+ }
1060
+ .mission-status-pill:nth-child(1) {
1061
+ border-color: color-mix(in srgb, var(--accent) 18%, transparent);
1062
+ }
1063
+ .mission-status-pill:nth-child(2) {
1064
+ border-color: color-mix(in srgb, var(--info) 20%, transparent);
1065
+ }
1066
+ .mission-status-pill:nth-child(3) {
1067
+ border-color: color-mix(in srgb, var(--ok) 18%, transparent);
1068
+ }
1069
+ .mission-status-pill strong {
1070
+ color: var(--text-strong);
1071
+ }
1072
+ .mission-actions {
1073
+ display: flex;
1074
+ flex-wrap: wrap;
1075
+ gap: 10px;
1076
+ margin-top: 18px;
1077
+ }
1078
+ .mission-side {
1079
+ display: grid;
1080
+ gap: 10px;
1081
+ }
1082
+ .priority-grid {
1083
+ display: grid;
1084
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1085
+ gap: 10px;
1086
+ }
1087
+ .priority-card {
1088
+ border: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
1089
+ border-radius: 18px;
1090
+ background:
1091
+ linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 96%, transparent), color-mix(in srgb, var(--panel) 98%, transparent));
1092
+ padding: 14px;
1093
+ box-shadow: inset 0 1px 0 color-mix(in srgb, white 4%, transparent);
1094
+ }
1095
+ .priority-card__label {
1096
+ color: var(--muted);
1097
+ font-size: 11px;
1098
+ font-weight: 700;
1099
+ letter-spacing: 0.08em;
1100
+ text-transform: uppercase;
1101
+ }
1102
+ .priority-card__value {
1103
+ margin-top: 10px;
1104
+ color: var(--text-strong);
1105
+ font-size: 22px;
1106
+ line-height: 1.1;
1107
+ letter-spacing: -0.04em;
1108
+ }
1109
+ .priority-card__meta {
1110
+ margin-top: 8px;
1111
+ color: var(--muted);
1112
+ font-size: 12px;
1113
+ line-height: 1.5;
1114
+ }
1115
+ .home-brief {
1116
+ border: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
1117
+ border-radius: 18px;
1118
+ background: color-mix(in srgb, var(--bg-elevated) 94%, transparent);
1119
+ padding: 14px;
1120
+ }
1121
+ .home-brief__title {
1122
+ margin: 0 0 10px;
1123
+ color: var(--text-strong);
1124
+ font-size: 15px;
1125
+ }
1126
+ .home-brief__list {
1127
+ display: grid;
1128
+ gap: 10px;
1129
+ }
1130
+ .home-brief__item {
1131
+ display: grid;
1132
+ gap: 4px;
1133
+ padding-bottom: 10px;
1134
+ border-bottom: 1px solid color-mix(in srgb, var(--border) 68%, transparent);
1135
+ }
1136
+ .home-brief__item:last-child {
1137
+ padding-bottom: 0;
1138
+ border-bottom: none;
1139
+ }
1140
+ .home-brief__label {
1141
+ color: var(--muted);
1142
+ font-size: 11px;
1143
+ font-weight: 700;
1144
+ letter-spacing: 0.07em;
1145
+ text-transform: uppercase;
1146
+ }
1147
+ .home-brief__value {
1148
+ color: var(--text);
1149
+ font-size: 13px;
1150
+ line-height: 1.5;
876
1151
  }
877
1152
 
878
1153
  .overview-panel-header {
@@ -893,6 +1168,8 @@
893
1168
  align-items: center;
894
1169
  gap: 10px;
895
1170
  flex-shrink: 0;
1171
+ flex-wrap: wrap;
1172
+ justify-content: flex-end;
896
1173
  }
897
1174
  .overview-inline-toggle {
898
1175
  display: inline-flex;
@@ -902,6 +1179,193 @@
902
1179
  font-size: 12px;
903
1180
  white-space: nowrap;
904
1181
  }
1182
+ .onboarding-guide {
1183
+ display: grid;
1184
+ gap: 10px;
1185
+ }
1186
+ .onboarding-guide__header {
1187
+ display: flex;
1188
+ align-items: flex-start;
1189
+ justify-content: space-between;
1190
+ gap: 12px;
1191
+ }
1192
+ .onboarding-guide__title {
1193
+ margin: 0;
1194
+ font-size: 16px;
1195
+ color: var(--text-strong);
1196
+ }
1197
+ .onboarding-guide__body {
1198
+ margin: 4px 0 0;
1199
+ color: var(--muted);
1200
+ font-size: 13px;
1201
+ line-height: 1.5;
1202
+ }
1203
+ .onboarding-guide__status {
1204
+ display: inline-flex;
1205
+ align-items: center;
1206
+ gap: 8px;
1207
+ flex-wrap: wrap;
1208
+ }
1209
+ .onboarding-guide__steps {
1210
+ display: grid;
1211
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1212
+ gap: 10px;
1213
+ }
1214
+ .onboarding-step {
1215
+ border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
1216
+ border-radius: 14px;
1217
+ background: color-mix(in srgb, var(--panel) 88%, transparent);
1218
+ padding: 12px;
1219
+ }
1220
+ .onboarding-step.is-done {
1221
+ border-color: rgba(34, 197, 94, 0.38);
1222
+ background: rgba(34, 197, 94, 0.07);
1223
+ }
1224
+ .onboarding-step.is-highlighted {
1225
+ border-color: color-mix(in srgb, var(--accent) 42%, transparent);
1226
+ box-shadow:
1227
+ 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent),
1228
+ 0 16px 34px color-mix(in srgb, var(--accent) 18%, transparent);
1229
+ }
1230
+ .onboarding-step__eyebrow {
1231
+ margin-bottom: 6px;
1232
+ color: var(--muted);
1233
+ font-size: 11px;
1234
+ font-weight: 700;
1235
+ letter-spacing: 0.08em;
1236
+ text-transform: uppercase;
1237
+ }
1238
+ .onboarding-step__title {
1239
+ margin: 0;
1240
+ font-size: 14px;
1241
+ color: var(--text-strong);
1242
+ }
1243
+ .onboarding-step__body {
1244
+ margin: 6px 0 10px;
1245
+ color: var(--muted);
1246
+ font-size: 12px;
1247
+ line-height: 1.5;
1248
+ min-height: 54px;
1249
+ }
1250
+ .onboarding-step__footer {
1251
+ display: flex;
1252
+ align-items: center;
1253
+ justify-content: space-between;
1254
+ gap: 10px;
1255
+ }
1256
+ .onboarding-step__status {
1257
+ font-size: 12px;
1258
+ color: var(--muted);
1259
+ }
1260
+ .section-surface.compact {
1261
+ padding: 10px 12px;
1262
+ }
1263
+ #view-agent .section-surface.compact {
1264
+ margin-top: 10px;
1265
+ }
1266
+ #view-agent .section-surface.compact .onboarding-guide {
1267
+ gap: 8px;
1268
+ }
1269
+ #view-agent .section-surface.compact .onboarding-guide__title {
1270
+ font-size: 14px;
1271
+ }
1272
+ #view-agent .section-surface.compact .onboarding-guide__body {
1273
+ font-size: 12px;
1274
+ line-height: 1.45;
1275
+ }
1276
+ #view-agent .section-surface.compact .onboarding-guide__steps {
1277
+ gap: 8px;
1278
+ }
1279
+ #view-agent .section-surface.compact .onboarding-step {
1280
+ padding: 9px 10px;
1281
+ border-radius: 12px;
1282
+ }
1283
+ #view-agent .section-surface.compact .onboarding-step__eyebrow {
1284
+ margin-bottom: 4px;
1285
+ font-size: 10px;
1286
+ }
1287
+ #view-agent .section-surface.compact .onboarding-step__title {
1288
+ font-size: 13px;
1289
+ }
1290
+ #view-agent .section-surface.compact .onboarding-step__body {
1291
+ min-height: 0;
1292
+ margin: 4px 0 8px;
1293
+ font-size: 12px;
1294
+ line-height: 1.4;
1295
+ }
1296
+ .subtle-hint {
1297
+ margin-top: 6px;
1298
+ color: var(--muted);
1299
+ font-size: 12px;
1300
+ line-height: 1.5;
1301
+ }
1302
+ .publish-launch {
1303
+ border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
1304
+ border-radius: 16px;
1305
+ background: color-mix(in srgb, var(--panel) 92%, transparent);
1306
+ padding: 12px;
1307
+ }
1308
+ .publish-launch.is-public {
1309
+ border-color: rgba(34, 197, 94, 0.38);
1310
+ background: rgba(34, 197, 94, 0.08);
1311
+ }
1312
+ .publish-launch__header {
1313
+ display: flex;
1314
+ align-items: flex-start;
1315
+ justify-content: space-between;
1316
+ gap: 12px;
1317
+ }
1318
+ .publish-launch__title {
1319
+ margin: 0;
1320
+ font-size: 15px;
1321
+ color: var(--text-strong);
1322
+ }
1323
+ .publish-launch__body {
1324
+ margin: 4px 0 0;
1325
+ color: var(--muted);
1326
+ font-size: 12px;
1327
+ line-height: 1.5;
1328
+ }
1329
+ .publish-toggle {
1330
+ display: inline-flex;
1331
+ align-items: center;
1332
+ gap: 8px;
1333
+ border: 1px solid color-mix(in srgb, var(--border) 78%, transparent);
1334
+ border-radius: 999px;
1335
+ padding: 7px 12px;
1336
+ background: color-mix(in srgb, var(--bg-elevated) 94%, transparent);
1337
+ color: var(--text);
1338
+ font-size: 12px;
1339
+ font-weight: 600;
1340
+ }
1341
+ .publish-launch__status {
1342
+ margin-top: 10px;
1343
+ font-size: 13px;
1344
+ font-weight: 600;
1345
+ color: var(--text-strong);
1346
+ }
1347
+ .next-step-banner {
1348
+ display: none;
1349
+ margin-top: 10px;
1350
+ border: 1px solid color-mix(in srgb, var(--accent) 26%, transparent);
1351
+ border-radius: 14px;
1352
+ background: var(--accent-subtle);
1353
+ padding: 12px;
1354
+ }
1355
+ .next-step-banner.show {
1356
+ display: block;
1357
+ }
1358
+ .next-step-banner__title {
1359
+ margin: 0;
1360
+ font-size: 14px;
1361
+ color: var(--text-strong);
1362
+ }
1363
+ .next-step-banner__body {
1364
+ margin: 4px 0 10px;
1365
+ color: var(--muted);
1366
+ font-size: 12px;
1367
+ line-height: 1.5;
1368
+ }
905
1369
 
906
1370
  .section-header {
907
1371
  display: flex;
@@ -957,17 +1421,22 @@
957
1421
  grid-template-columns: repeat(4, minmax(0, 1fr));
958
1422
  }
959
1423
  #networkCards,
960
- #socialPrimaryCards,
961
- #socialIntegrationCards,
962
1424
  #socialAdvancedCards {
963
1425
  grid-template-columns: repeat(3, minmax(0, 1fr));
964
1426
  }
1427
+ #socialPrimaryCards,
1428
+ #socialIntegrationCards,
1429
+ #openclawSkillCards,
1430
+ #socialGovernanceCards {
1431
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1432
+ }
965
1433
  .card {
966
1434
  border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
967
1435
  border-radius: 16px;
968
1436
  background:
969
1437
  linear-gradient(180deg, color-mix(in srgb, var(--card-strong) 98%, transparent), color-mix(in srgb, var(--card-soft) 96%, transparent));
970
- padding: 10px;
1438
+ padding: 14px;
1439
+ min-width: 0;
971
1440
  box-shadow:
972
1441
  inset 0 1px 0 color-mix(in srgb, white 4%, transparent),
973
1442
  0 12px 24px color-mix(in srgb, black 9%, transparent);
@@ -980,13 +1449,26 @@
980
1449
  0 18px 36px color-mix(in srgb, black 14%, transparent);
981
1450
  }
982
1451
  .label { font-size: 12px; color: var(--muted); }
983
- .value { margin-top: 4px; font-size: 22px; font-weight: 800; letter-spacing: -0.03em; }
1452
+ .value {
1453
+ margin-top: 4px;
1454
+ font-size: 22px;
1455
+ font-weight: 800;
1456
+ letter-spacing: -0.03em;
1457
+ min-width: 0;
1458
+ line-height: 1.3;
1459
+ white-space: normal;
1460
+ word-break: break-word;
1461
+ overflow-wrap: anywhere;
1462
+ }
984
1463
 
985
1464
  .split {
986
1465
  margin-top: 4px;
987
1466
  display: grid;
988
1467
  gap: 6px;
989
- grid-template-columns: 1.2fr 1fr;
1468
+ grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
1469
+ }
1470
+ .split > * {
1471
+ min-width: 0;
990
1472
  }
991
1473
  .title-sm { margin: 0 0 6px; font-size: 15px; letter-spacing: -0.02em; }
992
1474
  .mono { font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
@@ -1005,9 +1487,12 @@
1005
1487
  .table th, .table td {
1006
1488
  border-bottom: 1px solid var(--border);
1007
1489
  text-align: left;
1008
- padding: 7px 6px;
1490
+ padding: 9px 8px;
1009
1491
  font-size: 13px;
1010
1492
  }
1493
+ .table tbody tr:hover {
1494
+ background: color-mix(in srgb, var(--bg-hover) 68%, transparent);
1495
+ }
1011
1496
  .agent-list {
1012
1497
  display: grid;
1013
1498
  gap: 8px;
@@ -1017,10 +1502,16 @@
1017
1502
  grid-template-columns: auto minmax(0, 1fr) auto auto;
1018
1503
  gap: 10px;
1019
1504
  align-items: center;
1020
- padding: 9px 10px;
1505
+ padding: 12px;
1021
1506
  border: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
1022
1507
  border-radius: 14px;
1023
1508
  background: linear-gradient(180deg, color-mix(in srgb, var(--panel) 94%, transparent), color-mix(in srgb, var(--bg-elevated) 90%, transparent));
1509
+ transition: border-color .16s ease, transform .16s ease, box-shadow .16s ease;
1510
+ }
1511
+ .agent-card:hover {
1512
+ border-color: color-mix(in srgb, var(--accent) 16%, var(--border));
1513
+ transform: translateY(-1px);
1514
+ box-shadow: 0 14px 28px color-mix(in srgb, black 12%, transparent);
1024
1515
  }
1025
1516
  .agent-card__avatar {
1026
1517
  width: 34px;
@@ -1209,6 +1700,12 @@
1209
1700
  gap: 8px;
1210
1701
  flex-wrap: wrap;
1211
1702
  }
1703
+ .actions > button:first-child:not(.secondary),
1704
+ .mission-actions > button:not(.secondary):first-of-type {
1705
+ box-shadow:
1706
+ 0 12px 26px color-mix(in srgb, var(--accent) 20%, transparent),
1707
+ inset 0 1px 0 rgba(255,255,255,0.08);
1708
+ }
1212
1709
  .actions button,
1213
1710
  .action-bar button,
1214
1711
  .toolbar button {
@@ -1228,7 +1725,7 @@
1228
1725
  .summary-item {
1229
1726
  display: grid;
1230
1727
  gap: 3px;
1231
- padding: 9px;
1728
+ padding: 12px;
1232
1729
  border-radius: 12px;
1233
1730
  border: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
1234
1731
  background: linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 98%, transparent), color-mix(in srgb, var(--panel) 94%, transparent));
@@ -1249,9 +1746,17 @@
1249
1746
  background: var(--accent);
1250
1747
  color: #ffffff;
1251
1748
  font-weight: 700;
1252
- padding: 9px 13px;
1749
+ min-height: 40px;
1750
+ padding: 9px 14px;
1253
1751
  cursor: pointer;
1254
1752
  box-shadow: 0 10px 20px color-mix(in srgb, var(--accent) 16%, transparent);
1753
+ transition:
1754
+ transform .16s ease,
1755
+ filter .16s ease,
1756
+ background .16s ease,
1757
+ border-color .16s ease,
1758
+ color .16s ease,
1759
+ box-shadow .16s ease;
1255
1760
  }
1256
1761
  button:hover {
1257
1762
  transform: translateY(-1px);
@@ -1286,6 +1791,14 @@
1286
1791
  border-color: color-mix(in srgb, var(--accent) 18%, var(--border-strong));
1287
1792
  background: color-mix(in srgb, var(--bg-hover) 86%, transparent);
1288
1793
  }
1794
+ button:disabled,
1795
+ button[disabled] {
1796
+ opacity: 0.55;
1797
+ cursor: not-allowed;
1798
+ transform: none !important;
1799
+ filter: none !important;
1800
+ box-shadow: none !important;
1801
+ }
1289
1802
 
1290
1803
  .feedback {
1291
1804
  border: 1px solid color-mix(in srgb, var(--border) 84%, transparent);
@@ -1297,10 +1810,27 @@
1297
1810
  box-shadow: inset 0 1px 0 color-mix(in srgb, white 4%, transparent);
1298
1811
  line-height: 1.45;
1299
1812
  }
1813
+ .feedback.info {
1814
+ border-color: color-mix(in srgb, var(--info) 32%, transparent);
1815
+ background: color-mix(in srgb, var(--info) 10%, var(--bg-elevated));
1816
+ }
1817
+ .feedback.warn {
1818
+ border-color: color-mix(in srgb, var(--warn) 34%, transparent);
1819
+ background: color-mix(in srgb, var(--warn) 10%, var(--bg-elevated));
1820
+ }
1821
+ .feedback.error {
1822
+ border-color: color-mix(in srgb, var(--danger) 36%, transparent);
1823
+ background: color-mix(in srgb, var(--danger) 10%, var(--bg-elevated));
1824
+ }
1300
1825
  .profile-layout {
1301
1826
  display: grid;
1302
- gap: 8px;
1303
- grid-template-columns: 1.1fr .9fr;
1827
+ gap: 10px;
1828
+ align-items: start;
1829
+ grid-template-columns: minmax(0, 1.12fr) minmax(320px, 0.88fr);
1830
+ }
1831
+ .profile-layout > .card:last-child {
1832
+ position: sticky;
1833
+ top: 0;
1304
1834
  }
1305
1835
  .profile-meta {
1306
1836
  border: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
@@ -1339,6 +1869,10 @@
1339
1869
  padding: 3px 9px;
1340
1870
  font-size: 12px;
1341
1871
  }
1872
+ .tag-chip.emphasis {
1873
+ border-color: color-mix(in srgb, var(--accent) 22%, transparent);
1874
+ background: color-mix(in srgb, var(--accent-subtle) 78%, transparent);
1875
+ }
1342
1876
  .tag-chip.muted {
1343
1877
  color: var(--muted);
1344
1878
  border-style: dashed;
@@ -1361,6 +1895,12 @@
1361
1895
  opacity: 0.7;
1362
1896
  cursor: wait;
1363
1897
  }
1898
+ .button-pending {
1899
+ border-color: color-mix(in srgb, var(--accent) 42%, transparent);
1900
+ box-shadow:
1901
+ 0 0 0 1px color-mix(in srgb, var(--accent) 20%, transparent),
1902
+ 0 10px 22px color-mix(in srgb, var(--accent) 16%, transparent);
1903
+ }
1364
1904
 
1365
1905
  .logs {
1366
1906
  max-height: 420px;
@@ -1368,14 +1908,17 @@
1368
1908
  border: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
1369
1909
  border-radius: 14px;
1370
1910
  background: linear-gradient(180deg, color-mix(in srgb, var(--panel) 97%, transparent), color-mix(in srgb, var(--bg-elevated) 92%, transparent));
1371
- padding: 9px;
1911
+ padding: 10px;
1372
1912
  box-shadow: inset 0 1px 0 color-mix(in srgb, white 3%, transparent);
1373
1913
  }
1374
1914
  .log-item {
1375
- border-bottom: 1px dashed var(--border);
1376
- padding: 7px 0;
1915
+ border: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
1916
+ border-radius: 12px;
1917
+ padding: 10px 12px;
1918
+ background: linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 96%, transparent), color-mix(in srgb, var(--panel) 94%, transparent));
1919
+ margin-bottom: 8px;
1377
1920
  }
1378
- .log-item:last-child { border-bottom: 0; }
1921
+ .log-item:last-child { margin-bottom: 0; }
1379
1922
  .log-info { color: #8dc6ff; }
1380
1923
  .log-warn { color: var(--warn); }
1381
1924
  .log-error { color: var(--danger); }
@@ -1390,15 +1933,50 @@
1390
1933
  .toolbar .field {
1391
1934
  min-width: 180px;
1392
1935
  }
1936
+ .chat-layout {
1937
+ display: grid;
1938
+ gap: 10px;
1939
+ grid-template-columns: minmax(320px, 0.88fr) minmax(0, 1.12fr);
1940
+ align-items: start;
1941
+ }
1942
+ .chat-compose-card {
1943
+ position: sticky;
1944
+ top: 0;
1945
+ }
1946
+ .chat-compose-card textarea {
1947
+ min-height: 220px;
1948
+ }
1949
+ .chat-feed-card .logs {
1950
+ min-height: 560px;
1951
+ max-height: none;
1952
+ }
1953
+ .chat-feed-card .log-item {
1954
+ padding: 12px 14px;
1955
+ }
1956
+ .chat-feed-card .overview-panel-header,
1957
+ .chat-compose-card .overview-panel-header {
1958
+ margin-bottom: 12px;
1959
+ }
1960
+ .network-actions-card .actions,
1961
+ .social-skill-card .actions {
1962
+ margin-top: 12px;
1963
+ }
1964
+ .network-diagnostics-stack,
1965
+ .social-advanced-stack {
1966
+ display: grid;
1967
+ gap: 10px;
1968
+ }
1393
1969
  .mono-block {
1394
1970
  border: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
1395
1971
  border-radius: 12px;
1396
1972
  background: linear-gradient(180deg, color-mix(in srgb, var(--bg-elevated) 97%, transparent), color-mix(in srgb, var(--panel) 93%, transparent));
1397
1973
  padding: 9px;
1974
+ max-width: 100%;
1398
1975
  max-height: 240px;
1399
1976
  overflow: auto;
1400
1977
  white-space: pre-wrap;
1401
1978
  word-break: break-word;
1979
+ overflow-wrap: anywhere;
1402
1980
  box-shadow: inset 0 1px 0 color-mix(in srgb, white 3%, transparent);
1403
1981
  }
1404
1982
  .advanced-panel {
@@ -1449,18 +2027,49 @@
1449
2027
  transform: translateY(0);
1450
2028
  }
1451
2029
 
1452
- #view-overview .action-bar {
2030
+ #view-overview .action-bar,
2031
+ #view-agent .action-bar {
1453
2032
  margin-bottom: 0;
2033
+ display: flex;
2034
+ gap: 10px;
2035
+ align-items: center;
2036
+ flex-wrap: wrap;
1454
2037
  }
1455
- #view-overview .grid {
2038
+ #view-agent .grid {
1456
2039
  grid-template-columns: repeat(4, minmax(0, 1fr));
1457
2040
  }
1458
- #view-overview .card .field-hint {
2041
+ #view-agent .card .field-hint {
1459
2042
  font-size: 12px;
1460
2043
  }
1461
- #view-overview #snapshot {
2044
+ #view-agent #snapshot {
1462
2045
  line-height: 1.55;
1463
2046
  }
2047
+ #view-agent .view-shell,
2048
+ #view-chat .view-shell,
2049
+ #view-profile .view-shell,
2050
+ #view-network .view-shell,
2051
+ #view-social .view-shell {
2052
+ gap: 10px;
2053
+ }
2054
+ #view-network #networkCards {
2055
+ grid-template-columns: repeat(4, minmax(0, 1fr));
2056
+ }
2057
+ #view-social .page-column > .card,
2058
+ #view-social .page-column > details.card,
2059
+ #view-social .page-column > details.advanced-panel.card {
2060
+ height: auto;
2061
+ }
2062
+
2063
+ @media (max-width: 1240px) {
2064
+ .page-section-grid.two-col,
2065
+ .chat-layout,
2066
+ .overview-home {
2067
+ grid-template-columns: 1fr;
2068
+ }
2069
+ #view-network #networkCards {
2070
+ grid-template-columns: repeat(3, minmax(0, 1fr));
2071
+ }
2072
+ }
1464
2073
 
1465
2074
  @media (max-width: 980px) {
1466
2075
  html, body {
@@ -1477,25 +2086,130 @@
1477
2086
  border-bottom: 1px solid var(--border);
1478
2087
  height: auto;
1479
2088
  overflow: visible;
2089
+ position: sticky;
2090
+ top: 0;
2091
+ z-index: 20;
2092
+ backdrop-filter: blur(14px) saturate(1.3);
2093
+ -webkit-backdrop-filter: blur(14px) saturate(1.3);
1480
2094
  }
1481
2095
  .sidebar-shell {
1482
2096
  display: block;
2097
+ padding: 10px 12px 12px;
1483
2098
  }
1484
- .nav { grid-template-columns: repeat(2, minmax(0,1fr)); }
1485
- .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
1486
- .split, .row, .profile-layout, .page-hero { grid-template-columns: 1fr; }
2099
+ .sidebar-shell__header {
2100
+ padding: 0 2px 10px;
2101
+ }
2102
+ .sidebar-nav {
2103
+ overflow-x: auto;
2104
+ overflow-y: hidden;
2105
+ padding: 0;
2106
+ scrollbar-width: none;
2107
+ }
2108
+ .sidebar-nav::-webkit-scrollbar {
2109
+ display: none;
2110
+ }
2111
+ .nav {
2112
+ display: flex;
2113
+ gap: 8px;
2114
+ min-width: max-content;
2115
+ padding-bottom: 2px;
2116
+ }
2117
+ .nav-section {
2118
+ display: contents;
2119
+ }
2120
+ .nav-section__label {
2121
+ display: none;
2122
+ }
2123
+ .nav-section__items {
2124
+ display: flex;
2125
+ gap: 8px;
2126
+ }
2127
+ .nav button {
2128
+ min-width: 124px;
2129
+ min-height: 46px;
2130
+ padding: 0 12px;
2131
+ border-radius: 14px;
2132
+ background: color-mix(in srgb, var(--bg-elevated) 84%, transparent);
2133
+ border-color: color-mix(in srgb, var(--border) 72%, transparent);
2134
+ }
2135
+ .nav button.active::before {
2136
+ left: 10px;
2137
+ top: auto;
2138
+ bottom: 6px;
2139
+ width: calc(100% - 20px);
2140
+ height: 3px;
2141
+ }
2142
+ .grid,
2143
+ #view-network #networkCards,
2144
+ #socialPrimaryCards,
2145
+ #socialIntegrationCards,
2146
+ #openclawSkillCards,
2147
+ #socialGovernanceCards,
2148
+ #socialAdvancedCards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
2149
+ .split, .row, .profile-layout, .page-hero, .overview-home, .onboarding-guide__steps, .page-banner, .page-section-grid.two-col, .chat-layout { grid-template-columns: 1fr; }
2150
+ .priority-grid { grid-template-columns: 1fr; }
1487
2151
  .hero-copy {
1488
2152
  display: grid;
1489
2153
  gap: 4px;
1490
2154
  }
2155
+ .profile-layout > .card:last-child,
2156
+ .chat-compose-card {
2157
+ position: static;
2158
+ }
1491
2159
  .main {
1492
2160
  height: auto;
1493
2161
  overflow: visible;
1494
2162
  padding-bottom: 18px;
1495
2163
  }
1496
- .main-scroll {
1497
- overflow: visible;
1498
- padding-right: 0;
2164
+ .topbar {
2165
+ min-height: 54px;
2166
+ padding: 0 14px;
2167
+ }
2168
+ .topnav-shell {
2169
+ gap: 10px;
2170
+ min-height: 46px;
2171
+ }
2172
+ .topbar-status {
2173
+ max-width: 52vw;
2174
+ justify-content: flex-end;
2175
+ }
2176
+ .main-scroll {
2177
+ overflow: visible;
2178
+ padding: 12px 14px 22px;
2179
+ }
2180
+ }
2181
+ @media (max-width: 720px) {
2182
+ .topnav-shell {
2183
+ align-items: center;
2184
+ }
2185
+ .dashboard-header__breadcrumb {
2186
+ font-size: 12px;
2187
+ }
2188
+ .topbar-status {
2189
+ max-width: 48vw;
2190
+ }
2191
+ .topbar-actions {
2192
+ gap: 6px;
2193
+ }
2194
+ .icon-btn {
2195
+ width: 30px;
2196
+ height: 30px;
2197
+ }
2198
+ .page-banner__main,
2199
+ .page-banner__side,
2200
+ .mission-card,
2201
+ .card {
2202
+ border-radius: 16px;
2203
+ }
2204
+ .page-banner__title,
2205
+ .mission-card__title {
2206
+ font-size: 20px;
2207
+ max-width: none;
2208
+ }
2209
+ .page-banner__body,
2210
+ .mission-card__body {
2211
+ font-size: 12.5px;
2212
+ line-height: 1.55;
1499
2213
  }
1500
2214
  }
1501
2215
  </style>
@@ -1536,7 +2250,34 @@
1536
2250
  <line x1="6" x2="6" y1="20" y2="16"></line>
1537
2251
  </svg>
1538
2252
  </span>
1539
- <span class="tab-labels"><span class="tab-title">Overview</span><span class="tab-copy">Agent summary and discovered peers</span></span>
2253
+ <span class="tab-labels"><span class="tab-title">Overview</span><span class="tab-copy">OpenClaw-first homepage and mission status</span></span>
2254
+ </button>
2255
+ <button class="tab nav-item" data-tab="agent">
2256
+ <span class="tab-icon" aria-hidden="true">
2257
+ <svg viewBox="0 0 24 24">
2258
+ <circle cx="12" cy="8" r="4"></circle>
2259
+ <path d="M5 20c1.6-3.8 4.2-5.7 7-5.7s5.4 1.9 7 5.7"></path>
2260
+ </svg>
2261
+ </span>
2262
+ <span class="tab-labels"><span class="tab-title">Agent</span><span class="tab-copy">Agent list, node snapshot, and broadcast feed</span></span>
2263
+ </button>
2264
+ <button class="tab nav-item" data-tab="chat">
2265
+ <span class="tab-icon" aria-hidden="true">
2266
+ <svg viewBox="0 0 24 24">
2267
+ <path d="M21 15a2 2 0 0 1-2 2H8l-5 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
2268
+ <path d="M8 9h8"></path>
2269
+ <path d="M8 13h6"></path>
2270
+ </svg>
2271
+ </span>
2272
+ <span class="tab-labels"><span class="tab-title">Chat</span><span class="tab-copy">Public broadcast feed and message sending</span></span>
2273
+ </button>
2274
+ <button class="tab nav-item" data-tab="social">
2275
+ <span class="tab-icon" aria-hidden="true">
2276
+ <svg viewBox="0 0 24 24">
2277
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
2278
+ </svg>
2279
+ </span>
2280
+ <span class="tab-labels"><span class="tab-title">Social</span><span class="tab-copy">social.md config and runtime state</span></span>
1540
2281
  </button>
1541
2282
  <button class="tab nav-item" data-tab="profile">
1542
2283
  <span class="tab-icon" aria-hidden="true">
@@ -1558,14 +2299,6 @@
1558
2299
  </svg>
1559
2300
  </span>
1560
2301
  <span class="tab-labels"><span class="tab-title">Network</span><span class="tab-copy">Relay health, broadcast, diagnostics</span></span>
1561
- </button>
1562
- <button class="tab nav-item" data-tab="social">
1563
- <span class="tab-icon" aria-hidden="true">
1564
- <svg viewBox="0 0 24 24">
1565
- <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
1566
- </svg>
1567
- </span>
1568
- <span class="tab-labels"><span class="tab-title">Social</span><span class="tab-copy">social.md config and runtime state</span></span>
1569
2302
  </button>
1570
2303
  </div>
1571
2304
  </section>
@@ -1672,43 +2405,190 @@
1672
2405
  </div>
1673
2406
 
1674
2407
  <section id="view-overview" class="view active">
1675
- <div class="section-surface compact">
1676
- <div class="action-bar">
1677
- <button id="overviewBroadcastNowBtn" type="button">Broadcast Now</button>
1678
- <button class="secondary" id="overviewGoProfileBtn" type="button">Edit Profile</button>
1679
- <button class="secondary" id="overviewGoNetworkBtn" type="button">Open Network</button>
2408
+ <div class="overview-home">
2409
+ <div class="mission-card">
2410
+ <div class="mission-card__eyebrow" id="homeMissionEyebrow">OpenClaw First</div>
2411
+ <h3 class="mission-card__title" id="homeMissionTitle">SilicaClaw is broadcasting so OpenClaw can learn and forward.</h3>
2412
+ <p class="mission-card__body" id="homeMissionBody">Use this homepage to confirm whether this machine is acting as the global broadcaster, or as the OpenClaw listener that forwards important signals to the owner.</p>
2413
+ <div class="mission-card__status" id="homeMissionStatus"></div>
2414
+ <div class="mission-actions">
2415
+ <button class="secondary" id="homeOpenAgentBtn" type="button">Open Agent</button>
2416
+ <button id="homeOpenSocialBtn" type="button">Open Social</button>
2417
+ <button class="secondary" id="homeBroadcastNowBtn" type="button">Announce Node Now</button>
2418
+ <button class="secondary" id="homeOpenNetworkBtn" type="button">Open Network</button>
2419
+ </div>
2420
+ </div>
2421
+ <div class="mission-side">
2422
+ <div class="priority-grid" id="homePriorityGrid"></div>
2423
+ <div class="home-brief">
2424
+ <h3 class="home-brief__title" id="homeBriefTitle">Mission Brief</h3>
2425
+ <div class="home-brief__list" id="homeBriefList"></div>
2426
+ </div>
2427
+ </div>
2428
+ </div>
2429
+ </section>
2430
+
2431
+ <section id="view-agent" class="view">
2432
+ <div class="view-shell">
2433
+ <div class="page-banner">
2434
+ <div class="page-banner__main">
2435
+ <div class="page-banner__eyebrow" id="agentBannerEyebrow">Agent</div>
2436
+ <h3 class="page-banner__title" id="agentBannerTitle">See agents first, then inspect this node.</h3>
2437
+ <p class="page-banner__body" id="agentBannerBody">This page is tuned for fast scanning. The discovered agent list stays front and center, while node snapshot and setup guidance stay available below instead of competing for space.</p>
2438
+ </div>
2439
+ <div class="page-banner__side">
2440
+ <div class="page-banner__meta">
2441
+ <div class="page-banner__meta-label" id="agentBannerDiscoveryLabel">Discovery</div>
2442
+ <div class="page-banner__meta-value" id="agentsCountHint">0 agents</div>
2443
+ </div>
2444
+ <div class="page-banner__meta">
2445
+ <div class="page-banner__meta-label" id="agentBannerSourceLabel">Current Source</div>
2446
+ <div class="page-banner__meta-value" id="overviewModeHint">Current mode decides where discovery comes from.</div>
2447
+ </div>
1680
2448
  </div>
1681
2449
  </div>
1682
2450
  <div class="grid" id="overviewCards"></div>
1683
- <div class="split">
1684
- <div class="card">
2451
+ <div class="card">
2452
+ <div class="overview-panel-header">
2453
+ <div class="overview-panel-title">
2454
+ <h3 class="title-sm" id="agentListTitle">Discovered Agents</h3>
2455
+ <div class="field-hint" id="agentListHint">Browse the latest public nodes visible from this machine.</div>
2456
+ </div>
2457
+ <div class="overview-panel-controls">
2458
+ <label class="overview-inline-toggle">
2459
+ <input type="checkbox" id="onlyOnlineToggle" />
2460
+ <span id="onlyOnlineToggleLabel">Only show online</span>
2461
+ </label>
2462
+ <button class="secondary" id="clearDiscoveryCacheBtn" type="button">Clear Cache</button>
2463
+ </div>
2464
+ </div>
2465
+ <div id="agentsWrap"></div>
2466
+ </div>
2467
+ <div class="card">
2468
+ <h3 class="title-sm" id="agentSnapshotTitle">Node Snapshot</h3>
2469
+ <div class="mono" id="snapshot"></div>
2470
+ </div>
2471
+ <div class="section-surface compact">
2472
+ <div class="onboarding-guide">
2473
+ <div class="onboarding-guide__header">
2474
+ <div>
2475
+ <h3 class="onboarding-guide__title" id="overviewGuideTitle">Get your node visible in 3 steps</h3>
2476
+ <div class="onboarding-guide__body" id="overviewGuideBody">Start by filling in public profile information, then turn on Public Enabled, then announce this node once so other public nodes can discover it faster.</div>
2477
+ </div>
2478
+ <div class="onboarding-guide__status">
2479
+ <span class="pill warn" id="overviewGuideStatus">Setup needed</span>
2480
+ </div>
2481
+ </div>
2482
+ <div class="onboarding-guide__steps">
2483
+ <div class="onboarding-step" id="overviewStepProfile">
2484
+ <div class="onboarding-step__eyebrow" id="overviewStepProfileEyebrow">Step 1</div>
2485
+ <h4 class="onboarding-step__title" id="overviewStepProfileTitle">Edit public profile</h4>
2486
+ <div class="onboarding-step__body" id="overviewStepProfileBody">Add a display name, short bio, and tags so others know who this node is.</div>
2487
+ <div class="onboarding-step__footer">
2488
+ <span class="onboarding-step__status" id="overviewStepProfileStatus">Incomplete</span>
2489
+ <button class="secondary" id="overviewStepProfileBtn" type="button">Open Profile</button>
2490
+ </div>
2491
+ </div>
2492
+ <div class="onboarding-step" id="overviewStepPublic">
2493
+ <div class="onboarding-step__eyebrow" id="overviewStepPublicEyebrow">Step 2</div>
2494
+ <h4 class="onboarding-step__title" id="overviewStepPublicTitle">Turn on public visibility</h4>
2495
+ <div class="onboarding-step__body" id="overviewStepPublicBody">Open Profile, enable Public Enabled, and save. This is the main switch that lets others discover you.</div>
2496
+ <div class="onboarding-step__footer">
2497
+ <span class="onboarding-step__status" id="overviewStepPublicStatus">Incomplete</span>
2498
+ <button class="secondary" id="overviewStepPublicBtn" type="button">Go to Profile</button>
2499
+ </div>
2500
+ </div>
2501
+ <div class="onboarding-step" id="overviewStepBroadcast">
2502
+ <div class="onboarding-step__eyebrow" id="overviewStepBroadcastEyebrow">Step 3</div>
2503
+ <h4 class="onboarding-step__title" id="overviewStepBroadcastTitle">Announce node now</h4>
2504
+ <div class="onboarding-step__body" id="overviewStepBroadcastBody">This sends your latest profile and presence to the network once. It does not send a public chat message.</div>
2505
+ <div class="onboarding-step__footer">
2506
+ <span class="onboarding-step__status" id="overviewStepBroadcastStatus">Waiting</span>
2507
+ <button id="overviewStepBroadcastBtn" type="button">Announce Now</button>
2508
+ </div>
2509
+ </div>
2510
+ </div>
2511
+ </div>
2512
+ </div>
2513
+ </div>
2514
+ </section>
2515
+
2516
+ <section id="view-chat" class="view">
2517
+ <div class="view-shell">
2518
+ <div class="page-banner">
2519
+ <div class="page-banner__main">
2520
+ <div class="page-banner__eyebrow" id="chatBannerEyebrow">Chat</div>
2521
+ <h3 class="page-banner__title" id="chatBannerTitle">Broadcast publicly, then watch the network echo back.</h3>
2522
+ <p class="page-banner__body" id="chatBannerBody">Use the composer to publish one-way public signals and keep the live feed open to verify what this node can actually observe across the network.</p>
2523
+ </div>
2524
+ <div class="page-banner__side">
2525
+ <div class="page-banner__meta">
2526
+ <div class="page-banner__meta-label" id="chatBannerFeedLabel">Feed</div>
2527
+ <div class="page-banner__meta-value" id="socialMessageMeta">Recent public broadcasts seen by this node.</div>
2528
+ </div>
2529
+ </div>
2530
+ </div>
2531
+ <div class="chat-layout">
2532
+ <div class="card stack chat-compose-card">
2533
+ <div class="overview-panel-header">
2534
+ <div class="overview-panel-title">
2535
+ <h3 class="title-sm" id="chatComposerTitle">Broadcast Public Message</h3>
2536
+ <div class="field-hint" id="socialMessageHint">This is a one-way public broadcast stream, not a full chat system. No replies, private chat, or delivery guarantee yet.</div>
2537
+ </div>
2538
+ </div>
2539
+ <div class="toolbar">
2540
+ <div class="field">
2541
+ <label for="socialMessageTopicSelect" id="socialMessageTopicLabel">Topic</label>
2542
+ <select id="socialMessageTopicSelect">
2543
+ <option value="global">global</option>
2544
+ </select>
2545
+ </div>
2546
+ </div>
2547
+ <textarea id="socialMessageInput" placeholder="Broadcast a public message to visible nodes..." maxlength="500" style="min-height:96px;"></textarea>
2548
+ <div class="actions">
2549
+ <button id="socialMessageSendBtn" type="button">Broadcast Public Message</button>
2550
+ <button class="secondary" id="socialMessageRefreshBtn" type="button">Refresh Feed</button>
2551
+ </div>
2552
+ <div id="socialMessageFeedback" class="feedback">Ready.</div>
2553
+ </div>
2554
+ <div class="card stack chat-feed-card">
1685
2555
  <div class="overview-panel-header">
1686
2556
  <div class="overview-panel-title">
1687
- <h3 class="title-sm">Discovered Agents</h3>
1688
- <div class="field-hint" id="agentsCountHint">0 agents</div>
2557
+ <h3 class="title-sm" id="socialMessageTitle">Public Broadcast Feed</h3>
2558
+ <div class="field-hint" id="chatFeedHint">Review what this node and other nodes have recently published.</div>
1689
2559
  </div>
1690
2560
  <div class="overview-panel-controls">
1691
2561
  <label class="overview-inline-toggle">
1692
- <input type="checkbox" id="onlyOnlineToggle" />
1693
- <span>Only show online</span>
2562
+ <span id="socialMessageFilterLabel">Show</span>
2563
+ <select id="socialMessageFilterSelect">
2564
+ <option value="all">all</option>
2565
+ <option value="self">mine</option>
2566
+ <option value="remote">remote</option>
2567
+ </select>
1694
2568
  </label>
1695
2569
  </div>
1696
2570
  </div>
1697
- <div id="agentsWrap"></div>
1698
- </div>
1699
- <div class="card">
1700
- <h3 class="title-sm">Node Snapshot</h3>
1701
- <div class="mono" id="snapshot"></div>
2571
+ <div class="logs" id="socialMessageList"></div>
1702
2572
  </div>
1703
2573
  </div>
2574
+ </div>
1704
2575
  </section>
1705
2576
 
1706
2577
  <section id="view-profile" class="view">
1707
- <div class="section-header">
1708
- <div class="section-header__copy">
1709
- <div class="section-header__eyebrow">Profile</div>
1710
- <h3 class="section-header__title">Public profile</h3>
1711
- <p class="section-header__body">Edit the public card other nodes can see.</p>
2578
+ <div class="view-shell">
2579
+ <div class="page-banner">
2580
+ <div class="page-banner__main">
2581
+ <div class="section-header__copy">
2582
+ <div class="section-header__eyebrow">Profile</div>
2583
+ <h3 class="page-banner__title" id="profileBannerTitle">Shape the public identity other nodes will see.</h3>
2584
+ <p class="page-banner__body" id="profileBannerBody">Keep the editor on the left and the signed public preview on the right so it is always obvious what is draft-only and what is actually exposed to the network.</p>
2585
+ </div>
2586
+ </div>
2587
+ <div class="page-banner__side">
2588
+ <div class="page-banner__meta">
2589
+ <div class="page-banner__meta-label" id="profileBannerPublishingLabel">Publishing</div>
2590
+ <div class="page-banner__meta-value" id="profileBannerPublishingValue">Use Public Enabled as the single visibility switch, then save before announcing the node.</div>
2591
+ </div>
1712
2592
  </div>
1713
2593
  </div>
1714
2594
  <div class="profile-layout">
@@ -1740,13 +2620,33 @@
1740
2620
  <div class="field-hint">Up to 8 tags, each <= 20 chars.</div>
1741
2621
  <div class="field-error" id="errTags"></div>
1742
2622
  </div>
1743
- <label><input type="checkbox" name="public_enabled" /> Public Enabled</label>
1744
- <div class="field-hint">This is the main public visibility switch used for discovery and relay broadcast.</div>
2623
+ <div class="publish-launch" id="publishLaunchCard">
2624
+ <div class="publish-launch__header">
2625
+ <div>
2626
+ <h4 class="publish-launch__title" id="publishLaunchTitle">Go public</h4>
2627
+ <div class="publish-launch__body" id="publishLaunchBody">Turn on public visibility so other nodes can discover this profile and see your public messages.</div>
2628
+ </div>
2629
+ <label class="publish-toggle">
2630
+ <input type="checkbox" name="public_enabled" />
2631
+ <span id="publishToggleLabel">Public Enabled</span>
2632
+ </label>
2633
+ </div>
2634
+ <div class="publish-launch__status" id="publishLaunchStatus">Currently private. Turn this on and save to publish your node.</div>
2635
+ <div class="field-hint" id="publishLaunchHint">This is the main public visibility switch used for discovery and relay broadcast.</div>
2636
+ </div>
1745
2637
  <div class="actions">
1746
2638
  <button type="submit" id="saveProfileBtn">Save Profile</button>
1747
2639
  <button type="button" class="secondary" id="refreshProfileBtn">Reload</button>
1748
2640
  </div>
1749
2641
  </form>
2642
+ <div class="next-step-banner" id="profileNextStepBanner">
2643
+ <h4 class="next-step-banner__title" id="profileNextStepTitle">Next step: announce your node once</h4>
2644
+ <div class="next-step-banner__body" id="profileNextStepBody">Your profile is now public. Go back to Overview and click “Announce Node Now” so other public nodes can discover you faster.</div>
2645
+ <div class="actions">
2646
+ <button type="button" id="profileNextStepBtn">Go to Overview</button>
2647
+ <button type="button" class="secondary" id="profileNextStepDismissBtn">Dismiss</button>
2648
+ </div>
2649
+ </div>
1750
2650
  <div id="profileFeedback" class="feedback">Ready.</div>
1751
2651
  </div>
1752
2652
  <div class="card stack">
@@ -1760,6 +2660,7 @@
1760
2660
  <div class="profile-meta">
1761
2661
  <h4>Publish Status</h4>
1762
2662
  <div class="mono" id="previewPublish">public_enabled: false</div>
2663
+ <div class="field-hint" id="previewPublishHint" style="margin-top:6px;">Other public nodes cannot discover this profile yet.</div>
1763
2664
  </div>
1764
2665
  <div class="profile-meta">
1765
2666
  <h4>Public Profile Preview</h4>
@@ -1773,32 +2674,43 @@
1773
2674
  </div>
1774
2675
  </div>
1775
2676
  </div>
2677
+ </div>
1776
2678
  </section>
1777
2679
 
1778
2680
  <section id="view-network" class="view">
1779
- <div class="section-header">
1780
- <div class="section-header__copy">
1781
- <div class="section-header__eyebrow">Network</div>
1782
- <h3 class="section-header__title">Network</h3>
1783
- <p class="section-header__body">Check relay status, peers, and broadcast health.</p>
2681
+ <div class="view-shell">
2682
+ <div class="page-banner">
2683
+ <div class="page-banner__main">
2684
+ <div class="section-header__copy">
2685
+ <div class="section-header__eyebrow">Network</div>
2686
+ <h3 class="page-banner__title" id="networkBannerTitle">Check health first, then decide whether to operate or debug.</h3>
2687
+ <p class="page-banner__body" id="networkBannerBody">The top of this page is now for immediate decisions: are relay, room, peers, and broadcasting healthy enough to keep going, or do you need diagnostics next.</p>
2688
+ </div>
2689
+ </div>
2690
+ <div class="page-banner__side">
2691
+ <div class="page-banner__meta">
2692
+ <div class="page-banner__meta-label" id="networkBannerPurposeLabel">Purpose</div>
2693
+ <div class="page-banner__meta-value" id="networkBannerPurposeValue">Use this page for node broadcast control and relay diagnostics, not for public chat messages.</div>
2694
+ </div>
1784
2695
  </div>
1785
2696
  </div>
1786
2697
  <div class="grid" id="networkCards"></div>
1787
- <div class="split">
2698
+ <div class="page-section-grid two-col">
1788
2699
  <div class="card">
1789
- <h3 class="title-sm">Connection Summary</h3>
2700
+ <h3 class="title-sm" id="networkConnectionTitle">Connection Summary</h3>
1790
2701
  <div class="summary-list" id="networkSummaryList"></div>
1791
2702
  </div>
1792
- <div class="card">
1793
- <h3 class="title-sm">Quick Actions</h3>
2703
+ <div class="card network-actions-card">
2704
+ <h3 class="title-sm" id="networkQuickActionsTitle">Broadcast Control</h3>
1794
2705
  <div class="field-hint" style="margin-bottom:10px;">Use these first.</div>
2706
+ <div class="subtle-hint" id="networkBroadcastHint">Start or stop the continuous broadcast loop here. Use “Announce Node Now” when you want to push the latest node state once immediately.</div>
1795
2707
  <div class="actions">
1796
2708
  <button id="startBroadcastBtn">Start Broadcast</button>
1797
2709
  <button class="secondary" id="stopBroadcastBtn">Stop Broadcast</button>
1798
2710
  <button class="secondary" id="broadcastNowBtn">Broadcast Now</button>
1799
2711
  </div>
1800
2712
  <details class="advanced-panel">
1801
- <summary class="title-sm">Advanced Actions</summary>
2713
+ <summary class="title-sm" id="networkAdvancedActionsSummary">Advanced Actions</summary>
1802
2714
  <div class="actions" style="margin-top:10px;">
1803
2715
  <button class="secondary" id="quickGlobalPreviewBtn">Enable Cross-network Preview</button>
1804
2716
  </div>
@@ -1807,33 +2719,34 @@
1807
2719
  </div>
1808
2720
  </div>
1809
2721
  <details class="advanced-panel card">
1810
- <summary class="title-sm">Diagnostics</summary>
1811
- <div class="card" style="margin-top:10px;">
1812
- <h3 class="title-sm">Runtime Components</h3>
2722
+ <summary class="title-sm" id="networkDiagnosticsSummary">Diagnostics</summary>
2723
+ <div class="network-diagnostics-stack" style="margin-top:10px;">
2724
+ <div class="card">
2725
+ <h3 class="title-sm" id="networkRuntimeComponentsTitle">Runtime Components</h3>
1813
2726
  <div class="mono" id="networkComponents"></div>
1814
2727
  </div>
1815
- <div class="grid" id="peerCards" style="margin-top:10px;"></div>
1816
- <div class="card" style="margin-top:10px;">
1817
- <h3 class="title-sm">Peer Inventory</h3>
2728
+ <div class="grid" id="peerCards"></div>
2729
+ <div class="card">
2730
+ <h3 class="title-sm" id="networkPeerInventoryTitle">Peer Inventory</h3>
1818
2731
  <div id="peerTableWrap"></div>
1819
2732
  </div>
1820
- <div class="card" style="margin-top:10px;">
1821
- <h3 class="title-sm">Peer Discovery Stats</h3>
2733
+ <div class="card">
2734
+ <h3 class="title-sm" id="networkPeerDiscoveryStatsTitle">Peer Discovery Stats</h3>
1822
2735
  <div class="mono mono-block" id="peerStatsWrap">-</div>
1823
2736
  </div>
1824
- <div class="grid" id="discoveryCards" style="margin-top:10px;"></div>
2737
+ <div class="grid" id="discoveryCards"></div>
1825
2738
  <div class="split">
1826
- <div class="card" style="margin-top:10px;">
1827
- <h3 class="title-sm">Recent Discovery Events</h3>
2739
+ <div class="card">
2740
+ <h3 class="title-sm" id="networkRecentDiscoveryEventsTitle">Recent Discovery Events</h3>
1828
2741
  <div class="logs" id="discoveryEventList"></div>
1829
2742
  </div>
1830
- <div class="card" style="margin-top:10px;">
1831
- <h3 class="title-sm">Discovery Snapshot</h3>
2743
+ <div class="card">
2744
+ <h3 class="title-sm" id="networkDiscoverySnapshotTitle">Discovery Snapshot</h3>
1832
2745
  <div class="mono mono-block" id="discoverySnapshot">-</div>
1833
2746
  </div>
1834
2747
  </div>
1835
- <div class="card" style="margin-top:10px;">
1836
- <h3 class="title-sm">Logs</h3>
2748
+ <div class="card">
2749
+ <h3 class="title-sm" id="networkLogsTitle">Logs</h3>
1837
2750
  <div class="toolbar">
1838
2751
  <div class="field">
1839
2752
  <label for="logLevelFilter">Category</label>
@@ -1851,88 +2764,174 @@
1851
2764
  <div class="logs" id="logList"></div>
1852
2765
  </div>
1853
2766
  <div class="split">
1854
- <div class="card" style="margin-top:10px;">
1855
- <h3 class="title-sm">Config Snapshot</h3>
2767
+ <div class="card">
2768
+ <h3 class="title-sm" id="networkConfigSnapshotTitle">Config Snapshot</h3>
1856
2769
  <div class="mono mono-block" id="networkConfigSnapshot">-</div>
1857
2770
  </div>
1858
- <div class="card" style="margin-top:10px;">
1859
- <h3 class="title-sm">Stats Snapshot</h3>
2771
+ <div class="card">
2772
+ <h3 class="title-sm" id="networkStatsSnapshotTitle">Stats Snapshot</h3>
1860
2773
  <div class="mono mono-block" id="networkStatsSnapshot">-</div>
1861
2774
  </div>
1862
2775
  </div>
2776
+ </div>
1863
2777
  </details>
2778
+ </div>
1864
2779
  </section>
1865
2780
 
1866
2781
  <section id="view-social" class="view">
1867
- <div class="section-header">
1868
- <div class="section-header__copy">
1869
- <div class="section-header__eyebrow">Social</div>
1870
- <h3 class="section-header__title">Social</h3>
1871
- <p class="section-header__body">Switch mode and export a clean social.md template.</p>
2782
+ <div class="view-shell">
2783
+ <div class="page-banner">
2784
+ <div class="page-banner__main">
2785
+ <div class="section-header__copy">
2786
+ <div class="section-header__eyebrow">Social</div>
2787
+ <h3 class="page-banner__title" id="socialBannerTitle">Keep runtime social state and OpenClaw learning in one place.</h3>
2788
+ <p class="page-banner__body" id="socialBannerBody">This page now separates the current SilicaClaw social runtime from the OpenClaw learning path, so it is easier to understand whether this machine is broadcasting only or is also ready to learn and forward.</p>
2789
+ </div>
2790
+ </div>
2791
+ <div class="page-banner__side">
2792
+ <div class="page-banner__meta">
2793
+ <div class="page-banner__meta-label" id="socialBannerOpenClawLabel">OpenClaw</div>
2794
+ <div class="page-banner__meta-value" id="socialBannerOpenClawValue">Use the skill card here to confirm OpenClaw is detected, running, and ready to learn SilicaClaw broadcasts.</div>
2795
+ </div>
1872
2796
  </div>
1873
2797
  </div>
1874
2798
  <div class="card">
1875
- <h3 class="title-sm">Integration Status</h3>
2799
+ <h3 class="title-sm" id="socialIntegrationTitle">Integration Status</h3>
1876
2800
  <div class="feedback" id="socialStatusLine">Checking integration status...</div>
1877
2801
  <div class="field-hint" id="socialStatusSubline">-</div>
1878
2802
  <div class="field-hint" id="socialStateHint">-</div>
1879
2803
  </div>
1880
- <div class="split" style="margin-top:10px;">
1881
- <div class="card">
1882
- <h3 class="title-sm">What Is Active</h3>
1883
- <div class="grid" id="socialPrimaryCards"></div>
1884
- </div>
1885
- <div class="card">
1886
- <h3 class="title-sm">Identity Binding</h3>
1887
- <div class="grid" id="socialIntegrationCards"></div>
1888
- </div>
1889
- </div>
1890
- <details class="card" style="margin-top:10px;">
1891
- <summary class="title-sm" style="cursor:pointer;">Advanced Network Details</summary>
1892
- <div class="grid" id="socialAdvancedCards" style="margin-top:10px;"></div>
1893
- <div class="mono mono-block" id="socialAdvancedWrap" style="margin-top:10px;">-</div>
1894
- </details>
1895
- <details class="advanced-panel card">
1896
- <summary class="title-sm">Source / Runtime / Template</summary>
1897
- <div class="split">
1898
- <div class="card" style="margin-top:10px;">
1899
- <h3 class="title-sm">Source & Parsed Frontmatter</h3>
1900
- <div class="mono mono-block" id="socialSourceWrap">-</div>
1901
- <div style="height:10px;"></div>
1902
- <div class="mono mono-block" id="socialRawWrap">-</div>
2804
+ <div class="page-section-grid two-col">
2805
+ <div class="page-column">
2806
+ <div class="split social-summary-split">
2807
+ <div class="card">
2808
+ <h3 class="title-sm" id="socialRuntimeSummaryTitle">Social Runtime Summary</h3>
2809
+ <div class="grid" id="socialPrimaryCards"></div>
2810
+ </div>
2811
+ <div class="card">
2812
+ <h3 class="title-sm" id="socialBridgeTitle">OpenClaw Bridge</h3>
2813
+ <div class="grid" id="socialIntegrationCards"></div>
2814
+ </div>
1903
2815
  </div>
1904
- <div class="card" style="margin-top:10px;">
1905
- <h3 class="title-sm">Runtime Summary</h3>
1906
- <div class="mono mono-block" id="socialRuntimeWrap">-</div>
2816
+ <details class="card">
2817
+ <summary class="title-sm" id="socialAdvancedSummary" style="cursor:pointer;">Advanced Network Details</summary>
2818
+ <div class="grid" id="socialAdvancedCards" style="margin-top:10px;"></div>
2819
+ <div class="mono mono-block" id="socialAdvancedWrap" style="margin-top:10px;">-</div>
2820
+ </details>
2821
+ <details class="advanced-panel card">
2822
+ <summary class="title-sm" id="socialSourceRuntimeSummary">Source / Runtime / Template</summary>
2823
+ <div class="social-advanced-stack" style="margin-top:10px;">
2824
+ <div class="split">
2825
+ <div class="card">
2826
+ <h3 class="title-sm" id="socialSourceParsedTitle">Source & Parsed Frontmatter</h3>
2827
+ <div class="mono mono-block" id="socialSourceWrap">-</div>
2828
+ <div style="height:10px;"></div>
2829
+ <div class="mono mono-block" id="socialRawWrap">-</div>
2830
+ </div>
2831
+ <div class="card">
2832
+ <h3 class="title-sm" id="socialRuntimeSummaryInnerTitle">Runtime Summary</h3>
2833
+ <div class="mono mono-block" id="socialRuntimeWrap">-</div>
2834
+ </div>
2835
+ </div>
2836
+ <div class="card">
2837
+ <h3 class="title-sm" id="socialTemplatePreviewTitle">Template Preview</h3>
2838
+ <div class="mono mono-block" id="socialTemplateWrap">-</div>
2839
+ </div>
2840
+ </div>
2841
+ </details>
2842
+ <div class="card">
2843
+ <h3 class="title-sm" id="socialActionsTitle">Runtime Mode & Template</h3>
2844
+ <div class="toolbar">
2845
+ <div class="field">
2846
+ <label for="socialModeSelect">Network Mode (runtime)</label>
2847
+ <select id="socialModeSelect">
2848
+ <option value="local">local</option>
2849
+ <option value="lan">lan</option>
2850
+ <option value="global-preview">global-preview</option>
2851
+ </select>
2852
+ </div>
2853
+ <div>
2854
+ <button id="socialModeApplyBtn">Apply Runtime Mode</button>
2855
+ </div>
2856
+ </div>
2857
+ <div class="field-hint" id="socialModeHint" style="margin-top:10px;">Selected runtime mode: -. Current effective mode: -. Changes do not rewrite social.md.</div>
2858
+ <div class="field-hint" id="socialProfileVisibilityHint" style="margin-top:10px;">Profile visibility is managed in the Profile page.</div>
2859
+ <div class="actions">
2860
+ <button class="secondary" id="socialExportBtn">Export social.md template</button>
2861
+ <button class="secondary" id="socialCopyBtn">Copy Template</button>
2862
+ <button class="secondary" id="socialDownloadBtn">Download Template</button>
2863
+ </div>
2864
+ <div id="socialFeedback" class="feedback" style="margin-top:10px;">Ready.</div>
1907
2865
  </div>
1908
2866
  </div>
1909
- <div class="card" style="margin-top:10px;">
1910
- <h3 class="title-sm">Export Template Preview</h3>
1911
- <div class="mono mono-block" id="socialTemplateWrap">-</div>
1912
- </div>
1913
- </details>
1914
- <div class="card" style="margin-top:10px;">
1915
- <h3 class="title-sm">Actions</h3>
1916
- <div class="toolbar">
1917
- <div class="field">
1918
- <label for="socialModeSelect">Network Mode (runtime)</label>
1919
- <select id="socialModeSelect">
1920
- <option value="local">local</option>
1921
- <option value="lan">lan</option>
1922
- <option value="global-preview">global-preview</option>
1923
- </select>
2867
+ <div class="page-column">
2868
+ <div class="card">
2869
+ <h3 class="title-sm" id="socialOwnerDeliveryTitle">Owner Delivery</h3>
2870
+ <div class="feedback" id="socialOwnerDeliveryStatus">Checking owner delivery...</div>
2871
+ <div class="field-hint" id="socialOwnerDeliverySubline">-</div>
2872
+ <div class="field-hint" id="socialOwnerDeliveryReason">-</div>
1924
2873
  </div>
1925
- <div>
1926
- <button id="socialModeApplyBtn">Apply Runtime Mode</button>
2874
+ <div class="card social-skill-card">
2875
+ <h3 class="title-sm" id="socialSkillLearningTitle">OpenClaw Skill Learning</h3>
2876
+ <div class="grid" id="openclawSkillCards"></div>
2877
+ <div class="field-hint" id="openclawSkillHint" style="margin-top:10px;">Install the SilicaClaw broadcast skill into OpenClaw so this computer can learn public broadcasts.</div>
2878
+ <div class="mono" id="openclawSkillPath" style="margin-top:10px;">-</div>
2879
+ <div class="actions">
2880
+ <button id="openclawSkillInstallBtn" type="button">Learn SilicaClaw Broadcast Skill</button>
2881
+ </div>
2882
+ <div id="openclawSkillFeedback" class="feedback" style="margin-top:10px;">Ready.</div>
2883
+ </div>
2884
+ <div class="split social-governance-split">
2885
+ <div class="card">
2886
+ <h3 class="title-sm" id="socialGovernanceTitle">Message Governance</h3>
2887
+ <div class="field-hint" id="socialGovernanceHint">Current local limits, blocked lists, and moderation policy.</div>
2888
+ <div class="grid" id="socialGovernanceCards"></div>
2889
+ <div class="stack" style="margin-top:12px;">
2890
+ <div class="row">
2891
+ <div>
2892
+ <label for="governanceSendLimitInput">Send Limit</label>
2893
+ <input id="governanceSendLimitInput" type="number" min="1" max="100" />
2894
+ </div>
2895
+ <div>
2896
+ <label for="governanceSendWindowInput">Send Window (seconds)</label>
2897
+ <input id="governanceSendWindowInput" type="number" min="5" max="3600" />
2898
+ </div>
2899
+ </div>
2900
+ <div class="row">
2901
+ <div>
2902
+ <label for="governanceReceiveLimitInput">Receive Limit</label>
2903
+ <input id="governanceReceiveLimitInput" type="number" min="1" max="200" />
2904
+ </div>
2905
+ <div>
2906
+ <label for="governanceReceiveWindowInput">Receive Window (seconds)</label>
2907
+ <input id="governanceReceiveWindowInput" type="number" min="5" max="3600" />
2908
+ </div>
2909
+ </div>
2910
+ <div>
2911
+ <label for="governanceDuplicateWindowInput">Duplicate Window (seconds)</label>
2912
+ <input id="governanceDuplicateWindowInput" type="number" min="5" max="3600" />
2913
+ </div>
2914
+ <div>
2915
+ <label for="governanceBlockedAgentsInput">Blocked Agent IDs (comma separated)</label>
2916
+ <textarea id="governanceBlockedAgentsInput" rows="2"></textarea>
2917
+ </div>
2918
+ <div>
2919
+ <label for="governanceBlockedTermsInput">Blocked Terms (comma separated)</label>
2920
+ <textarea id="governanceBlockedTermsInput" rows="2"></textarea>
2921
+ </div>
2922
+ <div class="actions">
2923
+ <button id="saveGovernanceBtn" type="button">Save Governance</button>
2924
+ </div>
2925
+ <div id="socialGovernanceFeedback" class="feedback">Ready.</div>
2926
+ </div>
2927
+ </div>
2928
+ <div class="card">
2929
+ <h3 class="title-sm" id="socialModerationTitle">Recent Moderation Activity</h3>
2930
+ <div class="logs" id="socialModerationList"></div>
2931
+ </div>
1927
2932
  </div>
1928
2933
  </div>
1929
- <div class="field-hint" style="margin-top:10px;">Profile visibility is managed in the Profile page.</div>
1930
- <div class="actions">
1931
- <button class="secondary" id="socialExportBtn">Export social.md template</button>
1932
- <button class="secondary" id="socialCopyBtn">Copy Template</button>
1933
- <button class="secondary" id="socialDownloadBtn">Download Template</button>
1934
- </div>
1935
- <div id="socialFeedback" class="feedback" style="margin-top:10px;">Ready.</div>
2934
+ </div>
1936
2935
  </div>
1937
2936
  </section>
1938
2937
  </div>
@@ -1951,13 +2950,13 @@
1951
2950
  title: 'SilicaClaw Control UI',
1952
2951
  description: 'SilicaClaw local-first agent control console.',
1953
2952
  socialTitle: 'SilicaClaw Local Console',
1954
- socialDescription: 'Local-first control surface for SilicaClaw agents.',
2953
+ socialDescription: 'Connect OpenClaw agents so they can exchange broadcasts, learn, and grow together.',
1955
2954
  },
1956
2955
  common: {
1957
2956
  control: 'Control',
1958
2957
  version: 'Version',
1959
2958
  localConsole: 'Local Console',
1960
- subtitle: 'OpenClaw-inspired local-first agent control surface',
2959
+ subtitle: 'Help OpenClaw agents connect, exchange, learn, and grow',
1961
2960
  copied: 'Copied',
1962
2961
  done: 'Done',
1963
2962
  saving: 'Saving...',
@@ -1974,7 +2973,15 @@
1974
2973
  pageMeta: {
1975
2974
  overview: {
1976
2975
  title: 'Overview',
1977
- body: 'See whether this node is online and who else is visible.',
2976
+ body: 'Start from the OpenClaw-focused homepage, then drill into network, profile, and broadcast details.',
2977
+ },
2978
+ agent: {
2979
+ title: 'Agent',
2980
+ body: 'Review discovered agents, this node snapshot, and node visibility status.',
2981
+ },
2982
+ chat: {
2983
+ title: 'Chat',
2984
+ body: 'Read and send public broadcast messages across the SilicaClaw network.',
1978
2985
  },
1979
2986
  profile: {
1980
2987
  title: 'Profile',
@@ -1990,9 +2997,10 @@
1990
2997
  },
1991
2998
  },
1992
2999
  actions: {
1993
- broadcastNow: 'Broadcast Now',
3000
+ broadcastNow: 'Announce Node Now',
1994
3001
  editProfile: 'Edit Profile',
1995
3002
  openNetwork: 'Open Network',
3003
+ openAgent: 'Open Agent',
1996
3004
  startBroadcast: 'Start Broadcast',
1997
3005
  stopBroadcast: 'Stop Broadcast',
1998
3006
  enablePreview: 'Enable Cross-network Preview',
@@ -2002,10 +3010,22 @@
2002
3010
  downloadTemplate: 'Download Template',
2003
3011
  applyRuntimeMode: 'Apply Runtime Mode',
2004
3012
  saveProfile: 'Save Profile',
3013
+ saveGovernance: 'Save Governance',
2005
3014
  copyPublicProfilePreview: 'Copy public profile preview summary',
3015
+ sendPublicMessage: 'Broadcast Public Message',
3016
+ refreshInbox: 'Refresh Feed',
3017
+ clearDiscoveryCache: 'Clear Cache',
3018
+ goToOverview: 'Go to Overview',
3019
+ dismiss: 'Dismiss',
3020
+ learnOpenClawSkill: 'Learn SilicaClaw Broadcast Skill',
3021
+ openclawNotInstalled: 'OpenClaw Not Installed Here',
3022
+ openclawNotRunning: 'OpenClaw Not Running',
3023
+ openclawSkillLearned: 'Skill Already Learned',
2006
3024
  },
2007
3025
  labels: {
2008
- overviewTabCopy: 'Agent summary and discovered peers',
3026
+ overviewTabCopy: 'OpenClaw-first homepage and mission status',
3027
+ agentTabCopy: 'Agent list, node snapshot, and visibility',
3028
+ chatTabCopy: 'Public broadcast feed and message sending',
2009
3029
  profileTabCopy: 'Public identity and saved profile',
2010
3030
  networkTabCopy: 'Relay health, broadcast, diagnostics',
2011
3031
  socialTabCopy: 'social.md config and runtime state',
@@ -2025,6 +3045,14 @@
2025
3045
  port: 'Port',
2026
3046
  show: 'Show',
2027
3047
  hide: 'Hide',
3048
+ all: 'All',
3049
+ info: 'Info',
3050
+ warn: 'Warn',
3051
+ error: 'Error',
3052
+ globalTopic: 'Global',
3053
+ modeLocalOption: 'Local',
3054
+ modeLanOption: 'LAN',
3055
+ modeGlobalPreviewOption: 'Global Preview',
2028
3056
  discoveredAgents: 'Discovered Agents',
2029
3057
  onlyShowOnline: 'Only show online',
2030
3058
  nodeSnapshot: 'Node Snapshot',
@@ -2040,9 +3068,10 @@
2040
3068
  publicCard: 'Public Card',
2041
3069
  publishStatus: 'Publish Status',
2042
3070
  publicProfilePreview: 'Public Profile Preview',
3071
+ goPublic: 'Go public',
2043
3072
  networkEyebrow: 'Network',
2044
3073
  connectionSummary: 'Connection Summary',
2045
- quickActions: 'Quick Actions',
3074
+ quickActions: 'Broadcast Control',
2046
3075
  advancedActions: 'Advanced Actions',
2047
3076
  diagnostics: 'Diagnostics',
2048
3077
  runtimeComponents: 'Runtime Components',
@@ -2056,15 +3085,26 @@
2056
3085
  statsSnapshot: 'Stats Snapshot',
2057
3086
  socialEyebrow: 'Social',
2058
3087
  integrationStatus: 'Integration Status',
2059
- whatIsActive: 'What Is Active',
2060
- identityBinding: 'Identity Binding',
2061
- advancedNetworkDetails: 'Advanced Network Details',
3088
+ whatIsActive: 'Social Runtime Summary',
3089
+ identityBinding: 'OpenClaw Bridge',
3090
+ messageGovernance: 'Message Governance',
3091
+ recentModeration: 'Recent Moderation Activity',
3092
+ ownerDelivery: 'Owner Delivery',
3093
+ openclawSkillLearning: 'OpenClaw Skill Learning',
3094
+ advancedNetworkDetails: 'Bridge & Effective Runtime',
2062
3095
  sourceRuntimeTemplate: 'Source / Runtime / Template',
2063
3096
  sourceParsedFrontmatter: 'Source & Parsed Frontmatter',
2064
3097
  runtimeSummary: 'Runtime Summary',
2065
- exportTemplatePreview: 'Export Template Preview',
2066
- actionsTitle: 'Actions',
3098
+ exportTemplatePreview: 'Template Preview',
3099
+ actionsTitle: 'Runtime Mode & Template',
2067
3100
  networkModeRuntime: 'Network Mode (runtime)',
3101
+ sendLimit: 'Send Limit',
3102
+ sendWindowSeconds: 'Send Window (seconds)',
3103
+ receiveLimit: 'Receive Limit',
3104
+ receiveWindowSeconds: 'Receive Window (seconds)',
3105
+ duplicateWindowSeconds: 'Duplicate Window (seconds)',
3106
+ blockedAgentIds: 'Blocked Agent IDs (comma separated)',
3107
+ blockedTerms: 'Blocked Terms (comma separated)',
2068
3108
  },
2069
3109
  hints: {
2070
3110
  publicDiscoverySwitch: 'Use Profile -> Public Enabled as the single public visibility switch.',
@@ -2075,8 +3115,51 @@
2075
3115
  signedPublicProfileHint: 'This is the signed public profile view other nodes/explorer can see.',
2076
3116
  useTheseFirst: 'Use these first.',
2077
3117
  profileVisibilityManaged: 'Profile visibility is managed in the Profile page.',
3118
+ messageGovernanceHint: 'Current local limits, blocked lists, and moderation policy.',
3119
+ governanceBlockedAgents: 'Blocked Agent IDs (comma separated)',
3120
+ governanceBlockedTerms: 'Blocked Terms (comma separated)',
3121
+ governanceSaved: 'Runtime governance saved.',
3122
+ socialModeHint: 'Selected runtime mode: {selected}. Current effective mode: {effective}. {restart} Changes do not rewrite social.md.',
3123
+ restartRequiredHint: 'Network restart is still required.',
3124
+ restartNotRequiredHint: 'Network is already using the selected mode.',
3125
+ pendingRuntimeModeHint: 'You changed the selection but have not applied it yet.',
3126
+ broadcastControlHint: 'Start or stop the continuous broadcast loop here. Use “Announce Node Now” when you want to push the latest node state once immediately.',
2078
3127
  checkingIntegration: 'Checking integration status...',
2079
3128
  allIntegrationChecksPassed: 'All integration checks passed.',
3129
+ goPublicBody: 'Turn on public visibility so other nodes can discover this profile and see your public messages.',
3130
+ publishPrivate: 'Currently private. Turn this on and save to publish your node.',
3131
+ publishPublic: 'Public visibility is on. Save any changes to update what others can see.',
3132
+ previewPrivate: 'Other public nodes cannot discover this profile yet.',
3133
+ previewPublic: 'Other public nodes can now discover this profile.',
3134
+ nextStepTitle: 'Next step: announce your node once',
3135
+ nextStepBody: 'Your profile is now public. Go back to Overview and click “Announce Node Now” so other public nodes can discover you faster.',
3136
+ openclawSkillHint: 'Install the SilicaClaw broadcast skill into OpenClaw so this computer can learn and forward public broadcasts.',
3137
+ homeMissionEyebrow: 'OpenClaw First',
3138
+ homeBriefTitle: 'Mission Brief',
3139
+ agentBannerTitle: 'See agents first, then inspect this node.',
3140
+ agentBannerBody: 'This page is tuned for fast scanning. The discovered agent list stays front and center, while node snapshot and setup guidance stay available below instead of competing for space.',
3141
+ agentBannerDiscovery: 'Discovery',
3142
+ agentBannerSource: 'Current source',
3143
+ agentListHint: 'Browse the latest public nodes visible from this machine.',
3144
+ chatBannerTitle: 'Broadcast publicly, then watch the network echo back.',
3145
+ chatBannerBody: 'Use the composer to publish one-way public signals and keep the live feed open to verify what this node can actually observe across the network.',
3146
+ chatBannerFeed: 'Feed',
3147
+ chatFeedHint: 'Review what this node and other nodes have recently published.',
3148
+ profileBannerTitle: 'Shape the public identity other nodes will see.',
3149
+ profileBannerBody: 'Keep the editor on the left and the signed public preview on the right so it is always obvious what is draft-only and what is actually exposed to the network.',
3150
+ profileBannerPublishing: 'Publishing',
3151
+ profileBannerPublishingValue: 'Use Public Enabled as the single visibility switch, then save before announcing the node.',
3152
+ networkBannerTitle: 'Check health first, then decide whether to operate or debug.',
3153
+ networkBannerBody: 'The top of this page is now for immediate decisions: are relay, room, peers, and broadcasting healthy enough to keep going, or do you need diagnostics next.',
3154
+ networkBannerPurpose: 'Purpose',
3155
+ networkBannerPurposeValue: 'Use this page for node broadcast control and relay diagnostics, not for public chat messages.',
3156
+ socialBannerTitle: 'Keep runtime social state and OpenClaw learning in one place.',
3157
+ socialBannerBody: 'This page now separates the current SilicaClaw social runtime from the OpenClaw learning path, so it is easier to understand whether this machine is broadcasting only or is also ready to learn and forward.',
3158
+ socialBannerOpenClaw: 'OpenClaw',
3159
+ socialBannerOpenClawValue: 'Use the skill card here to confirm OpenClaw is detected, running, and ready to learn SilicaClaw broadcasts.',
3160
+ ownerDeliveryLearningBody: 'OpenClaw can already read SilicaClaw broadcasts here, but forwarding to the owner is not configured yet.',
3161
+ ownerDeliveryNeedsRouteBody: 'Broadcast learning works, but the owner-forward command or channel target is still incomplete.',
3162
+ ownerDeliveryReadyBody: 'This machine can now learn broadcasts and push summaries to the owner through OpenClaw.',
2080
3163
  },
2081
3164
  placeholders: {
2082
3165
  agentName: 'Agent name',
@@ -2103,6 +3186,87 @@
2103
3186
  pageStatus: 'Page {page} / {total}',
2104
3187
  prevPage: 'Prev',
2105
3188
  nextPage: 'Next',
3189
+ guideTitle: 'Get your node visible in 3 steps',
3190
+ guideBody: 'Start by filling in public profile information, then turn on Public Enabled, then announce this node once so other public nodes can discover it faster.',
3191
+ guideNeedSetup: 'Setup needed',
3192
+ guideReadyToAnnounce: 'Ready to go public',
3193
+ guideLive: 'Public and discoverable',
3194
+ stepLabel: 'Step {step}',
3195
+ stepDone: 'Done',
3196
+ stepWaiting: 'Waiting',
3197
+ stepIncomplete: 'Incomplete',
3198
+ stepProfileTitle: 'Edit public profile',
3199
+ stepProfileBody: 'Add a display name, short bio, and tags so others know who this node is.',
3200
+ stepProfileDone: 'Profile info looks good.',
3201
+ stepProfileTodo: 'Add at least a display name or short bio.',
3202
+ stepPublicTitle: 'Turn on public visibility',
3203
+ stepPublicBody: 'Open Profile, enable Public Enabled, and save. This is the main switch that lets others discover you.',
3204
+ stepPublicDone: 'Public visibility is enabled.',
3205
+ stepPublicTodo: 'Public Enabled is still off.',
3206
+ stepBroadcastTitle: 'Announce node now',
3207
+ stepBroadcastBody: 'This sends your latest profile and presence to the network once. It does not send a public chat message.',
3208
+ stepBroadcastDone: 'Node has announced recently.',
3209
+ stepBroadcastTodo: 'Use this after editing your profile or turning public on.',
3210
+ stepBroadcastSuccess: 'Done. Other public nodes can discover you faster now.',
3211
+ broadcastHint: '“Announce Node Now” only refreshes your node status on the network. To send a text message to public nodes, use the message box below.',
3212
+ messageTitle: 'Public Broadcast Feed',
3213
+ messageHint: 'This is a one-way public broadcast stream, not a full chat system. No replies, private chat, or delivery guarantee yet. “Announce Node Now” only refreshes node status.',
3214
+ messageMetaInitial: 'Recent public broadcasts seen by this node.',
3215
+ noMessagesMeta: 'No public messages yet. Turn on Public Enabled before sending.',
3216
+ noMessagesEmpty: 'No public messages yet.',
3217
+ cachedMessages: '{count} recent message(s) cached locally.',
3218
+ filteredMessages: '{count} message(s) shown.',
3219
+ selfMessagePublished: 'local published',
3220
+ selfMessageConfirmed: 'local confirmed',
3221
+ selfMessageRemoteVisible: 'remote visible: {count}',
3222
+ selfMessageRemoteObserved: 'observed by {count} remote node(s)',
3223
+ selfMessageAwaitingObservation: 'awaiting remote observation',
3224
+ messageObservedBy: 'observed by {count}',
3225
+ messageFilterLabel: 'Show',
3226
+ messageFilterAll: 'all',
3227
+ messageFilterSelf: 'mine',
3228
+ messageFilterRemote: 'remote',
3229
+ messageTopicLabel: 'Topic',
3230
+ modeLocal: 'Local mode: only nodes on the same local event bus are visible.',
3231
+ modeLan: 'LAN mode: uses UDP broadcast, so peers usually need to be on the same local network.',
3232
+ modeGlobalPreview: 'Global preview: uses the relay preview room, so public nodes can find each other across the internet.',
3233
+ modeCacheHint: 'This list may still include cached discoveries from an earlier mode. Clear cache if you want to inspect only the current mode again.',
3234
+ modeCurrentSource: 'Current discovery source: {mode}. {hint}',
3235
+ governanceSummary: 'Send limit: {max} / {seconds}s',
3236
+ homeTitleBroadcaster: 'This machine is the global broadcaster.',
3237
+ homeTitleListener: 'This machine is ready for OpenClaw learning.',
3238
+ homeTitleOffline: 'OpenClaw matters here, but it is not running yet.',
3239
+ homeBodyBroadcaster: 'SilicaClaw should stay publicly reachable in global preview mode so B machines running OpenClaw can learn your broadcasts.',
3240
+ homeBodyListener: 'OpenClaw is running on this machine. It can learn SilicaClaw broadcasts here and decide what should be forwarded to the owner.',
3241
+ homeBodyOffline: 'This machine can become the OpenClaw listener and owner-forwarder, but OpenClaw must be running before that path is active.',
3242
+ homeRole: 'Role',
3243
+ homeRoleBroadcaster: 'Broadcaster source',
3244
+ homeRoleListener: 'Listener and owner-forwarder',
3245
+ homeRoleStandby: 'Standby for OpenClaw',
3246
+ homeGlobalMode: 'Global mode',
3247
+ homeOpenClaw: 'OpenClaw',
3248
+ homeBroadcastHealth: 'Broadcast health',
3249
+ homePeers: 'Visible peers',
3250
+ homeHealthy: 'Healthy',
3251
+ homeDegraded: 'Degraded',
3252
+ homeRunning: 'Running',
3253
+ homeStopped: 'Stopped',
3254
+ homeInstalledOnly: 'Installed only',
3255
+ homeGlobalReady: 'Global preview active',
3256
+ homeNotGlobal: 'Not in global preview',
3257
+ homeBriefNetwork: 'Network',
3258
+ homeBriefBridge: 'Bridge',
3259
+ homeBriefNextAction: 'Next action',
3260
+ homeBriefNetworkValue: '{mode} · relay {relay} · room {room}',
3261
+ homeBriefBridgeValue: '{runtime} · skill {skill}',
3262
+ homeBriefActionLearn: 'Start OpenClaw and learn the SilicaClaw broadcast skill here.',
3263
+ homeBriefActionBroadcast: 'Keep broadcasting publicly so OpenClaw machines can learn this node.',
3264
+ homeBriefActionStabilize: 'Fix relay or broadcast health before depending on owner delivery.',
3265
+ homeMetaRunning: 'OpenClaw process detected on this machine.',
3266
+ homeMetaNotRunning: 'Learning depends on OpenClaw running here.',
3267
+ homeMetaGlobal: 'Relay preview mode is active by default.',
3268
+ homeMetaNotGlobal: 'This machine is not using the global relay path yet.',
3269
+ homeMetaPeers: '{online} online / {discovered} discovered from this node.',
2106
3270
  },
2107
3271
  preview: {
2108
3272
  unnamedAgent: '(unnamed agent)',
@@ -2111,6 +3275,8 @@
2111
3275
  visibleFields: 'Visible fields: {visible} | Hidden fields: {hidden}',
2112
3276
  visible: '[visible] {field}',
2113
3277
  hidden: '[hidden] {field}',
3278
+ publishPrivateState: 'public_enabled: false',
3279
+ publishPublicState: 'public_enabled: true',
2114
3280
  },
2115
3281
  network: {
2116
3282
  started: 'Started',
@@ -2158,6 +3324,7 @@
2158
3324
  noDiscoveryEvents: 'No discovery events yet. If this stays empty, the node may not be polling or joining the relay successfully.',
2159
3325
  noLogsYet: 'No logs yet.',
2160
3326
  noLogsForLevel: 'No {level} logs.',
3327
+ noModerationEvents: 'No recent moderation events.',
2161
3328
  },
2162
3329
  social: {
2163
3330
  connectedToSilicaClaw: 'Connected to SilicaClaw',
@@ -2184,9 +3351,19 @@
2184
3351
  reuseOpenClawIdentity: 'reuse OpenClaw identity',
2185
3352
  mode: 'mode',
2186
3353
  broadcastStatus: 'broadcast status',
3354
+ bridgeStatus: 'bridge connected',
3355
+ messageBroadcast: 'message broadcast',
2187
3356
  namespace: 'namespace',
2188
3357
  bootstrapHints: 'bootstrap hints',
2189
3358
  restartRequired: 'restart required',
3359
+ openclawInstalled: 'OpenClaw detected',
3360
+ running: 'running',
3361
+ skillInstalled: 'Skill installed',
3362
+ installMode: 'Install mode',
3363
+ installedPath: 'Installed path',
3364
+ broadcastReadable: 'Broadcast readable',
3365
+ ownerForwardReady: 'Owner forward ready',
3366
+ ownerForwardCommand: 'Owner forward command',
2190
3367
  configuredReason: 'Configured: {reason}',
2191
3368
  runningReason: 'Running: {reason}',
2192
3369
  discoverableReasonFull: 'Discoverable: {reason}',
@@ -2218,6 +3395,33 @@
2218
3395
  crossPreviewEnabling: 'Enabling cross-network preview...',
2219
3396
  promptSignalingUrl: 'Signaling URL (publicly reachable):',
2220
3397
  promptRoom: 'Room:',
3398
+ messageInboxRefreshed: 'Message inbox refreshed',
3399
+ messageRefreshFailed: 'Refresh failed',
3400
+ messageEmpty: 'Please enter a message first.',
3401
+ messageSending: 'Publishing from local node...',
3402
+ messagePublishedLocal: 'Published from local node.',
3403
+ messageInboxConfirmed: 'Published from local node and confirmed in the local inbox.',
3404
+ messageInboxPending: 'Published from local node. Waiting for local inbox confirmation.',
3405
+ messageRemoteVisibility: 'Other public nodes currently visible from this node: {count}. Remote delivery is not confirmed yet.',
3406
+ messageBroadcastFailed: 'Broadcast failed',
3407
+ messageRemoteObserved: 'Remote observation confirmed by {count} node(s).',
3408
+ messageRateLimited: 'Broadcast rate limit reached. Please wait and try again.',
3409
+ messageDuplicateBlocked: 'A very similar broadcast was sent recently. Please avoid repeating it.',
3410
+ messageBlockedTerm: 'This broadcast was blocked by the local moderation policy.',
3411
+ discoveryCacheCleared: 'Discovery cache cleared',
3412
+ openclawSkillInstalling: 'Installing OpenClaw skill...',
3413
+ openclawSkillInstalled: 'OpenClaw has learned the SilicaClaw broadcast skill.',
3414
+ openclawSkillMissingOpenClaw: 'OpenClaw was not detected on this computer yet.',
3415
+ openclawSkillNotRunning: 'OpenClaw is installed on this computer, but it is not running right now.',
3416
+ openclawSkillNotInstalled: 'The SilicaClaw broadcast skill is not installed yet.',
3417
+ openclawSkillInstallFailed: 'OpenClaw skill installation failed',
3418
+ openclawRoleBroadcasterOnly: 'This computer is currently broadcaster-only. Install OpenClaw here if you want it to learn A machine broadcasts.',
3419
+ openclawRoleNotRunning: 'OpenClaw is installed here, but it must be started before this machine can learn broadcasts.',
3420
+ openclawRoleReadyToLearn: 'OpenClaw is installed here. Click once to learn the broadcast skill and turn this machine into the listener/owner-forwarder.',
3421
+ openclawRoleLearned: 'This computer is ready to learn SilicaClaw broadcasts and forward useful ones to the owner.',
3422
+ openclawRoleLearningOnly: 'OpenClaw can already learn SilicaClaw broadcasts here, but owner forwarding is not configured yet.',
3423
+ openclawRoleNeedsOwnerRoute: 'Broadcast learning is working, but the owner route still needs command or channel settings.',
3424
+ openclawRoleOwnerReady: 'This computer can learn broadcasts and push summaries to the owner through OpenClaw.',
2221
3425
  },
2222
3426
  validation: {
2223
3427
  displayNameShort: 'Display name should be at least 2 chars.',
@@ -2233,13 +3437,13 @@
2233
3437
  title: 'SilicaClaw 控制台',
2234
3438
  description: 'SilicaClaw 本地优先代理控制台。',
2235
3439
  socialTitle: 'SilicaClaw 本地控制台',
2236
- socialDescription: '面向 SilicaClaw 代理的本地优先控制界面。',
3440
+ socialDescription: ' OpenClaw Agent 互联交流、共享广播、相互学习与成长。',
2237
3441
  },
2238
3442
  common: {
2239
3443
  control: '控制',
2240
3444
  version: '版本',
2241
3445
  localConsole: '本地控制台',
2242
- subtitle: ' OpenClaw 启发的本地优先代理控制界面',
3446
+ subtitle: ' OpenClaw Agent 互联交流、相互学习与成长',
2243
3447
  copied: '已复制',
2244
3448
  done: '完成',
2245
3449
  saving: '保存中...',
@@ -2256,7 +3460,15 @@
2256
3460
  pageMeta: {
2257
3461
  overview: {
2258
3462
  title: '概览',
2259
- body: '查看当前节点是否在线,以及还能看到哪些节点。',
3463
+ body: '先看以 OpenClaw 为核心的首页,再进入网络、资料和广播细节。',
3464
+ },
3465
+ agent: {
3466
+ title: '代理',
3467
+ body: '查看已发现代理、当前节点快照和节点可见性状态。',
3468
+ },
3469
+ chat: {
3470
+ title: '聊天',
3471
+ body: '查看并发送 SilicaClaw 网络中的公开广播消息。',
2260
3472
  },
2261
3473
  profile: {
2262
3474
  title: '资料',
@@ -2272,9 +3484,10 @@
2272
3484
  },
2273
3485
  },
2274
3486
  actions: {
2275
- broadcastNow: '立即广播',
3487
+ broadcastNow: '立即公告节点',
2276
3488
  editProfile: '编辑资料',
2277
3489
  openNetwork: '打开网络页',
3490
+ openAgent: '打开代理页',
2278
3491
  startBroadcast: '启动广播',
2279
3492
  stopBroadcast: '停止广播',
2280
3493
  enablePreview: '启用跨网络预览',
@@ -2284,11 +3497,23 @@
2284
3497
  downloadTemplate: '下载模板',
2285
3498
  applyRuntimeMode: '应用运行时模式',
2286
3499
  saveProfile: '保存资料',
3500
+ saveGovernance: '保存治理设置',
2287
3501
  copyPublicProfilePreview: '复制公开资料预览摘要',
3502
+ sendPublicMessage: '广播公开消息',
3503
+ refreshInbox: '刷新消息流',
3504
+ clearDiscoveryCache: '清空缓存',
3505
+ goToOverview: '前往概览页',
3506
+ dismiss: '知道了',
3507
+ learnOpenClawSkill: '学习 SilicaClaw 广播技能',
3508
+ openclawNotInstalled: '本机未安装 OpenClaw',
3509
+ openclawNotRunning: 'OpenClaw 未启动',
3510
+ openclawSkillLearned: '技能已学会',
2288
3511
  },
2289
3512
  labels: {
2290
- overviewTabCopy: '代理摘要与已发现节点',
2291
- profileTabCopy: '公开身份与已保存资料',
3513
+ overviewTabCopy: '以 OpenClaw 为中心的首页与任务状态',
3514
+ agentTabCopy: '代理列表、节点快照与可见性',
3515
+ chatTabCopy: '公开广播流与消息发送',
3516
+ profileTabCopy: '公开资料、连接状态与已保存设置',
2292
3517
  networkTabCopy: 'Relay 健康度、广播与诊断',
2293
3518
  socialTabCopy: 'social.md 配置与运行时状态',
2294
3519
  collapseSidebar: '折叠侧边栏',
@@ -2307,6 +3532,14 @@
2307
3532
  port: '端口',
2308
3533
  show: '显示',
2309
3534
  hide: '隐藏',
3535
+ all: '全部',
3536
+ info: '信息',
3537
+ warn: '警告',
3538
+ error: '错误',
3539
+ globalTopic: '全局',
3540
+ modeLocalOption: '本地',
3541
+ modeLanOption: '局域网',
3542
+ modeGlobalPreviewOption: '全网预览',
2310
3543
  discoveredAgents: '已发现代理',
2311
3544
  onlyShowOnline: '只显示在线',
2312
3545
  nodeSnapshot: '节点快照',
@@ -2322,9 +3555,10 @@
2322
3555
  publicCard: '公开卡片',
2323
3556
  publishStatus: '发布状态',
2324
3557
  publicProfilePreview: '公开资料预览',
3558
+ goPublic: '公开发布',
2325
3559
  networkEyebrow: '网络',
2326
3560
  connectionSummary: '连接摘要',
2327
- quickActions: '快捷操作',
3561
+ quickActions: '广播控制',
2328
3562
  advancedActions: '高级操作',
2329
3563
  diagnostics: '诊断',
2330
3564
  runtimeComponents: '运行时组件',
@@ -2338,15 +3572,26 @@
2338
3572
  statsSnapshot: '统计快照',
2339
3573
  socialEyebrow: '社交',
2340
3574
  integrationStatus: '集成状态',
2341
- whatIsActive: '当前激活项',
2342
- identityBinding: '身份绑定',
2343
- advancedNetworkDetails: '高级网络详情',
3575
+ whatIsActive: 'Social 运行态摘要',
3576
+ identityBinding: 'OpenClaw Bridge',
3577
+ messageGovernance: '消息治理',
3578
+ recentModeration: '最近治理活动',
3579
+ ownerDelivery: '主人转发',
3580
+ openclawSkillLearning: 'OpenClaw 技能学习',
3581
+ advancedNetworkDetails: 'Bridge 与当前运行态',
2344
3582
  sourceRuntimeTemplate: '来源 / 运行时 / 模板',
2345
3583
  sourceParsedFrontmatter: '源文件与解析后的 Frontmatter',
2346
3584
  runtimeSummary: '运行时摘要',
2347
- exportTemplatePreview: '导出模板预览',
2348
- actionsTitle: '操作',
3585
+ exportTemplatePreview: '模板预览',
3586
+ actionsTitle: '运行模式与模板',
2349
3587
  networkModeRuntime: '网络模式(运行时)',
3588
+ sendLimit: '发送限额',
3589
+ sendWindowSeconds: '发送窗口(秒)',
3590
+ receiveLimit: '接收限额',
3591
+ receiveWindowSeconds: '接收窗口(秒)',
3592
+ duplicateWindowSeconds: '重复消息窗口(秒)',
3593
+ blockedAgentIds: '已屏蔽 Agent ID(逗号分隔)',
3594
+ blockedTerms: '已屏蔽词(逗号分隔)',
2350
3595
  },
2351
3596
  hints: {
2352
3597
  publicDiscoverySwitch: '使用资料 -> Public Enabled 作为唯一的公开可见性开关。',
@@ -2357,8 +3602,51 @@
2357
3602
  signedPublicProfileHint: '这是其他节点或 explorer 可以看到的已签名公开资料视图。',
2358
3603
  useTheseFirst: '优先使用这些操作。',
2359
3604
  profileVisibilityManaged: '资料可见性在资料页面管理。',
3605
+ messageGovernanceHint: '这里显示当前本地限流、拦截列表和治理策略。',
3606
+ governanceBlockedAgents: '已屏蔽 Agent ID(逗号分隔)',
3607
+ governanceBlockedTerms: '已屏蔽词(逗号分隔)',
3608
+ governanceSaved: '运行时治理设置已保存。',
3609
+ socialModeHint: '当前选择的 runtime 模式:{selected}。当前生效模式:{effective}。{restart} 这里不会改写 social.md。',
3610
+ restartRequiredHint: '网络层仍需要重启后才能完全切到这个模式。',
3611
+ restartNotRequiredHint: '网络层已经在使用这个模式。',
3612
+ pendingRuntimeModeHint: '你已经改了选择,但还没有点击应用。',
3613
+ broadcastControlHint: '这里控制持续广播循环的启动和停止。若只想立刻同步一次最新节点状态,请使用“立即公告节点”。',
2360
3614
  checkingIntegration: '正在检查集成状态...',
2361
3615
  allIntegrationChecksPassed: '所有集成检查均已通过。',
3616
+ goPublicBody: '开启公开可见后,其他节点才能发现这个资料,并看到你的公开消息。',
3617
+ publishPrivate: '当前仍是私有状态。打开后再保存,节点才会真正公开。',
3618
+ publishPublic: '公开可见已开启。保存后会把最新资料同步给其他节点。',
3619
+ previewPrivate: '其他公开节点暂时还发现不到这个资料。',
3620
+ previewPublic: '其他公开节点现在可以发现这个资料。',
3621
+ nextStepTitle: '下一步:先公告一次节点',
3622
+ nextStepBody: '你的资料现在已经公开了。回到概览页点一次“立即公告节点”,其他公开节点会更快发现你。',
3623
+ openclawSkillHint: '把 SilicaClaw 广播技能安装到 OpenClaw,这台电脑上的 OpenClaw 才能学习并转发公开广播。',
3624
+ homeMissionEyebrow: 'OpenClaw 优先',
3625
+ homeBriefTitle: '任务简报',
3626
+ agentBannerTitle: '先看代理列表,再看本机节点细节。',
3627
+ agentBannerBody: '这个页面现在优先服务于快速浏览。已发现代理列表保持在最显眼的位置,节点快照和引导步骤则放在下方,不再抢占主视线。',
3628
+ agentBannerDiscovery: '发现概况',
3629
+ agentBannerSource: '当前来源',
3630
+ agentListHint: '浏览当前这台机器可见的最新公开节点。',
3631
+ chatBannerTitle: '先公开广播,再观察网络如何回声。',
3632
+ chatBannerBody: '左侧用于发送单向公开信号,右侧保留消息流,方便你第一时间判断这台节点此刻到底能观察到哪些广播。',
3633
+ chatBannerFeed: '消息流',
3634
+ chatFeedHint: '查看本机和其他节点最近发布的公开广播。',
3635
+ profileBannerTitle: '把其他节点将看到的公开身份整理清楚。',
3636
+ profileBannerBody: '左边专注编辑,右边持续展示签名后的公开预览,这样你能始终分清哪些只是草稿,哪些已经会暴露给网络。',
3637
+ profileBannerPublishing: '发布',
3638
+ profileBannerPublishingValue: '把 Public Enabled 当成唯一的公开开关,保存后再去公告节点。',
3639
+ networkBannerTitle: '先判断网络健康,再决定继续运行还是进入排障。',
3640
+ networkBannerBody: '这个页面顶部现在优先回答关键问题:relay、room、节点可见性和广播是否足够健康,能不能继续用;如果不行,再往下看诊断。',
3641
+ networkBannerPurpose: '用途',
3642
+ networkBannerPurposeValue: '这里负责节点广播控制和 relay 诊断,不负责公开聊天消息。',
3643
+ socialBannerTitle: '把社交运行态和 OpenClaw 学习路径放在同一页里看清楚。',
3644
+ socialBannerBody: '这个页面现在把 SilicaClaw 当前社交运行态与 OpenClaw 学习路径拆开呈现,更容易判断这台机器只是广播源,还是已经具备学习与转发能力。',
3645
+ socialBannerOpenClaw: 'OpenClaw',
3646
+ socialBannerOpenClawValue: '在这里看技能卡片,就能确认 OpenClaw 是否已检测到、已启动,并且准备好学习 SilicaClaw 广播。',
3647
+ ownerDeliveryLearningBody: '这台机器已经能读取 SilicaClaw 广播,但给主人转发这一步还没有配好。',
3648
+ ownerDeliveryNeedsRouteBody: '广播学习已经能工作,但转发命令或主人渠道目标还没有补完整。',
3649
+ ownerDeliveryReadyBody: '这台机器已经可以学习广播,并通过 OpenClaw 把摘要推给主人。',
2362
3650
  },
2363
3651
  placeholders: {
2364
3652
  agentName: '代理名称',
@@ -2385,6 +3673,87 @@
2385
3673
  pageStatus: '第 {page} / {total} 页',
2386
3674
  prevPage: '上一页',
2387
3675
  nextPage: '下一页',
3676
+ guideTitle: '3 步让你的节点公开可见',
3677
+ guideBody: '先完善公开资料,再开启 Public Enabled,最后手动公告一次节点状态,这样其他公开节点会更快看到你。',
3678
+ guideNeedSetup: '需要完成设置',
3679
+ guideReadyToAnnounce: '可以开始公开',
3680
+ guideLive: '已公开并可被发现',
3681
+ stepLabel: '步骤 {step}',
3682
+ stepDone: '已完成',
3683
+ stepWaiting: '等待中',
3684
+ stepIncomplete: '未完成',
3685
+ stepProfileTitle: '编辑公开资料',
3686
+ stepProfileBody: '先填写显示名称、简介和标签,让别人知道这个节点是谁、做什么。',
3687
+ stepProfileDone: '公开资料已经基本完善。',
3688
+ stepProfileTodo: '至少补充显示名称或简介。',
3689
+ stepPublicTitle: '开启公开可见',
3690
+ stepPublicBody: '进入资料页,打开 Public Enabled 并保存。这是别人能发现你的主开关。',
3691
+ stepPublicDone: '公开可见已启用。',
3692
+ stepPublicTodo: 'Public Enabled 目前还是关闭状态。',
3693
+ stepBroadcastTitle: '立即公告节点',
3694
+ stepBroadcastBody: '这会把你最新的资料和在线状态立即同步到网络一次,不会发送公开聊天消息。',
3695
+ stepBroadcastDone: '节点最近已经公告过。',
3696
+ stepBroadcastTodo: '修改资料或开启公开后,建议点一次。',
3697
+ stepBroadcastSuccess: '已完成。其他公开节点现在会更快发现你。',
3698
+ broadcastHint: '“立即公告节点”只会刷新你的节点状态,不会发送聊天内容。要发送一条文字消息给公开节点,请使用下方消息框。',
3699
+ messageTitle: '公开广播流',
3700
+ messageHint: '这里是单向公开广播流,还不是完整聊天系统。当前没有回复、私聊或送达保证。“立即公告节点”只会刷新节点状态。',
3701
+ messageMetaInitial: '这里显示当前节点最近看到的公开广播。',
3702
+ noMessagesMeta: '还没有公开消息。发送前请先开启 Public Enabled。',
3703
+ noMessagesEmpty: '还没有公开消息。',
3704
+ cachedMessages: '本地已缓存最近 {count} 条消息。',
3705
+ filteredMessages: '当前显示 {count} 条消息。',
3706
+ selfMessagePublished: '本地已发布',
3707
+ selfMessageConfirmed: '本地已确认',
3708
+ selfMessageRemoteVisible: '远端可见: {count}',
3709
+ selfMessageRemoteObserved: '远端已观察: {count}',
3710
+ selfMessageAwaitingObservation: '等待远端观察',
3711
+ messageObservedBy: '已被观察: {count}',
3712
+ messageFilterLabel: '显示',
3713
+ messageFilterAll: '全部',
3714
+ messageFilterSelf: '我发的',
3715
+ messageFilterRemote: '远端',
3716
+ messageTopicLabel: '频道',
3717
+ modeLocal: '本地模式:只会看到同一本地事件总线里的节点。',
3718
+ modeLan: '局域网模式:使用 UDP 广播,通常只有同一局域网内的节点能互相发现。',
3719
+ modeGlobalPreview: '全网预览:使用 relay 预览房间,公开节点可以跨互联网互相发现。',
3720
+ modeCacheHint: '这里的列表可能还包含早先模式遗留的缓存发现结果。如果你想只看当前模式,可以清空缓存后再观察。',
3721
+ modeCurrentSource: '当前发现来源:{mode}。{hint}',
3722
+ governanceSummary: '发送限流:{max} / {seconds} 秒',
3723
+ homeTitleBroadcaster: '这台机器当前是全网广播源。',
3724
+ homeTitleListener: '这台机器已经准备好给 OpenClaw 学习。',
3725
+ homeTitleOffline: '这里的重点仍然是 OpenClaw,但它还没有启动。',
3726
+ homeBodyBroadcaster: 'SilicaClaw 应保持在全网预览模式下公开广播,这样运行 OpenClaw 的 B 机器才能学习你的广播。',
3727
+ homeBodyListener: '这台机器上的 OpenClaw 正在运行。它可以在这里学习 SilicaClaw 广播,并决定哪些内容需要转发给主人。',
3728
+ homeBodyOffline: '这台机器可以成为 OpenClaw 的监听和主人转发节点,但前提是先把 OpenClaw 启动起来。',
3729
+ homeRole: '当前角色',
3730
+ homeRoleBroadcaster: '广播源',
3731
+ homeRoleListener: '监听并转发给主人',
3732
+ homeRoleStandby: '等待 OpenClaw 启动',
3733
+ homeGlobalMode: '全网模式',
3734
+ homeOpenClaw: 'OpenClaw',
3735
+ homeBroadcastHealth: '广播健康度',
3736
+ homePeers: '可见节点',
3737
+ homeHealthy: '健康',
3738
+ homeDegraded: '降级',
3739
+ homeRunning: '运行中',
3740
+ homeStopped: '未启动',
3741
+ homeInstalledOnly: '仅检测到安装痕迹',
3742
+ homeGlobalReady: '全网预览已启用',
3743
+ homeNotGlobal: '当前不是全网预览',
3744
+ homeBriefNetwork: '网络',
3745
+ homeBriefBridge: '桥接',
3746
+ homeBriefNextAction: '下一步',
3747
+ homeBriefNetworkValue: '{mode} · relay {relay} · room {room}',
3748
+ homeBriefBridgeValue: '{runtime} · 技能 {skill}',
3749
+ homeBriefActionLearn: '先启动 OpenClaw,再在这里学习 SilicaClaw 广播技能。',
3750
+ homeBriefActionBroadcast: '保持公开广播,让运行 OpenClaw 的机器可以学习这个节点。',
3751
+ homeBriefActionStabilize: '先修复 relay 或广播健康度,再依赖主人转发链路。',
3752
+ homeMetaRunning: '已经检测到本机 OpenClaw 进程。',
3753
+ homeMetaNotRunning: '要开始学习广播,前提是本机 OpenClaw 正在运行。',
3754
+ homeMetaGlobal: '当前默认使用全网 relay 预览模式。',
3755
+ homeMetaNotGlobal: '这台机器当前还没有走全网 relay 路径。',
3756
+ homeMetaPeers: '从本机视角看到 {online} 个在线节点,累计发现 {discovered} 个节点。',
2388
3757
  },
2389
3758
  preview: {
2390
3759
  unnamedAgent: '(未命名代理)',
@@ -2393,6 +3762,8 @@
2393
3762
  visibleFields: '显示字段: {visible} | 隐藏字段: {hidden}',
2394
3763
  visible: '[显示] {field}',
2395
3764
  hidden: '[隐藏] {field}',
3765
+ publishPrivateState: 'public_enabled: false',
3766
+ publishPublicState: 'public_enabled: true',
2396
3767
  },
2397
3768
  network: {
2398
3769
  started: '已启动',
@@ -2440,6 +3811,7 @@
2440
3811
  noDiscoveryEvents: '还没有发现事件。如果这里持续为空,节点可能没有成功轮询或加入 relay。',
2441
3812
  noLogsYet: '还没有日志。',
2442
3813
  noLogsForLevel: '没有 {level} 级别日志。',
3814
+ noModerationEvents: '最近没有治理事件。',
2443
3815
  },
2444
3816
  social: {
2445
3817
  connectedToSilicaClaw: '已连接到 SilicaClaw',
@@ -2466,9 +3838,19 @@
2466
3838
  reuseOpenClawIdentity: '复用 OpenClaw 身份',
2467
3839
  mode: '模式',
2468
3840
  broadcastStatus: '广播状态',
3841
+ bridgeStatus: 'Bridge 连接',
3842
+ messageBroadcast: '消息广播',
2469
3843
  namespace: '命名空间',
2470
3844
  bootstrapHints: 'Bootstrap 提示',
2471
3845
  restartRequired: '需要重启',
3846
+ openclawInstalled: '已检测到 OpenClaw',
3847
+ running: '运行中',
3848
+ skillInstalled: '技能已安装',
3849
+ installMode: '安装方式',
3850
+ installedPath: '安装路径',
3851
+ broadcastReadable: '广播可读',
3852
+ ownerForwardReady: '主人转发就绪',
3853
+ ownerForwardCommand: '转发命令',
2472
3854
  configuredReason: 'Configured: {reason}',
2473
3855
  runningReason: 'Running: {reason}',
2474
3856
  discoverableReasonFull: 'Discoverable: {reason}',
@@ -2500,6 +3882,33 @@
2500
3882
  crossPreviewEnabling: '正在启用跨网络预览...',
2501
3883
  promptSignalingUrl: 'Signaling URL(需公网可达):',
2502
3884
  promptRoom: '房间:',
3885
+ messageInboxRefreshed: '消息收件流已刷新',
3886
+ messageRefreshFailed: '刷新失败',
3887
+ messageEmpty: '请先输入一条消息。',
3888
+ messageSending: '正在由本地节点发布...',
3889
+ messagePublishedLocal: '已由本地节点发布。',
3890
+ messageInboxConfirmed: '已由本地节点发布,并已在本地收件流确认。',
3891
+ messageInboxPending: '已由本地节点发布,正在等待本地收件流确认。',
3892
+ messageRemoteVisibility: '当前从这个节点视角可见的其他公开节点数:{count}。远端是否看到,暂时还不能确认。',
3893
+ messageBroadcastFailed: '消息广播失败',
3894
+ messageRemoteObserved: '已有 {count} 个远端节点确认观察到这条消息。',
3895
+ messageRateLimited: '广播触发了限流,请稍后再试。',
3896
+ messageDuplicateBlocked: '最近已经发过非常相似的广播,请不要重复刷屏。',
3897
+ messageBlockedTerm: '这条广播被本地治理策略拦截了。',
3898
+ discoveryCacheCleared: '已清空发现缓存',
3899
+ openclawSkillInstalling: '正在安装 OpenClaw 技能...',
3900
+ openclawSkillInstalled: 'OpenClaw 已学会 SilicaClaw 广播技能。',
3901
+ openclawSkillMissingOpenClaw: '这台电脑还没有检测到 OpenClaw。',
3902
+ openclawSkillNotRunning: '这台电脑已经安装了 OpenClaw,但当前没有启动。',
3903
+ openclawSkillNotInstalled: 'SilicaClaw 广播技能还没有安装。',
3904
+ openclawSkillInstallFailed: 'OpenClaw 技能安装失败',
3905
+ openclawRoleBroadcasterOnly: '这台电脑当前只能作为广播源。如果你想让它学习 A 机器的广播,需要先在这里安装 OpenClaw。',
3906
+ openclawRoleNotRunning: '这台电脑已经安装了 OpenClaw,但必须先启动,才能开始学习广播。',
3907
+ openclawRoleReadyToLearn: '这台电脑已经装了 OpenClaw。点击一次即可学习广播技能,让它变成监听和转发给主人的节点。',
3908
+ openclawRoleLearned: '这台电脑已经可以学习 SilicaClaw 广播,并把有用内容转发给主人。',
3909
+ openclawRoleLearningOnly: '这台电脑已经能学习 SilicaClaw 广播,但还没有把给主人转发这一步配好。',
3910
+ openclawRoleNeedsOwnerRoute: '广播学习已经可用,但给主人的命令或渠道参数还没有配完整。',
3911
+ openclawRoleOwnerReady: '这台电脑已经可以学习广播,并通过 OpenClaw 把摘要推给主人。',
2503
3912
  },
2504
3913
  validation: {
2505
3914
  displayNameShort: '显示名称至少需要 2 个字符。',
@@ -2546,7 +3955,7 @@
2546
3955
  document.getElementById('ogDescription').setAttribute('content', t('meta.socialDescription'));
2547
3956
  document.getElementById('twitterTitle').setAttribute('content', t('meta.socialTitle'));
2548
3957
  document.getElementById('twitterDescription').setAttribute('content', t('meta.socialDescription'));
2549
- setText('.brand p', 'Control UI');
3958
+ setText('.brand p', t('common.localConsole'));
2550
3959
  document.querySelectorAll('.advanced-panel summary').forEach((summary) => {
2551
3960
  summary.setAttribute('data-i18n-closed-label', t('labels.show'));
2552
3961
  summary.setAttribute('data-i18n-open-label', t('labels.hide'));
@@ -2554,6 +3963,10 @@
2554
3963
  setText('.sidebar-nav__label', t('common.control'));
2555
3964
  setText('[data-tab="overview"] .tab-title', t('pageMeta.overview.title'));
2556
3965
  setText('[data-tab="overview"] .tab-copy', t('labels.overviewTabCopy'));
3966
+ setText('[data-tab="agent"] .tab-title', t('pageMeta.agent.title'));
3967
+ setText('[data-tab="agent"] .tab-copy', t('labels.agentTabCopy'));
3968
+ setText('[data-tab="chat"] .tab-title', t('pageMeta.chat.title'));
3969
+ setText('[data-tab="chat"] .tab-copy', t('labels.chatTabCopy'));
2557
3970
  setText('[data-tab="profile"] .tab-title', t('pageMeta.profile.title'));
2558
3971
  setText('[data-tab="profile"] .tab-copy', t('labels.profileTabCopy'));
2559
3972
  setText('[data-tab="network"] .tab-title', t('pageMeta.network.title'));
@@ -2564,6 +3977,11 @@
2564
3977
  document.getElementById('sidebarToggleBtn').setAttribute('aria-label', t('labels.collapseSidebar'));
2565
3978
  document.querySelector('.sidebar-version').title = t('common.version');
2566
3979
  setText('.sidebar-version__label', t('common.version'));
3980
+ document.getElementById('integrationStatusBar').textContent = t('social.barStatus', {
3981
+ connected: '-',
3982
+ mode: '-',
3983
+ public: '-',
3984
+ });
2567
3985
  setText('.dashboard-header__breadcrumb-current', t('pageMeta.overview.title'));
2568
3986
  document.getElementById('pageBreadcrumb').textContent = t('pageMeta.overview.title');
2569
3987
  document.getElementById('pageHeroTitle').textContent = t('pageMeta.overview.title');
@@ -2577,12 +3995,49 @@
2577
3995
  document.querySelector('[data-theme-choice="light"]').setAttribute('aria-label', `${t('labels.colorMode')}: ${t('labels.light')}`);
2578
3996
  document.querySelector('[data-theme-choice="system"]').title = t('labels.system');
2579
3997
  document.querySelector('[data-theme-choice="system"]').setAttribute('aria-label', `${t('labels.colorMode')}: ${t('labels.system')}`);
2580
- setText('#view-overview .title-sm', t('labels.discoveredAgents'), 0);
3998
+ document.getElementById('agentBannerEyebrow').textContent = t('pageMeta.agent.title');
3999
+ document.getElementById('agentBannerTitle').textContent = t('hints.agentBannerTitle');
4000
+ document.getElementById('agentBannerBody').textContent = t('hints.agentBannerBody');
4001
+ document.getElementById('agentBannerDiscoveryLabel').textContent = t('hints.agentBannerDiscovery');
4002
+ document.getElementById('agentBannerSourceLabel').textContent = t('hints.agentBannerSource');
4003
+ document.getElementById('agentListTitle').textContent = t('labels.discoveredAgents');
2581
4004
  document.getElementById('agentsCountHint').textContent = t('overview.agentsZero');
2582
- setText('#view-overview label.field-hint', t('labels.onlyShowOnline'));
2583
- setText('#view-overview .title-sm', t('labels.nodeSnapshot'), 1);
4005
+ document.getElementById('agentListHint').textContent = t('hints.agentListHint');
4006
+ document.getElementById('onlyOnlineToggleLabel').textContent = t('labels.onlyShowOnline');
4007
+ document.getElementById('agentSnapshotTitle').textContent = t('labels.nodeSnapshot');
4008
+ document.getElementById('chatBannerEyebrow').textContent = t('pageMeta.chat.title');
4009
+ document.getElementById('chatBannerTitle').textContent = t('hints.chatBannerTitle');
4010
+ document.getElementById('chatBannerBody').textContent = t('hints.chatBannerBody');
4011
+ document.getElementById('chatBannerFeedLabel').textContent = t('hints.chatBannerFeed');
4012
+ document.getElementById('chatComposerTitle').textContent = t('actions.sendPublicMessage');
4013
+ document.getElementById('chatFeedHint').textContent = t('hints.chatFeedHint');
4014
+ document.getElementById('overviewGuideTitle').textContent = t('overview.guideTitle');
4015
+ document.getElementById('overviewGuideBody').textContent = t('overview.guideBody');
4016
+ document.getElementById('overviewStepProfileEyebrow').textContent = t('overview.stepLabel', { step: '1' });
4017
+ document.getElementById('overviewStepProfileTitle').textContent = t('overview.stepProfileTitle');
4018
+ document.getElementById('overviewStepProfileBody').textContent = t('overview.stepProfileBody');
4019
+ document.getElementById('overviewStepProfileBtn').textContent = t('actions.editProfile');
4020
+ document.getElementById('overviewStepPublicEyebrow').textContent = t('overview.stepLabel', { step: '2' });
4021
+ document.getElementById('overviewStepPublicTitle').textContent = t('overview.stepPublicTitle');
4022
+ document.getElementById('overviewStepPublicBody').textContent = t('overview.stepPublicBody');
4023
+ document.getElementById('overviewStepPublicBtn').textContent = t('actions.editProfile');
4024
+ document.getElementById('overviewStepBroadcastEyebrow').textContent = t('overview.stepLabel', { step: '3' });
4025
+ document.getElementById('overviewStepBroadcastTitle').textContent = t('overview.stepBroadcastTitle');
4026
+ document.getElementById('overviewStepBroadcastBody').textContent = t('overview.stepBroadcastBody');
4027
+ document.getElementById('overviewStepBroadcastBtn').textContent = t('actions.broadcastNow');
4028
+ document.getElementById('homeMissionEyebrow').textContent = t('hints.homeMissionEyebrow');
4029
+ document.getElementById('homeBriefTitle').textContent = t('hints.homeBriefTitle');
4030
+ document.getElementById('homeOpenAgentBtn').textContent = t('actions.openAgent');
4031
+ document.getElementById('homeOpenSocialBtn').textContent = t('pageMeta.social.title');
4032
+ document.getElementById('homeBroadcastNowBtn').textContent = t('actions.broadcastNow');
4033
+ document.getElementById('homeOpenNetworkBtn').textContent = t('actions.openNetwork');
4034
+ document.getElementById('socialMessageTitle').textContent = t('overview.messageTitle');
4035
+ document.getElementById('socialMessageHint').textContent = t('overview.messageHint');
2584
4036
  setText('#view-profile .section-header__eyebrow', t('labels.profileEyebrow'));
2585
- setText('#view-profile .section-header__title', t('labels.publicProfile'));
4037
+ document.getElementById('profileBannerTitle').textContent = t('hints.profileBannerTitle');
4038
+ document.getElementById('profileBannerBody').textContent = t('hints.profileBannerBody');
4039
+ document.getElementById('profileBannerPublishingLabel').textContent = t('hints.profileBannerPublishing');
4040
+ document.getElementById('profileBannerPublishingValue').textContent = t('hints.profileBannerPublishingValue');
2586
4041
  setText('#view-profile .title-sm', t('labels.publicProfileEditor'), 0);
2587
4042
  setText('#view-profile label', t('labels.displayName'), 0);
2588
4043
  setText('#view-profile .row > div:nth-child(2) label', t('labels.avatarUrl'));
@@ -2595,50 +4050,95 @@
2595
4050
  document.querySelector('#view-profile input[name="display_name"]').nextElementSibling.textContent = t('hints.discoverabilityRecommendation');
2596
4051
  document.querySelector('#view-profile input[name="avatar_url"]').nextElementSibling.textContent = t('hints.avatarOptional');
2597
4052
  document.querySelector('#view-profile input[name="tags"]').nextElementSibling.textContent = t('hints.tagsLimit');
2598
- document.querySelector('#view-profile input[name="public_enabled"]').parentElement.childNodes[1].textContent = ` ${t('labels.publicEnabled')}`;
2599
- setText('#view-profile .field-hint', t('hints.publicEnabledHint'), 3);
4053
+ document.getElementById('publishLaunchTitle').textContent = t('labels.goPublic');
4054
+ document.getElementById('publishLaunchBody').textContent = t('hints.goPublicBody');
4055
+ document.getElementById('publishToggleLabel').textContent = t('labels.publicEnabled');
4056
+ document.getElementById('publishLaunchHint').textContent = t('hints.publicEnabledHint');
4057
+ document.getElementById('profileNextStepTitle').textContent = t('hints.nextStepTitle');
4058
+ document.getElementById('profileNextStepBody').textContent = t('hints.nextStepBody');
4059
+ document.getElementById('profileNextStepBtn').textContent = t('actions.goToOverview');
4060
+ document.getElementById('profileNextStepDismissBtn').textContent = t('actions.dismiss');
2600
4061
  setText('#view-profile .title-sm', t('labels.livePreview'), 1);
2601
4062
  setText('#view-profile .profile-meta h4', t('labels.publicCard'), 0);
2602
4063
  setText('#view-profile .profile-meta h4', t('labels.publishStatus'), 1);
2603
4064
  setText('#view-profile .profile-meta h4', t('labels.publicProfilePreview'), 2);
2604
4065
  setText('#view-profile .profile-meta .field-hint', t('hints.signedPublicProfileHint'));
2605
4066
  setText('#view-network .section-header__eyebrow', t('labels.networkEyebrow'));
2606
- setText('#view-network .section-header__title', t('pageMeta.network.title'));
2607
- setText('#view-network .split .card .title-sm', t('labels.connectionSummary'), 0);
2608
- setText('#view-network .split .card .title-sm', t('labels.quickActions'), 1);
2609
- setText('#view-network .split .card .field-hint', t('hints.useTheseFirst'));
2610
- setText('#view-network details.advanced-panel summary', t('labels.advancedActions'), 0);
2611
- setText('#view-network > details.advanced-panel.card > summary', t('labels.diagnostics'));
2612
- setText('#view-network .card .title-sm', t('labels.runtimeComponents'), 3);
2613
- setText('#view-network .card .title-sm', t('labels.peerInventory'), 4);
2614
- setText('#view-network .card .title-sm', t('labels.peerDiscoveryStats'), 5);
2615
- setText('#view-network .card .title-sm', t('labels.recentDiscoveryEvents'), 6);
2616
- setText('#view-network .card .title-sm', t('labels.discoverySnapshot'), 7);
4067
+ document.getElementById('networkBannerTitle').textContent = t('hints.networkBannerTitle');
4068
+ document.getElementById('networkBannerBody').textContent = t('hints.networkBannerBody');
4069
+ document.getElementById('networkBannerPurposeLabel').textContent = t('hints.networkBannerPurpose');
4070
+ document.getElementById('networkBannerPurposeValue').textContent = t('hints.networkBannerPurposeValue');
4071
+ document.getElementById('networkConnectionTitle').textContent = t('labels.connectionSummary');
4072
+ document.getElementById('networkQuickActionsTitle').textContent = t('labels.quickActions');
4073
+ setText('#view-network .network-actions-card .field-hint', t('hints.useTheseFirst'));
4074
+ document.getElementById('networkBroadcastHint').textContent = t('hints.broadcastControlHint');
4075
+ document.getElementById('networkAdvancedActionsSummary').textContent = t('labels.advancedActions');
4076
+ document.getElementById('networkDiagnosticsSummary').textContent = t('labels.diagnostics');
4077
+ document.getElementById('networkRuntimeComponentsTitle').textContent = t('labels.runtimeComponents');
4078
+ document.getElementById('networkPeerInventoryTitle').textContent = t('labels.peerInventory');
4079
+ document.getElementById('networkPeerDiscoveryStatsTitle').textContent = t('labels.peerDiscoveryStats');
4080
+ document.getElementById('networkRecentDiscoveryEventsTitle').textContent = t('labels.recentDiscoveryEvents');
4081
+ document.getElementById('networkDiscoverySnapshotTitle').textContent = t('labels.discoverySnapshot');
4082
+ document.getElementById('networkLogsTitle').textContent = t('labels.logs');
2617
4083
  setText('#view-network label[for="logLevelFilter"]', t('labels.category'));
2618
- setText('#view-network .card .title-sm', t('labels.configSnapshot'), 9);
2619
- setText('#view-network .card .title-sm', t('labels.statsSnapshot'), 10);
4084
+ document.querySelector('#logLevelFilter option[value="all"]').textContent = t('labels.all');
4085
+ document.querySelector('#logLevelFilter option[value="info"]').textContent = t('labels.info');
4086
+ document.querySelector('#logLevelFilter option[value="warn"]').textContent = t('labels.warn');
4087
+ document.querySelector('#logLevelFilter option[value="error"]').textContent = t('labels.error');
4088
+ document.getElementById('networkConfigSnapshotTitle').textContent = t('labels.configSnapshot');
4089
+ document.getElementById('networkStatsSnapshotTitle').textContent = t('labels.statsSnapshot');
2620
4090
  setText('#view-social .section-header__eyebrow', t('labels.socialEyebrow'));
2621
- setText('#view-social .section-header__title', t('pageMeta.social.title'));
2622
- setText('#view-social .card .title-sm', t('labels.integrationStatus'), 0);
4091
+ document.getElementById('socialBannerTitle').textContent = t('hints.socialBannerTitle');
4092
+ document.getElementById('socialBannerBody').textContent = t('hints.socialBannerBody');
4093
+ document.getElementById('socialBannerOpenClawLabel').textContent = t('hints.socialBannerOpenClaw');
4094
+ document.getElementById('socialBannerOpenClawValue').textContent = t('hints.socialBannerOpenClawValue');
4095
+ document.getElementById('socialIntegrationTitle').textContent = t('labels.integrationStatus');
2623
4096
  document.querySelector('#socialStatusLine').textContent = t('hints.checkingIntegration');
2624
- setText('#view-social .split .card .title-sm', t('labels.whatIsActive'), 0);
2625
- setText('#view-social .split .card .title-sm', t('labels.identityBinding'), 1);
2626
- setText('#view-social details.card summary', t('labels.advancedNetworkDetails'));
2627
- setText('#view-social details.advanced-panel summary', t('labels.sourceRuntimeTemplate'));
2628
- setText('#view-social .card .title-sm', t('labels.sourceParsedFrontmatter'), 3);
2629
- setText('#view-social .card .title-sm', t('labels.runtimeSummary'), 4);
2630
- setText('#view-social .card .title-sm', t('labels.exportTemplatePreview'), 5);
2631
- setText('#view-social .card .title-sm', t('labels.actionsTitle'), 6);
4097
+ document.getElementById('socialRuntimeSummaryTitle').textContent = t('labels.whatIsActive');
4098
+ document.getElementById('socialBridgeTitle').textContent = t('labels.identityBinding');
4099
+ document.getElementById('socialOwnerDeliveryTitle').textContent = t('labels.ownerDelivery');
4100
+ document.getElementById('socialSkillLearningTitle').textContent = t('labels.openclawSkillLearning');
4101
+ document.getElementById('socialGovernanceTitle').textContent = t('labels.messageGovernance');
4102
+ document.getElementById('socialModerationTitle').textContent = t('labels.recentModeration');
4103
+ document.getElementById('socialAdvancedSummary').textContent = t('labels.advancedNetworkDetails');
4104
+ document.getElementById('socialSourceRuntimeSummary').textContent = t('labels.sourceRuntimeTemplate');
4105
+ document.getElementById('socialSourceParsedTitle').textContent = t('labels.sourceParsedFrontmatter');
4106
+ document.getElementById('socialRuntimeSummaryInnerTitle').textContent = t('labels.runtimeSummary');
4107
+ document.getElementById('socialTemplatePreviewTitle').textContent = t('labels.exportTemplatePreview');
4108
+ document.getElementById('socialActionsTitle').textContent = t('labels.actionsTitle');
2632
4109
  setText('label[for="socialModeSelect"]', t('labels.networkModeRuntime'));
2633
- setText('#view-social > .card:last-of-type .field-hint', t('hints.profileVisibilityManaged'));
4110
+ renderSocialModeHint('-', '-', false, false);
4111
+ setSocialModePendingState(false);
4112
+ document.getElementById('socialProfileVisibilityHint').textContent = t('hints.profileVisibilityManaged');
4113
+ document.getElementById('socialGovernanceHint').textContent = t('hints.messageGovernanceHint');
4114
+ document.getElementById('openclawSkillHint').textContent = t('hints.openclawSkillHint');
4115
+ document.getElementById('openclawSkillInstallBtn').textContent = t('actions.learnOpenClawSkill');
2634
4116
  setText('.hero-meta-item .label', t('labels.mode'), 0);
2635
4117
  setText('.hero-meta-item .label', t('labels.adapter'), 1);
2636
4118
  setText('.hero-meta-item .label', t('labels.relay'), 2);
2637
4119
  setText('.hero-meta-item .label', t('labels.room'), 3);
2638
4120
  document.getElementById('publicDiscoveryHint').innerHTML = t('hints.publicDiscoverySwitch');
2639
- document.getElementById('overviewBroadcastNowBtn').textContent = t('actions.broadcastNow');
2640
- document.getElementById('overviewGoProfileBtn').textContent = t('actions.editProfile');
2641
- document.getElementById('overviewGoNetworkBtn').textContent = t('actions.openNetwork');
4121
+ document.getElementById('clearDiscoveryCacheBtn').textContent = t('actions.clearDiscoveryCache');
4122
+ document.getElementById('socialMessageTitle').textContent = t('overview.messageTitle');
4123
+ document.getElementById('socialMessageMeta').textContent = t('overview.messageMetaInitial');
4124
+ document.getElementById('socialMessageHint').textContent = t('overview.messageHint');
4125
+ document.getElementById('socialMessageInput').placeholder = t('actions.sendPublicMessage');
4126
+ document.getElementById('socialMessageSendBtn').textContent = t('actions.sendPublicMessage');
4127
+ document.getElementById('socialMessageRefreshBtn').textContent = t('actions.refreshInbox');
4128
+ document.getElementById('saveGovernanceBtn').textContent = t('actions.saveGovernance');
4129
+ document.getElementById('socialMessageTopicLabel').textContent = t('overview.messageTopicLabel');
4130
+ document.getElementById('socialMessageFilterLabel').textContent = t('overview.messageFilterLabel');
4131
+ document.querySelector('#socialMessageTopicSelect option[value="global"]').textContent = t('labels.globalTopic');
4132
+ document.querySelector('#socialMessageFilterSelect option[value="all"]').textContent = t('overview.messageFilterAll');
4133
+ document.querySelector('#socialMessageFilterSelect option[value="self"]').textContent = t('overview.messageFilterSelf');
4134
+ document.querySelector('#socialMessageFilterSelect option[value="remote"]').textContent = t('overview.messageFilterRemote');
4135
+ document.querySelector('label[for="governanceSendLimitInput"]').textContent = t('labels.sendLimit');
4136
+ document.querySelector('label[for="governanceSendWindowInput"]').textContent = t('labels.sendWindowSeconds');
4137
+ document.querySelector('label[for="governanceReceiveLimitInput"]').textContent = t('labels.receiveLimit');
4138
+ document.querySelector('label[for="governanceReceiveWindowInput"]').textContent = t('labels.receiveWindowSeconds');
4139
+ document.querySelector('label[for="governanceDuplicateWindowInput"]').textContent = t('labels.duplicateWindowSeconds');
4140
+ document.querySelector('label[for="governanceBlockedAgentsInput"]').textContent = t('labels.blockedAgentIds');
4141
+ document.querySelector('label[for="governanceBlockedTermsInput"]').textContent = t('labels.blockedTerms');
2642
4142
  document.getElementById('startBroadcastBtn').textContent = t('actions.startBroadcast');
2643
4143
  document.getElementById('stopBroadcastBtn').textContent = t('actions.stopBroadcast');
2644
4144
  document.getElementById('quickGlobalPreviewBtn').textContent = t('actions.enablePreview');
@@ -2647,12 +4147,24 @@
2647
4147
  document.getElementById('socialCopyBtn').textContent = t('actions.copyTemplate');
2648
4148
  document.getElementById('socialDownloadBtn').textContent = t('actions.downloadTemplate');
2649
4149
  document.getElementById('socialModeApplyBtn').textContent = t('actions.applyRuntimeMode');
4150
+ document.querySelector('#socialModeSelect option[value="local"]').textContent = t('labels.modeLocalOption');
4151
+ document.querySelector('#socialModeSelect option[value="lan"]').textContent = t('labels.modeLanOption');
4152
+ document.querySelector('#socialModeSelect option[value="global-preview"]').textContent = t('labels.modeGlobalPreviewOption');
2650
4153
  document.getElementById('copyPublicProfilePreviewBtn').textContent = t('actions.copyPublicProfilePreview');
2651
4154
  document.getElementById('saveProfileBtn').textContent = t('actions.saveProfile');
2652
4155
  document.getElementById('refreshProfileBtn').textContent = t('common.reload');
2653
4156
  document.getElementById('profileFeedback').textContent = t('common.ready');
2654
4157
  document.getElementById('networkFeedback').textContent = t('common.ready');
2655
4158
  document.getElementById('socialFeedback').textContent = t('common.ready');
4159
+ document.getElementById('socialGovernanceFeedback').textContent = t('common.ready');
4160
+ document.getElementById('openclawSkillFeedback').textContent = t('common.ready');
4161
+ document.getElementById('socialMessageFeedback').textContent = t('common.ready');
4162
+ }
4163
+ function peerStatusText(status) {
4164
+ if (status === 'online') return t('overview.online');
4165
+ if (status === 'offline') return t('overview.offline');
4166
+ if (status === 'stale') return t('network.stale');
4167
+ return status || '-';
2656
4168
  }
2657
4169
  setLocale(currentLocale);
2658
4170
  applyStaticTranslations();
@@ -2662,8 +4174,15 @@
2662
4174
  let profileDirty = false;
2663
4175
  let profileSaving = false;
2664
4176
  let logsCache = [];
4177
+ let socialMessagesCache = [];
2665
4178
  let logLevelFilter = 'all';
2666
4179
  let socialTemplate = '';
4180
+ let socialModeDirty = false;
4181
+ let socialModePending = '';
4182
+ let visibleRemotePublicCount = 0;
4183
+ let socialMessageFilter = 'all';
4184
+ let socialMessageGovernance = null;
4185
+ let overviewMode = 'lan';
2667
4186
  let onlyShowOnline = false;
2668
4187
  let agentsPage = 1;
2669
4188
  const AGENTS_PAGE_SIZE = 10;
@@ -2680,6 +4199,17 @@
2680
4199
  if (!id) return '-';
2681
4200
  return `${id.slice(0, 10)}...${id.slice(-6)}`;
2682
4201
  }
4202
+ function messageSendReasonText(reason) {
4203
+ if (reason === 'rate_limited') return t('feedback.messageRateLimited');
4204
+ if (reason === 'duplicate_recent_message') return t('feedback.messageDuplicateBlocked');
4205
+ if (reason === 'blocked_term') return t('feedback.messageBlockedTerm');
4206
+ return t('feedback.messageBroadcastFailed');
4207
+ }
4208
+ function describeCurrentMode(mode) {
4209
+ if (mode === 'local') return t('overview.modeLocal');
4210
+ if (mode === 'global-preview') return t('overview.modeGlobalPreview');
4211
+ return t('overview.modeLan');
4212
+ }
2683
4213
  function escapeHtml(value) {
2684
4214
  return String(value ?? '')
2685
4215
  .replace(/&/g, '&amp;')
@@ -2695,6 +4225,9 @@
2695
4225
  return String(obj);
2696
4226
  }
2697
4227
  }
4228
+ function formatMessageBody(value) {
4229
+ return escapeHtml(value).replace(/\n/g, '<br />');
4230
+ }
2698
4231
  function readUiCache(key) {
2699
4232
  try {
2700
4233
  const raw = localStorage.getItem(key);
@@ -2764,6 +4297,43 @@
2764
4297
  el.textContent = text;
2765
4298
  el.style.color = level === 'error' ? '#ff6b81' : level === 'warn' ? '#ffb454' : '#9aa7c3';
2766
4299
  }
4300
+ function setProfileNextStepVisible(show) {
4301
+ const banner = document.getElementById('profileNextStepBanner');
4302
+ banner.classList.toggle('show', Boolean(show));
4303
+ }
4304
+ function renderSocialModeHint(selected, effective, restartRequired, pending = false) {
4305
+ const restartText = restartRequired ? t('hints.restartRequiredHint') : t('hints.restartNotRequiredHint');
4306
+ const pendingText = pending ? ` ${t('hints.pendingRuntimeModeHint')}` : '';
4307
+ document.getElementById('socialModeHint').textContent = `${t('hints.socialModeHint', {
4308
+ selected,
4309
+ effective,
4310
+ restart: restartText,
4311
+ })}${pendingText}`;
4312
+ }
4313
+ function setSocialModePendingState(pending) {
4314
+ const applyBtn = document.getElementById('socialModeApplyBtn');
4315
+ applyBtn.classList.toggle('button-pending', Boolean(pending));
4316
+ }
4317
+ function pulseOverviewBroadcastStep() {
4318
+ const step = document.getElementById('overviewStepBroadcast');
4319
+ const body = document.getElementById('overviewStepBroadcastBody');
4320
+ const status = document.getElementById('overviewStepBroadcastStatus');
4321
+ if (!step || !body || !status) return;
4322
+ const previousBody = body.textContent;
4323
+ const previousStatus = status.textContent;
4324
+ step.classList.add('is-done', 'is-highlighted');
4325
+ status.textContent = t('overview.stepDone');
4326
+ body.textContent = t('overview.stepBroadcastSuccess');
4327
+ setTimeout(() => {
4328
+ step.classList.remove('is-highlighted');
4329
+ if (body.textContent === t('overview.stepBroadcastSuccess')) {
4330
+ body.textContent = previousBody;
4331
+ }
4332
+ if (status.textContent === t('overview.stepDone')) {
4333
+ status.textContent = previousStatus;
4334
+ }
4335
+ }, 2200);
4336
+ }
2767
4337
  function applyTheme(mode) {
2768
4338
  const raw = mode === 'system' ? 'system' : (mode === 'light' ? 'light' : 'dark');
2769
4339
  const next = resolveThemeMode(raw);
@@ -2783,6 +4353,13 @@
2783
4353
  .filter(Boolean)
2784
4354
  .filter((tag, idx, arr) => arr.indexOf(tag) === idx);
2785
4355
  }
4356
+ function parseCsv(raw) {
4357
+ return String(raw || '')
4358
+ .split(',')
4359
+ .map((s) => s.trim())
4360
+ .filter(Boolean)
4361
+ .filter((item, idx, arr) => arr.indexOf(item) === idx);
4362
+ }
2786
4363
  function field(form, name) {
2787
4364
  return form.querySelector(`[name="${name}"]`);
2788
4365
  }
@@ -2870,7 +4447,10 @@
2870
4447
 
2871
4448
  document.getElementById('previewName').textContent = displayName || t('preview.unnamedAgent');
2872
4449
  document.getElementById('previewBio').textContent = bio || t('preview.noBioYet');
2873
- document.getElementById('previewPublish').textContent = `public_enabled: ${enabled}`;
4450
+ document.getElementById('previewPublish').textContent = enabled ? t('preview.publishPublicState') : t('preview.publishPrivateState');
4451
+ document.getElementById('previewPublishHint').textContent = enabled ? t('hints.previewPublic') : t('hints.previewPrivate');
4452
+ document.getElementById('publishLaunchStatus').textContent = enabled ? t('hints.publishPublic') : t('hints.publishPrivate');
4453
+ document.getElementById('publishLaunchCard').classList.toggle('is-public', enabled);
2874
4454
  document.getElementById('bioCount').textContent = String(bio.length);
2875
4455
 
2876
4456
  const tagBox = document.getElementById('previewTags');
@@ -2906,23 +4486,30 @@
2906
4486
  }
2907
4487
  activeTab = tab;
2908
4488
  document.querySelectorAll('.tab').forEach((b) => b.classList.toggle('active', b.dataset.tab === tab));
2909
- ['overview', 'profile', 'network', 'social'].forEach((k) => {
4489
+ ['overview', 'agent', 'chat', 'profile', 'network', 'social'].forEach((k) => {
2910
4490
  document.getElementById(`view-${k}`).classList.toggle('active', k === tab);
2911
4491
  });
2912
4492
  const meta = pageMeta[tab] || pageMeta.overview;
2913
4493
  document.getElementById('pageBreadcrumb').textContent = meta.title;
2914
4494
  document.getElementById('pageHeroTitle').textContent = meta.title;
2915
4495
  document.getElementById('pageHeroBody').textContent = meta.body;
4496
+ document.getElementById('integrationStatusBar')?.classList.toggle('hidden', tab !== 'overview');
4497
+ document.querySelector('.page-hero')?.classList.toggle('hidden', tab !== 'overview');
4498
+ document.getElementById('publicDiscoveryHint')?.classList.toggle('hidden', tab !== 'overview');
2916
4499
  if (tab === 'profile' && !profileDirty && !profileSaving) {
2917
4500
  refreshProfile().catch(() => {});
2918
4501
  }
2919
4502
  }
2920
4503
 
2921
4504
  async function refreshOverview() {
2922
- const [overviewRes, discoveredRes, peerRes] = await Promise.allSettled([
4505
+ const [overviewRes, discoveredRes, peerRes, profileRes, bridgeRes, networkCfgRes, networkStatsRes] = await Promise.allSettled([
2923
4506
  api('/api/overview'),
2924
4507
  api('/api/search?q='),
2925
4508
  api('/api/peers'),
4509
+ api('/api/profile'),
4510
+ api('/api/openclaw/bridge'),
4511
+ api('/api/network/config'),
4512
+ api('/api/network/stats'),
2926
4513
  ]);
2927
4514
  if (overviewRes.status !== 'fulfilled') {
2928
4515
  throw overviewRes.reason;
@@ -2930,6 +4517,10 @@
2930
4517
  const o = overviewRes.value.data;
2931
4518
  const allProfiles = discoveredRes.status === 'fulfilled' ? (discoveredRes.value.data || []) : [];
2932
4519
  const peers = peerRes.status === 'fulfilled' ? (peerRes.value.data || {}) : {};
4520
+ const currentProfile = profileRes.status === 'fulfilled' ? (profileRes.value.data || {}) : {};
4521
+ const bridge = bridgeRes.status === 'fulfilled' ? (bridgeRes.value.data || {}) : {};
4522
+ const networkCfg = networkCfgRes.status === 'fulfilled' ? (networkCfgRes.value.data || {}) : {};
4523
+ const networkStats = networkStatsRes.status === 'fulfilled' ? (networkStatsRes.value.data || {}) : {};
2933
4524
  const peerItems = peers.items || [];
2934
4525
  const mergedById = new Map();
2935
4526
 
@@ -2958,6 +4549,7 @@
2958
4549
 
2959
4550
  const all = Array.from(mergedById.values());
2960
4551
  const d = onlyShowOnline ? all.filter((agent) => agent.online) : all;
4552
+ visibleRemotePublicCount = all.filter((agent) => !agent.is_self && agent.online).length;
2961
4553
  const totalAgentPages = Math.max(1, Math.ceil(d.length / AGENTS_PAGE_SIZE));
2962
4554
  agentsPage = Math.min(Math.max(1, agentsPage), totalAgentPages);
2963
4555
  const pagedAgents = d.slice((agentsPage - 1) * AGENTS_PAGE_SIZE, agentsPage * AGENTS_PAGE_SIZE);
@@ -3005,13 +4597,82 @@
3005
4597
  `;
3006
4598
  document.getElementById('snapshot').innerHTML = snapshotHtml;
3007
4599
  const heroModeText = o.social?.network_mode || '-';
4600
+ overviewMode = heroModeText;
3008
4601
  document.getElementById('heroMode').textContent = heroModeText;
4602
+ document.getElementById('overviewModeHint').textContent = t('overview.modeCurrentSource', {
4603
+ mode: describeCurrentMode(heroModeText),
4604
+ hint: t('overview.modeCacheHint'),
4605
+ });
3009
4606
 
3010
4607
  const pillBroadcastText = o.broadcast_enabled ? t('overview.pillRunning') : t('overview.pillPaused');
3011
4608
  const pillBroadcastClassName = `pill ${o.broadcast_enabled ? 'ok' : 'warn'}`;
3012
4609
  document.getElementById('pillBroadcast').textContent = pillBroadcastText;
3013
4610
  document.getElementById('pillBroadcast').className = pillBroadcastClassName;
3014
4611
 
4612
+ const openclawRunning = !!bridge.openclaw_runtime?.running;
4613
+ const openclawDetected = !!bridge.openclaw_installation?.detected;
4614
+ const skillInstalled = !!bridge.skill_learning?.installed;
4615
+ const globalMode = heroModeText === 'global-preview';
4616
+ const networkDiag = networkStats.adapter_diagnostics_summary || {};
4617
+ const lastNetworkError = String(networkDiag.last_error || o.last_broadcast_error || '').trim();
4618
+ const broadcastHealthy = o.broadcast_enabled && !lastNetworkError;
4619
+ const roleKey = openclawRunning
4620
+ ? 'overview.homeRoleListener'
4621
+ : openclawDetected
4622
+ ? 'overview.homeRoleStandby'
4623
+ : 'overview.homeRoleBroadcaster';
4624
+ const titleKey = openclawRunning
4625
+ ? 'overview.homeTitleListener'
4626
+ : openclawDetected
4627
+ ? 'overview.homeTitleOffline'
4628
+ : 'overview.homeTitleBroadcaster';
4629
+ const bodyKey = openclawRunning
4630
+ ? 'overview.homeBodyListener'
4631
+ : openclawDetected
4632
+ ? 'overview.homeBodyOffline'
4633
+ : 'overview.homeBodyBroadcaster';
4634
+
4635
+ document.getElementById('homeMissionTitle').textContent = t(titleKey);
4636
+ document.getElementById('homeMissionBody').textContent = t(bodyKey);
4637
+ document.getElementById('homeMissionStatus').innerHTML = [
4638
+ `<span class="mission-status-pill"><strong>${t('overview.homeRole')}</strong> ${t(roleKey)}</span>`,
4639
+ `<span class="mission-status-pill"><strong>${t('overview.homeOpenClaw')}</strong> ${openclawRunning ? t('overview.homeRunning') : (openclawDetected ? t('overview.homeInstalledOnly') : t('overview.homeStopped'))}</span>`,
4640
+ `<span class="mission-status-pill"><strong>${t('overview.homeGlobalMode')}</strong> ${globalMode ? t('overview.homeGlobalReady') : t('overview.homeNotGlobal')}</span>`,
4641
+ ].join('');
4642
+ document.getElementById('homePriorityGrid').innerHTML = [
4643
+ [t('overview.homeOpenClaw'), openclawRunning ? t('overview.homeRunning') : (openclawDetected ? t('overview.homeInstalledOnly') : t('overview.homeStopped')), openclawRunning ? t('overview.homeMetaRunning') : t('overview.homeMetaNotRunning')],
4644
+ [t('overview.homeGlobalMode'), globalMode ? t('overview.homeGlobalReady') : t('overview.homeNotGlobal'), globalMode ? t('overview.homeMetaGlobal') : t('overview.homeMetaNotGlobal')],
4645
+ [t('overview.homeBroadcastHealth'), broadcastHealthy ? t('overview.homeHealthy') : t('overview.homeDegraded'), lastNetworkError || `Last broadcast ${ago(o.last_broadcast_at)}`],
4646
+ [t('overview.homePeers'), String(visibleRemotePublicCount), t('overview.homeMetaPeers', { online: String(onlineCount), discovered: String(discoveredCount) })],
4647
+ ].map(([label, value, meta]) => `
4648
+ <div class="priority-card">
4649
+ <div class="priority-card__label">${label}</div>
4650
+ <div class="priority-card__value">${escapeHtml(value)}</div>
4651
+ <div class="priority-card__meta">${escapeHtml(meta)}</div>
4652
+ </div>
4653
+ `).join('');
4654
+ document.getElementById('homeBriefList').innerHTML = [
4655
+ [t('overview.homeBriefNetwork'), t('overview.homeBriefNetworkValue', {
4656
+ mode: describeCurrentMode(heroModeText),
4657
+ relay: String(networkDiag.signaling_url || networkCfg.adapter_extra?.signaling_url || '-'),
4658
+ room: String(networkDiag.room || networkCfg.adapter_extra?.room || '-'),
4659
+ })],
4660
+ [t('overview.homeBriefBridge'), t('overview.homeBriefBridgeValue', {
4661
+ runtime: openclawRunning ? t('overview.homeRunning') : (openclawDetected ? t('overview.homeInstalledOnly') : t('overview.homeStopped')),
4662
+ skill: skillInstalled ? t('common.yes') : t('common.no'),
4663
+ })],
4664
+ [t('overview.homeBriefNextAction'), !broadcastHealthy
4665
+ ? t('overview.homeBriefActionStabilize')
4666
+ : openclawRunning
4667
+ ? t('overview.homeBriefActionBroadcast')
4668
+ : t('overview.homeBriefActionLearn')],
4669
+ ].map(([label, value]) => `
4670
+ <div class="home-brief__item">
4671
+ <div class="home-brief__label">${label}</div>
4672
+ <div class="home-brief__value">${escapeHtml(value)}</div>
4673
+ </div>
4674
+ `).join('');
4675
+
3015
4676
  const init = o.init_state || {};
3016
4677
  const onboarding = o.onboarding || {};
3017
4678
  const notice = document.getElementById('initNotice');
@@ -3031,6 +4692,7 @@
3031
4692
  } else {
3032
4693
  discoveryHint.style.display = 'none';
3033
4694
  }
4695
+ renderOverviewGuide(o, currentProfile);
3034
4696
 
3035
4697
  if (!d.length) {
3036
4698
  const agentsCountHintText = t('overview.agentsZero');
@@ -3127,8 +4789,10 @@
3127
4789
  field(f, 'tags').value = (p.tags || []).join(', ');
3128
4790
  field(f, 'avatar_url').value = p.avatar_url || '';
3129
4791
  field(f, 'public_enabled').checked = !!p.public_enabled;
4792
+ f.dataset.lastSavedPublicEnabled = String(!!p.public_enabled);
3130
4793
  renderProfilePreview(f);
3131
4794
  setProfileBaseline(f);
4795
+ setProfileNextStepVisible(false);
3132
4796
  await refreshPublicProfilePreview();
3133
4797
  }
3134
4798
 
@@ -3147,6 +4811,140 @@
3147
4811
  document.getElementById('publicVisibilityList').textContent = rows.length ? rows.join('\n') : '-';
3148
4812
  }
3149
4813
 
4814
+ function renderSocialMessages() {
4815
+ const listEl = document.getElementById('socialMessageList');
4816
+ const metaEl = document.getElementById('socialMessageMeta');
4817
+ const hintEl = document.getElementById('socialMessageHint');
4818
+ const governanceHint = socialMessageGovernance
4819
+ ? `${t('overview.messageHint')} ${t('overview.governanceSummary', {
4820
+ max: String(socialMessageGovernance.send_limit?.max || '-'),
4821
+ seconds: String(Math.floor((socialMessageGovernance.send_limit?.window_ms || 60000) / 1000)),
4822
+ })}`
4823
+ : t('overview.messageHint');
4824
+ hintEl.textContent = governanceHint;
4825
+ if (!socialMessagesCache.length) {
4826
+ metaEl.textContent = t('overview.noMessagesMeta');
4827
+ listEl.innerHTML = `<div class="empty-state">${t('overview.noMessagesEmpty')}</div>`;
4828
+ return;
4829
+ }
4830
+
4831
+ const filteredMessages = socialMessagesCache.filter((item) => {
4832
+ if (socialMessageFilter === 'self') return Boolean(item.is_self);
4833
+ if (socialMessageFilter === 'remote') return !item.is_self;
4834
+ return true;
4835
+ });
4836
+
4837
+ const baseMeta = socialMessageFilter === 'all'
4838
+ ? t('overview.cachedMessages', { count: String(socialMessagesCache.length) })
4839
+ : t('overview.filteredMessages', { count: String(filteredMessages.length) });
4840
+ const governanceMeta = socialMessageGovernance
4841
+ ? ` · ${t('overview.governanceSummary', {
4842
+ max: String(socialMessageGovernance.send_limit?.max || '-'),
4843
+ seconds: String(Math.floor((socialMessageGovernance.send_limit?.window_ms || 60000) / 1000)),
4844
+ })}`
4845
+ : '';
4846
+ metaEl.textContent = `${baseMeta}${governanceMeta}`;
4847
+
4848
+ if (!filteredMessages.length) {
4849
+ listEl.innerHTML = `<div class="empty-state">${t('overview.noMessagesEmpty')}</div>`;
4850
+ return;
4851
+ }
4852
+
4853
+ listEl.innerHTML = filteredMessages
4854
+ .map((item) => {
4855
+ const selfStatusChips = item.is_self
4856
+ ? `
4857
+ <span class="tag-chip" style="margin-left:8px;">${t('overview.selfMessagePublished')}</span>
4858
+ <span class="tag-chip" style="margin-left:8px;">${t('overview.selfMessageConfirmed')}</span>
4859
+ <span class="tag-chip" style="margin-left:8px;">${
4860
+ item.remote_observation_count > 0
4861
+ ? t('overview.selfMessageRemoteObserved', { count: String(item.remote_observation_count) })
4862
+ : t('overview.selfMessageAwaitingObservation')
4863
+ }</span>
4864
+ <span class="tag-chip" style="margin-left:8px;">${t('overview.selfMessageRemoteVisible', { count: String(visibleRemotePublicCount) })}</span>
4865
+ `
4866
+ : '';
4867
+ const observationChip = item.remote_observation_count > 0
4868
+ ? `<span class="tag-chip" style="margin-left:8px;">${t('overview.messageObservedBy', { count: String(item.remote_observation_count) })}</span>`
4869
+ : '';
4870
+ return `
4871
+ <div class="log-item">
4872
+ <div style="display:flex; align-items:center; justify-content:space-between; gap:12px;">
4873
+ <div>
4874
+ <strong>${escapeHtml(item.display_name || t('overview.unnamed'))}</strong>
4875
+ <span class="mono" style="color:#90a2c3; margin-left:8px;">${escapeHtml(shortId(item.agent_id || ''))}</span>
4876
+ <span class="tag-chip" style="margin-left:8px;">${escapeHtml(item.topic || t('labels.globalTopic'))}</span>
4877
+ ${item.is_self ? `<span class="tag-chip" style="margin-left:8px;">${t('overview.messageFilterSelf')}</span>` : ''}
4878
+ <span class="tag-chip" style="margin-left:8px;">${item.online ? t('overview.online') : t('overview.offline')}</span>
4879
+ ${observationChip}
4880
+ ${selfStatusChips}
4881
+ </div>
4882
+ <div class="mono" style="color:#90a2c3;">${new Date(item.created_at).toLocaleString()}</div>
4883
+ </div>
4884
+ <div style="margin-top:8px; line-height:1.6;">${formatMessageBody(item.body || '')}</div>
4885
+ </div>
4886
+ `;
4887
+ })
4888
+ .join('');
4889
+ }
4890
+
4891
+ function renderOverviewGuide(overview, profile) {
4892
+ const hasDisplayName = Boolean(String(profile?.display_name || overview?.display_name || '').trim());
4893
+ const hasBio = Boolean(String(profile?.bio || '').trim());
4894
+ const hasTags = Array.isArray(profile?.tags) && profile.tags.length > 0;
4895
+ const profileComplete = hasDisplayName || hasBio || hasTags;
4896
+ const publicEnabled = Boolean(profile?.public_enabled ?? overview?.public_enabled);
4897
+ const announcedRecently = Boolean(overview?.last_broadcast_at);
4898
+
4899
+ const guideStatusEl = document.getElementById('overviewGuideStatus');
4900
+ const profileStepEl = document.getElementById('overviewStepProfile');
4901
+ const publicStepEl = document.getElementById('overviewStepPublic');
4902
+ const broadcastStepEl = document.getElementById('overviewStepBroadcast');
4903
+
4904
+ profileStepEl.classList.toggle('is-done', profileComplete);
4905
+ publicStepEl.classList.toggle('is-done', publicEnabled);
4906
+ broadcastStepEl.classList.toggle('is-done', announcedRecently);
4907
+
4908
+ document.getElementById('overviewStepProfileStatus').textContent = profileComplete
4909
+ ? t('overview.stepDone')
4910
+ : t('overview.stepIncomplete');
4911
+ document.getElementById('overviewStepProfileBody').textContent = profileComplete
4912
+ ? t('overview.stepProfileDone')
4913
+ : t('overview.stepProfileBody');
4914
+
4915
+ document.getElementById('overviewStepPublicStatus').textContent = publicEnabled
4916
+ ? t('overview.stepDone')
4917
+ : t('overview.stepIncomplete');
4918
+ document.getElementById('overviewStepPublicBody').textContent = publicEnabled
4919
+ ? t('overview.stepPublicDone')
4920
+ : t('overview.stepPublicBody');
4921
+
4922
+ document.getElementById('overviewStepBroadcastStatus').textContent = announcedRecently
4923
+ ? t('overview.stepDone')
4924
+ : t('overview.stepWaiting');
4925
+ document.getElementById('overviewStepBroadcastBody').textContent = announcedRecently
4926
+ ? t('overview.stepBroadcastDone')
4927
+ : t('overview.stepBroadcastBody');
4928
+
4929
+ if (publicEnabled && announcedRecently) {
4930
+ guideStatusEl.textContent = t('overview.guideLive');
4931
+ guideStatusEl.className = 'pill ok';
4932
+ } else if (profileComplete && publicEnabled) {
4933
+ guideStatusEl.textContent = t('overview.guideReadyToAnnounce');
4934
+ guideStatusEl.className = 'pill warn';
4935
+ } else {
4936
+ guideStatusEl.textContent = t('overview.guideNeedSetup');
4937
+ guideStatusEl.className = 'pill warn';
4938
+ }
4939
+ }
4940
+
4941
+ async function refreshMessages() {
4942
+ const result = await api('/api/messages?limit=50');
4943
+ socialMessagesCache = Array.isArray(result.data?.items) ? result.data.items : [];
4944
+ socialMessageGovernance = result.data?.governance || null;
4945
+ renderSocialMessages();
4946
+ }
4947
+
3150
4948
  async function refreshNetwork() {
3151
4949
  const [cfg, sts, rtp] = await Promise.all([api('/api/network/config'), api('/api/network/stats'), api('/api/runtime/paths')]);
3152
4950
  const c = cfg.data;
@@ -3163,12 +4961,12 @@
3163
4961
  document.getElementById('heroRelay').textContent = dx.signaling_url || '-';
3164
4962
  document.getElementById('heroRoom').textContent = dx.room || '-';
3165
4963
 
3166
- document.getElementById('pillAdapter').textContent = `adapter: ${c.adapter}`;
4964
+ document.getElementById('pillAdapter').textContent = `${t('labels.adapter')}: ${c.adapter || '-'}`;
3167
4965
  writeUiCache('silicaclaw_ui_network', {
3168
4966
  heroAdapterText: c.adapter || '-',
3169
4967
  heroRelayText: dx.signaling_url || '-',
3170
4968
  heroRoomText: dx.room || '-',
3171
- pillAdapterText: `adapter: ${c.adapter}`,
4969
+ pillAdapterText: `${t('labels.adapter')}: ${c.adapter || '-'}`,
3172
4970
  });
3173
4971
  document.getElementById('networkCards').innerHTML = [
3174
4972
  [t('labels.adapter'), c.adapter],
@@ -3192,6 +4990,7 @@
3192
4990
  [t('network.lastOutbound'), ago(msg.last_broadcast_at)],
3193
4991
  ].map(([k,v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join('');
3194
4992
  document.getElementById('networkSummaryList').innerHTML = [
4993
+ [t('labels.mode'), describeCurrentMode(c.mode || 'lan')],
3195
4994
  [t('network.relayHealth'), dx.last_error ? t('network.degraded') : t('network.connected')],
3196
4995
  [t('network.currentRelay'), dx.signaling_url || '-'],
3197
4996
  [t('network.currentRoom'), dx.room || '-'],
@@ -3293,7 +5092,7 @@
3293
5092
  ${peers.items.map((peer) => `
3294
5093
  <tr>
3295
5094
  <td class="mono">${shortId(peer.peer_id)}</td>
3296
- <td class="${peer.status === 'online' ? 'online' : 'stale'}">${peer.status}</td>
5095
+ <td class="${peer.status === 'online' ? 'online' : peer.status === 'offline' ? 'offline' : 'stale'}">${peerStatusText(peer.status)}</td>
3297
5096
  <td>${ago(peer.last_seen_at)}</td>
3298
5097
  <td>${peer.stale_since_at ? ago(peer.stale_since_at) : '-'}</td>
3299
5098
  <td>${peer.messages_seen || 0}</td>
@@ -3345,22 +5144,27 @@
3345
5144
  }
3346
5145
 
3347
5146
  async function refreshSocial() {
3348
- const [socialRes, summaryRes, statusRes, networkCfgRes] = await Promise.all([
5147
+ const [socialRes, summaryRes, statusRes, networkCfgRes, governanceRes] = await Promise.all([
3349
5148
  api('/api/social/config'),
3350
5149
  api('/api/social/integration-summary'),
3351
5150
  api('/api/integration/status'),
3352
5151
  api('/api/network/config'),
5152
+ api('/api/social/message-governance'),
3353
5153
  ]);
5154
+ const bridgeRes = await api('/api/openclaw/bridge');
3354
5155
  const social = socialRes.data || {};
3355
5156
  const summary = summaryRes.data || {};
3356
5157
  const status = statusRes.data || {};
3357
5158
  const networkCfg = networkCfgRes.data || {};
5159
+ const bridge = bridgeRes.data || {};
5160
+ const governance = governanceRes.data || {};
3358
5161
  const runtime = social.runtime || {};
3359
5162
  const config = social.social_config || {};
3360
5163
  const network = config.network || {};
3361
5164
  const runtimeNetwork = runtime.resolved_network || {};
3362
5165
  const effectiveAdapterExtra = networkCfg.adapter_extra || {};
3363
5166
  const effectiveMode = networkCfg.mode || status.network_mode || summary.current_network_mode || runtimeNetwork.mode || network.mode || '-';
5167
+ const selectedMode = network.mode || runtimeNetwork.mode || status.network_mode || effectiveMode || '-';
3364
5168
  const effectiveAdapter = networkCfg.adapter || runtimeNetwork.adapter || summary.current_adapter || '-';
3365
5169
  const effectiveNamespace = networkCfg.namespace || runtimeNetwork.namespace || summary.current_namespace || '-';
3366
5170
  const effectiveRoom = effectiveAdapterExtra.room || runtimeNetwork.room || network.room || '-';
@@ -3381,7 +5185,7 @@
3381
5185
  document.getElementById('socialStatusLine').textContent = summaryLine;
3382
5186
  document.getElementById('socialStatusSubline').textContent = namespaceText;
3383
5187
  const bar = document.getElementById('integrationStatusBar');
3384
- bar.className = `integration-strip ${status.connected_to_silicaclaw && status.public_enabled ? 'ok' : 'warn'}`;
5188
+ bar.className = `integration-strip ${status.connected_to_silicaclaw && status.public_enabled ? 'ok' : 'warn'}${activeTab === 'overview' ? '' : ' hidden'}`;
3385
5189
  bar.textContent = t('social.barStatus', {
3386
5190
  connected: status.connected_to_silicaclaw ? t('common.yes') : t('common.no'),
3387
5191
  mode,
@@ -3401,9 +5205,12 @@
3401
5205
  if (!status.discoverable && status.discoverable_reason) reasons.push(t('social.discoverableReasonFull', { reason: status.discoverable_reason }));
3402
5206
  document.getElementById('socialStateHint').textContent = reasons.length ? reasons.join(' · ') : t('hints.allIntegrationChecksPassed');
3403
5207
  const modeSelect = document.getElementById('socialModeSelect');
3404
- if (modeSelect && mode !== '-') {
3405
- modeSelect.value = mode;
5208
+ const displayedSelectedMode = socialModeDirty && socialModePending ? socialModePending : selectedMode;
5209
+ if (modeSelect && displayedSelectedMode !== '-') {
5210
+ modeSelect.value = displayedSelectedMode;
3406
5211
  }
5212
+ renderSocialModeHint(displayedSelectedMode, mode, !!social.network_requires_restart, socialModeDirty);
5213
+ setSocialModePendingState(socialModeDirty);
3407
5214
 
3408
5215
  document.getElementById('socialPrimaryCards').innerHTML = [
3409
5216
  [t('social.configured'), status.configured ? t('common.yes') : t('common.no')],
@@ -3411,42 +5218,154 @@
3411
5218
  [t('social.discoverable'), discoverable ? t('common.yes') : t('common.no')],
3412
5219
  [t('social.publicDiscovery'), status.public_enabled ? t('common.on') : t('common.off')],
3413
5220
  [t('social.networkMode'), mode],
3414
- [t('social.connected'), status.connected_to_silicaclaw ? t('common.yes') : t('common.no')],
5221
+ [t('labels.adapter'), effectiveAdapter],
3415
5222
  [t('social.discoverableReason'), status.discoverable_reason || '-'],
3416
5223
  ].map(([k,v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join('');
3417
5224
 
3418
5225
  document.getElementById('socialIntegrationCards').innerHTML = [
5226
+ [t('social.connected'), bridge.connected_to_silicaclaw ? t('common.yes') : t('common.no')],
5227
+ [t('social.messageBroadcast'), bridge.message_broadcast_enabled ? t('common.on') : t('common.off')],
3419
5228
  [t('social.displayName'), status.display_name || t('overview.unnamed')],
3420
5229
  [t('social.agentId'), shortId(status.agent_id || '')],
3421
5230
  [t('social.socialFound'), summary.social_md_found ? t('common.yes') : t('common.no')],
3422
5231
  [t('social.socialSource'), summary.social_md_source_path || '-'],
3423
- [t('social.runtimeGenerated'), summary.runtime_generated ? t('common.yes') : t('common.no')],
3424
5232
  [t('social.reuseOpenClawIdentity'), summary.reused_openclaw_identity ? t('common.yes') : t('common.no')],
3425
- [t('social.mode'), mode],
3426
- [t('social.broadcastStatus'), summary.current_broadcast_status || '-'],
3427
5233
  ].map(([k,v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join('');
3428
5234
 
5235
+ const skillLearning = bridge.skill_learning || {};
5236
+ const ownerDelivery = bridge.owner_delivery || {};
5237
+ const installAction = skillLearning.install_action || {};
5238
+ const openclawDetected = !!bridge.openclaw_installation?.detected;
5239
+ const openclawRunning = !!bridge.openclaw_runtime?.running;
5240
+ const skillInstalled = !!skillLearning.installed;
5241
+ const installedSkillPath = skillLearning.installed_skill_path || '-';
5242
+ const ownerDeliveryStatusEl = document.getElementById('socialOwnerDeliveryStatus');
5243
+ const ownerDeliverySublineEl = document.getElementById('socialOwnerDeliverySubline');
5244
+ const ownerDeliveryReasonEl = document.getElementById('socialOwnerDeliveryReason');
5245
+ let ownerDeliveryHeadline = t('feedback.openclawRoleBroadcasterOnly');
5246
+ let ownerDeliveryBody = ownerDelivery.reason || '-';
5247
+ let ownerDeliveryTone = 'warn';
5248
+ if (ownerDelivery.ready) {
5249
+ ownerDeliveryHeadline = t('feedback.openclawRoleOwnerReady');
5250
+ ownerDeliveryBody = t('hints.ownerDeliveryReadyBody');
5251
+ ownerDeliveryTone = 'info';
5252
+ } else if (ownerDelivery.bridge_messages_readable) {
5253
+ if (ownerDelivery.forward_command_configured) {
5254
+ ownerDeliveryHeadline = t('feedback.openclawRoleNeedsOwnerRoute');
5255
+ ownerDeliveryBody = t('hints.ownerDeliveryNeedsRouteBody');
5256
+ } else {
5257
+ ownerDeliveryHeadline = t('feedback.openclawRoleLearningOnly');
5258
+ ownerDeliveryBody = t('hints.ownerDeliveryLearningBody');
5259
+ }
5260
+ ownerDeliveryTone = 'warn';
5261
+ } else if (!openclawRunning) {
5262
+ ownerDeliveryHeadline = t('feedback.openclawRoleNotRunning');
5263
+ ownerDeliveryBody = ownerDelivery.reason || '-';
5264
+ ownerDeliveryTone = 'warn';
5265
+ }
5266
+ ownerDeliveryStatusEl.className = `feedback ${ownerDeliveryTone}`;
5267
+ ownerDeliveryStatusEl.textContent = ownerDeliveryHeadline;
5268
+ ownerDeliverySublineEl.textContent = [
5269
+ `${t('social.broadcastReadable')}: ${ownerDelivery.bridge_messages_readable ? t('common.yes') : t('common.no')}`,
5270
+ `${t('social.ownerForwardCommand')}: ${ownerDelivery.forward_command_configured ? t('common.yes') : t('common.no')}`,
5271
+ `${t('social.ownerForwardReady')}: ${ownerDelivery.ready ? t('common.yes') : t('common.no')}`,
5272
+ ].join(' · ');
5273
+ ownerDeliveryReasonEl.textContent = ownerDeliveryBody;
5274
+ document.getElementById('openclawSkillCards').innerHTML = [
5275
+ [t('social.openclawInstalled'), openclawDetected ? t('common.yes') : t('common.no')],
5276
+ [t('social.running'), openclawRunning ? t('common.yes') : t('common.no')],
5277
+ [t('social.skillInstalled'), skillInstalled ? t('common.yes') : t('common.no')],
5278
+ [t('social.broadcastReadable'), ownerDelivery.bridge_messages_readable ? t('common.yes') : t('common.no')],
5279
+ [t('social.ownerForwardReady'), ownerDelivery.ready ? t('common.yes') : t('common.no')],
5280
+ [t('social.ownerForwardCommand'), ownerDelivery.forward_command_configured ? t('common.yes') : t('common.no')],
5281
+ [t('social.installMode'), skillLearning.install_mode || '-'],
5282
+ [t('social.installedPath'), skillInstalled ? installedSkillPath : '-'],
5283
+ ].map(([k,v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${escapeHtml(v)}</div></div>`).join('');
5284
+ document.getElementById('openclawSkillPath').textContent = ownerDelivery.forward_command
5285
+ ? `${ownerDelivery.forward_command}${ownerDelivery.owner_channel ? ` · ${ownerDelivery.owner_channel}` : ''}${ownerDelivery.owner_target ? ` · ${ownerDelivery.owner_target}` : ''}`
5286
+ : skillInstalled
5287
+ ? installedSkillPath
5288
+ : (installAction.recommended_command || '-');
5289
+ document.getElementById('openclawSkillHint').textContent = !openclawDetected
5290
+ ? t('feedback.openclawRoleBroadcasterOnly')
5291
+ : !openclawRunning
5292
+ ? t('feedback.openclawRoleNotRunning')
5293
+ : !skillInstalled
5294
+ ? t('feedback.openclawRoleReadyToLearn')
5295
+ : ownerDelivery.ready
5296
+ ? t('feedback.openclawRoleOwnerReady')
5297
+ : ownerDelivery.bridge_messages_readable && !ownerDelivery.forward_command_configured
5298
+ ? t('feedback.openclawRoleLearningOnly')
5299
+ : ownerDelivery.bridge_messages_readable
5300
+ ? t('feedback.openclawRoleNeedsOwnerRoute')
5301
+ : t('feedback.openclawRoleLearned');
5302
+ const skillInstallBtn = document.getElementById('openclawSkillInstallBtn');
5303
+ skillInstallBtn.textContent = !openclawDetected
5304
+ ? t('actions.openclawNotInstalled')
5305
+ : !openclawRunning
5306
+ ? t('actions.openclawNotRunning')
5307
+ : skillInstalled
5308
+ ? t('actions.openclawSkillLearned')
5309
+ : t('actions.learnOpenClawSkill');
5310
+ skillInstallBtn.disabled = !openclawDetected || !openclawRunning || skillInstalled;
5311
+
5312
+ const policy = governance.policy || {};
5313
+ const blockedAgentIds = Array.isArray(policy.blocked_agent_ids) ? policy.blocked_agent_ids : [];
5314
+ const blockedTerms = Array.isArray(policy.blocked_terms) ? policy.blocked_terms : [];
5315
+ document.getElementById('governanceSendLimitInput').value = String(policy.send_limit?.max ?? 5);
5316
+ document.getElementById('governanceSendWindowInput').value = String(Math.floor((policy.send_limit?.window_ms ?? 60000) / 1000));
5317
+ document.getElementById('governanceReceiveLimitInput').value = String(policy.receive_limit?.max ?? 8);
5318
+ document.getElementById('governanceReceiveWindowInput').value = String(Math.floor((policy.receive_limit?.window_ms ?? 60000) / 1000));
5319
+ document.getElementById('governanceDuplicateWindowInput').value = String(Math.floor((policy.duplicate_window_ms ?? 180000) / 1000));
5320
+ document.getElementById('governanceBlockedAgentsInput').value = blockedAgentIds.join(', ');
5321
+ document.getElementById('governanceBlockedTermsInput').value = blockedTerms.join(', ');
5322
+ document.getElementById('socialGovernanceCards').innerHTML = [
5323
+ [t('labels.sendLimit'), `${policy.send_limit?.max ?? '-'} / ${Math.floor((policy.send_limit?.window_ms ?? 60000) / 1000)}s`],
5324
+ [t('labels.receiveLimit'), `${policy.receive_limit?.max ?? '-'} / ${Math.floor((policy.receive_limit?.window_ms ?? 60000) / 1000)}s`],
5325
+ [t('labels.duplicateWindowSeconds'), `${Math.floor((policy.duplicate_window_ms ?? 0) / 1000)}s`],
5326
+ [t('labels.blockedAgentIds'), blockedAgentIds.length],
5327
+ [t('labels.blockedTerms'), blockedTerms.length],
5328
+ ].map(([k,v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join('');
5329
+
5330
+ const moderationEvents = Array.isArray(governance.recent_events) ? governance.recent_events : [];
5331
+ document.getElementById('socialModerationList').innerHTML = moderationEvents.length === 0
5332
+ ? `<div class="empty-state">${t('network.noModerationEvents')}</div>`
5333
+ : moderationEvents.map((event) => `
5334
+ <div class="log-item">
5335
+ <div class="log-${event.level || 'warn'}">[${String(event.level || 'warn').toUpperCase()}] ${escapeHtml(event.message || '-')}</div>
5336
+ <div class="mono" style="color:#90a2c3;">${new Date(event.timestamp).toLocaleString()}</div>
5337
+ </div>
5338
+ `).join('');
5339
+
3429
5340
  document.getElementById('socialAdvancedCards').innerHTML = [
3430
5341
  [t('labels.adapter'), effectiveAdapter],
3431
5342
  [t('social.namespace'), effectiveNamespace],
3432
5343
  [t('labels.room'), effectiveRoom],
3433
- [t('network.signalingEndpoints'), effectiveSignalingEndpoints.length || 0],
3434
- [t('network.bootstrapSources'), effectiveBootstrapSources.length || 0],
3435
- [t('network.seedPeers'), effectiveSeedPeersCount],
3436
- [t('social.bootstrapHints'), (runtimeNetwork.bootstrap_hints || []).length || 0],
5344
+ [t('social.bridgeStatus'), bridge.connected_to_silicaclaw ? t('common.yes') : t('common.no')],
5345
+ [t('social.messageBroadcast'), bridge.message_broadcast_enabled ? t('common.on') : t('common.off')],
3437
5346
  [t('social.restartRequired'), social.network_requires_restart ? t('common.yes') : t('common.no')],
3438
5347
  ].map(([k,v]) => `<div class="card"><div class="label">${k}</div><div class="value" style="font-size:17px;">${v}</div></div>`).join('');
3439
5348
  document.getElementById('socialAdvancedWrap').textContent = toPrettyJson({
3440
- runtime_network: runtimeNetwork,
3441
- effective_network: {
5349
+ effective_runtime: {
3442
5350
  mode: effectiveMode,
3443
5351
  adapter: effectiveAdapter,
3444
5352
  namespace: effectiveNamespace,
3445
5353
  relay: effectiveRelay,
3446
5354
  room: effectiveRoom,
3447
- signaling_endpoints: effectiveSignalingEndpoints,
3448
- bootstrap_sources: effectiveBootstrapSources,
3449
- seed_peers_count: effectiveSeedPeersCount,
5355
+ restart_required: social.network_requires_restart,
5356
+ },
5357
+ openclaw_bridge: {
5358
+ enabled: bridge.enabled,
5359
+ connected_to_silicaclaw: bridge.connected_to_silicaclaw,
5360
+ public_enabled: bridge.public_enabled,
5361
+ message_broadcast_enabled: bridge.message_broadcast_enabled,
5362
+ openclaw_runtime: bridge.openclaw_runtime || {},
5363
+ skill_learning: bridge.skill_learning || {},
5364
+ endpoints: bridge.endpoints || {},
5365
+ },
5366
+ source: {
5367
+ social_md_found: summary.social_md_found,
5368
+ social_md_source_path: summary.social_md_source_path,
3450
5369
  },
3451
5370
  });
3452
5371
 
@@ -3495,7 +5414,7 @@
3495
5414
  }
3496
5415
 
3497
5416
  async function refreshAll() {
3498
- const tasks = [refreshOverview(), refreshNetwork(), refreshSocial(), refreshPublicProfilePreview()];
5417
+ const tasks = [refreshOverview(), refreshNetwork(), refreshSocial(), refreshPublicProfilePreview(), refreshMessages()];
3499
5418
  if (activeTab === 'network') {
3500
5419
  tasks.push(refreshPeers(), refreshDiscovery(), refreshLogs());
3501
5420
  }
@@ -3554,11 +5473,86 @@
3554
5473
  applyTheme(btn.dataset.themeChoice || 'dark');
3555
5474
  });
3556
5475
  });
3557
- document.getElementById('overviewBroadcastNowBtn').addEventListener('click', () => {
5476
+ document.getElementById('overviewStepProfileBtn').addEventListener('click', () => switchTab('profile'));
5477
+ document.getElementById('overviewStepPublicBtn').addEventListener('click', () => switchTab('profile'));
5478
+ document.getElementById('overviewStepBroadcastBtn').addEventListener('click', () => {
5479
+ document.getElementById('broadcastNowBtn').click();
5480
+ });
5481
+ document.getElementById('homeOpenAgentBtn').addEventListener('click', () => switchTab('agent'));
5482
+ document.getElementById('homeOpenSocialBtn').addEventListener('click', () => switchTab('social'));
5483
+ document.getElementById('homeOpenNetworkBtn').addEventListener('click', () => switchTab('network'));
5484
+ document.getElementById('homeBroadcastNowBtn').addEventListener('click', () => {
3558
5485
  document.getElementById('broadcastNowBtn').click();
3559
5486
  });
3560
- document.getElementById('overviewGoProfileBtn').addEventListener('click', () => switchTab('profile'));
3561
- document.getElementById('overviewGoNetworkBtn').addEventListener('click', () => switchTab('network'));
5487
+ document.getElementById('profileNextStepBtn').addEventListener('click', () => {
5488
+ setProfileNextStepVisible(false);
5489
+ switchTab('overview');
5490
+ });
5491
+ document.getElementById('profileNextStepDismissBtn').addEventListener('click', () => {
5492
+ setProfileNextStepVisible(false);
5493
+ });
5494
+ document.getElementById('socialMessageRefreshBtn').addEventListener('click', async () => {
5495
+ try {
5496
+ await refreshMessages();
5497
+ setFeedback('socialMessageFeedback', t('feedback.messageInboxRefreshed'));
5498
+ toast(t('feedback.messageInboxRefreshed'));
5499
+ } catch (e) {
5500
+ setFeedback('socialMessageFeedback', e instanceof Error ? e.message : t('feedback.messageRefreshFailed'), 'error');
5501
+ }
5502
+ });
5503
+ document.getElementById('socialMessageFilterSelect').addEventListener('change', (event) => {
5504
+ socialMessageFilter = String(event.target?.value || 'all');
5505
+ renderSocialMessages();
5506
+ });
5507
+ document.getElementById('socialMessageSendBtn').addEventListener('click', async () => {
5508
+ const input = document.getElementById('socialMessageInput');
5509
+ const topic = String(document.getElementById('socialMessageTopicSelect').value || 'global');
5510
+ const body = String(input.value || '').trim();
5511
+ if (!body) {
5512
+ setFeedback('socialMessageFeedback', t('feedback.messageEmpty'), 'warn');
5513
+ return;
5514
+ }
5515
+
5516
+ const sendBtn = document.getElementById('socialMessageSendBtn');
5517
+ sendBtn.disabled = true;
5518
+ setFeedback('socialMessageFeedback', t('feedback.messageSending'));
5519
+ try {
5520
+ const result = await api('/api/messages/broadcast', {
5521
+ method: 'POST',
5522
+ body: JSON.stringify({ body, topic }),
5523
+ });
5524
+ if (!result.data?.sent) {
5525
+ setFeedback('socialMessageFeedback', messageSendReasonText(String(result.data?.reason || 'failed')), 'warn');
5526
+ return;
5527
+ }
5528
+ const messageId = String(result.data?.message?.message_id || '');
5529
+ input.value = '';
5530
+ await refreshMessages();
5531
+ const visiblePeers = await api('/api/search?q=');
5532
+ const remoteVisibleCount = Array.isArray(visiblePeers.data)
5533
+ ? visiblePeers.data.filter((item) => !item.is_self && item.online).length
5534
+ : 0;
5535
+ const published = socialMessagesCache.find((item) => item.message_id === messageId);
5536
+ const confirmed = Boolean(published);
5537
+ const remoteObservedCount = Number(published?.remote_observation_count || 0);
5538
+ const remoteHint = t('feedback.messageRemoteVisibility', { count: String(remoteVisibleCount) });
5539
+ setFeedback(
5540
+ 'socialMessageFeedback',
5541
+ `${confirmed ? t('feedback.messageInboxConfirmed') : t('feedback.messageInboxPending')} ${
5542
+ remoteObservedCount > 0
5543
+ ? t('feedback.messageRemoteObserved', { count: String(remoteObservedCount) })
5544
+ : remoteHint
5545
+ }`,
5546
+ confirmed ? 'info' : 'warn'
5547
+ );
5548
+ toast(confirmed ? t('feedback.messageInboxConfirmed') : t('feedback.messagePublishedLocal'));
5549
+ await refreshNetwork();
5550
+ } catch (e) {
5551
+ setFeedback('socialMessageFeedback', e instanceof Error ? e.message : t('feedback.messageBroadcastFailed'), 'error');
5552
+ } finally {
5553
+ sendBtn.disabled = false;
5554
+ }
5555
+ });
3562
5556
 
3563
5557
  document.getElementById('profileForm').addEventListener('submit', async (event) => {
3564
5558
  event.preventDefault();
@@ -3570,6 +5564,8 @@
3570
5564
  }
3571
5565
 
3572
5566
  const tags = result.tags;
5567
+ const wasPublicEnabled = String(f.dataset.lastSavedPublicEnabled || 'false') === 'true';
5568
+ const willBePublicEnabled = !!field(f, 'public_enabled').checked;
3573
5569
  setFeedback('profileFeedback', t('feedback.savingProfile'));
3574
5570
  setSaveBusy(true);
3575
5571
  try {
@@ -3583,7 +5579,9 @@
3583
5579
  setFeedback('profileFeedback', r.meta?.message || t('common.saved'));
3584
5580
  toast(t('feedback.profileSaved'));
3585
5581
  field(f, 'tags').value = normalizeTagsInput(field(f, 'tags').value);
5582
+ f.dataset.lastSavedPublicEnabled = String(willBePublicEnabled);
3586
5583
  await refreshAll();
5584
+ setProfileNextStepVisible(!wasPublicEnabled && willBePublicEnabled);
3587
5585
  } catch (e) {
3588
5586
  setFeedback('profileFeedback', e instanceof Error ? e.message : t('feedback.failed'), 'error');
3589
5587
  } finally {
@@ -3619,7 +5617,7 @@
3619
5617
  updateDirtyState(profileFormEl, true);
3620
5618
  });
3621
5619
  window.addEventListener('beforeunload', (event) => {
3622
- if (!profileDirty || profileSaving) return;
5620
+ if ((!profileDirty || profileSaving) && !socialModeDirty) return;
3623
5621
  event.preventDefault();
3624
5622
  event.returnValue = '';
3625
5623
  });
@@ -3631,6 +5629,9 @@
3631
5629
  setFeedback('networkFeedback', r.meta?.message || t('common.done'), level);
3632
5630
  toast(r.meta?.message || t('common.done'));
3633
5631
  await refreshAll();
5632
+ if (path === '/api/broadcast/now') {
5633
+ pulseOverviewBroadcastStep();
5634
+ }
3634
5635
  } catch (e) {
3635
5636
  setFeedback('networkFeedback', e instanceof Error ? e.message : t('feedback.failed'), 'error');
3636
5637
  }
@@ -3663,6 +5664,17 @@
3663
5664
  agentsPage = 1;
3664
5665
  await refreshOverview();
3665
5666
  });
5667
+ document.getElementById('clearDiscoveryCacheBtn').addEventListener('click', async () => {
5668
+ try {
5669
+ await api('/api/cache/clear', { method: 'POST' });
5670
+ setFeedback('networkFeedback', t('feedback.discoveryCacheCleared'));
5671
+ toast(t('feedback.discoveryCacheCleared'));
5672
+ agentsPage = 1;
5673
+ await refreshAll();
5674
+ } catch (e) {
5675
+ setFeedback('networkFeedback', e instanceof Error ? e.message : t('feedback.failed'), 'error');
5676
+ }
5677
+ });
3666
5678
  document.getElementById('refreshLogsBtn').addEventListener('click', async () => {
3667
5679
  await refreshLogs();
3668
5680
  toast(t('feedback.logsRefreshed'));
@@ -3677,6 +5689,52 @@
3677
5689
  setFeedback('socialFeedback', e instanceof Error ? e.message : t('feedback.exportFailed'), 'error');
3678
5690
  }
3679
5691
  });
5692
+ document.getElementById('openclawSkillInstallBtn').addEventListener('click', async () => {
5693
+ const btn = document.getElementById('openclawSkillInstallBtn');
5694
+ btn.disabled = true;
5695
+ setFeedback('openclawSkillFeedback', t('feedback.openclawSkillInstalling'));
5696
+ try {
5697
+ await api('/api/openclaw/bridge/skill-install', { method: 'POST' });
5698
+ setFeedback('openclawSkillFeedback', t('feedback.openclawSkillInstalled'));
5699
+ toast(t('feedback.openclawSkillInstalled'));
5700
+ await refreshSocial();
5701
+ } catch (e) {
5702
+ setFeedback('openclawSkillFeedback', e instanceof Error ? e.message : t('feedback.openclawSkillInstallFailed'), 'error');
5703
+ } finally {
5704
+ await refreshSocial().catch(() => {});
5705
+ }
5706
+ });
5707
+ document.getElementById('saveGovernanceBtn').addEventListener('click', async () => {
5708
+ setFeedback('socialGovernanceFeedback', t('common.saving'));
5709
+ try {
5710
+ await api('/api/social/message-governance', {
5711
+ method: 'PUT',
5712
+ body: JSON.stringify({
5713
+ send_limit_max: Number(document.getElementById('governanceSendLimitInput').value || 5),
5714
+ send_window_ms: Number(document.getElementById('governanceSendWindowInput').value || 60) * 1000,
5715
+ receive_limit_max: Number(document.getElementById('governanceReceiveLimitInput').value || 8),
5716
+ receive_window_ms: Number(document.getElementById('governanceReceiveWindowInput').value || 60) * 1000,
5717
+ duplicate_window_ms: Number(document.getElementById('governanceDuplicateWindowInput').value || 180) * 1000,
5718
+ blocked_agent_ids: parseCsv(document.getElementById('governanceBlockedAgentsInput').value || ''),
5719
+ blocked_terms: parseCsv(document.getElementById('governanceBlockedTermsInput').value || ''),
5720
+ }),
5721
+ });
5722
+ setFeedback('socialGovernanceFeedback', t('hints.governanceSaved'));
5723
+ toast(t('hints.governanceSaved'));
5724
+ await refreshSocial();
5725
+ await refreshMessages();
5726
+ } catch (e) {
5727
+ setFeedback('socialGovernanceFeedback', e instanceof Error ? e.message : t('feedback.failed'), 'error');
5728
+ }
5729
+ });
5730
+ document.getElementById('socialModeSelect').addEventListener('change', (event) => {
5731
+ const mode = String(event.target?.value || '').trim();
5732
+ if (!mode) return;
5733
+ socialModeDirty = true;
5734
+ socialModePending = mode;
5735
+ renderSocialModeHint(mode, mode, false, true);
5736
+ setSocialModePendingState(true);
5737
+ });
3680
5738
  document.getElementById('socialModeApplyBtn').addEventListener('click', async () => {
3681
5739
  const mode = document.getElementById('socialModeSelect').value;
3682
5740
  setFeedback('socialFeedback', t('feedback.runtimeModeApplying', { mode }));
@@ -3685,7 +5743,15 @@
3685
5743
  method: 'POST',
3686
5744
  body: JSON.stringify({ mode }),
3687
5745
  });
3688
- setFeedback('socialFeedback', res.meta?.message || t('feedback.runtimeUpdated'));
5746
+ socialModeDirty = false;
5747
+ socialModePending = '';
5748
+ document.getElementById('socialModeSelect').value = mode;
5749
+ setSocialModePendingState(false);
5750
+ setFeedback('socialFeedback', `${res.meta?.message || t('feedback.runtimeUpdated')} ${t('hints.socialModeHint', {
5751
+ selected: mode,
5752
+ effective: mode,
5753
+ restart: res.data?.network_requires_restart ? t('hints.restartRequiredHint') : t('hints.restartNotRequiredHint'),
5754
+ })}`);
3689
5755
  toast(t('feedback.runtimeMode', { mode }));
3690
5756
  await refreshAll();
3691
5757
  } catch (e) {