@@ -17,6 +17,8 @@ import { OrchestrationStatus, toProtobuf, fromProtobuf } from "../orchestration/
1717import { TimeoutError } from "../exception/timeout-error" ;
1818import { PurgeResult } from "../orchestration/orchestration-purge-result" ;
1919import { PurgeInstanceCriteria } from "../orchestration/orchestration-purge-criteria" ;
20+ import { PurgeInstanceOptions } from "../orchestration/orchestration-purge-options" ;
21+ import { TerminateInstanceOptions , isTerminateInstanceOptions } from "../orchestration/orchestration-terminate-options" ;
2022import { callWithMetadata , MetadataGenerator } from "../utils/grpc-helper.util" ;
2123import { OrchestrationQuery , ListInstanceIdsOptions , DEFAULT_PAGE_SIZE } from "../orchestration/orchestration-query" ;
2224import { Page , AsyncPageable , createAsyncPageable } from "../orchestration/page" ;
@@ -47,12 +49,19 @@ export interface TaskHubGrpcClientOptions {
4749 metadataGenerator ?: MetadataGenerator ;
4850 /** Optional logger instance. Defaults to ConsoleLogger. */
4951 logger ?: Logger ;
52+ /**
53+ * The default version to use when starting new orchestrations without an explicit version.
54+ * If specified, this will be used as the version for orchestrations that don't provide
55+ * their own version in StartOrchestrationOptions.
56+ */
57+ defaultVersion ?: string ;
5058}
5159
5260export class TaskHubGrpcClient {
5361 private _stub : stubs . TaskHubSidecarServiceClient ;
5462 private _metadataGenerator ?: MetadataGenerator ;
5563 private _logger : Logger ;
64+ private _defaultVersion ?: string ;
5665
5766 /**
5867 * Creates a new TaskHubGrpcClient instance.
@@ -95,6 +104,7 @@ export class TaskHubGrpcClient {
95104 let resolvedCredentials : grpc . ChannelCredentials | undefined ;
96105 let resolvedMetadataGenerator : MetadataGenerator | undefined ;
97106 let resolvedLogger : Logger | undefined ;
107+ let resolvedDefaultVersion : string | undefined ;
98108
99109 if ( typeof hostAddressOrOptions === "object" && hostAddressOrOptions !== null ) {
100110 // Options object constructor
@@ -104,6 +114,7 @@ export class TaskHubGrpcClient {
104114 resolvedCredentials = hostAddressOrOptions . credentials ;
105115 resolvedMetadataGenerator = hostAddressOrOptions . metadataGenerator ;
106116 resolvedLogger = hostAddressOrOptions . logger ;
117+ resolvedDefaultVersion = hostAddressOrOptions . defaultVersion ;
107118 } else {
108119 // Deprecated positional parameters constructor
109120 resolvedHostAddress = hostAddressOrOptions ;
@@ -117,6 +128,7 @@ export class TaskHubGrpcClient {
117128 this . _stub = new GrpcClient ( resolvedHostAddress , resolvedOptions , resolvedUseTLS , resolvedCredentials ) . stub ;
118129 this . _metadataGenerator = resolvedMetadataGenerator ;
119130 this . _logger = resolvedLogger ?? new ConsoleLogger ( ) ;
131+ this . _defaultVersion = resolvedDefaultVersion ;
120132 }
121133
122134 async stop ( ) : Promise < void > {
@@ -177,6 +189,13 @@ export class TaskHubGrpcClient {
177189 typeof instanceIdOrOptions === "string" || instanceIdOrOptions === undefined
178190 ? undefined
179191 : instanceIdOrOptions . tags ;
192+ const version =
193+ typeof instanceIdOrOptions === "string" || instanceIdOrOptions === undefined
194+ ? undefined
195+ : instanceIdOrOptions . version ;
196+
197+ // Use provided version, or fall back to client's default version
198+ const effectiveVersion = version ?? this . _defaultVersion ;
180199
181200 const req = new pb . CreateInstanceRequest ( ) ;
182201 req . setName ( name ) ;
@@ -191,9 +210,15 @@ export class TaskHubGrpcClient {
191210 req . setInput ( i ) ;
192211 req . setScheduledstarttimestamp ( ts ) ;
193212
213+ if ( effectiveVersion ) {
214+ const v = new StringValue ( ) ;
215+ v . setValue ( effectiveVersion ) ;
216+ req . setVersion ( v ) ;
217+ }
218+
194219 populateTagsMap ( req . getTagsMap ( ) , tags ) ;
195220
196- this . _logger . info ( `Starting new ${ name } instance with ID = ${ req . getInstanceid ( ) } ` ) ;
221+ this . _logger . info ( `Starting new ${ name } instance with ID = ${ req . getInstanceid ( ) } ${ effectiveVersion ? ` (version: ${ effectiveVersion } )` : "" } ` ) ;
197222
198223 const res = await callWithMetadata < pb . CreateInstanceRequest , pb . CreateInstanceResponse > (
199224 this . _stub . startInstance . bind ( this . _stub ) ,
@@ -364,18 +389,49 @@ export class TaskHubGrpcClient {
364389 * Terminates the orchestrator associated with the provided instance id.
365390 *
366391 * @param {string } instanceId - orchestrator instance id to terminate.
367- * @param {any } output - The optional output to set for the terminated orchestrator instance.
392+ * @param {any | TerminateInstanceOptions } outputOrOptions - The optional output to set for the terminated orchestrator instance,
393+ * or a TerminateInstanceOptions object created with `terminateOptions()` that can include both
394+ * output and recursive termination settings.
395+ *
396+ * @example
397+ * ```typescript
398+ * // Simple termination with output
399+ * await client.terminateOrchestration(instanceId, { reason: "cancelled" });
400+ *
401+ * // Recursive termination with options (use terminateOptions helper)
402+ * import { terminateOptions } from "@microsoft/durabletask-js";
403+ * await client.terminateOrchestration(instanceId, terminateOptions({
404+ * output: { reason: "cancelled" },
405+ * recursive: true
406+ * }));
407+ * ```
368408 */
369- async terminateOrchestration ( instanceId : string , output : any = null ) : Promise < void > {
409+ async terminateOrchestration (
410+ instanceId : string ,
411+ outputOrOptions : any | TerminateInstanceOptions = null ,
412+ ) : Promise < void > {
370413 const req = new pb . TerminateRequest ( ) ;
371414 req . setInstanceid ( instanceId ) ;
372415
416+ let output : any = null ;
417+ let recursive = false ;
418+
419+ // Use type guard to safely detect TerminateInstanceOptions
420+ // This avoids false positives when user output happens to have 'recursive' or 'output' properties
421+ if ( isTerminateInstanceOptions ( outputOrOptions ) ) {
422+ output = outputOrOptions . output ?? null ;
423+ recursive = outputOrOptions . recursive ?? false ;
424+ } else {
425+ output = outputOrOptions ;
426+ }
427+
373428 const i = new StringValue ( ) ;
374429 i . setValue ( JSON . stringify ( output ) ) ;
375430
376431 req . setOutput ( i ) ;
432+ req . setRecursive ( recursive ) ;
377433
378- this . _logger . info ( `Terminating '${ instanceId } '` ) ;
434+ this . _logger . info ( `Terminating '${ instanceId } '${ recursive ? ' (recursive)' : '' } ` ) ;
379435
380436 await callWithMetadata < pb . TerminateRequest , pb . TerminateResponse > (
381437 this . _stub . terminateInstance . bind ( this . _stub ) ,
@@ -537,16 +593,21 @@ export class TaskHubGrpcClient {
537593 *
538594 * @param value - The unique ID of the orchestration instance to purge or orchestration instance filter criteria used
539595 * to determine which instances to purge.
596+ * @param options - Optional options to control the purge behavior, such as recursive purging of sub-orchestrations.
540597 * @returns A Promise that resolves to a {@link PurgeResult} or `undefined` if the purge operation was not successful.
541598 */
542- async purgeOrchestration ( value : string | PurgeInstanceCriteria ) : Promise < PurgeResult | undefined > {
599+ async purgeOrchestration (
600+ value : string | PurgeInstanceCriteria ,
601+ options ?: PurgeInstanceOptions ,
602+ ) : Promise < PurgeResult | undefined > {
543603 let res ;
544- if ( typeof value === ` string` ) {
604+ if ( typeof value === " string" ) {
545605 const instanceId = value ;
546606 const req = new pb . PurgeInstancesRequest ( ) ;
547607 req . setInstanceid ( instanceId ) ;
608+ req . setRecursive ( options ?. recursive ?? false ) ;
548609
549- this . _logger . info ( `Purging Instance '${ instanceId } '` ) ;
610+ this . _logger . info ( `Purging Instance '${ instanceId } '${ options ?. recursive ? ' (recursive)' : '' } ` ) ;
550611
551612 res = await callWithMetadata < pb . PurgeInstancesRequest , pb . PurgeInstancesResponse > (
552613 this . _stub . purgeInstances . bind ( this . _stub ) ,
@@ -574,9 +635,10 @@ export class TaskHubGrpcClient {
574635 filter . addRuntimestatus ( toProtobuf ( status ) ) ;
575636 }
576637 req . setPurgeinstancefilter ( filter ) ;
638+ req . setRecursive ( options ?. recursive ?? false ) ;
577639 const timeout = purgeInstanceCriteria . getTimeout ( ) ;
578640
579- this . _logger . info ( " Purging Instance using purging criteria" ) ;
641+ this . _logger . info ( ` Purging Instances using purging criteria${ options ?. recursive ? " (recursive)" : "" } ` ) ;
580642
581643 const callPromise = callWithMetadata < pb . PurgeInstancesRequest , pb . PurgeInstancesResponse > (
582644 this . _stub . purgeInstances . bind ( this . _stub ) ,
0 commit comments