@voltagent/core 0.1.50 → 0.1.51

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.d.ts CHANGED
@@ -1227,7 +1227,7 @@ type PublicGenerateOptions = Omit<CommonGenerateOptions, "historyEntryId" | "ope
1227
1227
  /**
1228
1228
  * Agent status information
1229
1229
  */
1230
- type AgentStatus = "idle" | "working" | "tool_calling" | "error" | "completed";
1230
+ type AgentStatus = "idle" | "working" | "error" | "completed" | "cancelled";
1231
1231
  /**
1232
1232
  * Tool call definition
1233
1233
  */
@@ -1322,6 +1322,10 @@ type AgentHandoffOptions = {
1322
1322
  * Parent's operation context to merge SubAgent steps into
1323
1323
  */
1324
1324
  parentOperationContext?: OperationContext;
1325
+ /**
1326
+ * AbortSignal to cancel the handoff operation
1327
+ */
1328
+ signal?: AbortSignal;
1325
1329
  };
1326
1330
  /**
1327
1331
  * Result of a handoff to another agent
@@ -1380,6 +1384,8 @@ type OperationContext = {
1380
1384
  toolSpans?: Map<string, Span>;
1381
1385
  /** Conversation steps for building full message history including tool calls/results */
1382
1386
  conversationSteps?: StepWithContent[];
1387
+ /** AbortSignal for cancelling the operation */
1388
+ signal?: AbortSignal;
1383
1389
  };
1384
1390
  /**
1385
1391
  * Tool execution context passed to tool.execute method
@@ -3434,6 +3440,10 @@ declare class Agent<TProvider extends {
3434
3440
  */
3435
3441
  private _endOtelToolSpan;
3436
3442
  private publishTimelineEvent;
3443
+ /**
3444
+ * Sets up abort signal listener for cancellation handling
3445
+ */
3446
+ private setupAbortSignalListener;
3437
3447
  /**
3438
3448
  * Create an enhanced fullStream with real-time SubAgent event injection
3439
3449
  */
package/dist/index.js CHANGED
@@ -1598,6 +1598,10 @@ app.openapi(streamRoute, async (c) => {
1598
1598
  temperature: 0.7
1599
1599
  }
1600
1600
  } = c.req.valid("json");
