@theihtisham/agent-shadow-brain 7.22.0 → 7.22.1

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 (66) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README.md +7 -3
  3. package/dist/brain/auto-update.js +1 -1
  4. package/dist/brain/brain-portability.js +1 -1
  5. package/dist/brain/client-integrations.js +1 -1
  6. package/dist/brain/context-efficiency.d.ts.map +1 -1
  7. package/dist/brain/mcp-presence.js +2 -2
  8. package/dist/brain/mcp-server.js +5 -5
  9. package/dist/brain/native-codex.js +1 -1
  10. package/dist/brain/orchestrator.js +1 -1
  11. package/dist/brain/project-hub-pdf-worker.js +57 -57
  12. package/dist/brain/project-hub-store.js +11 -11
  13. package/dist/cli.js +1 -1
  14. package/dist/dashboard/brain-hub-agent-dock.js +252 -252
  15. package/dist/dashboard/brain-hub-controls.js +61 -61
  16. package/dist/dashboard/brain-hub-exchanges.js +80 -80
  17. package/dist/dashboard/brain-hub-graph.js +336 -336
  18. package/dist/dashboard/brain-hub-html.js +78 -78
  19. package/dist/dashboard/brain-hub-live.js +149 -149
  20. package/dist/dashboard/brain-hub-managed-skills.js +18 -18
  21. package/dist/dashboard/brain-hub-native.js +42 -42
  22. package/dist/dashboard/live-workspace-html.js +1 -1
  23. package/dist/dashboard/project-feedback-html.js +211 -211
  24. package/dist/dashboard/project-kit-html.js +353 -353
  25. package/dist/dashboard/server.js +1 -1
  26. package/dist/dashboard/v6-dashboard-html.js +4261 -4261
  27. package/dist/dashboard/workspace-api.js +1 -1
  28. package/dist/dashboard/workspace-html.js +2534 -2534
  29. package/dist/dashboard/workspace-status.js +1 -1
  30. package/dist/project-cli.js +1 -1
  31. package/docs/BRAND_ASSETS.md +36 -36
  32. package/docs/COMPARISON.md +22 -22
  33. package/docs/COMPONENTS.md +66 -66
  34. package/docs/CONTEXT_LAB.md +79 -79
  35. package/docs/INTEGRATIONS.md +69 -69
  36. package/docs/LEARNING.md +45 -45
  37. package/docs/PROJECT_KIT.md +97 -97
  38. package/docs/SHARING.md +13 -13
  39. package/docs/SHOWCASE.md +87 -87
  40. package/docs/STATS.md +21 -21
  41. package/docs/TROUBLESHOOTING.md +42 -42
  42. package/docs/UPGRADE_PLAN_v7.0.0.md +203 -203
  43. package/docs/WORKFLOW_INTEGRATION.md +125 -125
  44. package/docs/evaluation/CONTEXT_EVALUATION_v7.1.4.json +1818 -1818
  45. package/docs/evaluation/CONTEXT_EVALUATION_v7.1.4.md +36 -36
  46. package/docs/launch/COMPONENT_MAP_v7.1.4.md +122 -122
  47. package/docs/launch/PROJECT_KIT_PLAN_v7.1.4.md +110 -110
  48. package/docs/launch/PROJECT_LEARNING_PLAN_v7.1.4.md +63 -63
  49. package/docs/launch/RELEASE_ACCEPTANCE_v7.22.0.md +48 -48
  50. package/docs/launch/RELEASE_CHECKLIST_v7.0.0.md +24 -24
  51. package/docs/launch/RELEASE_NOTES_v7.0.0.md +44 -44
  52. package/docs/launch/RELEASE_NOTES_v7.1.0.md +32 -32
  53. package/docs/launch/RELEASE_NOTES_v7.1.3.md +40 -40
  54. package/docs/launch/RELEASE_NOTES_v7.1.4.md +30 -30
  55. package/docs/launch/RELEASE_NOTES_v7.2.0.md +24 -24
  56. package/docs/launch/RELEASE_NOTES_v7.22.0.md +53 -53
  57. package/docs/launch/RELEASE_NOTES_v7.22.1.md +11 -0
  58. package/docs/launch/RESEARCH_AND_PLAN_v7.1.4.md +255 -255
  59. package/docs/launch/RESEARCH_AND_PLAN_v7.22.0.md +672 -672
  60. package/package.json +7 -3
  61. package/skills/shadow-debug/SKILL.md +16 -16
  62. package/skills/shadow-implement/SKILL.md +16 -16
  63. package/skills/shadow-release/SKILL.md +16 -16
  64. package/skills/shadow-research/SKILL.md +14 -14
  65. package/skills/shadow-review/SKILL.md +14 -14
  66. package/skills/shadow-workflow/SKILL.md +39 -39
@@ -3,83 +3,83 @@ import { BRAIN_HUB_GRAPH } from './brain-hub-graph.js';
3
3
  import { BRAIN_HUB_EXCHANGES } from './brain-hub-exchanges.js';
4
4
  import { BRAIN_HUB_LIVE } from './brain-hub-live.js';
5
5
  import { BRAIN_HUB_VIEWS } from './brain-hub-views.js';
