mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
feat: improve spawn error handling and reporting across full stack (#249)
* feat: improve spawn error handling and reporting across full stack - Return error result instead of throwing in apiMachine spawn handler - Add lastSpawnError field to RunnerState for persistent error tracking - Add error awaiter system for early process exit/error detection before webhook - Build detailed webhook failure messages with exit code, signal, and stderr tail - Report spawn outcomes to hub via runner state updates - Handle more spawn result types in rpcGateway with better error messages - Display runner last spawn error in web UI (NewSession & SpawnSession) - Extract shared formatRunnerSpawnError utility to avoid duplication Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cli): narrow spawnResult type check to fix TS2339 error Use `type === 'error'` instead of `type !== 'success'` to properly narrow the discriminated union, allowing TypeScript to infer errorMessage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
b4b73d4405
commit
4716d315b7
@@ -21,6 +21,7 @@ import {
|
||||
} from './preferences'
|
||||
import { SessionTypeSelector } from './SessionTypeSelector'
|
||||
import { YoloToggle } from './YoloToggle'
|
||||
import { formatRunnerSpawnError } from '../../utils/formatRunnerSpawnError'
|
||||
|
||||
export function NewSession(props: {
|
||||
api: ApiClient
|
||||
@@ -82,6 +83,15 @@ export function NewSession(props: {
|
||||
}
|
||||
}, [props.machines, machineId, getLastUsedMachineId, getRecentPaths])
|
||||
|
||||
const selectedMachine = useMemo(
|
||||
() => (machineId ? props.machines.find((machine) => machine.id === machineId) ?? null : null),
|
||||
[machineId, props.machines]
|
||||
)
|
||||
const runnerSpawnError = useMemo(
|
||||
() => formatRunnerSpawnError(selectedMachine),
|
||||
[selectedMachine]
|
||||
)
|
||||
|
||||
const recentPaths = useMemo(
|
||||
() => getRecentPaths(machineId),
|
||||
[getRecentPaths, machineId]
|
||||
@@ -247,6 +257,11 @@ export function NewSession(props: {
|
||||
isDisabled={isFormDisabled}
|
||||
onChange={handleMachineChange}
|
||||
/>
|
||||
{runnerSpawnError ? (
|
||||
<div className="px-3 py-2 text-xs text-red-600">
|
||||
Runner last spawn error: {runnerSpawnError}
|
||||
</div>
|
||||
) : null}
|
||||
<DirectorySection
|
||||
directory={directory}
|
||||
suggestions={suggestions}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { usePlatform } from '@/hooks/usePlatform'
|
||||
import { useSpawnSession } from '@/hooks/mutations/useSpawnSession'
|
||||
import { formatRunnerSpawnError } from '@/utils/formatRunnerSpawnError'
|
||||
import { useTranslation } from '@/lib/use-translation'
|
||||
|
||||
type SessionType = 'simple' | 'worktree'
|
||||
@@ -32,6 +33,10 @@ export function SpawnSession(props: {
|
||||
const { spawnSession, isPending, error: spawnError } = useSpawnSession(props.api)
|
||||
|
||||
const machineTitle = useMemo(() => getMachineTitle(props.machine), [props.machine])
|
||||
const runnerSpawnError = useMemo(
|
||||
() => formatRunnerSpawnError(props.machine),
|
||||
[props.machine?.runnerState?.lastSpawnError]
|
||||
)
|
||||
|
||||
async function spawn() {
|
||||
const trimmed = directory.trim()
|
||||
@@ -144,6 +149,12 @@ export function SpawnSession(props: {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{runnerSpawnError ? (
|
||||
<div className="text-xs text-red-600">
|
||||
Runner last spawn error: {runnerSpawnError}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{(error ?? spawnError) ? (
|
||||
<div className="text-sm text-red-600">
|
||||
{error ?? spawnError}
|
||||
|
||||
Reference in New Issue
Block a user