@theihtisham/agent-shadow-brain 7.1.3 → 7.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +125 -90
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/brain/activity-journal.d.ts.map +1 -1
- package/dist/brain/activity-journal.js +2 -1
- package/dist/brain/activity-journal.js.map +1 -1
- package/dist/brain/auto-update.js +1 -1
- package/dist/brain/brain-portability.js +1 -1
- package/dist/brain/client-config.d.ts +19 -0
- package/dist/brain/client-config.d.ts.map +1 -0
- package/dist/brain/client-config.js +40 -0
- package/dist/brain/client-config.js.map +1 -0
- package/dist/brain/client-integrations.d.ts +2 -0
- package/dist/brain/client-integrations.d.ts.map +1 -1
- package/dist/brain/client-integrations.js +8 -27
- package/dist/brain/client-integrations.js.map +1 -1
- package/dist/brain/context-assembly.d.ts +10 -2
- package/dist/brain/context-assembly.d.ts.map +1 -1
- package/dist/brain/context-assembly.js +238 -14
- package/dist/brain/context-assembly.js.map +1 -1
- package/dist/brain/context-request.d.ts +4 -0
- package/dist/brain/context-request.d.ts.map +1 -0
- package/dist/brain/context-request.js +22 -0
- package/dist/brain/context-request.js.map +1 -0
- package/dist/brain/context-retrieval.d.ts +88 -0
- package/dist/brain/context-retrieval.d.ts.map +1 -0
- package/dist/brain/context-retrieval.js +300 -0
- package/dist/brain/context-retrieval.js.map +1 -0
- package/dist/brain/feature-settings.d.ts.map +1 -1
- package/dist/brain/feature-settings.js +2 -1
- package/dist/brain/feature-settings.js.map +1 -1
- package/dist/brain/file-identity.d.ts +4 -0
- package/dist/brain/file-identity.d.ts.map +1 -0
- package/dist/brain/file-identity.js +27 -0
- package/dist/brain/file-identity.js.map +1 -0
- package/dist/brain/global-brain.d.ts +11 -1
- package/dist/brain/global-brain.d.ts.map +1 -1
- package/dist/brain/global-brain.js +58 -6
- package/dist/brain/global-brain.js.map +1 -1
- package/dist/brain/mcp-server.d.ts +9 -0
- package/dist/brain/mcp-server.d.ts.map +1 -1
- package/dist/brain/mcp-server.js +237 -53
- package/dist/brain/mcp-server.js.map +1 -1
- package/dist/brain/mcp-stdio.d.ts.map +1 -1
- package/dist/brain/mcp-stdio.js +10 -4
- package/dist/brain/mcp-stdio.js.map +1 -1
- package/dist/brain/memory-annotations.d.ts.map +1 -1
- package/dist/brain/memory-annotations.js +2 -1
- package/dist/brain/memory-annotations.js.map +1 -1
- package/dist/brain/memory-inspection.d.ts +72 -0
- package/dist/brain/memory-inspection.d.ts.map +1 -0
- package/dist/brain/memory-inspection.js +131 -0
- package/dist/brain/memory-inspection.js.map +1 -0
- package/dist/brain/memory-mcp-content.d.ts +44 -0
- package/dist/brain/memory-mcp-content.d.ts.map +1 -0
- package/dist/brain/memory-mcp-content.js +91 -0
- package/dist/brain/memory-mcp-content.js.map +1 -0
- package/dist/brain/orchestrator.js +1 -1
- package/dist/brain/project-feedback.d.ts +63 -0
- package/dist/brain/project-feedback.d.ts.map +1 -0
- package/dist/brain/project-feedback.js +289 -0
- package/dist/brain/project-feedback.js.map +1 -0
- package/dist/brain/project-hub-contract.d.ts +326 -0
- package/dist/brain/project-hub-contract.d.ts.map +1 -0
- package/dist/brain/project-hub-contract.js +56 -0
- package/dist/brain/project-hub-contract.js.map +1 -0
- package/dist/brain/project-hub-mcp.d.ts +168 -0
- package/dist/brain/project-hub-mcp.d.ts.map +1 -0
- package/dist/brain/project-hub-mcp.js +41 -0
- package/dist/brain/project-hub-mcp.js.map +1 -0
- package/dist/brain/project-hub-pdf-worker.d.ts +13 -0
- package/dist/brain/project-hub-pdf-worker.d.ts.map +1 -0
- package/dist/brain/project-hub-pdf-worker.js +84 -0
- package/dist/brain/project-hub-pdf-worker.js.map +1 -0
- package/dist/brain/project-hub-store.d.ts +38 -0
- package/dist/brain/project-hub-store.d.ts.map +1 -0
- package/dist/brain/project-hub-store.js +189 -0
- package/dist/brain/project-hub-store.js.map +1 -0
- package/dist/brain/project-hub.d.ts +127 -0
- package/dist/brain/project-hub.d.ts.map +1 -0
- package/dist/brain/project-hub.js +381 -0
- package/dist/brain/project-hub.js.map +1 -0
- package/dist/brain/project-kit-inspection.d.ts +28 -0
- package/dist/brain/project-kit-inspection.d.ts.map +1 -0
- package/dist/brain/project-kit-inspection.js +200 -0
- package/dist/brain/project-kit-inspection.js.map +1 -0
- package/dist/brain/project-kit-paths.d.ts +13 -0
- package/dist/brain/project-kit-paths.d.ts.map +1 -0
- package/dist/brain/project-kit-paths.js +141 -0
- package/dist/brain/project-kit-paths.js.map +1 -0
- package/dist/brain/project-kit.d.ts +41 -0
- package/dist/brain/project-kit.d.ts.map +1 -0
- package/dist/brain/project-kit.js +255 -0
- package/dist/brain/project-kit.js.map +1 -0
- package/dist/brain/project-memory.d.ts +38 -0
- package/dist/brain/project-memory.d.ts.map +1 -0
- package/dist/brain/project-memory.js +76 -0
- package/dist/brain/project-memory.js.map +1 -0
- package/dist/brain/subconscious.js +2 -2
- package/dist/brain/subconscious.js.map +1 -1
- package/dist/brain/workflow-skills.d.ts.map +1 -1
- package/dist/brain/workflow-skills.js +3 -2
- package/dist/brain/workflow-skills.js.map +1 -1
- package/dist/cli.js +22 -3
- package/dist/cli.js.map +1 -1
- package/dist/context-cli.d.ts.map +1 -1
- package/dist/context-cli.js +39 -5
- package/dist/context-cli.js.map +1 -1
- package/dist/dashboard/brain-hub-actions.d.ts +2 -0
- package/dist/dashboard/brain-hub-actions.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-actions.js +137 -0
- package/dist/dashboard/brain-hub-actions.js.map +1 -0
- package/dist/dashboard/brain-hub-client.d.ts +2 -0
- package/dist/dashboard/brain-hub-client.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-client.js +335 -0
- package/dist/dashboard/brain-hub-client.js.map +1 -0
- package/dist/dashboard/brain-hub-graph.d.ts +2 -0
- package/dist/dashboard/brain-hub-graph.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-graph.js +176 -0
- package/dist/dashboard/brain-hub-graph.js.map +1 -0
- package/dist/dashboard/brain-hub-html.d.ts +2 -0
- package/dist/dashboard/brain-hub-html.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-html.js +30 -0
- package/dist/dashboard/brain-hub-html.js.map +1 -0
- package/dist/dashboard/brain-hub-project-views.d.ts +2 -0
- package/dist/dashboard/brain-hub-project-views.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-project-views.js +79 -0
- package/dist/dashboard/brain-hub-project-views.js.map +1 -0
- package/dist/dashboard/brain-hub-views.d.ts +2 -0
- package/dist/dashboard/brain-hub-views.d.ts.map +1 -0
- package/dist/dashboard/brain-hub-views.js +150 -0
- package/dist/dashboard/brain-hub-views.js.map +1 -0
- package/dist/dashboard/demo-workspace.d.ts +11 -0
- package/dist/dashboard/demo-workspace.d.ts.map +1 -0
- package/dist/dashboard/demo-workspace.js +178 -0
- package/dist/dashboard/demo-workspace.js.map +1 -0
- package/dist/dashboard/live-workspace-html.d.ts.map +1 -1
- package/dist/dashboard/live-workspace-html.js +177 -28
- package/dist/dashboard/live-workspace-html.js.map +1 -1
- package/dist/dashboard/project-feedback-html.d.ts +5 -0
- package/dist/dashboard/project-feedback-html.d.ts.map +1 -0
- package/dist/dashboard/project-feedback-html.js +216 -0
- package/dist/dashboard/project-feedback-html.js.map +1 -0
- package/dist/dashboard/project-hub-api.d.ts +5 -0
- package/dist/dashboard/project-hub-api.d.ts.map +1 -0
- package/dist/dashboard/project-hub-api.js +121 -0
- package/dist/dashboard/project-hub-api.js.map +1 -0
- package/dist/dashboard/project-kit-html.d.ts +4 -0
- package/dist/dashboard/project-kit-html.d.ts.map +1 -0
- package/dist/dashboard/project-kit-html.js +359 -0
- package/dist/dashboard/project-kit-html.js.map +1 -0
- package/dist/dashboard/project-workspace.d.ts +16 -0
- package/dist/dashboard/project-workspace.d.ts.map +1 -0
- package/dist/dashboard/project-workspace.js +106 -0
- package/dist/dashboard/project-workspace.js.map +1 -0
- package/dist/dashboard/server.d.ts +1 -0
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +15 -4
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/v6-dashboard-html.d.ts +1 -1
- package/dist/dashboard/v6-dashboard-html.d.ts.map +1 -1
- package/dist/dashboard/v6-dashboard-html.js +27 -27
- package/dist/dashboard/workspace-api.d.ts +6 -0
- package/dist/dashboard/workspace-api.d.ts.map +1 -1
- package/dist/dashboard/workspace-api.js +154 -34
- package/dist/dashboard/workspace-api.js.map +1 -1
- package/dist/dashboard/workspace-html.d.ts.map +1 -1
- package/dist/dashboard/workspace-html.js +487 -81
- package/dist/dashboard/workspace-html.js.map +1 -1
- package/dist/dashboard/workspace-status.d.ts +50 -0
- package/dist/dashboard/workspace-status.d.ts.map +1 -0
- package/dist/dashboard/workspace-status.js +22 -0
- package/dist/dashboard/workspace-status.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/integration-cli.d.ts.map +1 -1
- package/dist/integration-cli.js +6 -4
- package/dist/integration-cli.js.map +1 -1
- package/dist/project-cli.d.ts +3 -0
- package/dist/project-cli.d.ts.map +1 -0
- package/dist/project-cli.js +100 -0
- package/dist/project-cli.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/COMPARISON.md +22 -0
- package/docs/COMPONENTS.md +66 -0
- package/docs/CONTEXT_LAB.md +79 -0
- package/docs/FEATURES_AND_LIMITS.md +24 -0
- package/docs/INTEGRATIONS.md +68 -0
- package/docs/LEARNING.md +46 -0
- package/docs/PROJECT_KIT.md +93 -0
- package/docs/QUICKSTART.md +44 -0
- package/docs/README.md +33 -0
- package/docs/ROADMAP-v7.md +147 -0
- package/docs/SHARING.md +13 -0
- package/docs/SHOWCASE.md +87 -0
- package/docs/STATS.md +21 -0
- package/docs/TROUBLESHOOTING.md +42 -0
- package/docs/UPGRADE_PLAN_v7.0.0.md +203 -0
- package/docs/VIRAL-PLAYBOOK.md +259 -0
- package/docs/VISUAL_GUIDE_v7.1.4.md +70 -0
- package/docs/WORKFLOW_INTEGRATION.md +19 -1
- package/docs/WORKSPACE.md +17 -91
- package/docs/assets/7.1.4-collaboration-design-preview.png +0 -0
- package/docs/assets/7.1.4-comparison.png +0 -0
- package/docs/assets/7.1.4-context-lab.png +0 -0
- package/docs/assets/7.1.4-control-room-dense-preview.png +0 -0
- package/docs/assets/7.1.4-control-room-focus-preview.png +0 -0
- package/docs/assets/7.1.4-features.png +0 -0
- package/docs/assets/7.1.4-graph.png +0 -0
- package/docs/assets/7.1.4-hub-control-room.png +0 -0
- package/docs/assets/7.1.4-hub-empty.png +0 -0
- package/docs/assets/7.1.4-hub-knowledge.png +0 -0
- package/docs/assets/7.1.4-hub-learning.png +0 -0
- package/docs/assets/7.1.4-hub-mobile.png +0 -0
- package/docs/assets/7.1.4-hub-public-docs-source.png +0 -0
- package/docs/assets/7.1.4-hub-public-docs.gif +0 -0
- package/docs/assets/7.1.4-hub-public-docs.png +0 -0
- package/docs/assets/7.1.4-hub-setup.png +0 -0
- package/docs/assets/7.1.4-hub-walkthrough.gif +0 -0
- package/docs/assets/7.1.4-integrations.png +0 -0
- package/docs/assets/7.1.4-knowledge-design-preview.png +0 -0
- package/docs/assets/7.1.4-learning-design-preview.png +0 -0
- package/docs/assets/7.1.4-learning.png +0 -0
- package/docs/assets/7.1.4-live.png +0 -0
- package/docs/assets/7.1.4-memory-review.png +0 -0
- package/docs/assets/7.1.4-mobile.png +0 -0
- package/docs/assets/7.1.4-models-design-preview.png +0 -0
- package/docs/assets/7.1.4-outcome-ranking.png +0 -0
- package/docs/assets/7.1.4-overview.png +0 -0
- package/docs/assets/7.1.4-project-kit.png +0 -0
- package/docs/assets/7.1.4-project-skill-preview.png +0 -0
- package/docs/assets/7.1.4-replay.png +0 -0
- package/docs/assets/7.1.4-setup-design-preview.png +0 -0
- package/docs/assets/7.1.4-usage-design-preview.png +0 -0
- package/docs/assets/context-v7.1.3.png +0 -0
- package/docs/assets/features-v7.1.3.png +0 -0
- package/docs/assets/graph-v7.1.3.png +0 -0
- package/docs/assets/integrations-v7.1.3.png +0 -0
- package/docs/assets/live-v7.1.4.gif +0 -0
- package/docs/evaluation/CONTEXT_EVALUATION_v7.1.4.json +1818 -0
- package/docs/evaluation/CONTEXT_EVALUATION_v7.1.4.md +36 -0
- package/docs/launch/COMPONENT_MAP_v7.1.4.md +307 -0
- package/docs/launch/PROJECT_KIT_PLAN_v7.1.4.md +110 -0
- package/docs/launch/PROJECT_LEARNING_PLAN_v7.1.4.md +63 -0
- package/docs/launch/RELEASE_NOTES_v7.1.4.md +30 -0
- package/docs/launch/RESEARCH_AND_PLAN_v7.1.4.md +255 -0
- package/package.json +25 -7
- package/skills/shadow-research/SKILL.md +2 -0
- package/skills/shadow-workflow/SKILL.md +6 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
export const BRAIN_HUB_GRAPH = String.raw `
|
|
2
|
+
const tones={project:'124,233,232',memory:'172,199,255',agent:'234,172,249',measured:'124,233,232',reported:'250,208,140'};
|
|
3
|
+
let graphSurface=null;
|
|
4
|
+
function rand(seed){return ()=>{seed=(Math.imul(seed,1664525)+1013904223)>>>0;return seed/4294967296;};}
|
|
5
|
+
function hash(id){let value=2166136261;for(const char of id)value=Math.imul(value^char.charCodeAt(0),16777619);return value>>>0;}
|
|
6
|
+
function mountGraph(){
|
|
7
|
+
const canvas=$('brain-canvas'),stage=$('brain-stage');
|
|
8
|
+
if(!canvas||canvas.hidden||!stage)return;
|
|
9
|
+
const ctx=canvas.getContext('2d');
|
|
10
|
+
if(!ctx)return;
|
|
11
|
+
const surface={canvas,stage,ctx,width:0,height:0,raf:0,observer:null,points:new Map(),edges:[],snapshot:undefined,counts:{}};
|
|
12
|
+
graphSurface=surface;
|
|
13
|
+
surface.observer=new ResizeObserver(()=>resizeGraph(surface));
|
|
14
|
+
surface.observer.observe(stage);
|
|
15
|
+
resizeGraph(surface);
|
|
16
|
+
function hit(event){
|
|
17
|
+
const box=canvas.getBoundingClientRect();
|
|
18
|
+
const x=event.clientX-box.left,y=event.clientY-box.top;
|
|
19
|
+
let best=null,distance=16;
|
|
20
|
+
for(const point of surface.points.values()){
|
|
21
|
+
const d=Math.hypot(x-point.x,y-point.y);
|
|
22
|
+
if(d<distance){best=point;distance=d;}
|
|
23
|
+
}
|
|
24
|
+
return best;
|
|
25
|
+
}
|
|
26
|
+
canvas.addEventListener('pointermove',event=>{
|
|
27
|
+
const point=hit(event);
|
|
28
|
+
canvas.style.cursor=point?'pointer':'default';
|
|
29
|
+
const caption=$('node-caption');
|
|
30
|
+
if(caption&&point){caption.hidden=false;caption.textContent=point.kind==='agent'?hostName(point.label):point.label;}
|
|
31
|
+
else syncGraphControls();
|
|
32
|
+
});
|
|
33
|
+
canvas.addEventListener('pointerleave',syncGraphControls);
|
|
34
|
+
canvas.addEventListener('click',event=>{const point=hit(event);if(point)void chooseMemory(point.id);});
|
|
35
|
+
}
|
|
36
|
+
function unmountGraph(){
|
|
37
|
+
if(!graphSurface)return;
|
|
38
|
+
graphSurface.observer.disconnect();cancelAnimationFrame(graphSurface.raf);graphSurface=null;
|
|
39
|
+
}
|
|
40
|
+
function stroke(ctx,rgb,alpha,width){ctx.strokeStyle='rgba('+rgb+','+alpha+')';ctx.lineWidth=width;ctx.stroke();}
|
|
41
|
+
function dot(ctx,x,y,r,rgb,alpha){ctx.beginPath();ctx.arc(x,y,r,0,Math.PI*2);ctx.fillStyle='rgba('+rgb+','+alpha+')';ctx.fill();}
|
|
42
|
+
function resizeGraph(surface){
|
|
43
|
+
if(graphSurface!==surface)return;
|
|
44
|
+
const {stage,canvas,ctx}=surface;
|
|
45
|
+
const size=stage.getBoundingClientRect(),dpr=Math.min(devicePixelRatio,1.75);
|
|
46
|
+
if(!size.width||!size.height)return;
|
|
47
|
+
surface.width=size.width;surface.height=size.height;surface.snapshot=undefined;
|
|
48
|
+
canvas.width=Math.round(size.width*dpr);
|
|
49
|
+
canvas.height=Math.round(size.height*dpr);
|
|
50
|
+
ctx.setTransform(dpr,0,0,dpr,0,0);
|
|
51
|
+
drawGraph();
|
|
52
|
+
}
|
|
53
|
+
function brainFrame(width,height){return {x:width*.50,y:height*.51,rx:Math.min(width*.318,height*.76),ry:height*.42};}
|
|
54
|
+
function drawOutline(ctx,{x,y,rx,ry}){
|
|
55
|
+
ctx.save();ctx.translate(x,y);ctx.rotate(-.19);ctx.scale(rx,ry);
|
|
56
|
+
ctx.beginPath();ctx.moveTo(0,-.82);
|
|
57
|
+
ctx.bezierCurveTo(-.26,-1.12,-.68,-.95,-.78,-.65);ctx.bezierCurveTo(-1.07,-.56,-1.14,-.11,-.97,.09);
|
|
58
|
+
ctx.bezierCurveTo(-1.09,.45,-.80,.80,-.57,.80);ctx.bezierCurveTo(-.39,1.03,-.11,.96,0,.83);
|
|
59
|
+
ctx.bezierCurveTo(.14,.97,.42,.94,.56,.76);ctx.bezierCurveTo(.89,.77,1.10,.48,.99,.16);
|
|
60
|
+
ctx.bezierCurveTo(1.15,-.09,1.07,-.44,.85,-.57);ctx.bezierCurveTo(.76,-.87,.31,-1.06,0,-.82);ctx.closePath();
|
|
61
|
+
ctx.restore();stroke(ctx,'119,157,206',.19,1);
|
|
62
|
+
}
|
|
63
|
+
function graphPoints(width,height){
|
|
64
|
+
const nodes=arr(state.graph?.nodes),anchors=nodes.filter(node=>node.kind!=='memory');
|
|
65
|
+
const memories=nodes.filter(node=>node.kind==='memory').sort((a,b)=>hash(a.id)-hash(b.id));
|
|
66
|
+
const {x:cx,y:cy,rx,ry}=brainFrame(width,height);
|
|
67
|
+
const points=new Map();
|
|
68
|
+
function point(node,x,y,depth=1){points.set(node.id,{...node,x,y,depth});}
|
|
69
|
+
for(const kind of ['project','agent']){
|
|
70
|
+
const subset=anchors.filter(node=>node.kind===kind);
|
|
71
|
+
subset.forEach((node,i)=>{
|
|
72
|
+
const t=(i+1)/(subset.length+1),sign=kind==='project'?-1:1;
|
|
73
|
+
point(node,cx+sign*(rx*1.01+8*Math.sin(i*2.4)),height*.12+height*.75*t);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
const golden=Math.PI*(3-Math.sqrt(5));
|
|
77
|
+
memories.forEach((node,i)=>{
|
|
78
|
+
const random=rand(hash(node.id)),side=i%2===0?-1:1;
|
|
79
|
+
const count=Math.ceil((memories.length-(i%2))/2),ordinal=Math.floor(i/2);
|
|
80
|
+
const angle=ordinal*golden+(side<0?.55:1.71)+(random()-.5)*.10;
|
|
81
|
+
const r=Math.sqrt((ordinal+.55)/count);
|
|
82
|
+
const x=side*.47+Math.cos(angle)*r*.45,y=Math.sin(angle)*r*.88;
|
|
83
|
+
const projectedX=x*.982+y*.19,projectedY=y*.982-x*.19;
|
|
84
|
+
point(node,cx+projectedX*rx,cy+projectedY*ry,.56+random()*.44);
|
|
85
|
+
});
|
|
86
|
+
return points;
|
|
87
|
+
}
|
|
88
|
+
function displayEvent(){return state.events.find(event=>event.id===state.replayId)??state.events.at(-1);}
|
|
89
|
+
function graphEventPath(event,surface){
|
|
90
|
+
const {width,height,points}=surface;
|
|
91
|
+
const from=points.get('project:'+event.projectId),end=points.get('agent:'+event.agent);
|
|
92
|
+
if(!from||!end)return null;
|
|
93
|
+
const reverse=event.kind==='tool-start'||event.kind==='session-start';
|
|
94
|
+
return reverse?[end,{x:width*.51,y:height*.18},{x:width*.52,y:height*.69},from]:
|
|
95
|
+
[from,{x:width*.47,y:height*.73},{x:width*.49,y:height*.18},end];
|
|
96
|
+
}
|
|
97
|
+
function labelPoint(ctx,point,label,side,color,width,alpha){
|
|
98
|
+
ctx.font='600 10.5px system-ui,sans-serif';
|
|
99
|
+
const limit=Math.min(126,width*.20);
|
|
100
|
+
while(ctx.measureText(label).width>limit&&label.length>1)label=label.slice(0,label.endsWith('…')?-2:-1)+'…';
|
|
101
|
+
const pad=6,labelWidth=ctx.measureText(label).width+2*pad;
|
|
102
|
+
const x=Math.max(3,Math.min(width-labelWidth-3,side<0?point.x-12-labelWidth:point.x+12)),y=point.y-9;
|
|
103
|
+
ctx.globalAlpha=alpha;ctx.fillStyle='#111e31';ctx.beginPath();ctx.roundRect(x,y,labelWidth,18,3);ctx.fill();stroke(ctx,color,.43,.7);
|
|
104
|
+
ctx.fillStyle='#ddefff';ctx.textAlign='left';ctx.textBaseline='middle';ctx.fillText(label,x+pad,y+9);ctx.globalAlpha=1;
|
|
105
|
+
}
|
|
106
|
+
function drawGraph(){
|
|
107
|
+
const surface=graphSurface;
|
|
108
|
+
if(!surface||!surface.width)return;
|
|
109
|
+
if(surface.raf){cancelAnimationFrame(surface.raf);surface.raf=0;}
|
|
110
|
+
const {ctx,width,height,canvas}=surface;
|
|
111
|
+
if(surface.snapshot!==state.graph){
|
|
112
|
+
surface.snapshot=state.graph;
|
|
113
|
+
surface.points=graphPoints(width,height);
|
|
114
|
+
surface.edges=arr(state.graph?.edges).filter(edge=>surface.points.has(edge.source)&&surface.points.has(edge.target));
|
|
115
|
+
surface.counts={};
|
|
116
|
+
for(const point of surface.points.values())surface.counts[point.kind]=(surface.counts[point.kind]??0)+1;
|
|
117
|
+
}
|
|
118
|
+
const {points,edges}=surface;
|
|
119
|
+
const current=state.focus?state.picked:null;
|
|
120
|
+
const connected=new Set(current?[current]:[]);
|
|
121
|
+
if(current)for(const edge of edges){
|
|
122
|
+
if(edge.source===current)connected.add(edge.target);
|
|
123
|
+
if(edge.target===current)connected.add(edge.source);
|
|
124
|
+
}
|
|
125
|
+
ctx.clearRect(0,0,width,height);
|
|
126
|
+
if(points.size)drawOutline(ctx,brainFrame(width,height));
|
|
127
|
+
for(const edge of edges){
|
|
128
|
+
const a=points.get(edge.source),b=points.get(edge.target);
|
|
129
|
+
const active=current&&(edge.source===current||edge.target===current);
|
|
130
|
+
ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.quadraticCurveTo((a.x+b.x)/2,(a.y+b.y)/2+(a.x-b.x)*.15,b.x,b.y);
|
|
131
|
+
const color=edge.kind==='belongs-to'?tones.project:edge.kind==='recorded-by'?tones.agent:'241,200,138';
|
|
132
|
+
if(active){stroke(ctx,color,.22,4.5);stroke(ctx,color,.96,1.45);}
|
|
133
|
+
else stroke(ctx,color,current?.08:edge.kind==='recorded-by'?.46:.52,.84);
|
|
134
|
+
}
|
|
135
|
+
for(const point of points.values()){
|
|
136
|
+
const active=point.id===current,color=tones[point.kind]??tones.memory;
|
|
137
|
+
const alpha=(current&&!connected.has(point.id)?.31:1)*point.depth;
|
|
138
|
+
const r=point.kind==='memory'?(points.size>70?2.8:4.1):5.2;
|
|
139
|
+
dot(ctx,point.x,point.y,active?15:r+5,color,.13*alpha);
|
|
140
|
+
dot(ctx,point.x,point.y,active?4.5:r,color,.92*alpha);
|
|
141
|
+
if(active||point.kind!=='memory'){
|
|
142
|
+
ctx.beginPath();ctx.arc(point.x,point.y,active?10:8,0,Math.PI*2);stroke(ctx,color,.68*alpha,.9);
|
|
143
|
+
}
|
|
144
|
+
if(point.kind!=='memory'&&width>510&&(active||surface.counts[point.kind]<=11))labelPoint(ctx,point,point.kind==='agent'?hostName(point.label):point.label,point.kind==='project'?-1:1,color,width,alpha);
|
|
145
|
+
}
|
|
146
|
+
const age=performance.now()-state.motionStarted;
|
|
147
|
+
const animate=!document.hidden&&!reduced.matches&&!state.motionPaused&&!state.replayId&&state.live&&state.connection==='reachable'&&state.pulseIds.length&&age<1500;
|
|
148
|
+
const traceEvents=current?[]:animate?state.events.filter(event=>state.pulseIds.includes(event.id)):
|
|
149
|
+
state.replayId?[displayEvent()].filter(Boolean):[];
|
|
150
|
+
const routes=traceEvents.map(event=>({event,path:graphEventPath(event,surface)})).filter(route=>route.path);
|
|
151
|
+
routes.forEach(({event,path},index)=>{
|
|
152
|
+
const [a,b,c,d]=path,color=tones[event.source]??tones.reported;
|
|
153
|
+
ctx.beginPath();ctx.moveTo(a.x,a.y);ctx.bezierCurveTo(b.x,b.y,c.x,c.y,d.x,d.y);
|
|
154
|
+
stroke(ctx,color,.19,4.2);stroke(ctx,color,.81,1.25);
|
|
155
|
+
const t=animate?Math.max(0,Math.min(1,age/1310-index*.055)):.58,u=1-t;
|
|
156
|
+
const x=u**3*a.x+3*u*u*t*b.x+3*u*t*t*c.x+t**3*d.x;
|
|
157
|
+
const y=u**3*a.y+3*u*u*t*b.y+3*u*t*t*c.y+t**3*d.y;
|
|
158
|
+
dot(ctx,x,y,8,color,.19);dot(ctx,x,y,4,color,.52);dot(ctx,x,y,1.9,'237,255,255',1);
|
|
159
|
+
});
|
|
160
|
+
const graphEvent=$('graph-event');
|
|
161
|
+
if(graphEvent){
|
|
162
|
+
const event=traceEvents.at(-1),text=event?evidence(event)+' · '+hostName(event.agent)+(routes.length?'':' · journal only'):'';
|
|
163
|
+
if(graphEvent.textContent!==text)graphEvent.textContent=text;
|
|
164
|
+
}
|
|
165
|
+
canvas.dataset.nodes=String(points.size);canvas.dataset.edges=String(edges.length);
|
|
166
|
+
canvas.dataset.pulses=String(routes.length);canvas.dataset.frame=animate&&routes.length?String(Math.round(age)):'static';
|
|
167
|
+
if(animate&&routes.length)surface.raf=requestAnimationFrame(drawGraph);
|
|
168
|
+
}
|
|
169
|
+
function syncGraphControls(){
|
|
170
|
+
const label=$('node-caption'),point=arr(state.graph?.nodes).find(node=>node.id===state.picked);
|
|
171
|
+
if(label){label.hidden=!state.focus||!point||state.listing;label.textContent=point?.label??'';}
|
|
172
|
+
const clear=$('clear-focus');if(clear)clear.hidden=!state.focus;
|
|
173
|
+
$('brain-stage')?.querySelectorAll('[data-node]').forEach(button=>button.setAttribute('aria-pressed',String(button.dataset.node===state.picked&&state.focus)));
|
|
174
|
+
}
|
|
175
|
+
`;
|
|
176
|
+
//# sourceMappingURL=brain-hub-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-hub-graph.js","sourceRoot":"","sources":["../../src/dashboard/brain-hub-graph.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8KxC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-hub-html.d.ts","sourceRoot":"","sources":["../../src/dashboard/brain-hub-html.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,QAyBH,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BRAIN_HUB_CLIENT } from './brain-hub-client.js';
|
|
2
|
+
import { BRAIN_HUB_GRAPH } from './brain-hub-graph.js';
|
|
3
|
+
import { BRAIN_HUB_VIEWS } from './brain-hub-views.js';
|
|
4
|
+
export const BRAIN_HUB_HTML = String.raw `<!doctype html>
|
|
5
|
+
<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>
|
|
6
|
+
<style>
|
|
7
|
+
: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)}
|
|
8
|
+
*,*::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}
|
|
9
|
+
.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}
|
|
10
|
+
.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}
|
|
11
|
+
.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)}
|
|
12
|
+
.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}
|
|
13
|
+
@media(min-width:981px){.control-grid{grid-template-rows:429px}.graph-stage{min-height:0}}
|
|
14
|
+
@media(max-width:1200px){.control-grid{grid-template-columns:153px minmax(0,1fr) 235px}.frame{padding-inline:14px}}
|
|
15
|
+
@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}}
|
|
16
|
+
@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}}
|
|
17
|
+
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}
|
|
18
|
+
</style></head><body>
|
|
19
|
+
<a class="btn skip" href="#main">Skip to content</a>
|
|
20
|
+
<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>
|
|
21
|
+
<nav class="nav" id="nav" aria-label="Brain workspace"></nav>
|
|
22
|
+
<p class="notice" id="notice" role="status"></p>
|
|
23
|
+
<main id="main" tabindex="-1"><div class="empty"><strong>Opening the workspace</strong><p>Loading the local memory and activity stores.</p></div></main>
|
|
24
|
+
<footer class="footer"><span id="scope-note"></span><span><a href="/workspace">Classic workspace</a> · <a href="/live">Activity diagnostics</a></span></footer>
|
|
25
|
+
</div>
|
|
26
|
+
<script>'use strict';
|
|
27
|
+
` + BRAIN_HUB_CLIENT + BRAIN_HUB_GRAPH + BRAIN_HUB_VIEWS + String.raw `
|
|
28
|
+
start();
|
|
29
|
+
</script></body></html>`;
|
|
30
|
+
//# sourceMappingURL=brain-hub-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-hub-html.js","sourceRoot":"","sources":["../../src/dashboard/brain-hub-html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;CAuBvC,GAAG,gBAAgB,GAAG,eAAe,GAAG,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;wBAE7C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-hub-project-views.d.ts","sourceRoot":"","sources":["../../src/dashboard/brain-hub-project-views.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,QA6EnC,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export const BRAIN_HUB_PROJECT_VIEWS = String.raw `
|
|
2
|
+
function projectRequired(title,description){
|
|
3
|
+
return heading(title,description)+panel('Project workspace required','<div class="panel-body stack"><p class="muted">Open a project-local workspace from its directory to access its documents, work room and learning history.</p><pre>shadow-brain project workspace .</pre>'+action('copy-project-command','Copy launch command')+'</div>');
|
|
4
|
+
}
|
|
5
|
+
function projectHubError(title){
|
|
6
|
+
return panel(title,error('hub','project hub')||empty('Reading project hub','The project-local store is loading.'));
|
|
7
|
+
}
|
|
8
|
+
function skillPanel(){
|
|
9
|
+
const input=state.skillInput??{};
|
|
10
|
+
const form='<form class="form" data-form="skill"><label>Project requirement<textarea name="requirement" rows="3" maxlength="3000" required>'+esc(input.requirement)+'</textarea></label><div class="form-grid"><label>Host target<select name="target">'+['codex','claude-code','opencode','deepseek-harness','portable'].map(target=>'<option value="'+target+'" '+(target===input.target?'selected':'')+'>'+esc(hostName(target))+'</option>').join('')+'</select></label><label>Skill name<input name="name" maxlength="64" value="'+esc(input.name)+'" placeholder="optional-skill-name"></label></div><label>Approved project knowledge<textarea name="knowledge" rows="2" maxlength="4000">'+esc(input.knowledge)+'</textarea></label>'+submit('Preview project skill')+'</form>';
|
|
11
|
+
const plan=state.skill;
|
|
12
|
+
const files=arr(plan?.files);
|
|
13
|
+
const result=plan?'<div class="receipt"><div class="row"><strong>'+esc(plan.name??'Applied skill')+'</strong>'+chip(plan.applied?'Applied':'Preview ready',plan.applied?'green':'cyan')+'</div>'+files.map(file=>'<details><summary>'+esc(file.relativePath)+' · '+esc(file.status)+'</summary>'+(file.content?'<pre>'+esc(file.content)+'</pre>':'')+(file.reason?'<p class="small amber">'+esc(file.reason)+'</p>':'')+'</details>').join('')+arr(plan.warnings).map(warning=>'<p class="small amber">'+esc(warning)+'</p>').join('')+(!plan.applied&&!files.some(file=>file.status==='conflict')?action('apply-skill','Apply reviewed plan','primary'):'')+'</div>':'';
|
|
14
|
+
return panel('Project skill','<div class="panel-body stack">'+form+result+'</div>');
|
|
15
|
+
}
|
|
16
|
+
function docPageMarkup(){
|
|
17
|
+
const record=state.documents;
|
|
18
|
+
if(!record)return empty('Select a document','Choose an uploaded PDF to see its extracted page text and citation.');
|
|
19
|
+
const doc=record.document,pages=arr(record.pages);
|
|
20
|
+
const page=pages.find(item=>item.page===state.docPage);
|
|
21
|
+
const prev=pages.findLast(item=>item.page<state.docPage),next=pages.find(item=>item.page>state.docPage);
|
|
22
|
+
return '<div class="panel-body stack"><div class="row"><div><h3>'+esc(doc.name)+'</h3><p class="small muted">'+fmt(doc.pageCount)+' pages · '+esc(doc.parser??'Parser unavailable')+'</p></div>'+chip(doc.status,doc.status==='ready'?'green':'amber')+'</div>'+
|
|
23
|
+
(doc.error?'<p class="small amber">'+esc(doc.error)+'</p>':'')+'<details><summary>Document fingerprint</summary><pre>'+esc(doc.sha256)+'</pre></details>'+
|
|
24
|
+
(page?'<div class="actions">'+btn('Previous page','data-page="'+(prev?.page??'')+'" '+(prev?'':'disabled'))+btn('Next page','data-page="'+(next?.page??'')+'" '+(next?'':'disabled'))+chip('Page '+page.page)+chip(page.status,page.status==='approved'?'green':'amber')+'</div>'+(page.truncated?'<p class="small amber">Extraction reached the text limit. Approval stores only the excerpt shown here.</p>':'')+'<pre>'+esc(page.text||'This page has no extracted text. OCR is unavailable in this workspace.')+'</pre>'+(page.citation?'<p class="small mono cyan">'+esc(typeof page.citation==='string'?page.citation:JSON.stringify(page.citation))+'</p>':'')+
|
|
25
|
+
(page.status==='pending'&&page.text?'<div class="actions">'+action('review-page','Approve page','primary','data-decision="approve"')+action('review-page','Reject page','','data-decision="reject"')+'</div>':'')+(page.memoryId?action('open-memory','Inspect approved memory','','data-memory="'+esc(page.memoryId)+'"'):''):'')+'</div>';
|
|
26
|
+
}
|
|
27
|
+
function knowledgePage(){
|
|
28
|
+
if(!local)return projectRequired('Knowledge intake','Review sources and commit project-local knowledge.');
|
|
29
|
+
const docs=arr(state.hub?.documents);
|
|
30
|
+
const queue=docs.length?list(docs.map(doc=>'<li><button class="entry" type="button" data-document="'+esc(doc.id)+'" aria-pressed="'+(doc.id===state.documents?.document?.id)+'"><strong>'+esc(doc.name)+'</strong><small class="muted">'+esc(doc.status)+' · '+fmt(doc.pageCount)+' pages</small></button></li>').join(''),'class="list section-list"'):empty('No PDFs uploaded','Choose a local PDF to extract and review its pages.');
|
|
31
|
+
const pdfEnabled=state.server?.capabilities?.pdf!==false;
|
|
32
|
+
const pdf=state.hub?queue+(pdfEnabled?'<div class="panel-body"><form class="form" data-form="upload"><label>PDF source<input name="pdf" type="file" accept="application/pdf,.pdf" required></label><p class="small muted">'+(state.hub.limits?.pdfBytes?fmt(state.hub.limits.pdfBytes/1024)+' KiB maximum. ':'')+'Review extracted text before adding it to memory.</p>'+submit('Upload PDF')+'</form></div>':''):error('hub','document queue')||empty('Loading document queue','Reading project-local document records.');
|
|
33
|
+
const knowledge='<div class="panel-body"><form class="form" data-form="knowledge"><label>Title<input name="title" maxlength="130" required></label><label>Knowledge<textarea name="content" rows="4" maxlength="6000" required></textarea></label><label>Source reference<input name="source" maxlength="500" placeholder="Project-relative source or citation"></label>'+submit('Save project knowledge')+'</form></div>';
|
|
34
|
+
const profile=state.profile;
|
|
35
|
+
const project=profile?'<div class="panel-body stack"><dl class="facts">'+fact('Stack',arr(profile.stack).join(' · ')||'No markers found')+fact('Package managers',arr(profile.packageManagers).join(' · ')||'No markers found')+'</dl>'+arr(profile.warnings).map(text=>'<p class="small amber">'+esc(text)+'</p>').join('')+(arr(profile.evidence).length?'<details><summary>Observed project evidence</summary>'+list(profile.evidence.map(item=>'<li class="item mono small">'+esc(item.path)+' · '+esc(arr(item.signals).join(', '))+'</li>').join(''))+'</details>':'')+'</div>':error('profile','project profile')||empty('Reading project profile','Inspecting bounded project-local markers.');
|
|
36
|
+
return heading('Knowledge intake','Upload source PDFs, approve cited pages, or save project knowledge.',view('context','Build context pack'))+'<div class="two">'+panel('Source queue',pdf)+panel('Page citation review',docPageMarkup())+'</div><div class="two" style="margin-top:10px"><div class="stack">'+panel('Add knowledge',knowledge)+panel('Observed project profile',project)+'</div>'+skillPanel()+'</div>';
|
|
37
|
+
}
|
|
38
|
+
function roomAction(kind,label,id,extra=''){return btn(label,'data-room-action="'+kind+'" data-id="'+esc(id)+'" '+extra);}
|
|
39
|
+
function operator(actor){return actor?.kind==='user'&&actor.id==='Operator';}
|
|
40
|
+
function roomPage(){
|
|
41
|
+
if(!local)return projectRequired('Shared work room','Exchange proposals, tasks, artifacts and outcomes in a project-local room.');
|
|
42
|
+
if(!state.hub)return heading('Shared work room','Coordinate proposals, artifacts and outcomes.')+projectHubError('Rooms');
|
|
43
|
+
const rooms=arr(state.hub.rooms),current=state.room;
|
|
44
|
+
const roster=(rooms.length?list(rooms.map(room=>'<li><button class="entry" type="button" data-room="'+esc(room.id)+'" aria-pressed="'+(room.id===current?.room?.id)+'"><strong>'+esc(room.goal)+'</strong><small class="muted">'+esc(isoTime(room.createdAt))+'</small></button></li>').join(''),'class="list section-list"'):empty('No work rooms','Create a room for a shared project goal.'))+
|
|
45
|
+
'<div class="panel-body"><form class="form" data-form="room"><label>Room goal<textarea name="goal" rows="2" maxlength="400" required></textarea></label>'+submit('Create room')+'</form></div>';
|
|
46
|
+
if(!current)return heading('Shared work room','Coordinate proposals, artifacts and outcomes.')+'<div class="two">'+panel('Project rooms',roster)+panel('Discussion',empty('No room selected','Choose a project room or create a room for this task.'))+'</div>';
|
|
47
|
+
const messages=arr(current.messages);
|
|
48
|
+
const messageForm='<div class="panel-body"><form class="form" data-form="message"><div class="form-grid"><label>Message type<select name="type">'+['proposal','critique','question','answer','decision','handoff','status'].map(type=>'<option>'+type+'</option>').join('')+'</select></label><label>Reply to<select name="replyTo"><option value="">No reply</option>'+messages.map(message=>'<option value="'+esc(message.id)+'">'+esc(message.type+' · '+message.text.slice(0,60))+'</option>').join('')+'</select></label></div><label>Message<textarea name="text" rows="2" maxlength="3000" required></textarea></label>'+submit('Post message')+'</form></div>';
|
|
49
|
+
const discussion='<div class="panel-body"><h3>'+esc(current.room.goal)+'</h3><p class="small muted mono">'+esc(current.room.id)+'</p></div>'+list(messages.map(message=>'<li class="item"><div class="row"><span>'+chip(message.type,'cyan')+' <strong>'+esc(hostName(message.author?.id))+'</strong></span><time class="small muted mono">'+esc(time(message.createdAt))+'</time></div><p>'+esc(message.text)+'</p>'+(message.replyTo?'<small class="muted">Reply to '+esc(message.replyTo)+'</small>':'')+(!operator(message.author)?'<div class="actions">'+roomAction('ack-message','Acknowledge message',message.id)+'</div>':'')+'</li>').join(''),'class="list section-list"')+messageForm;
|
|
50
|
+
const tasks=arr(current.tasks), artifacts=arr(current.artifacts),outcomes=arr(current.outcomes);
|
|
51
|
+
const taskList=list(tasks.map(task=>'<li class="item"><div class="row"><strong>'+esc(task.title)+'</strong>'+chip(task.status,task.status==='completed'?'green':'')+'</div><small class="muted">'+esc(task.owner?'Owner '+hostName(task.owner.id)+(task.leaseUntil?' · lease '+isoTime(task.leaseUntil):''):'Unclaimed')+'</small><div class="actions">'+(task.status==='open'?roomAction('claim','Claim',task.id,'data-revision="'+esc(task.revision)+'"'):task.status==='claimed'&&operator(task.owner)?roomAction('renew','Renew',task.id,'data-revision="'+esc(task.revision)+'"')+roomAction('release','Release',task.id,'data-revision="'+esc(task.revision)+'"'):'')+'</div></li>').join(''));
|
|
52
|
+
const taskForm='<div class="panel-body"><form class="form" data-form="task"><label>Task title<input name="title" maxlength="240" required></label>'+submit('Add task')+'</form></div>';
|
|
53
|
+
const artifactsMarkup=artifacts.length?list(artifacts.map(item=>'<li class="item"><div class="row"><strong>'+esc(item.path)+'</strong>'+chip(item.status)+'</div><small class="muted mono">'+esc(item.sha256)+'</small><div class="actions"><a class="btn" href="/api/workspace/hub/rooms/'+encodeURIComponent(current.room.id)+'/artifacts/'+encodeURIComponent(item.id)+'">Download</a>'+(item.status==='submitted'&&tasks.some(task=>task.id===item.taskId&&task.artifactId===item.id&&task.status==='claimed')?roomAction('accept','Accept artifact',item.id):'')+(!operator(item.author)?roomAction('ack-artifact','Acknowledge',item.id,'data-sha256="'+esc(item.sha256)+'"'):'')+'</div></li>').join('')):'';
|
|
54
|
+
const taskOptions=tasks.map(item=>'<option value="'+esc(item.id)+'">'+esc(item.title)+'</option>').join('');
|
|
55
|
+
const claimed=tasks.filter(item=>item.status==='claimed'&&operator(item.owner));
|
|
56
|
+
const artifactForm=claimed.length?'<div class="panel-body"><form class="form" data-form="artifact"><label>Claimed task<select name="taskId">'+claimed.map(item=>'<option value="'+esc(item.id)+'">'+esc(item.title)+'</option>').join('')+'</select></label><label>Project-relative artifact path<input name="path" maxlength="400" required></label>'+submit('Attach artifact')+'</form></div>':'';
|
|
57
|
+
const outcomeForm=tasks.length?'<div class="panel-body"><form class="form" data-form="outcome"><label>Task<select name="taskId">'+taskOptions+'</select></label><label>Artifact<select name="artifactId"><option value="">No artifact</option>'+artifacts.map(item=>'<option value="'+esc(item.id)+'">'+esc(item.path)+'</option>').join('')+'</select></label><label>Result<select name="result"><option>pass</option><option>fail</option><option>partial</option></select></label><label>Acceptance check<input name="check" maxlength="240" required></label><label>Evidence<textarea name="evidence" maxlength="3000" rows="2" required></textarea></label>'+submit('Record outcome')+'</form></div>':'';
|
|
58
|
+
const outcomeRows=list(outcomes.map(item=>'<li class="item"><div class="row"><strong>'+esc(item.check)+'</strong>'+chip(item.result,item.result==='pass'?'green':'amber')+'</div><p class="small muted">'+esc(item.evidence)+'</p><small class="muted">'+esc(item.provenance)+'</small>'+btn('Propose lesson','data-lesson-from="'+esc(item.id)+'"','quiet')+'</li>').join(''));
|
|
59
|
+
const acks=arr(current.acknowledgements);
|
|
60
|
+
const right='<div class="panel-head"><h2>Tasks</h2>'+chip(tasks.length)+'</div>'+taskList+taskForm+'<div class="panel-head"><h2>Artifacts and outcomes</h2>'+chip(artifacts.length+outcomes.length)+'</div>'+artifactsMarkup+artifactForm+outcomeRows+outcomeForm+
|
|
61
|
+
(acks.length?'<details class="panel-body"><summary>'+acks.length+' acknowledgements</summary>'+list(acks.map(item=>'<li class="item small">'+esc(hostName(item.author?.id))+' · '+esc(item.targetType)+' · <span class="mono">'+esc(item.targetId)+'</span></li>').join(''))+'</details>':'');
|
|
62
|
+
return heading('Shared work room','Coordinate proposals, artifacts and outcomes.',action('refresh-room','Refresh room'))+'<div class="three">'+panel('Project rooms',roster)+panel('Discussion',discussion,chip(messages.length))+'<section class="panel">'+right+'</section></div>';
|
|
63
|
+
}
|
|
64
|
+
function lessonAction(kind,label,id){return btn(label,'data-lesson-action="'+kind+'" data-id="'+esc(id)+'"');}
|
|
65
|
+
function learningPage(){
|
|
66
|
+
if(!local)return projectRequired('Memory and learning','Evaluate source-backed lessons and review their recorded outcomes.');
|
|
67
|
+
if(!state.hub)return heading('Memory and learning','Evaluate project lessons against observed outcomes.')+projectHubError('Lessons');
|
|
68
|
+
const lessons=arr(state.hub.lessons);
|
|
69
|
+
const outcomes=arr(state.room?.outcomes);
|
|
70
|
+
const lessonForm=outcomes.length?'<div class="panel-body"><form class="form" data-form="lesson"><label>Recorded outcome<select name="outcomeId">'+outcomes.map(item=>'<option value="'+esc(item.id)+'" '+(state.lessonFrom===item.id?'selected':'')+'>'+esc(item.check)+'</option>').join('')+'</select></label><label>Lesson title<input name="title" maxlength="150" required></label><label>Lesson and scope<textarea name="text" rows="3" maxlength="4000" required></textarea></label>'+submit('Record lesson candidate')+'</form></div>':empty('No room outcome selected','Open a work room with a recorded outcome to propose a lesson.',view('room','Open collaboration'));
|
|
71
|
+
const rows=lessons.length?list(lessons.map(lesson=>'<li class="item"><div class="row"><h3>'+esc(lesson.title)+'</h3>'+chip(lesson.status,lesson.status==='promoted'?'green':'amber')+'</div><p>'+esc(lesson.text)+'</p><small class="muted mono">Outcome '+esc(lesson.outcomeId)+'</small>'+
|
|
72
|
+
(lesson.evaluation?'<dl class="facts">'+fact('Baseline',lesson.evaluation.baseline?'Pass':'Fail')+fact('Candidate',lesson.evaluation.candidate?'Pass':'Fail')+fact('Control',lesson.evaluation.control?'Pass':'Fail')+fact('Evidence',lesson.evaluation.evidence)+fact('Provenance',lesson.evaluation.provenance)+'</dl>':'')+
|
|
73
|
+
(['candidate','evaluated'].includes(lesson.status)&&!lesson.memoryId?'<details><summary>'+esc(lesson.evaluation?'Update operator-reported comparison':'Record operator-reported comparison')+'</summary><form class="form" data-form="evaluate" data-id="'+esc(lesson.id)+'"><p class="small muted">Report the results of checks you ran outside this workspace.</p><label class="check"><input type="checkbox" name="baseline" '+(lesson.evaluation?.baseline?'checked':'')+'> Baseline passed</label><label class="check"><input type="checkbox" name="candidate" '+(lesson.evaluation?.candidate?'checked':'')+'> Candidate passed</label><label class="check"><input type="checkbox" name="control" '+(lesson.evaluation?.control?'checked':'')+'> Safety controls passed</label><label>Evaluation evidence<textarea name="evidence" maxlength="4000" rows="2" required>'+esc(lesson.evaluation?.evidence)+'</textarea></label>'+submit('Record evaluation')+'</form></details>':'')+
|
|
74
|
+
'<div class="actions">'+(lesson.status==='evaluated'&&lesson.evaluation&&!lesson.evaluation.baseline&&lesson.evaluation.candidate&&lesson.evaluation.control?lessonAction('promote','Promote lesson',lesson.id):lesson.status==='promoted'?lessonAction('rollback','Roll back lesson',lesson.id):'')+(lesson.memoryId?action('open-memory','Inspect lesson memory','','data-memory="'+esc(lesson.memoryId)+'"'):'')+'</div></li>').join('')):empty('No candidate lessons','Record a work-room outcome to create a candidate for review.');
|
|
75
|
+
const feedback=state.feedback;
|
|
76
|
+
return heading('Memory and learning','Record evidence, evaluate candidates, and review promotion or rollback.')+'<div class="two">'+panel('Propose a lesson',lessonForm)+panel('Lesson history',rows,chip(lessons.length))+'</div>'+panel('Retrieval feedback',feedback?'<div class="panel-body stack"><dl class="facts">'+fact('Influence',feedback.enabled?'Enabled':'Disabled')+fact('Recorded evaluations',arr(feedback.records).length)+fact('Revision',feedback.revision)+'</dl><a href="/workspace" class="btn quiet">Open feedback controls</a></div>':error('feedback','retrieval feedback')||empty('Reading retrieval feedback','Loading the project’s feedback store.'));
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
79
|
+
//# sourceMappingURL=brain-hub-project-views.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-hub-project-views.js","sourceRoot":"","sources":["../../src/dashboard/brain-hub-project-views.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6EhD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-hub-views.d.ts","sourceRoot":"","sources":["../../src/dashboard/brain-hub-views.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,QAkJmB,CAAC"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { BRAIN_HUB_PROJECT_VIEWS } from './brain-hub-project-views.js';
|
|
2
|
+
import { BRAIN_HUB_ACTIONS } from './brain-hub-actions.js';
|
|
3
|
+
export const BRAIN_HUB_VIEWS = String.raw `
|
|
4
|
+
function eventLabel(event){
|
|
5
|
+
if(event.tool)return event.tool+' · '+(event.outcome??(event.kind==='tool-start'?'started':'returned'));
|
|
6
|
+
if(event.phase)return 'Phase · '+event.phase;
|
|
7
|
+
return event.kind.replaceAll('-',' ');
|
|
8
|
+
}
|
|
9
|
+
function eventTone(event){return event.source==='measured'?'cyan':'amber';}
|
|
10
|
+
function evidence(event){return event.source==='measured'?'Measured '+(event.transport==='mcp'?'MCP':'tool'):'Reported';}
|
|
11
|
+
function timelineMarkup(trace=false){
|
|
12
|
+
const events=state.events;
|
|
13
|
+
if(!events.length)return empty(state.errors.telemetry?'Activity unavailable':state.live?'No recorded activity':'Activity display is off',state.errors.telemetry||
|
|
14
|
+
(state.live?'A tool exchange or reported phase will appear here when activity recording is enabled.':'Enable live dashboard activity in Setup.'),view('setup','Open setup'));
|
|
15
|
+
return list([...events].reverse().map(event=>'<li><button class="entry event" type="button" data-event="'+esc(event.id)+'" aria-pressed="'+(state.replayId===event.id)+'"><time class="mono">'+esc(time(event.timestamp))+'</time><span>'+esc(eventLabel(event))+' <span class="muted">· '+esc(hostName(event.agent))+'</span></span>'+chip(evidence(event),eventTone(event))+'</button></li>').join(''),trace?'aria-label="Recorded tool trace"':'aria-label="Recorded activity"');
|
|
16
|
+
}
|
|
17
|
+
function trace(values){
|
|
18
|
+
if(values.length<2)return '';
|
|
19
|
+
const max=Math.max(...values,1);
|
|
20
|
+
const points=values.map((value,index)=>(2+index*62/(values.length-1))+','+(22-value*19/max));
|
|
21
|
+
return '<svg class="metric-trace cyan" viewBox="0 0 66 26" aria-hidden="true"><path d="M'+points.join(' L')+'" fill="none" stroke="currentColor" stroke-width="1.25"/></svg>';
|
|
22
|
+
}
|
|
23
|
+
function telemetryStrip(){
|
|
24
|
+
const measured=state.events.filter(event=>event.source==='measured'&&event.kind==='tool-end');
|
|
25
|
+
const durations=measured.map(event=>event.durationMs).filter(Number.isFinite);
|
|
26
|
+
const observed=new Set(state.events.filter(event=>event.agent&&event.agent!=='user'&&event.agent!=='portal').map(event=>event.agent));
|
|
27
|
+
const memories=state.graph?.totalMemories??state.overview?.quality?.total;
|
|
28
|
+
const pack=state.context?.budget;
|
|
29
|
+
return '<dl class="strip"><div class="metric"><dt>Stored memories in scope</dt><dd class="mono cyan">'+fmt(memories)+'</dd><small>'+esc(scopeName())+'</small></div><div class="metric">'+trace(durations.slice(-16))+'<dt>Measured tool returns</dt><dd class="mono">'+(state.live?fmt(measured.length):'Unavailable')+'</dd><small>'+esc(state.errors.telemetry?'Activity unavailable':state.live?fmt(observed.size)+' client labels in retained activity':'Activity display off')+'</small></div><div class="metric"><dt>Model input and output</dt><dd class="mono">Unavailable</dd><small>Model usage receipts are unavailable</small></div><div class="metric"><dt>Latest context pack estimate</dt><dd class="mono pink">'+(pack?fmt(pack.estimatedTokens)+' / '+fmt(pack.tokenBudget):'No pack built')+'</dd><small>'+esc(pack?arr(state.context.entries).length+' selected memories':'Assemble a scoped pack in Context')+'</small></div></dl>';
|
|
30
|
+
}
|
|
31
|
+
function rail(){
|
|
32
|
+
const graph=arr(state.graph?.nodes);
|
|
33
|
+
const projects=arr(state.overview?.projects).filter(project=>!state.project||project.id===state.project);
|
|
34
|
+
const memories=graph.filter(node=>node.kind==='memory').slice(0,6);
|
|
35
|
+
const projectsMarkup=projects.length?list(projects.slice(0,7).map(project=>'<li><button type="button" class="rail-entry" data-project="'+esc(project.id)+'" aria-pressed="'+(state.project===project.id)+'"><strong>'+esc(project.name)+'</strong><small>'+fmt(project.memories)+' memories</small></button></li>').join('')):empty('No projects with memories','Open a project workspace to add project-local knowledge.',view('setup','See setup'));
|
|
36
|
+
return '<aside class="panel rail" aria-label="Projects and recent records"><div class="rail-title row"><h2>Projects</h2>'+chip(projects.length)+'</div>'+projectsMarkup+'<div class="rail-title row"><h2>Recent records</h2>'+chip(memories.length)+'</div>'+(memories.length?list(memories.map(node=>'<li><button type="button" class="rail-entry" data-node="'+esc(node.id)+'"><strong>'+esc(node.label)+'</strong><small>'+esc(node.category)+' · '+esc(hostName(node.agent))+'</small></button></li>').join('')):empty('No memory records','Add project knowledge or connect a host.',view('knowledge','Open knowledge')) )+'</aside>';
|
|
37
|
+
}
|
|
38
|
+
function graphMarkup(){
|
|
39
|
+
const nodes=arr(state.graph?.nodes),nodeIds=new Set(nodes.map(node=>node.id));
|
|
40
|
+
const edges=arr(state.graph?.edges).filter(edge=>nodeIds.has(edge.source)&&nodeIds.has(edge.target));
|
|
41
|
+
const traceMode=state.graphMode==='trace';
|
|
42
|
+
const listNodes=list(nodes.map(node=>'<li><button class="entry" type="button" data-node="'+esc(node.id)+'" aria-pressed="'+(state.focus&&state.picked===node.id)+'"><strong>'+esc(node.kind==='agent'?hostName(node.label):node.label)+'</strong><small class="muted">'+esc(node.kind+(node.category?' · '+node.category:''))+'</small></button></li>').join(''),'id="node-list" aria-label="Stored graph nodes" '+(state.listing&&!traceMode?'':'hidden'),'node-list');
|
|
43
|
+
return '<section class="panel graph-panel"><div class="panel-head"><div><h2>'+(traceMode?'Recorded trace':'Memory graph')+'</h2><span class="small mono muted">'+fmt(nodes.length)+' records / '+fmt(edges.length)+' relationships'+(state.graph?.truncated?' · limited view':'')+'</span></div><div class="actions">'+action('clear-focus','Clear focus','quiet','id="clear-focus" '+(state.focus?'':'hidden'))+action('graph','Graph','','aria-pressed="'+!traceMode+'"')+action('trace','Trace','','aria-pressed="'+traceMode+'"')+action('node-list','Node list','','aria-expanded="'+state.listing+'" aria-controls="node-list" '+(traceMode||!nodes.length?'hidden':''))+'</div></div>'+
|
|
44
|
+
'<div class="graph-stage" id="brain-stage"><canvas id="brain-canvas" aria-hidden="true" '+(traceMode?'hidden':'')+'></canvas><div class="graph-meta" aria-hidden="true"><span>PROJECT MEMORY</span><span>RECORDED AUTHORS</span></div>'+
|
|
45
|
+
(!nodes.length&&!traceMode?'<div class="graph-empty"><strong>'+esc(state.errors.graph?'Memory graph unavailable':state.graph?'No stored graph records':'Loading memory graph')+'</strong><p class="small muted">'+esc(state.errors.graph??(state.graph?'Save knowledge or use a connected host to create your first record.':'Reading the selected workspace.'))+'</p><div class="actions">'+(state.errors.graph?action('refresh','Retry'):view('knowledge','Open knowledge')+view('setup','Connect a host'))+'</div></div>':'')+
|
|
46
|
+
listNodes+'<div id="trace-list" class="trace-list" '+(traceMode?'':'hidden')+'>'+(traceMode?timelineMarkup(true):'')+'</div><div id="node-caption" class="focus-label" hidden></div></div>'+
|
|
47
|
+
'<div class="graph-foot"><div class="legend"><span class="cyan"><i></i> Project relation</span><span class="pink"><i></i> Recorded by</span><span class="amber"><i></i> Typed relation</span></div><span class="mono" id="graph-event"></span></div></section>';
|
|
48
|
+
}
|
|
49
|
+
function inspectorBody(){
|
|
50
|
+
const item=arr(state.graph?.nodes).find(node=>node.id===state.picked);
|
|
51
|
+
const memory=state.memory?.memory;
|
|
52
|
+
const event=displayEvent();
|
|
53
|
+
const tabs=[['record','Record'],['sources','Sources'],['relations','Links'],['event','Event']].map(([id,label])=>btn(label,'data-inspect="'+id+'" aria-pressed="'+(state.inspector===id)+'"')).join('');
|
|
54
|
+
let details;
|
|
55
|
+
if(state.inspector==='event'){
|
|
56
|
+
details=event?'<div class="panel-body stack"><div class="row"><h3>'+esc(eventLabel(event))+'</h3>'+chip(evidence(event),eventTone(event))+'</div><dl class="facts">'+fact('Host',hostName(event.agent))+fact('Time',isoTime(event.timestamp))+fact('Transport',event.transport)+fact('Session',event.sessionId)+fact('Outcome',event.outcome)+fact('Duration',Number.isFinite(event.durationMs)?event.durationMs+' ms':undefined)+'</dl>'+action('copy-event','Copy event receipt')+'</div>':empty('No activity selected','Select a recorded journal event to inspect its source and outcome.');
|
|
57
|
+
}else if(!item){
|
|
58
|
+
details=empty('Select a graph record','Choose a node, a recent record, or a journal event to inspect its evidence.',state.events.length?action('inspect-latest','Inspect latest event'):'');
|
|
59
|
+
}else if(state.inspector==='sources'){
|
|
60
|
+
const sources=arr(memory?.sources??item.sources);
|
|
61
|
+
details='<div class="panel-body stack"><h3>'+esc(item.label)+'</h3>'+(sources.length?list(sources.map(source=>'<li class="item mono small">'+esc(source)+'</li>').join('')):empty('No source attached','This record has no persisted source reference.'))+'</div>';
|
|
62
|
+
}else if(state.inspector==='relations'){
|
|
63
|
+
const edges=arr(state.graph?.edges).filter(edge=>edge.source===item.id||edge.target===item.id);
|
|
64
|
+
details='<div class="panel-body stack"><h3>'+esc(item.label)+'</h3>'+(edges.length?list(edges.map(edge=>{
|
|
65
|
+
const id=edge.source===item.id?edge.target:edge.source;
|
|
66
|
+
const node=arr(state.graph?.nodes).find(point=>point.id===id);
|
|
67
|
+
return '<li><button type="button" class="entry" data-node="'+esc(id)+'"><strong>'+esc(node?.label??id)+'</strong><small>'+esc(edge.kind)+'</small></button></li>';
|
|
68
|
+
}).join('')):empty('No graph relationships','There are no visible relationships for this record.'))+'</div>';
|
|
69
|
+
}else{
|
|
70
|
+
details='<div class="panel-body stack"><div class="row"><h3>'+esc(item.kind==='agent'?hostName(item.label):item.label)+'</h3>'+chip(item.kind)+'</div><dl class="facts">'+fact('Project',item.project)+fact('Recorded by',item.agent&&hostName(item.agent))+fact('State',memory?.effectiveState??item.effectiveState)+fact('Updated',item.updatedAt&&isoTime(item.updatedAt))+'</dl>'+(item.kind==='memory'?'<pre>'+esc(memory?.content??item.snippet)+'</pre>'+action('copy-memory','Copy record'):'')+'</div>';
|
|
71
|
+
}
|
|
72
|
+
return '<div class="panel-head"><h2>Record inspector</h2>'+(item?chip(item.category??item.kind):'')+'</div><div class="tabs" aria-label="Inspector tabs">'+tabs+'</div>'+details;
|
|
73
|
+
}
|
|
74
|
+
function renderInspector(){const target=$('inspector');if(target)target.innerHTML=inspectorBody();syncGraphControls();}
|
|
75
|
+
function overviewPage(){
|
|
76
|
+
const event=displayEvent();
|
|
77
|
+
const pack=state.context?.budget;
|
|
78
|
+
const compare=state.comparison;
|
|
79
|
+
const contextBody=pack?'<div class="panel-body stack"><div class="row"><span class="muted">Estimated pack tokens</span><strong class="mono">'+fmt(pack.estimatedTokens)+' / '+fmt(pack.tokenBudget)+'</strong></div><div class="meter"><i style="width:'+Math.min(100,Math.round(100*pack.estimatedTokens/Math.max(1,pack.tokenBudget)))+'%"></i></div>'+(compare?'<p class="small muted">Legacy '+fmt(compare.legacy.budget.estimatedTokens)+' · Adaptive '+fmt(compare.adaptive.budget.estimatedTokens)+' estimated tokens</p>':'')+view('context','Open context pack')+'</div>':empty('No context pack for this session','Assemble a pack to inspect estimated tokens and selection reasons.',view('context','Build context pack'));
|
|
80
|
+
return heading('Brain control room','Explore stored memories, inspect tool exchanges, and connect your project.',action('pause',state.motionPaused?'Resume motion':'Pause motion','','id="pause-motion" '+(reduced.matches?'disabled':''))+view('setup','Connection setup'))+
|
|
81
|
+
telemetryStrip()+'<div class="control-grid">'+rail()+graphMarkup()+'<section class="panel inspect" id="inspector">'+inspectorBody()+'</section></div><div class="lower">'+panel('Context efficiency',contextBody,chip('Estimates','pink'))+
|
|
82
|
+
panel('Activity journal','<div class="replay"><label for="replay" class="small muted">Seek record</label><input id="replay" type="range" min="0" max="'+Math.max(0,state.events.length-1)+'" value="'+Math.max(0,state.events.indexOf(event))+'" '+(state.events.length?'':'disabled')+'><output class="mono small" id="event-time">'+esc(event?time(event.timestamp):'—')+'</output>'+action('live','Latest','','id="return-live" '+(state.replayId?'':'hidden'))+'</div><div class="timeline" id="timeline">'+timelineMarkup()+'</div>', '<span id="journal-state">'+chip(state.replayId?'Replay':state.live?'Recorded activity':'Activity unavailable',state.replayId?'amber':'cyan')+'</span>')+'</div>';
|
|
83
|
+
}
|
|
84
|
+
function updateOverviewLive(){
|
|
85
|
+
const timeline=$('timeline'),range=$('replay');
|
|
86
|
+
if(!timeline||!range)return;
|
|
87
|
+
const event=displayEvent();
|
|
88
|
+
const markup=timelineMarkup(),previous=timeline.querySelector('[data-event]:focus')?.dataset.event;
|
|
89
|
+
if(timeline.dataset.markup!==markup){
|
|
90
|
+
timeline.innerHTML=markup;timeline.dataset.markup=markup;
|
|
91
|
+
if(previous)[...timeline.querySelectorAll('[data-event]')].find(node=>node.dataset.event===previous)?.focus({preventScroll:true});
|
|
92
|
+
}
|
|
93
|
+
const traceList=$('trace-list');
|
|
94
|
+
if(traceList&&!traceList.hidden){
|
|
95
|
+
const trace=timelineMarkup(true),previous=traceList.querySelector('[data-event]:focus')?.dataset.event;
|
|
96
|
+
if(traceList.dataset.markup!==trace){
|
|
97
|
+
traceList.innerHTML=trace;traceList.dataset.markup=trace;
|
|
98
|
+
if(previous)[...traceList.querySelectorAll('[data-event]')].find(node=>node.dataset.event===previous)?.focus({preventScroll:true});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
range.max=String(Math.max(0,state.events.length-1));range.value=String(Math.max(0,state.events.indexOf(event)));range.disabled=!state.events.length;
|
|
102
|
+
if(event)range.setAttribute('aria-valuetext',time(event.timestamp)+' · '+eventLabel(event));
|
|
103
|
+
else range.removeAttribute('aria-valuetext');
|
|
104
|
+
$('event-time').textContent=event?time(event.timestamp):'—';
|
|
105
|
+
$('return-live').hidden=!state.replayId;
|
|
106
|
+
$('journal-state').innerHTML=chip(state.replayId?'Replay':state.live?'Recorded activity':'Activity unavailable',state.replayId?'amber':'cyan');
|
|
107
|
+
const strip=$('main').querySelector('.strip');if(strip)strip.outerHTML=telemetryStrip();
|
|
108
|
+
if(state.inspector==='event'&&!$('inspector').matches(':focus-within'))renderInspector();
|
|
109
|
+
const pause=$('pause-motion');pause.textContent=state.motionPaused?'Resume motion':'Pause motion';pause.disabled=reduced.matches;
|
|
110
|
+
drawGraph();
|
|
111
|
+
}
|
|
112
|
+
function contextPage(){
|
|
113
|
+
const input=state.contextInput??{};
|
|
114
|
+
const enabled=state.features?.features?.contextAssembly!==false;
|
|
115
|
+
const form='<div class="panel-body"><form class="form" data-form="context"><label>Task or keywords<textarea name="query" rows="3" maxlength="4096" placeholder="Describe the work this context pack supports">'+esc(input.query)+'</textarea></label><div class="form-grid"><label>Token budget<input name="tokenBudget" type="number" min="0" max="12000" value="'+esc(input.tokenBudget??2000)+'" required></label><label>Retrieval profile<select name="profile"><option value="adaptive">Adaptive</option><option value="legacy" '+(input.profile==='legacy'?'selected':'')+'>Legacy</option></select></label></div><label class="check"><input name="expandRelated" type="checkbox" '+(input.expandRelated?'checked':'')+'> Expand related memories</label><div class="actions">'+(state.project&&enabled?submit('Build pack')+'<button class="btn" type="submit" name="compare" value="yes">Compare profiles</button>':chip(state.project?'Context packs disabled':'Select a project','amber'))+'</div></form></div>';
|
|
116
|
+
const pack=state.context;
|
|
117
|
+
const output=pack?'<div class="panel-body stack"><div class="row"><strong>'+fmt(arr(pack.entries).length)+' selected memories</strong>'+chip(fmt(pack.budget.estimatedTokens)+' estimated tokens','pink')+'</div>'+arr(pack.warnings).map(warning=>'<p class="small amber">'+esc(warning)+'</p>').join('')+
|
|
118
|
+
(state.comparison?'<dl class="facts">'+fact('Legacy estimate',fmt(state.comparison.legacy.budget.estimatedTokens)+' tokens')+fact('Adaptive estimate',fmt(state.comparison.adaptive.budget.estimatedTokens)+' tokens')+'</dl>':'')+
|
|
119
|
+
(arr(pack.entries).length?list(pack.entries.map(entry=>'<li class="item"><strong>'+esc(entry.excerpt)+'</strong><small class="muted">'+esc(arr(entry.reasons).join(' · '))+'</small><small class="mono cyan">'+esc(arr(entry.sources).join(' · '))+'</small></li>').join('')):empty('No memories fit this pack','Check the project, keywords and budget.'))+'<div class="actions">'+action('copy-pack','Copy pack','primary')+'</div><details><summary>Rendered pack</summary><pre>'+esc(pack.markdown)+'</pre></details></div>':empty('Build a scoped context pack','The result shows the actual selected records, source references, and estimated token budget.');
|
|
120
|
+
return heading('Context packs','Assemble and copy project memory for a task.',view('usage','Usage evidence'))+'<div class="two">'+panel('Pack request',form,chip(scopeName()))+panel('Pack result',output)+'</div>';
|
|
121
|
+
}
|
|
122
|
+
function modelsPage(){
|
|
123
|
+
const hosts=arr(state.integrations?.agents);
|
|
124
|
+
const body=hosts.length?'<div class="table-wrap"><table><thead><tr><th>Client recipe</th><th>Project skill files</th><th>Retained activity</th><th>Model</th><th>Usage</th></tr></thead><tbody>'+hosts.map(host=>{
|
|
125
|
+
const events=state.events.filter(event=>event.agent===host.id),latest=events.at(-1);
|
|
126
|
+
return '<tr><td><strong>'+esc(host.label)+'</strong></td><td>'+esc(host.installation)+'</td><td>'+esc(latest?evidence(latest)+' · '+eventLabel(latest)+' · '+isoTime(latest.timestamp):state.live?'No retained records for this client':'Activity display is off')+'</td><td>Unavailable</td><td>Unavailable</td></tr>';
|
|
127
|
+
}).join('')+'</tbody></table></div><p class="panel-body small muted">Recipe availability and file presence do not verify client configuration. The journal records exchanges and reports. Current client connectivity is unavailable.</p>':error('integrations','client checks')||empty('Reading integration evidence','Client skill-file checks are loading.');
|
|
128
|
+
return heading('Connections and models','Review available client recipes and retained activity separately.',view('setup','Configure hosts'))+panel('Client evidence',body);
|
|
129
|
+
}
|
|
130
|
+
function usagePage(){
|
|
131
|
+
const measured=state.events.filter(event=>event.source==='measured'&&event.kind==='tool-end');
|
|
132
|
+
const reported=state.events.filter(event=>event.source==='reported');
|
|
133
|
+
const duration=measured.map(event=>event.durationMs).filter(Number.isFinite).sort((a,b)=>a-b);
|
|
134
|
+
const total=duration.length?duration.reduce((sum,item)=>sum+item,0):null;
|
|
135
|
+
return heading('Usage and timing','Inspect recorded tool activity separately from model usage and context estimates.')+telemetryStrip()+'<div class="two">'+panel('Tool activity','<div class="panel-body stack"><dl class="facts">'+fact('Measured tool returns',state.live?fmt(measured.length):undefined)+fact('Reported activity records',state.live?fmt(reported.length):undefined)+fact('Measured tool duration',total!==null?fmt(total)+' ms':undefined)+fact('Duration coverage',state.live?duration.length+' of '+measured.length+' measured tool returns':undefined)+'</dl><p class="small muted">Counts describe the retained records loaded for this workspace.</p></div>')+panel('Model usage',empty('Model usage unavailable','This workspace does not receive input, output, cached-token or cost receipts from model providers.',view('context','Inspect context estimates')) )+'</div>';
|
|
136
|
+
}
|
|
137
|
+
function setupPage(){
|
|
138
|
+
const features=state.features;
|
|
139
|
+
const flags=features?list(arr(features.definitions).map(item=>{
|
|
140
|
+
const reason=featureLimit(item.id),on=!reason&&features.features[item.id];
|
|
141
|
+
return '<li class="item"><div class="row"><strong>'+esc(item.label)+'</strong>'+btn(reason?'Unavailable':on?'On':'Off','data-feature="'+esc(item.id)+'" role="switch" aria-checked="'+!!on+'" aria-label="'+esc(item.label)+'" '+(state.pending||reason?'disabled':''))+'</div><p class="small muted">'+esc(reason??item.description)+'</p></li>';
|
|
142
|
+
}).join('')):error('features','feature settings')||empty('Loading feature settings','The server supplies the current switches and their descriptions.');
|
|
143
|
+
const hosts=arr(state.integrations?.agents);
|
|
144
|
+
const recipes=hosts.length?list(hosts.map(host=>'<li class="item"><div class="row"><h3>'+esc(host.label)+'</h3>'+chip(host.installation)+'</div><p class="small muted">'+esc(host.detail)+'</p><details><summary>Connection recipe</summary><div class="stack"><pre>'+esc(host.config?.content)+'</pre>'+arr(host.config?.notes).map(note=>'<p class="small muted">'+esc(note)+'</p>').join('')+'<div class="actions">'+action('copy-host','Copy configuration','','data-host="'+esc(host.id)+'"')+action('copy-command','Copy skill command','','data-host="'+esc(host.id)+'"')+'</div></div></details></li>').join('')):error('integrations','host recipes')||empty('Loading host recipes','Configuration recipes are generated locally.');
|
|
145
|
+
const checks=arr(state.integrations?.checks);
|
|
146
|
+
return heading('Workspace setup','Configure host access and manage the workspace’s real feature switches.',action('refresh','Refresh checks'))+'<div class="two">'+panel('Features',flags,features?chip('Revision '+features.revision):'')+panel('Client configuration',recipes,chip('Local recipes','cyan'))+'</div>'+panel('Local checks',checks.length?list(checks.map(check=>'<li class="item"><div class="row"><strong>'+esc(check.label)+'</strong>'+chip(check.status,check.status==='pass'?'green':check.status==='error'?'red':'')+'</div><p class="small muted">'+esc(check.detail)+'</p></li>').join('')):empty('No checks loaded','Refresh to retry host and storage checks.'),checks.length?action('copy-diagnostics','Copy diagnostics'):'');
|
|
147
|
+
}
|
|
148
|
+
const views={overview:overviewPage,context:contextPage,models:modelsPage,usage:usagePage,setup:setupPage,knowledge:knowledgePage,room:roomPage,learning:learningPage};
|
|
149
|
+
` + BRAIN_HUB_PROJECT_VIEWS + BRAIN_HUB_ACTIONS;
|
|
150
|
+
//# sourceMappingURL=brain-hub-views.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-hub-views.js","sourceRoot":"","sources":["../../src/dashboard/brain-hub-views.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkJxC,GAAG,uBAAuB,GAAG,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface DemoWorkspaceOptions {
|
|
2
|
+
port?: number;
|
|
3
|
+
activity?: boolean;
|
|
4
|
+
}
|
|
5
|
+
/** An isolated loopback tour. Never discovers clients or opens default memory/provider configuration. */
|
|
6
|
+
export declare function startDemoWorkspace(options?: DemoWorkspaceOptions): Promise<{
|
|
7
|
+
url: string;
|
|
8
|
+
directory: string;
|
|
9
|
+
close: () => Promise<void>;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=demo-workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo-workspace.d.ts","sourceRoot":"","sources":["../../src/dashboard/demo-workspace.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,oBAAoB;IAAG,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE;AAyB3E,yGAAyG;AACzG,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,oBAAyB;;;;GA0G1E"}
|