@omiron33/omi-neuron-web 0.1.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/README.md +55 -0
- package/dist/api/index.cjs +943 -0
- package/dist/api/index.cjs.map +1 -0
- package/dist/api/index.d.cts +140 -0
- package/dist/api/index.d.ts +140 -0
- package/dist/api/index.js +934 -0
- package/dist/api/index.js.map +1 -0
- package/dist/chunk-BSOSHBDR.cjs +300 -0
- package/dist/chunk-BSOSHBDR.cjs.map +1 -0
- package/dist/chunk-COO66N7H.cjs +950 -0
- package/dist/chunk-COO66N7H.cjs.map +1 -0
- package/dist/chunk-FXKXMSLY.cjs +270 -0
- package/dist/chunk-FXKXMSLY.cjs.map +1 -0
- package/dist/chunk-PSDVPB7Y.js +289 -0
- package/dist/chunk-PSDVPB7Y.js.map +1 -0
- package/dist/chunk-RQCGONPN.js +937 -0
- package/dist/chunk-RQCGONPN.js.map +1 -0
- package/dist/chunk-RTSFO7BW.cjs +592 -0
- package/dist/chunk-RTSFO7BW.cjs.map +1 -0
- package/dist/chunk-TFLMPBX7.js +262 -0
- package/dist/chunk-TFLMPBX7.js.map +1 -0
- package/dist/chunk-XNR42GCJ.js +547 -0
- package/dist/chunk-XNR42GCJ.js.map +1 -0
- package/dist/cli/index.cjs +571 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +563 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/database-B0vplyA4.d.cts +41 -0
- package/dist/database-B0vplyA4.d.ts +41 -0
- package/dist/edge-BzsYe2Ed.d.cts +269 -0
- package/dist/edge-BzsYe2Ed.d.ts +269 -0
- package/dist/index.cjs +895 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1484 -0
- package/dist/index.d.ts +1484 -0
- package/dist/index.js +654 -0
- package/dist/index.js.map +1 -0
- package/dist/migration/index.cjs +32 -0
- package/dist/migration/index.cjs.map +1 -0
- package/dist/migration/index.d.cts +51 -0
- package/dist/migration/index.d.ts +51 -0
- package/dist/migration/index.js +3 -0
- package/dist/migration/index.js.map +1 -0
- package/dist/query-helpers-D8po5Mn-.d.cts +777 -0
- package/dist/query-helpers-DvQTA2_Z.d.ts +777 -0
- package/dist/visualization/index.cjs +485 -0
- package/dist/visualization/index.cjs.map +1 -0
- package/dist/visualization/index.d.cts +134 -0
- package/dist/visualization/index.d.ts +134 -0
- package/dist/visualization/index.js +460 -0
- package/dist/visualization/index.js.map +1 -0
- package/docker/docker-compose.template.yml +28 -0
- package/package.json +116 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
import { useRef, useMemo, useEffect, useState } from 'react';
|
|
2
|
+
import * as THREE2 from 'three';
|
|
3
|
+
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
|
|
4
|
+
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
// src/visualization/constants.ts
|
|
8
|
+
var DEFAULT_THEME = {
|
|
9
|
+
colors: {
|
|
10
|
+
background: "#020314",
|
|
11
|
+
domainColors: {},
|
|
12
|
+
defaultDomainColor: "#c0c5ff",
|
|
13
|
+
edgeDefault: "#4d4d55",
|
|
14
|
+
edgeActive: "#c6d4ff",
|
|
15
|
+
edgeSelected: "#ffffff",
|
|
16
|
+
labelText: "#ffffff",
|
|
17
|
+
labelBackground: "rgba(0, 0, 0, 0.8)"
|
|
18
|
+
},
|
|
19
|
+
typography: {
|
|
20
|
+
labelFontFamily: "system-ui, sans-serif",
|
|
21
|
+
labelFontSize: 12,
|
|
22
|
+
labelFontWeight: "500"
|
|
23
|
+
},
|
|
24
|
+
effects: {
|
|
25
|
+
starfieldEnabled: true,
|
|
26
|
+
starfieldColor: "#ffffff",
|
|
27
|
+
glowEnabled: true,
|
|
28
|
+
glowIntensity: 0.6
|
|
29
|
+
},
|
|
30
|
+
animation: {
|
|
31
|
+
focusDuration: 800,
|
|
32
|
+
transitionDuration: 650,
|
|
33
|
+
easing: "easeInOut"
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var SceneManager = class {
|
|
37
|
+
constructor(container, config) {
|
|
38
|
+
this.container = container;
|
|
39
|
+
this.config = config;
|
|
40
|
+
this.scene = new THREE2.Scene();
|
|
41
|
+
this.camera = new THREE2.PerspectiveCamera(60, 1, 0.1, 2e3);
|
|
42
|
+
this.renderer = new THREE2.WebGLRenderer({ antialias: true });
|
|
43
|
+
this.labelRenderer = new CSS2DRenderer();
|
|
44
|
+
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
|
|
45
|
+
}
|
|
46
|
+
scene;
|
|
47
|
+
camera;
|
|
48
|
+
renderer;
|
|
49
|
+
labelRenderer;
|
|
50
|
+
controls;
|
|
51
|
+
animationId = null;
|
|
52
|
+
initialize() {
|
|
53
|
+
const { cameraPosition, cameraTarget, backgroundColor } = this.config;
|
|
54
|
+
this.scene.background = new THREE2.Color(backgroundColor);
|
|
55
|
+
this.camera.position.set(...cameraPosition);
|
|
56
|
+
this.controls.target.set(...cameraTarget);
|
|
57
|
+
this.controls.update();
|
|
58
|
+
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, this.config.pixelRatioCap));
|
|
59
|
+
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
|
|
60
|
+
this.labelRenderer.setSize(this.container.clientWidth, this.container.clientHeight);
|
|
61
|
+
this.container.appendChild(this.renderer.domElement);
|
|
62
|
+
this.container.appendChild(this.labelRenderer.domElement);
|
|
63
|
+
window.addEventListener("resize", this.resize);
|
|
64
|
+
this.startAnimationLoop();
|
|
65
|
+
}
|
|
66
|
+
dispose() {
|
|
67
|
+
this.stopAnimationLoop();
|
|
68
|
+
window.removeEventListener("resize", this.resize);
|
|
69
|
+
this.renderer.dispose();
|
|
70
|
+
this.scene.clear();
|
|
71
|
+
this.container.innerHTML = "";
|
|
72
|
+
}
|
|
73
|
+
startAnimationLoop() {
|
|
74
|
+
const loop = () => {
|
|
75
|
+
this.render();
|
|
76
|
+
this.animationId = requestAnimationFrame(loop);
|
|
77
|
+
};
|
|
78
|
+
loop();
|
|
79
|
+
}
|
|
80
|
+
stopAnimationLoop() {
|
|
81
|
+
if (this.animationId) {
|
|
82
|
+
cancelAnimationFrame(this.animationId);
|
|
83
|
+
this.animationId = null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
render() {
|
|
87
|
+
this.renderer.render(this.scene, this.camera);
|
|
88
|
+
this.labelRenderer.render(this.scene, this.camera);
|
|
89
|
+
}
|
|
90
|
+
resize = () => {
|
|
91
|
+
const width = this.container.clientWidth;
|
|
92
|
+
const height = this.container.clientHeight;
|
|
93
|
+
this.camera.aspect = width / height;
|
|
94
|
+
this.camera.updateProjectionMatrix();
|
|
95
|
+
this.renderer.setSize(width, height);
|
|
96
|
+
this.labelRenderer.setSize(width, height);
|
|
97
|
+
};
|
|
98
|
+
updateBackground(color) {
|
|
99
|
+
this.scene.background = new THREE2.Color(color);
|
|
100
|
+
}
|
|
101
|
+
updateCamera(position) {
|
|
102
|
+
this.camera.position.set(...position);
|
|
103
|
+
}
|
|
104
|
+
getWorldPosition(screenX, screenY) {
|
|
105
|
+
return this.screenToWorld(screenX, screenY);
|
|
106
|
+
}
|
|
107
|
+
screenToWorld(x, y) {
|
|
108
|
+
const rect = this.container.getBoundingClientRect();
|
|
109
|
+
const ndc = new THREE2.Vector3(
|
|
110
|
+
(x - rect.left) / rect.width * 2 - 1,
|
|
111
|
+
-((y - rect.top) / rect.height) * 2 + 1,
|
|
112
|
+
0.5
|
|
113
|
+
);
|
|
114
|
+
ndc.unproject(this.camera);
|
|
115
|
+
return ndc;
|
|
116
|
+
}
|
|
117
|
+
worldToScreen(position) {
|
|
118
|
+
const vector = position.clone().project(this.camera);
|
|
119
|
+
const rect = this.container.getBoundingClientRect();
|
|
120
|
+
return {
|
|
121
|
+
x: (vector.x * 0.5 + 0.5) * rect.width + rect.left,
|
|
122
|
+
y: (-vector.y * 0.5 + 0.5) * rect.height + rect.top
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
onContextLost = () => {
|
|
126
|
+
};
|
|
127
|
+
onContextRestored = () => {
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// src/visualization/hooks/useSceneManager.ts
|
|
132
|
+
function useSceneManager(containerRef, config) {
|
|
133
|
+
const [manager, setManager] = useState(null);
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
const container = containerRef.current;
|
|
136
|
+
if (!container) return;
|
|
137
|
+
const sceneManager = new SceneManager(container, config);
|
|
138
|
+
sceneManager.initialize();
|
|
139
|
+
setManager(sceneManager);
|
|
140
|
+
return () => {
|
|
141
|
+
sceneManager.dispose();
|
|
142
|
+
setManager(null);
|
|
143
|
+
};
|
|
144
|
+
}, [containerRef, config.backgroundColor]);
|
|
145
|
+
return manager;
|
|
146
|
+
}
|
|
147
|
+
var NodeRenderer = class {
|
|
148
|
+
constructor(scene, config) {
|
|
149
|
+
this.scene = scene;
|
|
150
|
+
this.config = config;
|
|
151
|
+
this.scene.add(this.group);
|
|
152
|
+
}
|
|
153
|
+
group = new THREE2.Group();
|
|
154
|
+
nodeObjects = /* @__PURE__ */ new Map();
|
|
155
|
+
renderNodes(nodes) {
|
|
156
|
+
this.clear();
|
|
157
|
+
nodes.forEach((node) => {
|
|
158
|
+
const color = this.config.domainColors[node.domain] ?? this.config.defaultColor;
|
|
159
|
+
const geometry = new THREE2.SphereGeometry(this.config.baseScale, 16, 16);
|
|
160
|
+
const material = new THREE2.MeshBasicMaterial({ color });
|
|
161
|
+
const mesh = new THREE2.Mesh(geometry, material);
|
|
162
|
+
if (node.position) {
|
|
163
|
+
mesh.position.set(...node.position);
|
|
164
|
+
}
|
|
165
|
+
mesh.userData = { nodeId: node.id };
|
|
166
|
+
this.group.add(mesh);
|
|
167
|
+
this.nodeObjects.set(node.id, mesh);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
updateNode(nodeId, updates) {
|
|
171
|
+
const obj = this.nodeObjects.get(nodeId);
|
|
172
|
+
if (!obj) return;
|
|
173
|
+
if (updates.position) {
|
|
174
|
+
obj.position.set(...updates.position);
|
|
175
|
+
}
|
|
176
|
+
if (updates.domain) {
|
|
177
|
+
const color = this.config.domainColors[updates.domain] ?? this.config.defaultColor;
|
|
178
|
+
obj.material.color = new THREE2.Color(color);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
removeNode(nodeId) {
|
|
182
|
+
const obj = this.nodeObjects.get(nodeId);
|
|
183
|
+
if (!obj) return;
|
|
184
|
+
this.group.remove(obj);
|
|
185
|
+
this.nodeObjects.delete(nodeId);
|
|
186
|
+
}
|
|
187
|
+
clear() {
|
|
188
|
+
this.group.clear();
|
|
189
|
+
this.nodeObjects.clear();
|
|
190
|
+
}
|
|
191
|
+
showNodes(nodeIds) {
|
|
192
|
+
nodeIds.forEach((id) => {
|
|
193
|
+
const obj = this.nodeObjects.get(id);
|
|
194
|
+
if (obj) obj.visible = true;
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
hideNodes(nodeIds) {
|
|
198
|
+
nodeIds.forEach((id) => {
|
|
199
|
+
const obj = this.nodeObjects.get(id);
|
|
200
|
+
if (obj) obj.visible = false;
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
setVisibleNodes(nodeIds) {
|
|
204
|
+
if (!nodeIds) {
|
|
205
|
+
this.nodeObjects.forEach((obj) => {
|
|
206
|
+
obj.visible = true;
|
|
207
|
+
});
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const visibleSet = new Set(nodeIds);
|
|
211
|
+
this.nodeObjects.forEach((obj, id) => {
|
|
212
|
+
obj.visible = visibleSet.has(id);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
updateLabelVisibility() {
|
|
216
|
+
}
|
|
217
|
+
highlightNode(nodeId) {
|
|
218
|
+
const obj = this.nodeObjects.get(nodeId);
|
|
219
|
+
if (obj) {
|
|
220
|
+
obj.material.color = new THREE2.Color("#ffffff");
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
unhighlightNode(nodeId) {
|
|
224
|
+
const obj = this.nodeObjects.get(nodeId);
|
|
225
|
+
if (obj) {
|
|
226
|
+
const color = this.config.defaultColor;
|
|
227
|
+
obj.material.color = new THREE2.Color(color);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
clearHighlights() {
|
|
231
|
+
this.nodeObjects.forEach((obj) => {
|
|
232
|
+
obj.material.color = new THREE2.Color(this.config.defaultColor);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
getNodePosition(nodeId) {
|
|
236
|
+
const obj = this.nodeObjects.get(nodeId);
|
|
237
|
+
return obj ? obj.position.clone() : null;
|
|
238
|
+
}
|
|
239
|
+
getNodeObject(nodeId) {
|
|
240
|
+
return this.nodeObjects.get(nodeId) ?? null;
|
|
241
|
+
}
|
|
242
|
+
dispose() {
|
|
243
|
+
this.clear();
|
|
244
|
+
this.scene.remove(this.group);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
var EdgeRenderer = class {
|
|
248
|
+
constructor(scene, config) {
|
|
249
|
+
this.scene = scene;
|
|
250
|
+
this.config = config;
|
|
251
|
+
this.scene.add(this.group);
|
|
252
|
+
}
|
|
253
|
+
group = new THREE2.Group();
|
|
254
|
+
edgeObjects = /* @__PURE__ */ new Map();
|
|
255
|
+
renderEdges(edges, nodePositions) {
|
|
256
|
+
this.clear();
|
|
257
|
+
edges.forEach((edge) => {
|
|
258
|
+
const from = nodePositions.get(edge.from);
|
|
259
|
+
const to = nodePositions.get(edge.to);
|
|
260
|
+
if (!from || !to) return;
|
|
261
|
+
const geometry = new THREE2.BufferGeometry().setFromPoints([from, to]);
|
|
262
|
+
const opacity = this.config.strengthOpacityScale ? edge.strength : this.config.baseOpacity;
|
|
263
|
+
const material = new THREE2.LineBasicMaterial({ color: this.config.defaultColor, transparent: true, opacity });
|
|
264
|
+
const line = new THREE2.Line(geometry, material);
|
|
265
|
+
line.userData = { edgeId: edge.id };
|
|
266
|
+
this.group.add(line);
|
|
267
|
+
this.edgeObjects.set(edge.id, line);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
updateEdge(edgeId, updates) {
|
|
271
|
+
const line = this.edgeObjects.get(edgeId);
|
|
272
|
+
if (!line) return;
|
|
273
|
+
if (updates.strength !== void 0) {
|
|
274
|
+
const opacity = this.config.strengthOpacityScale ? updates.strength : this.config.baseOpacity;
|
|
275
|
+
line.material.opacity = opacity;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
removeEdge(edgeId) {
|
|
279
|
+
const line = this.edgeObjects.get(edgeId);
|
|
280
|
+
if (!line) return;
|
|
281
|
+
this.group.remove(line);
|
|
282
|
+
this.edgeObjects.delete(edgeId);
|
|
283
|
+
}
|
|
284
|
+
clear() {
|
|
285
|
+
this.group.clear();
|
|
286
|
+
this.edgeObjects.clear();
|
|
287
|
+
}
|
|
288
|
+
filterByStrength(minStrength) {
|
|
289
|
+
this.edgeObjects.forEach((line) => {
|
|
290
|
+
line.visible = line.material.opacity >= minStrength;
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
filterByType() {
|
|
294
|
+
}
|
|
295
|
+
highlightEdge(edgeId) {
|
|
296
|
+
const line = this.edgeObjects.get(edgeId);
|
|
297
|
+
if (line) {
|
|
298
|
+
line.material.color = new THREE2.Color(this.config.activeColor);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
highlightEdgesForNode() {
|
|
302
|
+
}
|
|
303
|
+
unhighlightEdge(edgeId) {
|
|
304
|
+
const line = this.edgeObjects.get(edgeId);
|
|
305
|
+
if (line) {
|
|
306
|
+
line.material.color = new THREE2.Color(this.config.defaultColor);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
clearHighlights() {
|
|
310
|
+
this.edgeObjects.forEach((line) => {
|
|
311
|
+
line.material.color = new THREE2.Color(this.config.defaultColor);
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
showEdges(edgeIds) {
|
|
315
|
+
edgeIds.forEach((id) => {
|
|
316
|
+
const line = this.edgeObjects.get(id);
|
|
317
|
+
if (line) line.visible = true;
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
hideEdges(edgeIds) {
|
|
321
|
+
edgeIds.forEach((id) => {
|
|
322
|
+
const line = this.edgeObjects.get(id);
|
|
323
|
+
if (line) line.visible = false;
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
dispose() {
|
|
327
|
+
this.clear();
|
|
328
|
+
this.scene.remove(this.group);
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
function NeuronWeb({
|
|
332
|
+
graphData,
|
|
333
|
+
className,
|
|
334
|
+
style,
|
|
335
|
+
isLoading,
|
|
336
|
+
error,
|
|
337
|
+
renderEmptyState,
|
|
338
|
+
renderLoadingState,
|
|
339
|
+
ariaLabel,
|
|
340
|
+
theme
|
|
341
|
+
}) {
|
|
342
|
+
const containerRef = useRef(null);
|
|
343
|
+
const resolvedTheme = { ...DEFAULT_THEME, ...theme };
|
|
344
|
+
const sceneManager = useSceneManager(containerRef, {
|
|
345
|
+
backgroundColor: resolvedTheme.colors.background,
|
|
346
|
+
cameraPosition: [4, 8, 20],
|
|
347
|
+
cameraTarget: [0, 0, 0],
|
|
348
|
+
minZoom: 4,
|
|
349
|
+
maxZoom: 42,
|
|
350
|
+
enableStarfield: resolvedTheme.effects.starfieldEnabled,
|
|
351
|
+
starfieldCount: 1200,
|
|
352
|
+
pixelRatioCap: 2
|
|
353
|
+
});
|
|
354
|
+
const nodeRenderer = useMemo(() => {
|
|
355
|
+
if (!sceneManager) return null;
|
|
356
|
+
return new NodeRenderer(sceneManager.scene, {
|
|
357
|
+
domainColors: resolvedTheme.colors.domainColors,
|
|
358
|
+
defaultColor: resolvedTheme.colors.defaultDomainColor,
|
|
359
|
+
baseScale: 0.4,
|
|
360
|
+
tierScales: {
|
|
361
|
+
primary: 1.6,
|
|
362
|
+
secondary: 1.2,
|
|
363
|
+
tertiary: 1,
|
|
364
|
+
insight: 1
|
|
365
|
+
},
|
|
366
|
+
glowIntensity: resolvedTheme.effects.glowIntensity,
|
|
367
|
+
labelDistance: 20,
|
|
368
|
+
maxVisibleLabels: 50
|
|
369
|
+
});
|
|
370
|
+
}, [sceneManager]);
|
|
371
|
+
const edgeRenderer = useMemo(() => {
|
|
372
|
+
if (!sceneManager) return null;
|
|
373
|
+
return new EdgeRenderer(sceneManager.scene, {
|
|
374
|
+
defaultColor: resolvedTheme.colors.edgeDefault,
|
|
375
|
+
activeColor: resolvedTheme.colors.edgeActive,
|
|
376
|
+
selectedColor: resolvedTheme.colors.edgeSelected,
|
|
377
|
+
baseOpacity: 0.5,
|
|
378
|
+
strengthOpacityScale: true
|
|
379
|
+
});
|
|
380
|
+
}, [sceneManager]);
|
|
381
|
+
useEffect(() => {
|
|
382
|
+
if (!sceneManager || !nodeRenderer || !edgeRenderer) return;
|
|
383
|
+
nodeRenderer.renderNodes(graphData.nodes);
|
|
384
|
+
const positions = /* @__PURE__ */ new Map();
|
|
385
|
+
graphData.nodes.forEach((node) => {
|
|
386
|
+
if (!node.position) return;
|
|
387
|
+
positions.set(node.slug, new THREE2.Vector3(...node.position));
|
|
388
|
+
});
|
|
389
|
+
edgeRenderer.renderEdges(graphData.edges, positions);
|
|
390
|
+
}, [graphData, sceneManager, nodeRenderer, edgeRenderer]);
|
|
391
|
+
if (isLoading) {
|
|
392
|
+
return /* @__PURE__ */ jsx("div", { className, style, "aria-label": ariaLabel, children: renderLoadingState ? renderLoadingState() : /* @__PURE__ */ jsx("div", { children: "Loading\u2026" }) });
|
|
393
|
+
}
|
|
394
|
+
if (error) {
|
|
395
|
+
return /* @__PURE__ */ jsx("div", { className, style, "aria-label": ariaLabel, children: renderEmptyState ? renderEmptyState() : /* @__PURE__ */ jsx("div", { children: error }) });
|
|
396
|
+
}
|
|
397
|
+
if (!graphData.nodes.length) {
|
|
398
|
+
return /* @__PURE__ */ jsx("div", { className, style, "aria-label": ariaLabel, children: renderEmptyState ? renderEmptyState() : /* @__PURE__ */ jsx("div", { children: "No data" }) });
|
|
399
|
+
}
|
|
400
|
+
return /* @__PURE__ */ jsx("div", { ref: containerRef, className, style, "aria-label": ariaLabel });
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// src/visualization/themes/theme-engine.ts
|
|
404
|
+
var ThemeEngine = class {
|
|
405
|
+
theme;
|
|
406
|
+
onThemeChange = () => {
|
|
407
|
+
};
|
|
408
|
+
constructor(initialTheme) {
|
|
409
|
+
this.theme = { ...DEFAULT_THEME, ...initialTheme };
|
|
410
|
+
}
|
|
411
|
+
getTheme() {
|
|
412
|
+
return this.theme;
|
|
413
|
+
}
|
|
414
|
+
setTheme(theme) {
|
|
415
|
+
this.theme = { ...this.theme, ...theme };
|
|
416
|
+
this.onThemeChange(this.theme);
|
|
417
|
+
}
|
|
418
|
+
resetTheme() {
|
|
419
|
+
this.theme = { ...DEFAULT_THEME };
|
|
420
|
+
this.onThemeChange(this.theme);
|
|
421
|
+
}
|
|
422
|
+
setDomainColor(domain, color) {
|
|
423
|
+
this.theme.colors.domainColors[domain] = color;
|
|
424
|
+
this.onThemeChange(this.theme);
|
|
425
|
+
}
|
|
426
|
+
setBackground(color) {
|
|
427
|
+
this.theme.colors.background = color;
|
|
428
|
+
this.onThemeChange(this.theme);
|
|
429
|
+
}
|
|
430
|
+
setLabelStyle(style) {
|
|
431
|
+
this.theme.typography = { ...this.theme.typography, ...style };
|
|
432
|
+
this.onThemeChange(this.theme);
|
|
433
|
+
}
|
|
434
|
+
applyPreset(preset) {
|
|
435
|
+
if (preset === "light") {
|
|
436
|
+
this.theme = {
|
|
437
|
+
...DEFAULT_THEME,
|
|
438
|
+
colors: { ...DEFAULT_THEME.colors, background: "#f7f7fb", labelText: "#111" }
|
|
439
|
+
};
|
|
440
|
+
} else if (preset === "dark") {
|
|
441
|
+
this.theme = { ...DEFAULT_THEME };
|
|
442
|
+
}
|
|
443
|
+
this.onThemeChange(this.theme);
|
|
444
|
+
}
|
|
445
|
+
saveToStorage() {
|
|
446
|
+
if (typeof window === "undefined") return;
|
|
447
|
+
window.localStorage.setItem("omi-neuron-theme", JSON.stringify(this.theme));
|
|
448
|
+
}
|
|
449
|
+
loadFromStorage() {
|
|
450
|
+
if (typeof window === "undefined") return;
|
|
451
|
+
const stored = window.localStorage.getItem("omi-neuron-theme");
|
|
452
|
+
if (stored) {
|
|
453
|
+
this.theme = { ...this.theme, ...JSON.parse(stored) };
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
export { DEFAULT_THEME, NeuronWeb, SceneManager, ThemeEngine };
|
|
459
|
+
//# sourceMappingURL=index.js.map
|
|
460
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/visualization/constants.ts","../../src/visualization/scene/scene-manager.ts","../../src/visualization/hooks/useSceneManager.ts","../../src/visualization/scene/node-renderer.ts","../../src/visualization/scene/edge-renderer.ts","../../src/visualization/NeuronWeb.tsx","../../src/visualization/themes/theme-engine.ts"],"names":["THREE","THREE3","useEffect","THREE4"],"mappings":"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","file":"index.js","sourcesContent":["import type { NeuronWebTheme } from './types';\n\nexport const DEFAULT_THEME: NeuronWebTheme = {\n colors: {\n background: '#020314',\n domainColors: {},\n defaultDomainColor: '#c0c5ff',\n edgeDefault: '#4d4d55',\n edgeActive: '#c6d4ff',\n edgeSelected: '#ffffff',\n labelText: '#ffffff',\n labelBackground: 'rgba(0, 0, 0, 0.8)',\n },\n typography: {\n labelFontFamily: 'system-ui, sans-serif',\n labelFontSize: 12,\n labelFontWeight: '500',\n },\n effects: {\n starfieldEnabled: true,\n starfieldColor: '#ffffff',\n glowEnabled: true,\n glowIntensity: 0.6,\n },\n animation: {\n focusDuration: 800,\n transitionDuration: 650,\n easing: 'easeInOut',\n },\n};\n","import * as THREE from 'three';\nimport { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';\nimport { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer.js';\n\nexport interface SceneConfig {\n backgroundColor: string;\n cameraPosition: [number, number, number];\n cameraTarget: [number, number, number];\n minZoom: number;\n maxZoom: number;\n enableStarfield: boolean;\n starfieldCount: number;\n pixelRatioCap: number;\n}\n\nexport class SceneManager {\n scene: THREE.Scene;\n camera: THREE.PerspectiveCamera;\n renderer: THREE.WebGLRenderer;\n labelRenderer: CSS2DRenderer;\n controls: OrbitControls;\n private animationId: number | null = null;\n\n constructor(private container: HTMLElement, private config: SceneConfig) {\n this.scene = new THREE.Scene();\n this.camera = new THREE.PerspectiveCamera(60, 1, 0.1, 2000);\n this.renderer = new THREE.WebGLRenderer({ antialias: true });\n this.labelRenderer = new CSS2DRenderer();\n this.controls = new OrbitControls(this.camera, this.renderer.domElement);\n }\n\n initialize(): void {\n const { cameraPosition, cameraTarget, backgroundColor } = this.config;\n this.scene.background = new THREE.Color(backgroundColor);\n this.camera.position.set(...cameraPosition);\n this.controls.target.set(...cameraTarget);\n this.controls.update();\n\n this.renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, this.config.pixelRatioCap));\n this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);\n this.labelRenderer.setSize(this.container.clientWidth, this.container.clientHeight);\n\n this.container.appendChild(this.renderer.domElement);\n this.container.appendChild(this.labelRenderer.domElement);\n\n window.addEventListener('resize', this.resize);\n this.startAnimationLoop();\n }\n\n dispose(): void {\n this.stopAnimationLoop();\n window.removeEventListener('resize', this.resize);\n this.renderer.dispose();\n this.scene.clear();\n this.container.innerHTML = '';\n }\n\n startAnimationLoop(): void {\n const loop = () => {\n this.render();\n this.animationId = requestAnimationFrame(loop);\n };\n loop();\n }\n\n stopAnimationLoop(): void {\n if (this.animationId) {\n cancelAnimationFrame(this.animationId);\n this.animationId = null;\n }\n }\n\n render(): void {\n this.renderer.render(this.scene, this.camera);\n this.labelRenderer.render(this.scene, this.camera);\n }\n\n resize = (): void => {\n const width = this.container.clientWidth;\n const height = this.container.clientHeight;\n this.camera.aspect = width / height;\n this.camera.updateProjectionMatrix();\n this.renderer.setSize(width, height);\n this.labelRenderer.setSize(width, height);\n };\n\n updateBackground(color: string): void {\n this.scene.background = new THREE.Color(color);\n }\n\n updateCamera(position: [number, number, number]): void {\n this.camera.position.set(...position);\n }\n\n getWorldPosition(screenX: number, screenY: number): THREE.Vector3 {\n return this.screenToWorld(screenX, screenY);\n }\n\n screenToWorld(x: number, y: number): THREE.Vector3 {\n const rect = this.container.getBoundingClientRect();\n const ndc = new THREE.Vector3(\n ((x - rect.left) / rect.width) * 2 - 1,\n -((y - rect.top) / rect.height) * 2 + 1,\n 0.5\n );\n ndc.unproject(this.camera);\n return ndc;\n }\n\n worldToScreen(position: THREE.Vector3): { x: number; y: number } {\n const vector = position.clone().project(this.camera);\n const rect = this.container.getBoundingClientRect();\n return {\n x: (vector.x * 0.5 + 0.5) * rect.width + rect.left,\n y: (-vector.y * 0.5 + 0.5) * rect.height + rect.top,\n };\n }\n\n onContextLost = () => {};\n onContextRestored = () => {};\n}\n","import { useEffect, useState } from 'react';\nimport type { RefObject } from 'react';\nimport { SceneManager, type SceneConfig } from '../scene/scene-manager';\n\nexport function useSceneManager(\n containerRef: RefObject<HTMLElement | null>,\n config: SceneConfig\n): SceneManager | null {\n const [manager, setManager] = useState<SceneManager | null>(null);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const sceneManager = new SceneManager(container, config);\n sceneManager.initialize();\n setManager(sceneManager);\n return () => {\n sceneManager.dispose();\n setManager(null);\n };\n }, [containerRef, config.backgroundColor]);\n\n return manager;\n}\n","import * as THREE from 'three';\nimport type { NeuronVisualNode, NodeTier } from '../../core/types';\n\nexport interface NodeRenderConfig {\n domainColors: Record<string, string>;\n defaultColor: string;\n baseScale: number;\n tierScales: Record<NodeTier, number>;\n glowIntensity: number;\n labelDistance: number;\n maxVisibleLabels: number;\n}\n\nexport class NodeRenderer {\n private group = new THREE.Group();\n private nodeObjects = new Map<string, THREE.Mesh>();\n\n constructor(private scene: THREE.Scene, private config: NodeRenderConfig) {\n this.scene.add(this.group);\n }\n\n renderNodes(nodes: NeuronVisualNode[]): void {\n this.clear();\n nodes.forEach((node) => {\n const color = this.config.domainColors[node.domain] ?? this.config.defaultColor;\n const geometry = new THREE.SphereGeometry(this.config.baseScale, 16, 16);\n const material = new THREE.MeshBasicMaterial({ color });\n const mesh = new THREE.Mesh(geometry, material);\n if (node.position) {\n mesh.position.set(...node.position);\n }\n mesh.userData = { nodeId: node.id };\n this.group.add(mesh);\n this.nodeObjects.set(node.id, mesh);\n });\n }\n\n updateNode(nodeId: string, updates: Partial<NeuronVisualNode>): void {\n const obj = this.nodeObjects.get(nodeId) as THREE.Mesh | undefined;\n if (!obj) return;\n if (updates.position) {\n obj.position.set(...updates.position);\n }\n if (updates.domain) {\n const color = this.config.domainColors[updates.domain] ?? this.config.defaultColor;\n (obj.material as THREE.MeshBasicMaterial).color = new THREE.Color(color);\n }\n }\n\n removeNode(nodeId: string): void {\n const obj = this.nodeObjects.get(nodeId);\n if (!obj) return;\n this.group.remove(obj);\n this.nodeObjects.delete(nodeId);\n }\n\n clear(): void {\n this.group.clear();\n this.nodeObjects.clear();\n }\n\n showNodes(nodeIds: string[]): void {\n nodeIds.forEach((id) => {\n const obj = this.nodeObjects.get(id);\n if (obj) obj.visible = true;\n });\n }\n\n hideNodes(nodeIds: string[]): void {\n nodeIds.forEach((id) => {\n const obj = this.nodeObjects.get(id);\n if (obj) obj.visible = false;\n });\n }\n\n setVisibleNodes(nodeIds: string[] | null): void {\n if (!nodeIds) {\n this.nodeObjects.forEach((obj) => {\n obj.visible = true;\n });\n return;\n }\n const visibleSet = new Set(nodeIds);\n this.nodeObjects.forEach((obj, id) => {\n obj.visible = visibleSet.has(id);\n });\n }\n\n updateLabelVisibility(): void {\n // Labels not implemented in this stub.\n }\n\n highlightNode(nodeId: string): void {\n const obj = this.nodeObjects.get(nodeId) as THREE.Mesh | undefined;\n if (obj) {\n (obj.material as THREE.MeshBasicMaterial).color = new THREE.Color('#ffffff');\n }\n }\n\n unhighlightNode(nodeId: string): void {\n const obj = this.nodeObjects.get(nodeId) as THREE.Mesh | undefined;\n if (obj) {\n const color = this.config.defaultColor;\n (obj.material as THREE.MeshBasicMaterial).color = new THREE.Color(color);\n }\n }\n\n clearHighlights(): void {\n this.nodeObjects.forEach((obj) => {\n (obj.material as THREE.MeshBasicMaterial).color = new THREE.Color(this.config.defaultColor);\n });\n }\n\n getNodePosition(nodeId: string): THREE.Vector3 | null {\n const obj = this.nodeObjects.get(nodeId);\n return obj ? obj.position.clone() : null;\n }\n\n getNodeObject(nodeId: string): THREE.Object3D | null {\n return this.nodeObjects.get(nodeId) ?? null;\n }\n\n dispose(): void {\n this.clear();\n this.scene.remove(this.group);\n }\n}\n","import * as THREE from 'three';\nimport type { NeuronVisualEdge } from '../../core/types';\n\nexport interface EdgeRenderConfig {\n defaultColor: string;\n activeColor: string;\n selectedColor: string;\n baseOpacity: number;\n strengthOpacityScale: boolean;\n}\n\nexport class EdgeRenderer {\n private group = new THREE.Group();\n private edgeObjects = new Map<string, THREE.Line>();\n\n constructor(private scene: THREE.Scene, private config: EdgeRenderConfig) {\n this.scene.add(this.group);\n }\n\n renderEdges(edges: NeuronVisualEdge[], nodePositions: Map<string, THREE.Vector3>): void {\n this.clear();\n edges.forEach((edge) => {\n const from = nodePositions.get(edge.from);\n const to = nodePositions.get(edge.to);\n if (!from || !to) return;\n const geometry = new THREE.BufferGeometry().setFromPoints([from, to]);\n const opacity = this.config.strengthOpacityScale ? edge.strength : this.config.baseOpacity;\n const material = new THREE.LineBasicMaterial({ color: this.config.defaultColor, transparent: true, opacity });\n const line = new THREE.Line(geometry, material);\n line.userData = { edgeId: edge.id };\n this.group.add(line);\n this.edgeObjects.set(edge.id, line);\n });\n }\n\n updateEdge(edgeId: string, updates: Partial<NeuronVisualEdge>): void {\n const line = this.edgeObjects.get(edgeId);\n if (!line) return;\n if (updates.strength !== undefined) {\n const opacity = this.config.strengthOpacityScale ? updates.strength : this.config.baseOpacity;\n (line.material as THREE.LineBasicMaterial).opacity = opacity;\n }\n }\n\n removeEdge(edgeId: string): void {\n const line = this.edgeObjects.get(edgeId);\n if (!line) return;\n this.group.remove(line);\n this.edgeObjects.delete(edgeId);\n }\n\n clear(): void {\n this.group.clear();\n this.edgeObjects.clear();\n }\n\n filterByStrength(minStrength: number): void {\n this.edgeObjects.forEach((line) => {\n line.visible = (line.material as THREE.LineBasicMaterial).opacity >= minStrength;\n });\n }\n\n filterByType(): void {\n // Not implemented in stub.\n }\n\n highlightEdge(edgeId: string): void {\n const line = this.edgeObjects.get(edgeId);\n if (line) {\n (line.material as THREE.LineBasicMaterial).color = new THREE.Color(this.config.activeColor);\n }\n }\n\n highlightEdgesForNode(): void {\n // Not implemented in stub.\n }\n\n unhighlightEdge(edgeId: string): void {\n const line = this.edgeObjects.get(edgeId);\n if (line) {\n (line.material as THREE.LineBasicMaterial).color = new THREE.Color(this.config.defaultColor);\n }\n }\n\n clearHighlights(): void {\n this.edgeObjects.forEach((line) => {\n (line.material as THREE.LineBasicMaterial).color = new THREE.Color(this.config.defaultColor);\n });\n }\n\n showEdges(edgeIds: string[]): void {\n edgeIds.forEach((id) => {\n const line = this.edgeObjects.get(id);\n if (line) line.visible = true;\n });\n }\n\n hideEdges(edgeIds: string[]): void {\n edgeIds.forEach((id) => {\n const line = this.edgeObjects.get(id);\n if (line) line.visible = false;\n });\n }\n\n dispose(): void {\n this.clear();\n this.scene.remove(this.group);\n }\n}\n","'use client';\n\nimport React, { useEffect, useMemo, useRef } from 'react';\nimport * as THREE from 'three';\nimport type { NeuronWebProps } from './types';\nimport { DEFAULT_THEME } from './constants';\nimport { useSceneManager } from './hooks/useSceneManager';\nimport { NodeRenderer } from './scene/node-renderer';\nimport { EdgeRenderer } from './scene/edge-renderer';\n\nexport function NeuronWeb({\n graphData,\n className,\n style,\n isLoading,\n error,\n renderEmptyState,\n renderLoadingState,\n ariaLabel,\n theme,\n}: NeuronWebProps): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null);\n const resolvedTheme = { ...DEFAULT_THEME, ...theme };\n\n const sceneManager = useSceneManager(containerRef, {\n backgroundColor: resolvedTheme.colors.background,\n cameraPosition: [4, 8, 20],\n cameraTarget: [0, 0, 0],\n minZoom: 4,\n maxZoom: 42,\n enableStarfield: resolvedTheme.effects.starfieldEnabled,\n starfieldCount: 1200,\n pixelRatioCap: 2,\n });\n\n const nodeRenderer = useMemo(() => {\n if (!sceneManager) return null;\n return new NodeRenderer(sceneManager.scene, {\n domainColors: resolvedTheme.colors.domainColors,\n defaultColor: resolvedTheme.colors.defaultDomainColor,\n baseScale: 0.4,\n tierScales: {\n primary: 1.6,\n secondary: 1.2,\n tertiary: 1,\n insight: 1,\n },\n glowIntensity: resolvedTheme.effects.glowIntensity,\n labelDistance: 20,\n maxVisibleLabels: 50,\n });\n }, [sceneManager]);\n\n const edgeRenderer = useMemo(() => {\n if (!sceneManager) return null;\n return new EdgeRenderer(sceneManager.scene, {\n defaultColor: resolvedTheme.colors.edgeDefault,\n activeColor: resolvedTheme.colors.edgeActive,\n selectedColor: resolvedTheme.colors.edgeSelected,\n baseOpacity: 0.5,\n strengthOpacityScale: true,\n });\n }, [sceneManager]);\n\n useEffect(() => {\n if (!sceneManager || !nodeRenderer || !edgeRenderer) return;\n nodeRenderer.renderNodes(graphData.nodes);\n const positions = new Map<string, THREE.Vector3>();\n graphData.nodes.forEach((node) => {\n if (!node.position) return;\n positions.set(node.slug, new THREE.Vector3(...node.position));\n });\n edgeRenderer.renderEdges(graphData.edges, positions);\n }, [graphData, sceneManager, nodeRenderer, edgeRenderer]);\n\n if (isLoading) {\n return (\n <div className={className} style={style} aria-label={ariaLabel}>\n {renderLoadingState ? renderLoadingState() : <div>Loading…</div>}\n </div>\n );\n }\n\n if (error) {\n return (\n <div className={className} style={style} aria-label={ariaLabel}>\n {renderEmptyState ? renderEmptyState() : <div>{error}</div>}\n </div>\n );\n }\n\n if (!graphData.nodes.length) {\n return (\n <div className={className} style={style} aria-label={ariaLabel}>\n {renderEmptyState ? renderEmptyState() : <div>No data</div>}\n </div>\n );\n }\n\n return <div ref={containerRef} className={className} style={style} aria-label={ariaLabel} />;\n}\n","import { DEFAULT_THEME } from '../constants';\nimport type { NeuronWebTheme } from '../types';\n\nexport class ThemeEngine {\n private theme: NeuronWebTheme;\n onThemeChange: (theme: NeuronWebTheme) => void = () => {};\n\n constructor(initialTheme?: Partial<NeuronWebTheme>) {\n this.theme = { ...DEFAULT_THEME, ...initialTheme } as NeuronWebTheme;\n }\n\n getTheme(): NeuronWebTheme {\n return this.theme;\n }\n\n setTheme(theme: Partial<NeuronWebTheme>): void {\n this.theme = { ...this.theme, ...theme } as NeuronWebTheme;\n this.onThemeChange(this.theme);\n }\n\n resetTheme(): void {\n this.theme = { ...DEFAULT_THEME };\n this.onThemeChange(this.theme);\n }\n\n setDomainColor(domain: string, color: string): void {\n this.theme.colors.domainColors[domain] = color;\n this.onThemeChange(this.theme);\n }\n\n setBackground(color: string): void {\n this.theme.colors.background = color;\n this.onThemeChange(this.theme);\n }\n\n setLabelStyle(style: Partial<NeuronWebTheme['typography']>): void {\n this.theme.typography = { ...this.theme.typography, ...style };\n this.onThemeChange(this.theme);\n }\n\n applyPreset(preset: 'dark' | 'light' | 'custom'): void {\n if (preset === 'light') {\n this.theme = {\n ...DEFAULT_THEME,\n colors: { ...DEFAULT_THEME.colors, background: '#f7f7fb', labelText: '#111' },\n };\n } else if (preset === 'dark') {\n this.theme = { ...DEFAULT_THEME };\n }\n this.onThemeChange(this.theme);\n }\n\n saveToStorage(): void {\n if (typeof window === 'undefined') return;\n window.localStorage.setItem('omi-neuron-theme', JSON.stringify(this.theme));\n }\n\n loadFromStorage(): void {\n if (typeof window === 'undefined') return;\n const stored = window.localStorage.getItem('omi-neuron-theme');\n if (stored) {\n this.theme = { ...this.theme, ...(JSON.parse(stored) as NeuronWebTheme) };\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
version: '3.8'
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
pg-{{REPO_NAME}}:
|
|
5
|
+
image: {{IMAGE_NAME}}
|
|
6
|
+
container_name: {{CONTAINER_NAME}}
|
|
7
|
+
restart: unless-stopped
|
|
8
|
+
environment:
|
|
9
|
+
POSTGRES_USER: {{DB_USER}}
|
|
10
|
+
POSTGRES_PASSWORD: {{DB_PASSWORD}}
|
|
11
|
+
POSTGRES_DB: {{DB_NAME}}
|
|
12
|
+
ports:
|
|
13
|
+
- "{{DB_PORT}}:5432"
|
|
14
|
+
volumes:
|
|
15
|
+
- {{VOLUME_NAME}}:/var/lib/postgresql/data
|
|
16
|
+
healthcheck:
|
|
17
|
+
test: ["CMD-SHELL", "pg_isready -U {{DB_USER}} -d {{DB_NAME}}"]
|
|
18
|
+
interval: 10s
|
|
19
|
+
timeout: 5s
|
|
20
|
+
retries: 5
|
|
21
|
+
deploy:
|
|
22
|
+
resources:
|
|
23
|
+
limits:
|
|
24
|
+
memory: {{MEMORY_LIMIT}}
|
|
25
|
+
|
|
26
|
+
volumes:
|
|
27
|
+
{{VOLUME_NAME}}:
|
|
28
|
+
name: {{REPO_NAME}}_neuron_data
|
package/package.json
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@omiron33/omi-neuron-web",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A drop-in Next.js library for data analysis and 3D visualization with OpenAI-powered insights",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"omi-neuron": "./dist/cli/index.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"require": "./dist/index.cjs"
|
|
17
|
+
},
|
|
18
|
+
"./visualization": {
|
|
19
|
+
"types": "./dist/visualization/index.d.ts",
|
|
20
|
+
"import": "./dist/visualization/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./api": {
|
|
23
|
+
"types": "./dist/api/index.d.ts",
|
|
24
|
+
"import": "./dist/api/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./cli": {
|
|
27
|
+
"types": "./dist/cli/index.d.ts",
|
|
28
|
+
"import": "./dist/cli/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./migration": {
|
|
31
|
+
"types": "./dist/migration/index.d.ts",
|
|
32
|
+
"import": "./dist/migration/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"docker",
|
|
38
|
+
"README.md"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public",
|
|
42
|
+
"registry": "https://registry.npmjs.org/"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsup",
|
|
46
|
+
"dev": "tsup --watch",
|
|
47
|
+
"lint": "eslint src/",
|
|
48
|
+
"lint:fix": "eslint src/ --fix",
|
|
49
|
+
"format": "prettier --write src/",
|
|
50
|
+
"typecheck": "tsc --noEmit",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"prepublishOnly": "pnpm run build",
|
|
54
|
+
"changeset": "changeset",
|
|
55
|
+
"version": "changeset version",
|
|
56
|
+
"release": "pnpm build && changeset publish",
|
|
57
|
+
"prerelease": "pnpm run test && pnpm run build"
|
|
58
|
+
},
|
|
59
|
+
"keywords": [
|
|
60
|
+
"nextjs",
|
|
61
|
+
"react",
|
|
62
|
+
"threejs",
|
|
63
|
+
"graph",
|
|
64
|
+
"visualization",
|
|
65
|
+
"openai",
|
|
66
|
+
"embeddings",
|
|
67
|
+
"knowledge-graph",
|
|
68
|
+
"neuron-web",
|
|
69
|
+
"data-analysis"
|
|
70
|
+
],
|
|
71
|
+
"author": "",
|
|
72
|
+
"license": "MIT",
|
|
73
|
+
"peerDependencies": {
|
|
74
|
+
"next": ">=13.0.0",
|
|
75
|
+
"react": ">=18.0.0",
|
|
76
|
+
"react-dom": ">=18.0.0",
|
|
77
|
+
"three": ">=0.150.0"
|
|
78
|
+
},
|
|
79
|
+
"peerDependenciesMeta": {
|
|
80
|
+
"three": {
|
|
81
|
+
"optional": true
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"dependencies": {
|
|
85
|
+
"chalk": "^5.6.2",
|
|
86
|
+
"commander": "^14.0.2",
|
|
87
|
+
"nanoid": "^5.1.6",
|
|
88
|
+
"openai": "^6.15.0",
|
|
89
|
+
"pg": "^8.16.3",
|
|
90
|
+
"slugify": "^1.6.6",
|
|
91
|
+
"zod": "^4.3.4"
|
|
92
|
+
},
|
|
93
|
+
"devDependencies": {
|
|
94
|
+
"@changesets/changelog-github": "^0.5.1",
|
|
95
|
+
"@changesets/cli": "^2.27.7",
|
|
96
|
+
"@eslint/js": "^9.39.0",
|
|
97
|
+
"@types/node": "^25.0.3",
|
|
98
|
+
"@types/pg": "^8.16.0",
|
|
99
|
+
"@types/react": "^19.2.7",
|
|
100
|
+
"@types/react-dom": "^19.2.3",
|
|
101
|
+
"@types/three": "^0.182.0",
|
|
102
|
+
"@typescript-eslint/eslint-plugin": "^8.51.0",
|
|
103
|
+
"@typescript-eslint/parser": "^8.51.0",
|
|
104
|
+
"eslint": "^9.39.2",
|
|
105
|
+
"eslint-config-prettier": "^10.1.8",
|
|
106
|
+
"jsdom": "^24.0.0",
|
|
107
|
+
"prettier": "^3.7.4",
|
|
108
|
+
"tsup": "^8.5.1",
|
|
109
|
+
"typescript": "^5.9.3",
|
|
110
|
+
"vitest": "^4.0.16"
|
|
111
|
+
},
|
|
112
|
+
"packageManager": "pnpm@10.27.0",
|
|
113
|
+
"engines": {
|
|
114
|
+
"node": ">=18.0.0"
|
|
115
|
+
}
|
|
116
|
+
}
|