1601
+ const abortController = new AbortController();
1602
+ c.req.raw.signal?.addEventListener("abort", () => {
1603
+ abortController.abort();
1604
+ });
1601
1605
  const stream = new ReadableStream({
1602
1606
  async start(controller) {
1603
1607
  try {
@@ -1632,7 +1636,9 @@ app.openapi(streamRoute, async (c) => {
1632
1636
  temperature: options.temperature
1633
1637
  // Note: No onError callback needed - tool errors are handled via fullStream
1634
1638
  // Stream errors are handled by try/catch blocks around fullStream iteration
1635
- }
1639
+ },
1640
+ // Pass the abort signal to the agent
1641
+ signal: abortController.signal
1636
1642
  };
1637
1643
  const response = await agent.streamText(input, processedStreamOptions);
1638
1644
  try {
@@ -1908,6 +1914,11 @@ app.openapi(streamObjectRoute, async (c) => {
1908
1914
  options = {}
1909
1915
  } = c.req.valid("json");
1910
1916
  const schemaInZodObject = (0, import_zod_from_json_schema.convertJsonSchemaToZod)(schema);
1917
+ const abortController = new AbortController();
1918
+ c.req.raw.signal?.addEventListener("abort", () => {
1919
+ console.log("\u{1F6D1} API: Client aborted object stream request, stopping agent stream...");
1920
+ abortController.abort();
1921
+ });
1911
1922
  const sseStream = new ReadableStream({
1912
1923
  async start(controller) {
1913
1924
  try {
@@ -1954,7 +1965,9 @@ app.openapi(streamObjectRoute, async (c) => {
1954
1965
  safeEnqueue(errorMessage);
1955
1966
  safeClose();
1956
1967
  }
1957
- }
1968
+ },
1969
+ // Pass the abort signal to the agent
1970
+ signal: abortController.signal
1958
1971
  };
1959
1972
  const agentStream = await agent.streamObject(
1960
1973
  input,
@@ -7702,7 +7715,9 @@ Context: ${JSON.stringify(context, null, 2)}`;
7702
7715
  // @ts-expect-error - bad types
7703
7716
  parentAgentId: sourceAgent?.id || parentAgentId,
7704
7717
  parentHistoryEntryId,
7705
- parentOperationContext
7718
+ parentOperationContext,
7719
+ // Pass the abort signal from parent's operation context to subagent
7720
+ signal: parentOperationContext?.signal
7706
7721
  });
7707
7722
  let finalText = "";
7708
7723
  if (streamResponse.fullStream) {
@@ -8469,7 +8484,9 @@ ${retrieverContext}`;
8469
8484
  parentHistoryEntryId: options.parentHistoryEntryId,
8470
8485
  otelSpan,
8471
8486
  // Use parent's conversationSteps if available (for SubAgents), otherwise create new array
8472
- conversationSteps: options.parentOperationContext?.conversationSteps || []
8487
+ conversationSteps: options.parentOperationContext?.conversationSteps || [],
8488
+ // Inherit signal from parent context or use provided signal
8489
+ signal: options.parentOperationContext?.signal || options.signal
8473
8490
  };
8474
8491
  return opContext;
8475
8492
  }
@@ -8603,6 +8620,52 @@ ${retrieverContext}`;
8603
8620
  parentHistoryEntryId: operationContext.parentHistoryEntryId
8604
8621
  });
8605
8622
  }
8623
+ /**
8624
+ * Sets up abort signal listener for cancellation handling
8625
+ */
8626
+ setupAbortSignalListener(signal, operationContext, finalConversationId, agentStartEvent) {
8627
+ if (!signal)
8628
+ return;
8629
+ signal.addEventListener("abort", async () => {
8630
+ this.updateHistoryEntry(operationContext, {
8631
+ status: "cancelled",
8632
+ endTime: /* @__PURE__ */ new Date()
8633
+ });
8634
+ operationContext.isActive = false;
8635
+ const cancellationError = new Error("Operation cancelled by user");
8636
+ cancellationError.name = "AbortError";
8637
+ const agentCancelledEvent = {
8638
+ id: crypto.randomUUID(),
8639
+ name: "agent:cancel",
8640
+ type: "agent",
8641
+ startTime: agentStartEvent.startTime,
8642
+ endTime: (/* @__PURE__ */ new Date()).toISOString(),
8643
+ level: "INFO",
8644
+ input: null,
8645
+ statusMessage: {
8646
+ message: cancellationError.message,
8647
+ code: "USER_CANCELLED",
8648
+ stage: "cancelled"
8649
+ },
8650
+ status: "cancelled",
8651
+ metadata: {
8652
+ displayName: this.name,
8653
+ id: this.id,
8654
+ userContext: Object.fromEntries(operationContext.userContext.entries())
8655
+ },
8656
+ traceId: operationContext.historyEntry.id,
8657
+ parentEventId: agentStartEvent.id
8658
+ };
8659
+ this.publishTimelineEvent(operationContext, agentCancelledEvent);
8660
+ await this.hooks.onEnd?.({
8661
+ agent: this,
8662
+ output: void 0,
8663
+ error: cancellationError,
8664
+ conversationId: finalConversationId || "",
8665
+ context: operationContext
8666
+ });
8667
+ });
8668
+ }
8606
8669
  /**
8607
8670
  * Create an enhanced fullStream with real-time SubAgent event injection
8608
8671
  */
@@ -8659,7 +8722,8 @@ ${retrieverContext}`;
8659
8722
  parentHistoryEntryId,
8660
8723
  parentOperationContext,
8661
8724
  contextLimit = 10,
8662
- userContext
8725
+ userContext,
8726
+ signal
8663
8727
  } = internalOptions;
8664
8728
  const operationContext = await this.initializeHistory(input, "working", {
8665
8729
  parentAgentId,
@@ -8668,7 +8732,8 @@ ${retrieverContext}`;
8668
8732
  userContext,
8669
8733
  userId,
8670
8734
  conversationId: initialConversationId,
8671
- parentOperationContext
8735
+ parentOperationContext,
8736
+ signal
8672
8737
  });
8673
8738
  const { messages: contextMessages, conversationId: finalConversationId } = await this.memoryManager.prepareConversationContext(
8674
8739
  operationContext,
@@ -8727,6 +8792,10 @@ ${retrieverContext}`;
8727
8792
  operationContext.userContext.set("agent_start_time", agentStartTime);
8728
8793
  operationContext.userContext.set("agent_start_event_id", agentStartEvent.id);
8729
8794
  this.publishTimelineEvent(operationContext, agentStartEvent);
8795
+ this.setupAbortSignalListener(signal, operationContext, finalConversationId, {
8796
+ id: agentStartEvent.id,
8797
+ startTime: agentStartTime
8798
+ });
8730
8799
  const onStepFinish = this.memoryManager.createStepFinishHandler(
8731
8800
  operationContext,
8732
8801
  userId,
@@ -8840,7 +8909,7 @@ ${retrieverContext}`;
8840
8909
  id: crypto.randomUUID(),
8841
8910
  name: "tool:success",
8842
8911
  type: "tool",
8843
- startTime: (/* @__PURE__ */ new Date()).toISOString(),
8912
+ startTime: toolStartInfo.startTime,
8844
8913
  // Use the original start time
8845
8914
  endTime: (/* @__PURE__ */ new Date()).toISOString(),
8846
8915
  // Current time as end time
@@ -9015,7 +9084,8 @@ ${retrieverContext}`;
9015
9084
  parentHistoryEntryId,
9016
9085
  parentOperationContext,
9017
9086
  contextLimit = 10,
9018
- userContext
9087
+ userContext,
9088
+ signal
9019
9089
  } = internalOptions;
9020
9090
  const operationContext = await this.initializeHistory(input, "working", {
9021
9091
  parentAgentId,
@@ -9024,7 +9094,8 @@ ${retrieverContext}`;
9024
9094
  userContext,
9025
9095
  userId,
9026
9096
  conversationId: initialConversationId,
9027
- parentOperationContext
9097
+ parentOperationContext,
9098
+ signal
9028
9099
  });
9029
9100
  const { messages: contextMessages, conversationId: finalConversationId } = await this.memoryManager.prepareConversationContext(
9030
9101
  operationContext,
@@ -9081,6 +9152,10 @@ ${retrieverContext}`;
9081
9152
  operationContext.userContext.set("agent_start_time", agentStartTime);
9082
9153
  operationContext.userContext.set("agent_start_event_id", agentStartEvent.id);
9083
9154
  this.publishTimelineEvent(operationContext, agentStartEvent);
9155
+ this.setupAbortSignalListener(signal, operationContext, finalConversationId, {
9156
+ id: agentStartEvent.id,
9157
+ startTime: agentStartTime
9158
+ });
9084
9159
  const onStepFinish = this.memoryManager.createStepFinishHandler(
9085
9160
  operationContext,
9086
9161
  userId,
@@ -9201,7 +9276,7 @@ ${retrieverContext}`;
9201
9276
  id: crypto.randomUUID(),
9202
9277
  name: "tool:error",
9203
9278
  type: "tool",
9204
- startTime: (/* @__PURE__ */ new Date()).toISOString(),
9279
+ startTime: toolStartInfo.startTime,
9205
9280
  // Use the original start time
9206
9281
  endTime: (/* @__PURE__ */ new Date()).toISOString(),
9207
9282
  // Current time as end time
@@ -9225,7 +9300,7 @@ ${retrieverContext}`;
9225
9300
  id: crypto.randomUUID(),
9226
9301
  name: "tool:success",
9227
9302
  type: "tool",
9228
- startTime: (/* @__PURE__ */ new Date()).toISOString(),
9303
+ startTime: toolStartInfo.startTime,
9229
9304
  // Use the original start time
9230
9305
  endTime: (/* @__PURE__ */ new Date()).toISOString(),
9231
9306
  // Current time as end time
@@ -9356,7 +9431,7 @@ ${retrieverContext}`;
9356
9431
  id: crypto.randomUUID(),
9357
9432
  name: "tool:error",
9358
9433
  type: "tool",
9359
- startTime: (/* @__PURE__ */ new Date()).toISOString(),
9434
+ startTime: toolStartInfo.startTime,
9360
9435
  endTime: (/* @__PURE__ */ new Date()).toISOString(),
9361
9436
  status: "error",
9362
9437
  level: "ERROR",
@@ -9474,7 +9549,8 @@ ${retrieverContext}`;
9474
9549
  parentHistoryEntryId,
9475
9550
  parentOperationContext,
9476
9551
  contextLimit = 10,
9477
- userContext
9552
+ userContext,
9553
+ signal
9478
9554
  } = internalOptions;
9479
9555
  const operationContext = await this.initializeHistory(input, "working", {
9480
9556
  parentAgentId,
@@ -9483,7 +9559,8 @@ ${retrieverContext}`;
9483
9559
  userContext,
9484
9560
  userId,
9485
9561
  conversationId: initialConversationId,
9486
- parentOperationContext
9562
+ parentOperationContext,
9563
+ signal
9487
9564
  });
9488
9565
  const { messages: contextMessages, conversationId: finalConversationId } = await this.memoryManager.prepareConversationContext(
9489
9566
  operationContext,
@@ -9542,6 +9619,10 @@ ${retrieverContext}`;
9542
9619
  operationContext.userContext.set("agent_start_time", agentStartTime);
9543
9620
  operationContext.userContext.set("agent_start_event_id", agentStartEvent.id);
9544
9621
  this.publishTimelineEvent(operationContext, agentStartEvent);
9622
+ this.setupAbortSignalListener(signal, operationContext, finalConversationId, {
9623
+ id: agentStartEvent.id,
9624
+ startTime: agentStartTime
9625
+ });
9545
9626
  const onStepFinish = this.memoryManager.createStepFinishHandler(
9546
9627
  operationContext,
9547
9628
  userId,
@@ -9716,7 +9797,8 @@ ${retrieverContext}`;
9716
9797
  parentOperationContext,
9717
9798
  provider,
9718
9799
  contextLimit = 10,
9719
- userContext
9800
+ userContext,
9801
+ signal
9720
9802
  } = internalOptions;
9721
9803
  const operationContext = await this.initializeHistory(input, "working", {
9722
9804
  parentAgentId,
@@ -9725,7 +9807,8 @@ ${retrieverContext}`;
9725
9807
  userContext,
9726
9808
  userId,
9727
9809
  conversationId: initialConversationId,
9728
- parentOperationContext
9810
+ parentOperationContext,
9811
+ signal
9729
9812
  });
9730
9813
  const { messages: contextMessages, conversationId: finalConversationId } = await this.memoryManager.prepareConversationContext(
9731
9814
  operationContext,
@@ -9782,6 +9865,10 @@ ${retrieverContext}`;
9782
9865
  operationContext.userContext.set("agent_start_time", agentStartTime);
9783
9866
  operationContext.userContext.set("agent_start_event_id", agentStartEvent.id);
9784
9867
  this.publishTimelineEvent(operationContext, agentStartEvent);
9868
+ this.setupAbortSignalListener(signal, operationContext, finalConversationId, {
9869
+ id: agentStartEvent.id,
9870
+ startTime: agentStartTime
9871
+ });
9785
9872
  const onStepFinish = this.memoryManager.createStepFinishHandler(
9786
9873
  operationContext,
9787
9874
  userId,