feat: unify autopilot launch on server preflight with live balance polling

- New shared launch module (web/src/lib/launch): preflight client, model/
  exchange resolution, and a single launchAutopilot orchestrator used by both
  Strategy Studio and the guided launch panel — the two previously duplicated
  and divergent launch implementations are gone.
- Preflight runs BEFORE any strategy mutation, so a failed launch no longer
  rewrites/activates the strategy as a side effect; readiness and minimums
  come from the server (live balances) instead of stale client caches.
- Guided panel polls preflight every 20s so deposits are detected without
  manual refresh; step metas show live balances and required minimums; the
  beginner wallet page polls its balance while the deposit screen is open.
- Every failure now routes to a guided fix: hyperliquid-funds gets its own
  setup anchor (scrolls to the launch panel), start rejections surface the
  server's preflight reason (including manual restarts from the trader list),
  and structured error bodies flow through ApiError.errorData.
- Terminal dashboard shows a persistent runtime banner when the AI fee wallet
  runs low/empty or the trader enters safe mode.
- Vitest coverage for setup-target routing, readiness helpers, and the
  launch orchestration order (no side effects before preflight).
This commit is contained in:
tinkle-community
2026-07-05 20:38:51 +09:00
parent b17d97effc
commit a744328313
14 changed files with 996 additions and 400 deletions

View File

@@ -2,6 +2,7 @@ import { useState, useEffect } from 'react'
import { useNavigate, useSearchParams } from 'react-router-dom'
import useSWR from 'swr'
import { api } from '../../lib/api'
import { ApiError } from '../../lib/httpClient'
import type {
TraderInfo,
CreateTraderRequest,
@@ -305,7 +306,15 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
await mutateTraders()
} catch (error) {
console.error('Failed to toggle trader:', error)
// Launch preflight rejections carry an actionable reason (e.g. "AI fee
// wallet is empty") — show it instead of a generic failure toast.
if (
error instanceof ApiError &&
error.errorKey === 'trader.start.preflight_failed'
) {
toast.error(error.message)
return
}
toast.error(t('operationFailed', language))
}
}
@@ -662,6 +671,15 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
handleOpenClaw402Config()
} else if (setupTarget === 'hyperliquid') {
handleOpenHyperliquidConfig()
} else if (setupTarget === 'hyperliquid-funds') {
// Funding shortfall: bring the guided launch panel (with the trading
// balance step and live preflight polling) into view.
document
.getElementById('autopilot-launch-panel')
?.scrollIntoView({ behavior: 'smooth', block: 'start' })
toast.info(
'Deposit USDC to your Hyperliquid account, the balance check updates automatically.'
)
} else {
return
}