@ai.ntellect/core 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,30 +1,17 @@
1
- import { LanguageModelV1 } from "ai";
1
+ import { generateObject, LanguageModelV1 } from "ai";
2
2
  import { z } from "zod";
3
3
  import { CacheMemory } from "../../memory/cache";
4
4
  import { PersistentMemory } from "../../memory/persistent";
5
- import { ActionQueueManager } from "../../services/queue";
6
- import { CacheConfig, RedisCache } from "../../services/redis-cache";
7
- import { TaskScheduler } from "../../services/scheduler";
8
- import {
9
- ActionSchema,
10
- GenerateObjectResponse,
11
- MemoryScope,
12
- QueueCallbacks,
13
- } from "../../types";
14
- import { generateObject } from "../../utils/generate-object";
5
+ import { ActionSchema, MemoryScope, MyContext, SharedState } from "../../types";
15
6
  import { LLMHeaderBuilder } from "../../utils/header-builder";
16
7
  import { injectActions } from "../../utils/inject-actions";
17
8
  import { Interpreter } from "../interpreter";
18
9
  import { orchestratorInstructions } from "./context";
19
- import { State } from "./types";
20
10
 
21
- export class AgentRuntime {
11
+ export class Orchestrator {
22
12
  private readonly model: LanguageModelV1;
23
13
  private readonly tools: ActionSchema[];
24
14
  private readonly interpreters: Interpreter[];
25
- private readonly queueManager: ActionQueueManager;
26
- private readonly scheduler: TaskScheduler;
27
- private readonly cache: RedisCache;
28
15
  private memory?: {
29
16
  persistent?: PersistentMemory;
30
17
  cache?: CacheMemory;
@@ -34,23 +21,18 @@ export class AgentRuntime {
34
21
  model: LanguageModelV1,
35
22
  tools: ActionSchema[],
36
23
  interpreters: Interpreter[],
37
- redisConfig: CacheConfig,
38
24
  memory?: {
39
25
  persistent?: PersistentMemory;
40
26
  cache?: CacheMemory;
41
- },
42
- callbacks?: QueueCallbacks
27
+ }
43
28
  ) {
44
29
  this.model = model;
45
30
  this.tools = tools;
46
31
  this.interpreters = interpreters;
47
- this.queueManager = new ActionQueueManager(tools, callbacks);
48
32
  this.memory = memory;
49
- this.cache = new RedisCache(redisConfig);
50
- this.scheduler = new TaskScheduler(this, this.cache);
51
33
  }
52
34
 
53
- private async buildContext(state: State): Promise<string> {
35
+ private async buildContext(state: SharedState<MyContext>): Promise<string> {
54
36
  console.log("🧠 Building context with RAG and CAG...");
55
37
  const context = LLMHeaderBuilder.create();
56
38
 
@@ -65,18 +47,10 @@ export class AgentRuntime {
65
47
  // Add tools to context
66
48
  context.addHeader("TOOLS", injectActions(this.tools));
67
49
 
68
- // Add previous actions if any
69
- if (state.previousActions?.length) {
70
- context.addHeader(
71
- "PREVIOUS_ACTIONS",
72
- JSON.stringify(state.previousActions)
73
- );
74
- }
75
-
76
50
  // Get recent similar actions (CAG)
77
- if (this.memory?.cache) {
51
+ if (this.memory?.cache && state.messages) {
78
52
  const cacheMemories = await this.memory.cache.findSimilarActions(
79
- state.currentContext,
53
+ state.messages[state.messages.length - 1].content.toString(),
80
54
  {
81
55
  similarityThreshold: 80,
82
56
  maxResults: 3,
@@ -90,10 +64,10 @@ export class AgentRuntime {
90
64
  }
91
65
 
92
66
  // Get relevant knowledge (RAG)
93
- if (this.memory?.persistent) {
67
+ if (this.memory?.persistent && state.messages) {
94
68
  const persistentMemory =
95
69
  await this.memory.persistent.findRelevantDocuments(
96
- state.currentContext,
70
+ state.messages[state.messages.length - 1].content.toString(),
97
71
  {
98
72
  similarityThreshold: 80,
99
73
  }
@@ -109,15 +83,25 @@ export class AgentRuntime {
109
83
 
110
84
  // Add available interpreters
111
85
  context.addHeader(
112
- "AVAILABLE_INTERPRETERS",
86
+ "INTERPRETERS (choose one)",
113
87
  JSON.stringify(this.interpreters.map((i) => i.name))
88
+ .replace("[", "")
89
+ .replace("]", "")
114
90
  );
115
- console.log("Context built with memories", context.toString());
116
91
  return context.toString();
117
92
  }
118
93
 
119
- async process(state: State): Promise<{
120
- shouldContinue: boolean;
94
+ async process(
95
+ state: SharedState<MyContext>,
96
+ callbacks?: {
97
+ onStart?: () => void;
98
+ onFinish?: (event: any) => void;
99
+ }
100
+ ): Promise<{
101
+ processing: {
102
+ stop: boolean;
103
+ stopReason?: string;
104
+ };
121
105
  actions: Array<{
122
106
  name: string;
123
107
  parameters: Array<{
@@ -126,37 +110,40 @@ export class AgentRuntime {
126
110
  }>;
127
111
  scheduler?: {
128
112
  isScheduled: boolean;
129
- scheduledAtInC?: string;
130
- interval?: string;
113
+ cronExpression?: string;
131
114
  reason?: string;
132
115
  };
133
116
  }>;
134
- socialResponse?: {
135
- shouldRespond: boolean;
136
- response?: string;
137
- isPartialResponse?: boolean;
138
- };
139
- interpreter?: string;
117
+ response: string;
118
+ interpreter?: string | null;
140
119
  results?: string;
141
120
  }> {
142
- console.log("🔄 Processing state:");
143
- console.dir(state, { depth: null });
144
- if (state.previousActions?.length) {
145
- console.log(
146
- "📊 Previous actions:",
147
- state.previousActions
148
- .map((a) => (typeof a === "string" ? a : a.name))
149
- .join(", ")
150
- );
151
- }
121
+ if (callbacks?.onStart) callbacks.onStart();
152
122
 
153
123
  const context = await this.buildContext(state);
124
+ let prompt = LLMHeaderBuilder.create();
125
+ if (state.messages) {
126
+ prompt.addHeader(
127
+ "REQUEST",
128
+ state.messages[state.messages.length - 1].content.toString()
129
+ );
130
+
131
+ if (state.messages.length > 1) {
132
+ prompt.addHeader("RECENT_MESSAGES", JSON.stringify(state.messages));
133
+ }
134
+ }
135
+ if (state.context.results) {
136
+ prompt.addHeader("ACTIONS_DONE", JSON.stringify(state.context.results));
137
+ }
154
138
 
155
- console.log("\n🧠 Generating response from LLM...");
156
- const response = await generateObject<GenerateObjectResponse>({
139
+ console.log("\n🧠 Generating response from Orchestrator...");
140
+ const response = await generateObject({
157
141
  model: this.model,
158
142
  schema: z.object({
159
- shouldContinue: z.boolean(),
143
+ processing: z.object({
144
+ stop: z.boolean(),
145
+ reason: z.string(),
146
+ }),
160
147
  actions: z.array(
161
148
  z.object({
162
149
  name: z.string(),
@@ -166,67 +153,40 @@ export class AgentRuntime {
166
153
  value: z.any(),
167
154
  })
168
155
  ),
169
- scheduler: z
170
- .object({
171
- isScheduled: z.boolean(),
172
- cronExpression: z.string().optional(),
173
- reason: z.string().optional(),
174
- })
175
- .optional(),
156
+ scheduler: z.object({
157
+ isScheduled: z.boolean(),
158
+ cronExpression: z.string(),
159
+ reason: z.string(),
160
+ }),
176
161
  })
177
162
  ),
178
- socialResponse: z
179
- .object({
180
- shouldRespond: z.boolean(),
181
- response: z.string().optional(),
182
- isPartialResponse: z.boolean().optional(),
183
- })
184
- .optional(),
185
- interpreter: z.string().optional(),
163
+ response: z.string(),
164
+ interpreter: z.string().or(z.null()),
186
165
  }),
187
- prompt: state.currentContext,
188
166
  system: context.toString(),
189
167
  temperature: 0,
168
+ prompt: prompt.toString(),
190
169
  });
191
170
  console.log("🔄 Orchestrator response:");
192
171
  console.dir(response.object, { depth: null });
193
172
 
194
173
  // Force shouldContinue to false if no actions are planned
195
174
  if (response.object.actions.length === 0) {
196
- response.object.shouldContinue = false;
197
- console.log("⚠️ No actions planned, forcing shouldContinue to false");
175
+ response.object.processing.stop = true;
176
+ console.log("⚠️ No actions planned, forcing isProcessing to false");
198
177
  }
199
178
 
200
179
  // Handle social interactions and actions in a single block
201
- if (response.object.socialResponse?.shouldRespond) {
180
+ if (response.object.response) {
202
181
  console.log("\n💬 Processing social response");
203
- if (response.object.socialResponse.response) {
204
- console.log("📢 Response:", response.object.socialResponse.response);
182
+ if (response.object.response) {
183
+ console.log("📢 Response:", response.object.response);
205
184
  // Ensure all parameters have a value property
206
185
  }
207
186
  }
208
187
 
209
- // Handle scheduled actions
210
- for (const action of response.object.actions) {
211
- if (action.scheduler?.isScheduled) {
212
- await this.scheduler.scheduleRequest({
213
- originalRequest: state.currentContext,
214
- cronExpression: action.scheduler.cronExpression,
215
- });
216
- }
217
- }
218
-
219
- // Store actions in Redis cache
220
- if (response.object.actions.length > 0) {
221
- const requestId = crypto.randomUUID();
222
- await this.cache.storePreviousActions(requestId, response.object.actions);
223
- }
224
-
225
- // Store message in recent messages
226
- await this.cache.storeRecentMessage(state.currentContext, {
227
- socialResponse: response.object.socialResponse,
228
- });
188
+ if (callbacks?.onFinish) callbacks.onFinish(response.object);
229
189
 
230
- return response.object;
190
+ return response.object as any;
231
191
  }
232
192
  }
@@ -1,11 +1,11 @@
1
+ import { CoreMessage } from "ai";
1
2
  import { QueueResult } from "../../types";
2
3
 
3
4
  export interface State {
4
5
  currentContext: string;
5
6
  previousActions: (string | QueueResult)[];
6
- reward?: number;
7
- userRequest?: string;
8
7
  results?: string;
8
+ recentMessages: CoreMessage[];
9
9
  }
10
10
 
11
11
  export interface Action {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai.ntellect/core",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -16,7 +16,9 @@
16
16
  "@ai-sdk/openai": "1.0.6",
17
17
  "@types/node-cron": "^3.0.11",
18
18
  "ai": "^3.0.0",
19
+ "chalk": "^5.4.1",
19
20
  "ethers": "^6.13.5",
21
+ "ioredis": "^5.4.2",
20
22
  "langchain": "^0.3.11",
21
23
  "node-cron": "^3.0.3",
22
24
  "readline": "^1.3.0",
package/script.js ADDED
@@ -0,0 +1,167 @@
1
+ // Dimensions de l'espace SVG
2
+ const width = 800;
3
+ const height = 600;
4
+
5
+ // Exemple de données pour les nœuds et les arêtes
6
+ const nodes = [
7
+ { id: "fetchData", name: "Fetch Data", group: 1, selected: false },
8
+ { id: "analyzeData", name: "Analyze Data", group: 1, selected: false },
9
+ { id: "sendAlert", name: "Send Alert", group: 1, selected: false },
10
+ ];
11
+
12
+ const links = [
13
+ { source: "fetchData", target: "analyzeData" },
14
+ { source: "analyzeData", target: "sendAlert" },
15
+ ];
16
+
17
+ // Simulation de force
18
+ const simulation = d3
19
+ .forceSimulation(nodes)
20
+ .force(
21
+ "link",
22
+ d3.forceLink(links).id((d) => d.id)
23
+ )
24
+ .force("charge", d3.forceManyBody().strength(-300))
25
+ .force("center", d3.forceCenter(width / 2, height / 2));
26
+
27
+ // Créer le conteneur SVG
28
+ const svg = d3.select("#graph").attr("width", width).attr("height", height);
29
+
30
+ // Groupes pour liens et nœuds
31
+ const linkGroup = svg
32
+ .append("g")
33
+ .attr("class", "links")
34
+ .attr("stroke", "#999")
35
+ .attr("stroke-opacity", 0.6);
36
+
37
+ const nodeGroup = svg.append("g").attr("class", "nodes");
38
+
39
+ // Fonction pour mettre à jour le graphe
40
+ function updateGraph() {
41
+ // Mettre à jour les liens
42
+ const link = linkGroup.selectAll("line").data(links);
43
+
44
+ link
45
+ .enter()
46
+ .append("line")
47
+ .attr("stroke-width", 2)
48
+ .merge(link)
49
+ .attr("x1", (d) => d.source.x)
50
+ .attr("y1", (d) => d.source.y)
51
+ .attr("x2", (d) => d.target.x)
52
+ .attr("y2", (d) => d.target.y);
53
+
54
+ link.exit().remove();
55
+
56
+ // Mettre à jour les nœuds
57
+ const node = nodeGroup.selectAll("circle").data(nodes, (d) => d.id);
58
+
59
+ node.exit().remove();
60
+
61
+ const nodeEnter = node
62
+ .enter()
63
+ .append("circle")
64
+ .attr("r", 20)
65
+ .attr("fill", (d) => (d.selected ? "orange" : "#69b3a2"))
66
+ .attr("stroke", "#fff")
67
+ .attr("stroke-width", 1.5)
68
+ .call(
69
+ d3
70
+ .drag()
71
+ .on("start", dragstarted)
72
+ .on("drag", dragged)
73
+ .on("end", dragended)
74
+ )
75
+ .on("click", nodeClicked);
76
+
77
+ nodeEnter
78
+ .merge(node)
79
+ .attr("cx", (d) => d.x)
80
+ .attr("cy", (d) => d.y)
81
+ .attr("fill", (d) => (d.selected ? "orange" : "#69b3a2"));
82
+
83
+ // Ajouter des labels
84
+ const label = nodeGroup.selectAll("text").data(nodes);
85
+
86
+ label.exit().remove();
87
+
88
+ label
89
+ .enter()
90
+ .append("text")
91
+ .attr("dy", 4)
92
+ .attr("dx", 25)
93
+ .merge(label)
94
+ .attr("x", (d) => d.x)
95
+ .attr("y", (d) => d.y)
96
+ .text((d) => d.name);
97
+
98
+ simulation.on("tick", () => {
99
+ link
100
+ .attr("x1", (d) => d.source.x)
101
+ .attr("y1", (d) => d.source.y)
102
+ .attr("x2", (d) => d.target.x)
103
+ .attr("y2", (d) => d.target.y);
104
+
105
+ node.attr("cx", (d) => d.x).attr("cy", (d) => d.y);
106
+
107
+ label.attr("x", (d) => d.x + 25).attr("y", (d) => d.y);
108
+ });
109
+
110
+ updateWorkflowOrder();
111
+ }
112
+
113
+ // Fonction pour mettre à jour l'ordre du workflow
114
+ function updateWorkflowOrder() {
115
+ const selectedNodes = nodes.filter((node) => node.selected);
116
+ if (selectedNodes.length > 0) {
117
+ workflowOrder = selectedNodes.map((node) => node.name);
118
+ } else {
119
+ const startNode = nodes.find(
120
+ (node) => !links.some((link) => link.target === node.id)
121
+ );
122
+
123
+ if (!startNode) {
124
+ workflowOrder = [];
125
+ console.log("Workflow Order: []");
126
+ return;
127
+ }
128
+
129
+ workflowOrder = [];
130
+ let currentNode = startNode;
131
+ while (currentNode) {
132
+ workflowOrder.push(currentNode.name);
133
+ const nextLink = links.find((link) => link.source === currentNode.id);
134
+ currentNode = nextLink
135
+ ? nodes.find((node) => node.id === nextLink.target)
136
+ : null;
137
+ }
138
+ }
139
+ console.log("Workflow Order:", workflowOrder);
140
+ }
141
+
142
+ // Gestion de la sélection multiple
143
+ function nodeClicked(event, node) {
144
+ node.selected = !node.selected;
145
+ updateGraph();
146
+ }
147
+
148
+ // Gestion du drag & drop
149
+ function dragstarted(event, d) {
150
+ if (!event.active) simulation.alphaTarget(0.3).restart();
151
+ d.fx = d.x;
152
+ d.fy = d.y;
153
+ }
154
+
155
+ function dragged(event, d) {
156
+ d.fx = event.x;
157
+ d.fy = event.y;
158
+ }
159
+
160
+ function dragended(event, d) {
161
+ if (!event.active) simulation.alphaTarget(0);
162
+ d.fx = null;
163
+ d.fy = null;
164
+ }
165
+
166
+ // Initialisation
167
+ updateGraph();
@@ -1,6 +1,6 @@
1
1
  import cron from "node-cron";
2
- import { AgentRuntime } from "../llm/orchestrator";
3
- import { RedisCache } from "./redis-cache";
2
+ import { Orchestrator } from "../llm/orchestrator";
3
+ import { RedisCache } from "./cache";
4
4
 
5
5
  interface ScheduledRequest {
6
6
  id: string;
@@ -10,24 +10,30 @@ interface ScheduledRequest {
10
10
  createdAt: Date;
11
11
  }
12
12
 
13
- export class TaskScheduler {
13
+ export class Agenda {
14
14
  private scheduledRequests: Map<string, ScheduledRequest> = new Map();
15
15
  private cronJobs: Map<string, cron.ScheduledTask> = new Map();
16
- private readonly agentRuntime: AgentRuntime;
16
+ private readonly orchestrator: Orchestrator;
17
17
  private readonly cache: RedisCache;
18
18
 
19
- constructor(agentRuntime: AgentRuntime, cache: RedisCache) {
20
- this.agentRuntime = agentRuntime;
19
+ constructor(orchestrator: Orchestrator, cache: RedisCache) {
20
+ this.orchestrator = orchestrator;
21
21
  this.cache = cache;
22
22
  }
23
23
 
24
24
  /**
25
25
  * Schedule a new request to be processed later
26
26
  */
27
- async scheduleRequest(request: {
28
- originalRequest: string;
29
- cronExpression: string;
30
- }): Promise<string> {
27
+ async scheduleRequest(
28
+ request: {
29
+ originalRequest: string;
30
+ cronExpression: string;
31
+ },
32
+ callbacks?: {
33
+ onScheduled?: (id: string) => void;
34
+ onExecuted?: (id: string, originalRequest: string) => void;
35
+ }
36
+ ): Promise<string> {
31
37
  const id = crypto.randomUUID();
32
38
 
33
39
  const scheduledRequest: ScheduledRequest = {
@@ -42,6 +48,9 @@ export class TaskScheduler {
42
48
  const cronJob = cron.schedule(request.cronExpression, async () => {
43
49
  await this.executeScheduledRequest(scheduledRequest);
44
50
 
51
+ if (callbacks?.onExecuted)
52
+ callbacks.onExecuted(id, scheduledRequest.originalRequest);
53
+
45
54
  if (!scheduledRequest.isRecurring) {
46
55
  this.cancelScheduledRequest(id);
47
56
  }
@@ -51,9 +60,7 @@ export class TaskScheduler {
51
60
  this.scheduledRequests.set(id, scheduledRequest);
52
61
  this.cronJobs.set(id, cronJob);
53
62
 
54
- console.log(
55
- `✅ Request scheduled with cron expression: ${request.cronExpression}`
56
- );
63
+ if (callbacks?.onScheduled) callbacks.onScheduled(id);
57
64
 
58
65
  return id;
59
66
  }
@@ -67,28 +74,6 @@ export class TaskScheduler {
67
74
  try {
68
75
  console.log(`🔄 Executing scheduled request from ${request.createdAt}`);
69
76
 
70
- // Récupérer les actions précédentes du cache
71
- const previousActions = await this.cache.getPreviousActions(request.id);
72
-
73
- // Add context about when this request was scheduled
74
- const contextualRequest = `You are a scheduler.
75
- You were asked to execute this request: ${request.originalRequest}\n
76
- Date of the request: ${request.createdAt.toISOString()}\n
77
- Act like if you know the request was scheduled.
78
- Don't reschedule the same action.
79
- Just execute it.`;
80
-
81
- // Process the request as if it was just received
82
- const result = await this.agentRuntime.process({
83
- currentContext: contextualRequest,
84
- previousActions,
85
- });
86
-
87
- // Store the new actions in cache
88
- if (result.actions.length > 0) {
89
- await this.cache.storePreviousActions(request.id, result.actions);
90
- }
91
-
92
77
  console.log(`✅ Scheduled request executed successfully`);
93
78
  } catch (error) {
94
79
  console.error(`❌ Failed to execute scheduled request:`, error);