feat(#116): update command hooks for synchronous group response
Some checks failed
CI / cleanup-branch (push) Has been skipped
CI / build (push) Failing after 30s
CI / docker (push) Has been skipped
CI / deploy (push) Has been skipped
CI / deploy-feature (push) Has been skipped

Add CommandGroupResponse and ConfigUpdateResponse types. Switch
useSendGroupCommand and useSendRouteCommand from openapi-fetch to authFetch
returning CommandGroupResponse. Update useUpdateApplicationConfig to return
ConfigUpdateResponse and fix all consumer onSuccess callbacks to access
saved.config.version instead of saved.version.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-02 19:01:06 +02:00
parent 027e45aadf
commit c3b4f70913
5 changed files with 36 additions and 20 deletions

View File

@@ -1,5 +1,4 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { api } from '../client'
import { useAuthStore } from '../../auth/auth-store'
// ── Application Config ────────────────────────────────────────────────────
@@ -65,6 +64,11 @@ export function useApplicationConfig(application: string | undefined) {
})
}
export interface ConfigUpdateResponse {
config: ApplicationConfig
pushResult: CommandGroupResponse
}
export function useUpdateApplicationConfig() {
const queryClient = useQueryClient()
return useMutation({
@@ -75,10 +79,10 @@ export function useUpdateApplicationConfig() {
body: JSON.stringify(config),
})
if (!res.ok) throw new Error('Failed to update config')
return res.json() as Promise<ApplicationConfig>
return res.json() as Promise<ConfigUpdateResponse>
},
onSuccess: (saved) => {
queryClient.setQueryData(['applicationConfig', saved.application], saved)
onSuccess: (result) => {
queryClient.setQueryData(['applicationConfig', result.config.application], result.config)
queryClient.invalidateQueries({ queryKey: ['applicationConfig', 'all'] })
},
})
@@ -98,6 +102,16 @@ export function useProcessorRouteMapping(application?: string) {
})
}
// ── Group Command Response ───────────────────────────────────────────────
export interface CommandGroupResponse {
success: boolean
total: number
responded: number
responses: { agentId: string; status: string; message: string }[]
timedOut: string[]
}
// ── Generic Group Command (kept for non-config commands) ──────────────────
interface SendGroupCommandParams {
@@ -109,12 +123,13 @@ interface SendGroupCommandParams {
export function useSendGroupCommand() {
return useMutation({
mutationFn: async ({ group, type, payload }: SendGroupCommandParams) => {
const { data, error } = await api.POST('/agents/groups/{group}/commands', {
params: { path: { group } },
body: { type, payload } as any,
const res = await authFetch(`/api/v1/agents/groups/${encodeURIComponent(group)}/commands`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ type, payload }),
})
if (error) throw new Error('Failed to send command')
return data!
if (!res.ok) throw new Error('Failed to send command')
return res.json() as Promise<CommandGroupResponse>
},
})
}
@@ -163,12 +178,13 @@ export function useSendRouteCommand() {
action: 'start' | 'stop' | 'suspend' | 'resume'
routeId: string
}) => {
const { data, error } = await api.POST('/agents/groups/{group}/commands', {
params: { path: { group: application } },
body: { type: 'route-control', payload: { routeId, action, nonce: crypto.randomUUID() } } as any,
const res = await authFetch(`/api/v1/agents/groups/${encodeURIComponent(application)}/commands`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ type: 'route-control', payload: { routeId, action, nonce: crypto.randomUUID() } }),
})
if (error) throw new Error('Failed to send route command')
return data!
if (!res.ok) throw new Error('Failed to send route command')
return res.json() as Promise<CommandGroupResponse>
},
})
}