@ai.ntellect/core 0.1.90 → 0.1.92
Sign up to get free protection for your applications and to get access to all the features.
- package/agent/index.ts +45 -52
- package/llm/evaluator/context.ts +25 -40
- package/llm/evaluator/index.ts +75 -28
- package/llm/orchestrator/context.ts +13 -19
- package/llm/orchestrator/index.ts +112 -25
- package/llm/synthesizer/context.ts +62 -48
- package/llm/synthesizer/index.ts +76 -19
- package/memory/cache.ts +43 -26
- package/memory/persistent.ts +21 -25
- package/package.json +1 -1
- package/services/queue.ts +28 -13
- package/types.ts +3 -1
package/agent/index.ts
CHANGED
@@ -9,16 +9,32 @@ import {
|
|
9
9
|
MemoryScope,
|
10
10
|
MemoryType,
|
11
11
|
QueueResult,
|
12
|
-
TransformedQueueItem,
|
13
12
|
User,
|
14
13
|
} from "../types";
|
15
14
|
import { QueueItemTransformer } from "../utils/queue-item-transformer";
|
16
15
|
import { ResultSanitizer } from "../utils/sanitize-results";
|
17
16
|
import { ActionHandler } from "./handlers/ActionHandler";
|
18
17
|
|
18
|
+
export type State = {
|
19
|
+
behavior: {
|
20
|
+
role: string;
|
21
|
+
language: string;
|
22
|
+
guidelines: {
|
23
|
+
important: string[];
|
24
|
+
warnings: string[];
|
25
|
+
steps?: string[];
|
26
|
+
};
|
27
|
+
};
|
28
|
+
userRequest: string;
|
29
|
+
actions: ActionSchema[];
|
30
|
+
results: QueueResult[];
|
31
|
+
examplesMessages?: {
|
32
|
+
role: string;
|
33
|
+
content: string;
|
34
|
+
}[];
|
35
|
+
};
|
36
|
+
|
19
37
|
export class Agent {
|
20
|
-
private readonly SIMILARITY_THRESHOLD = 95;
|
21
|
-
private readonly MAX_RESULTS = 1;
|
22
38
|
private readonly actionHandler: ActionHandler;
|
23
39
|
private readonly user: User;
|
24
40
|
private readonly orchestrator: Orchestrator;
|
@@ -54,45 +70,19 @@ export class Agent {
|
|
54
70
|
this.accumulatedResults = [];
|
55
71
|
}
|
56
72
|
|
57
|
-
async process(
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
let isSimilar: boolean = false;
|
65
|
-
|
66
|
-
if (this.cacheMemory) {
|
67
|
-
const similarActions = await this.cacheMemory.findSimilarQueries(prompt, {
|
68
|
-
similarityThreshold: this.SIMILARITY_THRESHOLD,
|
69
|
-
maxResults: this.MAX_RESULTS,
|
70
|
-
userId: this.user.id,
|
71
|
-
scope: MemoryScope.GLOBAL,
|
72
|
-
});
|
73
|
-
|
74
|
-
if (similarActions.length > 0) {
|
75
|
-
actions = QueueItemTransformer.transformActionsToQueueItems(
|
76
|
-
similarActions[0].data
|
77
|
-
);
|
78
|
-
isSimilar = true;
|
79
|
-
}
|
80
|
-
}
|
81
|
-
|
82
|
-
if (!actions?.length && !isSimilar) {
|
83
|
-
console.log("No similar actions found in cache for query: ", prompt);
|
84
|
-
console.log("Requesting orchestrator for actions..");
|
85
|
-
const request = await this.orchestrator.process(contextualizedPrompt);
|
86
|
-
events.onMessage?.(request);
|
87
|
-
actions = request.actions;
|
88
|
-
}
|
73
|
+
async process(prompt: string, events: AgentEvent): Promise<any> {
|
74
|
+
console.log("Requesting orchestrator for actions..");
|
75
|
+
const request = await this.orchestrator.process(
|
76
|
+
prompt,
|
77
|
+
this.accumulatedResults
|
78
|
+
);
|
79
|
+
events.onMessage?.(request);
|
89
80
|
|
90
|
-
return actions
|
81
|
+
return request.actions.length > 0
|
91
82
|
? this.handleActions(
|
92
83
|
{
|
93
84
|
initialPrompt: prompt,
|
94
|
-
|
95
|
-
actions: actions as ActionSchema[],
|
85
|
+
actions: request.actions as ActionSchema[],
|
96
86
|
},
|
97
87
|
events
|
98
88
|
)
|
@@ -102,11 +92,9 @@ export class Agent {
|
|
102
92
|
private async handleActions(
|
103
93
|
{
|
104
94
|
initialPrompt,
|
105
|
-
contextualizedPrompt,
|
106
95
|
actions,
|
107
96
|
}: {
|
108
97
|
initialPrompt: string;
|
109
|
-
contextualizedPrompt: string;
|
110
98
|
actions: ActionSchema[];
|
111
99
|
},
|
112
100
|
events: AgentEvent
|
@@ -144,11 +132,10 @@ export class Agent {
|
|
144
132
|
console.log("Accumulated results:");
|
145
133
|
console.dir(this.accumulatedResults, { depth: null });
|
146
134
|
|
147
|
-
const sanitizedResults = ResultSanitizer.sanitize(this.accumulatedResults);
|
135
|
+
// const sanitizedResults = ResultSanitizer.sanitize(this.accumulatedResults);
|
148
136
|
const evaluation = await evaluator.process(
|
149
137
|
initialPrompt,
|
150
|
-
|
151
|
-
sanitizedResults
|
138
|
+
this.accumulatedResults
|
152
139
|
);
|
153
140
|
|
154
141
|
events.onMessage?.(evaluation);
|
@@ -157,8 +144,7 @@ export class Agent {
|
|
157
144
|
this.evaluatorIteration++;
|
158
145
|
return this.handleActions(
|
159
146
|
{
|
160
|
-
initialPrompt:
|
161
|
-
contextualizedPrompt: initialPrompt,
|
147
|
+
initialPrompt: initialPrompt,
|
162
148
|
actions: evaluation.nextActionsNeeded,
|
163
149
|
},
|
164
150
|
events
|
@@ -191,12 +177,16 @@ export class Agent {
|
|
191
177
|
this.accumulatedResults = [];
|
192
178
|
this.evaluatorIteration = 0;
|
193
179
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
180
|
+
for (const action of actionsResult.data) {
|
181
|
+
if (!action.error) {
|
182
|
+
await this.cacheMemory?.createMemory({
|
183
|
+
content: actionsResult.initialPrompt,
|
184
|
+
data: action.result,
|
185
|
+
scope: MemoryScope.GLOBAL,
|
186
|
+
type: MemoryType.ACTION,
|
187
|
+
});
|
188
|
+
}
|
189
|
+
}
|
200
190
|
|
201
191
|
return this.stream
|
202
192
|
? (
|
@@ -205,7 +195,10 @@ export class Agent {
|
|
205
195
|
summaryData
|
206
196
|
)
|
207
197
|
).toDataStreamResponse()
|
208
|
-
: await synthesizer.process(
|
198
|
+
: await synthesizer.process(
|
199
|
+
actionsResult.initialPrompt,
|
200
|
+
this.accumulatedResults
|
201
|
+
);
|
209
202
|
}
|
210
203
|
|
211
204
|
private transformActions(actions: ActionSchema[]) {
|
package/llm/evaluator/context.ts
CHANGED
@@ -1,43 +1,28 @@
|
|
1
|
-
import { ActionSchema } from "../../types";
|
2
|
-
import { injectActions } from "../../utils/inject-actions";
|
3
1
|
export const evaluatorContext = {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
Follow these steps to evaluate:
|
30
|
-
1. Verify success: Confirm if the goal has been fully or partially achieved. If partially, describe what's missing.
|
31
|
-
2. Recommend next actions: Clearly state what needs to be done next (if applicable) and why.
|
32
|
-
3. Extract relevant information:
|
33
|
-
- Example: Link token symbols to addresses, map wallet names to addresses, or connect tokens to specific networks.
|
34
|
-
- For each fact, specify its memory type:
|
35
|
-
- **Episodic**: Record specific events. Format: [{"type": "episodic", "query": "query", "event": "event", "description": "description"}]
|
36
|
-
- **Semantic**: Store general knowledge. Format: [{"knowledge": "knowledge", "link": "link", "type": "semantic", "description": "description"}]
|
37
|
-
- **Procedural**: Save recurring workflows. Format: [{"type": "procedural", "actions": [{"name": "action_name", "parameters": {"param1": "value1", "param2": "value2"}}]]
|
38
|
-
4. Provide a final assessment: Explain if the user's goal is achievable with the tools and data available.
|
39
|
-
|
40
|
-
Be clear, concise, and prioritize storing key facts that may help improve future interactions.
|
41
|
-
`;
|
2
|
+
behavior: {
|
3
|
+
language: "user_language",
|
4
|
+
role: "Your role is to verify if the goal has been achieved and make a response or suggest next actions.",
|
5
|
+
guidelines: {
|
6
|
+
important: [
|
7
|
+
"Verify if all required actions were executed successfully.",
|
8
|
+
"Check if the results align with the initial goal.",
|
9
|
+
"Identify and extract additional relevant information naturally during the process. Examples:",
|
10
|
+
" - Link a token symbol (e.g., 'USDC') to its address (e.g., '0xA0b8...6EB48').",
|
11
|
+
" - Associate a wallet address (e.g., '0x1234...abcd') to a user-friendly name (e.g., 'Work Wallet').",
|
12
|
+
" - Map a token address (e.g., '0x6B17...71d0F') back to its symbol or name (e.g., 'DAI').",
|
13
|
+
"Store these facts in memory with their type (episodic, semantic, or procedural).",
|
14
|
+
],
|
15
|
+
warnings: [
|
16
|
+
"NEVER modify the results directly.",
|
17
|
+
"NEVER make assumptions about missing data.",
|
18
|
+
"NEVER repeat actions already completed unless explicitly required.",
|
19
|
+
],
|
20
|
+
steps: [
|
21
|
+
"Verify success: Confirm if the goal has been fully or partially achieved. If partially, describe what's missing.",
|
22
|
+
"Recommend next actions: Clearly state what needs to be done next (if applicable) and why.",
|
23
|
+
"Store key facts: Store any relevant information in memory with their type (episodic, semantic, or procedural).",
|
24
|
+
"Be clear, concise, and prioritize storing key facts that may help improve future interactions.",
|
25
|
+
],
|
26
|
+
},
|
42
27
|
},
|
43
28
|
};
|
package/llm/evaluator/index.ts
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
import { openai } from "@ai-sdk/openai";
|
2
2
|
import { generateObject } from "ai";
|
3
3
|
import { z } from "zod";
|
4
|
+
import { State } from "../../agent";
|
4
5
|
import { PersistentMemory } from "../../memory/persistent";
|
5
|
-
import { ActionSchema, MemoryScope } from "../../types";
|
6
|
+
import { ActionSchema, MemoryScope, QueueResult } from "../../types";
|
7
|
+
import { injectActions } from "../../utils/inject-actions";
|
6
8
|
import { evaluatorContext } from "./context";
|
7
9
|
|
8
10
|
export class Evaluator {
|
@@ -15,13 +17,43 @@ export class Evaluator {
|
|
15
17
|
this.memory = memory;
|
16
18
|
}
|
17
19
|
|
18
|
-
|
20
|
+
composeContext(state: State) {
|
21
|
+
const { behavior, userRequest, actions, results } = state;
|
22
|
+
const { role, language, guidelines } = behavior;
|
23
|
+
const { important, warnings, steps } = guidelines;
|
24
|
+
|
25
|
+
const context = `
|
26
|
+
# ROLE: ${role}
|
27
|
+
# LANGUAGE: ${language}
|
28
|
+
# IMPORTANT: ${important.join("\n")}
|
29
|
+
# NEVER: ${warnings.join("\n")}
|
30
|
+
# USER_REQUEST: ${userRequest}
|
31
|
+
# ACTIONS AVAILABLE: ${injectActions(actions)}
|
32
|
+
# CURRENT_RESULTS: ${results.map((r) => r.result).join(", ")}
|
33
|
+
# STEPS: ${steps?.join("\n") || ""}
|
34
|
+
`;
|
35
|
+
|
36
|
+
return context;
|
37
|
+
}
|
38
|
+
|
39
|
+
async process(prompt: string, results: QueueResult[]): Promise<any> {
|
19
40
|
try {
|
41
|
+
const context = this.composeContext({
|
42
|
+
behavior: evaluatorContext.behavior,
|
43
|
+
userRequest: prompt,
|
44
|
+
actions: this.tools,
|
45
|
+
results: results,
|
46
|
+
});
|
47
|
+
|
48
|
+
console.log("\n🔍 Evaluator processing");
|
49
|
+
console.log("Goal:", prompt);
|
50
|
+
console.log("Results to evaluate:", JSON.stringify(results, null, 2));
|
51
|
+
|
20
52
|
const response = await generateObject({
|
21
53
|
model: this.model,
|
22
54
|
schema: z.object({
|
23
55
|
isRemindNeeded: z.boolean(),
|
24
|
-
|
56
|
+
importantToRemembers: z.array(
|
25
57
|
z.object({
|
26
58
|
memoryType: z.string(),
|
27
59
|
content: z.string(),
|
@@ -30,11 +62,21 @@ export class Evaluator {
|
|
30
62
|
),
|
31
63
|
response: z.string(),
|
32
64
|
isNextActionNeeded: z.boolean(),
|
33
|
-
nextActionsNeeded:
|
65
|
+
nextActionsNeeded: z.array(
|
66
|
+
z.object({
|
67
|
+
name: z.string(),
|
68
|
+
parameters: z.array(
|
69
|
+
z.object({
|
70
|
+
name: z.string(),
|
71
|
+
value: z.any(),
|
72
|
+
})
|
73
|
+
),
|
74
|
+
})
|
75
|
+
),
|
34
76
|
why: z.string(),
|
35
77
|
}),
|
36
78
|
prompt: prompt,
|
37
|
-
system:
|
79
|
+
system: context,
|
38
80
|
});
|
39
81
|
|
40
82
|
const validatedResponse = {
|
@@ -46,47 +88,52 @@ export class Evaluator {
|
|
46
88
|
};
|
47
89
|
|
48
90
|
if (validatedResponse.isRemindNeeded) {
|
49
|
-
|
50
|
-
|
91
|
+
console.log(
|
92
|
+
"\n💭 Processing important memories to store",
|
93
|
+
validatedResponse
|
94
|
+
);
|
95
|
+
for (const item of validatedResponse.importantToRemembers) {
|
96
|
+
console.log("\n📝 Processing memory item:");
|
97
|
+
console.log("Type:", item.memoryType);
|
98
|
+
console.log("Content:", item.content);
|
99
|
+
|
51
100
|
const memories = await this.memory.searchSimilarQueries(
|
52
101
|
item.content,
|
53
102
|
{
|
54
103
|
similarityThreshold: 95,
|
55
104
|
}
|
56
105
|
);
|
106
|
+
|
57
107
|
if (memories.length > 0) {
|
58
|
-
console.log("Similar
|
59
|
-
memories,
|
60
|
-
});
|
108
|
+
console.log("🔄 Similar memory already exists - skipping");
|
61
109
|
continue;
|
62
110
|
}
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
scope: MemoryScope.GLOBAL,
|
74
|
-
createdAt: new Date(),
|
75
|
-
});
|
76
|
-
}
|
111
|
+
|
112
|
+
console.log("✨ Storing new memory");
|
113
|
+
await this.memory.createMemory({
|
114
|
+
id: crypto.randomUUID(),
|
115
|
+
purpose: item.memoryType,
|
116
|
+
query: item.content,
|
117
|
+
data: item.data,
|
118
|
+
scope: MemoryScope.GLOBAL,
|
119
|
+
createdAt: new Date(),
|
120
|
+
});
|
77
121
|
}
|
78
122
|
}
|
79
123
|
|
80
|
-
console.log("
|
81
|
-
console.
|
124
|
+
console.log("\n✅ Evaluation completed");
|
125
|
+
console.log("─".repeat(50));
|
126
|
+
console.log("Results:", JSON.stringify(validatedResponse, null, 2));
|
127
|
+
|
82
128
|
return validatedResponse;
|
83
129
|
} catch (error: any) {
|
130
|
+
console.error("\n❌ Evaluator error:", error.message);
|
84
131
|
if (error) {
|
85
132
|
console.log("Evaluator error");
|
86
133
|
console.dir(error.value, { depth: null });
|
87
134
|
console.error(error.message);
|
88
|
-
if (error.value.
|
89
|
-
for (const item of error.value.
|
135
|
+
if (error.value.importantToRemembers.length > 0) {
|
136
|
+
for (const item of error.value.importantToRemembers) {
|
90
137
|
// Check if the item is already in the memory
|
91
138
|
const memories = await this.memory.searchSimilarQueries(
|
92
139
|
item.content
|
@@ -1,22 +1,16 @@
|
|
1
|
-
import { ActionSchema } from "../../types";
|
2
|
-
import { injectActions } from "../../utils/inject-actions";
|
3
|
-
|
4
1
|
export const orchestratorContext = {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
The actions are: ${injectActions(tools)}
|
20
|
-
`;
|
2
|
+
behavior: {
|
3
|
+
language: "user_language",
|
4
|
+
role: "You are the orchestrator agent. Your role is to determine what actions are needed to achieve the user goal.",
|
5
|
+
guidelines: {
|
6
|
+
important: [
|
7
|
+
"If there is no action to do, you must answer in the 'answer' field.",
|
8
|
+
"If some parameters are not clear or missing, don't add the action, YOU MUST ask the user for them.",
|
9
|
+
"ALWAYS use the same language as user request. (If it's English, use English, if it's French, use French, etc.)",
|
10
|
+
"For QUESTIONS or ANALYSIS, BEFORE executing ANY actions, you CAN search in memory and internal knowledge base.",
|
11
|
+
"NEVER repeat same actions if the user doesn't ask for it.",
|
12
|
+
],
|
13
|
+
warnings: [],
|
14
|
+
},
|
21
15
|
},
|
22
16
|
};
|
@@ -1,32 +1,71 @@
|
|
1
1
|
import { openai } from "@ai-sdk/openai";
|
2
2
|
import { generateObject } from "ai";
|
3
3
|
import { z } from "zod";
|
4
|
+
import { State } from "../../agent";
|
5
|
+
import { CacheMemory } from "../../memory/cache";
|
4
6
|
import { PersistentMemory } from "../../memory/persistent";
|
5
|
-
import {
|
7
|
+
import {
|
8
|
+
ActionSchema,
|
9
|
+
MemoryScope,
|
10
|
+
MemoryScopeType,
|
11
|
+
QueueResult,
|
12
|
+
} from "../../types";
|
13
|
+
import { injectActions } from "../../utils/inject-actions";
|
6
14
|
import { orchestratorContext } from "./context";
|
7
15
|
|
8
|
-
export class Orchestrator
|
16
|
+
export class Orchestrator {
|
9
17
|
private readonly model = openai("gpt-4o");
|
10
18
|
public tools: ActionSchema[];
|
11
|
-
private memory:
|
19
|
+
private memory: {
|
20
|
+
persistent: PersistentMemory;
|
21
|
+
cache: CacheMemory;
|
22
|
+
};
|
23
|
+
private id: string;
|
12
24
|
|
13
|
-
constructor(
|
25
|
+
constructor(
|
26
|
+
id: string,
|
27
|
+
tools: ActionSchema[],
|
28
|
+
memory: {
|
29
|
+
persistent: PersistentMemory;
|
30
|
+
cache: CacheMemory;
|
31
|
+
}
|
32
|
+
) {
|
33
|
+
this.id = id;
|
14
34
|
this.memory = memory;
|
15
35
|
this.tools = [
|
16
36
|
...tools,
|
17
37
|
{
|
18
|
-
name: "
|
38
|
+
name: "search_internal_knowledge_base",
|
19
39
|
description:
|
20
40
|
"Search for relevant information in the internal knowledge base",
|
21
41
|
parameters: z.object({
|
22
42
|
query: z.string(),
|
23
43
|
}),
|
24
44
|
execute: async ({ query }: { query: string }) => {
|
25
|
-
const
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
return
|
45
|
+
const persistentMemories =
|
46
|
+
await this.memory.persistent.searchSimilarQueries(query, {
|
47
|
+
similarityThreshold: 70,
|
48
|
+
});
|
49
|
+
return persistentMemories;
|
50
|
+
},
|
51
|
+
},
|
52
|
+
{
|
53
|
+
name: "search_cache_memory",
|
54
|
+
description: "Search for relevant information in the cache",
|
55
|
+
parameters: z.object({
|
56
|
+
query: z.string(),
|
57
|
+
}),
|
58
|
+
execute: async ({ query }: { query: string }) => {
|
59
|
+
const cacheMemories = await this.memory.cache.findSimilarQueries(
|
60
|
+
query,
|
61
|
+
{
|
62
|
+
similarityThreshold: 70,
|
63
|
+
maxResults: 1,
|
64
|
+
userId: this.id,
|
65
|
+
scope: MemoryScope.GLOBAL,
|
66
|
+
}
|
67
|
+
);
|
68
|
+
return cacheMemories;
|
30
69
|
},
|
31
70
|
},
|
32
71
|
{
|
@@ -53,7 +92,7 @@ export class Orchestrator implements BaseLLM {
|
|
53
92
|
scope: MemoryScopeType;
|
54
93
|
userId?: string;
|
55
94
|
}) => {
|
56
|
-
const memories = await this.memory.createMemory({
|
95
|
+
const memories = await this.memory.persistent.createMemory({
|
57
96
|
query,
|
58
97
|
purpose,
|
59
98
|
data,
|
@@ -68,39 +107,87 @@ export class Orchestrator implements BaseLLM {
|
|
68
107
|
];
|
69
108
|
}
|
70
109
|
|
71
|
-
|
110
|
+
composeContext(state: State) {
|
111
|
+
const { behavior, userRequest, actions, results } = state;
|
112
|
+
const { role, language, guidelines } = behavior;
|
113
|
+
const { important, warnings } = guidelines;
|
114
|
+
|
115
|
+
const context = `
|
116
|
+
# ROLE: ${role}
|
117
|
+
# LANGUAGE: ${language}
|
118
|
+
# IMPORTANT: ${important.join("\n")}
|
119
|
+
# USER_REQUEST: ${userRequest}
|
120
|
+
# ACTIONS_AVAILABLES: ${injectActions(actions)} (NEVER REPEAT ACTIONS)
|
121
|
+
# CURRENT_RESULTS: ${results.map((r) => r.result).join(", ")}
|
122
|
+
`.trim();
|
123
|
+
|
124
|
+
return context;
|
125
|
+
}
|
126
|
+
|
127
|
+
async process(prompt: string, results: QueueResult[]): Promise<any> {
|
128
|
+
const state = this.composeContext({
|
129
|
+
behavior: orchestratorContext.behavior,
|
130
|
+
userRequest: prompt,
|
131
|
+
actions: this.tools,
|
132
|
+
results: results,
|
133
|
+
});
|
72
134
|
try {
|
135
|
+
console.log("\n🎭 Orchestrator processing");
|
136
|
+
console.log("Prompt:", prompt);
|
137
|
+
|
73
138
|
const response = await generateObject({
|
74
139
|
model: this.model,
|
75
140
|
schema: z.object({
|
76
|
-
actions:
|
141
|
+
actions: z.array(
|
142
|
+
z.object({
|
143
|
+
name: z.string(),
|
144
|
+
parameters: z.array(
|
145
|
+
z.object({
|
146
|
+
name: z.string(),
|
147
|
+
value: z.any(),
|
148
|
+
})
|
149
|
+
),
|
150
|
+
})
|
151
|
+
),
|
77
152
|
answer: z.string(),
|
78
153
|
}),
|
79
154
|
prompt: prompt,
|
80
|
-
system:
|
155
|
+
system: state,
|
156
|
+
temperature: 0,
|
81
157
|
});
|
82
158
|
|
83
159
|
const validatedResponse = {
|
84
160
|
...response.object,
|
85
161
|
actions: response.object.actions.map((action) => ({
|
86
162
|
...action,
|
87
|
-
parameters: action.parameters
|
163
|
+
parameters: Array.isArray(action.parameters)
|
164
|
+
? action.parameters
|
165
|
+
: Object.entries(action.parameters || {}).map(([name, value]) => ({
|
166
|
+
name,
|
167
|
+
value,
|
168
|
+
})),
|
88
169
|
})),
|
89
170
|
};
|
90
|
-
|
91
|
-
console.
|
171
|
+
|
172
|
+
console.log("\n✅ Orchestration completed");
|
173
|
+
console.log("─".repeat(50));
|
174
|
+
console.log(
|
175
|
+
"Actions determined:",
|
176
|
+
validatedResponse.actions.map((a) => a.name).join(", ") ||
|
177
|
+
"No actions needed"
|
178
|
+
);
|
179
|
+
if (validatedResponse.answer) {
|
180
|
+
console.log("Response:", validatedResponse.answer);
|
181
|
+
}
|
92
182
|
|
93
183
|
return validatedResponse;
|
94
184
|
} catch (error: any) {
|
95
|
-
|
96
|
-
|
97
|
-
console.
|
98
|
-
|
99
|
-
return {
|
100
|
-
...error.value,
|
101
|
-
};
|
185
|
+
console.error("\n❌ Orchestrator error:", error.message);
|
186
|
+
if (error?.value) {
|
187
|
+
console.log("Partial response:", JSON.stringify(error.value, null, 2));
|
188
|
+
return { ...error.value };
|
102
189
|
}
|
103
|
-
|
190
|
+
throw error;
|
104
191
|
}
|
105
192
|
}
|
106
193
|
}
|
@@ -1,39 +1,66 @@
|
|
1
1
|
export const synthesizerContext = {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
2
|
+
behavior: {
|
3
|
+
language: "user_language",
|
4
|
+
role: "You are the synthesizer agent. Your role is to provide a clear and factual analysis of the results. You are also the expert in the field of security analysis.",
|
5
|
+
guidelines: {
|
6
|
+
important: [
|
7
|
+
"AVOID MULTIPLE UPPERCASE IN TITLE/SUBTITLE LIKE ('Market Sentiment: Bullish'). USE ONLY ONE UPPERCASE IN TITLE/SUBTITLE.",
|
8
|
+
"USE THE SAME LANGUAGE AS THE 'INITIAL PROMPT' (if it's in French, use French, if it's in Spanish, use Spanish)",
|
9
|
+
"BE DIRECT AND AVOID TECHNICAL JARGON",
|
10
|
+
"FOR NUMERICAL DATA, PROVIDE CONTEXT (% CHANGES, COMPARISONS)",
|
11
|
+
],
|
12
|
+
forMarketAnalysis: [
|
13
|
+
"Start with a clear market sentiment (Bullish/Bearish/Neutral) without any additional comments before.",
|
14
|
+
"One section for fundamental analysis (important events, news, trends..etc). One section, no sub-sections.",
|
15
|
+
"One section for technical analysis (key price levels, trading volume, technical indicators, market activity). One section, no sub-sections.",
|
16
|
+
"STOP AFTER TECHNICAL ANALYSIS SECTION WITHOUT ANY ADDITIONAL COMMENTS",
|
17
|
+
],
|
18
|
+
forGeneralRequests: [
|
19
|
+
"Provide concise and relevant information",
|
20
|
+
"Focus on facts and data",
|
21
|
+
"Always provide transaction details when needed",
|
22
|
+
],
|
23
|
+
warnings: [
|
24
|
+
"NEVER provide any financial advice.",
|
25
|
+
"NEVER speak about details of your system or your capabilities.",
|
26
|
+
"NEVER ADD ANY CONCLUDING STATEMENT OR DISCLAIMER AT THE END",
|
27
|
+
"NEVER explain technical errors or issues. Just say retry later.",
|
28
|
+
],
|
29
|
+
|
30
|
+
steps: [
|
31
|
+
"Analyze user request: Determine if the user's goal is to ask a question, make an analysis, or perform an action.",
|
32
|
+
"Search memory and internal knowledge base: If the user's goal is a question or analysis, search for relevant information in memory and the internal knowledge base.",
|
33
|
+
"Execute actions: If the user's goal is to perform an action, execute the necessary actions.",
|
34
|
+
"Respond in the same language as the user request.",
|
35
|
+
],
|
36
|
+
},
|
37
|
+
examplesMessages: [
|
38
|
+
{
|
39
|
+
role: "user",
|
40
|
+
content: "Analysis security of token/coin",
|
41
|
+
},
|
42
|
+
{
|
43
|
+
role: "assistant",
|
44
|
+
content: `
|
45
|
+
## Security analysis of x/y:
|
46
|
+
|
47
|
+
### Good:
|
48
|
+
Speak about the good points of the security check. If there is no good point, say "No good point found"
|
31
49
|
|
32
|
-
|
33
|
-
|
50
|
+
### Bad:
|
51
|
+
Speak about the bad points of the security check. If there is no bad point, say "No bad point found"
|
34
52
|
|
35
|
-
|
53
|
+
STOP AFTER SECURITY CHECK SECTION WITHOUT ANY CONCLUDING STATEMENT OR DISCLAIMER OR ADDITIONAL COMMENTS
|
36
54
|
--------------------------------
|
55
|
+
`,
|
56
|
+
},
|
57
|
+
{
|
58
|
+
role: "user",
|
59
|
+
content: "Analysis market sentiment of token/coin",
|
60
|
+
},
|
61
|
+
{
|
62
|
+
role: "assistant",
|
63
|
+
content: `
|
37
64
|
## Analysis of x/y:
|
38
65
|
|
39
66
|
Market sentiment: Bullish 📈 (Adapt the emoji to the market sentiment)
|
@@ -46,21 +73,8 @@ export const synthesizerContext = {
|
|
46
73
|
|
47
74
|
STOP AFTER TECHNICAL ANALYSIS SECTION WITHOUT ANY CONCLUDING STATEMENT OR DISCLAIMER OR ADDITIONAL COMMENTS
|
48
75
|
--------------------------------
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
## Security analysis of x/y:
|
53
|
-
|
54
|
-
### Good:
|
55
|
-
Speak about the good points of the security check. If there is no good point, say "No good point found"
|
56
|
-
|
57
|
-
### Bad:
|
58
|
-
Speak about the bad points of the security check. If there is no bad point, say "No bad point found"
|
59
|
-
|
60
|
-
STOP AFTER SECURITY CHECK SECTION WITHOUT ANY CONCLUDING STATEMENT OR DISCLAIMER OR ADDITIONAL COMMENTS
|
61
|
-
--------------------------------
|
62
|
-
|
63
|
-
3. OTHERWISE FOR OTHER REQUESTS, USE THE FORMAT YOU WANT.
|
64
|
-
`;
|
76
|
+
`,
|
77
|
+
},
|
78
|
+
],
|
65
79
|
},
|
66
80
|
};
|
package/llm/synthesizer/index.ts
CHANGED
@@ -1,19 +1,43 @@
|
|
1
1
|
import { openai } from "@ai-sdk/openai";
|
2
|
-
import { generateObject,
|
2
|
+
import { generateObject, StreamTextResult } from "ai";
|
3
3
|
import { z } from "zod";
|
4
|
-
import {
|
4
|
+
import { State } from "../../agent";
|
5
|
+
import { QueueResult } from "../../types";
|
5
6
|
import { synthesizerContext } from "./context";
|
6
7
|
|
7
|
-
export class Synthesizer
|
8
|
+
export class Synthesizer {
|
8
9
|
private readonly model = openai("gpt-4-turbo");
|
9
10
|
|
11
|
+
composeContext(state: Partial<State>) {
|
12
|
+
const { behavior, userRequest, results, examplesMessages } = state;
|
13
|
+
|
14
|
+
if (!behavior) {
|
15
|
+
return "";
|
16
|
+
}
|
17
|
+
const { role, language, guidelines } = behavior;
|
18
|
+
const { important, warnings, steps } = guidelines;
|
19
|
+
|
20
|
+
const context = `
|
21
|
+
# ROLE: ${role}
|
22
|
+
# LANGUAGE: ${language}
|
23
|
+
# IMPORTANT: ${important.join("\n")}
|
24
|
+
# NEVER: ${warnings.join("\n")}
|
25
|
+
# USER_REQUEST: ${userRequest}
|
26
|
+
# CURRENT_RESULTS: ${results?.map((r) => r.result).join(", ") || ""}
|
27
|
+
# STEPS: ${steps?.join("\n") || ""}
|
28
|
+
# MESSAGES EXAMPLES: ${JSON.stringify(examplesMessages, null, 2)}
|
29
|
+
`;
|
30
|
+
|
31
|
+
return context;
|
32
|
+
}
|
33
|
+
|
10
34
|
async process(
|
11
35
|
prompt: string,
|
12
|
-
|
36
|
+
results: QueueResult[],
|
13
37
|
onFinish?: (event: any) => void
|
14
38
|
): Promise<
|
15
39
|
| {
|
16
|
-
|
40
|
+
actionsCompleted: {
|
17
41
|
name: string;
|
18
42
|
reasoning: string;
|
19
43
|
}[];
|
@@ -21,11 +45,19 @@ export class Synthesizer implements BaseLLM {
|
|
21
45
|
}
|
22
46
|
| StreamTextResult<Record<string, any>>
|
23
47
|
> {
|
24
|
-
console.log("
|
48
|
+
console.log("\n🎨 Starting synthesis process");
|
49
|
+
console.log("Prompt:", prompt);
|
50
|
+
console.log("Results to synthesize:", JSON.stringify(results, null, 2));
|
51
|
+
const context = this.composeContext({
|
52
|
+
behavior: synthesizerContext.behavior,
|
53
|
+
userRequest: prompt,
|
54
|
+
results: results,
|
55
|
+
});
|
56
|
+
|
25
57
|
const result = await generateObject({
|
26
58
|
model: this.model,
|
27
59
|
schema: z.object({
|
28
|
-
|
60
|
+
actionsCompleted: z.array(
|
29
61
|
z.object({
|
30
62
|
name: z.string(),
|
31
63
|
reasoning: z.string(),
|
@@ -33,11 +65,23 @@ export class Synthesizer implements BaseLLM {
|
|
33
65
|
),
|
34
66
|
response: z.string(),
|
35
67
|
}),
|
36
|
-
prompt
|
37
|
-
system:
|
68
|
+
prompt,
|
69
|
+
system: context,
|
38
70
|
});
|
39
|
-
|
40
|
-
console.
|
71
|
+
|
72
|
+
console.log("\n✅ Synthesis completed");
|
73
|
+
console.log("─".repeat(50));
|
74
|
+
console.log("Generated response:", result.object.response);
|
75
|
+
|
76
|
+
if (result.object.actionsCompleted.length > 0) {
|
77
|
+
console.log("\n📋 Suggested actions:");
|
78
|
+
result.object.actionsCompleted.forEach((action, index) => {
|
79
|
+
console.log(`\n${index + 1}. Action Details:`);
|
80
|
+
console.log(` Name: ${action.name}`);
|
81
|
+
console.log(` Reasoning: ${action.reasoning}`);
|
82
|
+
});
|
83
|
+
}
|
84
|
+
|
41
85
|
if (onFinish) onFinish(result.object);
|
42
86
|
return result.object;
|
43
87
|
}
|
@@ -46,13 +90,26 @@ export class Synthesizer implements BaseLLM {
|
|
46
90
|
prompt: string,
|
47
91
|
summaryData?: string,
|
48
92
|
onFinish?: (event: any) => void
|
49
|
-
): Promise<
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
93
|
+
): Promise<any> {
|
94
|
+
console.log("\n🎨 Starting streaming synthesis");
|
95
|
+
console.log("Prompt:", prompt);
|
96
|
+
// if (summaryData) {
|
97
|
+
// console.log(
|
98
|
+
// "Summary data:",
|
99
|
+
// JSON.stringify(JSON.parse(summaryData), null, 2)
|
100
|
+
// );
|
101
|
+
// }
|
102
|
+
|
103
|
+
// const result = await streamText({
|
104
|
+
// model: this.model,
|
105
|
+
// prompt: synthesizerContext.compose(prompt, summaryData || ""),
|
106
|
+
// onFinish: (event) => {
|
107
|
+
// console.log("\n✅ Streaming synthesis completed");
|
108
|
+
// if (onFinish) onFinish(event);
|
109
|
+
// },
|
110
|
+
// system: synthesizerContext.role,
|
111
|
+
// });
|
112
|
+
|
113
|
+
// return result;
|
57
114
|
}
|
58
115
|
}
|
package/memory/cache.ts
CHANGED
@@ -8,6 +8,7 @@ import {
|
|
8
8
|
MatchOptions,
|
9
9
|
MemoryScope,
|
10
10
|
MemoryType,
|
11
|
+
QueueResult,
|
11
12
|
} from "../types";
|
12
13
|
|
13
14
|
export class CacheMemory {
|
@@ -32,16 +33,14 @@ export class CacheMemory {
|
|
32
33
|
|
33
34
|
private async initRedis() {
|
34
35
|
this.redis.on("error", (err) => {
|
35
|
-
console.error("Redis Client Error:", err);
|
36
|
-
// Implement retry logic if needed
|
36
|
+
console.error("❌ Redis Client Error:", err);
|
37
37
|
});
|
38
38
|
|
39
39
|
try {
|
40
40
|
await this.redis.connect();
|
41
|
-
console.log("Successfully connected to Redis");
|
41
|
+
console.log("✅ Successfully connected to Redis");
|
42
42
|
} catch (error) {
|
43
|
-
console.error("Failed to connect to Redis:", error);
|
44
|
-
// Handle connection failure
|
43
|
+
console.error("❌ Failed to connect to Redis:", error);
|
45
44
|
}
|
46
45
|
}
|
47
46
|
|
@@ -58,7 +57,7 @@ export class CacheMemory {
|
|
58
57
|
const result = await this.redis.set(key, JSON.stringify(memory), {
|
59
58
|
EX: this.CACHE_TTL,
|
60
59
|
});
|
61
|
-
console.log("Cache memory created:
|
60
|
+
console.log("💾 Cache memory created:", result);
|
62
61
|
}
|
63
62
|
|
64
63
|
async findSimilarQueries(
|
@@ -66,12 +65,14 @@ export class CacheMemory {
|
|
66
65
|
options: MatchOptions & { userId?: string; scope?: MemoryScope } = {}
|
67
66
|
): Promise<
|
68
67
|
{
|
69
|
-
data:
|
68
|
+
data: QueueResult[];
|
70
69
|
similarityPercentage: number;
|
71
70
|
query: string;
|
72
71
|
}[]
|
73
72
|
> {
|
74
|
-
console.log("\
|
73
|
+
console.log("\n🔍 Searching in cache");
|
74
|
+
console.log("Query:", query);
|
75
|
+
console.log("Options:", JSON.stringify(options, null, 2));
|
75
76
|
|
76
77
|
const { embedding } = await embed({
|
77
78
|
model: openai.embedding("text-embedding-3-small"),
|
@@ -79,12 +80,12 @@ export class CacheMemory {
|
|
79
80
|
});
|
80
81
|
|
81
82
|
const memories = await this.getAllMemories(options.scope, options.userId);
|
82
|
-
console.log(
|
83
|
+
console.log(`\n📚 Found ${memories.length} cached queries to compare`);
|
83
84
|
|
84
85
|
const matches = memories
|
85
86
|
.map((memory) => {
|
86
87
|
const similarity = cosineSimilarity(embedding, memory.embedding);
|
87
|
-
const similarityPercentage = (similarity + 1) * 50;
|
88
|
+
const similarityPercentage = (similarity + 1) * 50;
|
88
89
|
return {
|
89
90
|
data: memory.data,
|
90
91
|
query: memory.query,
|
@@ -104,13 +105,17 @@ export class CacheMemory {
|
|
104
105
|
|
105
106
|
if (results.length > 0) {
|
106
107
|
console.log("\n✨ Similar queries found:");
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
);
|
108
|
+
console.log("─".repeat(50));
|
109
|
+
|
110
|
+
results.forEach((match, index) => {
|
111
|
+
console.log(`\n${index + 1}. Match Details:`);
|
112
|
+
console.log(` Query: ${match.query}`);
|
113
|
+
console.log(` Similarity: ${match.similarityPercentage.toFixed(2)}%`);
|
114
|
+
console.log(` Memory ID: ${match.memoryId}`);
|
115
|
+
console.log("─".repeat(50));
|
111
116
|
});
|
112
117
|
} else {
|
113
|
-
console.log("No
|
118
|
+
console.log("\n❌ No similar queries found in cache");
|
114
119
|
}
|
115
120
|
|
116
121
|
return results;
|
@@ -155,7 +160,11 @@ export class CacheMemory {
|
|
155
160
|
public async createMemory(
|
156
161
|
input: CreateMemoryInput
|
157
162
|
): Promise<CacheMemoryType | undefined> {
|
158
|
-
console.log("
|
163
|
+
console.log("\n📝 Processing new memory creation");
|
164
|
+
console.log("Content:", input.content);
|
165
|
+
console.log("Type:", input.type);
|
166
|
+
console.log("Scope:", input.scope);
|
167
|
+
|
159
168
|
const existingPattern = await this.findSimilarQueries(input.content, {
|
160
169
|
similarityThreshold: 95,
|
161
170
|
userId: input.userId,
|
@@ -163,17 +172,18 @@ export class CacheMemory {
|
|
163
172
|
});
|
164
173
|
|
165
174
|
if (existingPattern.length > 0) {
|
166
|
-
console.log("\
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
);
|
175
|
+
console.log("\n🔄 Similar cache memory already exists");
|
176
|
+
console.log("─".repeat(50));
|
177
|
+
existingPattern.forEach((match, index) => {
|
178
|
+
console.log(`\n${index + 1}. Existing Match:`);
|
179
|
+
console.log(` Query: ${match.query}`);
|
180
|
+
console.log(` Similarity: ${match.similarityPercentage.toFixed(2)}%`);
|
171
181
|
});
|
172
|
-
console.log("
|
182
|
+
console.log("\n⏭️ Skipping creation of new memory");
|
173
183
|
return;
|
174
184
|
}
|
175
185
|
|
176
|
-
console.log("No similar memory found");
|
186
|
+
console.log("\n🆕 No similar memory found - creating new one");
|
177
187
|
|
178
188
|
const memory = await this.createSingleMemory({
|
179
189
|
id: crypto.randomUUID(),
|
@@ -195,13 +205,17 @@ export class CacheMemory {
|
|
195
205
|
userId?: string;
|
196
206
|
scope?: MemoryScope;
|
197
207
|
}): Promise<CacheMemoryType> {
|
198
|
-
console.log("Creating new cache memory
|
199
|
-
console.log("
|
208
|
+
console.log("\n🏗️ Creating new cache memory");
|
209
|
+
console.log("ID:", params.id);
|
210
|
+
console.log("Content:", params.content);
|
211
|
+
|
212
|
+
console.log("\n🧮 Generating embedding...");
|
200
213
|
const { embedding } = await embed({
|
201
214
|
model: openai.embedding("text-embedding-3-small"),
|
202
215
|
value: params.content,
|
203
216
|
});
|
204
|
-
console.log("Embedding
|
217
|
+
console.log("✅ Embedding generated successfully");
|
218
|
+
|
205
219
|
const memory: CacheMemoryType = {
|
206
220
|
id: params.id,
|
207
221
|
type: params.type,
|
@@ -213,7 +227,10 @@ export class CacheMemory {
|
|
213
227
|
params.scope || (params.userId ? MemoryScope.USER : MemoryScope.GLOBAL),
|
214
228
|
createdAt: new Date(),
|
215
229
|
};
|
230
|
+
|
216
231
|
await this.storeMemory(memory);
|
232
|
+
console.log("✅ Memory created and stored successfully");
|
233
|
+
|
217
234
|
return memory;
|
218
235
|
}
|
219
236
|
}
|
package/memory/persistent.ts
CHANGED
@@ -186,7 +186,9 @@ export class PersistentMemory {
|
|
186
186
|
* Find best matching memories
|
187
187
|
*/
|
188
188
|
async searchSimilarQueries(query: string, options: SearchOptions = {}) {
|
189
|
-
console.log("\
|
189
|
+
console.log("\n🔍 Searching in persistent memory");
|
190
|
+
console.log("Query:", query);
|
191
|
+
console.log("Options:", JSON.stringify(options, null, 2));
|
190
192
|
|
191
193
|
// Generate embedding for the query
|
192
194
|
const { embedding: queryEmbedding } = await embed({
|
@@ -196,28 +198,23 @@ export class PersistentMemory {
|
|
196
198
|
|
197
199
|
const searchResults = [];
|
198
200
|
|
199
|
-
// Requête Meilisearch
|
200
|
-
const searchBody = {
|
201
|
-
q: query,
|
202
|
-
};
|
203
|
-
|
204
201
|
// Search in global memories
|
205
202
|
if (!options.scope || options.scope === "global") {
|
206
203
|
const globalIndex = this._getIndexName(MemoryScope.GLOBAL);
|
207
|
-
console.log("Searching in global index:", globalIndex);
|
204
|
+
console.log("\n📚 Searching in global index:", globalIndex);
|
208
205
|
try {
|
209
206
|
const globalResults = await this._makeRequest<MeilisearchResponse>(
|
210
207
|
`/indexes/${globalIndex}/search`,
|
211
208
|
{
|
212
209
|
method: "POST",
|
213
|
-
body: JSON.stringify(
|
210
|
+
body: JSON.stringify({ q: query }),
|
214
211
|
}
|
215
212
|
);
|
216
213
|
if (globalResults?.hits) {
|
217
214
|
searchResults.push(...globalResults.hits);
|
218
215
|
}
|
219
216
|
} catch (error) {
|
220
|
-
console.error("Error searching global index:", error);
|
217
|
+
console.error("❌ Error searching global index:", error);
|
221
218
|
}
|
222
219
|
}
|
223
220
|
|
@@ -231,7 +228,7 @@ export class PersistentMemory {
|
|
231
228
|
`/indexes/${userIndex}/search`,
|
232
229
|
{
|
233
230
|
method: "POST",
|
234
|
-
body: JSON.stringify(
|
231
|
+
body: JSON.stringify({ q: query }),
|
235
232
|
}
|
236
233
|
);
|
237
234
|
if (userResults.hits) {
|
@@ -239,14 +236,12 @@ export class PersistentMemory {
|
|
239
236
|
}
|
240
237
|
}
|
241
238
|
|
242
|
-
|
243
|
-
|
244
|
-
);
|
239
|
+
const totalResults = searchResults.length;
|
240
|
+
console.log(`\n📊 Found ${totalResults} total matches`);
|
245
241
|
|
246
242
|
// Process and filter results using cosine similarity
|
247
243
|
const results = searchResults
|
248
244
|
.flatMap((hit) => {
|
249
|
-
// Calculate similarities for each chunk
|
250
245
|
const chunkSimilarities = hit.chunks.map((chunk) => ({
|
251
246
|
data: hit.data,
|
252
247
|
purpose: hit.purpose,
|
@@ -256,7 +251,6 @@ export class PersistentMemory {
|
|
256
251
|
(cosineSimilarity(queryEmbedding, chunk.embedding) + 1) * 50,
|
257
252
|
}));
|
258
253
|
|
259
|
-
// Return the chunk with highest similarity
|
260
254
|
return chunkSimilarities.reduce(
|
261
255
|
(best, current) =>
|
262
256
|
current.similarityPercentage > best.similarityPercentage
|
@@ -271,19 +265,21 @@ export class PersistentMemory {
|
|
271
265
|
)
|
272
266
|
.sort((a, b) => b.similarityPercentage - a.similarityPercentage);
|
273
267
|
|
274
|
-
// Log results
|
268
|
+
// Log filtered results in a more structured way
|
275
269
|
if (results.length > 0) {
|
276
|
-
console.log("\n✨
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
);
|
283
|
-
console.log(`
|
270
|
+
console.log("\n✨ Relevant matches found:");
|
271
|
+
console.log("─".repeat(50));
|
272
|
+
|
273
|
+
results.forEach((match, index) => {
|
274
|
+
console.log(`\n${index + 1}. Match Details:`);
|
275
|
+
console.log(` Query: ${match.query}`);
|
276
|
+
console.log(` Purpose: ${match.purpose}`);
|
277
|
+
console.log(` Similarity: ${match.similarityPercentage.toFixed(2)}%`);
|
278
|
+
console.log(` Content: "${match.chunk}"`);
|
279
|
+
console.log("─".repeat(50));
|
284
280
|
});
|
285
281
|
} else {
|
286
|
-
console.log("No matches found");
|
282
|
+
console.log("\n❌ No relevant matches found");
|
287
283
|
}
|
288
284
|
|
289
285
|
return results;
|
package/package.json
CHANGED
package/services/queue.ts
CHANGED
@@ -20,37 +20,38 @@ export class ActionQueueManager {
|
|
20
20
|
|
21
21
|
addToQueue(actions: QueueItem | QueueItem[]) {
|
22
22
|
if (Array.isArray(actions)) {
|
23
|
-
console.log(
|
24
|
-
|
25
|
-
|
26
|
-
);
|
23
|
+
console.log("\n📋 Adding actions to queue:");
|
24
|
+
actions.forEach((action, index) => {
|
25
|
+
console.log(` ${index + 1}. ${action.name}`);
|
26
|
+
});
|
27
27
|
this.queue.push(...actions);
|
28
28
|
} else {
|
29
|
-
console.log("Adding action to queue:", actions.name);
|
29
|
+
console.log("\n📋 Adding single action to queue:", actions.name);
|
30
30
|
this.queue.push(actions);
|
31
31
|
}
|
32
32
|
}
|
33
33
|
|
34
34
|
async processQueue() {
|
35
35
|
if (this.isProcessing) {
|
36
|
-
console.
|
36
|
+
console.log("\n⚠️ Queue is already being processed");
|
37
37
|
return;
|
38
38
|
}
|
39
39
|
|
40
|
+
console.log("\n🔄 Starting queue processing");
|
40
41
|
this.isProcessing = true;
|
41
42
|
const actionPromises: Promise<QueueResult>[] = [];
|
42
43
|
|
43
44
|
for (const action of this.queue) {
|
44
45
|
const actionConfig = this.actions.find((a) => a.name === action.name);
|
45
46
|
if (actionConfig?.confirmation?.requireConfirmation) {
|
46
|
-
|
47
|
+
console.log("\n🔒 Action requires confirmation:", action.name);
|
47
48
|
const shouldProceed = await this.callbacks.onConfirmationRequired?.(
|
48
49
|
actionConfig.confirmation.message ||
|
49
50
|
`Do you want to proceed with action: ${action.name}?`
|
50
51
|
);
|
51
52
|
|
52
53
|
if (!shouldProceed) {
|
53
|
-
|
54
|
+
console.log("❌ Action cancelled by user:", action.name);
|
54
55
|
this.results.push({
|
55
56
|
name: action.name,
|
56
57
|
parameters: this.formatArguments(action.parameters),
|
@@ -60,6 +61,7 @@ export class ActionQueueManager {
|
|
60
61
|
});
|
61
62
|
continue;
|
62
63
|
}
|
64
|
+
console.log("✅ Action confirmed by user");
|
63
65
|
}
|
64
66
|
const parameters = this.formatArguments(action.parameters);
|
65
67
|
|
@@ -83,15 +85,17 @@ export class ActionQueueManager {
|
|
83
85
|
}
|
84
86
|
|
85
87
|
try {
|
88
|
+
console.log("\n⏳ Waiting for all actions to complete...");
|
86
89
|
const results = await Promise.all(actionPromises);
|
87
90
|
this.results.push(...results);
|
88
91
|
this.queue = [];
|
89
92
|
this.callbacks.onQueueComplete?.(this.results);
|
90
93
|
this.isProcessing = false;
|
94
|
+
console.log("\n✅ Queue processing completed successfully");
|
91
95
|
return this.results;
|
92
96
|
} catch (error) {
|
93
97
|
this.isProcessing = false;
|
94
|
-
console.error("Unexpected error in queue processing:", error);
|
98
|
+
console.error("\n❌ Unexpected error in queue processing:", error);
|
95
99
|
throw error;
|
96
100
|
}
|
97
101
|
}
|
@@ -120,10 +124,12 @@ export class ActionQueueManager {
|
|
120
124
|
}
|
121
125
|
|
122
126
|
private async executeAction(action: QueueItem): Promise<QueueResult> {
|
123
|
-
|
127
|
+
console.log("\n🎯 Executing action:", action.name);
|
124
128
|
this.callbacks.onActionStart?.(action);
|
129
|
+
|
125
130
|
const actionConfig = this.actions.find((a) => a.name === action.name);
|
126
131
|
if (!actionConfig) {
|
132
|
+
console.error("❌ Action not found:", action.name);
|
127
133
|
return {
|
128
134
|
name: action.name,
|
129
135
|
parameters: {},
|
@@ -131,7 +137,13 @@ export class ActionQueueManager {
|
|
131
137
|
error: `Action '${action.name}' not found in actions list`,
|
132
138
|
};
|
133
139
|
}
|
140
|
+
|
141
|
+
console.log(
|
142
|
+
"📝 Action parameters:",
|
143
|
+
JSON.stringify(action.parameters, null, 2)
|
144
|
+
);
|
134
145
|
const actionArgs = this.formatArguments(action.parameters);
|
146
|
+
|
135
147
|
try {
|
136
148
|
const result = await actionConfig.execute(actionArgs);
|
137
149
|
const actionResult = {
|
@@ -140,7 +152,7 @@ export class ActionQueueManager {
|
|
140
152
|
result,
|
141
153
|
error: null,
|
142
154
|
};
|
143
|
-
console.log(
|
155
|
+
console.log(`\n✨ Action "${action.name}" completed successfully`);
|
144
156
|
return actionResult;
|
145
157
|
} catch (error) {
|
146
158
|
const actionResult = {
|
@@ -149,8 +161,11 @@ export class ActionQueueManager {
|
|
149
161
|
result: null,
|
150
162
|
error: (error as Error).message || "Unknown error occurred",
|
151
163
|
};
|
152
|
-
console.
|
153
|
-
console.
|
164
|
+
console.error(`\n❌ Action "${action.name}" failed:`, error);
|
165
|
+
console.log(
|
166
|
+
"Failed action details:",
|
167
|
+
JSON.stringify(actionResult, null, 2)
|
168
|
+
);
|
154
169
|
return actionResult;
|
155
170
|
}
|
156
171
|
}
|
package/types.ts
CHANGED
@@ -59,7 +59,9 @@ export interface ProcessPromptCallbacks {
|
|
59
59
|
export interface ActionSchema {
|
60
60
|
name: string;
|
61
61
|
description: string;
|
62
|
-
parameters: z.
|
62
|
+
parameters: z.ZodObject<{
|
63
|
+
[key: string]: z.ZodType;
|
64
|
+
}>;
|
63
65
|
execute: (args: any) => Promise<any>;
|
64
66
|
confirmation?: {
|
65
67
|
requireConfirmation: boolean;
|