@@ -50,7 +50,8 @@ export type CallActorGetDatasetResult = {
5050 * @param {unknown } input - The input to pass to the actor.
5151 * @param {string } apifyToken - The Apify token to use for authentication.
5252 * @param {ProgressTracker } progressTracker - Optional progress tracker for real-time updates.
53- * @returns {Promise<CallActorGetDatasetResult> } - A promise that resolves to metadata about the Actor run and dataset.
53+ * @param {AbortSignal } abortSignal - Optional abort signal to cancel the actor run.
54+ * @returns {Promise<CallActorGetDatasetResult | null> } - A promise that resolves to an object containing the actor run and dataset items.
5455 * @throws {Error } - Throws an error if the `APIFY_TOKEN` is not set
5556 */
5657export async function callActorGetDataset (
@@ -59,22 +60,48 @@ export async function callActorGetDataset(
5960 apifyToken : string ,
6061 callOptions : ActorCallOptions | undefined = undefined ,
6162 progressTracker ?: ProgressTracker | null ,
62- ) : Promise < CallActorGetDatasetResult > {
63+ abortSignal ?: AbortSignal ,
64+ ) : Promise < CallActorGetDatasetResult | null > {
65+ const CLIENT_ABORT = Symbol ( 'CLIENT_ABORT' ) ; // Just internal symbol to identify client abort
6366 try {
6467 const client = new ApifyClient ( { token : apifyToken } ) ;
6568 const actorClient = client . actor ( actorName ) ;
6669
67- // Start the Actor run but don't wait for completion
70+ // Start the actor run
6871 const actorRun : ActorRun = await actorClient . start ( input , callOptions ) ;
6972
7073 // Start progress tracking if tracker is provided
7174 if ( progressTracker ) {
7275 progressTracker . startActorRunUpdates ( actorRun . id , apifyToken , actorName ) ;
7376 }
7477
75- // Wait for the actor to complete
76- const completedRun = await client . run ( actorRun . id ) . waitForFinish ( ) ;
78+ // Create abort promise that handles both API abort and race rejection
79+ const abortPromise = async ( ) => new Promise < typeof CLIENT_ABORT > ( ( resolve ) => {
80+ abortSignal ?. addEventListener ( 'abort' , async ( ) => {
81+ // Abort the actor run via API
82+ try {
83+ await client . run ( actorRun . id ) . abort ( { gracefully : false } ) ;
84+ } catch ( e ) {
85+ log . error ( 'Error aborting Actor run' , { error : e , runId : actorRun . id } ) ;
86+ }
87+ // Reject to stop waiting
88+ resolve ( CLIENT_ABORT ) ;
89+ } , { once : true } ) ;
90+ } ) ;
91+
92+ // Wait for completion or cancellation
93+ const potentialAbortedRun = await Promise . race ( [
94+ client . run ( actorRun . id ) . waitForFinish ( ) ,
95+ ...( abortSignal ? [ abortPromise ( ) ] : [ ] ) ,
96+ ] ) ;
7797
98+ if ( potentialAbortedRun === CLIENT_ABORT ) {
99+ log . info ( 'Actor run aborted by client' , { actorName, input } ) ;
100+ return null ;
101+ }
102+ const completedRun = potentialAbortedRun as ActorRun ;
103+
104+ // Process the completed run
78105 const dataset = client . dataset ( completedRun . defaultDatasetId ) ;
79106 const [ datasetItems , defaultBuild ] = await Promise . all ( [
80107 dataset . listItems ( ) ,
@@ -309,7 +336,7 @@ The step parameter enforces this workflow - you cannot call an Actor without fir
309336 inputSchema : zodToJsonSchema ( callActorArgs ) ,
310337 ajvValidate : ajv . compile ( zodToJsonSchema ( callActorArgs ) ) ,
311338 call : async ( toolArgs ) => {
312- const { args, apifyToken, progressTracker } = toolArgs ;
339+ const { args, apifyToken, progressTracker, extra } = toolArgs ;
313340 const { actor : actorName , step, input, callOptions } = callActorArgs . parse ( args ) ;
314341
315342 try {
@@ -364,8 +391,15 @@ The step parameter enforces this workflow - you cannot call an Actor without fir
364391 apifyToken ,
365392 callOptions ,
366393 progressTracker ,
394+ extra . signal ,
367395 ) ;
368396
397+ if ( ! callResult ) {
398+ // Receivers of cancellation notifications SHOULD NOT send a response for the cancelled request
399+ // https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/cancellation#behavior-requirements
400+ return { } ;
401+ }
402+
369403 const content = buildActorResponseContent ( actorName , callResult ) ;
370404
371405 return { content } ;
0 commit comments