Merge pull request #1714 from QwenLM/feat/sdk-support-resume

feat(query): add support for resuming sessions with session ID
This commit is contained in:
tanzhenxin 2026-02-05 16:26:53 +08:00 committed by GitHub
commit 90b529b44c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 54 additions and 1 deletions

View file

@ -91,7 +91,7 @@ export class Query implements AsyncIterable<SDKMessage> {
) { ) {
this.transport = transport; this.transport = transport;
this.options = options; this.options = options;
this.sessionId = randomUUID(); this.sessionId = options.resume ?? randomUUID();
this.inputStream = new Stream<SDKMessage>(); this.inputStream = new Stream<SDKMessage>();
this.abortController = options.abortController ?? new AbortController(); this.abortController = options.abortController ?? new AbortController();
this.isSingleTurn = singleTurn; this.isSingleTurn = singleTurn;

View file

@ -57,6 +57,7 @@ export function query({
allowedTools: options.allowedTools, allowedTools: options.allowedTools,
authType: options.authType, authType: options.authType,
includePartialMessages: options.includePartialMessages, includePartialMessages: options.includePartialMessages,
resume: options.resume,
}); });
const queryOptions: QueryOptions = { const queryOptions: QueryOptions = {

View file

@ -178,6 +178,10 @@ export class ProcessTransport implements Transport {
args.push('--include-partial-messages'); args.push('--include-partial-messages');
} }
if (this.options.resume) {
args.push('--resume', this.options.resume);
}
return args; return args;
} }

View file

@ -164,6 +164,7 @@ export const QueryOptionsSchema = z
) )
.optional(), .optional(),
includePartialMessages: z.boolean().optional(), includePartialMessages: z.boolean().optional(),
resume: z.string().optional(),
timeout: TimeoutConfigSchema.optional(), timeout: TimeoutConfigSchema.optional(),
}) })
.strict(); .strict();

View file

@ -25,6 +25,7 @@ export type TransportOptions = {
allowedTools?: string[]; allowedTools?: string[];
authType?: string; authType?: string;
includePartialMessages?: boolean; includePartialMessages?: boolean;
resume?: string;
}; };
type ToolInput = Record<string, unknown>; type ToolInput = Record<string, unknown>;
@ -402,6 +403,13 @@ export interface QueryOptions {
*/ */
includePartialMessages?: boolean; 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. * Timeout configuration for various SDK operations.
* All values are in milliseconds. * All values are in milliseconds.

View file

@ -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', () => { it('should throw if aborted before initialization', () => {
mockPrepareSpawnInfo.mockReturnValue({ mockPrepareSpawnInfo.mockReturnValue({
command: 'qwen', command: 'qwen',

View file

@ -329,6 +329,19 @@ describe('Query', () => {
await transport2.close(); 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 () => { it('should handle initialization errors', async () => {
const query = new Query(transport, { const query = new Query(transport, {
cwd: '/test', cwd: '/test',