@peebles-group/agentlib-js 1.0.2 → 1.0.4
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/package.json +2 -2
- package/src/Agent.js +45 -16
- package/src/config.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peebles-group/agentlib-js",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "A minimal JavaScript library implementing concurrent async agents for illustrating multi-agent systems and other agentic design patterns including recursive ones purely through function calling loops.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"js-yaml": "^4.1.0",
|
|
21
21
|
"mongodb": "^6.20.0",
|
|
22
22
|
"openai": "^5.16.0",
|
|
23
|
-
"agentlib-js": "^1.0.0",
|
|
23
|
+
"@peebles-group/agentlib-js": "^1.0.0",
|
|
24
24
|
"playwright": "^1.55.0",
|
|
25
25
|
"prompt-sync": "^4.2.0",
|
|
26
26
|
"sqlite": "^5.1.1",
|
package/src/Agent.js
CHANGED
|
@@ -3,7 +3,7 @@ import { defaultModel } from "./config.js";
|
|
|
3
3
|
import { MCPManager } from "./mcp/MCPManager.js";
|
|
4
4
|
|
|
5
5
|
export class Agent {
|
|
6
|
-
constructor(provider, apiKey, {model = defaultModel, tools = [], inputSchema = null, outputSchema = null, enableMCP = false} = {}) {
|
|
6
|
+
constructor(provider, apiKey, {model = defaultModel, tools = [], inputSchema = null, outputSchema = null, enableMCP = false, ...options} = {}) {
|
|
7
7
|
this.llmService = new LLMService(provider, apiKey);
|
|
8
8
|
this.model = model;
|
|
9
9
|
this.nativeTools = tools;
|
|
@@ -11,6 +11,7 @@ export class Agent {
|
|
|
11
11
|
this.outputSchema = outputSchema;
|
|
12
12
|
this.mcpManager = enableMCP ? new MCPManager() : null;
|
|
13
13
|
this.updateSystemPrompt();
|
|
14
|
+
this.options = options;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
async addMCPServer(serverName, config) {
|
|
@@ -31,6 +32,34 @@ export class Agent {
|
|
|
31
32
|
return result;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
addTool(tool) {
|
|
36
|
+
if (!tool || typeof tool !== 'object') {
|
|
37
|
+
throw new Error("Invalid tool: expected an object");
|
|
38
|
+
}
|
|
39
|
+
const { name, func } = tool;
|
|
40
|
+
if (typeof name !== 'string' || name.trim() === '') {
|
|
41
|
+
throw new Error("Invalid tool: missing valid 'name' (string)");
|
|
42
|
+
}
|
|
43
|
+
if (typeof func !== 'function') {
|
|
44
|
+
throw new Error("Invalid tool: missing 'func' (function)");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Prevent name collisions across native and MCP tools
|
|
48
|
+
const nameExistsInNative = this.nativeTools.some(t => t && t.name === name);
|
|
49
|
+
const nameExistsInMCP = this.mcpManager ? this.mcpManager.getAllTools().some(t => t && t.name === name) : false;
|
|
50
|
+
if (nameExistsInNative || nameExistsInMCP) {
|
|
51
|
+
throw new Error(`Tool with name '${name}' already exists`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (typeof tool.description !== 'string') {
|
|
55
|
+
tool.description = '';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.nativeTools.push(tool);
|
|
59
|
+
this.updateSystemPrompt();
|
|
60
|
+
return tool;
|
|
61
|
+
}
|
|
62
|
+
|
|
34
63
|
getAllTools() {
|
|
35
64
|
const mcpTools = this.mcpManager ? this.mcpManager.getAllTools() : [];
|
|
36
65
|
return [...this.nativeTools, ...mcpTools];
|
|
@@ -63,27 +92,29 @@ export class Agent {
|
|
|
63
92
|
*/
|
|
64
93
|
async run() {
|
|
65
94
|
const allTools = this.getAllTools();
|
|
95
|
+
const executed = []
|
|
66
96
|
|
|
67
97
|
// Step 1: send input to model
|
|
68
98
|
let response = await this.llmService.chat(this.input, {
|
|
69
99
|
model: this.model,
|
|
70
100
|
outputSchema: this.outputSchema,
|
|
71
101
|
tools: allTools,
|
|
102
|
+
...this.options,
|
|
72
103
|
});
|
|
73
104
|
|
|
74
105
|
const { output, rawResponse } = response;
|
|
75
106
|
|
|
76
107
|
// Step 2: Clean and add the response to input history
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const { parsed_arguments, ...
|
|
81
|
-
|
|
108
|
+
rawResponse.output.forEach(item => {
|
|
109
|
+
if (item.type === "function_call") {
|
|
110
|
+
// Remove parsed_arguments if it exists
|
|
111
|
+
const { parsed_arguments, ...rest } = item;
|
|
112
|
+
const cleanedItem = { ...rest, arguments: JSON.stringify(item.arguments) };
|
|
113
|
+
this.addInput(cleanedItem);
|
|
114
|
+
} else {
|
|
115
|
+
this.addInput(item);
|
|
82
116
|
}
|
|
83
|
-
return item;
|
|
84
117
|
});
|
|
85
|
-
|
|
86
|
-
this.input = this.input.concat(cleanedOutput);
|
|
87
118
|
|
|
88
119
|
// Step 3: collect all function calls
|
|
89
120
|
const functionCalls = rawResponse.output.filter(item => item.type === "function_call");
|
|
@@ -91,12 +122,9 @@ export class Agent {
|
|
|
91
122
|
if (functionCalls.length > 0) {
|
|
92
123
|
for (const call of functionCalls) {
|
|
93
124
|
let args;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
console.error("Failed to parse function call arguments:", call.arguments);
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
125
|
+
args = JSON.parse(call.arguments);
|
|
126
|
+
call.arguments = args
|
|
127
|
+
executed.push(call)
|
|
100
128
|
|
|
101
129
|
const tool = allTools.find(t => t.name === call.name);
|
|
102
130
|
if (!tool || !tool.func) {
|
|
@@ -113,7 +141,7 @@ export class Agent {
|
|
|
113
141
|
output: JSON.stringify(result),
|
|
114
142
|
});
|
|
115
143
|
}
|
|
116
|
-
|
|
144
|
+
|
|
117
145
|
// Step 6: send updated input back to model for final response
|
|
118
146
|
response = await this.llmService.chat(this.input, {
|
|
119
147
|
tools: allTools,
|
|
@@ -121,6 +149,7 @@ export class Agent {
|
|
|
121
149
|
outputSchema: this.outputSchema,
|
|
122
150
|
});
|
|
123
151
|
}
|
|
152
|
+
response.executed = executed;
|
|
124
153
|
return response;
|
|
125
154
|
}
|
|
126
155
|
|
package/src/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const defaultModel = 'gpt-
|
|
1
|
+
export const defaultModel = 'gpt-5';
|