diff --git a/frontend/src/features/admin/AgentRunsPage.tsx b/frontend/src/features/admin/AgentRunsPage.tsx index d896c00..4e97d6a 100644 --- a/frontend/src/features/admin/AgentRunsPage.tsx +++ b/frontend/src/features/admin/AgentRunsPage.tsx @@ -1,9 +1,10 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; +import { useSearchParams } from 'react-router-dom'; import type { AgentRun, AgentRunStatus } from '@workorders/shared'; import { useAgentRunDetail, useAgentRuns } from './queries'; import { usePageTitle } from '../../hooks/usePageTitle'; import { PageHeader, EmptyState, ErrorBanner } from '../../components/primitives/Feedback'; -import { FullPageSpinner } from '../../components/primitives/Spinner'; +import { FullPageSpinner, Spinner } from '../../components/primitives/Spinner'; import { Card } from '../../components/primitives/Card'; import { formatDate } from '../../lib/utils'; import { messageFromError } from '../../lib/errors'; @@ -42,8 +43,14 @@ export function AgentRunsPage() { const limit = 10; const { data, isPending, isError, error } = useAgentRuns(page, limit); const [selectedId, setSelectedId] = useState(null); + const [searchParams] = useSearchParams(); const detail = useAgentRunDetail(selectedId); + useEffect(() => { + const runParam = searchParams.get('run'); + if (runParam) setSelectedId(runParam); + }, [searchParams]); + const totalPages = data ? Math.max(1, Math.ceil(data.total / data.limit)) : 1; function toggleRow(run: AgentRun) { @@ -84,7 +91,7 @@ export function AgentRunsPage() { toggleRow(run)}> {selectedId === run.id && detail.isPending && (
- + Loading run detail…
)} @@ -172,6 +179,19 @@ function FragmentRow({ ); } +function isJsonLike(content: string): boolean { + const trimmed = content.trim(); + return trimmed.startsWith('{') || trimmed.startsWith('['); +} + +function formatJson(content: string): string { + try { + return JSON.stringify(JSON.parse(content), null, 2); + } catch { + return content; + } +} + function RunDetail({ messages, toolCalls, @@ -186,13 +206,21 @@ function RunDetail({ createdAt: string; }[]; }) { + const visibleMessages = messages.filter((m) => m.role !== 'system'); return (
-

Messages

- {messages.length === 0 &&

No messages recorded.

} +

+ Messages + {messages.some((m) => m.role === 'system') && ( + + (system prompt omitted) + + )} +

+ {visibleMessages.length === 0 &&

No messages recorded.

}
- {messages.map((m, i) => ( + {visibleMessages.map((m, i) => (
@@ -204,7 +232,11 @@ function RunDetail({ )}
- {m.role === 'user' || m.role === 'assistant' ? ( + {isJsonLike(m.content) ? ( +
+                  {formatJson(m.content)}
+                
+ ) : m.role === 'user' || m.role === 'assistant' ? ( ) : (
@@ -231,14 +263,24 @@ function RunDetail({
                 
               
{tc.args !== undefined && ( -
-                  {JSON.stringify(tc.args, null, 2)}
-                
+
+

+ args +

+
+                    {JSON.stringify(tc.args, null, 2)}
+                  
+
)} {tc.result !== undefined && ( -
-                  {JSON.stringify(tc.result, null, 2)}
-                
+
+

+ result +

+
+                    {JSON.stringify(tc.result, null, 2)}
+                  
+
)}
))} diff --git a/frontend/src/features/admin/AgentSettingsPage.tsx b/frontend/src/features/admin/AgentSettingsPage.tsx index 215a2be..73f0c4b 100644 --- a/frontend/src/features/admin/AgentSettingsPage.tsx +++ b/frontend/src/features/admin/AgentSettingsPage.tsx @@ -1,4 +1,5 @@ import { useEffect, useRef, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import type { TriageMode, WorkOrderPriority } from '@workorders/shared'; import { useAgentConfig, useDisableAgent, useManualTriageRun, useUpdateAgentConfig } from './queries'; import { usePageTitle } from '../../hooks/usePageTitle'; @@ -10,6 +11,7 @@ import { messageFromError } from '../../lib/errors'; export function AgentSettingsPage() { usePageTitle('Agents'); + const navigate = useNavigate(); const { data: config, isPending, isError, error } = useAgentConfig(); const updateConfig = useUpdateAgentConfig(); const disableAgent = useDisableAgent(); @@ -73,7 +75,11 @@ export function AgentSettingsPage() { async function handleRun() { setFeedback(null); try { - const { outcome } = await manualRun.mutateAsync(workOrderId.trim() || undefined); + const { outcome, runId } = await manualRun.mutateAsync(workOrderId.trim() || undefined); + if (runId) { + navigate(`/app/admin/agents/runs?run=${runId}`); + return; + } setFeedback({ kind: 'ok', text: `Triage run finished: ${outcome}.` }); } catch (err) { setFeedback({ kind: 'error', text: messageFromError(err, 'Triage run failed') }); diff --git a/frontend/src/features/admin/queries.ts b/frontend/src/features/admin/queries.ts index b8791a2..3030b42 100644 --- a/frontend/src/features/admin/queries.ts +++ b/frontend/src/features/admin/queries.ts @@ -153,7 +153,7 @@ export function useDisableAgent() { export function useManualTriageRun() { return useMutation({ mutationFn: (workOrderId?: string) => - api.post<{ outcome: 'done' | 'skipped' | 'failed' | 'retry' }>( + api.post<{ outcome: 'done' | 'skipped' | 'failed' | 'retry'; runId: string | null }>( '/admin/agents/triage/run', workOrderId ? { workOrderId } : {}, ),