@lupaflow/agent 0.1.0 → 0.1.2
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/dist/index.cjs +645 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +105 -0
- package/dist/index.d.ts +105 -0
- package/dist/index.js +620 -0
- package/dist/index.js.map +1 -0
- package/package.json +9 -8
- package/tsconfig.json +0 -8
- package/tsup.config.ts +0 -9
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,645 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
Agent: () => Agent,
|
|
24
|
+
AgentRunner: () => AgentRunner,
|
|
25
|
+
ContextManager: () => ContextManager,
|
|
26
|
+
buildSystemPrompt: () => buildSystemPrompt,
|
|
27
|
+
validateAgentConfig: () => validateAgentConfig,
|
|
28
|
+
withRetry: () => withRetry
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(src_exports);
|
|
31
|
+
|
|
32
|
+
// src/runner.ts
|
|
33
|
+
var import_providers = require("@lupaflow/providers");
|
|
34
|
+
|
|
35
|
+
// src/context.ts
|
|
36
|
+
var import_core = require("@lupaflow/core");
|
|
37
|
+
var ContextManager = class {
|
|
38
|
+
messages = [];
|
|
39
|
+
config;
|
|
40
|
+
constructor(config = {}) {
|
|
41
|
+
this.config = {
|
|
42
|
+
maxMessages: config.maxMessages || 50,
|
|
43
|
+
maxTokens: config.maxTokens || 4e3,
|
|
44
|
+
preserveSystem: config.preserveSystem ?? true
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
add(message) {
|
|
48
|
+
this.messages.push(message);
|
|
49
|
+
this.trim();
|
|
50
|
+
}
|
|
51
|
+
getMessages() {
|
|
52
|
+
return [...this.messages];
|
|
53
|
+
}
|
|
54
|
+
getTotalTokens() {
|
|
55
|
+
return this.messages.reduce((sum, m) => sum + (0, import_core.estimateTokens)(m.content || ""), 0);
|
|
56
|
+
}
|
|
57
|
+
trim() {
|
|
58
|
+
if (this.messages.length <= this.config.maxMessages && this.getTotalTokens() <= this.config.maxTokens) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
while (this.messages.length > 2 && (this.messages.length > this.config.maxMessages || this.getTotalTokens() > this.config.maxTokens)) {
|
|
62
|
+
const startIdx = this.config.preserveSystem && this.messages[0]?.role === "system" ? 1 : 0;
|
|
63
|
+
if (startIdx < this.messages.length) {
|
|
64
|
+
this.messages.splice(startIdx, 1);
|
|
65
|
+
} else {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
clear() {
|
|
71
|
+
const systemMsg = this.config.preserveSystem ? this.messages.find((m) => m.role === "system") : void 0;
|
|
72
|
+
this.messages = systemMsg ? [systemMsg] : [];
|
|
73
|
+
}
|
|
74
|
+
toJSON() {
|
|
75
|
+
return this.getMessages();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// src/retry.ts
|
|
80
|
+
var import_core2 = require("@lupaflow/core");
|
|
81
|
+
var import_core3 = require("@lupaflow/core");
|
|
82
|
+
var import_core4 = require("@lupaflow/core");
|
|
83
|
+
async function withRetry(fn, config = {}, context) {
|
|
84
|
+
const cfg = {
|
|
85
|
+
maxRetries: config.maxRetries ?? 3,
|
|
86
|
+
baseDelay: config.baseDelay ?? 1e3,
|
|
87
|
+
maxDelay: config.maxDelay ?? 3e4,
|
|
88
|
+
backoffFactor: config.backoffFactor ?? 2
|
|
89
|
+
};
|
|
90
|
+
let lastError = null;
|
|
91
|
+
for (let attempt = 0; attempt <= cfg.maxRetries; attempt++) {
|
|
92
|
+
try {
|
|
93
|
+
return await fn();
|
|
94
|
+
} catch (err) {
|
|
95
|
+
lastError = err;
|
|
96
|
+
if (attempt < cfg.maxRetries) {
|
|
97
|
+
const waitTime = Math.min(cfg.baseDelay * Math.pow(cfg.backoffFactor, attempt), cfg.maxDelay);
|
|
98
|
+
await import_core4.globalEventBus.emit("agent:error", {
|
|
99
|
+
error: err.message,
|
|
100
|
+
retryAttempt: attempt + 1
|
|
101
|
+
});
|
|
102
|
+
await (0, import_core2.delay)(waitTime);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
throw new import_core3.RetryError(
|
|
107
|
+
`${context ? `[${context}] ` : ""}Failed after ${cfg.maxRetries + 1} attempts`,
|
|
108
|
+
cfg.maxRetries + 1,
|
|
109
|
+
lastError
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/config.ts
|
|
114
|
+
var import_core5 = require("@lupaflow/core");
|
|
115
|
+
function validateAgentConfig(config) {
|
|
116
|
+
if (!config.name) throw new import_core5.ConfigError("Agent name is required");
|
|
117
|
+
if (!config.provider) throw new import_core5.ConfigError("Provider is required for agent");
|
|
118
|
+
if (config.temperature !== void 0 && (config.temperature < 0 || config.temperature > 2)) {
|
|
119
|
+
throw new import_core5.ConfigError("Temperature must be between 0 and 2");
|
|
120
|
+
}
|
|
121
|
+
if (config.maxRetries !== void 0 && config.maxRetries < 0) {
|
|
122
|
+
throw new import_core5.ConfigError("maxRetries must be >= 0");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function buildSystemPrompt(config) {
|
|
126
|
+
const parts = [];
|
|
127
|
+
parts.push(config.systemPrompt || `You are ${config.name}, an AI assistant.`);
|
|
128
|
+
if (config.personality) {
|
|
129
|
+
const p = config.personality;
|
|
130
|
+
parts.push("");
|
|
131
|
+
parts.push("--- Personality ---");
|
|
132
|
+
if (p.name) parts.push(`Name: ${p.name}`);
|
|
133
|
+
if (p.tone) parts.push(`Tone: ${p.tone}`);
|
|
134
|
+
if (p.style) parts.push(`Style: ${p.style}`);
|
|
135
|
+
if (p.traits?.length) parts.push(`Traits: ${p.traits.join(", ")}`);
|
|
136
|
+
}
|
|
137
|
+
if (config.goals?.length) {
|
|
138
|
+
parts.push("");
|
|
139
|
+
parts.push("--- Goals ---");
|
|
140
|
+
config.goals.forEach((g, i) => parts.push(`${i + 1}. ${g.description}`));
|
|
141
|
+
}
|
|
142
|
+
if (config.constraints?.length) {
|
|
143
|
+
parts.push("");
|
|
144
|
+
parts.push("--- Constraints ---");
|
|
145
|
+
config.constraints.forEach((c) => parts.push(`- ${c.description}`));
|
|
146
|
+
}
|
|
147
|
+
if (config.tools?.length) {
|
|
148
|
+
parts.push("");
|
|
149
|
+
parts.push(`You have access to these tools: ${config.tools.map((t) => t.definition.name).join(", ")}`);
|
|
150
|
+
parts.push("Use them when appropriate to fulfill the user's request.");
|
|
151
|
+
}
|
|
152
|
+
return parts.join("\n");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/runner.ts
|
|
156
|
+
var import_core6 = require("@lupaflow/core");
|
|
157
|
+
var import_core7 = require("@lupaflow/core");
|
|
158
|
+
var import_core8 = require("@lupaflow/core");
|
|
159
|
+
var import_plugins = require("@lupaflow/plugins");
|
|
160
|
+
var AgentRunner = class {
|
|
161
|
+
config;
|
|
162
|
+
context;
|
|
163
|
+
memory;
|
|
164
|
+
toolCallCount = 0;
|
|
165
|
+
totalPromptTokens = 0;
|
|
166
|
+
totalCompletionTokens = 0;
|
|
167
|
+
constructor(config, memory) {
|
|
168
|
+
this.config = config;
|
|
169
|
+
this.context = new ContextManager({
|
|
170
|
+
maxMessages: config.maxContextMessages || 50
|
|
171
|
+
});
|
|
172
|
+
this.memory = memory;
|
|
173
|
+
}
|
|
174
|
+
async run(options) {
|
|
175
|
+
const runId = (0, import_core6.generateId)();
|
|
176
|
+
const startTime = Date.now();
|
|
177
|
+
this.toolCallCount = 0;
|
|
178
|
+
this.totalPromptTokens = 0;
|
|
179
|
+
this.totalCompletionTokens = 0;
|
|
180
|
+
const provider = import_providers.providerRegistry.get(this.config.provider, {
|
|
181
|
+
model: this.config.model,
|
|
182
|
+
temperature: this.config.temperature,
|
|
183
|
+
maxTokens: this.config.maxTokens,
|
|
184
|
+
topP: this.config.topP
|
|
185
|
+
});
|
|
186
|
+
const systemPrompt = buildSystemPrompt(this.config);
|
|
187
|
+
(0, import_plugins.runBeforeAgentRunHooks)({
|
|
188
|
+
input: options.input,
|
|
189
|
+
...this.config
|
|
190
|
+
});
|
|
191
|
+
this.context.add({ role: "system", content: systemPrompt });
|
|
192
|
+
this.context.add({ role: "user", content: options.input });
|
|
193
|
+
await import_core7.globalEventBus.emit("agent:start", {
|
|
194
|
+
agentId: this.config.id || this.config.name,
|
|
195
|
+
runId,
|
|
196
|
+
config: this.config
|
|
197
|
+
});
|
|
198
|
+
await import_core7.globalEventBus.emit("agent:thinking", {
|
|
199
|
+
agentId: this.config.id || this.config.name,
|
|
200
|
+
runId,
|
|
201
|
+
message: options.input
|
|
202
|
+
});
|
|
203
|
+
let finalContent = "";
|
|
204
|
+
let finishReason = "stop";
|
|
205
|
+
let iterationCount = 0;
|
|
206
|
+
const maxIterations = 20;
|
|
207
|
+
while (iterationCount < maxIterations) {
|
|
208
|
+
iterationCount++;
|
|
209
|
+
const request = (0, import_plugins.runBeforeProviderCallHooks)(this.config.provider, {
|
|
210
|
+
model: this.config.model,
|
|
211
|
+
messages: this.context.getMessages(),
|
|
212
|
+
tools: this.config.tools,
|
|
213
|
+
systemPrompt: void 0,
|
|
214
|
+
temperature: this.config.temperature,
|
|
215
|
+
maxTokens: this.config.maxTokens,
|
|
216
|
+
topP: this.config.topP
|
|
217
|
+
});
|
|
218
|
+
const response = await withRetry(
|
|
219
|
+
() => provider.complete({
|
|
220
|
+
messages: request.messages || this.context.getMessages(),
|
|
221
|
+
tools: this.config.tools,
|
|
222
|
+
systemPrompt: void 0,
|
|
223
|
+
temperature: this.config.temperature,
|
|
224
|
+
maxTokens: this.config.maxTokens,
|
|
225
|
+
topP: this.config.topP,
|
|
226
|
+
model: this.config.model
|
|
227
|
+
}),
|
|
228
|
+
{
|
|
229
|
+
maxRetries: this.config.maxRetries ?? 3,
|
|
230
|
+
baseDelay: this.config.retryDelay ?? 1e3
|
|
231
|
+
},
|
|
232
|
+
this.config.name
|
|
233
|
+
);
|
|
234
|
+
(0, import_plugins.runAfterProviderCallHooks)(response);
|
|
235
|
+
this.totalPromptTokens += response.usage.promptTokens;
|
|
236
|
+
this.totalCompletionTokens += response.usage.completionTokens;
|
|
237
|
+
if (response.toolCalls.length > 0) {
|
|
238
|
+
this.context.add({
|
|
239
|
+
role: "assistant",
|
|
240
|
+
content: response.content || null,
|
|
241
|
+
toolCalls: response.toolCalls.map((tc) => ({
|
|
242
|
+
id: tc.id,
|
|
243
|
+
type: "function",
|
|
244
|
+
function: { name: tc.name, arguments: JSON.stringify(tc.args) }
|
|
245
|
+
}))
|
|
246
|
+
});
|
|
247
|
+
} else if (response.content) {
|
|
248
|
+
this.context.add({ role: "assistant", content: response.content });
|
|
249
|
+
}
|
|
250
|
+
if (response.toolCalls.length === 0) {
|
|
251
|
+
finalContent = response.content || "";
|
|
252
|
+
finishReason = response.finishReason;
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
for (const tc of response.toolCalls) {
|
|
256
|
+
this.toolCallCount++;
|
|
257
|
+
await import_core7.globalEventBus.emit("tool:start", {
|
|
258
|
+
agentId: this.config.id || this.config.name,
|
|
259
|
+
runId,
|
|
260
|
+
tool: tc.name,
|
|
261
|
+
args: tc.args
|
|
262
|
+
});
|
|
263
|
+
options.onToolCall?.(tc.name, tc.args);
|
|
264
|
+
try {
|
|
265
|
+
const tool = this.config.tools?.find((t) => t.definition.name === tc.name);
|
|
266
|
+
if (!tool) throw new import_core8.ToolError(tc.name, `Tool "${tc.name}" not found on agent`);
|
|
267
|
+
const hookArgs = (0, import_plugins.runBeforeToolCallHooks)(tc.name, tc.args);
|
|
268
|
+
const result = await tool.execute(hookArgs);
|
|
269
|
+
const hookResult = (0, import_plugins.runAfterToolCallHooks)(result);
|
|
270
|
+
const resultStr = typeof hookResult === "string" ? hookResult : JSON.stringify(hookResult, null, 2);
|
|
271
|
+
this.context.add({
|
|
272
|
+
role: "tool",
|
|
273
|
+
toolCallId: tc.id,
|
|
274
|
+
name: tc.name,
|
|
275
|
+
content: resultStr
|
|
276
|
+
});
|
|
277
|
+
await import_core7.globalEventBus.emit("tool:finish", {
|
|
278
|
+
agentId: this.config.id || this.config.name,
|
|
279
|
+
runId,
|
|
280
|
+
tool: tc.name,
|
|
281
|
+
result: hookResult,
|
|
282
|
+
durationMs: Date.now() - startTime
|
|
283
|
+
});
|
|
284
|
+
options.onToolResult?.(tc.name, hookResult);
|
|
285
|
+
} catch (err) {
|
|
286
|
+
this.context.add({
|
|
287
|
+
role: "tool",
|
|
288
|
+
toolCallId: tc.id,
|
|
289
|
+
name: tc.name,
|
|
290
|
+
content: `Error: ${err.message}`
|
|
291
|
+
});
|
|
292
|
+
await import_core7.globalEventBus.emit("tool:error", {
|
|
293
|
+
agentId: this.config.id || this.config.name,
|
|
294
|
+
runId,
|
|
295
|
+
tool: tc.name,
|
|
296
|
+
error: err.message
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
const totalLatency = Date.now() - startTime;
|
|
302
|
+
if (this.memory) {
|
|
303
|
+
await this.memory.store({
|
|
304
|
+
id: (0, import_core6.generateId)(),
|
|
305
|
+
type: "short-term",
|
|
306
|
+
key: `agent:${this.config.name}:input:${(0, import_core6.generateId)()}`,
|
|
307
|
+
content: options.input,
|
|
308
|
+
metadata: { runId, agentName: this.config.name },
|
|
309
|
+
timestamp: Date.now()
|
|
310
|
+
});
|
|
311
|
+
if (finalContent) {
|
|
312
|
+
await this.memory.store({
|
|
313
|
+
id: (0, import_core6.generateId)(),
|
|
314
|
+
type: "short-term",
|
|
315
|
+
key: `agent:${this.config.name}:output:${(0, import_core6.generateId)()}`,
|
|
316
|
+
content: finalContent,
|
|
317
|
+
metadata: { runId, agentName: this.config.name },
|
|
318
|
+
timestamp: Date.now()
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
await import_core7.globalEventBus.emit("agent:response", {
|
|
323
|
+
agentId: this.config.id || this.config.name,
|
|
324
|
+
runId,
|
|
325
|
+
content: finalContent,
|
|
326
|
+
tokens: this.totalCompletionTokens,
|
|
327
|
+
latencyMs: totalLatency
|
|
328
|
+
});
|
|
329
|
+
(0, import_plugins.runAfterAgentRunHooks)({
|
|
330
|
+
id: runId,
|
|
331
|
+
output: finalContent,
|
|
332
|
+
messages: this.context.getMessages(),
|
|
333
|
+
usage: {
|
|
334
|
+
totalTokens: this.totalPromptTokens + this.totalCompletionTokens,
|
|
335
|
+
promptTokens: this.totalPromptTokens,
|
|
336
|
+
completionTokens: this.totalCompletionTokens
|
|
337
|
+
},
|
|
338
|
+
latencyMs: totalLatency,
|
|
339
|
+
toolCalls: this.toolCallCount,
|
|
340
|
+
finishReason
|
|
341
|
+
});
|
|
342
|
+
await import_core7.globalEventBus.emit("agent:complete", {
|
|
343
|
+
agentId: this.config.id || this.config.name,
|
|
344
|
+
runId,
|
|
345
|
+
totalTokens: this.totalPromptTokens + this.totalCompletionTokens,
|
|
346
|
+
totalLatencyMs: totalLatency,
|
|
347
|
+
toolCalls: this.toolCallCount
|
|
348
|
+
});
|
|
349
|
+
return {
|
|
350
|
+
id: runId,
|
|
351
|
+
output: finalContent,
|
|
352
|
+
messages: this.context.getMessages(),
|
|
353
|
+
usage: {
|
|
354
|
+
totalTokens: this.totalPromptTokens + this.totalCompletionTokens,
|
|
355
|
+
promptTokens: this.totalPromptTokens,
|
|
356
|
+
completionTokens: this.totalCompletionTokens
|
|
357
|
+
},
|
|
358
|
+
latencyMs: totalLatency,
|
|
359
|
+
toolCalls: this.toolCallCount,
|
|
360
|
+
finishReason
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
async *streamRun(options) {
|
|
364
|
+
const runId = (0, import_core6.generateId)();
|
|
365
|
+
const startTime = Date.now();
|
|
366
|
+
this.toolCallCount = 0;
|
|
367
|
+
this.totalPromptTokens = 0;
|
|
368
|
+
this.totalCompletionTokens = 0;
|
|
369
|
+
const provider = import_providers.providerRegistry.get(this.config.provider, {
|
|
370
|
+
model: this.config.model,
|
|
371
|
+
temperature: this.config.temperature,
|
|
372
|
+
maxTokens: this.config.maxTokens,
|
|
373
|
+
topP: this.config.topP
|
|
374
|
+
});
|
|
375
|
+
const systemPrompt = buildSystemPrompt(this.config);
|
|
376
|
+
(0, import_plugins.runBeforeAgentRunHooks)({
|
|
377
|
+
input: options.input,
|
|
378
|
+
...this.config
|
|
379
|
+
});
|
|
380
|
+
this.context.add({ role: "system", content: systemPrompt });
|
|
381
|
+
this.context.add({ role: "user", content: options.input });
|
|
382
|
+
await import_core7.globalEventBus.emit("agent:start", {
|
|
383
|
+
agentId: this.config.id || this.config.name,
|
|
384
|
+
runId,
|
|
385
|
+
config: this.config
|
|
386
|
+
});
|
|
387
|
+
await import_core7.globalEventBus.emit("agent:thinking", {
|
|
388
|
+
agentId: this.config.id || this.config.name,
|
|
389
|
+
runId,
|
|
390
|
+
message: options.input
|
|
391
|
+
});
|
|
392
|
+
let finalContent = "";
|
|
393
|
+
let finishReason = "stop";
|
|
394
|
+
let iterationCount = 0;
|
|
395
|
+
const maxIterations = 20;
|
|
396
|
+
while (iterationCount < maxIterations) {
|
|
397
|
+
iterationCount++;
|
|
398
|
+
const request = (0, import_plugins.runBeforeProviderCallHooks)(this.config.provider, {
|
|
399
|
+
model: this.config.model,
|
|
400
|
+
messages: this.context.getMessages(),
|
|
401
|
+
tools: this.config.tools,
|
|
402
|
+
systemPrompt: void 0,
|
|
403
|
+
temperature: this.config.temperature,
|
|
404
|
+
maxTokens: this.config.maxTokens,
|
|
405
|
+
topP: this.config.topP
|
|
406
|
+
});
|
|
407
|
+
const messages = request.messages || this.context.getMessages();
|
|
408
|
+
const stream = provider.streamComplete({
|
|
409
|
+
messages,
|
|
410
|
+
tools: this.config.tools,
|
|
411
|
+
systemPrompt: void 0,
|
|
412
|
+
temperature: this.config.temperature,
|
|
413
|
+
maxTokens: this.config.maxTokens,
|
|
414
|
+
topP: this.config.topP,
|
|
415
|
+
model: this.config.model
|
|
416
|
+
});
|
|
417
|
+
let roundContent = "";
|
|
418
|
+
let roundToolCalls = [];
|
|
419
|
+
for await (const chunk of stream) {
|
|
420
|
+
if (chunk.type === "text") {
|
|
421
|
+
roundContent += chunk.text;
|
|
422
|
+
yield { type: "text", text: chunk.text };
|
|
423
|
+
} else if (chunk.type === "tool_call") {
|
|
424
|
+
roundToolCalls.push(chunk.toolCall);
|
|
425
|
+
} else if (chunk.type === "finish") {
|
|
426
|
+
roundContent = chunk.content;
|
|
427
|
+
roundToolCalls = chunk.toolCalls;
|
|
428
|
+
this.totalPromptTokens += chunk.usage.promptTokens;
|
|
429
|
+
this.totalCompletionTokens += chunk.usage.completionTokens;
|
|
430
|
+
finishReason = chunk.finishReason;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
(0, import_plugins.runAfterProviderCallHooks)({
|
|
434
|
+
content: roundContent,
|
|
435
|
+
toolCalls: roundToolCalls
|
|
436
|
+
});
|
|
437
|
+
if (roundToolCalls.length > 0) {
|
|
438
|
+
this.context.add({
|
|
439
|
+
role: "assistant",
|
|
440
|
+
content: roundContent || null,
|
|
441
|
+
toolCalls: roundToolCalls.map((tc) => ({
|
|
442
|
+
id: tc.id,
|
|
443
|
+
type: "function",
|
|
444
|
+
function: { name: tc.name, arguments: JSON.stringify(tc.args) }
|
|
445
|
+
}))
|
|
446
|
+
});
|
|
447
|
+
} else if (roundContent) {
|
|
448
|
+
this.context.add({ role: "assistant", content: roundContent });
|
|
449
|
+
}
|
|
450
|
+
if (roundToolCalls.length === 0) {
|
|
451
|
+
finalContent = roundContent;
|
|
452
|
+
finishReason = finishReason || "stop";
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
455
|
+
for (const tc of roundToolCalls) {
|
|
456
|
+
this.toolCallCount++;
|
|
457
|
+
await import_core7.globalEventBus.emit("tool:start", {
|
|
458
|
+
agentId: this.config.id || this.config.name,
|
|
459
|
+
runId,
|
|
460
|
+
tool: tc.name,
|
|
461
|
+
args: tc.args
|
|
462
|
+
});
|
|
463
|
+
options.onToolCall?.(tc.name, tc.args);
|
|
464
|
+
yield { type: "tool_call", toolCall: tc };
|
|
465
|
+
try {
|
|
466
|
+
const tool = this.config.tools?.find((t) => t.definition.name === tc.name);
|
|
467
|
+
if (!tool) throw new import_core8.ToolError(tc.name, `Tool "${tc.name}" not found on agent`);
|
|
468
|
+
const hookArgs = (0, import_plugins.runBeforeToolCallHooks)(tc.name, tc.args);
|
|
469
|
+
const result = await tool.execute(hookArgs);
|
|
470
|
+
const hookResult = (0, import_plugins.runAfterToolCallHooks)(result);
|
|
471
|
+
const resultStr = typeof hookResult === "string" ? hookResult : JSON.stringify(hookResult, null, 2);
|
|
472
|
+
this.context.add({
|
|
473
|
+
role: "tool",
|
|
474
|
+
toolCallId: tc.id,
|
|
475
|
+
name: tc.name,
|
|
476
|
+
content: resultStr
|
|
477
|
+
});
|
|
478
|
+
await import_core7.globalEventBus.emit("tool:finish", {
|
|
479
|
+
agentId: this.config.id || this.config.name,
|
|
480
|
+
runId,
|
|
481
|
+
tool: tc.name,
|
|
482
|
+
result: hookResult,
|
|
483
|
+
durationMs: Date.now() - startTime
|
|
484
|
+
});
|
|
485
|
+
options.onToolResult?.(tc.name, hookResult);
|
|
486
|
+
yield { type: "tool_result", toolCall: tc, result: hookResult };
|
|
487
|
+
} catch (err) {
|
|
488
|
+
this.context.add({
|
|
489
|
+
role: "tool",
|
|
490
|
+
toolCallId: tc.id,
|
|
491
|
+
name: tc.name,
|
|
492
|
+
content: `Error: ${err.message}`
|
|
493
|
+
});
|
|
494
|
+
await import_core7.globalEventBus.emit("tool:error", {
|
|
495
|
+
agentId: this.config.id || this.config.name,
|
|
496
|
+
runId,
|
|
497
|
+
tool: tc.name,
|
|
498
|
+
error: err.message
|
|
499
|
+
});
|
|
500
|
+
yield { type: "error", error: err.message };
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
const totalLatency = Date.now() - startTime;
|
|
505
|
+
if (this.memory) {
|
|
506
|
+
await this.memory.store({
|
|
507
|
+
id: (0, import_core6.generateId)(),
|
|
508
|
+
type: "short-term",
|
|
509
|
+
key: `agent:${this.config.name}:input:${(0, import_core6.generateId)()}`,
|
|
510
|
+
content: options.input,
|
|
511
|
+
metadata: { runId, agentName: this.config.name },
|
|
512
|
+
timestamp: Date.now()
|
|
513
|
+
});
|
|
514
|
+
if (finalContent) {
|
|
515
|
+
await this.memory.store({
|
|
516
|
+
id: (0, import_core6.generateId)(),
|
|
517
|
+
type: "short-term",
|
|
518
|
+
key: `agent:${this.config.name}:output:${(0, import_core6.generateId)()}`,
|
|
519
|
+
content: finalContent,
|
|
520
|
+
metadata: { runId, agentName: this.config.name },
|
|
521
|
+
timestamp: Date.now()
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
await import_core7.globalEventBus.emit("agent:response", {
|
|
526
|
+
agentId: this.config.id || this.config.name,
|
|
527
|
+
runId,
|
|
528
|
+
content: finalContent,
|
|
529
|
+
tokens: this.totalCompletionTokens,
|
|
530
|
+
latencyMs: totalLatency
|
|
531
|
+
});
|
|
532
|
+
(0, import_plugins.runAfterAgentRunHooks)({
|
|
533
|
+
id: runId,
|
|
534
|
+
output: finalContent,
|
|
535
|
+
messages: this.context.getMessages(),
|
|
536
|
+
usage: {
|
|
537
|
+
totalTokens: this.totalPromptTokens + this.totalCompletionTokens,
|
|
538
|
+
promptTokens: this.totalPromptTokens,
|
|
539
|
+
completionTokens: this.totalCompletionTokens
|
|
540
|
+
},
|
|
541
|
+
latencyMs: totalLatency,
|
|
542
|
+
toolCalls: this.toolCallCount,
|
|
543
|
+
finishReason
|
|
544
|
+
});
|
|
545
|
+
await import_core7.globalEventBus.emit("agent:complete", {
|
|
546
|
+
agentId: this.config.id || this.config.name,
|
|
547
|
+
runId,
|
|
548
|
+
totalTokens: this.totalPromptTokens + this.totalCompletionTokens,
|
|
549
|
+
totalLatencyMs: totalLatency,
|
|
550
|
+
toolCalls: this.toolCallCount
|
|
551
|
+
});
|
|
552
|
+
yield {
|
|
553
|
+
type: "finish",
|
|
554
|
+
output: finalContent,
|
|
555
|
+
finishReason,
|
|
556
|
+
usage: {
|
|
557
|
+
totalTokens: this.totalPromptTokens + this.totalCompletionTokens,
|
|
558
|
+
promptTokens: this.totalPromptTokens,
|
|
559
|
+
completionTokens: this.totalCompletionTokens
|
|
560
|
+
},
|
|
561
|
+
toolCalls: this.toolCallCount,
|
|
562
|
+
latencyMs: totalLatency
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
// src/agent.ts
|
|
568
|
+
var import_core9 = require("@lupaflow/core");
|
|
569
|
+
var import_tools = require("@lupaflow/tools");
|
|
570
|
+
var Agent = class {
|
|
571
|
+
config;
|
|
572
|
+
memoryStore;
|
|
573
|
+
constructor(config) {
|
|
574
|
+
validateAgentConfig(config);
|
|
575
|
+
this.config = {
|
|
576
|
+
...config,
|
|
577
|
+
id: config.id || (0, import_core9.generateId)()
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
tool(t) {
|
|
581
|
+
this.config.tools = this.config.tools || [];
|
|
582
|
+
this.config.tools.push(t);
|
|
583
|
+
return this;
|
|
584
|
+
}
|
|
585
|
+
useTool(name) {
|
|
586
|
+
try {
|
|
587
|
+
const tool = import_tools.toolRegistry.get(name);
|
|
588
|
+
this.config.tools = this.config.tools || [];
|
|
589
|
+
this.config.tools.push(tool);
|
|
590
|
+
} catch {
|
|
591
|
+
throw new Error(`Tool "${name}" not found in registry`);
|
|
592
|
+
}
|
|
593
|
+
return this;
|
|
594
|
+
}
|
|
595
|
+
memory(memory) {
|
|
596
|
+
this.memoryStore = memory;
|
|
597
|
+
return this;
|
|
598
|
+
}
|
|
599
|
+
personality(p) {
|
|
600
|
+
this.config.personality = p;
|
|
601
|
+
return this;
|
|
602
|
+
}
|
|
603
|
+
goal(g) {
|
|
604
|
+
this.config.goals = this.config.goals || [];
|
|
605
|
+
this.config.goals.push(g);
|
|
606
|
+
return this;
|
|
607
|
+
}
|
|
608
|
+
constraint(c) {
|
|
609
|
+
this.config.constraints = this.config.constraints || [];
|
|
610
|
+
this.config.constraints.push(c);
|
|
611
|
+
return this;
|
|
612
|
+
}
|
|
613
|
+
temperature(t) {
|
|
614
|
+
this.config.temperature = t;
|
|
615
|
+
return this;
|
|
616
|
+
}
|
|
617
|
+
model(m) {
|
|
618
|
+
this.config.model = m;
|
|
619
|
+
return this;
|
|
620
|
+
}
|
|
621
|
+
async run(input, options) {
|
|
622
|
+
const runner = new AgentRunner(this.config, this.memoryStore);
|
|
623
|
+
return runner.run({
|
|
624
|
+
input,
|
|
625
|
+
...options
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
async *streamRun(input, options) {
|
|
629
|
+
const runner = new AgentRunner(this.config, this.memoryStore);
|
|
630
|
+
yield* runner.streamRun({
|
|
631
|
+
input,
|
|
632
|
+
...options
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
637
|
+
0 && (module.exports = {
|
|
638
|
+
Agent,
|
|
639
|
+
AgentRunner,
|
|
640
|
+
ContextManager,
|
|
641
|
+
buildSystemPrompt,
|
|
642
|
+
validateAgentConfig,
|
|
643
|
+
withRetry
|
|
644
|
+
});
|
|
645
|
+
//# sourceMappingURL=index.cjs.map
|