@aiready/visualizer 0.1.23 → 0.1.25

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.
@@ -4,8 +4,8 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>AIReady Visualizer (Dev)</title>
7
- <script type="module" crossorigin src="/assets/index-B4sbK1AD.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-cSvqzd3J.css">
7
+ <script type="module" crossorigin src="/assets/index-wP4FeLdN.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-Dizv739M.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/web/src/App.tsx CHANGED
@@ -24,6 +24,7 @@ function App() {
24
24
  const [selectedNode, setSelectedNode] = useState<FileNode | null>(null);
25
25
  const [loading, setLoading] = useState(true);
26
26
  const [error, setError] = useState<string | null>(null);
27
+ const [truncatedWarning, setTruncatedWarning] = useState<{ nodes: boolean; edges: boolean } | null>(null);
27
28
 
28
29
  // Filter state - start with all visible
29
30
  const [visibleSeverities, setVisibleSeverities] = useState<Set<SeverityLevel>>(
@@ -51,7 +52,19 @@ function App() {
51
52
  return;
52
53
  }
53
54
 
54
- setData(transformReportToGraph(reportData));
55
+ // Extract optional visualizer config from report (injected by CLI)
56
+ const visualizerConfig = (reportData as any).visualizerConfig;
57
+ const graphData = transformReportToGraph(reportData, visualizerConfig);
58
+ setData(graphData);
59
+
60
+ // Show warning if graph was truncated
61
+ if (graphData.truncated?.nodes || graphData.truncated?.edges) {
62
+ setTruncatedWarning({
63
+ nodes: graphData.truncated.nodes,
64
+ edges: graphData.truncated.edges,
65
+ });
66
+ }
67
+
55
68
  setLoading(false);
56
69
  };
57
70
 
@@ -148,6 +161,34 @@ function App() {
148
161
  data={filteredData}
149
162
  />
150
163
 
164
+ {/* Truncation warning banner */}
165
+ {truncatedWarning && (truncatedWarning.nodes || truncatedWarning.edges) && (
166
+ <div
167
+ className="px-4 py-3 bg-yellow-50 border-b flex items-center justify-between"
168
+ style={{ borderColor: colors.panelBorder }}
169
+ >
170
+ <div className="flex-1">
171
+ <p className="text-sm text-yellow-800 font-medium">
172
+ ⚠️ Graph visualization truncated at display limits.
173
+ {truncatedWarning.nodes && ' Too many nodes.'}
174
+ {truncatedWarning.edges && ' Too many edges.'}
175
+ </p>
176
+ <p className="text-xs text-yellow-700 mt-1">
177
+ To show more data, increase graph limits in aiready.json:
178
+ <code className="bg-yellow-100 px-1 rounded" style={{ marginLeft: '4px' }}>
179
+ {'"visualizer": { "graph": { "maxNodes": 2000, "maxEdges": 5000 } }'}
180
+ </code>
181
+ </p>
182
+ </div>
183
+ <button
184
+ onClick={() => setTruncatedWarning(null)}
185
+ className="text-yellow-600 hover:text-yellow-800 ml-4 flex-shrink-0"
186
+ >
187
+
188
+ </button>
189
+ </div>
190
+ )}
191
+
151
192
  <div className="flex flex-1 overflow-hidden">
152
193
  <div ref={containerRef} className="flex-1 relative">
153
194
  {filteredData && (
@@ -103,7 +103,7 @@ export function NodeDetails({ colors, selectedNode, onClose }: NodeDetailsProps)
103
103
  style={{ color: colors.textMuted }}
104
104
  title={selectedNode.id}
105
105
  >
106
- {selectedNode.id}
106
+ {selectedNode.label}
107
107
  </p>
108
108
  </div>
109
109
 
@@ -65,8 +65,8 @@ export const themeConfig: Record<'dark' | 'light', ThemeColors> = {
65
65
  };
66
66
 
67
67
  export const GRAPH_CONFIG = {
68
- maxNodes: 200,
69
- maxEdges: 300,
68
+ maxNodes: 400,
69
+ maxEdges: 600,
70
70
  nodeBaseRadius: 3,
71
71
  collisionRadius: 25,
72
72
  zoomMin: 0.1,
package/web/src/types.ts CHANGED
@@ -20,6 +20,14 @@ export interface GraphEdge {
20
20
  export interface GraphData {
21
21
  nodes: FileNode[];
22
22
  edges: GraphEdge[];
23
+ truncated?: {
24
+ nodes: boolean;
25
+ edges: boolean;
26
+ nodeCount: number;
27
+ edgeCount: number;
28
+ nodeLimit: number;
29
+ edgeLimit: number;
30
+ };
23
31
  }
24
32
 
25
33
  // Filter types
package/web/src/utils.ts CHANGED
@@ -11,7 +11,12 @@ export function getSeverityColor(severity: string | undefined): string {
11
11
  return severityColors.default;
12
12
  }
13
13
 
14
- export function transformReportToGraph(report: ReportData): GraphData {
14
+ export function transformReportToGraph(report: ReportData, runtimeGraphConfig?: { maxNodes?: number; maxEdges?: number }): GraphData {
15
+ // Use runtime config if available (from aiready.json), else use defaults from constants
16
+ const graphConfig = {
17
+ maxNodes: runtimeGraphConfig?.maxNodes ?? GRAPH_CONFIG.maxNodes,
18
+ maxEdges: runtimeGraphConfig?.maxEdges ?? GRAPH_CONFIG.maxEdges,
19
+ };
15
20
  const nodes: FileNode[] = [];
16
21
  const edges: GraphEdge[] = [];
17
22
  const nodeMap = new Map<string, FileNode>();
@@ -179,8 +184,8 @@ export function transformReportToGraph(report: ReportData): GraphData {
179
184
  const edgePriority: Record<string, number> = {
180
185
  similarity: 1,
181
186
  dependency: 2,
182
- reference: 3,
183
- related: 4,
187
+ reference: 4,
188
+ related: 3,
184
189
  };
185
190
  const sortedEdges = [...edges].sort((a, b) => {
186
191
  const priorityA = edgePriority[a.type] || 99;
@@ -189,8 +194,16 @@ export function transformReportToGraph(report: ReportData): GraphData {
189
194
  });
190
195
 
191
196
  return {
192
- nodes: nodes.slice(0, GRAPH_CONFIG.maxNodes),
193
- edges: sortedEdges.slice(0, GRAPH_CONFIG.maxEdges),
197
+ nodes: nodes.slice(0, graphConfig.maxNodes),
198
+ edges: sortedEdges.slice(0, graphConfig.maxEdges),
199
+ truncated: {
200
+ nodes: nodes.length > graphConfig.maxNodes,
201
+ edges: sortedEdges.length > graphConfig.maxEdges,
202
+ nodeCount: nodes.length,
203
+ edgeCount: sortedEdges.length,
204
+ nodeLimit: graphConfig.maxNodes,
205
+ edgeLimit: graphConfig.maxEdges,
206
+ },
194
207
  };
195
208
  }
196
209
 
@@ -28,6 +28,7 @@ export default defineConfig(async ({ command }) => {
28
28
  name: 'aiready-report-proxy',
29
29
  configureServer(server: any) {
30
30
  const reportPath = process.env.AIREADY_REPORT_PATH;
31
+ const visualizerConfigStr = process.env.AIREADY_VISUALIZER_CONFIG;
31
32
  if (!reportPath) return;
32
33
  server.middlewares.use(async (req: any, res: any, next: any) => {
33
34
  try {
@@ -40,10 +41,22 @@ export default defineConfig(async ({ command }) => {
40
41
  res.end('Report not found');
41
42
  return;
42
43
  }
43
- const data = await fsp.readFile(reportPath, 'utf8');
44
+ let data = await fsp.readFile(reportPath, 'utf8');
45
+ const report = JSON.parse(data);
46
+
47
+ // Inject visualizer config from env if available
48
+ if (visualizerConfigStr) {
49
+ try {
50
+ const visualizerConfig = JSON.parse(visualizerConfigStr);
51
+ report.visualizerConfig = visualizerConfig;
52
+ } catch (e) {
53
+ // Silently ignore parse errors
54
+ }
55
+ }
56
+
44
57
  res.statusCode = 200;
45
58
  res.setHeader('Content-Type', 'application/json; charset=utf-8');
46
- res.end(data);
59
+ res.end(JSON.stringify(report));
47
60
  return;
48
61
  }
49
62
  } catch (e) {