@coreason-ai/sensory-core 1.3.0 → 1.5.0
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 +24 -0
- package/dist/components/DlpParticleShield.d.ts +9 -0
- package/dist/components/DlpParticleShield.js +197 -0
- package/dist/components/EpistemicDeficitRadar.d.ts +19 -0
- package/dist/components/EpistemicDeficitRadar.js +108 -0
- package/dist/components/KeysigningCeremonyModal.d.ts +25 -0
- package/dist/components/KeysigningCeremonyModal.js +139 -0
- package/dist/components/PredictionMarketConsensusHud.d.ts +32 -0
- package/dist/components/PredictionMarketConsensusHud.js +166 -0
- package/dist/components/SemanticConstellationMap.d.ts +23 -0
- package/dist/components/SemanticConstellationMap.js +273 -0
- package/dist/components/SpeculativeTreeRenderer.d.ts +23 -0
- package/dist/components/SpeculativeTreeRenderer.js +202 -0
- package/dist/components/TemporalScrubber.d.ts +3 -0
- package/dist/components/TemporalScrubber.js +19 -7
- package/dist/components/TopologicalCanvas.d.ts +2 -6
- package/dist/components/TopologicalCanvas.js +159 -18
- package/dist/components/WasmSandboxCagingHud.d.ts +21 -0
- package/dist/components/WasmSandboxCagingHud.js +167 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.js +7 -1
- package/package.json +1 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// Copyright (c) 2026 CoReason, Inc
|
|
2
|
+
//
|
|
3
|
+
// This software is proprietary and dual-licensed
|
|
4
|
+
// Licensed under the Prosperity Public License 3.0 (the "License")
|
|
5
|
+
// A copy of the license is available at <https://prosperitylicense.com/versions/3.0.0>
|
|
6
|
+
// For details, see the LICENSE file
|
|
7
|
+
// Commercial use beyond a 30-day trial requires a separate license
|
|
8
|
+
//
|
|
9
|
+
// Source Code: <https://github.com/CoReason-AI/coreason-sensory-core>
|
|
10
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
11
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
12
|
+
import { GlassBox } from './GlassBox';
|
|
13
|
+
/**
|
|
14
|
+
* Computes horizontal tree layout using post-order positioning.
|
|
15
|
+
*/
|
|
16
|
+
function computeTreeLayout(node, depth = 0, layoutState = { nextLeafY: 0 }, xSpacing = 170, ySpacing = 65) {
|
|
17
|
+
const x = depth * xSpacing + 70;
|
|
18
|
+
if (!node.childSpeculations || node.childSpeculations.length === 0) {
|
|
19
|
+
const y = layoutState.nextLeafY * ySpacing + 60;
|
|
20
|
+
layoutState.nextLeafY += 1;
|
|
21
|
+
return {
|
|
22
|
+
tokenId: node.tokenId,
|
|
23
|
+
tokenValue: node.tokenValue,
|
|
24
|
+
logitProbability: node.logitProbability,
|
|
25
|
+
validationStatus: node.validationStatus,
|
|
26
|
+
x,
|
|
27
|
+
y,
|
|
28
|
+
children: [],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const children = node.childSpeculations.map((child) => computeTreeLayout(child, depth + 1, layoutState, xSpacing, ySpacing));
|
|
32
|
+
const sumY = children.reduce((sum, child) => sum + child.y, 0);
|
|
33
|
+
const y = sumY / children.length;
|
|
34
|
+
return {
|
|
35
|
+
tokenId: node.tokenId,
|
|
36
|
+
tokenValue: node.tokenValue,
|
|
37
|
+
logitProbability: node.logitProbability,
|
|
38
|
+
validationStatus: node.validationStatus,
|
|
39
|
+
x,
|
|
40
|
+
y,
|
|
41
|
+
children,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Traverses the computed layout tree to gather all node and connection information.
|
|
46
|
+
*/
|
|
47
|
+
function collectLayoutEntities(node, accumulatedNodes = [], accumulatedEdges = []) {
|
|
48
|
+
accumulatedNodes.push(node);
|
|
49
|
+
for (const child of node.children) {
|
|
50
|
+
accumulatedEdges.push({
|
|
51
|
+
parentId: node.tokenId,
|
|
52
|
+
childId: child.tokenId,
|
|
53
|
+
x1: node.x,
|
|
54
|
+
y1: node.y,
|
|
55
|
+
x2: child.x,
|
|
56
|
+
y2: child.y,
|
|
57
|
+
status: child.validationStatus,
|
|
58
|
+
});
|
|
59
|
+
collectLayoutEntities(child, accumulatedNodes, accumulatedEdges);
|
|
60
|
+
}
|
|
61
|
+
return { nodes: accumulatedNodes, edges: accumulatedEdges };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* SpeculativeTreeRenderer
|
|
65
|
+
*
|
|
66
|
+
* Target Persona: Systems Engineer / Operational Intelligencer
|
|
67
|
+
* Concept: System 1 / Speculative Decoding telemetry projection.
|
|
68
|
+
* Projects real-time speculative logit draft token proposals, visual decay,
|
|
69
|
+
* and target model validation status in a cybernetic tree diagram.
|
|
70
|
+
*/
|
|
71
|
+
export const SpeculativeTreeRenderer = ({ tokenTree, onTokenFocus, className, }) => {
|
|
72
|
+
const [particles, setParticles] = useState([]);
|
|
73
|
+
const [hoveredToken, setHoveredToken] = useState(null);
|
|
74
|
+
// Track triggered rejections to prevent double-spawning particles
|
|
75
|
+
const processedRejectionsRef = useRef(new Set());
|
|
76
|
+
// Compute layout structures
|
|
77
|
+
const layoutRoot = computeTreeLayout(tokenTree);
|
|
78
|
+
const { nodes: layoutNodes, edges: layoutEdges } = collectLayoutEntities(layoutRoot);
|
|
79
|
+
// Determine viewport boundary limits
|
|
80
|
+
const maxX = Math.max(...layoutNodes.map((n) => n.x), 500) + 120;
|
|
81
|
+
const maxY = Math.max(...layoutNodes.map((n) => n.y), 250) + 80;
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
const freshRejections = [];
|
|
84
|
+
// Identify nodes that became rejected and haven't spawned particles yet
|
|
85
|
+
const inspectForRejections = (n) => {
|
|
86
|
+
if (n.validationStatus === 'target_rejected' && !processedRejectionsRef.current.has(n.tokenId)) {
|
|
87
|
+
freshRejections.push(n);
|
|
88
|
+
}
|
|
89
|
+
n.children.forEach(inspectForRejections);
|
|
90
|
+
};
|
|
91
|
+
inspectForRejections(layoutRoot);
|
|
92
|
+
if (freshRejections.length > 0) {
|
|
93
|
+
const generatedParticles = [];
|
|
94
|
+
for (const rejNode of freshRejections) {
|
|
95
|
+
processedRejectionsRef.current.add(rejNode.tokenId);
|
|
96
|
+
// Spawn 8 disperse particles for decay animation
|
|
97
|
+
for (let i = 0; i < 8; i++) {
|
|
98
|
+
const angle = Math.random() * Math.PI * 2;
|
|
99
|
+
const speed = 25 + Math.random() * 40;
|
|
100
|
+
generatedParticles.push({
|
|
101
|
+
id: `${rejNode.tokenId}-particle-${i}-${Math.random()}`,
|
|
102
|
+
x: rejNode.x,
|
|
103
|
+
y: rejNode.y,
|
|
104
|
+
dx: Math.cos(angle) * speed,
|
|
105
|
+
dy: Math.sin(angle) * speed,
|
|
106
|
+
color: Math.random() > 0.4 ? '#ff4444' : '#ffaa00',
|
|
107
|
+
size: 2 + Math.random() * 3,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
setParticles((prev) => [...prev, ...generatedParticles]);
|
|
112
|
+
// Clean up dissolved particles after 500ms
|
|
113
|
+
const cleanupTimer = setTimeout(() => {
|
|
114
|
+
setParticles((prev) => prev.filter((p) => !generatedParticles.includes(p)));
|
|
115
|
+
}, 500);
|
|
116
|
+
return () => clearTimeout(cleanupTimer);
|
|
117
|
+
}
|
|
118
|
+
}, [tokenTree, layoutRoot]);
|
|
119
|
+
const handleInteraction = (token) => {
|
|
120
|
+
if (onTokenFocus) {
|
|
121
|
+
onTokenFocus({
|
|
122
|
+
tokenId: token.tokenId,
|
|
123
|
+
tokenValue: token.tokenValue,
|
|
124
|
+
logitProbability: token.logitProbability,
|
|
125
|
+
validationStatus: token.validationStatus,
|
|
126
|
+
childSpeculations: [],
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
return (React.createElement(GlassBox, { className: className, variant: "black" },
|
|
131
|
+
React.createElement("div", { className: "flex flex-col space-y-3 font-mono" },
|
|
132
|
+
React.createElement("div", { className: "flex justify-between items-center border-b border-gray-800 pb-2" },
|
|
133
|
+
React.createElement("div", null,
|
|
134
|
+
React.createElement("h3", { className: "text-xs font-semibold text-white tracking-widest uppercase" }, "Speculative Telemetry"),
|
|
135
|
+
React.createElement("span", { className: "text-[9px] text-gray-500 uppercase" }, "System 1 Draft Proposals & Validation Decay")),
|
|
136
|
+
React.createElement("div", { className: "flex gap-3 text-[9px] uppercase tracking-wider" },
|
|
137
|
+
React.createElement("span", { className: "flex items-center gap-1" },
|
|
138
|
+
React.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-[var(--cr-accent-cyan)] shadow-[0_0_4px_var(--cr-accent-cyan)]" }),
|
|
139
|
+
"Validated"),
|
|
140
|
+
React.createElement("span", { className: "flex items-center gap-1" },
|
|
141
|
+
React.createElement("span", { className: "w-1.5 h-1.5 rounded-full border border-dashed border-gray-500" }),
|
|
142
|
+
"Draft Proposal"),
|
|
143
|
+
React.createElement("span", { className: "flex items-center gap-1" },
|
|
144
|
+
React.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-red-500/40 line-through" }),
|
|
145
|
+
"Decayed"))),
|
|
146
|
+
React.createElement("div", { className: "relative w-full overflow-auto bg-black/60 rounded border border-gray-850 p-2 h-72 custom-scrollbar" },
|
|
147
|
+
React.createElement("svg", { width: maxX, height: maxY, className: "absolute top-0 left-0 overflow-visible" },
|
|
148
|
+
React.createElement("g", null, layoutEdges.map((edge) => {
|
|
149
|
+
const isRejected = edge.status === 'target_rejected';
|
|
150
|
+
const isValidated = edge.status === 'target_validated';
|
|
151
|
+
// SVG Bezier path curve calculation
|
|
152
|
+
const controlOffset = 50;
|
|
153
|
+
const pathData = `M ${edge.x1} ${edge.y1} C ${edge.x1 + controlOffset} ${edge.y1}, ${edge.x2 - controlOffset} ${edge.y2}, ${edge.x2} ${edge.y2}`;
|
|
154
|
+
return (React.createElement("path", { key: `${edge.parentId}-${edge.childId}`, d: pathData, fill: "none", stroke: isRejected
|
|
155
|
+
? 'rgba(239, 68, 68, 0.1)'
|
|
156
|
+
: isValidated
|
|
157
|
+
? 'var(--cr-accent-cyan)'
|
|
158
|
+
: 'rgba(255, 255, 255, 0.15)', strokeWidth: isValidated ? 2 : 1, strokeDasharray: isRejected ? '3, 3' : undefined, className: "transition-all duration-300" }));
|
|
159
|
+
})),
|
|
160
|
+
React.createElement("g", null, particles.map((p) => (React.createElement(motion.circle, { key: p.id, cx: p.x, cy: p.y, r: p.size, fill: p.color, initial: { opacity: 1, x: 0, y: 0 }, animate: { opacity: 0, x: p.dx, y: p.dy }, transition: { duration: 0.45, ease: 'easeOut' } }))))),
|
|
161
|
+
React.createElement("div", { className: "absolute top-0 left-0", style: { width: maxX, height: maxY } }, layoutNodes.map((node) => {
|
|
162
|
+
const isValidated = node.validationStatus === 'target_validated';
|
|
163
|
+
const isRejected = node.validationStatus === 'target_rejected';
|
|
164
|
+
// Map probability value to distinct colors
|
|
165
|
+
const probColor = node.logitProbability >= 0.8
|
|
166
|
+
? 'text-green-400'
|
|
167
|
+
: node.logitProbability >= 0.5
|
|
168
|
+
? 'text-yellow-400'
|
|
169
|
+
: 'text-red-400';
|
|
170
|
+
return (React.createElement(motion.div, { key: node.tokenId, style: {
|
|
171
|
+
position: 'absolute',
|
|
172
|
+
left: node.x,
|
|
173
|
+
top: node.y,
|
|
174
|
+
transform: 'translate(-50%, -50%)',
|
|
175
|
+
zIndex: 10,
|
|
176
|
+
}, initial: false, animate: {
|
|
177
|
+
scale: isRejected ? 0.85 : 1,
|
|
178
|
+
opacity: isRejected ? 0.35 : 1,
|
|
179
|
+
}, transition: { duration: 0.3 } },
|
|
180
|
+
React.createElement("button", { onClick: () => handleInteraction(node), onMouseEnter: () => setHoveredToken(node), onMouseLeave: () => setHoveredToken(null), style: { borderRadius: 'var(--cr-border-radius)' }, className: `px-3 py-2 text-xs font-mono transition-all duration-300 border flex flex-col items-center select-none ${isValidated
|
|
181
|
+
? 'border-[var(--cr-accent-cyan)] shadow-[0_0_12px_rgba(0,255,204,0.4)] bg-black/90 text-white'
|
|
182
|
+
: isRejected
|
|
183
|
+
? 'border-red-500/20 bg-red-950/5 text-gray-500 line-through'
|
|
184
|
+
: 'border-dashed border-gray-700 bg-gray-950/80 text-gray-300 hover:border-gray-500'}` },
|
|
185
|
+
React.createElement("span", { className: "font-semibold tracking-wider text-[11px]" }, node.tokenValue),
|
|
186
|
+
React.createElement("span", { className: `text-[8px] font-bold mt-0.5 ${probColor}` },
|
|
187
|
+
(node.logitProbability * 100).toFixed(0),
|
|
188
|
+
"%"))));
|
|
189
|
+
}))),
|
|
190
|
+
React.createElement(AnimatePresence, null, hoveredToken && (React.createElement(motion.div, { initial: { opacity: 0, y: 5 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: 5 }, className: "bg-gray-950/95 border border-gray-850 p-2.5 rounded text-[10px] text-gray-400 flex flex-col space-y-1" },
|
|
191
|
+
React.createElement("div", { className: "flex justify-between text-white font-semibold" },
|
|
192
|
+
React.createElement("span", null,
|
|
193
|
+
"Token ID: ",
|
|
194
|
+
hoveredToken.tokenId),
|
|
195
|
+
React.createElement("span", { className: "uppercase text-[9px] tracking-widest px-1.5 py-0.5 bg-gray-900 border border-gray-800 rounded" }, hoveredToken.validationStatus.replace('target_', '').replace('speculative_', ''))),
|
|
196
|
+
React.createElement("div", { className: "flex justify-between" },
|
|
197
|
+
React.createElement("span", null, "Value representation:"),
|
|
198
|
+
React.createElement("span", { className: "text-white font-mono bg-black px-1.5 rounded" }, JSON.stringify(hoveredToken.tokenValue))),
|
|
199
|
+
React.createElement("div", { className: "flex justify-between" },
|
|
200
|
+
React.createElement("span", null, "Logit Probability:"),
|
|
201
|
+
React.createElement("span", { className: "text-white font-mono" }, hoveredToken.logitProbability.toFixed(5)))))))));
|
|
202
|
+
};
|
|
@@ -9,8 +9,11 @@ export interface TemporalScrubberProps {
|
|
|
9
9
|
minRange: number;
|
|
10
10
|
maxRange: number;
|
|
11
11
|
forks?: TemporalFork[];
|
|
12
|
+
activeForkId?: string;
|
|
12
13
|
onScrub: (newTime: number) => void;
|
|
13
14
|
onForkSelect?: (forkId: string) => void;
|
|
15
|
+
onForkInitiate?: (branchPoint: number) => void;
|
|
16
|
+
onForkClose?: (forkId: string) => void;
|
|
14
17
|
className?: string;
|
|
15
18
|
}
|
|
16
19
|
export declare const TemporalScrubber: React.FC<TemporalScrubberProps>;
|
|
@@ -10,11 +10,13 @@
|
|
|
10
10
|
import React from 'react';
|
|
11
11
|
import { motion } from 'framer-motion';
|
|
12
12
|
import { cn } from './GlassBox';
|
|
13
|
-
export const TemporalScrubber = ({ timestamp, minRange, maxRange, forks = [], onScrub, onForkSelect, className }) => {
|
|
13
|
+
export const TemporalScrubber = ({ timestamp, minRange, maxRange, forks = [], activeForkId, onScrub, onForkSelect, onForkInitiate, onForkClose, className }) => {
|
|
14
14
|
const getPercentage = (val) => ((val - minRange) / (maxRange - minRange)) * 100;
|
|
15
15
|
return (React.createElement("div", { className: cn('flex flex-col items-stretch gap-4 p-4 bg-[var(--cr-glass-box-black)] rounded-xl border border-gray-800', className) },
|
|
16
16
|
React.createElement("div", { className: "flex justify-between items-center mb-2" },
|
|
17
|
-
React.createElement("
|
|
17
|
+
React.createElement("div", { className: "flex items-center gap-3" },
|
|
18
|
+
React.createElement("span", { className: "text-white uppercase tracking-widest text-xs font-bold" }, "Temporal Navigation"),
|
|
19
|
+
onForkInitiate && (React.createElement("button", { onClick: () => onForkInitiate(timestamp), className: "px-2 py-0.5 bg-purple-950/60 border border-purple-500/50 hover:bg-purple-900/60 text-purple-300 text-[10px] font-mono rounded transition-all uppercase tracking-wider font-bold" }, "Fork Timeline"))),
|
|
18
20
|
React.createElement("span", { className: "text-[var(--cr-accent-cyan)] font-mono text-xs" },
|
|
19
21
|
"T - ",
|
|
20
22
|
Math.floor((Date.now() - timestamp) / 1000),
|
|
@@ -25,11 +27,21 @@ export const TemporalScrubber = ({ timestamp, minRange, maxRange, forks = [], on
|
|
|
25
27
|
forks.map((fork, idx) => {
|
|
26
28
|
const startPct = getPercentage(fork.branchPoint);
|
|
27
29
|
const topOffset = idx % 2 === 0 ? 0 : 16;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
30
|
+
const isActive = activeForkId === fork.id;
|
|
31
|
+
return (React.createElement(motion.div, { key: fork.id, initial: { opacity: 0 }, animate: { opacity: 1 }, className: cn("absolute h-1 cursor-pointer group transition-all duration-300", isActive
|
|
32
|
+
? "bg-purple-500 shadow-[0_0_8px_rgba(168,85,247,0.8)] z-20"
|
|
33
|
+
: "bg-[var(--cr-accent-orange)] z-10"), style: { left: `${startPct}%`, top: topOffset, width: `calc(100% - ${startPct}%)` }, onClick: () => onForkSelect === null || onForkSelect === void 0 ? void 0 : onForkSelect(fork.id) },
|
|
34
|
+
React.createElement("div", { className: cn("absolute -left-1 -top-1 w-3 h-3 rounded-full transition-all duration-300", isActive ? "bg-purple-400 scale-125" : "bg-[var(--cr-accent-orange)]") }),
|
|
35
|
+
React.createElement("div", { className: cn("absolute -top-6 left-0 transition-opacity bg-black text-[10px] font-mono px-2 py-1 rounded flex items-center gap-1.5 whitespace-nowrap", isActive
|
|
36
|
+
? "opacity-100 text-purple-300 border border-purple-500/30"
|
|
37
|
+
: "opacity-0 group-hover:opacity-100 text-[var(--cr-accent-orange)]") },
|
|
38
|
+
React.createElement("span", null,
|
|
39
|
+
"\u2443 ",
|
|
40
|
+
fork.name),
|
|
41
|
+
onForkClose && (React.createElement("button", { onClick: (e) => {
|
|
42
|
+
e.stopPropagation();
|
|
43
|
+
onForkClose(fork.id);
|
|
44
|
+
}, className: "hover:text-white text-xs ml-1 focus:outline-none font-bold", title: "Dismiss Fork" }, "\u00D7")))));
|
|
33
45
|
}),
|
|
34
46
|
React.createElement("input", { type: "range", min: minRange, max: maxRange, value: timestamp, onChange: (e) => onScrub(Number(e.target.value)), className: "absolute top-[26px] w-full cursor-ew-resize opacity-0 z-10" }),
|
|
35
47
|
React.createElement(motion.div, { className: "absolute top-6 w-5 h-5 rounded-full bg-white border-2 border-[var(--cr-accent-cyan)] shadow-[0_0_10px_var(--cr-accent-cyan)] pointer-events-none", style: { left: `calc(${getPercentage(timestamp)}% - 10px)` }, layout: true }))));
|
|
@@ -17,11 +17,7 @@ export interface TopologicalCanvasProps {
|
|
|
17
17
|
x: number;
|
|
18
18
|
y: number;
|
|
19
19
|
}) => void;
|
|
20
|
+
onExecuteIntervention?: (nodeId: string) => void;
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
* TopologicalCanvas
|
|
23
|
-
*
|
|
24
|
-
* Concept: Visualizes the Macro-Swarm Architecture
|
|
25
|
-
* Uses ReactFlow to map mathematical DAGs to the UI
|
|
26
|
-
*/
|
|
22
|
+
export declare const computeBlastRadius: (nodes: Node[], edges: Edge[], startNodeId: string) => Set<string>;
|
|
27
23
|
export declare const TopologicalCanvas: React.FC<TopologicalCanvasProps>;
|
|
@@ -17,14 +17,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
17
17
|
});
|
|
18
18
|
};
|
|
19
19
|
import React from 'react';
|
|
20
|
-
import { ReactFlow, Background, Controls, getBezierPath, EdgeLabelRenderer, Panel } from '@xyflow/react';
|
|
20
|
+
import { ReactFlow, Background, Controls, getBezierPath, EdgeLabelRenderer, Panel, ReactFlowProvider, useViewport } from '@xyflow/react';
|
|
21
21
|
import '@xyflow/react/dist/style.css';
|
|
22
22
|
import { GlassBox } from './GlassBox';
|
|
23
23
|
import { StatusPulse } from './StatusPulse';
|
|
24
|
-
import { Lock, Unlock, ShieldAlert, ShieldX } from 'lucide-react';
|
|
24
|
+
import { Lock, Unlock, ShieldAlert, ShieldX, AlertTriangle } from 'lucide-react';
|
|
25
25
|
import { ConformanceGuillotine } from './ConformanceGuillotine';
|
|
26
26
|
// Custom Node: SwarmNode
|
|
27
|
-
const SwarmNode = ({ data }) => {
|
|
27
|
+
const SwarmNode = ({ id, data }) => {
|
|
28
28
|
var _a;
|
|
29
29
|
const isBreached = data.status === 'suspended_security_violation' || data.isSecurityViolation;
|
|
30
30
|
const isCompact = data.density === 'compact';
|
|
@@ -32,6 +32,9 @@ const SwarmNode = ({ data }) => {
|
|
|
32
32
|
if (data.isPanicked) {
|
|
33
33
|
borderColorClass = 'border-red-600/80 shadow-[0_0_15px_rgba(220,38,38,0.3)]';
|
|
34
34
|
}
|
|
35
|
+
else if (data.isInBlastRadius) {
|
|
36
|
+
borderColorClass = 'border-red-500/90 shadow-[0_0_18px_rgba(239,68,68,0.6)] bg-red-950/20 animate-pulse';
|
|
37
|
+
}
|
|
35
38
|
else if (isBreached) {
|
|
36
39
|
borderColorClass = 'border-orange-500/80 shadow-[0_0_15px_rgba(249,115,22,0.3)]';
|
|
37
40
|
}
|
|
@@ -48,7 +51,16 @@ const SwarmNode = ({ data }) => {
|
|
|
48
51
|
React.createElement("div", { className: "flex flex-col" },
|
|
49
52
|
React.createElement("div", { className: "flex justify-between items-center mb-2" },
|
|
50
53
|
React.createElement("span", { className: "text-[10px] uppercase tracking-widest text-gray-500" }, data.typeLabel || 'AGENT'),
|
|
51
|
-
|
|
54
|
+
React.createElement("div", { className: "flex items-center gap-1.5" },
|
|
55
|
+
React.createElement("button", { onMouseEnter: () => { var _a; return (_a = data.onHoverRetract) === null || _a === void 0 ? void 0 : _a.call(data, id); }, onMouseLeave: () => { var _a; return (_a = data.onLeaveRetract) === null || _a === void 0 ? void 0 : _a.call(data); }, onClick: (e) => {
|
|
56
|
+
var _a;
|
|
57
|
+
e.stopPropagation();
|
|
58
|
+
(_a = data.onExecuteIntervention) === null || _a === void 0 ? void 0 : _a.call(data, id);
|
|
59
|
+
}, className: "text-gray-500 hover:text-red-500 transition-colors p-0.5 rounded cursor-pointer flex items-center justify-center bg-black/40 border border-white/5 hover:border-red-500/30", title: "Retract Node (Do-Operator)" },
|
|
60
|
+
React.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
61
|
+
React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
62
|
+
React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" }))),
|
|
63
|
+
!isCompact && React.createElement(StatusPulse, { status: data.status || 'idle' }))),
|
|
52
64
|
!isCompact && (React.createElement("span", { className: "text-sm font-mono text-white truncate max-w-[120px]", title: data.urn }, ((_a = data.urn) === null || _a === void 0 ? void 0 : _a.split(':').slice(-2).join(':')) || 'urn:unknown')),
|
|
53
65
|
data.causalRole && (React.createElement("div", { className: `mt-2 text-[8px] font-bold uppercase tracking-wider px-1 py-0.5 rounded text-center ${data.causalRole === 'confounder'
|
|
54
66
|
? 'bg-yellow-500/20 text-yellow-400 border border-yellow-500/30'
|
|
@@ -76,13 +88,24 @@ const SandboxNode = ({ id, data }) => {
|
|
|
76
88
|
const isCompact = data.density === 'compact';
|
|
77
89
|
return (React.createElement("div", { className: `bg-[rgba(20,20,20,0.8)] border relative rounded-lg p-4 min-w-[300px] ${isCompact ? 'min-h-[50px]' : 'min-h-[200px]'} shadow-[0_0_15px_rgba(255,100,0,0.2)] ${data.isPanicked
|
|
78
90
|
? 'border-red-600/80 shadow-[0_0_20px_rgba(220,38,38,0.4)]'
|
|
79
|
-
:
|
|
91
|
+
: data.isInBlastRadius
|
|
92
|
+
? 'border-red-500/90 shadow-[0_0_20px_rgba(239,68,68,0.6)] bg-red-950/20 animate-pulse'
|
|
93
|
+
: 'border-[var(--cr-accent-orange)]'}` },
|
|
80
94
|
React.createElement("div", { className: `absolute top-0 left-0 right-0 text-[10px] font-bold uppercase tracking-wider px-2 py-1 rounded-t-sm flex justify-between items-center ${data.isPanicked ? 'bg-red-600 text-white' : 'bg-[var(--cr-accent-orange)] text-black'}` },
|
|
81
95
|
React.createElement("span", null,
|
|
82
96
|
"\u26CA ",
|
|
83
97
|
data.sandboxType || 'WASM ENCLAVE',
|
|
84
98
|
" ISOLATION BOUNDARY"),
|
|
85
|
-
React.createElement("
|
|
99
|
+
React.createElement("div", { className: "flex items-center gap-2" },
|
|
100
|
+
React.createElement("button", { onMouseEnter: () => { var _a; return (_a = data.onHoverRetract) === null || _a === void 0 ? void 0 : _a.call(data, id); }, onMouseLeave: () => { var _a; return (_a = data.onLeaveRetract) === null || _a === void 0 ? void 0 : _a.call(data); }, onClick: (e) => {
|
|
101
|
+
var _a;
|
|
102
|
+
e.stopPropagation();
|
|
103
|
+
(_a = data.onExecuteIntervention) === null || _a === void 0 ? void 0 : _a.call(data, id);
|
|
104
|
+
}, className: `p-0.5 rounded transition-colors cursor-pointer flex items-center justify-center bg-black/40 border border-white/5 ${data.isPanicked ? 'text-white/70 hover:text-white hover:border-white/30' : 'text-black/70 hover:text-red-600 hover:border-red-600/30'}`, title: "Retract WASM Sandbox" },
|
|
105
|
+
React.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
106
|
+
React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
107
|
+
React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" }))),
|
|
108
|
+
React.createElement("span", { className: "font-mono" }, data.id || id))),
|
|
86
109
|
!isCompact && (React.createElement("div", { className: "mt-6 mb-2 flex flex-col gap-2" },
|
|
87
110
|
React.createElement("div", { className: "flex items-center justify-between text-[10px] font-mono text-gray-400" },
|
|
88
111
|
React.createElement("span", null, "CPU FUEL"),
|
|
@@ -124,6 +147,8 @@ const TelemetryEdge = ({ id, sourceX, sourceY, targetX, targetY, sourcePosition,
|
|
|
124
147
|
});
|
|
125
148
|
const [showDetails, setShowDetails] = React.useState(false);
|
|
126
149
|
const getEdgeColor = () => {
|
|
150
|
+
if (data === null || data === void 0 ? void 0 : data.isInBlastRadius)
|
|
151
|
+
return '#ef4444'; // Flashing red hazard line
|
|
127
152
|
if (data === null || data === void 0 ? void 0 : data.isSecurityViolation)
|
|
128
153
|
return '#f97316'; // Flashing firewall orange
|
|
129
154
|
if (data === null || data === void 0 ? void 0 : data.isSecureMtls)
|
|
@@ -133,11 +158,15 @@ const TelemetryEdge = ({ id, sourceX, sourceY, targetX, targetY, sourcePosition,
|
|
|
133
158
|
return (data === null || data === void 0 ? void 0 : data.isStreaming) ? 'var(--cr-accent-orange)' : '#4B5563';
|
|
134
159
|
};
|
|
135
160
|
const getStrokeDashArray = () => {
|
|
161
|
+
if (data === null || data === void 0 ? void 0 : data.isInBlastRadius)
|
|
162
|
+
return '5,5';
|
|
136
163
|
if ((data === null || data === void 0 ? void 0 : data.isSecureMtls) || (data === null || data === void 0 ? void 0 : data.isStreaming) || (data === null || data === void 0 ? void 0 : data.isSecurityViolation))
|
|
137
164
|
return '5,5';
|
|
138
165
|
return 'none';
|
|
139
166
|
};
|
|
140
167
|
const getAnimation = () => {
|
|
168
|
+
if (data === null || data === void 0 ? void 0 : data.isInBlastRadius)
|
|
169
|
+
return 'dashdraw 0.3s linear infinite'; // Accelerated dash warning
|
|
141
170
|
if (data === null || data === void 0 ? void 0 : data.isSecurityViolation)
|
|
142
171
|
return 'dashdraw 0.5s linear infinite';
|
|
143
172
|
if ((data === null || data === void 0 ? void 0 : data.isStreaming) || (data === null || data === void 0 ? void 0 : data.isSecureMtls))
|
|
@@ -212,15 +241,101 @@ const nodeTypes = {
|
|
|
212
241
|
const edgeTypes = {
|
|
213
242
|
telemetryEdge: TelemetryEdge,
|
|
214
243
|
};
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
244
|
+
export const computeBlastRadius = (nodes, edges, startNodeId) => {
|
|
245
|
+
const visited = new Set();
|
|
246
|
+
const queue = [startNodeId];
|
|
247
|
+
while (queue.length > 0) {
|
|
248
|
+
const current = queue.shift();
|
|
249
|
+
if (!visited.has(current)) {
|
|
250
|
+
visited.add(current);
|
|
251
|
+
const downstream = edges
|
|
252
|
+
.filter(e => e.source === current)
|
|
253
|
+
.map(e => e.target);
|
|
254
|
+
queue.push(...downstream);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return visited;
|
|
258
|
+
};
|
|
259
|
+
const CausalInterventionOverlay = ({ nodes, hoveredNodeId }) => {
|
|
260
|
+
var _a, _b, _c, _d;
|
|
261
|
+
const { x, y, zoom } = useViewport();
|
|
262
|
+
const [pulseRadius, setPulseRadius] = React.useState(0);
|
|
263
|
+
React.useEffect(() => {
|
|
264
|
+
let frame;
|
|
265
|
+
const start = performance.now();
|
|
266
|
+
const animate = (time) => {
|
|
267
|
+
const elapsed = time - start;
|
|
268
|
+
const progress = (elapsed % 1500) / 1500;
|
|
269
|
+
setPulseRadius(progress * 120);
|
|
270
|
+
frame = requestAnimationFrame(animate);
|
|
271
|
+
};
|
|
272
|
+
frame = requestAnimationFrame(animate);
|
|
273
|
+
return () => cancelAnimationFrame(frame);
|
|
274
|
+
}, []);
|
|
275
|
+
const targetNode = nodes.find(n => n.id === hoveredNodeId);
|
|
276
|
+
if (!targetNode)
|
|
277
|
+
return null;
|
|
278
|
+
const isSandbox = targetNode.type === 'sandboxNode';
|
|
279
|
+
const width = (_b = (_a = targetNode.measured) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : (isSandbox ? 300 : 150);
|
|
280
|
+
const height = (_d = (_c = targetNode.measured) === null || _c === void 0 ? void 0 : _c.height) !== null && _d !== void 0 ? _d : (isSandbox ? 200 : 100);
|
|
281
|
+
const cx = targetNode.position.x + width / 2;
|
|
282
|
+
const cy = targetNode.position.y + height / 2;
|
|
283
|
+
const screenCx = cx * zoom + x;
|
|
284
|
+
const screenCy = cy * zoom + y;
|
|
285
|
+
return (React.createElement("svg", { style: {
|
|
286
|
+
position: 'absolute',
|
|
287
|
+
left: 0,
|
|
288
|
+
top: 0,
|
|
289
|
+
width: '100%',
|
|
290
|
+
height: '100%',
|
|
291
|
+
pointerEvents: 'none',
|
|
292
|
+
zIndex: 9999,
|
|
293
|
+
} },
|
|
294
|
+
React.createElement("circle", { cx: screenCx, cy: screenCy, r: pulseRadius * zoom, fill: "rgba(239, 68, 68, 0.08)", stroke: "rgba(239, 68, 68, 0.5)", strokeWidth: "2", style: {
|
|
295
|
+
transformOrigin: `${screenCx}px ${screenCy}px`,
|
|
296
|
+
} }),
|
|
297
|
+
React.createElement("circle", { cx: screenCx, cy: screenCy, r: 8 * zoom, fill: "#ef4444", className: "animate-ping" }),
|
|
298
|
+
React.createElement("circle", { cx: screenCx, cy: screenCy, r: 5 * zoom, fill: "#ef4444" })));
|
|
299
|
+
};
|
|
300
|
+
const TopologicalCanvasInner = ({ nodes, edges, availableCapabilities = [], onNodeClick, onNodesChange, onEdgesChange, onConnect, onDropCapability, onExecuteIntervention }) => {
|
|
301
|
+
var _a, _b;
|
|
222
302
|
const [isLayouting, setIsLayouting] = React.useState(false);
|
|
223
303
|
const [activePanicNode, setActivePanicNode] = React.useState(null);
|
|
304
|
+
const [hoveredRetractNodeId, setHoveredRetractNodeId] = React.useState(null);
|
|
305
|
+
const blastRadiusIds = React.useMemo(() => {
|
|
306
|
+
if (!hoveredRetractNodeId)
|
|
307
|
+
return new Set();
|
|
308
|
+
return computeBlastRadius(nodes, edges, hoveredRetractNodeId);
|
|
309
|
+
}, [nodes, edges, hoveredRetractNodeId]);
|
|
310
|
+
const processedNodes = React.useMemo(() => {
|
|
311
|
+
return nodes.map(node => {
|
|
312
|
+
const isInBlast = blastRadiusIds.has(node.id);
|
|
313
|
+
const isTarget = node.id === hoveredRetractNodeId;
|
|
314
|
+
return Object.assign(Object.assign({}, node), { data: Object.assign(Object.assign({}, node.data), { isInBlastRadius: isInBlast, isInterventionTarget: isTarget, onHoverRetract: (id) => setHoveredRetractNodeId(id), onLeaveRetract: () => setHoveredRetractNodeId(null), onExecuteIntervention: (id) => {
|
|
315
|
+
setHoveredRetractNodeId(null);
|
|
316
|
+
if (onExecuteIntervention) {
|
|
317
|
+
onExecuteIntervention(id);
|
|
318
|
+
}
|
|
319
|
+
} }) });
|
|
320
|
+
});
|
|
321
|
+
}, [nodes, blastRadiusIds, hoveredRetractNodeId, onExecuteIntervention]);
|
|
322
|
+
const processedEdges = React.useMemo(() => {
|
|
323
|
+
return edges.map(edge => {
|
|
324
|
+
const isInBlast = blastRadiusIds.has(edge.source);
|
|
325
|
+
return Object.assign(Object.assign({}, edge), { data: Object.assign(Object.assign({}, edge.data), { isInBlastRadius: isInBlast }) });
|
|
326
|
+
});
|
|
327
|
+
}, [edges, blastRadiusIds]);
|
|
328
|
+
const affectedSandboxCount = React.useMemo(() => {
|
|
329
|
+
return Array.from(blastRadiusIds).filter(id => {
|
|
330
|
+
var _a;
|
|
331
|
+
const node = nodes.find(n => n.id === id);
|
|
332
|
+
if (!node)
|
|
333
|
+
return false;
|
|
334
|
+
const urn = ((_a = node.data) === null || _a === void 0 ? void 0 : _a.urn) || '';
|
|
335
|
+
return node.type === 'sandboxNode' || urn.includes('urn:coreason:node:sandbox');
|
|
336
|
+
}).length;
|
|
337
|
+
}, [blastRadiusIds, nodes]);
|
|
338
|
+
const deficitForecast = blastRadiusIds.size * 150.0;
|
|
224
339
|
const onDragStart = (event, capability) => {
|
|
225
340
|
event.dataTransfer.setData('application/reactflow', JSON.stringify(capability));
|
|
226
341
|
event.dataTransfer.effectAllowed = 'move';
|
|
@@ -291,8 +406,8 @@ export const TopologicalCanvas = ({ nodes, edges, availableCapabilities = [], on
|
|
|
291
406
|
onNodesChange(changes);
|
|
292
407
|
}
|
|
293
408
|
}
|
|
294
|
-
catch (
|
|
295
|
-
console.error('ELK Layout
|
|
409
|
+
catch (err) {
|
|
410
|
+
console.error('ELK Layout fault:', err);
|
|
296
411
|
}
|
|
297
412
|
finally {
|
|
298
413
|
setIsLayouting(false);
|
|
@@ -314,15 +429,41 @@ export const TopologicalCanvas = ({ nodes, edges, availableCapabilities = [], on
|
|
|
314
429
|
background-color: #000;
|
|
315
430
|
}
|
|
316
431
|
`),
|
|
317
|
-
React.createElement(ReactFlow, { nodes:
|
|
432
|
+
React.createElement(ReactFlow, { nodes: processedNodes, edges: processedEdges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onNodeClick: handleInternalNodeClick, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onConnect: onConnect, fitView: true, proOptions: { hideAttribution: true } },
|
|
318
433
|
React.createElement(Background, { color: "#1f2937", gap: 20 }),
|
|
319
434
|
React.createElement(Controls, { className: "bg-[var(--cr-glass-box-black)] border border-gray-800 fill-white" }),
|
|
320
435
|
React.createElement(Panel, { position: "top-right", className: "m-4" },
|
|
321
|
-
React.createElement("button", { onClick: handleAutoLayout, disabled: isLayouting, className: `bg-[var(--cr-accent-orange)] text-black font-bold uppercase tracking-wider text-[10px] px-4 py-2 rounded shadow-lg transition-opacity ${isLayouting ? 'opacity-50 cursor-not-allowed' : 'hover:opacity-90'}` }, isLayouting ? 'Computing Topology...' : 'Orthogonal Layout'))
|
|
436
|
+
React.createElement("button", { onClick: handleAutoLayout, disabled: isLayouting, className: `bg-[var(--cr-accent-orange)] text-black font-bold uppercase tracking-wider text-[10px] px-4 py-2 rounded shadow-lg transition-opacity ${isLayouting ? 'opacity-50 cursor-not-allowed' : 'hover:opacity-90'}` }, isLayouting ? 'Computing Topology...' : 'Orthogonal Layout')),
|
|
437
|
+
hoveredRetractNodeId && (React.createElement(Panel, { position: "bottom-center", className: "mb-4" },
|
|
438
|
+
React.createElement(GlassBox, { density: "dense", className: "border border-red-500/30 bg-black/85 backdrop-blur-md p-4 rounded-lg w-[450px] shadow-[0_0_20px_rgba(239,68,68,0.2)]" },
|
|
439
|
+
React.createElement("div", { className: "flex items-start gap-3" },
|
|
440
|
+
React.createElement(AlertTriangle, { className: "w-5 h-5 text-red-500 animate-pulse shrink-0 mt-0.5" }),
|
|
441
|
+
React.createElement("div", { className: "flex-1 space-y-1.5" },
|
|
442
|
+
React.createElement("div", { className: "text-[11px] font-bold text-red-400 uppercase tracking-widest" }, "Causal Intervention Forecast"),
|
|
443
|
+
React.createElement("div", { className: "text-[10px] font-mono text-gray-400 break-all leading-normal" },
|
|
444
|
+
"Target URN: ",
|
|
445
|
+
React.createElement("span", { className: "text-white font-bold" }, String(((_b = (_a = nodes.find(n => n.id === hoveredRetractNodeId)) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.urn) || hoveredRetractNodeId))),
|
|
446
|
+
React.createElement("div", { className: "grid grid-cols-3 gap-2 py-1.5 border-t border-b border-white/5 my-1" },
|
|
447
|
+
React.createElement("div", null,
|
|
448
|
+
React.createElement("div", { className: "text-[9px] text-gray-500 font-mono" }, "AFFECTED NODES"),
|
|
449
|
+
React.createElement("div", { className: "text-xs font-bold text-white font-mono" }, blastRadiusIds.size)),
|
|
450
|
+
React.createElement("div", null,
|
|
451
|
+
React.createElement("div", { className: "text-[9px] text-gray-500 font-mono" }, "SANDBOXES"),
|
|
452
|
+
React.createElement("div", { className: "text-xs font-bold text-white font-mono" }, affectedSandboxCount)),
|
|
453
|
+
React.createElement("div", null,
|
|
454
|
+
React.createElement("div", { className: "text-[9px] text-gray-500 font-mono" }, "DEFICIT FORECAST"),
|
|
455
|
+
React.createElement("div", { className: "text-xs font-bold text-white font-mono" },
|
|
456
|
+
deficitForecast.toFixed(1),
|
|
457
|
+
" u"))),
|
|
458
|
+
React.createElement("div", { className: "text-[9px] text-red-400/80 font-sans italic leading-relaxed" }, "CAUTION: Retracting this node executes a Do-operator mutation. All downstream dependent nodes will be invalidated."))))))),
|
|
459
|
+
hoveredRetractNodeId && (React.createElement(CausalInterventionOverlay, { nodes: nodes, hoveredNodeId: hoveredRetractNodeId }))),
|
|
322
460
|
activePanicNode && (React.createElement("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm z-[9999] flex justify-center items-center p-6" },
|
|
323
461
|
React.createElement(ConformanceGuillotine, { nodeId: activePanicNode.nodeId, panicMessage: activePanicNode.panicMessage, backtrace: activePanicNode.backtrace, onClose: () => setActivePanicNode(null), onRecover: () => {
|
|
324
462
|
console.log(`Triggering hot enclave recovery for ${activePanicNode.nodeId}`);
|
|
325
|
-
// In production this emits a hot-attestation reload request to the Temporal ledger
|
|
326
463
|
setActivePanicNode(null);
|
|
327
464
|
} })))));
|
|
328
465
|
};
|
|
466
|
+
export const TopologicalCanvas = (props) => {
|
|
467
|
+
return (React.createElement(ReactFlowProvider, null,
|
|
468
|
+
React.createElement(TopologicalCanvasInner, Object.assign({}, props))));
|
|
469
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface AttestationReceipt {
|
|
3
|
+
transactionId: string;
|
|
4
|
+
proofStatus: 'VALIDATED' | 'FORGED' | 'INVALID' | 'UNCHECKED';
|
|
5
|
+
originatingAgentUrn: string;
|
|
6
|
+
verificationTimestamp: string;
|
|
7
|
+
zkProofHash: string;
|
|
8
|
+
sdJwtCompliance: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface SandboxHardwareTelemetry {
|
|
11
|
+
sandboxUrn: string;
|
|
12
|
+
cpuFuelRemaining: number;
|
|
13
|
+
cpuFuelBurnRate: number;
|
|
14
|
+
ramBytesAllocated: number;
|
|
15
|
+
}
|
|
16
|
+
export interface WasmSandboxCagingHudProps {
|
|
17
|
+
telemetry: SandboxHardwareTelemetry;
|
|
18
|
+
attestation?: AttestationReceipt;
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const WasmSandboxCagingHud: React.FC<WasmSandboxCagingHudProps>;
|