@ai.ntellect/core 0.6.16 → 0.6.19
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/.mocharc.json +1 -2
- package/README.md +123 -178
- package/dist/graph/controller.js +29 -6
- package/dist/graph/index.js +402 -0
- package/dist/index.js +22 -7
- package/dist/interfaces/index.js +15 -0
- package/dist/modules/agenda/adapters/node-cron/index.js +29 -0
- package/dist/modules/agenda/index.js +140 -0
- package/dist/{services/embedding.js → modules/embedding/adapters/ai/index.js} +24 -7
- package/dist/modules/embedding/index.js +59 -0
- package/dist/modules/memory/adapters/in-memory/index.js +210 -0
- package/dist/{memory → modules/memory}/adapters/meilisearch/index.js +97 -2
- package/dist/{memory → modules/memory}/adapters/redis/index.js +77 -15
- package/dist/modules/memory/index.js +103 -0
- package/dist/utils/{stringifiy-zod-schema.js → generate-action-schema.js} +5 -5
- package/graph/controller.ts +38 -14
- package/graph/index.ts +468 -0
- package/index.ts +25 -7
- package/interfaces/index.ts +346 -28
- package/modules/agenda/adapters/node-cron/index.ts +25 -0
- package/modules/agenda/index.ts +159 -0
- package/modules/embedding/adapters/ai/index.ts +42 -0
- package/modules/embedding/index.ts +45 -0
- package/modules/memory/adapters/in-memory/index.ts +203 -0
- package/{memory → modules/memory}/adapters/meilisearch/index.ts +114 -8
- package/modules/memory/adapters/redis/index.ts +164 -0
- package/modules/memory/index.ts +93 -0
- package/package.json +4 -4
- package/test/graph/index.test.ts +646 -0
- package/test/modules/agenda/node-cron.test.ts +286 -0
- package/test/modules/embedding/ai.test.ts +78 -0
- package/test/modules/memory/adapters/in-memory.test.ts +153 -0
- package/test/{memory → modules/memory}/adapters/meilisearch.test.ts +80 -94
- package/test/modules/memory/adapters/redis.test.ts +169 -0
- package/test/modules/memory/base.test.ts +230 -0
- package/test/services/agenda.test.ts +279 -280
- package/tsconfig.json +0 -3
- package/types/index.ts +82 -203
- package/utils/{stringifiy-zod-schema.ts → generate-action-schema.ts} +3 -3
- package/app/README.md +0 -36
- package/app/app/favicon.ico +0 -0
- package/app/app/globals.css +0 -21
- package/app/app/gun.ts +0 -0
- package/app/app/layout.tsx +0 -18
- package/app/app/page.tsx +0 -321
- package/app/eslint.config.mjs +0 -16
- package/app/next.config.ts +0 -7
- package/app/package-lock.json +0 -5912
- package/app/package.json +0 -31
- package/app/pnpm-lock.yaml +0 -4031
- package/app/postcss.config.mjs +0 -8
- package/app/public/file.svg +0 -1
- package/app/public/globe.svg +0 -1
- package/app/public/next.svg +0 -1
- package/app/public/vercel.svg +0 -1
- package/app/public/window.svg +0 -1
- package/app/tailwind.config.ts +0 -18
- package/app/tsconfig.json +0 -27
- package/dist/graph/graph.js +0 -162
- package/dist/memory/index.js +0 -9
- package/dist/services/agenda.js +0 -115
- package/dist/services/queue.js +0 -142
- package/dist/utils/experimental-graph-rag.js +0 -152
- package/dist/utils/generate-object.js +0 -111
- package/dist/utils/inject-actions.js +0 -16
- package/dist/utils/queue-item-transformer.js +0 -24
- package/dist/utils/sanitize-results.js +0 -60
- package/graph/graph.ts +0 -193
- package/memory/adapters/redis/index.ts +0 -103
- package/memory/index.ts +0 -22
- package/services/agenda.ts +0 -118
- package/services/embedding.ts +0 -26
- package/services/queue.ts +0 -145
- package/test/.env.test +0 -4
- package/test/graph/engine.test.ts +0 -533
- package/test/memory/adapters/redis.test.ts +0 -160
- package/test/memory/base.test.ts +0 -229
- package/test/services/queue.test.ts +0 -286
- package/utils/experimental-graph-rag.ts +0 -170
- package/utils/generate-object.ts +0 -117
- package/utils/inject-actions.ts +0 -19
- package/utils/queue-item-transformer.ts +0 -38
- package/utils/sanitize-results.ts +0 -66
package/app/app/page.tsx
DELETED
@@ -1,321 +0,0 @@
|
|
1
|
-
"use client";
|
2
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
3
|
-
import ForceGraph2D from "react-force-graph-2d";
|
4
|
-
import { MeilisearchAdapter } from "../../memory/adapters/meilisearch";
|
5
|
-
|
6
|
-
// Interfaces restent les mêmes
|
7
|
-
export interface GraphNode {
|
8
|
-
id: number;
|
9
|
-
name?: string;
|
10
|
-
neighbors: GraphNode[];
|
11
|
-
links: GraphLink[];
|
12
|
-
x?: number;
|
13
|
-
y?: number;
|
14
|
-
}
|
15
|
-
|
16
|
-
export interface GraphLink {
|
17
|
-
source: number | GraphNode;
|
18
|
-
target: number | GraphNode;
|
19
|
-
relation?: string;
|
20
|
-
}
|
21
|
-
const SPACING_FORCE = -200; // Augmente la répulsion entre les nœuds
|
22
|
-
|
23
|
-
async function fetchGraphData() {
|
24
|
-
const memoryManager = new MeilisearchAdapter({
|
25
|
-
apiKey: process.env.NEXT_PUBLIC_MEILISEARCH_API_KEY,
|
26
|
-
host: process.env.NEXT_PUBLIC_MEILISEARCH_HOST,
|
27
|
-
});
|
28
|
-
|
29
|
-
const existingNodesMemories = await memoryManager.getAllMemories("nodes");
|
30
|
-
const existingEdgesMemories = await memoryManager.getAllMemories("edges");
|
31
|
-
|
32
|
-
let nodes: GraphNode[] = existingNodesMemories.map((memory) => ({
|
33
|
-
id: memory.id,
|
34
|
-
name: memory.data.name,
|
35
|
-
neighbors: [],
|
36
|
-
links: [],
|
37
|
-
}));
|
38
|
-
|
39
|
-
let nodeMap: Record<string, GraphNode> = {};
|
40
|
-
nodes.forEach((node, idx) => {
|
41
|
-
nodeMap[existingNodesMemories[idx].id] = node;
|
42
|
-
});
|
43
|
-
|
44
|
-
let links: GraphLink[] = existingEdgesMemories
|
45
|
-
.map((memory) => {
|
46
|
-
const sourceNode = nodeMap[memory.data.source];
|
47
|
-
const targetNode = nodeMap[memory.data.target];
|
48
|
-
|
49
|
-
if (!sourceNode || !targetNode) {
|
50
|
-
console.warn(
|
51
|
-
`⚠️ Relation ignorée : ${memory.data.source} → ${memory.data.relation} → ${memory.data.target}`
|
52
|
-
);
|
53
|
-
return null;
|
54
|
-
}
|
55
|
-
|
56
|
-
return {
|
57
|
-
source: sourceNode,
|
58
|
-
target: targetNode,
|
59
|
-
relation: memory.data.relation,
|
60
|
-
};
|
61
|
-
})
|
62
|
-
.filter((link) => link !== null) as GraphLink[];
|
63
|
-
|
64
|
-
return { nodes, links };
|
65
|
-
}
|
66
|
-
|
67
|
-
const NODE_R = 12;
|
68
|
-
|
69
|
-
const HighlightGraph = () => {
|
70
|
-
const fgRef = useRef<any>(null);
|
71
|
-
const [data, setData] = useState<{ nodes: GraphNode[]; links: GraphLink[] }>({
|
72
|
-
nodes: [],
|
73
|
-
links: [],
|
74
|
-
});
|
75
|
-
const [highlightNodes, setHighlightNodes] = useState(new Set<GraphNode>());
|
76
|
-
const [highlightLinks, setHighlightLinks] = useState(new Set<GraphLink>());
|
77
|
-
const [hoverNode, setHoverNode] = useState<GraphNode | null>(null);
|
78
|
-
const [selectedNode, setSelectedNode] = useState<GraphNode | null>(null);
|
79
|
-
|
80
|
-
useEffect(() => {
|
81
|
-
const loadGraphData = async () => {
|
82
|
-
try {
|
83
|
-
const graphData = await fetchGraphData();
|
84
|
-
setData(graphData);
|
85
|
-
} catch (error) {
|
86
|
-
console.error("❌ Erreur lors de la récupération du graphe :", error);
|
87
|
-
}
|
88
|
-
};
|
89
|
-
|
90
|
-
loadGraphData();
|
91
|
-
}, []);
|
92
|
-
|
93
|
-
useEffect(() => {
|
94
|
-
if (fgRef.current && data.nodes.length > 0) {
|
95
|
-
fgRef.current.d3Force("charge")?.strength(-200);
|
96
|
-
fgRef.current.d3Force("link")?.distance(200);
|
97
|
-
}
|
98
|
-
}, [data]);
|
99
|
-
|
100
|
-
useMemo(() => {
|
101
|
-
data.links.forEach((link) => {
|
102
|
-
const a =
|
103
|
-
typeof link.source === "object"
|
104
|
-
? link.source
|
105
|
-
: data.nodes.find((node) => node.id === link.source);
|
106
|
-
const b =
|
107
|
-
typeof link.target === "object"
|
108
|
-
? link.target
|
109
|
-
: data.nodes.find((node) => node.id === link.target);
|
110
|
-
|
111
|
-
if (!a || !b) return;
|
112
|
-
|
113
|
-
if (!a.neighbors.includes(b)) a.neighbors.push(b);
|
114
|
-
if (!b.neighbors.includes(a)) b.neighbors.push(a);
|
115
|
-
if (!a.links.includes(link)) a.links.push(link);
|
116
|
-
if (!b.links.includes(link)) b.links.push(link);
|
117
|
-
});
|
118
|
-
}, [data]);
|
119
|
-
|
120
|
-
const handleNodeHover = useCallback((node: GraphNode | null) => {
|
121
|
-
setHoverNode(node);
|
122
|
-
}, []);
|
123
|
-
|
124
|
-
const handleNodeClick = useCallback((node: GraphNode) => {
|
125
|
-
// Mise à jour des nœuds et liens en surbrillance
|
126
|
-
const newHighlightNodes = new Set<GraphNode>([node, ...node.neighbors]);
|
127
|
-
const newHighlightLinks = new Set<GraphLink>(node.links);
|
128
|
-
|
129
|
-
setHighlightNodes(newHighlightNodes);
|
130
|
-
setHighlightLinks(newHighlightLinks);
|
131
|
-
setSelectedNode(node);
|
132
|
-
|
133
|
-
if (node.x !== undefined && node.y !== undefined && fgRef.current) {
|
134
|
-
fgRef.current.centerAt(node.x, node.y, 1000);
|
135
|
-
}
|
136
|
-
}, []);
|
137
|
-
|
138
|
-
const getNodeColor = useCallback(
|
139
|
-
(node: GraphNode) => {
|
140
|
-
if (selectedNode?.id === node.id) {
|
141
|
-
return "#3b82f6"; // Bleu vif pour le nœud sélectionné
|
142
|
-
}
|
143
|
-
if (highlightNodes.has(node)) {
|
144
|
-
return "#60a5fa"; // Bleu clair pour les voisins
|
145
|
-
}
|
146
|
-
return selectedNode ? "#1e3a8a" : "#1d4ed8"; // Assombri si non connecté, normal sinon
|
147
|
-
},
|
148
|
-
[selectedNode, highlightNodes]
|
149
|
-
);
|
150
|
-
|
151
|
-
const paintRing = useCallback(
|
152
|
-
(node: GraphNode, ctx: CanvasRenderingContext2D) => {
|
153
|
-
const x = node.x ?? 0;
|
154
|
-
const y = node.y ?? 0;
|
155
|
-
|
156
|
-
// Effet de lueur pour les nœuds en surbrillance
|
157
|
-
if (highlightNodes.has(node)) {
|
158
|
-
ctx.beginPath();
|
159
|
-
ctx.arc(x, y, NODE_R + 4, 0, 2 * Math.PI);
|
160
|
-
ctx.fillStyle = "rgba(147, 197, 253, 0.3)"; // Lueur bleue
|
161
|
-
ctx.fill();
|
162
|
-
}
|
163
|
-
|
164
|
-
// Nœud principal
|
165
|
-
ctx.beginPath();
|
166
|
-
ctx.arc(x, y, NODE_R, 0, 2 * Math.PI);
|
167
|
-
ctx.fillStyle = getNodeColor(node);
|
168
|
-
ctx.fill();
|
169
|
-
|
170
|
-
// Bordure
|
171
|
-
ctx.strokeStyle = highlightNodes.has(node) ? "#ffffff" : "#94a3b8";
|
172
|
-
ctx.lineWidth = highlightNodes.has(node) ? 2.5 : 2.5;
|
173
|
-
ctx.stroke();
|
174
|
-
|
175
|
-
// Label
|
176
|
-
const label = node.name ?? `Node ${node.id}`;
|
177
|
-
ctx.font = "14px Inter, system-ui, sans-serif";
|
178
|
-
const textWidth = ctx.measureText(label).width;
|
179
|
-
|
180
|
-
// Fond du label
|
181
|
-
ctx.fillStyle = "#000000";
|
182
|
-
ctx.globalAlpha = 0.8;
|
183
|
-
ctx.fillRect(x - textWidth / 2 - 6, y - NODE_R - 24, textWidth + 12, 22);
|
184
|
-
ctx.globalAlpha = 1;
|
185
|
-
|
186
|
-
// Texte
|
187
|
-
ctx.textAlign = "center";
|
188
|
-
ctx.fillStyle = "white";
|
189
|
-
ctx.fillText(label, x, y - NODE_R - 8);
|
190
|
-
},
|
191
|
-
[hoverNode, selectedNode, highlightNodes, getNodeColor]
|
192
|
-
);
|
193
|
-
|
194
|
-
const clearSelection = useCallback(() => {
|
195
|
-
setSelectedNode(null);
|
196
|
-
setHighlightNodes(new Set());
|
197
|
-
setHighlightLinks(new Set());
|
198
|
-
}, []);
|
199
|
-
|
200
|
-
return (
|
201
|
-
<div className="drawer">
|
202
|
-
<input
|
203
|
-
id="my-drawer"
|
204
|
-
type="checkbox"
|
205
|
-
className="drawer-toggle"
|
206
|
-
checked={selectedNode !== null}
|
207
|
-
onChange={(e) => !e.target.checked && clearSelection()}
|
208
|
-
/>
|
209
|
-
<div
|
210
|
-
className="drawer-content"
|
211
|
-
style={{ height: "100vh", background: "#0f172a" }}
|
212
|
-
>
|
213
|
-
<ForceGraph2D
|
214
|
-
ref={fgRef}
|
215
|
-
graphData={data}
|
216
|
-
nodeRelSize={NODE_R}
|
217
|
-
autoPauseRedraw={false}
|
218
|
-
linkWidth={(link) => (highlightLinks.has(link as GraphLink) ? 5 : 2)}
|
219
|
-
linkColor={(link) =>
|
220
|
-
highlightLinks.has(link as GraphLink) ? "#60a5fa" : "#64748b"
|
221
|
-
}
|
222
|
-
linkDirectionalParticles={4}
|
223
|
-
linkDirectionalParticleWidth={(link) =>
|
224
|
-
highlightLinks.has(link as GraphLink) ? 6 : 2
|
225
|
-
}
|
226
|
-
linkDirectionalParticleSpeed={0.004}
|
227
|
-
linkDirectionalParticleColor={(link) =>
|
228
|
-
highlightLinks.has(link as GraphLink) ? "#93c5fd" : "#94a3b8"
|
229
|
-
}
|
230
|
-
nodeCanvasObjectMode={() => "before"}
|
231
|
-
nodeCanvasObject={paintRing}
|
232
|
-
onNodeHover={handleNodeHover}
|
233
|
-
onNodeClick={handleNodeClick}
|
234
|
-
linkLabel={(link: GraphLink) => link.relation ?? ""}
|
235
|
-
backgroundColor="#0f172a"
|
236
|
-
linkCanvasObjectMode={() => "after"}
|
237
|
-
linkCanvasObject={(
|
238
|
-
link: GraphLink,
|
239
|
-
ctx: CanvasRenderingContext2D
|
240
|
-
) => {
|
241
|
-
const start = link.source as GraphNode;
|
242
|
-
const end = link.target as GraphNode;
|
243
|
-
const textPos = {
|
244
|
-
x: start.x! + (end.x! - start.x!) * 0.5,
|
245
|
-
y: start.y! + (end.y! - start.y!) * 0.5,
|
246
|
-
};
|
247
|
-
|
248
|
-
if (!textPos.x || !textPos.y) return;
|
249
|
-
|
250
|
-
// Fond du label
|
251
|
-
const label = link.relation || "";
|
252
|
-
ctx.font = "12px Inter";
|
253
|
-
const textWidth = ctx.measureText(label).width;
|
254
|
-
|
255
|
-
ctx.fillStyle = "#000000";
|
256
|
-
ctx.globalAlpha = 0.8;
|
257
|
-
ctx.fillRect(
|
258
|
-
textPos.x - textWidth / 2 - 4,
|
259
|
-
textPos.y - 8,
|
260
|
-
textWidth + 8,
|
261
|
-
16
|
262
|
-
);
|
263
|
-
ctx.globalAlpha = 1;
|
264
|
-
|
265
|
-
// Texte de la relation
|
266
|
-
ctx.textAlign = "center";
|
267
|
-
ctx.textBaseline = "middle";
|
268
|
-
ctx.fillStyle = highlightLinks.has(link) ? "#93c5fd" : "#ffffff";
|
269
|
-
ctx.fillText(label, textPos.x, textPos.y);
|
270
|
-
}}
|
271
|
-
d3AlphaDecay={0.05}
|
272
|
-
d3VelocityDecay={0.2}
|
273
|
-
/>
|
274
|
-
</div>
|
275
|
-
<div className="drawer-side">
|
276
|
-
<label htmlFor="my-drawer" className="drawer-overlay"></label>
|
277
|
-
<div className="bg-slate-900 text-white min-h-full w-80 p-6 shadow-xl">
|
278
|
-
{selectedNode ? (
|
279
|
-
<div className="space-y-6">
|
280
|
-
<h3 className="text-xl font-bold border-b border-slate-700 pb-2">
|
281
|
-
{selectedNode.name || `Node ${selectedNode.id}`}
|
282
|
-
</h3>
|
283
|
-
<div>
|
284
|
-
<h4 className="text-lg font-semibold mb-3">Connexions</h4>
|
285
|
-
<ul className="space-y-2">
|
286
|
-
{selectedNode.neighbors.map((neighbor) => (
|
287
|
-
<li
|
288
|
-
key={neighbor.id}
|
289
|
-
className="pl-2 border-l-2 border-blue-500"
|
290
|
-
>
|
291
|
-
<button
|
292
|
-
className="text-blue-400 hover:text-blue-300 transition-colors"
|
293
|
-
onClick={() => handleNodeClick(neighbor)}
|
294
|
-
>
|
295
|
-
{neighbor.name || `Node ${neighbor.id}`}
|
296
|
-
</button>
|
297
|
-
</li>
|
298
|
-
))}
|
299
|
-
</ul>
|
300
|
-
</div>
|
301
|
-
<button
|
302
|
-
className="w-full px-4 py-2 bg-slate-700 text-white rounded hover:bg-slate-600 transition-colors"
|
303
|
-
onClick={clearSelection}
|
304
|
-
>
|
305
|
-
Fermer
|
306
|
-
</button>
|
307
|
-
</div>
|
308
|
-
) : (
|
309
|
-
<p className="text-slate-400">
|
310
|
-
Sélectionnez un nœud pour voir ses détails
|
311
|
-
</p>
|
312
|
-
)}
|
313
|
-
</div>
|
314
|
-
</div>
|
315
|
-
</div>
|
316
|
-
);
|
317
|
-
};
|
318
|
-
|
319
|
-
export default function Home() {
|
320
|
-
return <HighlightGraph />;
|
321
|
-
}
|
package/app/eslint.config.mjs
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
import { dirname } from "path";
|
2
|
-
import { fileURLToPath } from "url";
|
3
|
-
import { FlatCompat } from "@eslint/eslintrc";
|
4
|
-
|
5
|
-
const __filename = fileURLToPath(import.meta.url);
|
6
|
-
const __dirname = dirname(__filename);
|
7
|
-
|
8
|
-
const compat = new FlatCompat({
|
9
|
-
baseDirectory: __dirname,
|
10
|
-
});
|
11
|
-
|
12
|
-
const eslintConfig = [
|
13
|
-
...compat.extends("next/core-web-vitals", "next/typescript"),
|
14
|
-
];
|
15
|
-
|
16
|
-
export default eslintConfig;
|