diff --git a/packages/sdk-typescript/src/query/Query.ts b/packages/sdk-typescript/src/query/Query.ts index 540291769..7d1a936a4 100644 --- a/packages/sdk-typescript/src/query/Query.ts +++ b/packages/sdk-typescript/src/query/Query.ts @@ -91,7 +91,7 @@ export class Query implements AsyncIterable { ) { this.transport = transport; this.options = options; - this.sessionId = randomUUID(); + this.sessionId = options.resume ?? randomUUID(); this.inputStream = new Stream(); this.abortController = options.abortController ?? new AbortController(); this.isSingleTurn = singleTurn; diff --git a/packages/sdk-typescript/src/query/createQuery.ts b/packages/sdk-typescript/src/query/createQuery.ts index 3d0a76096..2a9842d0c 100644 --- a/packages/sdk-typescript/src/query/createQuery.ts +++ b/packages/sdk-typescript/src/query/createQuery.ts @@ -57,6 +57,7 @@ export function query({ allowedTools: options.allowedTools, authType: options.authType, includePartialMessages: options.includePartialMessages, + resume: options.resume, }); const queryOptions: QueryOptions = { diff --git a/packages/sdk-typescript/src/transport/ProcessTransport.ts b/packages/sdk-typescript/src/transport/ProcessTransport.ts index ff4518833..44c308e38 100644 --- a/packages/sdk-typescript/src/transport/ProcessTransport.ts +++ b/packages/sdk-typescript/src/transport/ProcessTransport.ts @@ -178,6 +178,10 @@ export class ProcessTransport implements Transport { args.push('--include-partial-messages'); } + if (this.options.resume) { + args.push('--resume', this.options.resume); + } + return args; } diff --git a/packages/sdk-typescript/src/types/queryOptionsSchema.ts b/packages/sdk-typescript/src/types/queryOptionsSchema.ts index a4794b3f8..948f1a1a0 100644 --- a/packages/sdk-typescript/src/types/queryOptionsSchema.ts +++ b/packages/sdk-typescript/src/types/queryOptionsSchema.ts @@ -164,6 +164,7 @@ export const QueryOptionsSchema = z ) .optional(), includePartialMessages: z.boolean().optional(), + resume: z.string().optional(), timeout: TimeoutConfigSchema.optional(), }) .strict(); diff --git a/packages/sdk-typescript/src/types/types.ts b/packages/sdk-typescript/src/types/types.ts index 3fbeca652..00f17d5d4 100644 --- a/packages/sdk-typescript/src/types/types.ts +++ b/packages/sdk-typescript/src/types/types.ts @@ -25,6 +25,7 @@ export type TransportOptions = { allowedTools?: string[]; authType?: string; includePartialMessages?: boolean; + resume?: string; }; type ToolInput = Record; @@ -402,6 +403,13 @@ export interface QueryOptions { */ includePartialMessages?: boolean; + /** + * Resume a previous session by providing its session ID. + * This is equivalent to using the `--resume` flag in the Qwen CLI. + * @example '123e4567-e89b-12d3-a456-426614174000' + */ + resume?: string; + /** * Timeout configuration for various SDK operations. * All values are in milliseconds. diff --git a/packages/sdk-typescript/test/unit/ProcessTransport.test.ts b/packages/sdk-typescript/test/unit/ProcessTransport.test.ts index 87bf6bc2a..0ee98c5b4 100644 --- a/packages/sdk-typescript/test/unit/ProcessTransport.test.ts +++ b/packages/sdk-typescript/test/unit/ProcessTransport.test.ts @@ -191,6 +191,32 @@ describe('ProcessTransport', () => { ); }); + it('should include --resume argument when provided', () => { + mockPrepareSpawnInfo.mockReturnValue({ + command: 'qwen', + args: [], + type: 'native', + originalInput: 'qwen', + }); + mockSpawn.mockReturnValue(mockChildProcess); + + const options: TransportOptions = { + pathToQwenExecutable: 'qwen', + resume: '123e4567-e89b-12d3-a456-426614174000', + }; + + new ProcessTransport(options); + + expect(mockSpawn).toHaveBeenCalledWith( + 'qwen', + expect.arrayContaining([ + '--resume', + '123e4567-e89b-12d3-a456-426614174000', + ]), + expect.any(Object), + ); + }); + it('should throw if aborted before initialization', () => { mockPrepareSpawnInfo.mockReturnValue({ command: 'qwen', diff --git a/packages/sdk-typescript/test/unit/Query.test.ts b/packages/sdk-typescript/test/unit/Query.test.ts index fd38555fb..1de1c37e4 100644 --- a/packages/sdk-typescript/test/unit/Query.test.ts +++ b/packages/sdk-typescript/test/unit/Query.test.ts @@ -329,6 +329,19 @@ describe('Query', () => { await transport2.close(); }); + it('should use resume parameter as session ID if provided', async () => { + const resumeId = '123e4567-e89b-12d3-a456-426614174000'; + const query = new Query(transport, { + cwd: '/test', + resume: resumeId, + }); + + expect(query.getSessionId()).toBe(resumeId); + + await respondToInitialize(transport, query); + await query.close(); + }); + it('should handle initialization errors', async () => { const query = new Query(transport, { cwd: '/test',