agentnet 0.1.31 → 0.1.32
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/examples/direct-agent-usage.js +9 -5
- package/package.json +1 -1
- package/src/agent/agent-loader.js +8 -1
- package/src/agent/agent.js +26 -1
- package/src/agent/executor.js +14 -1
- package/src/agent/runtime.js +3 -2
- package/src/llm/base.js +20 -0
- package/src/llm/gemini.js +21 -1
- package/src/llm/gpt.js +21 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Agent, GPT, Message, MemoryStore } from "../src/index.js"
|
|
1
|
+
import { Agent, GPT, Gemini, Message, MemoryStore } from "../src/index.js"
|
|
2
2
|
|
|
3
3
|
// Example: Creating an agent directly without using AgentLoader
|
|
4
4
|
async function createAgentDirectly() {
|
|
@@ -9,8 +9,8 @@ async function createAgentDirectly() {
|
|
|
9
9
|
namespace: "smartchat",
|
|
10
10
|
description: "A highly advanced accommodation manager agent"
|
|
11
11
|
})
|
|
12
|
-
.withLLM(
|
|
13
|
-
model: "
|
|
12
|
+
.withLLM(Gemini, {
|
|
13
|
+
model: "gemini-2.5-flash",
|
|
14
14
|
instructions: "You are a highly advanced accommodation manager agent. \nPrioritize clarity and helpfulness.\nUse tools effectively to gather information."
|
|
15
15
|
})
|
|
16
16
|
.withStore(MemoryStore(), {
|
|
@@ -20,7 +20,7 @@ async function createAgentDirectly() {
|
|
|
20
20
|
maxRuns: 10, // Maximum number of LLM calls per query
|
|
21
21
|
maxConversationLength: 10 // Maximum conversation history length
|
|
22
22
|
})
|
|
23
|
-
|
|
23
|
+
/*.addTool({
|
|
24
24
|
name: "get_rooms_list_tool",
|
|
25
25
|
description: "Retrieves a list of available rooms based on criteria.",
|
|
26
26
|
type: "function",
|
|
@@ -67,8 +67,12 @@ async function createAgentDirectly() {
|
|
|
67
67
|
return {
|
|
68
68
|
answer: "The Double room with a view of the sea has a king size bed, a private balcony, and a view of the sea."
|
|
69
69
|
}
|
|
70
|
-
})
|
|
70
|
+
})*/
|
|
71
71
|
// Optional: Add prompt handler
|
|
72
|
+
.onLLMResponse(async (state, response, usage) => {
|
|
73
|
+
console.log("LLM response:", state, usage)
|
|
74
|
+
return response
|
|
75
|
+
})
|
|
72
76
|
.prompt(async (state, formattedInput) => {
|
|
73
77
|
console.log("Processing prompt:", formattedInput)
|
|
74
78
|
return formattedInput
|
package/package.json
CHANGED
|
@@ -301,18 +301,25 @@ function configureRunner(agentBuilder, runnerSpec) {
|
|
|
301
301
|
* @returns {object} Agent interface
|
|
302
302
|
*/
|
|
303
303
|
function createAgentInterface(agentBuilder, toolMap) {
|
|
304
|
-
|
|
304
|
+
const agentInterface = {
|
|
305
305
|
tools: toolMap,
|
|
306
306
|
prompt: (callback) => {
|
|
307
307
|
agentBuilder._config.on.prompt = callback;
|
|
308
|
+
return agentInterface;
|
|
308
309
|
},
|
|
309
310
|
response: (callback) => {
|
|
310
311
|
agentBuilder._config.on.response = callback;
|
|
312
|
+
return agentInterface;
|
|
313
|
+
},
|
|
314
|
+
onLLMResponse: (callback) => {
|
|
315
|
+
agentBuilder._config.on.onLLMResponse = callback;
|
|
316
|
+
return agentInterface;
|
|
311
317
|
},
|
|
312
318
|
compile: async () => {
|
|
313
319
|
return await agentBuilder.compile();
|
|
314
320
|
}
|
|
315
321
|
};
|
|
322
|
+
return agentInterface;
|
|
316
323
|
}
|
|
317
324
|
|
|
318
325
|
/**
|
package/src/agent/agent.js
CHANGED
|
@@ -13,7 +13,8 @@ import { logger } from "../utils/logger.js"
|
|
|
13
13
|
*/
|
|
14
14
|
const DEFAULT_HOOKS = {
|
|
15
15
|
prompt: async (state, formattedInput) => formattedInput,
|
|
16
|
-
response: async (state, conversation, result) => result
|
|
16
|
+
response: async (state, conversation, result) => result,
|
|
17
|
+
onLLMResponse: null // Optional: called after each LLM call with (state, response, usage)
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -200,6 +201,10 @@ export function Agent() {
|
|
|
200
201
|
|
|
201
202
|
// Event handlers validation
|
|
202
203
|
Object.entries(config.on).forEach(([eventName, handler]) => {
|
|
204
|
+
// Skip null handlers (optional hooks like onLLMResponse)
|
|
205
|
+
if (handler === null) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
203
208
|
if (typeof handler !== 'function') {
|
|
204
209
|
throw new ConfigurationError(`Event handler for '${eventName}' must be a function`, {
|
|
205
210
|
eventName,
|
|
@@ -438,6 +443,25 @@ export function Agent() {
|
|
|
438
443
|
return this;
|
|
439
444
|
}
|
|
440
445
|
|
|
446
|
+
/**
|
|
447
|
+
* Sets the LLM response handler - called after each LLM API call
|
|
448
|
+
* @param {Function} handler - Handler function (state, response, usage) => void
|
|
449
|
+
* - state: Current agent state
|
|
450
|
+
* - response: Raw LLM response object
|
|
451
|
+
* - usage: Normalized token usage { inputTokens, outputTokens, totalTokens, reasoningTokens, cachedTokens, provider, model, raw }
|
|
452
|
+
* @returns {Object} Agent builder for chaining
|
|
453
|
+
*/
|
|
454
|
+
function onLLMResponse(handler) {
|
|
455
|
+
if (typeof handler !== 'function') {
|
|
456
|
+
throw new ConfigurationError("onLLMResponse handler must be a function", {
|
|
457
|
+
provided: typeof handler
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
config.on.onLLMResponse = handler;
|
|
462
|
+
return this;
|
|
463
|
+
}
|
|
464
|
+
|
|
441
465
|
/**
|
|
442
466
|
* Sets agent metadata
|
|
443
467
|
* @param {Object} metadata - Agent metadata
|
|
@@ -542,6 +566,7 @@ export function Agent() {
|
|
|
542
566
|
bindTool,
|
|
543
567
|
prompt,
|
|
544
568
|
response,
|
|
569
|
+
onLLMResponse,
|
|
545
570
|
compile,
|
|
546
571
|
setMetadata,
|
|
547
572
|
getToolsSchemas,
|
package/src/agent/executor.js
CHANGED
|
@@ -166,6 +166,8 @@ async function safeExecute(func, name, type, state, input, timeout = DEFAULT_TOO
|
|
|
166
166
|
* @param {Object} api - LLM API
|
|
167
167
|
* @param {Object} llmConfig - LLM configuration
|
|
168
168
|
* @param {Object} runner - Runner configuration
|
|
169
|
+
* @param {Object} callbacks - Callback functions
|
|
170
|
+
* @param {Function} callbacks.onLLMResponse - Called after each LLM call with (state, response, usage)
|
|
169
171
|
* @returns {Function} Executor function
|
|
170
172
|
*/
|
|
171
173
|
export async function build(
|
|
@@ -174,7 +176,8 @@ export async function build(
|
|
|
174
176
|
agentName,
|
|
175
177
|
api,
|
|
176
178
|
llmConfig,
|
|
177
|
-
runner
|
|
179
|
+
runner,
|
|
180
|
+
callbacks = {}
|
|
178
181
|
) {
|
|
179
182
|
const maxRuns = runner?.maxRuns || 10;
|
|
180
183
|
|
|
@@ -287,6 +290,16 @@ export async function build(
|
|
|
287
290
|
|
|
288
291
|
logger.debug(`LLM response received for agent ${agentName}`);
|
|
289
292
|
|
|
293
|
+
// Call onLLMResponse callback if defined
|
|
294
|
+
if (callbacks.onLLMResponse) {
|
|
295
|
+
try {
|
|
296
|
+
const usage = api.extractUsage(response);
|
|
297
|
+
await callbacks.onLLMResponse(state, response, usage);
|
|
298
|
+
} catch (error) {
|
|
299
|
+
logger.warn(`Error in onLLMResponse callback for agent ${agentName}`, { error });
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
290
303
|
// Process the response
|
|
291
304
|
const finished = await api.onResponse(state, contents, toolsAndHandoffsMap, response);
|
|
292
305
|
|
package/src/agent/runtime.js
CHANGED
|
@@ -16,7 +16,7 @@ export async function AgentRuntime(agentConfig) {
|
|
|
16
16
|
handoffs,
|
|
17
17
|
io: ioInterfaces,
|
|
18
18
|
discoverySchemas,
|
|
19
|
-
on: { prompt, response }
|
|
19
|
+
on: { prompt, response, onLLMResponse }
|
|
20
20
|
} = agentConfig
|
|
21
21
|
|
|
22
22
|
// Initialize IO runtime
|
|
@@ -38,7 +38,8 @@ export async function AgentRuntime(agentConfig) {
|
|
|
38
38
|
agentName,
|
|
39
39
|
llmApi,
|
|
40
40
|
llmConfig,
|
|
41
|
-
runner
|
|
41
|
+
runner,
|
|
42
|
+
{ onLLMResponse }
|
|
42
43
|
)
|
|
43
44
|
|
|
44
45
|
// Create task processing function
|
package/src/llm/base.js
CHANGED
|
@@ -28,6 +28,26 @@ export class BaseLLM {
|
|
|
28
28
|
return config;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Extracts and normalizes token usage from the LLM response
|
|
33
|
+
* @param {Object} response - The raw LLM response
|
|
34
|
+
* @returns {Object} Normalized usage object
|
|
35
|
+
*/
|
|
36
|
+
extractUsage(response) {
|
|
37
|
+
// Default implementation returns empty usage
|
|
38
|
+
// Subclasses should override this
|
|
39
|
+
return {
|
|
40
|
+
inputTokens: 0,
|
|
41
|
+
outputTokens: 0,
|
|
42
|
+
totalTokens: 0,
|
|
43
|
+
reasoningTokens: 0,
|
|
44
|
+
cachedTokens: 0,
|
|
45
|
+
provider: this.type,
|
|
46
|
+
model: null,
|
|
47
|
+
raw: null
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
31
51
|
getCalledTools() {
|
|
32
52
|
return this.calledTools;
|
|
33
53
|
}
|
package/src/llm/gemini.js
CHANGED
|
@@ -33,6 +33,25 @@ class GeminiLLM extends BaseLLM {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Extracts and normalizes token usage from the Gemini response
|
|
38
|
+
* @param {Object} response - The raw Gemini response
|
|
39
|
+
* @returns {Object} Normalized usage object
|
|
40
|
+
*/
|
|
41
|
+
extractUsage(response) {
|
|
42
|
+
const usage = response?.usageMetadata;
|
|
43
|
+
return {
|
|
44
|
+
inputTokens: usage?.promptTokenCount ?? 0,
|
|
45
|
+
outputTokens: usage?.candidatesTokenCount ?? 0,
|
|
46
|
+
totalTokens: usage?.totalTokenCount ?? 0,
|
|
47
|
+
reasoningTokens: usage?.thoughtsTokenCount ?? 0,
|
|
48
|
+
cachedTokens: 0, // Gemini doesn't report cached tokens
|
|
49
|
+
provider: this.type,
|
|
50
|
+
model: response?.modelVersion || null,
|
|
51
|
+
raw: usage || null
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
36
55
|
/**
|
|
37
56
|
* Calls the Gemini model with the provided configuration and context
|
|
38
57
|
* @param {Object} llmClientConfig - Configuration for the Gemini model
|
|
@@ -64,8 +83,8 @@ class GeminiLLM extends BaseLLM {
|
|
|
64
83
|
});
|
|
65
84
|
|
|
66
85
|
try {
|
|
67
|
-
|
|
68
86
|
const res = await client.models.generateContent(input);
|
|
87
|
+
|
|
69
88
|
logger.debug('Gemini response', res)
|
|
70
89
|
logger.debug('Gemini response received', {
|
|
71
90
|
responseType: res.response?.candidates ? 'candidates' : 'unknown',
|
|
@@ -197,6 +216,7 @@ export default {
|
|
|
197
216
|
prompt: geminiLLM.prompt.bind(geminiLLM),
|
|
198
217
|
callModel: geminiLLM.callModel.bind(geminiLLM),
|
|
199
218
|
onResponse: geminiLLM.onResponse.bind(geminiLLM),
|
|
219
|
+
extractUsage: geminiLLM.extractUsage.bind(geminiLLM),
|
|
200
220
|
getCalledTools: geminiLLM.getCalledTools.bind(geminiLLM),
|
|
201
221
|
resetCalledTools: geminiLLM.resetCalledTools.bind(geminiLLM)
|
|
202
222
|
}
|
package/src/llm/gpt.js
CHANGED
|
@@ -38,6 +38,25 @@ class OpenAILLM extends BaseLLM {
|
|
|
38
38
|
return llmClientConfig;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Extracts and normalizes token usage from the OpenAI response
|
|
43
|
+
* @param {Object} response - The raw OpenAI response
|
|
44
|
+
* @returns {Object} Normalized usage object
|
|
45
|
+
*/
|
|
46
|
+
extractUsage(response) {
|
|
47
|
+
const usage = response?.usage;
|
|
48
|
+
return {
|
|
49
|
+
inputTokens: usage?.input_tokens ?? 0,
|
|
50
|
+
outputTokens: usage?.output_tokens ?? 0,
|
|
51
|
+
totalTokens: usage?.total_tokens ?? 0,
|
|
52
|
+
reasoningTokens: usage?.output_tokens_details?.reasoning_tokens ?? 0,
|
|
53
|
+
cachedTokens: usage?.input_tokens_details?.cached_tokens ?? 0,
|
|
54
|
+
provider: this.type,
|
|
55
|
+
model: response?.model || null,
|
|
56
|
+
raw: usage || null
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
41
60
|
/**
|
|
42
61
|
* Calls the OpenAI model with the provided configuration and context
|
|
43
62
|
* @param {Object} llmClientConfig - Configuration for the OpenAI model
|
|
@@ -61,6 +80,7 @@ class OpenAILLM extends BaseLLM {
|
|
|
61
80
|
//console.log(JSON.stringify(input, null, 2))
|
|
62
81
|
try {
|
|
63
82
|
const response = await client.responses.create(input);
|
|
83
|
+
|
|
64
84
|
logger.debug('OpenAI response received');
|
|
65
85
|
return response;
|
|
66
86
|
} catch (error) {
|
|
@@ -197,6 +217,7 @@ export default {
|
|
|
197
217
|
prompt: openaiLLM.prompt.bind(openaiLLM),
|
|
198
218
|
callModel: openaiLLM.callModel.bind(openaiLLM),
|
|
199
219
|
onResponse: openaiLLM.onResponse.bind(openaiLLM),
|
|
220
|
+
extractUsage: openaiLLM.extractUsage.bind(openaiLLM),
|
|
200
221
|
getCalledTools: openaiLLM.getCalledTools.bind(openaiLLM),
|
|
201
222
|
resetCalledTools: openaiLLM.resetCalledTools.bind(openaiLLM)
|
|
202
223
|
}
|