mirror of
https://github.com/NanmiCoder/claude-code-haha.git
synced 2026-10-10 11:53:10 +08:00
fix(h5): show AskUserQuestion before tool stream completes #1220
Materialize the question card directly from a permission request when the streamed tool block has not arrived yet. Upsert by tool-use id so either event order produces one visible, answerable card without requiring a refresh.
This commit is contained in:
@@ -4054,6 +4054,92 @@ describe('chatStore history mapping', () => {
|
||||
expect(useChatStore.getState().sessions[TEST_SESSION_ID]?.runtimeConfigReadyCount).toBe(1)
|
||||
})
|
||||
|
||||
it('shows AskUserQuestion when permission arrives before the streamed tool block', () => {
|
||||
const input = {
|
||||
questions: [
|
||||
{
|
||||
question: 'Should we persist data?',
|
||||
options: [{ label: 'No' }, { label: 'Yes' }],
|
||||
},
|
||||
],
|
||||
}
|
||||
useChatStore.setState({
|
||||
sessions: { [TEST_SESSION_ID]: makeSession() },
|
||||
})
|
||||
|
||||
useChatStore.getState().handleServerMessage(TEST_SESSION_ID, {
|
||||
type: 'permission_request',
|
||||
requestId: 'perm-ask-permission-first',
|
||||
toolName: 'AskUserQuestion',
|
||||
toolUseId: 'tool-ask-permission-first',
|
||||
input,
|
||||
})
|
||||
|
||||
expect(useChatStore.getState().sessions[TEST_SESSION_ID]?.messages).toContainEqual(
|
||||
expect.objectContaining({
|
||||
type: 'tool_use',
|
||||
toolName: 'AskUserQuestion',
|
||||
toolUseId: 'tool-ask-permission-first',
|
||||
input,
|
||||
}),
|
||||
)
|
||||
|
||||
useChatStore.getState().handleServerMessage(TEST_SESSION_ID, {
|
||||
type: 'tool_use_complete',
|
||||
toolName: 'AskUserQuestion',
|
||||
toolUseId: 'tool-ask-permission-first',
|
||||
input,
|
||||
})
|
||||
|
||||
expect(
|
||||
useChatStore.getState().sessions[TEST_SESSION_ID]?.messages.filter(
|
||||
(message) => message.type === 'tool_use' &&
|
||||
message.toolUseId === 'tool-ask-permission-first',
|
||||
),
|
||||
).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('keeps one AskUserQuestion when the streamed tool block arrives first', () => {
|
||||
const input = {
|
||||
questions: [
|
||||
{
|
||||
question: 'Which scope?',
|
||||
options: [{ label: 'Current file' }, { label: 'Repository' }],
|
||||
},
|
||||
],
|
||||
}
|
||||
useChatStore.setState({
|
||||
sessions: { [TEST_SESSION_ID]: makeSession() },
|
||||
})
|
||||
const store = useChatStore.getState()
|
||||
|
||||
store.handleServerMessage(TEST_SESSION_ID, {
|
||||
type: 'tool_use_complete',
|
||||
toolName: 'AskUserQuestion',
|
||||
toolUseId: 'tool-ask-stream-first',
|
||||
input,
|
||||
})
|
||||
store.handleServerMessage(TEST_SESSION_ID, {
|
||||
type: 'permission_request',
|
||||
requestId: 'perm-ask-stream-first',
|
||||
toolName: 'AskUserQuestion',
|
||||
toolUseId: 'tool-ask-stream-first',
|
||||
input,
|
||||
})
|
||||
|
||||
const session = useChatStore.getState().sessions[TEST_SESSION_ID]
|
||||
expect(session?.pendingPermission).toMatchObject({
|
||||
requestId: 'perm-ask-stream-first',
|
||||
toolUseId: 'tool-ask-stream-first',
|
||||
})
|
||||
expect(
|
||||
session?.messages.filter(
|
||||
(message) => message.type === 'tool_use' &&
|
||||
message.toolUseId === 'tool-ask-stream-first',
|
||||
),
|
||||
).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('keeps AskUserQuestion permission requests out of the message list while tracking the pending request', () => {
|
||||
useChatStore.setState({
|
||||
sessions: {
|
||||
|
||||
@@ -3340,6 +3340,7 @@ export const useChatStore = create<ChatStore>((set, get) => ({
|
||||
}
|
||||
const hasPermissionMessage = s.messages.some((message) =>
|
||||
message.type === 'permission_request' && message.requestId === msg.requestId)
|
||||
const isAskUserQuestion = msg.toolName === 'AskUserQuestion'
|
||||
|
||||
return {
|
||||
pendingPermission,
|
||||
@@ -3349,8 +3350,21 @@ export const useChatStore = create<ChatStore>((set, get) => ({
|
||||
apiRetry: null,
|
||||
streamingFallback: null,
|
||||
messages:
|
||||
msg.toolName === 'AskUserQuestion' || hasPermissionMessage
|
||||
? s.messages
|
||||
isAskUserQuestion && msg.toolUseId
|
||||
? upsertToolUseMessage(s.messages, msg.toolUseId, (existing) => ({
|
||||
id: existing?.id ?? nextId(),
|
||||
type: 'tool_use',
|
||||
toolName: msg.toolName,
|
||||
toolUseId: msg.toolUseId!,
|
||||
originalToolUseId: existing?.originalToolUseId,
|
||||
input: msg.input,
|
||||
timestamp: existing?.timestamp ?? Date.now(),
|
||||
parentToolUseId: existing?.parentToolUseId,
|
||||
isPending: false,
|
||||
partialInput: existing?.partialInput,
|
||||
}))
|
||||
: isAskUserQuestion || hasPermissionMessage
|
||||
? s.messages
|
||||
: [...s.messages, {
|
||||
id: nextId(),
|
||||
type: 'permission_request',
|
||||
|
||||
Reference in New Issue
Block a user