6
- export const BRAIN_HUB_HTML = String.raw `<!doctype html>
7
- <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="color-scheme" content="dark"><title>Agent Shadow Brain</title>
8
- <style>
9
- :root{color-scheme:dark;--ground:#080e19;--surface:#0e1828;--raised:#142237;--border:#263a50;--strong:#425d78;--ink:#ecf5ff;--muted:#a9bed3;--cyan:#78e9e5;--blue:#afc7ff;--pink:#ecb0fc;--amber:#f9d28b;--green:#a0e7be;--red:#ffacb6;--sans:Inter,"Segoe UI",system-ui,sans-serif;--mono:"IBM Plex Mono","Cascadia Mono",Consolas,monospace;font:14px/1.45 var(--sans)}
10
- *,*::before,*::after{box-sizing:border-box}body{margin:0;background:var(--ground);color:var(--ink)}[hidden]{display:none!important}a{color:var(--cyan)}button,input,select,textarea{font:inherit}button,select{cursor:pointer}button:disabled{cursor:default;opacity:.52}a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,summary:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}h1,h2,h3,p,ul,ol,dl,dd{margin:0}h1,h2,h3{letter-spacing:-.022em;line-height:1.25}h1{font-size:1.95rem}h2{font-size:1.06rem}h3{font-size:.95rem}p,dd,li,pre,td{overflow-wrap:anywhere}small,.small{font-size:.81rem}.muted{color:var(--muted)}.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}.cyan{color:var(--cyan)}.pink{color:var(--pink)}.amber{color:var(--amber)}.green{color:var(--green)}.red{color:var(--red)}.skip{position:fixed;left:12px;top:8px;z-index:4;transform:translateY(-150%)}.skip:focus{transform:none}
11
- .frame{max-width:1700px;margin:auto;padding:0 22px 24px}.top,.page-head,.panel-head,.row,.actions,.nav{display:flex;align-items:center;gap:8px}.top,.page-head,.panel-head,.row{justify-content:space-between}.top{min-height:54px;border-bottom:1px solid var(--border);flex-wrap:wrap;padding-block:7px}.brand{display:flex;align-items:center;gap:9px;font-weight:740;white-space:nowrap}.brand svg{width:29px;height:29px;color:var(--cyan)}.actions{flex-wrap:wrap}.nav{margin-bottom:12px;border-bottom:1px solid var(--border);overflow:auto;align-items:stretch;gap:3px;scrollbar-width:thin}.nav button{flex:none;border:0;border-bottom:2px solid transparent;background:none;color:var(--muted);padding:8px 11px;font-size:.9rem;white-space:nowrap}.nav button[aria-current=page],.nav button:hover{color:var(--cyan);border-bottom-color:var(--cyan)}.page-head{margin-bottom:10px}.page-head p{margin-top:4px}.btn,input:not([type=range]),select,textarea{min-width:0;border:1px solid var(--strong);background:var(--raised);color:var(--ink);border-radius:5px;padding:6px 8px}.btn{display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;text-decoration:none;font-size:.83rem;font-weight:640}.btn:hover,.btn[aria-pressed=true]{background:#203747;border-color:#658c9e}.btn.primary{background:var(--cyan);border-color:var(--cyan);color:#0c252d}.btn.primary:hover{background:#a5f4ed}.btn.quiet{background:transparent;border-color:transparent;color:var(--cyan)}.btn.quiet:hover{background:var(--raised)}.chip{display:inline-flex;align-items:center;gap:5px;background:#203149;border-radius:4px;padding:3px 6px;color:#bfd2e8;font-size:.73rem;font-weight:650;line-height:1.2;max-width:100%}.chip.cyan{background:#153640;color:var(--cyan)}.chip.green{background:#17362b;color:var(--green)}.chip.pink{background:#382847;color:var(--pink)}.chip.amber{background:#392f23;color:var(--amber)}.chip.red{background:#422934;color:var(--red)}.dot{display:inline-block;width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
12
- .strip{display:grid;grid-template-columns:1fr 1.05fr 1fr 1.2fr;border:1px solid var(--border);border-radius:7px;background:var(--surface);margin-bottom:10px}.metric{min-width:0;padding:9px 12px}.metric+.metric{border-left:1px solid var(--border)}.metric dt{font-size:.76rem;color:var(--muted)}.metric dd{font-size:1.12rem;font-weight:700;margin:2px 0}.metric small{color:var(--muted);display:block}.metric-trace{width:68px;height:24px;float:right;margin:3px 0 0 6px;opacity:.85}
13
- .panel{min-width:0;background:var(--surface);border:1px solid var(--border);border-radius:7px;overflow:hidden}.panel-head{min-height:41px;padding:6px 10px;background:#111d30;border-bottom:1px solid var(--border)}.panel-body{padding:10px}.stack{display:grid;gap:10px}.list{list-style:none;padding:0}.list>li+li{border-top:1px solid var(--border)}.item{padding:8px 10px;display:grid;gap:4px}.rail-title{padding:8px 9px;background:#101c2c;border-bottom:1px solid var(--border)}.rail-title:not(:first-child){border-top:1px solid var(--border)}.rail-entry,.entry{width:100%;display:grid;gap:3px;text-align:left;border:0;background:transparent;color:var(--ink);padding:8px 9px;cursor:pointer}.rail-entry:hover,.rail-entry[aria-pressed=true],.entry:hover,.entry[aria-pressed=true]{background:#172c40}.rail-entry strong{font-size:.84rem}.rail-entry small{font-size:.73rem;color:var(--muted)}.empty{padding:12px;display:grid;gap:7px;color:var(--muted)}.empty strong{color:var(--ink)}.notice{padding:9px 11px;border:1px solid #654f37;border-radius:5px;background:#251f1b;color:#ffe1a7;margin:0 0 10px}.notice:empty{display:none}.status{min-height:0;color:var(--green)}.status:empty{display:none}.status[data-error=true]{color:var(--red)}
14
- .control-grid{display:grid;grid-template-columns:184px minmax(0,1fr) 265px;gap:10px;margin-bottom:10px}.control-grid>.rail,.control-grid>.inspect{overflow:auto;min-height:0}.graph-panel{display:flex;flex-direction:column;background:#080f1d;border-color:#344d68}.graph-stage{position:relative;isolation:isolate;flex:1;min-height:375px;overflow:hidden;background:radial-gradient(ellipse at 50% 49%,#182641 0%,#0e192d 39%,#090f1d 77%)}#brain-canvas{position:absolute;inset:0;width:100%;height:100%;display:block}.graph-meta{position:absolute;left:12px;right:12px;top:11px;display:flex;justify-content:space-between;gap:10px;font:.71rem var(--mono);color:var(--muted);pointer-events:none}.graph-empty{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:min(290px,90%);padding:10px 12px;background:#0e192ceb;border:1px solid #455e7e;border-radius:6px;text-align:center}.graph-empty .actions{justify-content:center;margin-top:6px}.graph-foot{display:flex;align-items:center;justify-content:space-between;gap:6px;flex-wrap:wrap;border-top:1px solid var(--border);background:#0e1828;color:var(--muted);padding:5px 8px;min-height:31px;font-size:.74rem}.legend{display:flex;gap:8px;flex-wrap:wrap}.legend span{display:flex;align-items:center;gap:4px}.legend i{display:inline-block;width:11px;border-top:2px solid currentColor}.node-list{position:absolute;inset:6px;overflow:auto;background:#0d182bef;border:1px solid var(--strong);z-index:1}.node-list>li+li{border-top:1px solid var(--border)}.focus-label{position:absolute;left:50%;bottom:10px;transform:translateX(-50%);max-width:92%;padding:4px 8px;background:#122136;border:1px solid #486787;border-radius:4px;overflow-wrap:anywhere;color:var(--ink);font-size:.76rem;text-align:center;pointer-events:none}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--border);padding:6px 7px}.tabs .btn{min-height:26px;padding-block:3px}.facts{display:grid;gap:0}.facts>div{display:flex;justify-content:space-between;gap:9px;border-bottom:1px solid var(--border);padding:6px 0;font-size:.81rem}.facts dt{color:var(--muted)}.facts dd{text-align:right}.receipt{display:grid;gap:5px;border:1px solid var(--border);border-radius:5px;padding:8px;background:#121e30}.lower{display:grid;grid-template-columns:minmax(235px,.8fr) minmax(0,1.8fr);gap:10px}.timeline{max-height:106px;overflow:auto}.event{grid-template-columns:76px minmax(0,1fr) auto;align-items:center;font-size:.8rem;min-height:29px;padding-block:5px}.event time{color:var(--muted)}.replay{padding:5px 8px;display:flex;align-items:center;gap:8px;border-bottom:1px solid var(--border)}.replay input{min-width:35px;flex:1;accent-color:var(--cyan)}.replay output{min-width:6em;text-align:right}.two{display:grid;grid-template-columns:minmax(220px,.85fr) minmax(0,1.45fr);gap:10px;align-items:start}.three{display:grid;grid-template-columns:minmax(150px,.64fr) minmax(0,1.45fr) minmax(220px,.9fr);gap:10px;align-items:start}.form{display:grid;gap:8px}.form label{display:grid;gap:3px;color:var(--muted);font-size:.83rem}.form :is(input,select,textarea){width:100%}.form textarea{resize:vertical}.form input[type=checkbox]{width:auto}.form .check{display:flex;gap:7px;align-items:flex-start}.form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}pre{margin:0;padding:9px;border:1px solid var(--border);background:#091321;border-radius:4px;white-space:pre-wrap;max-height:250px;overflow:auto;color:#d7e9ff;font:.81rem/1.5 var(--mono)}.section-list{max-height:480px;overflow:auto}.section-list .entry strong{font-size:.86rem}.table-wrap{overflow:auto}table{width:100%;border-collapse:collapse;font-size:.84rem}td,th{padding:7px 9px;border-bottom:1px solid var(--border);text-align:left;vertical-align:top}th{color:var(--muted)}.meter{height:5px;border-radius:4px;background:#2b3c53;overflow:hidden}.meter i{display:block;height:100%;background:var(--pink)}.footer{display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px;margin-top:10px;color:var(--muted);font-size:.77rem}details>summary{cursor:pointer;color:var(--cyan)}details[open]>summary{margin-bottom:7px}.trace-list{position:absolute;inset:0;overflow:auto;background:#0e1929}.trace-list .event{grid-template-columns:76px minmax(0,1fr) auto}
15
- @media(min-width:981px){.control-grid{grid-template-rows:429px}.graph-stage{min-height:0}}
16
- @media(max-width:1200px){.control-grid{grid-template-columns:153px minmax(0,1fr) 235px}.frame{padding-inline:14px}}
17
- @media(max-width:980px){.control-grid{grid-template-columns:145px minmax(0,1fr)}.control-grid>.inspect{grid-column:1/-1}.three{grid-template-columns:minmax(145px,.6fr) minmax(0,1.4fr)}.three>.panel:last-child{grid-column:1/-1}}
18
- @media(max-width:680px){.frame{padding-inline:10px}.top,.page-head{flex-wrap:wrap}.top .actions{width:100%}.nav{margin-bottom:10px}.strip{grid-template-columns:repeat(2,minmax(0,1fr))}.metric:nth-child(3){border-left:0}.metric:nth-child(n+3){border-top:1px solid var(--border)}.control-grid,.lower,.two,.three{grid-template-columns:minmax(0,1fr)}.graph-panel{grid-row:1}.graph-stage{min-height:320px}.control-grid>.rail{max-height:240px}.event{grid-template-columns:61px minmax(0,1fr)}.event .chip{justify-self:start;grid-column:2}.graph-meta{font-size:.62rem}h1{font-size:1.65rem}}
19
- @media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}
20
- .sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
21
- .graph-panel{background:var(--surface)}.graph-stage{background:radial-gradient(circle,#6a84a128 .6px,transparent .9px) 0 0/18px 18px,radial-gradient(ellipse at 50% 55%,#12243b,#0b1527 62%,#080f1c 100%)}
22
- .graph-meta{font-size:.73rem;color:#bdd0e6;text-transform:none}.graph-foot{padding-block:4px;gap:3px 8px}
23
- .legend,.graph-camera{display:flex;align-items:center;flex-wrap:wrap;gap:3px}.legend .legend-filter{display:inline-flex;gap:5px;align-items:center;padding:3px 6px;min-height:27px;border:1px solid transparent;border-radius:4px;background:transparent;color:var(--muted)}
24
- .legend .legend-filter[aria-pressed=true]{border-color:var(--strong);background:var(--raised);color:var(--ink)}
25
- .legend .legend-filter:hover{color:var(--ink);background:var(--raised)}.legend .legend-filter i{width:10px}
26
- .graph-camera .btn{font-size:.73rem;min-height:26px;padding:2px 7px}.graph-camera .btn[aria-disabled=true]{opacity:.55;cursor:default}.graph-camera output{width:4ch;text-align:center}
27
- .graph-finder{display:flex;flex-direction:column;border-radius:5px;overflow:hidden;background:#0d182b}
28
- .graph-find{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:8px;border-bottom:1px solid var(--border);background:var(--surface)}
29
- .graph-find input{flex:1;min-width:130px}.graph-results{overflow:auto;flex:1}.graph-search-note{padding:6px 9px}
30
- .graph-exchanges{border-top:1px solid var(--border);background:var(--surface)}
31
- .exchange-head{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:5px 9px}
32
- .exchange-head h3{font-size:.84rem;font-weight:650;letter-spacing:0}
33
- .exchange-row{display:grid;width:100%;grid-template-columns:minmax(110px,1.2fr) minmax(96px,1fr) auto;gap:4px 8px;align-items:center;text-align:left;border:0;border-top:1px solid var(--border);background:transparent;color:var(--ink);padding:4px 9px;font-size:.76rem}
34
- .exchange-row:hover,.exchange-row[aria-pressed=true]{background:var(--raised)}
35
- .exchange-row:focus-visible{outline-offset:-2px}
36
- .exchange-route,.exchange-summary{display:flex;align-items:center;gap:5px;min-width:0}
37
- .exchange-route span:not(.exchange-arrow),.exchange-summary strong{min-width:0;overflow-wrap:anywhere}
38
- .exchange-route .exchange-workspace{flex:none;white-space:nowrap}
39
- .exchange-route small{display:inline-block}
40
- .exchange-summary{color:var(--muted);flex-wrap:wrap}.exchange-summary strong{font:600 .76rem var(--mono);color:var(--ink)}
41
- .exchange-arrow{position:relative;flex:0 0 18px;height:1px;background:var(--cyan)}
42
- .exchange-arrow::after{content:"";position:absolute;right:0;top:-2px;width:5px;height:5px;transform:rotate(45deg);border-top:1px solid var(--cyan);border-right:1px solid var(--cyan)}
43
- .exchange-empty{padding:0 9px 7px}
44
- .live-path-label{position:absolute;bottom:3px;left:50%;transform:translateX(-50%);max-width:92%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:2px 6px;border-radius:4px;background:var(--ground);color:var(--ink);font-size:.73rem;pointer-events:none}
45
- @media(min-width:981px){.control-grid{grid-template-rows:576px}}
46
- @media(max-width:680px){.legend .legend-filter,.graph-camera .btn{min-height:36px}.exchange-row{min-height:40px;padding-block:6px}.graph-panel-empty .graph-stage{min-height:220px}}
47
- @media(max-width:360px){.exchange-row{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.exchange-row time{grid-column:1/-1}.graph-find input{flex-basis:100%}}
48
- .preserve{white-space:pre-wrap;overflow-wrap:anywhere}
49
- .tool-dock{margin-bottom:10px}.tool-dock-head{display:flex;align-items:baseline;justify-content:space-between;gap:4px 12px;flex-wrap:wrap;padding:9px 12px}
50
- .tool-dock-list{display:flex;align-items:stretch;gap:6px;flex-wrap:wrap;padding:0 12px 8px}
51
- .tool-dock-list>li+li{border:0}.tool-dock-button{display:flex;align-items:center;gap:8px;min-height:42px;padding:5px 10px;border:1px solid var(--border);
52
- border-radius:6px;color:var(--ink);background:var(--raised);text-align:left}
53
- .tool-dock-button:hover,.tool-dock-button[aria-expanded=true]{border-color:var(--cyan)}
54
- .tool-mark{width:23px;height:23px;display:grid;place-items:center;color:var(--ink);font:700 .72rem var(--mono)}
55
- .tool-mark svg{display:block;width:100%;height:100%}
56
- .tool-dock-text{display:grid;gap:1px;line-height:1.2}.tool-dock-text strong{font-size:.81rem}.tool-dock-text small{color:var(--muted);font-size:.69rem}
57
- .tool-dock-indicator{width:6px;height:6px;margin-left:4px;border-radius:50%;background:var(--strong)}
58
- .tool-activity-pulse{animation:tool-report 1.3s ease-out}
59
- @keyframes tool-report{0%{background:var(--cyan);box-shadow:0 0 0 5px #78e9e53d}100%{background:var(--strong);box-shadow:0 0 0 0 #78e9e500}}
60
- .tool-dock-empty,.tool-dock-caption{padding:0 12px 7px}.tool-dock-details{display:grid;gap:5px;padding:9px 12px;border-top:1px solid var(--border);background:var(--ground)}
61
- .tool-dock-record-list{display:flex;flex-wrap:wrap;gap:6px}.tool-dock-record-list>li+li{border:0}
62
- .tool-dock-record-list li{max-width:100%}.tool-dock-record{display:grid;gap:1px;min-height:36px;padding:4px 7px;color:var(--ink);background:var(--surface);border:1px solid var(--border);border-radius:5px;text-align:left;overflow-wrap:anywhere;font-size:.76rem}
63
- .tool-dock-record[aria-pressed=true],.tool-dock-record:hover{border-color:var(--cyan)}
64
- .tool-evidence-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.tool-evidence-grid dt,.tool-evidence-grid dd{overflow-wrap:anywhere}
65
- @media(max-width:680px){.tool-evidence-grid{grid-template-columns:minmax(0,1fr)}.tool-dock-button,.tool-dock-record{min-height:44px}}
66
- @media(prefers-reduced-motion:reduce){.tool-activity-pulse{animation:none}}
67
- [id^="policy-"][type="range"]{accent-color:var(--cyan)}
68
- #project-file-body strong{min-width:0;overflow-wrap:anywhere}
69
- #project-file-pulse{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted)}
70
- .file-fresh{animation:file-observed 1.6s ease-out}
71
- @keyframes file-observed{0%{color:var(--cyan)}100%{color:var(--muted)}}
72
- </style></head><body>
73
- <a class="btn skip" href="#main">Skip to content</a>
74
- <div class="frame"><header class="top"><div class="brand"><svg viewBox="0 0 32 32" aria-hidden="true"><path d="M16 2 28 9v14l-12 7-12-7V9Zm0 0v28M4 9l24 14M28 9 4 23" fill="none" stroke="currentColor" stroke-width="1.4"/><circle cx="16" cy="16" r="3.3" fill="currentColor"/></svg>Agent Shadow Brain</div><div class="actions"><span class="chip" id="connection"><i class="dot" aria-hidden="true"></i> Connecting to workspace</span><label for="project" class="small muted">Project</label><select id="project" disabled><option>Loading…</option></select><button class="btn" id="reload" type="button">Refresh</button></div></header>
75
- <nav class="nav" id="nav" aria-label="Brain workspace"></nav>
76
- <span class="chip" id="stream-health" role="status" hidden></span>
77
- <p class="notice" id="notice" role="status"></p>
78
- <main id="main" tabindex="-1"><div class="empty"><strong>Opening the workspace</strong><p>Loading the local memory and activity stores.</p></div></main>
79
- <footer class="footer"><span id="scope-note"></span><span><a href="/workspace">Classic workspace</a> · <a href="/live">Activity diagnostics</a></span></footer>
80
- </div>
81
- <script>'use strict';
82
- ` + BRAIN_HUB_CLIENT + BRAIN_HUB_LIVE + BRAIN_HUB_EXCHANGES + BRAIN_HUB_GRAPH + BRAIN_HUB_VIEWS + String.raw `
83
- start();
6
+ export const BRAIN_HUB_HTML = String.raw `<!doctype html>
7
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="color-scheme" content="dark"><title>Agent Shadow Brain</title>
8
+ <style>
9
+ :root{color-scheme:dark;--ground:#080e19;--surface:#0e1828;--raised:#142237;--border:#263a50;--strong:#425d78;--ink:#ecf5ff;--muted:#a9bed3;--cyan:#78e9e5;--blue:#afc7ff;--pink:#ecb0fc;--amber:#f9d28b;--green:#a0e7be;--red:#ffacb6;--sans:Inter,"Segoe UI",system-ui,sans-serif;--mono:"IBM Plex Mono","Cascadia Mono",Consolas,monospace;font:14px/1.45 var(--sans)}
10
+ *,*::before,*::after{box-sizing:border-box}body{margin:0;background:var(--ground);color:var(--ink)}[hidden]{display:none!important}a{color:var(--cyan)}button,input,select,textarea{font:inherit}button,select{cursor:pointer}button:disabled{cursor:default;opacity:.52}a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,summary:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}h1,h2,h3,p,ul,ol,dl,dd{margin:0}h1,h2,h3{letter-spacing:-.022em;line-height:1.25}h1{font-size:1.95rem}h2{font-size:1.06rem}h3{font-size:.95rem}p,dd,li,pre,td{overflow-wrap:anywhere}small,.small{font-size:.81rem}.muted{color:var(--muted)}.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}.cyan{color:var(--cyan)}.pink{color:var(--pink)}.amber{color:var(--amber)}.green{color:var(--green)}.red{color:var(--red)}.skip{position:fixed;left:12px;top:8px;z-index:4;transform:translateY(-150%)}.skip:focus{transform:none}
11
+ .frame{max-width:1700px;margin:auto;padding:0 22px 24px}.top,.page-head,.panel-head,.row,.actions,.nav{display:flex;align-items:center;gap:8px}.top,.page-head,.panel-head,.row{justify-content:space-between}.top{min-height:54px;border-bottom:1px solid var(--border);flex-wrap:wrap;padding-block:7px}.brand{display:flex;align-items:center;gap:9px;font-weight:740;white-space:nowrap}.brand svg{width:29px;height:29px;color:var(--cyan)}.actions{flex-wrap:wrap}.nav{margin-bottom:12px;border-bottom:1px solid var(--border);overflow:auto;align-items:stretch;gap:3px;scrollbar-width:thin}.nav button{flex:none;border:0;border-bottom:2px solid transparent;background:none;color:var(--muted);padding:8px 11px;font-size:.9rem;white-space:nowrap}.nav button[aria-current=page],.nav button:hover{color:var(--cyan);border-bottom-color:var(--cyan)}.page-head{margin-bottom:10px}.page-head p{margin-top:4px}.btn,input:not([type=range]),select,textarea{min-width:0;border:1px solid var(--strong);background:var(--raised);color:var(--ink);border-radius:5px;padding:6px 8px}.btn{display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;text-decoration:none;font-size:.83rem;font-weight:640}.btn:hover,.btn[aria-pressed=true]{background:#203747;border-color:#658c9e}.btn.primary{background:var(--cyan);border-color:var(--cyan);color:#0c252d}.btn.primary:hover{background:#a5f4ed}.btn.quiet{background:transparent;border-color:transparent;color:var(--cyan)}.btn.quiet:hover{background:var(--raised)}.chip{display:inline-flex;align-items:center;gap:5px;background:#203149;border-radius:4px;padding:3px 6px;color:#bfd2e8;font-size:.73rem;font-weight:650;line-height:1.2;max-width:100%}.chip.cyan{background:#153640;color:var(--cyan)}.chip.green{background:#17362b;color:var(--green)}.chip.pink{background:#382847;color:var(--pink)}.chip.amber{background:#392f23;color:var(--amber)}.chip.red{background:#422934;color:var(--red)}.dot{display:inline-block;width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
12
+ .strip{display:grid;grid-template-columns:1fr 1.05fr 1fr 1.2fr;border:1px solid var(--border);border-radius:7px;background:var(--surface);margin-bottom:10px}.metric{min-width:0;padding:9px 12px}.metric+.metric{border-left:1px solid var(--border)}.metric dt{font-size:.76rem;color:var(--muted)}.metric dd{font-size:1.12rem;font-weight:700;margin:2px 0}.metric small{color:var(--muted);display:block}.metric-trace{width:68px;height:24px;float:right;margin:3px 0 0 6px;opacity:.85}
13
+ .panel{min-width:0;background:var(--surface);border:1px solid var(--border);border-radius:7px;overflow:hidden}.panel-head{min-height:41px;padding:6px 10px;background:#111d30;border-bottom:1px solid var(--border)}.panel-body{padding:10px}.stack{display:grid;gap:10px}.list{list-style:none;padding:0}.list>li+li{border-top:1px solid var(--border)}.item{padding:8px 10px;display:grid;gap:4px}.rail-title{padding:8px 9px;background:#101c2c;border-bottom:1px solid var(--border)}.rail-title:not(:first-child){border-top:1px solid var(--border)}.rail-entry,.entry{width:100%;display:grid;gap:3px;text-align:left;border:0;background:transparent;color:var(--ink);padding:8px 9px;cursor:pointer}.rail-entry:hover,.rail-entry[aria-pressed=true],.entry:hover,.entry[aria-pressed=true]{background:#172c40}.rail-entry strong{font-size:.84rem}.rail-entry small{font-size:.73rem;color:var(--muted)}.empty{padding:12px;display:grid;gap:7px;color:var(--muted)}.empty strong{color:var(--ink)}.notice{padding:9px 11px;border:1px solid #654f37;border-radius:5px;background:#251f1b;color:#ffe1a7;margin:0 0 10px}.notice:empty{display:none}.status{min-height:0;color:var(--green)}.status:empty{display:none}.status[data-error=true]{color:var(--red)}
14
+ .control-grid{display:grid;grid-template-columns:184px minmax(0,1fr) 265px;gap:10px;margin-bottom:10px}.control-grid>.rail,.control-grid>.inspect{overflow:auto;min-height:0}.graph-panel{display:flex;flex-direction:column;background:#080f1d;border-color:#344d68}.graph-stage{position:relative;isolation:isolate;flex:1;min-height:375px;overflow:hidden;background:radial-gradient(ellipse at 50% 49%,#182641 0%,#0e192d 39%,#090f1d 77%)}#brain-canvas{position:absolute;inset:0;width:100%;height:100%;display:block}.graph-meta{position:absolute;left:12px;right:12px;top:11px;display:flex;justify-content:space-between;gap:10px;font:.71rem var(--mono);color:var(--muted);pointer-events:none}.graph-empty{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:min(290px,90%);padding:10px 12px;background:#0e192ceb;border:1px solid #455e7e;border-radius:6px;text-align:center}.graph-empty .actions{justify-content:center;margin-top:6px}.graph-foot{display:flex;align-items:center;justify-content:space-between;gap:6px;flex-wrap:wrap;border-top:1px solid var(--border);background:#0e1828;color:var(--muted);padding:5px 8px;min-height:31px;font-size:.74rem}.legend{display:flex;gap:8px;flex-wrap:wrap}.legend span{display:flex;align-items:center;gap:4px}.legend i{display:inline-block;width:11px;border-top:2px solid currentColor}.node-list{position:absolute;inset:6px;overflow:auto;background:#0d182bef;border:1px solid var(--strong);z-index:1}.node-list>li+li{border-top:1px solid var(--border)}.focus-label{position:absolute;left:50%;bottom:10px;transform:translateX(-50%);max-width:92%;padding:4px 8px;background:#122136;border:1px solid #486787;border-radius:4px;overflow-wrap:anywhere;color:var(--ink);font-size:.76rem;text-align:center;pointer-events:none}.tabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--border);padding:6px 7px}.tabs .btn{min-height:26px;padding-block:3px}.facts{display:grid;gap:0}.facts>div{display:flex;justify-content:space-between;gap:9px;border-bottom:1px solid var(--border);padding:6px 0;font-size:.81rem}.facts dt{color:var(--muted)}.facts dd{text-align:right}.receipt{display:grid;gap:5px;border:1px solid var(--border);border-radius:5px;padding:8px;background:#121e30}.lower{display:grid;grid-template-columns:minmax(235px,.8fr) minmax(0,1.8fr);gap:10px}.timeline{max-height:106px;overflow:auto}.event{grid-template-columns:76px minmax(0,1fr) auto;align-items:center;font-size:.8rem;min-height:29px;padding-block:5px}.event time{color:var(--muted)}.replay{padding:5px 8px;display:flex;align-items:center;gap:8px;border-bottom:1px solid var(--border)}.replay input{min-width:35px;flex:1;accent-color:var(--cyan)}.replay output{min-width:6em;text-align:right}.two{display:grid;grid-template-columns:minmax(220px,.85fr) minmax(0,1.45fr);gap:10px;align-items:start}.three{display:grid;grid-template-columns:minmax(150px,.64fr) minmax(0,1.45fr) minmax(220px,.9fr);gap:10px;align-items:start}.form{display:grid;gap:8px}.form label{display:grid;gap:3px;color:var(--muted);font-size:.83rem}.form :is(input,select,textarea){width:100%}.form textarea{resize:vertical}.form input[type=checkbox]{width:auto}.form .check{display:flex;gap:7px;align-items:flex-start}.form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}pre{margin:0;padding:9px;border:1px solid var(--border);background:#091321;border-radius:4px;white-space:pre-wrap;max-height:250px;overflow:auto;color:#d7e9ff;font:.81rem/1.5 var(--mono)}.section-list{max-height:480px;overflow:auto}.section-list .entry strong{font-size:.86rem}.table-wrap{overflow:auto}table{width:100%;border-collapse:collapse;font-size:.84rem}td,th{padding:7px 9px;border-bottom:1px solid var(--border);text-align:left;vertical-align:top}th{color:var(--muted)}.meter{height:5px;border-radius:4px;background:#2b3c53;overflow:hidden}.meter i{display:block;height:100%;background:var(--pink)}.footer{display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px;margin-top:10px;color:var(--muted);font-size:.77rem}details>summary{cursor:pointer;color:var(--cyan)}details[open]>summary{margin-bottom:7px}.trace-list{position:absolute;inset:0;overflow:auto;background:#0e1929}.trace-list .event{grid-template-columns:76px minmax(0,1fr) auto}
15
+ @media(min-width:981px){.control-grid{grid-template-rows:429px}.graph-stage{min-height:0}}
16
+ @media(max-width:1200px){.control-grid{grid-template-columns:153px minmax(0,1fr) 235px}.frame{padding-inline:14px}}
17
+ @media(max-width:980px){.control-grid{grid-template-columns:145px minmax(0,1fr)}.control-grid>.inspect{grid-column:1/-1}.three{grid-template-columns:minmax(145px,.6fr) minmax(0,1.4fr)}.three>.panel:last-child{grid-column:1/-1}}
18
+ @media(max-width:680px){.frame{padding-inline:10px}.top,.page-head{flex-wrap:wrap}.top .actions{width:100%}.nav{margin-bottom:10px}.strip{grid-template-columns:repeat(2,minmax(0,1fr))}.metric:nth-child(3){border-left:0}.metric:nth-child(n+3){border-top:1px solid var(--border)}.control-grid,.lower,.two,.three{grid-template-columns:minmax(0,1fr)}.graph-panel{grid-row:1}.graph-stage{min-height:320px}.control-grid>.rail{max-height:240px}.event{grid-template-columns:61px minmax(0,1fr)}.event .chip{justify-self:start;grid-column:2}.graph-meta{font-size:.62rem}h1{font-size:1.65rem}}
19
+ @media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}
20
+ .sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
21
+ .graph-panel{background:var(--surface)}.graph-stage{background:radial-gradient(circle,#6a84a128 .6px,transparent .9px) 0 0/18px 18px,radial-gradient(ellipse at 50% 55%,#12243b,#0b1527 62%,#080f1c 100%)}
22
+ .graph-meta{font-size:.73rem;color:#bdd0e6;text-transform:none}.graph-foot{padding-block:4px;gap:3px 8px}
23
+ .legend,.graph-camera{display:flex;align-items:center;flex-wrap:wrap;gap:3px}.legend .legend-filter{display:inline-flex;gap:5px;align-items:center;padding:3px 6px;min-height:27px;border:1px solid transparent;border-radius:4px;background:transparent;color:var(--muted)}
24
+ .legend .legend-filter[aria-pressed=true]{border-color:var(--strong);background:var(--raised);color:var(--ink)}
25
+ .legend .legend-filter:hover{color:var(--ink);background:var(--raised)}.legend .legend-filter i{width:10px}
26
+ .graph-camera .btn{font-size:.73rem;min-height:26px;padding:2px 7px}.graph-camera .btn[aria-disabled=true]{opacity:.55;cursor:default}.graph-camera output{width:4ch;text-align:center}
27
+ .graph-finder{display:flex;flex-direction:column;border-radius:5px;overflow:hidden;background:#0d182b}
28
+ .graph-find{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:8px;border-bottom:1px solid var(--border);background:var(--surface)}
29
+ .graph-find input{flex:1;min-width:130px}.graph-results{overflow:auto;flex:1}.graph-search-note{padding:6px 9px}
30
+ .graph-exchanges{border-top:1px solid var(--border);background:var(--surface)}
31
+ .exchange-head{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:5px 9px}
32
+ .exchange-head h3{font-size:.84rem;font-weight:650;letter-spacing:0}
33
+ .exchange-row{display:grid;width:100%;grid-template-columns:minmax(110px,1.2fr) minmax(96px,1fr) auto;gap:4px 8px;align-items:center;text-align:left;border:0;border-top:1px solid var(--border);background:transparent;color:var(--ink);padding:4px 9px;font-size:.76rem}
34
+ .exchange-row:hover,.exchange-row[aria-pressed=true]{background:var(--raised)}
35
+ .exchange-row:focus-visible{outline-offset:-2px}
36
+ .exchange-route,.exchange-summary{display:flex;align-items:center;gap:5px;min-width:0}
37
+ .exchange-route span:not(.exchange-arrow),.exchange-summary strong{min-width:0;overflow-wrap:anywhere}
38
+ .exchange-route .exchange-workspace{flex:none;white-space:nowrap}
39
+ .exchange-route small{display:inline-block}
40
+ .exchange-summary{color:var(--muted);flex-wrap:wrap}.exchange-summary strong{font:600 .76rem var(--mono);color:var(--ink)}
41
+ .exchange-arrow{position:relative;flex:0 0 18px;height:1px;background:var(--cyan)}
42
+ .exchange-arrow::after{content:"";position:absolute;right:0;top:-2px;width:5px;height:5px;transform:rotate(45deg);border-top:1px solid var(--cyan);border-right:1px solid var(--cyan)}
43
+ .exchange-empty{padding:0 9px 7px}
44
+ .live-path-label{position:absolute;bottom:3px;left:50%;transform:translateX(-50%);max-width:92%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:2px 6px;border-radius:4px;background:var(--ground);color:var(--ink);font-size:.73rem;pointer-events:none}
45
+ @media(min-width:981px){.control-grid{grid-template-rows:576px}}
46
+ @media(max-width:680px){.legend .legend-filter,.graph-camera .btn{min-height:36px}.exchange-row{min-height:40px;padding-block:6px}.graph-panel-empty .graph-stage{min-height:220px}}
47
+ @media(max-width:360px){.exchange-row{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.exchange-row time{grid-column:1/-1}.graph-find input{flex-basis:100%}}
48
+ .preserve{white-space:pre-wrap;overflow-wrap:anywhere}
49
+ .tool-dock{margin-bottom:10px}.tool-dock-head{display:flex;align-items:baseline;justify-content:space-between;gap:4px 12px;flex-wrap:wrap;padding:9px 12px}
50
+ .tool-dock-list{display:flex;align-items:stretch;gap:6px;flex-wrap:wrap;padding:0 12px 8px}
51
+ .tool-dock-list>li+li{border:0}.tool-dock-button{display:flex;align-items:center;gap:8px;min-height:42px;padding:5px 10px;border:1px solid var(--border);
52
+ border-radius:6px;color:var(--ink);background:var(--raised);text-align:left}
53
+ .tool-dock-button:hover,.tool-dock-button[aria-expanded=true]{border-color:var(--cyan)}
54
+ .tool-mark{width:23px;height:23px;display:grid;place-items:center;color:var(--ink);font:700 .72rem var(--mono)}
55
+ .tool-mark svg{display:block;width:100%;height:100%}
56
+ .tool-dock-text{display:grid;gap:1px;line-height:1.2}.tool-dock-text strong{font-size:.81rem}.tool-dock-text small{color:var(--muted);font-size:.69rem}
57
+ .tool-dock-indicator{width:6px;height:6px;margin-left:4px;border-radius:50%;background:var(--strong)}
58
+ .tool-activity-pulse{animation:tool-report 1.3s ease-out}
59
+ @keyframes tool-report{0%{background:var(--cyan);box-shadow:0 0 0 5px #78e9e53d}100%{background:var(--strong);box-shadow:0 0 0 0 #78e9e500}}
60
+ .tool-dock-empty,.tool-dock-caption{padding:0 12px 7px}.tool-dock-details{display:grid;gap:5px;padding:9px 12px;border-top:1px solid var(--border);background:var(--ground)}
61
+ .tool-dock-record-list{display:flex;flex-wrap:wrap;gap:6px}.tool-dock-record-list>li+li{border:0}
62
+ .tool-dock-record-list li{max-width:100%}.tool-dock-record{display:grid;gap:1px;min-height:36px;padding:4px 7px;color:var(--ink);background:var(--surface);border:1px solid var(--border);border-radius:5px;text-align:left;overflow-wrap:anywhere;font-size:.76rem}
63
+ .tool-dock-record[aria-pressed=true],.tool-dock-record:hover{border-color:var(--cyan)}
64
+ .tool-evidence-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.tool-evidence-grid dt,.tool-evidence-grid dd{overflow-wrap:anywhere}
65
+ @media(max-width:680px){.tool-evidence-grid{grid-template-columns:minmax(0,1fr)}.tool-dock-button,.tool-dock-record{min-height:44px}}
66
+ @media(prefers-reduced-motion:reduce){.tool-activity-pulse{animation:none}}
67
+ [id^="policy-"][type="range"]{accent-color:var(--cyan)}
68
+ #project-file-body strong{min-width:0;overflow-wrap:anywhere}
69
+ #project-file-pulse{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted)}
70
+ .file-fresh{animation:file-observed 1.6s ease-out}
71
+ @keyframes file-observed{0%{color:var(--cyan)}100%{color:var(--muted)}}
72
+ </style></head><body>
73
+ <a class="btn skip" href="#main">Skip to content</a>
74
+ <div class="frame"><header class="top"><div class="brand"><svg viewBox="0 0 32 32" aria-hidden="true"><path d="M16 2 28 9v14l-12 7-12-7V9Zm0 0v28M4 9l24 14M28 9 4 23" fill="none" stroke="currentColor" stroke-width="1.4"/><circle cx="16" cy="16" r="3.3" fill="currentColor"/></svg>Agent Shadow Brain</div><div class="actions"><span class="chip" id="connection"><i class="dot" aria-hidden="true"></i> Connecting to workspace</span><label for="project" class="small muted">Project</label><select id="project" disabled><option>Loading…</option></select><button class="btn" id="reload" type="button">Refresh</button></div></header>
75
+ <nav class="nav" id="nav" aria-label="Brain workspace"></nav>
76
+ <span class="chip" id="stream-health" role="status" hidden></span>
77
+ <p class="notice" id="notice" role="status"></p>
78
+ <main id="main" tabindex="-1"><div class="empty"><strong>Opening the workspace</strong><p>Loading the local memory and activity stores.</p></div></main>
79
+ <footer class="footer"><span id="scope-note"></span><span>Created by <a href="https://github.com/theihtishaam" target="_blank" rel="noopener noreferrer">@theihtishaam</a> · <a href="https://github.com/theihtishaam/agents-brain" target="_blank" rel="noopener noreferrer">Star Agent Shadow Brain on GitHub</a></span><span><a href="/workspace">Classic workspace</a> · <a href="/live">Activity diagnostics</a></span></footer>
80
+ </div>
81
+ <script>'use strict';
82
+ ` + BRAIN_HUB_CLIENT + BRAIN_HUB_LIVE + BRAIN_HUB_EXCHANGES + BRAIN_HUB_GRAPH + BRAIN_HUB_VIEWS + String.raw `
83
+ start();
84
84
  </script></body></html>`;
85
85
  //# sourceMappingURL=brain-hub-html.js.map
@@ -1,151 +1,151 @@
1
- export const BRAIN_HUB_LIVE = String.raw `
2
- const liveStream={source:null,status:'connecting',cursor:null,instance:null,replaying:false,ready:false,notice:null,areas:new Set(),
3
- timer:0,files:null,fileError:null,fileEpoch:0,inventoryTimer:0,seen:new Map(),filePulse:null};
4
- const streamAreas=['telemetry','graph','hub','sources','sessions','usage','features','feedback','policy','presence'];
5
- function streamBadge(){
6
- const badge=$('stream-health');
7
- if(!badge||!local)return;
8
- const state=liveStream.status;
9
- badge.hidden=false;
10
- badge.className='chip '+(state==='live'?'green':state==='fallback'?'amber':'');
11
- badge.textContent=state==='live'?'Live stream':state==='fallback'?'Polling fallback':state==='off'?'Live updates off':'Connecting stream';
12
- }
13
- function queueLive(areas){
14
- for(const area of areas)if(streamAreas.includes(area))liveStream.areas.add(area);
15
- if(liveStream.timer||!liveStream.areas.size)return;
16
- liveStream.timer=setTimeout(()=>{
17
- liveStream.timer=0;
18
- if(document.hidden)return;
19
- if(polling||state.pending){queueLive([]);return;}
20
- const areas=new Set(liveStream.areas);
21
- liveStream.areas.clear();
22
- void refresh(false,areas);
23
- },55);
24
- }
25
- function clearLiveFiles(){
26
- liveStream.files=null;liveStream.fileError=null;liveStream.filePulse=null;liveStream.seen.clear();liveStream.fileEpoch++;
27
- updateLiveFilePanel();updateLiveFilePulse();
28
- }
29
- function stopProjectStream(){
30
- liveStream.source?.close();liveStream.source=null;
31
- liveStream.ready=false;liveStream.replaying=false;
32
- clearTimeout(liveStream.timer);liveStream.timer=0;clearTimeout(liveStream.inventoryTimer);liveStream.inventoryTimer=0;
33
- liveStream.areas.clear();
34
- }
35
- function syncProjectStream(){
36
- if(!local||document.hidden||!state.server?.capabilities?.liveStream)return;
37
- if(state.features?.features?.liveActivity===false){
38
- stopProjectStream();clearLiveFiles();liveStream.cursor=null;liveStream.status='off';streamBadge();return;
39
- }
40
- if(liveStream.source)return;
41
- if(typeof EventSource!=='function'){liveStream.status='fallback';streamBadge();return;}
42
- liveStream.status='connecting';streamBadge();
43
- const previous=liveStream.cursor;
44
- liveStream.replaying=!!previous;
45
- const source=new EventSource('/api/workspace/stream'+(previous?'?'+new URLSearchParams({cursor:previous}):''));
46
- liveStream.source=source;
47
- function handle(message){
48
- if(liveStream.source!==source)return;
49
- let data;
50
- try{data=JSON.parse(message.data);}catch{return;}
51
- if(!data||typeof data.serverInstanceId!=='string'||!Number.isSafeInteger(data.sequence)||data.kind!==message.type)return;
52
- if(liveStream.instance&&liveStream.instance!==data.serverInstanceId)clearLiveFiles();
53
- liveStream.instance=data.serverInstanceId;
54
- liveStream.cursor=message.lastEventId;
55
- if(data.kind==='disabled'){
56
- stopProjectStream();clearLiveFiles();liveStream.cursor=null;liveStream.status='off';streamBadge();
57
- void refresh(true);return;
58
- }
59
- if(data.kind==='reset'){
60
- liveStream.notice='Live history changed. The workspace refreshed its current snapshot.';
61
- clearLiveFiles();return;
62
- }
63
- if(data.kind==='ready'){
64
- const reconnect=liveStream.replaying||liveStream.ready;
65
- liveStream.status='live';liveStream.ready=true;liveStream.replaying=false;
66
- if(!pollAgain)clearTimeout(timer);
67
- streamBadge();
68
- if(reconnect){state.suppressLivePulse=true;void refresh(true);}
69
- else queueLive(streamAreas);
70
- if(data.watch?.status!=='off')void readLiveFiles();
71
- renderChrome();return;
72
- }
73
- if(data.kind==='change'){if(liveStream.ready&&!liveStream.replaying)queueLive(arr(data.areas));return;}
74
- if(data.kind==='watch'){void readLiveFiles();return;}
75
- if(data.kind==='file'&&typeof data.path==='string'&&data.path.length<=320){
76
- if(liveStream.seen.has(data.sequence))return;
77
- liveStream.seen.set(data.sequence,data);
78
- if(liveStream.seen.size>50)liveStream.seen.delete(liveStream.seen.keys().next().value);
79
- if(liveStream.ready&&!liveStream.replaying&&state.view==='overview'){
80
- liveStream.filePulse=data;updateLiveFilePulse(!reduced.matches&&!state.motionPaused&&!state.replayId);
81
- }
82
- updateLiveFilePanel();
83
- clearTimeout(liveStream.inventoryTimer);
84
- liveStream.inventoryTimer=setTimeout(()=>void readLiveFiles(),240);
85
- }
86
- }
87
- for(const kind of ['ready','change','file','watch','reset','disabled'])source.addEventListener(kind,handle);
88
- source.addEventListener('error',()=>{
89
- if(liveStream.source!==source)return;
90
- liveStream.status='fallback';liveStream.replaying=true;streamBadge();
91
- if(!polling)void refresh();
92
- });
93
- }
94
- async function readLiveFiles(){
95
- if(!local||document.hidden||state.features?.features?.liveActivity===false)return;
96
- const id=++liveStream.fileEpoch;
97
- try{
98
- const files=await api('project-files');
99
- if(id!==liveStream.fileEpoch)return;
100
- if(liveStream.instance&&liveStream.instance!==files.serverInstanceId)liveStream.seen.clear();
101
- liveStream.files=files;liveStream.fileError=null;
102
- if(!files.enabled||files.watch?.status==='off'){liveStream.filePulse=null;liveStream.seen.clear();updateLiveFilePulse();}
103
- for(const event of arr(files.events))if(!liveStream.seen.has(event.sequence))liveStream.seen.set(event.sequence,event);
104
- const sequences=[...liveStream.seen.keys()].sort((a,b)=>a-b).slice(0,-50);
105
- for(const sequence of sequences)liveStream.seen.delete(sequence);
106
- }catch(failure){if(id===liveStream.fileEpoch)liveStream.fileError=failure.message;}
107
- updateLiveFilePanel();
108
- }
109
- function liveFileBody(){
110
- const fileFeature=state.features?.features?.projectFileActivity??liveStream.files?.enabled;
111
- if(!fileFeature)return empty('Project file activity is off','Enable it in Setup to observe safe relative paths in this project.',view('setup','Open Setup'));
112
- if(liveStream.status==='off')return empty('Live updates are off','Enable live dashboard activity in Setup.',view('setup','Open Setup'));
113
- if(state.features?.features?.activityRecording===false)return empty('Activity recording is off','Enable activity recording in Setup to observe file changes.',view('setup','Open Setup'));
114
- const watch=liveStream.files?.watch;
115
- const known=arr(liveStream.files?.items);
116
- const summary=watch?.status==='limited'?'Watch coverage is limited. Some paths may be omitted.':
117
- watch?.status==='watching'?fmt(watch.directories)+' watched directories':watch?.status==='off'?'Waiting for a live subscription.':'Opening the selected project.';
118
- const received=[...liveStream.seen.values()].sort((a,b)=>b.sequence-a.sequence).slice(0,24);
119
- const entries=received.map(event=>'<li class="item"><div class="row"><strong class="mono">'+esc(event.path)+'</strong><time class="small mono muted" datetime="'+esc(event.timestamp)+'">'+esc(time(event.timestamp))+'</time></div><small class="muted">'+
120
- esc(event.operation==='entry'?(event.exists?'Directory entry changed':'Removed or renamed'):'Change notification')+
121
- ' · Unknown actor'+(event.count>1?' · '+fmt(event.count)+' grouped notifications':'')+'</small></li>').join('');
122
- const mostRecent=received[0]?' · Last observed '+time(received[0].timestamp):'';
123
- return '<div class="panel-body stack"><p class="small muted">'+esc(liveStream.fileError??(summary+mostRecent))+'</p>'+
124
- (entries?list(entries,'aria-label="Observed project file changes"'):'<p class="small muted">No eligible changes have been observed.</p>')+
125
- (known.length?'<details><summary>Project paths · '+fmt(known.length)+(watch?.inventoryLimited?' shown':'')+'</summary>'+list(known.map(item=>'<li class="item small mono">'+esc(item.path)+(item.entry==='directory'?'/':'')+'</li>').join(''))+'</details>':'')+'</div>';
126
- }
127
- function liveFilePanel(){
128
- return '<section class="panel" aria-label="Project file activity"><div class="panel-head"><h2>Project file activity</h2></div><div id="project-file-body">'+liveFileBody()+'</div></section>';
129
- }
130
- function updateLiveFilePanel(){
131
- const region=$('project-file-body');
132
- if(!region)return;
133
- const markup=liveFileBody();
134
- if(region.dataset.markup===markup)return;
135
- const expanded=region.querySelector('details')?.open;
136
- const focused=region.querySelector('summary:focus');
137
- region.dataset.markup=markup;region.innerHTML=markup;
138
- const details=region.querySelector('details');
139
- if(details&&expanded)details.open=true;
140
- if(focused)details?.querySelector('summary')?.focus({preventScroll:true});
141
- }
142
- function updateLiveFilePulse(animate=false){
143
- const label=$('project-file-pulse');
144
- if(!label)return;
145
- label.hidden=!liveStream.filePulse;
146
- label.textContent=liveStream.filePulse?'Observed file change · '+liveStream.filePulse.path:'';
147
- label.classList.remove('file-fresh');
148
- if(animate&&!label.hidden)requestAnimationFrame(()=>{if(label.isConnected)label.classList.add('file-fresh');});
149
- }
1
+ export const BRAIN_HUB_LIVE = String.raw `
2
+ const liveStream={source:null,status:'connecting',cursor:null,instance:null,replaying:false,ready:false,notice:null,areas:new Set(),
3
+ timer:0,files:null,fileError:null,fileEpoch:0,inventoryTimer:0,seen:new Map(),filePulse:null};
4
+ const streamAreas=['telemetry','graph','hub','sources','sessions','usage','features','feedback','policy','presence'];
5
+ function streamBadge(){
6
+ const badge=$('stream-health');
7
+ if(!badge||!local)return;
8
+ const state=liveStream.status;
9
+ badge.hidden=false;
10
+ badge.className='chip '+(state==='live'?'green':state==='fallback'?'amber':'');
11
+ badge.textContent=state==='live'?'Live stream':state==='fallback'?'Polling fallback':state==='off'?'Live updates off':'Connecting stream';
12
+ }
13
+ function queueLive(areas){
14
+ for(const area of areas)if(streamAreas.includes(area))liveStream.areas.add(area);
15
+ if(liveStream.timer||!liveStream.areas.size)return;
16
+ liveStream.timer=setTimeout(()=>{
17
+ liveStream.timer=0;
18
+ if(document.hidden)return;
19
+ if(polling||state.pending){queueLive([]);return;}
20
+ const areas=new Set(liveStream.areas);
21
+ liveStream.areas.clear();
22
+ void refresh(false,areas);
23
+ },55);
24
+ }
25
+ function clearLiveFiles(){
26
+ liveStream.files=null;liveStream.fileError=null;liveStream.filePulse=null;liveStream.seen.clear();liveStream.fileEpoch++;
27
+ updateLiveFilePanel();updateLiveFilePulse();
28
+ }
29
+ function stopProjectStream(){
30
+ liveStream.source?.close();liveStream.source=null;
31
+ liveStream.ready=false;liveStream.replaying=false;
32
+ clearTimeout(liveStream.timer);liveStream.timer=0;clearTimeout(liveStream.inventoryTimer);liveStream.inventoryTimer=0;
33
+ liveStream.areas.clear();
34
+ }
35
+ function syncProjectStream(){
36
+ if(!local||document.hidden||!state.server?.capabilities?.liveStream)return;
37
+ if(state.features?.features?.liveActivity===false){
38
+ stopProjectStream();clearLiveFiles();liveStream.cursor=null;liveStream.status='off';streamBadge();return;
39
+ }
40
+ if(liveStream.source)return;
41
+ if(typeof EventSource!=='function'){liveStream.status='fallback';streamBadge();return;}
42
+ liveStream.status='connecting';streamBadge();
43
+ const previous=liveStream.cursor;
44
+ liveStream.replaying=!!previous;
45
+ const source=new EventSource('/api/workspace/stream'+(previous?'?'+new URLSearchParams({cursor:previous}):''));
46
+ liveStream.source=source;
47
+ function handle(message){
48
+ if(liveStream.source!==source)return;
49
+ let data;
50
+ try{data=JSON.parse(message.data);}catch{return;}
51
+ if(!data||typeof data.serverInstanceId!=='string'||!Number.isSafeInteger(data.sequence)||data.kind!==message.type)return;
52
+ if(liveStream.instance&&liveStream.instance!==data.serverInstanceId)clearLiveFiles();
53
+ liveStream.instance=data.serverInstanceId;
54
+ liveStream.cursor=message.lastEventId;
55
+ if(data.kind==='disabled'){
56
+ stopProjectStream();clearLiveFiles();liveStream.cursor=null;liveStream.status='off';streamBadge();
57
+ void refresh(true);return;
58
+ }
59
+ if(data.kind==='reset'){
60
+ liveStream.notice='Live history changed. The workspace refreshed its current snapshot.';
61
+ clearLiveFiles();return;
62
+ }
63
+ if(data.kind==='ready'){
64
+ const reconnect=liveStream.replaying||liveStream.ready;
65
+ liveStream.status='live';liveStream.ready=true;liveStream.replaying=false;
66
+ if(!pollAgain)clearTimeout(timer);
67
+ streamBadge();
68
+ if(reconnect){state.suppressLivePulse=true;void refresh(true);}
69
+ else queueLive(streamAreas);
70
+ if(data.watch?.status!=='off')void readLiveFiles();
71
+ renderChrome();return;
72
+ }
73
+ if(data.kind==='change'){if(liveStream.ready&&!liveStream.replaying)queueLive(arr(data.areas));return;}
74
+ if(data.kind==='watch'){void readLiveFiles();return;}
75
+ if(data.kind==='file'&&typeof data.path==='string'&&data.path.length<=320){
76
+ if(liveStream.seen.has(data.sequence))return;
77
+ liveStream.seen.set(data.sequence,data);
78
+ if(liveStream.seen.size>50)liveStream.seen.delete(liveStream.seen.keys().next().value);
79
+ if(liveStream.ready&&!liveStream.replaying&&state.view==='overview'){
80
+ liveStream.filePulse=data;updateLiveFilePulse(!reduced.matches&&!state.motionPaused&&!state.replayId);
81
+ }
82
+ updateLiveFilePanel();
83
+ clearTimeout(liveStream.inventoryTimer);
84
+ liveStream.inventoryTimer=setTimeout(()=>void readLiveFiles(),240);
85
+ }
86
+ }
87
+ for(const kind of ['ready','change','file','watch','reset','disabled'])source.addEventListener(kind,handle);
88
+ source.addEventListener('error',()=>{
89
+ if(liveStream.source!==source)return;
90
+ liveStream.status='fallback';liveStream.replaying=true;streamBadge();
91
+ if(!polling)void refresh();
92
+ });
93
+ }
94
+ async function readLiveFiles(){
95
+ if(!local||document.hidden||state.features?.features?.liveActivity===false)return;
96
+ const id=++liveStream.fileEpoch;
97
+ try{
98
+ const files=await api('project-files');
99
+ if(id!==liveStream.fileEpoch)return;
100
+ if(liveStream.instance&&liveStream.instance!==files.serverInstanceId)liveStream.seen.clear();
101
+ liveStream.files=files;liveStream.fileError=null;
102
+ if(!files.enabled||files.watch?.status==='off'){liveStream.filePulse=null;liveStream.seen.clear();updateLiveFilePulse();}
103
+ for(const event of arr(files.events))if(!liveStream.seen.has(event.sequence))liveStream.seen.set(event.sequence,event);
104
+ const sequences=[...liveStream.seen.keys()].sort((a,b)=>a-b).slice(0,-50);
105
+ for(const sequence of sequences)liveStream.seen.delete(sequence);
106
+ }catch(failure){if(id===liveStream.fileEpoch)liveStream.fileError=failure.message;}
107
+ updateLiveFilePanel();
108
+ }
109
+ function liveFileBody(){
110
+ const fileFeature=state.features?.features?.projectFileActivity??liveStream.files?.enabled;
111
+ if(!fileFeature)return empty('Project file activity is off','Enable it in Setup to observe safe relative paths in this project.',view('setup','Open Setup'));
112
+ if(liveStream.status==='off')return empty('Live updates are off','Enable live dashboard activity in Setup.',view('setup','Open Setup'));
113
+ if(state.features?.features?.activityRecording===false)return empty('Activity recording is off','Enable activity recording in Setup to observe file changes.',view('setup','Open Setup'));
114
+ const watch=liveStream.files?.watch;
115
+ const known=arr(liveStream.files?.items);
116
+ const summary=watch?.status==='limited'?'Watch coverage is limited. Some paths may be omitted.':
117
+ watch?.status==='watching'?fmt(watch.directories)+' watched directories':watch?.status==='off'?'Waiting for a live subscription.':'Opening the selected project.';
118
+ const received=[...liveStream.seen.values()].sort((a,b)=>b.sequence-a.sequence).slice(0,24);
119
+ const entries=received.map(event=>'<li class="item"><div class="row"><strong class="mono">'+esc(event.path)+'</strong><time class="small mono muted" datetime="'+esc(event.timestamp)+'">'+esc(time(event.timestamp))+'</time></div><small class="muted">'+
120
+ esc(event.operation==='entry'?(event.exists?'Directory entry changed':'Removed or renamed'):'Change notification')+
121
+ ' · Unknown actor'+(event.count>1?' · '+fmt(event.count)+' grouped notifications':'')+'</small></li>').join('');
122
+ const mostRecent=received[0]?' · Last observed '+time(received[0].timestamp):'';
123
+ return '<div class="panel-body stack"><p class="small muted">'+esc(liveStream.fileError??(summary+mostRecent))+'</p>'+
124
+ (entries?list(entries,'aria-label="Observed project file changes"'):'<p class="small muted">No eligible changes have been observed.</p>')+
125
+ (known.length?'<details><summary>Project paths · '+fmt(known.length)+(watch?.inventoryLimited?' shown':'')+'</summary>'+list(known.map(item=>'<li class="item small mono">'+esc(item.path)+(item.entry==='directory'?'/':'')+'</li>').join(''))+'</details>':'')+'</div>';
126
+ }
127
+ function liveFilePanel(){
128
+ return '<section class="panel" aria-label="Project file activity"><div class="panel-head"><h2>Project file activity</h2></div><div id="project-file-body">'+liveFileBody()+'</div></section>';
129
+ }
130
+ function updateLiveFilePanel(){
131
+ const region=$('project-file-body');
132
+ if(!region)return;
133
+ const markup=liveFileBody();
134
+ if(region.dataset.markup===markup)return;
135
+ const expanded=region.querySelector('details')?.open;
136
+ const focused=region.querySelector('summary:focus');
137
+ region.dataset.markup=markup;region.innerHTML=markup;
138
+ const details=region.querySelector('details');
139
+ if(details&&expanded)details.open=true;
140
+ if(focused)details?.querySelector('summary')?.focus({preventScroll:true});
141
+ }
142
+ function updateLiveFilePulse(animate=false){
143
+ const label=$('project-file-pulse');
144
+ if(!label)return;
145
+ label.hidden=!liveStream.filePulse;
146
+ label.textContent=liveStream.filePulse?'Observed file change · '+liveStream.filePulse.path:'';
147
+ label.classList.remove('file-fresh');
148
+ if(animate&&!label.hidden)requestAnimationFrame(()=>{if(label.isConnected)label.classList.add('file-fresh');});
149
+ }
150
150
  `;
151
151
  //# sourceMappingURL=brain-hub-live.js.map
@@ -1,20 +1,20 @@
1
- export const BRAIN_HUB_MANAGED_SKILLS = String.raw `
2
- function managedSkillControls(){
3
- if(!local)return '';
4
- const inventory=state.managedSkills;
5
- const listBody=arr(inventory?.skills).length?list(arr(inventory.skills).map(item=>{
6
- const choices=item.pendingAction?[item.pendingAction]:item.state==='enabled'?['disable','remove']:item.state==='disabled'?['enable','remove']:[];
7
- const buttons=choices.map(kind=>action('managed-skill-preview','Preview '+kind,'quiet','data-kind="'+esc(kind)+'" data-id="'+esc(item.id)+'" '+(state.pending?'disabled':''))).join('');
8
- return '<li class="item"><div class="row"><strong>'+esc(item.name)+'</strong>'+chip(item.state,item.state==='enabled'?'green':item.state==='disabled'?'':'amber')+'</div><small class="mono muted">'+esc(item.relativePath)+'</small><p class="small muted">'+esc(arr(item.targets).map(hostName).join(' · '))+'</p>'+(item.reason?'<p class="small amber">'+esc(item.reason)+'</p>':'')+(buttons?'<div class="actions">'+buttons+'</div>':'')+'</li>';
9
- }).join('')):empty('No managed project skills','Skills applied through Project Kit appear here.',view('knowledge','Open Knowledge'));
10
- const plan=state.managedSkillPlan;
11
- const pending=plan?'<div class="panel-body stack"><div class="row"><h3>'+esc('Review '+plan.action)+'</h3>'+action('managed-skill-cancel','Cancel','quiet')+'</div>'+arr(plan.effects).map(effect=>'<p>'+esc(effect)+'</p>').join('')+
12
- list(arr(plan.exactPaths).map(value=>'<li class="item mono small">'+esc(value)+'</li>').join(''))+
13
- arr(plan.conflicts).map(value=>'<p class="small amber">'+esc(value)+'</p>').join('')+'<small class="muted">'+esc(plan.hostRefreshNote)+'</small>'+
14
- (!arr(plan.conflicts).length?'<div class="actions">'+action('managed-skill-apply',plan.action==='remove'?'Remove verified skill':'Apply '+plan.action,plan.action==='remove'?'danger':'primary',state.pending?'disabled':'')+'</div>':'')+'</div>':'';
15
- return panel('Managed project skills',(error('managedSkills','managed skills')||(!inventory?empty('Loading managed skills','Checking Project Kit receipts.'):listBody))+
16
- (inventory?.invalidReceipts?'<p class="panel-body small amber">'+esc(inventory.invalidReceipts)+' ownership receipts could not be verified.</p>':'')+pending+
17
- '<p class="panel-body small muted">Controls apply to skills generated by Project Kit in this workspace. Other skills and supporting files stay untouched.</p>');
18
- }
1
+ export const BRAIN_HUB_MANAGED_SKILLS = String.raw `
2
+ function managedSkillControls(){
3
+ if(!local)return '';
4
+ const inventory=state.managedSkills;
5
+ const listBody=arr(inventory?.skills).length?list(arr(inventory.skills).map(item=>{
6
+ const choices=item.pendingAction?[item.pendingAction]:item.state==='enabled'?['disable','remove']:item.state==='disabled'?['enable','remove']:[];
7
+ const buttons=choices.map(kind=>action('managed-skill-preview','Preview '+kind,'quiet','data-kind="'+esc(kind)+'" data-id="'+esc(item.id)+'" '+(state.pending?'disabled':''))).join('');
8
+ return '<li class="item"><div class="row"><strong>'+esc(item.name)+'</strong>'+chip(item.state,item.state==='enabled'?'green':item.state==='disabled'?'':'amber')+'</div><small class="mono muted">'+esc(item.relativePath)+'</small><p class="small muted">'+esc(arr(item.targets).map(hostName).join(' · '))+'</p>'+(item.reason?'<p class="small amber">'+esc(item.reason)+'</p>':'')+(buttons?'<div class="actions">'+buttons+'</div>':'')+'</li>';
9
+ }).join('')):empty('No managed project skills','Skills applied through Project Kit appear here.',view('knowledge','Open Knowledge'));
10
+ const plan=state.managedSkillPlan;
11
+ const pending=plan?'<div class="panel-body stack"><div class="row"><h3>'+esc('Review '+plan.action)+'</h3>'+action('managed-skill-cancel','Cancel','quiet')+'</div>'+arr(plan.effects).map(effect=>'<p>'+esc(effect)+'</p>').join('')+
12
+ list(arr(plan.exactPaths).map(value=>'<li class="item mono small">'+esc(value)+'</li>').join(''))+
13
+ arr(plan.conflicts).map(value=>'<p class="small amber">'+esc(value)+'</p>').join('')+'<small class="muted">'+esc(plan.hostRefreshNote)+'</small>'+
14
+ (!arr(plan.conflicts).length?'<div class="actions">'+action('managed-skill-apply',plan.action==='remove'?'Remove verified skill':'Apply '+plan.action,plan.action==='remove'?'danger':'primary',state.pending?'disabled':'')+'</div>':'')+'</div>':'';
15
+ return panel('Managed project skills',(error('managedSkills','managed skills')||(!inventory?empty('Loading managed skills','Checking Project Kit receipts.'):listBody))+
16
+ (inventory?.invalidReceipts?'<p class="panel-body small amber">'+esc(inventory.invalidReceipts)+' ownership receipts could not be verified.</p>':'')+pending+
17
+ '<p class="panel-body small muted">Controls apply to skills generated by Project Kit in this workspace. Other skills and supporting files stay untouched.</p>');
18
+ }
19
19
  `;
20
20
  //# sourceMappingURL=brain-hub-managed-skills.js.map