Files
dify/web/app/components/base/agent-log-modal/index.stories.tsx
yyh 91856b09ca refactor: migrate appDetail from Zustand to TanStack Query
- Remove appDetail and setAppDetail from Zustand store
- Use useAppDetail hook for server state management
- Child components now call useAppDetail(appId) directly via useParams()
- Replace setAppDetail calls with useInvalidateAppDetail for cache invalidation
- Keep only client UI state in Zustand (sidebar, modals)
- Split sidebar initialization useEffect for clearer separation of concerns
- Update test mocks to use TanStack Query pattern
- Fix missing dependencies in use-checklist.ts useMemo/useCallback hooks
2026-01-18 23:07:33 +08:00

161 lines
4.4 KiB
TypeScript

import type { Meta, StoryObj } from '@storybook/nextjs'
import type { IChatItem } from '@/app/components/base/chat/chat/type'
import type { AgentLogDetailResponse } from '@/models/log'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { useEffect, useRef, useState } from 'react'
import { ToastProvider } from '@/app/components/base/toast'
import AgentLogModal from '.'
const MOCK_RESPONSE: AgentLogDetailResponse = {
meta: {
status: 'finished',
executor: 'Agent Runner',
start_time: '2024-03-12T10:00:00Z',
elapsed_time: 12.45,
total_tokens: 2589,
agent_mode: 'ReACT',
iterations: 2,
error: undefined,
},
iterations: [
{
created_at: '2024-03-12T10:00:05Z',
files: [],
thought: JSON.stringify({ reasoning: 'Summarise conversation' }, null, 2),
tokens: 934,
tool_calls: [
{
status: 'success',
tool_icon: null,
tool_input: { query: 'Latest revenue numbers' },
tool_output: { answer: 'Revenue up 12% QoQ' },
tool_name: 'search',
tool_label: {
'en-US': 'Revenue Search',
},
time_cost: 1.8,
},
],
tool_raw: {
inputs: JSON.stringify({ context: 'Summaries' }, null, 2),
outputs: JSON.stringify({ observation: 'Revenue up 12% QoQ' }, null, 2),
},
},
{
created_at: '2024-03-12T10:00:09Z',
files: [],
thought: JSON.stringify({ final: 'Revenue increased 12% quarter-over-quarter.' }, null, 2),
tokens: 642,
tool_calls: [],
tool_raw: {
inputs: JSON.stringify({ context: 'Compose summary' }, null, 2),
outputs: JSON.stringify({ observation: 'Final answer ready' }, null, 2),
},
},
],
files: [],
}
const MOCK_CHAT_ITEM: IChatItem = {
id: 'message-1',
content: JSON.stringify({ answer: 'Revenue grew 12% QoQ.' }, null, 2),
input: JSON.stringify({ question: 'Summarise revenue trends.' }, null, 2),
isAnswer: true,
conversationId: 'conv-123',
}
const MOCK_APP_DETAIL = {
id: 'app-1',
name: 'Analytics Agent',
mode: 'agent-chat',
}
const createQueryClient = () => {
const client = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
retry: false,
},
},
})
client.setQueryData(['apps', 'detail', 'app-1'], MOCK_APP_DETAIL)
return client
}
const AgentLogModalDemo = ({
width = 960,
}: {
width?: number
}) => {
const originalFetchRef = useRef<typeof globalThis.fetch>(null)
const [queryClient] = useState(() => createQueryClient())
useEffect(() => {
originalFetchRef.current = globalThis.fetch?.bind(globalThis)
const handler = async (input: RequestInfo | URL, init?: RequestInit) => {
const request = input instanceof Request ? input : new Request(input, init)
const url = request.url
const parsed = new URL(url, window.location.origin)
if (parsed.pathname.endsWith('/apps/app-1/agent/logs')) {
return new Response(JSON.stringify(MOCK_RESPONSE), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})
}
if (originalFetchRef.current)
return originalFetchRef.current(request)
throw new Error(`Unhandled request: ${url}`)
}
globalThis.fetch = handler as typeof globalThis.fetch
return () => {
if (originalFetchRef.current)
globalThis.fetch = originalFetchRef.current
}
}, [])
return (
<QueryClientProvider client={queryClient}>
<ToastProvider>
<div className="relative min-h-[540px] w-full bg-background-default-subtle p-6">
<AgentLogModal
currentLogItem={MOCK_CHAT_ITEM}
width={width}
onCancel={() => {
console.log('Agent log modal closed')
}}
/>
</div>
</ToastProvider>
</QueryClientProvider>
)
}
const meta = {
title: 'Base/Other/AgentLogModal',
component: AgentLogModalDemo,
parameters: {
layout: 'fullscreen',
docs: {
description: {
component: 'Agent execution viewer showing iterations, tool calls, and metadata. Fetch responses are mocked for Storybook.',
},
},
},
args: {
width: 960,
},
tags: ['autodocs'],
} satisfies Meta<typeof AgentLogModalDemo>
export default meta
type Story = StoryObj<typeof meta>
export const Playground: Story = {}