@opperai/agents 0.3.0 → 0.4.1

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.js CHANGED
@@ -100,7 +100,8 @@ var init_tool = __esm({
100
100
  output,
101
101
  ...init.startedAt !== void 0 && { startedAt: init.startedAt },
102
102
  finishedAt: init.finishedAt ?? Date.now(),
103
- metadata: init.metadata ?? {}
103
+ metadata: init.metadata ?? {},
104
+ ...init.usage !== void 0 && { usage: init.usage }
104
105
  };
105
106
  ToolResultSuccessSchema.parse(result);
106
107
  return result;
@@ -112,7 +113,8 @@ var init_tool = __esm({
112
113
  error,
113
114
  ...init.startedAt !== void 0 && { startedAt: init.startedAt },
114
115
  finishedAt: init.finishedAt ?? Date.now(),
115
- metadata: init.metadata ?? {}
116
+ metadata: init.metadata ?? {},
117
+ ...init.usage !== void 0 && { usage: init.usage }
116
118
  };
117
119
  ToolResultFailureSchema.parse(result);
118
120
  return result;
@@ -167,14 +169,43 @@ var init_tool = __esm({
167
169
  var context_exports = {};
168
170
  __export(context_exports, {
169
171
  AgentContext: () => AgentContext,
172
+ BaseUsageSchema: () => BaseUsageSchema,
170
173
  ExecutionCycleSchema: () => ExecutionCycleSchema,
171
- UsageSchema: () => UsageSchema
174
+ UsageSchema: () => UsageSchema,
175
+ addUsage: () => addUsage,
176
+ createEmptyUsage: () => createEmptyUsage
172
177
  });
173
- var UsageSchema, ExecutionCycleSchema, AgentContext;
178
+ function createEmptyUsage() {
179
+ return {
180
+ requests: 0,
181
+ inputTokens: 0,
182
+ outputTokens: 0,
183
+ totalTokens: 0,
184
+ cost: {
185
+ generation: 0,
186
+ platform: 0,
187
+ total: 0
188
+ }
189
+ };
190
+ }
191
+ function addUsage(a, b) {
192
+ return {
193
+ requests: a.requests + b.requests,
194
+ inputTokens: a.inputTokens + b.inputTokens,
195
+ outputTokens: a.outputTokens + b.outputTokens,
196
+ totalTokens: a.totalTokens + b.totalTokens,
197
+ cost: {
198
+ generation: a.cost.generation + b.cost.generation,
199
+ platform: a.cost.platform + b.cost.platform,
200
+ total: a.cost.total + b.cost.total
201
+ }
202
+ };
203
+ }
204
+ var BaseUsageSchema, UsageSchema, ExecutionCycleSchema, AgentContext;
174
205
  var init_context = __esm({
175
206
  "src/base/context.ts"() {
176
207
  init_tool();
177
- UsageSchema = z.object({
208
+ BaseUsageSchema = z.object({
178
209
  requests: z.number().int().nonnegative().default(0),
179
210
  inputTokens: z.number().int().nonnegative().default(0),
180
211
  outputTokens: z.number().int().nonnegative().default(0),
@@ -185,6 +216,13 @@ var init_context = __esm({
185
216
  total: z.number().nonnegative().default(0)
186
217
  }).default({ generation: 0, platform: 0, total: 0 })
187
218
  });
219
+ UsageSchema = BaseUsageSchema.extend({
220
+ /**
221
+ * Optional breakdown of usage by source (agent name).
222
+ * Only present when nested agents are used.
223
+ */
224
+ breakdown: z.record(z.string(), z.lazy(() => BaseUsageSchema)).optional()
225
+ });
188
226
  ExecutionCycleSchema = z.object({
189
227
  iteration: z.number().int().nonnegative(),
190
228
  thought: z.unknown().nullable().optional(),
@@ -226,10 +264,42 @@ var init_context = __esm({
226
264
  generation: this.usage.cost.generation + next.cost.generation,
227
265
  platform: this.usage.cost.platform + next.cost.platform,
228
266
  total: this.usage.cost.total + next.cost.total
229
- }
267
+ },
268
+ // Preserve existing breakdown
269
+ ...this.usage.breakdown && { breakdown: this.usage.breakdown }
230
270
  };
231
271
  this.touch();
232
272
  }
273
+ /**
274
+ * Update usage with source tracking for nested agent aggregation.
275
+ * This method updates the total usage AND tracks it by source in the breakdown.
276
+ *
277
+ * @param source - The source name (typically the agent/tool name)
278
+ * @param delta - The usage to add
279
+ */
280
+ updateUsageWithSource(source, delta) {
281
+ this.updateUsage(delta);
282
+ if (!this.usage.breakdown) {
283
+ this.usage.breakdown = {};
284
+ }
285
+ const existing = this.usage.breakdown[source] ?? createEmptyUsage();
286
+ this.usage.breakdown[source] = addUsage(existing, delta);
287
+ }
288
+ /**
289
+ * Clean up the usage breakdown if it only contains the parent agent.
290
+ * This ensures breakdown is only present when there are nested agents.
291
+ *
292
+ * @param parentAgentName - The name of the parent agent to check for
293
+ */
294
+ cleanupBreakdownIfOnlyParent(parentAgentName) {
295
+ if (!this.usage.breakdown) {
296
+ return;
297
+ }
298
+ const sources = Object.keys(this.usage.breakdown);
299
+ if (sources.length === 1 && sources[0] === parentAgentName) {
300
+ delete this.usage.breakdown;
301
+ }
302
+ }
233
303
  addCycle(cycle) {
234
304
  const parsed = ExecutionCycleSchema.parse(cycle);
235
305
  this.executionHistory.push(parsed);
@@ -275,6 +345,18 @@ var init_context = __esm({
275
345
  this.touch();
276
346
  }
277
347
  snapshot() {
348
+ const usageCopy = {
349
+ ...this.usage,
350
+ cost: { ...this.usage.cost },
351
+ ...this.usage.breakdown && {
352
+ breakdown: Object.fromEntries(
353
+ Object.entries(this.usage.breakdown).map(([key, value]) => [
354
+ key,
355
+ { ...value, cost: { ...value.cost } }
356
+ ])
357
+ )
358
+ }
359
+ };
278
360
  return {
279
361
  agentName: this.agentName,
280
362
  sessionId: this.sessionId,
@@ -282,7 +364,7 @@ var init_context = __esm({
282
364
  iteration: this.iteration,
283
365
  goal: this.goal,
284
366
  executionHistory: [...this.executionHistory],
285
- usage: { ...this.usage },
367
+ usage: usageCopy,
286
368
  toolCalls: [...this.toolCalls],
287
369
  metadata: { ...this.metadata },
288
370
  startedAt: this.startedAt,
@@ -469,82 +551,6 @@ var HookManager = class {
469
551
  };
470
552
  var createHookManager = (logger) => new HookManager(logger);
471
553
 
472
- // src/base/events.ts
473
- var AgentEvents = {
474
- StreamStart: HookEvents.StreamStart,
475
- StreamChunk: HookEvents.StreamChunk,
476
- StreamEnd: HookEvents.StreamEnd,
477
- StreamError: HookEvents.StreamError
478
- };
479
- var AgentEventEmitter = class {
480
- registry = /* @__PURE__ */ new Map();
481
- logger;
482
- constructor(logger) {
483
- this.logger = logger ?? getDefaultLogger();
484
- }
485
- on(event, listener) {
486
- const listeners = this.registry.get(event) ?? /* @__PURE__ */ new Set();
487
- listeners.add(listener);
488
- this.registry.set(event, listeners);
489
- return () => this.off(event, listener);
490
- }
491
- once(event, listener) {
492
- const wrapper = (payload) => {
493
- try {
494
- listener(payload);
495
- } finally {
496
- this.off(event, wrapper);
497
- }
498
- };
499
- return this.on(event, wrapper);
500
- }
501
- off(event, listener) {
502
- const listeners = this.registry.get(event);
503
- if (!listeners) {
504
- return;
505
- }
506
- listeners.delete(listener);
507
- if (listeners.size === 0) {
508
- this.registry.delete(event);
509
- }
510
- }
511
- emit(event, payload) {
512
- const listeners = Array.from(
513
- this.registry.get(event) ?? /* @__PURE__ */ new Set()
514
- );
515
- if (listeners.length === 0) {
516
- return;
517
- }
518
- for (const listener of listeners) {
519
- try {
520
- listener(payload);
521
- } catch (error) {
522
- this.logger.warn(`Agent event listener failed for "${event}"`, {
523
- event,
524
- error: error instanceof Error ? error.message : String(error)
525
- });
526
- }
527
- }
528
- }
529
- removeAllListeners(event) {
530
- if (event) {
531
- this.registry.delete(event);
532
- return;
533
- }
534
- this.registry.clear();
535
- }
536
- listenerCount(event) {
537
- if (event) {
538
- return this.registry.get(event)?.size ?? 0;
539
- }
540
- let total = 0;
541
- for (const listeners of this.registry.values()) {
542
- total += listeners.size;
543
- }
544
- return total;
545
- }
546
- };
547
-
548
554
  // src/base/agent.ts
549
555
  init_tool();
550
556
  function sanitizeId(name) {
@@ -929,10 +935,6 @@ var BaseAgent = class {
929
935
  * Hook manager for lifecycle events
930
936
  */
931
937
  hooks;
932
- /**
933
- * Event dispatcher for runtime events (notably streaming)
934
- */
935
- events;
936
938
  /**
937
939
  * Registry of available tools
938
940
  */
@@ -987,7 +989,6 @@ var BaseAgent = class {
987
989
  this.enableStreaming = config.enableStreaming ?? false;
988
990
  this.metadata = { ...config.metadata ?? {} };
989
991
  this.hooks = new HookManager();
990
- this.events = new AgentEventEmitter();
991
992
  this.tools = /* @__PURE__ */ new Map();
992
993
  this.baseTools = /* @__PURE__ */ new Map();
993
994
  this.toolProviders = /* @__PURE__ */ new Set();
@@ -1038,11 +1039,37 @@ var BaseAgent = class {
1038
1039
  * Main entry point for agent execution.
1039
1040
  * Orchestrates lifecycle: context initialization, hook triggering, loop execution, teardown.
1040
1041
  *
1042
+ * **Note:** This method will be removed in a future update.
1043
+ * Consider using {@link run} instead, which returns both result and usage statistics.
1044
+ *
1041
1045
  * @param input - Input to process
1042
1046
  * @param parentSpanId - Optional parent span ID for tracing
1043
1047
  * @returns Processed output
1044
1048
  */
1045
1049
  async process(input, parentSpanId) {
1050
+ const { result } = await this.executeProcess(input, parentSpanId);
1051
+ return result;
1052
+ }
1053
+ /**
1054
+ * Process input and return both result and usage statistics.
1055
+ * This is the recommended method for agent execution.
1056
+ *
1057
+ * @param input - Input to process
1058
+ * @param parentSpanId - Optional parent span ID for tracing
1059
+ * @returns Object containing the result and usage statistics
1060
+ */
1061
+ async run(input, parentSpanId) {
1062
+ return this.executeProcess(input, parentSpanId);
1063
+ }
1064
+ /**
1065
+ * Internal method that executes the process and returns both result and usage.
1066
+ * This is the core implementation shared by process() and run().
1067
+ *
1068
+ * @param input - Input to process
1069
+ * @param parentSpanId - Optional parent span ID for tracing
1070
+ * @returns Object containing the result and usage statistics
1071
+ */
1072
+ async executeProcess(input, parentSpanId) {
1046
1073
  const validatedInput = this.inputSchema ? this.inputSchema.parse(input) : input;
1047
1074
  const context = await this.initializeContext(validatedInput, parentSpanId);
1048
1075
  try {
@@ -1054,7 +1081,8 @@ var BaseAgent = class {
1054
1081
  context,
1055
1082
  result: validatedOutput
1056
1083
  });
1057
- return validatedOutput;
1084
+ context.cleanupBreakdownIfOnlyParent(this.name);
1085
+ return { result: validatedOutput, usage: context.usage };
1058
1086
  } catch (error) {
1059
1087
  await this.triggerHook(HookEvents.AgentEnd, {
1060
1088
  context,
@@ -1144,6 +1172,8 @@ var BaseAgent = class {
1144
1172
  }
1145
1173
  /**
1146
1174
  * Convert this agent into a tool that can be used by other agents.
1175
+ * When used as a tool, the nested agent's usage statistics are propagated
1176
+ * back to the parent agent for aggregation.
1147
1177
  *
1148
1178
  * @param toolName - Optional custom name for the tool (defaults to agent name)
1149
1179
  * @param toolDescription - Optional custom description (defaults to agent description)
@@ -1163,8 +1193,8 @@ var BaseAgent = class {
1163
1193
  execute: async (input, executionContext) => {
1164
1194
  try {
1165
1195
  const parentSpanId = executionContext.spanId ?? executionContext.agentContext.parentSpanId ?? void 0;
1166
- const result = await this.process(input, parentSpanId);
1167
- return ToolResultFactory.success(tool2.name, result);
1196
+ const { result, usage } = await this.run(input, parentSpanId);
1197
+ return ToolResultFactory.success(tool2.name, result, { usage });
1168
1198
  } catch (error) {
1169
1199
  return ToolResultFactory.failure(
1170
1200
  tool2.name,
@@ -1187,32 +1217,34 @@ var BaseAgent = class {
1187
1217
  }
1188
1218
  /**
1189
1219
  * Register an event listener.
1220
+ * This is equivalent to registerHook() - both methods use the unified hook system.
1190
1221
  *
1191
- * @param event - Event name
1222
+ * @param event - Event name (any HookEvents value)
1192
1223
  * @param listener - Listener callback
1193
1224
  * @returns Cleanup function to unregister the listener
1194
1225
  */
1195
1226
  on(event, listener) {
1196
- return this.events.on(event, listener);
1227
+ return this.hooks.on(event, listener);
1197
1228
  }
1198
1229
  /**
1199
1230
  * Register a one-time event listener that removes itself after the first call.
1231
+ * This is equivalent to calling registerHook() with a self-removing handler.
1200
1232
  *
1201
- * @param event - Event name
1233
+ * @param event - Event name (any HookEvents value)
1202
1234
  * @param listener - Listener callback
1203
1235
  * @returns Cleanup function (no-op once listener fires)
1204
1236
  */
1205
1237
  once(event, listener) {
1206
- return this.events.once(event, listener);
1238
+ return this.hooks.once(event, listener);
1207
1239
  }
1208
1240
  /**
1209
1241
  * Remove a previously registered event listener.
1210
1242
  *
1211
- * @param event - Event name
1243
+ * @param event - Event name (any HookEvents value)
1212
1244
  * @param listener - Listener callback to remove
1213
1245
  */
1214
1246
  off(event, listener) {
1215
- this.events.off(event, listener);
1247
+ this.hooks.off(event, listener);
1216
1248
  }
1217
1249
  /**
1218
1250
  * Trigger a hook event with a payload.
@@ -1228,15 +1260,6 @@ var BaseAgent = class {
1228
1260
  console.warn(`Hook error for event ${event}:`, error);
1229
1261
  }
1230
1262
  }
1231
- /**
1232
- * Emit a runtime event to listeners.
1233
- *
1234
- * @param event - Event name
1235
- * @param payload - Event payload
1236
- */
1237
- emitAgentEvent(event, payload) {
1238
- this.events.emit(event, payload);
1239
- }
1240
1263
  /**
1241
1264
  * Execute a tool with proper context, hooks, and error handling.
1242
1265
  *
@@ -1297,6 +1320,14 @@ var BaseAgent = class {
1297
1320
  finishedAt,
1298
1321
  metadata: {}
1299
1322
  });
1323
+ if (!result.success) {
1324
+ await this.triggerHook(HookEvents.ToolError, {
1325
+ context,
1326
+ tool: tool2,
1327
+ toolName: tool2.name,
1328
+ error: result.error
1329
+ });
1330
+ }
1300
1331
  await this.triggerHook(HookEvents.AfterTool, {
1301
1332
  context,
1302
1333
  tool: tool2,
@@ -1422,6 +1453,11 @@ var BaseAgent = class {
1422
1453
 
1423
1454
  // src/index.ts
1424
1455
  init_context();
1456
+
1457
+ // src/base/events.ts
1458
+ var AgentEvents = HookEvents;
1459
+
1460
+ // src/index.ts
1425
1461
  init_result();
1426
1462
  init_tool();
1427
1463
  var ThoughtSchema = z.object({
@@ -1590,7 +1626,7 @@ var mergeSchemaDefaults = (schema, value) => {
1590
1626
 
1591
1627
  // package.json
1592
1628
  var package_default = {
1593
- version: "0.3.0"};
1629
+ version: "0.4.1"};
1594
1630
 
1595
1631
  // src/utils/version.ts
1596
1632
  var SDK_NAME = "@opperai/agents";
@@ -2260,7 +2296,7 @@ var Agent = class extends BaseAgent {
2260
2296
  model: this.model,
2261
2297
  ...context.parentSpanId && { parentSpanId: context.parentSpanId }
2262
2298
  });
2263
- context.updateUsage({
2299
+ context.updateUsageWithSource(this.name, {
2264
2300
  requests: 1,
2265
2301
  inputTokens: response.usage.inputTokens,
2266
2302
  outputTokens: response.usage.outputTokens,
@@ -2312,10 +2348,6 @@ var Agent = class extends BaseAgent {
2312
2348
  context,
2313
2349
  callType: "think"
2314
2350
  });
2315
- this.emitAgentEvent(HookEvents.StreamStart, {
2316
- context,
2317
- callType: "think"
2318
- });
2319
2351
  try {
2320
2352
  const streamResponse = await this.opperClient.stream({
2321
2353
  name: spanName,
@@ -2352,7 +2384,6 @@ var Agent = class extends BaseAgent {
2352
2384
  fieldBuffers: feedResult.snapshot
2353
2385
  };
2354
2386
  await this.triggerHook(HookEvents.StreamChunk, chunkPayload);
2355
- this.emitAgentEvent(HookEvents.StreamChunk, chunkPayload);
2356
2387
  }
2357
2388
  const fieldBuffers = assembler.snapshot();
2358
2389
  const endPayload = {
@@ -2361,7 +2392,6 @@ var Agent = class extends BaseAgent {
2361
2392
  fieldBuffers
2362
2393
  };
2363
2394
  await this.triggerHook(HookEvents.StreamEnd, endPayload);
2364
- this.emitAgentEvent(HookEvents.StreamEnd, endPayload);
2365
2395
  const finalize = assembler.finalize();
2366
2396
  let decision;
2367
2397
  if (finalize.type === "structured" && finalize.structured) {
@@ -2378,7 +2408,7 @@ var Agent = class extends BaseAgent {
2378
2408
  streamSpanId
2379
2409
  );
2380
2410
  if (!usageTracked) {
2381
- context.updateUsage({
2411
+ context.updateUsageWithSource(this.name, {
2382
2412
  requests: 1,
2383
2413
  inputTokens: 0,
2384
2414
  outputTokens: 0,
@@ -2423,11 +2453,6 @@ var Agent = class extends BaseAgent {
2423
2453
  callType: "think",
2424
2454
  error
2425
2455
  });
2426
- this.emitAgentEvent(HookEvents.StreamError, {
2427
- context,
2428
- callType: "think",
2429
- error
2430
- });
2431
2456
  this.logger.error("Think step failed", error);
2432
2457
  throw new Error(
2433
2458
  `Think step failed: ${error instanceof Error ? error.message : String(error)}`
@@ -2485,12 +2510,30 @@ The memory you write persists across all process() calls on this agent.`;
2485
2510
  * Build dynamic context for the think step
2486
2511
  */
2487
2512
  async buildThinkContext(input, context) {
2488
- const availableTools = Array.from(this.tools.values()).map((tool2) => ({
2489
- name: tool2.name,
2490
- description: tool2.description || "",
2491
- // Convert Zod schema to JSON Schema for LLM consumption
2492
- parameters: tool2.schema ? schemaToJson(tool2.schema) : {}
2493
- }));
2513
+ const availableTools = Array.from(this.tools.values()).map((tool2) => {
2514
+ let parameters = {};
2515
+ if (tool2.schema) {
2516
+ parameters = schemaToJson(tool2.schema);
2517
+ } else if (tool2.metadata?.["parameters"] && typeof tool2.metadata["parameters"] === "object") {
2518
+ parameters = tool2.metadata["parameters"];
2519
+ }
2520
+ let returns = void 0;
2521
+ if (tool2.outputSchema) {
2522
+ returns = schemaToJson(tool2.outputSchema);
2523
+ } else if (tool2.metadata?.["outputSchema"] && typeof tool2.metadata["outputSchema"] === "object") {
2524
+ returns = tool2.metadata["outputSchema"];
2525
+ }
2526
+ return {
2527
+ name: tool2.name,
2528
+ description: tool2.description || "",
2529
+ // Include parameters (from Zod schema or MCP metadata)
2530
+ parameters,
2531
+ // Include output schema if defined (helps LLM understand what tool returns)
2532
+ ...returns !== void 0 ? { returns } : {},
2533
+ // Include examples if defined (helps LLM understand expected behavior)
2534
+ ...tool2.examples ? { examples: tool2.examples } : {}
2535
+ };
2536
+ });
2494
2537
  const executionHistory = context.getLastNCycles(3).map((cycle) => {
2495
2538
  const thought = typeof cycle.thought === "object" && cycle.thought !== null ? cycle.thought["reasoning"] || "" : String(cycle.thought || "");
2496
2539
  const results = Array.isArray(cycle.results) ? cycle.results.map((r) => {
@@ -2560,6 +2603,9 @@ The memory you write persists across all process() calls on this agent.`;
2560
2603
  context,
2561
2604
  { spanId: toolSpan.id }
2562
2605
  );
2606
+ if (result.usage) {
2607
+ context.updateUsageWithSource(toolCall.toolName, result.usage);
2608
+ }
2563
2609
  const endTime = /* @__PURE__ */ new Date();
2564
2610
  const durationMs = endTime.getTime() - startTime.getTime();
2565
2611
  if (result.success) {
@@ -2818,7 +2864,7 @@ Follow any instructions provided for formatting and style.`;
2818
2864
  callOptions.outputSchema = this.outputSchema;
2819
2865
  }
2820
2866
  const response = await this.opperClient.call(callOptions);
2821
- context.updateUsage({
2867
+ context.updateUsageWithSource(this.name, {
2822
2868
  requests: 1,
2823
2869
  inputTokens: response.usage.inputTokens,
2824
2870
  outputTokens: response.usage.outputTokens,
@@ -2848,10 +2894,6 @@ Follow any instructions provided for formatting and style.`;
2848
2894
  context,
2849
2895
  callType: "final_result"
2850
2896
  });
2851
- this.emitAgentEvent(HookEvents.StreamStart, {
2852
- context,
2853
- callType: "final_result"
2854
- });
2855
2897
  try {
2856
2898
  const sanitizedName = this.name.toLowerCase().replace(/[\s-]/g, "_");
2857
2899
  const functionName = `generate_final_result_${sanitizedName}`;
@@ -2890,7 +2932,6 @@ Follow any instructions provided for formatting and style.`;
2890
2932
  fieldBuffers: feedResult.snapshot
2891
2933
  };
2892
2934
  await this.triggerHook(HookEvents.StreamChunk, chunkPayload);
2893
- this.emitAgentEvent(HookEvents.StreamChunk, chunkPayload);
2894
2935
  }
2895
2936
  const fieldBuffers = assembler.snapshot();
2896
2937
  const endPayload = {
@@ -2899,7 +2940,6 @@ Follow any instructions provided for formatting and style.`;
2899
2940
  fieldBuffers
2900
2941
  };
2901
2942
  await this.triggerHook(HookEvents.StreamEnd, endPayload);
2902
- this.emitAgentEvent(HookEvents.StreamEnd, endPayload);
2903
2943
  const finalize = assembler.finalize();
2904
2944
  let result;
2905
2945
  if (this.outputSchema) {
@@ -2923,7 +2963,7 @@ Follow any instructions provided for formatting and style.`;
2923
2963
  streamSpanId
2924
2964
  );
2925
2965
  if (!usageTracked) {
2926
- context.updateUsage({
2966
+ context.updateUsageWithSource(this.name, {
2927
2967
  requests: 1,
2928
2968
  inputTokens: 0,
2929
2969
  outputTokens: 0,
@@ -2947,11 +2987,6 @@ Follow any instructions provided for formatting and style.`;
2947
2987
  callType: "final_result",
2948
2988
  error
2949
2989
  });
2950
- this.emitAgentEvent(HookEvents.StreamError, {
2951
- context,
2952
- callType: "final_result",
2953
- error
2954
- });
2955
2990
  this.logger.error("Failed to generate final result", error);
2956
2991
  throw new Error(
2957
2992
  `Failed to generate final result: ${error instanceof Error ? error.message : String(error)}`
@@ -2987,7 +3022,7 @@ Follow any instructions provided for formatting and style.`;
2987
3022
  const fallbackTotal = record["total_tokens"];
2988
3023
  const totalTokensRaw = typeof primaryTotal === "number" && Number.isFinite(primaryTotal) ? primaryTotal : typeof fallbackTotal === "number" && Number.isFinite(fallbackTotal) ? fallbackTotal : void 0;
2989
3024
  if (totalTokensRaw !== void 0) {
2990
- context.updateUsage({
3025
+ context.updateUsageWithSource(this.name, {
2991
3026
  requests: 1,
2992
3027
  inputTokens: 0,
2993
3028
  outputTokens: 0,
@@ -3352,6 +3387,11 @@ var mcp = (...configs) => {
3352
3387
 
3353
3388
  // src/utils/tool-decorators.ts
3354
3389
  init_tool();
3390
+ var isToolResult = (value) => {
3391
+ if (typeof value !== "object" || value === null) return false;
3392
+ const obj = value;
3393
+ return typeof obj["success"] === "boolean" && typeof obj["toolName"] === "string" && ("output" in obj || "error" in obj);
3394
+ };
3355
3395
  var reflectWithMetadata = Reflect;
3356
3396
  var ReflectMetadata = {
3357
3397
  define: (metadataKey, metadataValue, target, propertyKey) => {
@@ -3439,6 +3479,8 @@ function createToolDefinition(options, methodName, propertyKey, method, callTarg
3439
3479
  name,
3440
3480
  description,
3441
3481
  ...options.schema && { schema: options.schema },
3482
+ ...options.outputSchema && { outputSchema: options.outputSchema },
3483
+ ...options.examples && { examples: options.examples },
3442
3484
  ...options.timeoutMs !== void 0 && { timeoutMs: options.timeoutMs },
3443
3485
  metadata: {
3444
3486
  ...options.metadata,
@@ -3455,6 +3497,8 @@ function createFunctionTool(fn, options = {}) {
3455
3497
  name,
3456
3498
  description,
3457
3499
  ...options.schema && { schema: options.schema },
3500
+ ...options.outputSchema && { outputSchema: options.outputSchema },
3501
+ ...options.examples && { examples: options.examples },
3458
3502
  ...options.timeoutMs !== void 0 && { timeoutMs: options.timeoutMs },
3459
3503
  metadata: {
3460
3504
  ...options.metadata,
@@ -3477,6 +3521,9 @@ function createFunctionTool(fn, options = {}) {
3477
3521
  } else {
3478
3522
  result = await Promise.resolve(fn(input, context));
3479
3523
  }
3524
+ if (isToolResult(result)) {
3525
+ return result;
3526
+ }
3480
3527
  return ToolResultFactory.success(name, result, {
3481
3528
  startedAt,
3482
3529
  finishedAt: Date.now(),
@@ -3770,6 +3817,6 @@ var ToolRunner = class {
3770
3817
  }
3771
3818
  };
3772
3819
 
3773
- export { Agent, AgentContext, AgentDecisionSchema, AgentEventEmitter, AgentEvents, BaseAgent, ConsoleLogger, DEFAULT_MODEL, DEFAULT_RETRY_CONFIG, ExecutionCycleSchema, HookEvents, HookManager, InMemoryStore, LogLevel, MCPClient, MCPServerConfigSchema, MCPToolProvider, MCPconfig, MemoryEntryMetadataSchema, MemoryEntrySchema, MemoryUpdateSchema, OpperClient, Result, STREAM_ROOT_PATH, SchemaValidationError, SilentLogger, StreamAssembler, ThoughtSchema, ToolCallRecordSchema, ToolCallSchema, ToolExecutionSummarySchema, ToolMetadataSchema, ToolResultFactory, ToolResultFailureSchema, ToolResultSchema, ToolResultSuccessSchema, ToolRunner, UsageSchema, coerceToolDefinition, createAgentDecisionWithOutputSchema, createFunctionTool, createHookManager, createInMemoryStore, createMCPServerConfig, createOpperClient, createStreamAssembler, createToolCallRecord, err, extractTools, generateAgentFlowDiagram, getDefaultLogger, getSchemaDefault, isSchemaValid, isToolProvider, mcp, mergeSchemaDefaults, normalizeToolEntries, ok, schemaToJson, setDefaultLogger, tool, validateSchema, validateToolInput, zodSchemaToJsonSchema };
3820
+ export { Agent, AgentContext, AgentDecisionSchema, AgentEvents, BaseAgent, BaseUsageSchema, ConsoleLogger, DEFAULT_MODEL, DEFAULT_RETRY_CONFIG, ExecutionCycleSchema, HookEvents, HookManager, InMemoryStore, LogLevel, MCPClient, MCPServerConfigSchema, MCPToolProvider, MCPconfig, MemoryEntryMetadataSchema, MemoryEntrySchema, MemoryUpdateSchema, OpperClient, Result, STREAM_ROOT_PATH, SchemaValidationError, SilentLogger, StreamAssembler, ThoughtSchema, ToolCallRecordSchema, ToolCallSchema, ToolExecutionSummarySchema, ToolMetadataSchema, ToolResultFactory, ToolResultFailureSchema, ToolResultSchema, ToolResultSuccessSchema, ToolRunner, UsageSchema, addUsage, coerceToolDefinition, createAgentDecisionWithOutputSchema, createEmptyUsage, createFunctionTool, createHookManager, createInMemoryStore, createMCPServerConfig, createOpperClient, createStreamAssembler, createToolCallRecord, err, extractTools, generateAgentFlowDiagram, getDefaultLogger, getSchemaDefault, isSchemaValid, isToolProvider, mcp, mergeSchemaDefaults, normalizeToolEntries, ok, schemaToJson, setDefaultLogger, tool, validateSchema, validateToolInput, zodSchemaToJsonSchema };
3774
3821
  //# sourceMappingURL=index.js.map
3775
3822
  //# sourceMappingURL=index.js.map