@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
package/dist/index.js
ADDED
|
@@ -0,0 +1,654 @@
|
|
|
1
|
+
import { nodeCreateSchema, DEFAULT_ANALYSIS_SETTINGS, DEFAULT_VISUALIZATION_SETTINGS } from './chunk-XNR42GCJ.js';
|
|
2
|
+
export { DEFAULT_ANALYSIS_SETTINGS, DEFAULT_VISUALIZATION_SETTINGS, ScoringEngine, analysisOptionsSchema, analysisRequestSchema, analysisSettingsSchema, buildDelete, buildInsert, buildSelect, buildUpdate, buildWhereClause, createDatabase, createDatabaseFromEnv, databaseSettingsSchema, domainConfigSchema, edgeCreateSchema, edgeEvidenceSchema, edgeFilterSchema, edgeUpdateSchema, expandGraphRequestSchema, findPathRequestSchema, findSimilarRequestSchema, getDatabase, getGraphParamsSchema, listEdgesParamsSchema, listNodesParamsSchema, neuronConfigSchema, neuronSettingsSchema, neuronSettingsUpdateSchema, nodeBatchCreateSchema, nodeCreateSchema, nodeFilterSchema, nodeTierSchema, nodeTypeConfigSchema, nodeUpdateSchema, paginationSchema, relationshipTypeConfigSchema, resetDatabaseSingleton, semanticSearchRequestSchema, visualizationSettingsSchema } from './chunk-XNR42GCJ.js';
|
|
3
|
+
export { DockerManager } from './chunk-TFLMPBX7.js';
|
|
4
|
+
import { createEvent, EventBus } from './chunk-RQCGONPN.js';
|
|
5
|
+
export { AnalysisPipeline, ClusteringEngine, Database, EmbeddingsService, EventBus, RelationshipEngine, createEvent } from './chunk-RQCGONPN.js';
|
|
6
|
+
export { MigrationRunner, migration001, migration002, migration003, migration004, migrations } from './chunk-PSDVPB7Y.js';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import slugify from 'slugify';
|
|
9
|
+
import { createContext, useContext, useState, useCallback, useEffect, useMemo } from 'react';
|
|
10
|
+
import { jsx } from 'react/jsx-runtime';
|
|
11
|
+
|
|
12
|
+
var clusteringConfigSchema = z.object({
|
|
13
|
+
algorithm: z.enum(["kmeans", "dbscan", "hierarchical"]),
|
|
14
|
+
clusterCount: z.coerce.number().int().min(1).optional(),
|
|
15
|
+
minClusterSize: z.coerce.number().int().min(1).optional(),
|
|
16
|
+
similarityThreshold: z.coerce.number().min(0).max(1).optional(),
|
|
17
|
+
epsilon: z.coerce.number().min(0).optional(),
|
|
18
|
+
minSamples: z.coerce.number().int().min(1).optional()
|
|
19
|
+
});
|
|
20
|
+
var clusterCreateSchema = z.object({
|
|
21
|
+
label: z.string().min(1).max(255),
|
|
22
|
+
clusterType: z.string().max(100).optional(),
|
|
23
|
+
centroid: z.array(z.number()).optional(),
|
|
24
|
+
memberCount: z.number().int().min(0).optional(),
|
|
25
|
+
avgSimilarity: z.number().min(0).max(1).optional(),
|
|
26
|
+
cohesion: z.number().min(0).max(1).optional(),
|
|
27
|
+
description: z.string().optional(),
|
|
28
|
+
keywords: z.array(z.string()).optional(),
|
|
29
|
+
metadata: z.record(z.string(), z.unknown()).optional()
|
|
30
|
+
});
|
|
31
|
+
var clusterUpdateSchema = clusterCreateSchema.partial();
|
|
32
|
+
|
|
33
|
+
// src/core/events/helpers.ts
|
|
34
|
+
var createNodeEvent = (type, payload, source = "system") => createEvent(type, payload, source);
|
|
35
|
+
var createEdgeEvent = (type, payload, source = "system") => createEvent(type, payload, source);
|
|
36
|
+
var createAnalysisEvent = (type, payload, source = "analysis") => createEvent(type, payload, source);
|
|
37
|
+
var createGenericEvent = (type, payload, source = "system") => createEvent(type, payload, source);
|
|
38
|
+
|
|
39
|
+
// src/core/events/middleware/logging.ts
|
|
40
|
+
var loggingMiddleware = (event, next) => {
|
|
41
|
+
console.debug(`[omi-neuron:event] ${event.type}`, event);
|
|
42
|
+
void next();
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// src/core/events/middleware/validation.ts
|
|
46
|
+
var validationMiddleware = (event, next) => {
|
|
47
|
+
if (!event.type) {
|
|
48
|
+
throw new Error("Event missing type");
|
|
49
|
+
}
|
|
50
|
+
if (!event.timestamp) {
|
|
51
|
+
throw new Error("Event missing timestamp");
|
|
52
|
+
}
|
|
53
|
+
return next();
|
|
54
|
+
};
|
|
55
|
+
var stripHtml = (value) => value.replace(/<[^>]+>/g, " ");
|
|
56
|
+
var normalizeValue = (value) => {
|
|
57
|
+
if (value === null || value === void 0) return void 0;
|
|
58
|
+
if (value instanceof Date) return value.toISOString();
|
|
59
|
+
if (Array.isArray(value)) return value.map((item) => normalizeValue(item)).filter(Boolean).join(" ");
|
|
60
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
61
|
+
return String(value);
|
|
62
|
+
};
|
|
63
|
+
var flattenObject = (obj, prefix = "") => {
|
|
64
|
+
const result = {};
|
|
65
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
66
|
+
const nextKey = prefix ? `${prefix}.${key}` : key;
|
|
67
|
+
if (value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
|
|
68
|
+
Object.assign(result, flattenObject(value, nextKey));
|
|
69
|
+
} else {
|
|
70
|
+
result[nextKey] = value;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
};
|
|
75
|
+
var DataProcessor = class {
|
|
76
|
+
constructor(options = {}) {
|
|
77
|
+
this.options = options;
|
|
78
|
+
}
|
|
79
|
+
processItem(item) {
|
|
80
|
+
const flattened = flattenObject(item);
|
|
81
|
+
const labelField = this.options.labelField ?? "label";
|
|
82
|
+
const label = normalizeValue(flattened[labelField]) ?? "Untitled";
|
|
83
|
+
const slugField = this.options.slugField;
|
|
84
|
+
const slug = slugField ? normalizeValue(flattened[slugField]) : void 0;
|
|
85
|
+
const content = this.extractContent(flattened);
|
|
86
|
+
const metadata = this.extractMetadata(flattened);
|
|
87
|
+
const node = {
|
|
88
|
+
slug,
|
|
89
|
+
label,
|
|
90
|
+
nodeType: this.options.defaultNodeType,
|
|
91
|
+
domain: this.options.defaultDomain,
|
|
92
|
+
content,
|
|
93
|
+
metadata
|
|
94
|
+
};
|
|
95
|
+
return nodeCreateSchema.parse(node);
|
|
96
|
+
}
|
|
97
|
+
processBatch(items) {
|
|
98
|
+
const nodes = [];
|
|
99
|
+
const errors = [];
|
|
100
|
+
items.forEach((item, index) => {
|
|
101
|
+
try {
|
|
102
|
+
nodes.push(this.processItem(item));
|
|
103
|
+
} catch (error) {
|
|
104
|
+
errors.push({
|
|
105
|
+
index,
|
|
106
|
+
error: error instanceof Error ? error.message : String(error)
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
return { nodes, errors };
|
|
111
|
+
}
|
|
112
|
+
processJSON(json) {
|
|
113
|
+
const parsed = JSON.parse(json);
|
|
114
|
+
if (Array.isArray(parsed)) {
|
|
115
|
+
return this.processBatch(parsed).nodes;
|
|
116
|
+
}
|
|
117
|
+
return [this.processItem(parsed)];
|
|
118
|
+
}
|
|
119
|
+
processCSV(csv) {
|
|
120
|
+
const lines = csv.trim().split(/\r?\n/);
|
|
121
|
+
if (lines.length === 0) return [];
|
|
122
|
+
const headers = lines[0].split(",").map((h) => h.trim());
|
|
123
|
+
const items = lines.slice(1).map((line) => {
|
|
124
|
+
const values = line.split(",");
|
|
125
|
+
const item = {};
|
|
126
|
+
headers.forEach((header, idx) => {
|
|
127
|
+
item[header] = values[idx]?.trim();
|
|
128
|
+
});
|
|
129
|
+
return item;
|
|
130
|
+
});
|
|
131
|
+
return this.processBatch(items).nodes;
|
|
132
|
+
}
|
|
133
|
+
generateSlug(label, existingSlugs = /* @__PURE__ */ new Set()) {
|
|
134
|
+
const base = slugify(label, { lower: true, strict: true, trim: true }).slice(0, 255);
|
|
135
|
+
if (!existingSlugs.has(base)) return base;
|
|
136
|
+
let suffix = 1;
|
|
137
|
+
let slug = `${base}-${suffix}`;
|
|
138
|
+
while (existingSlugs.has(slug)) {
|
|
139
|
+
suffix += 1;
|
|
140
|
+
slug = `${base}-${suffix}`;
|
|
141
|
+
}
|
|
142
|
+
return slug;
|
|
143
|
+
}
|
|
144
|
+
extractContent(item) {
|
|
145
|
+
const fields = this.options.contentFields ?? ["label", "summary", "description", "content"];
|
|
146
|
+
const parts = fields.map((field) => normalizeValue(item[field])).filter((value) => Boolean(value));
|
|
147
|
+
const joined = parts.join(" ");
|
|
148
|
+
return stripHtml(joined).replace(/\s+/g, " ").trim();
|
|
149
|
+
}
|
|
150
|
+
detectDuplicates(nodes) {
|
|
151
|
+
const seen = /* @__PURE__ */ new Set();
|
|
152
|
+
const unique = [];
|
|
153
|
+
const duplicates = [];
|
|
154
|
+
nodes.forEach((node) => {
|
|
155
|
+
const slug = node.slug ?? this.generateSlug(node.label, seen);
|
|
156
|
+
if (seen.has(slug)) {
|
|
157
|
+
duplicates.push({ node, reason: `Duplicate slug: ${slug}` });
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
seen.add(slug);
|
|
161
|
+
unique.push({ ...node, slug });
|
|
162
|
+
});
|
|
163
|
+
return { unique, duplicates };
|
|
164
|
+
}
|
|
165
|
+
extractMetadata(item) {
|
|
166
|
+
if (!this.options.metadataFields?.length) return void 0;
|
|
167
|
+
const metadata = {};
|
|
168
|
+
this.options.metadataFields.forEach((field) => {
|
|
169
|
+
if (field in item) {
|
|
170
|
+
metadata[field] = item[field];
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// src/config/index.ts
|
|
178
|
+
var defineNeuronConfig = (config) => config;
|
|
179
|
+
var NeuronContext = createContext(null);
|
|
180
|
+
|
|
181
|
+
// src/react/hooks/useNeuronContext.ts
|
|
182
|
+
function useNeuronContext() {
|
|
183
|
+
const context = useContext(NeuronContext);
|
|
184
|
+
if (!context) {
|
|
185
|
+
throw new Error("useNeuronContext must be used within NeuronWebProvider");
|
|
186
|
+
}
|
|
187
|
+
return context;
|
|
188
|
+
}
|
|
189
|
+
function useNeuronGraph(options) {
|
|
190
|
+
const { api } = useNeuronContext();
|
|
191
|
+
const [nodes, setNodes] = useState([]);
|
|
192
|
+
const [edges, setEdges] = useState([]);
|
|
193
|
+
const [clusters, setClusters] = useState([]);
|
|
194
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
195
|
+
const [error, setError] = useState(null);
|
|
196
|
+
const [filters, setFilters] = useState({});
|
|
197
|
+
const [selectedNode, setSelectedNode] = useState(null);
|
|
198
|
+
const fetchGraph = useCallback(async () => {
|
|
199
|
+
setIsLoading(true);
|
|
200
|
+
try {
|
|
201
|
+
const params = {
|
|
202
|
+
domains: options?.domains,
|
|
203
|
+
nodeTypes: options?.nodeTypes,
|
|
204
|
+
minEdgeStrength: options?.minEdgeStrength
|
|
205
|
+
};
|
|
206
|
+
const response = await api.graph.get(params);
|
|
207
|
+
setNodes(response.nodes);
|
|
208
|
+
setEdges(response.edges);
|
|
209
|
+
setClusters(response.clusters ?? []);
|
|
210
|
+
setError(null);
|
|
211
|
+
} catch (err) {
|
|
212
|
+
setError(err);
|
|
213
|
+
} finally {
|
|
214
|
+
setIsLoading(false);
|
|
215
|
+
}
|
|
216
|
+
}, [api, options]);
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
void fetchGraph();
|
|
219
|
+
}, [fetchGraph]);
|
|
220
|
+
const expandFromNode = async (nodeId, depth = 1) => {
|
|
221
|
+
const response = await api.graph.expand({ fromNodeIds: [nodeId], depth, direction: "both" });
|
|
222
|
+
setNodes(response.nodes);
|
|
223
|
+
setEdges(response.edges);
|
|
224
|
+
};
|
|
225
|
+
const findPath = async (fromId, toId) => {
|
|
226
|
+
const response = await api.graph.findPath({ fromNodeId: fromId, toNodeId: toId });
|
|
227
|
+
return response.paths[0];
|
|
228
|
+
};
|
|
229
|
+
return {
|
|
230
|
+
nodes,
|
|
231
|
+
edges,
|
|
232
|
+
clusters,
|
|
233
|
+
isLoading,
|
|
234
|
+
error,
|
|
235
|
+
filters,
|
|
236
|
+
setFilters: (next) => setFilters((prev) => ({ ...prev, ...next })),
|
|
237
|
+
clearFilters: () => setFilters({}),
|
|
238
|
+
selectedNode: selectedNode ? nodes.find((node) => node.id === selectedNode) ?? null : null,
|
|
239
|
+
selectNode: (nodeId) => setSelectedNode(nodeId),
|
|
240
|
+
clearSelection: () => setSelectedNode(null),
|
|
241
|
+
refetch: fetchGraph,
|
|
242
|
+
expandFromNode,
|
|
243
|
+
findPath
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
function useNeuronNodes(options) {
|
|
247
|
+
const { api } = useNeuronContext();
|
|
248
|
+
const [nodes, setNodes] = useState([]);
|
|
249
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
250
|
+
const [error, setError] = useState(null);
|
|
251
|
+
const [page, setPage] = useState(1);
|
|
252
|
+
const [totalPages, setTotalPages] = useState(1);
|
|
253
|
+
const fetchNodes = useCallback(async () => {
|
|
254
|
+
setIsLoading(true);
|
|
255
|
+
try {
|
|
256
|
+
const response = await api.nodes.list({
|
|
257
|
+
...options?.initialFilters,
|
|
258
|
+
page,
|
|
259
|
+
limit: options?.pageSize ?? 50
|
|
260
|
+
});
|
|
261
|
+
setNodes(response.nodes);
|
|
262
|
+
setTotalPages(response.pagination.totalPages ?? 1);
|
|
263
|
+
setError(null);
|
|
264
|
+
} catch (err) {
|
|
265
|
+
setError(err);
|
|
266
|
+
} finally {
|
|
267
|
+
setIsLoading(false);
|
|
268
|
+
}
|
|
269
|
+
}, [api, options, page]);
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
void fetchNodes();
|
|
272
|
+
}, [fetchNodes]);
|
|
273
|
+
return {
|
|
274
|
+
nodes,
|
|
275
|
+
isLoading,
|
|
276
|
+
error,
|
|
277
|
+
createNode: async (data) => {
|
|
278
|
+
const response = await api.nodes.create({ nodes: [data] });
|
|
279
|
+
await fetchNodes();
|
|
280
|
+
return response.created[0];
|
|
281
|
+
},
|
|
282
|
+
updateNode: async (id, data) => {
|
|
283
|
+
const updated = await api.nodes.update(id, data);
|
|
284
|
+
await fetchNodes();
|
|
285
|
+
return updated;
|
|
286
|
+
},
|
|
287
|
+
deleteNode: async (id) => {
|
|
288
|
+
await api.nodes.delete(id);
|
|
289
|
+
await fetchNodes();
|
|
290
|
+
},
|
|
291
|
+
batchCreate: async (nodesInput) => {
|
|
292
|
+
const response = await api.nodes.create({ nodes: nodesInput });
|
|
293
|
+
await fetchNodes();
|
|
294
|
+
return response.created;
|
|
295
|
+
},
|
|
296
|
+
search: async (query) => {
|
|
297
|
+
const response = await api.nodes.list({ search: query });
|
|
298
|
+
setNodes(response.nodes);
|
|
299
|
+
},
|
|
300
|
+
pagination: {
|
|
301
|
+
page,
|
|
302
|
+
totalPages,
|
|
303
|
+
hasNext: page < totalPages,
|
|
304
|
+
hasPrev: page > 1
|
|
305
|
+
},
|
|
306
|
+
setPage,
|
|
307
|
+
nextPage: () => setPage((prev) => Math.min(prev + 1, totalPages)),
|
|
308
|
+
prevPage: () => setPage((prev) => Math.max(prev - 1, 1))
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function useNeuronAnalysis() {
|
|
312
|
+
const { api } = useNeuronContext();
|
|
313
|
+
const [activeJobs, setActiveJobs] = useState([]);
|
|
314
|
+
const [jobHistory, setJobHistory] = useState([]);
|
|
315
|
+
const [isRunning, setIsRunning] = useState(false);
|
|
316
|
+
const [currentProgress, setCurrentProgress] = useState(null);
|
|
317
|
+
const startAnalysis = async (request) => {
|
|
318
|
+
setIsRunning(true);
|
|
319
|
+
const response = await api.analyze.start(request);
|
|
320
|
+
setActiveJobs((prev) => [...prev, { ...response }]);
|
|
321
|
+
return response;
|
|
322
|
+
};
|
|
323
|
+
const cancelJob = async (jobId) => {
|
|
324
|
+
await api.analyze.cancel(jobId);
|
|
325
|
+
setActiveJobs((prev) => prev.filter((job) => job.id !== jobId));
|
|
326
|
+
};
|
|
327
|
+
const getJobStatus = async (jobId) => {
|
|
328
|
+
const response = await api.analyze.getStatus(jobId);
|
|
329
|
+
setJobHistory((prev) => [...prev, response.job]);
|
|
330
|
+
setIsRunning(false);
|
|
331
|
+
setCurrentProgress(response.job.progress ?? null);
|
|
332
|
+
return response.job;
|
|
333
|
+
};
|
|
334
|
+
return {
|
|
335
|
+
activeJobs,
|
|
336
|
+
jobHistory,
|
|
337
|
+
startAnalysis,
|
|
338
|
+
cancelJob,
|
|
339
|
+
getJobStatus,
|
|
340
|
+
isRunning,
|
|
341
|
+
currentProgress
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
function useNeuronSettings() {
|
|
345
|
+
const { settings, api, updateSettings } = useNeuronContext();
|
|
346
|
+
const [isLoading] = useState(false);
|
|
347
|
+
const [isUpdating, setIsUpdating] = useState(false);
|
|
348
|
+
const [error, setError] = useState(null);
|
|
349
|
+
const update = async (updates) => {
|
|
350
|
+
try {
|
|
351
|
+
setIsUpdating(true);
|
|
352
|
+
await updateSettings(updates);
|
|
353
|
+
} catch (err) {
|
|
354
|
+
setError(err);
|
|
355
|
+
} finally {
|
|
356
|
+
setIsUpdating(false);
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
const reset = async (sections) => {
|
|
360
|
+
await api.settings.reset();
|
|
361
|
+
if (sections?.length) {
|
|
362
|
+
await update({});
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
return {
|
|
366
|
+
settings,
|
|
367
|
+
isLoading,
|
|
368
|
+
isUpdating,
|
|
369
|
+
error,
|
|
370
|
+
updateSettings: update,
|
|
371
|
+
resetSettings: reset,
|
|
372
|
+
setDomainColor: async (domain, color) => {
|
|
373
|
+
await update({
|
|
374
|
+
visualization: {
|
|
375
|
+
...settings.visualization,
|
|
376
|
+
domainColors: { ...settings.visualization.domainColors, [domain]: color }
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
},
|
|
380
|
+
setVisualization: async (updates) => {
|
|
381
|
+
await update({ visualization: updates });
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
function useNeuronSearch() {
|
|
386
|
+
const { api } = useNeuronContext();
|
|
387
|
+
const [results, setResults] = useState([]);
|
|
388
|
+
const [isSearching, setIsSearching] = useState(false);
|
|
389
|
+
const [error, setError] = useState(null);
|
|
390
|
+
const search = async (query, options) => {
|
|
391
|
+
setIsSearching(true);
|
|
392
|
+
try {
|
|
393
|
+
const response = await api.search.semantic({ query, ...options });
|
|
394
|
+
setResults(response.results);
|
|
395
|
+
setError(null);
|
|
396
|
+
} catch (err) {
|
|
397
|
+
setError(err);
|
|
398
|
+
} finally {
|
|
399
|
+
setIsSearching(false);
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
const findSimilar = async (nodeId, options) => {
|
|
403
|
+
setIsSearching(true);
|
|
404
|
+
try {
|
|
405
|
+
const response = await api.search.similar({ nodeId, ...options });
|
|
406
|
+
setResults(response.results);
|
|
407
|
+
setError(null);
|
|
408
|
+
} catch (err) {
|
|
409
|
+
setError(err);
|
|
410
|
+
} finally {
|
|
411
|
+
setIsSearching(false);
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
return {
|
|
415
|
+
results,
|
|
416
|
+
isSearching,
|
|
417
|
+
error,
|
|
418
|
+
search,
|
|
419
|
+
findSimilar,
|
|
420
|
+
clearResults: () => setResults([])
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function useNeuronEvents() {
|
|
424
|
+
const { events } = useNeuronContext();
|
|
425
|
+
return {
|
|
426
|
+
subscribe: (type, handler) => {
|
|
427
|
+
useEffect(() => {
|
|
428
|
+
const sub = events.subscribe(type, handler);
|
|
429
|
+
return () => sub.unsubscribe();
|
|
430
|
+
}, [type, handler]);
|
|
431
|
+
},
|
|
432
|
+
emit: (type, payload) => {
|
|
433
|
+
events.emit(createEvent(type, payload, "ui"));
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
function useNodeEvents(handlers) {
|
|
438
|
+
const { events } = useNeuronContext();
|
|
439
|
+
useEffect(() => {
|
|
440
|
+
const subs = [];
|
|
441
|
+
if (handlers.onCreated) {
|
|
442
|
+
subs.push(
|
|
443
|
+
events.subscribe(
|
|
444
|
+
"node:created",
|
|
445
|
+
(event) => handlers.onCreated?.(event.payload.node)
|
|
446
|
+
)
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
if (handlers.onUpdated) {
|
|
450
|
+
subs.push(
|
|
451
|
+
events.subscribe(
|
|
452
|
+
"node:updated",
|
|
453
|
+
(event) => handlers.onUpdated?.(event.payload.node)
|
|
454
|
+
)
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
if (handlers.onDeleted) {
|
|
458
|
+
subs.push(
|
|
459
|
+
events.subscribe(
|
|
460
|
+
"node:deleted",
|
|
461
|
+
(event) => handlers.onDeleted?.(event.payload.nodeId)
|
|
462
|
+
)
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
return () => subs.forEach((sub) => sub.unsubscribe());
|
|
466
|
+
}, [handlers]);
|
|
467
|
+
}
|
|
468
|
+
function useAnalysisEvents(handlers) {
|
|
469
|
+
const { events } = useNeuronContext();
|
|
470
|
+
useEffect(() => {
|
|
471
|
+
const subs = [];
|
|
472
|
+
if (handlers.onStarted) {
|
|
473
|
+
subs.push(
|
|
474
|
+
events.subscribe(
|
|
475
|
+
"analysis:started",
|
|
476
|
+
(event) => handlers.onStarted?.(event.payload.jobId)
|
|
477
|
+
)
|
|
478
|
+
);
|
|
479
|
+
}
|
|
480
|
+
if (handlers.onProgress) {
|
|
481
|
+
subs.push(
|
|
482
|
+
events.subscribe("analysis:progress", (event) => {
|
|
483
|
+
const payload = event.payload;
|
|
484
|
+
return handlers.onProgress?.(payload.jobId, payload.progress);
|
|
485
|
+
})
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
if (handlers.onCompleted) {
|
|
489
|
+
subs.push(
|
|
490
|
+
events.subscribe(
|
|
491
|
+
"analysis:completed",
|
|
492
|
+
(event) => handlers.onCompleted?.(event.payload.job)
|
|
493
|
+
)
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
if (handlers.onFailed) {
|
|
497
|
+
subs.push(
|
|
498
|
+
events.subscribe("analysis:failed", (event) => {
|
|
499
|
+
const payload = event.payload;
|
|
500
|
+
return handlers.onFailed?.(payload.jobId, payload.error);
|
|
501
|
+
})
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
return () => subs.forEach((sub) => sub.unsubscribe());
|
|
505
|
+
}, [handlers]);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// src/react/api-client.ts
|
|
509
|
+
var NeuronApiClient = class {
|
|
510
|
+
constructor(basePath) {
|
|
511
|
+
this.basePath = basePath;
|
|
512
|
+
}
|
|
513
|
+
async request(path, options) {
|
|
514
|
+
const response = await fetch(`${this.basePath}${path}`, {
|
|
515
|
+
headers: { "Content-Type": "application/json" },
|
|
516
|
+
...options
|
|
517
|
+
});
|
|
518
|
+
if (!response.ok) {
|
|
519
|
+
throw new Error(`Request failed: ${response.status}`);
|
|
520
|
+
}
|
|
521
|
+
return response.json();
|
|
522
|
+
}
|
|
523
|
+
nodes = {
|
|
524
|
+
list: (params) => this.request(`/nodes?${new URLSearchParams(params)}`),
|
|
525
|
+
get: (id) => this.request(`/nodes/${id}`),
|
|
526
|
+
create: (data) => this.request("/nodes", { method: "POST", body: JSON.stringify(data) }),
|
|
527
|
+
update: (id, data) => this.request(`/nodes/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
|
|
528
|
+
delete: (id) => this.request(`/nodes/${id}`, { method: "DELETE" })
|
|
529
|
+
};
|
|
530
|
+
edges = {
|
|
531
|
+
list: (params) => this.request(`/edges?${new URLSearchParams(params)}`),
|
|
532
|
+
create: (data) => this.request("/edges", { method: "POST", body: JSON.stringify(data) }),
|
|
533
|
+
update: (id, data) => this.request(`/edges/${id}`, { method: "PATCH", body: JSON.stringify(data) }),
|
|
534
|
+
delete: (id) => this.request(`/edges/${id}`, { method: "DELETE" })
|
|
535
|
+
};
|
|
536
|
+
graph = {
|
|
537
|
+
get: (params) => this.request(`/graph?${new URLSearchParams(params)}`),
|
|
538
|
+
expand: (data) => this.request("/graph/expand", { method: "POST", body: JSON.stringify(data) }),
|
|
539
|
+
findPath: (data) => this.request("/graph/path", { method: "POST", body: JSON.stringify(data) })
|
|
540
|
+
};
|
|
541
|
+
analyze = {
|
|
542
|
+
start: (data) => this.request("/analyze", { method: "POST", body: JSON.stringify(data) }),
|
|
543
|
+
getStatus: (jobId) => this.request(`/analyze/${jobId}`),
|
|
544
|
+
cancel: (jobId) => this.request(`/analyze/${jobId}/cancel`, { method: "POST" })
|
|
545
|
+
};
|
|
546
|
+
settings = {
|
|
547
|
+
get: () => this.request("/settings"),
|
|
548
|
+
update: (data) => this.request("/settings", { method: "PATCH", body: JSON.stringify(data) }),
|
|
549
|
+
reset: () => this.request("/settings/reset", { method: "POST" })
|
|
550
|
+
};
|
|
551
|
+
search = {
|
|
552
|
+
semantic: (data) => this.request("/search", { method: "POST", body: JSON.stringify(data) }),
|
|
553
|
+
similar: (data) => this.request("/search/similar", { method: "POST", body: JSON.stringify(data) })
|
|
554
|
+
};
|
|
555
|
+
};
|
|
556
|
+
var buildDefaultConfig = (overrides) => ({
|
|
557
|
+
instance: {
|
|
558
|
+
name: "default",
|
|
559
|
+
version: "0.1.0",
|
|
560
|
+
repoName: "omi-neuron-web"
|
|
561
|
+
},
|
|
562
|
+
visualization: { ...DEFAULT_VISUALIZATION_SETTINGS, ...overrides?.visualization ?? {} },
|
|
563
|
+
analysis: { ...DEFAULT_ANALYSIS_SETTINGS, ...overrides?.analysis ?? {} },
|
|
564
|
+
nodeTypes: overrides?.nodeTypes ?? [],
|
|
565
|
+
domains: overrides?.domains ?? [],
|
|
566
|
+
relationshipTypes: overrides?.relationshipTypes ?? [],
|
|
567
|
+
openai: {
|
|
568
|
+
apiKey: ""
|
|
569
|
+
},
|
|
570
|
+
database: {
|
|
571
|
+
mode: "external",
|
|
572
|
+
port: 5433,
|
|
573
|
+
url: void 0
|
|
574
|
+
},
|
|
575
|
+
api: {
|
|
576
|
+
basePath: "/api/neuron",
|
|
577
|
+
enableCors: false
|
|
578
|
+
},
|
|
579
|
+
logging: {
|
|
580
|
+
level: "info",
|
|
581
|
+
prettyPrint: true
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
function NeuronWebProvider({ children, config }) {
|
|
585
|
+
const [settings, setSettings] = useState(
|
|
586
|
+
() => buildDefaultConfig(config.settings)
|
|
587
|
+
);
|
|
588
|
+
const [error, setError] = useState(null);
|
|
589
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
590
|
+
const resolvedConfig = useMemo(() => {
|
|
591
|
+
const base = buildDefaultConfig(config.settings);
|
|
592
|
+
return {
|
|
593
|
+
...base,
|
|
594
|
+
openai: {
|
|
595
|
+
apiKey: config.openaiApiKey ?? base.openai.apiKey
|
|
596
|
+
},
|
|
597
|
+
database: {
|
|
598
|
+
...base.database,
|
|
599
|
+
url: config.databaseUrl ?? base.database.url
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
}, [config]);
|
|
603
|
+
const apiClient = useMemo(() => new NeuronApiClient(resolvedConfig.api.basePath), [resolvedConfig]);
|
|
604
|
+
const eventBus = useMemo(() => new EventBus(), []);
|
|
605
|
+
useEffect(() => {
|
|
606
|
+
eventBus.subscribeAll((event) => config.onEvent?.(event));
|
|
607
|
+
}, [eventBus, config]);
|
|
608
|
+
useEffect(() => {
|
|
609
|
+
let mounted = true;
|
|
610
|
+
apiClient.settings.get().then((response) => {
|
|
611
|
+
if (mounted) {
|
|
612
|
+
setSettings(response.settings);
|
|
613
|
+
setIsInitialized(true);
|
|
614
|
+
}
|
|
615
|
+
}).catch((err) => {
|
|
616
|
+
setError(err);
|
|
617
|
+
config.onError?.(err, { message: "Failed to load settings" });
|
|
618
|
+
});
|
|
619
|
+
return () => {
|
|
620
|
+
mounted = false;
|
|
621
|
+
};
|
|
622
|
+
}, [apiClient]);
|
|
623
|
+
const updateSettings = async (updates) => {
|
|
624
|
+
const response = await apiClient.settings.update(updates);
|
|
625
|
+
setSettings(response.settings);
|
|
626
|
+
};
|
|
627
|
+
const resetSettings = async () => {
|
|
628
|
+
const response = await apiClient.settings.reset();
|
|
629
|
+
setSettings(response.settings);
|
|
630
|
+
};
|
|
631
|
+
const contextValue = useMemo(
|
|
632
|
+
() => ({
|
|
633
|
+
config: resolvedConfig,
|
|
634
|
+
settings,
|
|
635
|
+
api: apiClient,
|
|
636
|
+
events: eventBus,
|
|
637
|
+
isInitialized,
|
|
638
|
+
error,
|
|
639
|
+
updateSettings,
|
|
640
|
+
resetSettings,
|
|
641
|
+
onEvent: config.onEvent,
|
|
642
|
+
onError: config.onError
|
|
643
|
+
}),
|
|
644
|
+
[resolvedConfig, settings, apiClient, eventBus, isInitialized, error, config]
|
|
645
|
+
);
|
|
646
|
+
return /* @__PURE__ */ jsx(NeuronContext.Provider, { value: contextValue, children });
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// src/index.ts
|
|
650
|
+
var VERSION = "0.1.0";
|
|
651
|
+
|
|
652
|
+
export { DataProcessor, NeuronWebProvider, VERSION, clusterCreateSchema, clusterUpdateSchema, clusteringConfigSchema, createAnalysisEvent, createEdgeEvent, createGenericEvent, createNodeEvent, defineNeuronConfig, loggingMiddleware, useAnalysisEvents, useNeuronAnalysis, useNeuronContext, useNeuronEvents, useNeuronGraph, useNeuronNodes, useNeuronSearch, useNeuronSettings, useNodeEvents, validationMiddleware };
|
|
653
|
+
//# sourceMappingURL=index.js.map
|
|
654
|
+
//# sourceMappingURL=index.js.map
|