@opperai/agents 0.2.0 → 0.3.0-beta

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 CHANGED
@@ -945,6 +945,28 @@ var BaseAgent = class {
945
945
  * Opper client configuration
946
946
  */
947
947
  opperConfig;
948
+ /**
949
+ * Creates a new BaseAgent instance
950
+ *
951
+ * @param config - Agent configuration object
952
+ * @param config.name - Unique name identifying this agent (required)
953
+ * @param config.description - Human-readable description of the agent's purpose
954
+ * @param config.instructions - System instructions guiding agent behavior
955
+ * @param config.tools - Array of tools or tool providers available to the agent
956
+ * @param config.maxIterations - Maximum iterations before terminating the agent loop (default: 25)
957
+ * @param config.model - Model identifier(s). Single model or array for fallback (default: "gcp/gemini-flash-latest")
958
+ * @param config.inputSchema - Zod schema for input validation
959
+ * @param config.outputSchema - Zod schema for output validation
960
+ * @param config.enableStreaming - Enable Opper streaming APIs for LLM calls (default: false)
961
+ * @param config.enableMemory - Enable memory subsystem (default: false)
962
+ * @param config.memory - Custom memory implementation (defaults to InMemoryStore if enableMemory is true)
963
+ * @param config.metadata - Additional metadata for the agent
964
+ * @param config.opperConfig - Opper API configuration containing apiKey and baseUrl
965
+ * @param config.onStreamStart - Handler invoked when a streaming call starts
966
+ * @param config.onStreamChunk - Handler invoked for each streaming chunk
967
+ * @param config.onStreamEnd - Handler invoked when a streaming call ends
968
+ * @param config.onStreamError - Handler invoked when streaming encounters an error
969
+ */
948
970
  constructor(config) {
949
971
  this.name = config.name;
950
972
  this.description = config.description;
@@ -1445,6 +1467,10 @@ var AgentDecisionSchema = zod.z.object({
1445
1467
  * Agent's internal reasoning
1446
1468
  */
1447
1469
  reasoning: zod.z.string(),
1470
+ /**
1471
+ * Status message for the user (e.g., "Searching for information...", "Processing results...")
1472
+ */
1473
+ userMessage: zod.z.string().default("Working on it..."),
1448
1474
  /**
1449
1475
  * Tool calls to execute (if any)
1450
1476
  * Empty array signals task completion
@@ -1457,8 +1483,34 @@ var AgentDecisionSchema = zod.z.object({
1457
1483
  /**
1458
1484
  * Memory entries to write/update (key -> payload)
1459
1485
  */
1460
- memoryUpdates: zod.z.record(MemoryUpdateSchema).default({})
1486
+ memoryUpdates: zod.z.record(MemoryUpdateSchema).default({}),
1487
+ /**
1488
+ * Whether the task is complete and finalResult is available
1489
+ * (single LLM call pattern)
1490
+ */
1491
+ isComplete: zod.z.boolean().default(false),
1492
+ /**
1493
+ * The final result when isComplete=true
1494
+ * Should match outputSchema if specified
1495
+ */
1496
+ finalResult: zod.z.unknown().optional()
1461
1497
  });
1498
+ function createAgentDecisionWithOutputSchema(outputSchema) {
1499
+ if (!outputSchema) {
1500
+ return AgentDecisionSchema;
1501
+ }
1502
+ const finalResultSchema = outputSchema.optional();
1503
+ const dynamicSchema = zod.z.object({
1504
+ reasoning: zod.z.string(),
1505
+ userMessage: zod.z.string().default("Working on it..."),
1506
+ toolCalls: zod.z.array(ToolCallSchema).default([]),
1507
+ memoryReads: zod.z.array(zod.z.string()).default([]),
1508
+ memoryUpdates: zod.z.record(MemoryUpdateSchema).default({}),
1509
+ isComplete: zod.z.boolean().default(false),
1510
+ finalResult: finalResultSchema
1511
+ });
1512
+ return dynamicSchema;
1513
+ }
1462
1514
  var ToolExecutionSummarySchema = zod.z.object({
1463
1515
  /**
1464
1516
  * Tool name
@@ -1480,7 +1532,7 @@ var ToolExecutionSummarySchema = zod.z.object({
1480
1532
 
1481
1533
  // package.json
1482
1534
  var package_default = {
1483
- version: "0.2.0"};
1535
+ version: "0.3.0-beta"};
1484
1536
 
1485
1537
  // src/utils/version.ts
1486
1538
  var SDK_NAME = "@opperai/agents";
@@ -1608,7 +1660,8 @@ var OpperClient = class {
1608
1660
  const span = await this.client.spans.create({
1609
1661
  name: options.name,
1610
1662
  ...options.input !== void 0 && { input: options.input },
1611
- ...options.parentSpanId && { parentId: options.parentSpanId }
1663
+ ...options.parentSpanId && { parentId: options.parentSpanId },
1664
+ ...options.type && { type: options.type }
1612
1665
  });
1613
1666
  return {
1614
1667
  id: span.id,
@@ -1625,7 +1678,11 @@ var OpperClient = class {
1625
1678
  const serializedOutput = output !== void 0 && output !== null ? typeof output === "object" ? JSON.stringify(output) : String(output) : void 0;
1626
1679
  await this.client.spans.update(spanId, {
1627
1680
  ...serializedOutput !== void 0 && { output: serializedOutput },
1628
- ...options?.error && { error: options.error }
1681
+ ...options?.error && { error: options.error },
1682
+ ...options?.startTime && { startTime: options.startTime },
1683
+ ...options?.endTime && { endTime: options.endTime },
1684
+ ...options?.meta && { meta: options.meta },
1685
+ ...options?.name && { name: options.name }
1629
1686
  });
1630
1687
  }, `update-span:${spanId}`);
1631
1688
  }
@@ -1943,7 +2000,11 @@ var StreamAssembler = class {
1943
2000
  if (path === STREAM_ROOT_PATH) {
1944
2001
  continue;
1945
2002
  }
1946
- const value = resolveFieldValue(path, this.displayBuffers, this.valueBuffers);
2003
+ const value = resolveFieldValue(
2004
+ path,
2005
+ this.displayBuffers,
2006
+ this.valueBuffers
2007
+ );
1947
2008
  setNestedValue(result, path, value);
1948
2009
  }
1949
2010
  return normalizeIndexed(result);
@@ -1963,6 +2024,31 @@ var Agent = class extends BaseAgent {
1963
2024
  opperClient;
1964
2025
  logger;
1965
2026
  verbose;
2027
+ /**
2028
+ * Creates a new Agent instance
2029
+ *
2030
+ * @param config - Agent configuration object
2031
+ * @param config.name - Unique name identifying this agent (required)
2032
+ * @param config.description - Human-readable description of the agent's purpose
2033
+ * @param config.instructions - System instructions guiding agent behavior
2034
+ * @param config.tools - Array of tools or tool providers available to the agent
2035
+ * @param config.maxIterations - Maximum iterations before terminating (default: 25)
2036
+ * @param config.model - Model identifier(s) as string or array for fallback (default: "gcp/gemini-flash-latest")
2037
+ * @param config.inputSchema - Zod schema for input validation
2038
+ * @param config.outputSchema - Zod schema for output validation
2039
+ * @param config.enableStreaming - Enable streaming for LLM calls (default: false)
2040
+ * @param config.enableMemory - Enable memory subsystem (default: false)
2041
+ * @param config.memory - Custom memory implementation (defaults to InMemoryStore if enableMemory is true)
2042
+ * @param config.metadata - Additional metadata for the agent
2043
+ * @param config.opperConfig - Opper API configuration (apiKey, baseUrl)
2044
+ * @param config.opperClient - Custom Opper client instance (for testing or custom configuration)
2045
+ * @param config.logger - Logger instance for debugging
2046
+ * @param config.verbose - Enable verbose logging (default: false)
2047
+ * @param config.onStreamStart - Handler invoked when streaming starts
2048
+ * @param config.onStreamChunk - Handler invoked for each streaming chunk
2049
+ * @param config.onStreamEnd - Handler invoked when streaming ends
2050
+ * @param config.onStreamError - Handler invoked on streaming errors
2051
+ */
1966
2052
  constructor(config) {
1967
2053
  super(config);
1968
2054
  this.logger = config.logger ?? getDefaultLogger();
@@ -1998,6 +2084,7 @@ var Agent = class extends BaseAgent {
1998
2084
  maxIterations: this.maxIterations,
1999
2085
  tools: Array.from(this.tools.keys())
2000
2086
  });
2087
+ const executionStartTime = /* @__PURE__ */ new Date();
2001
2088
  const parentSpan = await this.opperClient.createSpan({
2002
2089
  name: `${this.name}_execution`,
2003
2090
  input: this.serializeInput(input),
@@ -2017,6 +2104,47 @@ var Agent = class extends BaseAgent {
2017
2104
  input,
2018
2105
  context
2019
2106
  );
2107
+ if (decision.isComplete && decision.finalResult !== void 0) {
2108
+ this.log("Task completed with final result in single call", {
2109
+ iteration: currentIteration
2110
+ });
2111
+ let finalResult;
2112
+ if (this.outputSchema) {
2113
+ const parseResult = this.outputSchema.safeParse(
2114
+ decision.finalResult
2115
+ );
2116
+ if (parseResult.success) {
2117
+ finalResult = parseResult.data;
2118
+ } else {
2119
+ this.logger.warn(
2120
+ "Final result validation against output schema failed, falling back to generate_final_result",
2121
+ { error: parseResult.error.message }
2122
+ );
2123
+ break;
2124
+ }
2125
+ } else {
2126
+ const rawResult = decision.finalResult;
2127
+ if (typeof rawResult === "string") {
2128
+ finalResult = rawResult;
2129
+ } else if (rawResult === null || rawResult === void 0) {
2130
+ finalResult = "";
2131
+ } else if (typeof rawResult === "object") {
2132
+ finalResult = JSON.stringify(rawResult);
2133
+ } else {
2134
+ finalResult = String(rawResult);
2135
+ }
2136
+ }
2137
+ const executionEndTime2 = /* @__PURE__ */ new Date();
2138
+ await this.opperClient.updateSpan(parentSpan.id, finalResult, {
2139
+ startTime: executionStartTime,
2140
+ endTime: executionEndTime2,
2141
+ meta: {
2142
+ durationMs: executionEndTime2.getTime() - executionStartTime.getTime()
2143
+ }
2144
+ });
2145
+ await this.triggerHook(HookEvents.LoopEnd, { context });
2146
+ return finalResult;
2147
+ }
2020
2148
  const memoryResults = await this.handleMemoryActions(
2021
2149
  decision,
2022
2150
  context,
@@ -2026,7 +2154,7 @@ var Agent = class extends BaseAgent {
2026
2154
  const toolResults = await this.executeToolCalls(
2027
2155
  decision,
2028
2156
  context,
2029
- thinkSpanId
2157
+ context.parentSpanId ?? void 0
2030
2158
  );
2031
2159
  const combinedResults = [...memoryResults, ...toolResults];
2032
2160
  const newToolCalls = context.toolCalls.slice(toolCallStartIndex);
@@ -2061,11 +2189,24 @@ var Agent = class extends BaseAgent {
2061
2189
  );
2062
2190
  }
2063
2191
  const result = await this.generateFinalResult(input, context);
2064
- await this.opperClient.updateSpan(parentSpan.id, result);
2192
+ const executionEndTime = /* @__PURE__ */ new Date();
2193
+ await this.opperClient.updateSpan(parentSpan.id, result, {
2194
+ startTime: executionStartTime,
2195
+ endTime: executionEndTime,
2196
+ meta: {
2197
+ durationMs: executionEndTime.getTime() - executionStartTime.getTime()
2198
+ }
2199
+ });
2065
2200
  return result;
2066
2201
  } catch (error) {
2202
+ const executionEndTime = /* @__PURE__ */ new Date();
2067
2203
  await this.opperClient.updateSpan(parentSpan.id, void 0, {
2068
- error: error instanceof Error ? error.message : String(error)
2204
+ error: error instanceof Error ? error.message : String(error),
2205
+ startTime: executionStartTime,
2206
+ endTime: executionEndTime,
2207
+ meta: {
2208
+ durationMs: executionEndTime.getTime() - executionStartTime.getTime()
2209
+ }
2069
2210
  });
2070
2211
  throw error;
2071
2212
  }
@@ -2074,11 +2215,15 @@ var Agent = class extends BaseAgent {
2074
2215
  * Think step: Call LLM to decide next action
2075
2216
  */
2076
2217
  async think(input, context) {
2077
- const spanName = "think";
2218
+ const sanitizedName = this.name.toLowerCase().replace(/[\s-]/g, "_");
2219
+ const spanName = `think_${sanitizedName}`;
2078
2220
  this.log("Think step", { iteration: context.iteration });
2079
2221
  await this.triggerHook(HookEvents.LlmCall, { context, callType: "think" });
2222
+ const decisionSchema = createAgentDecisionWithOutputSchema(
2223
+ this.outputSchema
2224
+ );
2080
2225
  if (this.enableStreaming) {
2081
- return this.thinkStreaming(input, context);
2226
+ return this.thinkStreaming(input, context, decisionSchema, spanName);
2082
2227
  }
2083
2228
  try {
2084
2229
  const instructions = this.buildThinkInstructions();
@@ -2087,7 +2232,7 @@ var Agent = class extends BaseAgent {
2087
2232
  name: spanName,
2088
2233
  instructions,
2089
2234
  input: thinkContext,
2090
- outputSchema: AgentDecisionSchema,
2235
+ outputSchema: decisionSchema,
2091
2236
  model: this.model,
2092
2237
  ...context.parentSpanId && { parentSpanId: context.parentSpanId }
2093
2238
  });
@@ -2098,15 +2243,25 @@ var Agent = class extends BaseAgent {
2098
2243
  totalTokens: response.usage.totalTokens,
2099
2244
  cost: response.usage.cost
2100
2245
  });
2101
- const decision = AgentDecisionSchema.parse(response.jsonPayload);
2246
+ const decision = decisionSchema.parse(
2247
+ response.jsonPayload
2248
+ );
2102
2249
  await this.triggerHook(HookEvents.LlmResponse, {
2103
2250
  context,
2104
2251
  callType: "think",
2105
2252
  response
2106
2253
  });
2254
+ if (response.spanId) {
2255
+ await this.opperClient.updateSpan(response.spanId, void 0, {
2256
+ name: "think"
2257
+ });
2258
+ }
2107
2259
  await this.triggerHook(HookEvents.ThinkEnd, {
2108
2260
  context,
2109
- thought: { reasoning: decision.reasoning }
2261
+ thought: {
2262
+ reasoning: decision.reasoning,
2263
+ userMessage: decision.userMessage
2264
+ }
2110
2265
  });
2111
2266
  this.log("Think result", {
2112
2267
  reasoning: decision.reasoning,
@@ -2122,12 +2277,11 @@ var Agent = class extends BaseAgent {
2122
2277
  );
2123
2278
  }
2124
2279
  }
2125
- async thinkStreaming(input, context) {
2126
- const spanName = "think";
2280
+ async thinkStreaming(input, context, decisionSchema, spanName) {
2127
2281
  const instructions = this.buildThinkInstructions();
2128
2282
  const thinkContext = await this.buildThinkContext(input, context);
2129
2283
  const assembler = createStreamAssembler({
2130
- schema: AgentDecisionSchema
2284
+ schema: decisionSchema
2131
2285
  });
2132
2286
  let streamSpanId;
2133
2287
  await this.triggerHook(HookEvents.StreamStart, {
@@ -2143,7 +2297,7 @@ var Agent = class extends BaseAgent {
2143
2297
  name: spanName,
2144
2298
  instructions,
2145
2299
  input: thinkContext,
2146
- outputSchema: AgentDecisionSchema,
2300
+ outputSchema: decisionSchema,
2147
2301
  model: this.model,
2148
2302
  ...context.parentSpanId && { parentSpanId: context.parentSpanId }
2149
2303
  });
@@ -2187,11 +2341,11 @@ var Agent = class extends BaseAgent {
2187
2341
  const finalize = assembler.finalize();
2188
2342
  let decision;
2189
2343
  if (finalize.type === "structured" && finalize.structured) {
2190
- decision = AgentDecisionSchema.parse(
2344
+ decision = decisionSchema.parse(
2191
2345
  finalize.structured
2192
2346
  );
2193
2347
  } else {
2194
- decision = AgentDecisionSchema.parse({
2348
+ decision = decisionSchema.parse({
2195
2349
  reasoning: finalize.type === "root" ? finalize.rootText ?? "" : ""
2196
2350
  });
2197
2351
  }
@@ -2214,9 +2368,17 @@ var Agent = class extends BaseAgent {
2214
2368
  response: streamResponse,
2215
2369
  parsed: decision
2216
2370
  });
2371
+ if (streamSpanId) {
2372
+ await this.opperClient.updateSpan(streamSpanId, void 0, {
2373
+ name: "think"
2374
+ });
2375
+ }
2217
2376
  await this.triggerHook(HookEvents.ThinkEnd, {
2218
2377
  context,
2219
- thought: { reasoning: decision.reasoning }
2378
+ thought: {
2379
+ reasoning: decision.reasoning,
2380
+ userMessage: decision.userMessage
2381
+ }
2220
2382
  });
2221
2383
  this.log("Think result", {
2222
2384
  reasoning: decision.reasoning,
@@ -2258,12 +2420,22 @@ YOUR TASK:
2258
2420
  1. Analyze the current situation
2259
2421
  2. Decide if the goal is complete or more actions are needed
2260
2422
  3. If more actions needed: specify tools to call
2261
- 4. If goal complete: return empty tool_calls list
2423
+ 4. If goal complete:
2424
+ - Set isComplete=true
2425
+ - Provide the complete answer/output in finalResult
2426
+ - Leave toolCalls empty
2262
2427
 
2263
2428
  IMPORTANT:
2264
- - Return empty toolCalls array when task is COMPLETE
2429
+ - When task is COMPLETE, you MUST set isComplete=true AND provide finalResult
2430
+ - The finalResult should be a complete, well-structured answer based on all work done
2265
2431
  - Only use available tools
2266
- - Provide clear reasoning for each decision`;
2432
+ - Provide clear reasoning for each decision
2433
+ - If an outputSchema was specified, ensure finalResult matches that schema
2434
+
2435
+ USER MESSAGE:
2436
+ - Always provide a brief, user-friendly status in userMessage
2437
+ - This message is shown to users to indicate progress (e.g., "Searching for weather data...", "Calculating results...", "Done!")
2438
+ - Keep it concise and informative`;
2267
2439
  if (this.enableMemory) {
2268
2440
  instructions += `
2269
2441
 
@@ -2347,9 +2519,14 @@ The memory you write persists across all process() calls on this agent.`;
2347
2519
  this.log(`Action: ${toolCall.toolName}`, {
2348
2520
  parameters: toolCall.arguments
2349
2521
  });
2522
+ const startTime = /* @__PURE__ */ new Date();
2523
+ const tool2 = this.tools.get(toolCall.toolName);
2524
+ const isAgentTool = tool2?.metadata?.["isAgent"] === true;
2525
+ const spanType = isAgentTool ? "\u{1F916} agent" : "\u{1F527} tool";
2350
2526
  const toolSpan = await this.opperClient.createSpan({
2351
2527
  name: `tool_${toolCall.toolName}`,
2352
2528
  input: toolCall.arguments,
2529
+ type: spanType,
2353
2530
  ...parentSpanId ? { parentSpanId } : context.parentSpanId ? { parentSpanId: context.parentSpanId } : {}
2354
2531
  });
2355
2532
  try {
@@ -2359,11 +2536,20 @@ The memory you write persists across all process() calls on this agent.`;
2359
2536
  context,
2360
2537
  { spanId: toolSpan.id }
2361
2538
  );
2539
+ const endTime = /* @__PURE__ */ new Date();
2540
+ const durationMs = endTime.getTime() - startTime.getTime();
2362
2541
  if (result.success) {
2363
- await this.opperClient.updateSpan(toolSpan.id, result.output);
2542
+ await this.opperClient.updateSpan(toolSpan.id, result.output, {
2543
+ startTime,
2544
+ endTime,
2545
+ meta: { durationMs }
2546
+ });
2364
2547
  } else {
2365
2548
  await this.opperClient.updateSpan(toolSpan.id, void 0, {
2366
- error: result.error instanceof Error ? result.error.message : String(result.error)
2549
+ error: result.error instanceof Error ? result.error.message : String(result.error),
2550
+ startTime,
2551
+ endTime,
2552
+ meta: { durationMs }
2367
2553
  });
2368
2554
  }
2369
2555
  const summary = {
@@ -2378,12 +2564,18 @@ The memory you write persists across all process() calls on this agent.`;
2378
2564
  this.log(
2379
2565
  `Tool ${toolCall.toolName} ${result.success ? "succeeded" : "failed"}`,
2380
2566
  {
2381
- success: result.success
2567
+ success: result.success,
2568
+ durationMs
2382
2569
  }
2383
2570
  );
2384
2571
  } catch (error) {
2572
+ const endTime = /* @__PURE__ */ new Date();
2573
+ const durationMs = endTime.getTime() - startTime.getTime();
2385
2574
  await this.opperClient.updateSpan(toolSpan.id, void 0, {
2386
- error: error instanceof Error ? error.message : String(error)
2575
+ error: error instanceof Error ? error.message : String(error),
2576
+ startTime,
2577
+ endTime,
2578
+ meta: { durationMs }
2387
2579
  });
2388
2580
  const summary = {
2389
2581
  toolName: toolCall.toolName,
@@ -2392,7 +2584,8 @@ The memory you write persists across all process() calls on this agent.`;
2392
2584
  };
2393
2585
  results.push(ToolExecutionSummarySchema.parse(summary));
2394
2586
  this.logger.warn(`Tool ${toolCall.toolName} threw error`, {
2395
- error: error instanceof Error ? error.message : String(error)
2587
+ error: error instanceof Error ? error.message : String(error),
2588
+ durationMs
2396
2589
  });
2397
2590
  }
2398
2591
  }
@@ -2421,6 +2614,7 @@ The memory you write persists across all process() calls on this agent.`;
2421
2614
  const spanParentId = parentSpanId ?? context.parentSpanId ?? void 0;
2422
2615
  const summaries = [];
2423
2616
  if (hasReads) {
2617
+ const startTime = /* @__PURE__ */ new Date();
2424
2618
  try {
2425
2619
  const keySet = new Set(
2426
2620
  decision.memoryReads.filter(
@@ -2432,10 +2626,17 @@ The memory you write persists across all process() calls on this agent.`;
2432
2626
  const memoryReadSpan = await this.opperClient.createSpan({
2433
2627
  name: "memory_read",
2434
2628
  input: keys,
2629
+ type: "\u{1F9E0} memory",
2435
2630
  ...spanParentId && { parentSpanId: spanParentId }
2436
2631
  });
2437
2632
  const memoryData = await this.memory.read(keys);
2438
- await this.opperClient.updateSpan(memoryReadSpan.id, memoryData);
2633
+ const endTime = /* @__PURE__ */ new Date();
2634
+ const durationMs = endTime.getTime() - startTime.getTime();
2635
+ await this.opperClient.updateSpan(memoryReadSpan.id, memoryData, {
2636
+ startTime,
2637
+ endTime,
2638
+ meta: { durationMs }
2639
+ });
2439
2640
  context.setMetadata("current_memory", memoryData);
2440
2641
  this.log(`Loaded ${Object.keys(memoryData).length} memory entries`, {
2441
2642
  keys
@@ -2474,10 +2675,12 @@ The memory you write persists across all process() calls on this agent.`;
2474
2675
  }
2475
2676
  }
2476
2677
  if (hasWrites) {
2678
+ const startTime = /* @__PURE__ */ new Date();
2477
2679
  try {
2478
2680
  const memoryWriteSpan = await this.opperClient.createSpan({
2479
2681
  name: "memory_write",
2480
2682
  input: updateEntries.map(([key]) => key),
2683
+ type: "\u{1F9E0} memory",
2481
2684
  ...spanParentId && { parentSpanId: spanParentId }
2482
2685
  });
2483
2686
  for (const [key, update] of updateEntries) {
@@ -2494,9 +2697,16 @@ The memory you write persists across all process() calls on this agent.`;
2494
2697
  value: castUpdate.value
2495
2698
  });
2496
2699
  }
2700
+ const endTime = /* @__PURE__ */ new Date();
2701
+ const durationMs = endTime.getTime() - startTime.getTime();
2497
2702
  await this.opperClient.updateSpan(
2498
2703
  memoryWriteSpan.id,
2499
- `Successfully wrote ${updateEntries.length} keys`
2704
+ `Successfully wrote ${updateEntries.length} keys`,
2705
+ {
2706
+ startTime,
2707
+ endTime,
2708
+ meta: { durationMs }
2709
+ }
2500
2710
  );
2501
2711
  this.log(`Wrote ${updateEntries.length} memory entries`);
2502
2712
  summaries.push(
@@ -2569,8 +2779,10 @@ Follow any instructions provided for formatting and style.`;
2569
2779
  );
2570
2780
  }
2571
2781
  try {
2782
+ const sanitizedName = this.name.toLowerCase().replace(/[\s-]/g, "_");
2783
+ const functionName = `generate_final_result_${sanitizedName}`;
2572
2784
  const callOptions = {
2573
- name: "generate_final_result",
2785
+ name: functionName,
2574
2786
  instructions,
2575
2787
  input: finalContext,
2576
2788
  model: this.model
@@ -2617,8 +2829,10 @@ Follow any instructions provided for formatting and style.`;
2617
2829
  callType: "final_result"
2618
2830
  });
2619
2831
  try {
2832
+ const sanitizedName = this.name.toLowerCase().replace(/[\s-]/g, "_");
2833
+ const functionName = `generate_final_result_${sanitizedName}`;
2620
2834
  const streamResponse = await this.opperClient.stream({
2621
- name: "generate_final_result",
2835
+ name: functionName,
2622
2836
  instructions,
2623
2837
  input: finalContext,
2624
2838
  model: this.model,
@@ -3560,6 +3774,7 @@ exports.ThoughtSchema = ThoughtSchema;
3560
3774
  exports.ToolCallSchema = ToolCallSchema;
3561
3775
  exports.ToolExecutionSummarySchema = ToolExecutionSummarySchema;
3562
3776
  exports.ToolRunner = ToolRunner;
3777
+ exports.createAgentDecisionWithOutputSchema = createAgentDecisionWithOutputSchema;
3563
3778
  exports.createFunctionTool = createFunctionTool;
3564
3779
  exports.createHookManager = createHookManager;
3565
3780
  exports.createInMemoryStore = createInMemoryStore;