Files
orca/mobile/src/source-control/use-mobile-commit-failure-recovery.ts
T
Jinjing 8a39450b18 refs/heads/handle-mobile-pull-request-issues (#6598)
* feat(mobile): add commit failure recovery panel with AI fix action

- Surfaces a "Commit failed" panel with a one-tap AI fix button when a
  git commit fails in the source control view or PR creation flow
- Detects commit failures specifically during the committing progress
  step and captures staged entries and commit message for context
- Extracts commit failure summary and prompt logic into
  `src/shared/source-control-commit-failure.ts` and PR checks prompt
  into `src/shared/pr-checks-fix-prompt.ts` so both desktop and mobile
  share the same implementations
- Adds auto-find of an available Metro port starting from 8081 and
  extracts expo CLI bootstrap into `mobile-expo-cli.mjs` shared by
  `start-emulator` and a new `start-expo.mjs` wrapper

* Share source-control AI prompts and simplify mobile PR actions

- Extract conflict, check-fixing, and commit-failure prompt builders
  to shared modules for reuse by both desktop and mobile.
- Configure Metro in the mobile package to watch and bundle modules
  from the repository-root shared directory.
- Remove the desktop-style merge method picker from the mobile PR
  actions panel, opting to use repository defaults automatically.
- Refactor mobile hosted review creation and git preparation logic
  into dedicated helper files.
2026-06-28 00:58:17 -07:00

81 lines
2.3 KiB
TypeScript

import { useCallback, useEffect, useMemo, useState } from 'react'
import type { ConnectionState } from '../transport/types'
import type { RpcClient } from '../transport/rpc-client'
import { triggerError, triggerSuccess } from '../platform/haptics'
import { createTerminalAndSendPrompt } from '../session/pr-ai-triage-launch'
import {
buildFixCommitFailurePrompt,
type MobileCommitFailureRecovery,
hasExpandedCommitFailureDetails,
summarizeCommitFailure
} from './mobile-commit-failure-recovery'
type Params = {
client: RpcClient | null
connState: ConnectionState
worktreeId: string
failure: MobileCommitFailureRecovery | null
}
export function useMobileCommitFailureRecovery({ client, connState, worktreeId, failure }: Params) {
const [launching, setLaunching] = useState(false)
const [launchError, setLaunchError] = useState<string | null>(null)
const summary = useMemo(() => (failure ? summarizeCommitFailure(failure.error) : null), [failure])
useEffect(() => {
setLaunchError(null)
}, [failure])
const hasDetails = useMemo(
() => (failure && summary ? hasExpandedCommitFailureDetails(failure.error, summary) : false),
[failure, summary]
)
const prompt = useMemo(
() =>
failure && summary
? buildFixCommitFailurePrompt({
summary,
error: failure.error,
entries: failure.stagedEntries,
worktreePath: null,
commitMessage: failure.commitMessage
})
: null,
[failure, summary]
)
const launch = useCallback(async (): Promise<boolean> => {
if (launching || !prompt) {
return false
}
if (!client || connState !== 'connected') {
setLaunchError('Waiting for desktop...')
triggerError()
return false
}
setLaunching(true)
setLaunchError(null)
try {
await createTerminalAndSendPrompt(client, worktreeId, prompt)
triggerSuccess()
return true
} catch (err) {
triggerError()
setLaunchError(err instanceof Error ? err.message : 'Failed to launch agent')
return false
} finally {
setLaunching(false)
}
}, [client, connState, launching, prompt, worktreeId])
return {
summary,
hasDetails,
launching,
launchError,
launch
}
}
export type MobileCommitFailureRecoveryAction = ReturnType<typeof useMobileCommitFailureRecovery>