feat: add support for includePartialMessages option in query and transport layers

This commit is contained in:
mingholy.lmh
2025-11-25 18:05:58 +08:00
parent ac6aecb622
commit 49dc84ac0e
6 changed files with 106 additions and 0 deletions

View File

@@ -43,6 +43,7 @@ export function query({
coreTools: options.coreTools, coreTools: options.coreTools,
excludeTools: options.excludeTools, excludeTools: options.excludeTools,
authType: options.authType, authType: options.authType,
includePartialMessages: options.includePartialMessages,
}); });
const queryOptions: QueryOptions = { const queryOptions: QueryOptions = {

View File

@@ -155,6 +155,10 @@ export class ProcessTransport implements Transport {
args.push('--auth-type', this.options.authType); args.push('--auth-type', this.options.authType);
} }
if (this.options.includePartialMessages) {
args.push('--include-partial-messages');
}
return args; return args;
} }

View File

@@ -76,6 +76,7 @@ export const QueryOptionsSchema = z
), ),
) )
.optional(), .optional(),
includePartialMessages: z.boolean().optional(),
}) })
.strict(); .strict();

View File

@@ -30,6 +30,7 @@ export type TransportOptions = {
coreTools?: string[]; coreTools?: string[];
excludeTools?: string[]; excludeTools?: string[];
authType?: string; authType?: string;
includePartialMessages?: boolean;
}; };
type ToolInput = Record<string, unknown>; type ToolInput = Record<string, unknown>;

View File

@@ -476,4 +476,67 @@ describe('Multi-Turn Conversations (E2E)', () => {
} }
}); });
}); });
describe('Partial Messages in Multi-Turn', () => {
it('should receive partial messages when includePartialMessages is enabled', async () => {
async function* createMultiTurnConversation(): AsyncIterable<CLIUserMessage> {
const sessionId = crypto.randomUUID();
yield {
type: 'user',
session_id: sessionId,
message: {
role: 'user',
content: 'What is 1 + 1?',
},
parent_tool_use_id: null,
} as CLIUserMessage;
await new Promise((resolve) => setTimeout(resolve, 100));
yield {
type: 'user',
session_id: sessionId,
message: {
role: 'user',
content: 'What is 2 + 2?',
},
parent_tool_use_id: null,
} as CLIUserMessage;
}
const q = query({
prompt: createMultiTurnConversation(),
options: {
...SHARED_TEST_OPTIONS,
includePartialMessages: true,
debug: false,
},
});
const messages: CLIMessage[] = [];
let partialMessageCount = 0;
let assistantMessageCount = 0;
try {
for await (const message of q) {
messages.push(message);
if (isCLIPartialAssistantMessage(message)) {
partialMessageCount++;
}
if (isCLIAssistantMessage(message)) {
assistantMessageCount++;
}
}
expect(messages.length).toBeGreaterThan(0);
expect(partialMessageCount).toBeGreaterThan(0);
expect(assistantMessageCount).toBeGreaterThanOrEqual(2);
} finally {
await q.close();
}
});
});
}); });

View File

@@ -9,6 +9,7 @@ import {
isCLIAssistantMessage, isCLIAssistantMessage,
isCLISystemMessage, isCLISystemMessage,
isCLIResultMessage, isCLIResultMessage,
isCLIPartialAssistantMessage,
type TextBlock, type TextBlock,
type ContentBlock, type ContentBlock,
type CLIMessage, type CLIMessage,
@@ -327,6 +328,41 @@ describe('Single-Turn Query (E2E)', () => {
await q.close(); await q.close();
} }
}); });
it('should receive partial messages when includePartialMessages is enabled', async () => {
const q = query({
prompt: 'Count from 1 to 5',
options: {
...SHARED_TEST_OPTIONS,
includePartialMessages: true,
debug: false,
},
});
const messages: CLIMessage[] = [];
let partialMessageCount = 0;
let assistantMessageCount = 0;
try {
for await (const message of q) {
messages.push(message);
if (isCLIPartialAssistantMessage(message)) {
partialMessageCount++;
}
if (isCLIAssistantMessage(message)) {
assistantMessageCount++;
}
}
expect(messages.length).toBeGreaterThan(0);
expect(partialMessageCount).toBeGreaterThan(0);
expect(assistantMessageCount).toBeGreaterThan(0);
} finally {
await q.close();
}
});
}); });
describe('Message Type Recognition', () => { describe('Message Type Recognition', () => {