feat: add route control bar and fix replay protocol compliance
Some checks failed
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m4s
CI / docker (push) Successful in 1m0s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Has been cancelled

Add ROUTE_CONTROL command type and route-control mapping in
AgentCommandController. New RouteControlBar component in the exchange
header shows Start/Stop/Suspend/Resume actions (grouped pill bar) and
a Replay button, gated by agent capabilities and OPERATOR/ADMIN role.

Fix useReplayExchange hook to match protocol section 16: payload now
uses { routeId, exchange: { body, headers }, originalExchangeId, nonce }
instead of the flat { headers, body } format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-30 21:42:06 +02:00
parent 30e9b55379
commit 8b0d473fcd
6 changed files with 258 additions and 9 deletions

View File

@@ -154,22 +154,53 @@ export function useTestExpression() {
})
}
// ── Route Control ────────────────────────────────────────────────────────
export function useSendRouteCommand() {
return useMutation({
mutationFn: async ({ application, action, routeId }: {
application: string
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,
})
if (error) throw new Error('Failed to send route command')
return data!
},
})
}
// ── Replay Exchange ───────────────────────────────────────────────────────
export function useReplayExchange() {
return useMutation({
mutationFn: async ({
agentId,
routeId,
headers,
body,
originalExchangeId,
}: {
agentId: string
headers: Record<string, string>
routeId: string
headers?: Record<string, string>
body: string
originalExchangeId?: string
}) => {
const { data, error } = await api.POST('/agents/{id}/commands', {
params: { path: { id: agentId } },
body: { type: 'replay', payload: { headers, body } } as any,
body: {
type: 'replay',
payload: {
routeId,
exchange: { body, headers: headers ?? {} },
originalExchangeId,
nonce: crypto.randomUUID(),
},
} as any,
})
if (error) throw new Error('Failed to send replay command')
return data!