mirror of
https://github.com/stablyai/orca.git
synced 2026-09-25 16:02:38 +00:00
* Add project Windows runtime selection * Fix project Windows runtime selection Co-authored-by: Orca <help@stably.ai> * fix: preserve WSL shell variables --------- Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com> Co-authored-by: Orca <help@stably.ai> Co-authored-by: Neil <neil@stably.ai>
56 lines
2.3 KiB
TypeScript
56 lines
2.3 KiB
TypeScript
import type { ClassifiedError } from '../../shared/types'
|
|
|
|
// Why: gh CLI surfaces API errors as unstructured stderr. Map known
|
|
// patterns to typed errors so callers can show user-friendly messages.
|
|
export function classifyGhError(stderr: string): ClassifiedError {
|
|
const s = stderr.toLowerCase()
|
|
if (s.includes('http 403') || s.includes('resource not accessible')) {
|
|
return {
|
|
type: 'permission_denied',
|
|
message: "You don't have permission to edit this issue. Check your GitHub token scopes."
|
|
}
|
|
}
|
|
if (s.includes('http 404') || s.includes('could not resolve to a repository')) {
|
|
return { type: 'not_found', message: 'Issue not found — it may have been deleted.' }
|
|
}
|
|
if (s.includes('has disabled issues')) {
|
|
return { type: 'issues_disabled', message: 'Issues are disabled on this repository.' }
|
|
}
|
|
if (s.includes('http 422') || s.includes('validation failed')) {
|
|
return { type: 'validation_error', message: `Invalid update — ${stderr.trim()}` }
|
|
}
|
|
if (s.includes('rate limit')) {
|
|
return {
|
|
type: 'rate_limited',
|
|
message: 'GitHub rate limit hit. Try again in a few minutes.'
|
|
}
|
|
}
|
|
if (
|
|
s.includes('timeout') ||
|
|
s.includes('no such host') ||
|
|
s.includes('network') ||
|
|
s.includes('could not resolve host')
|
|
) {
|
|
return { type: 'network_error', message: 'Network error — check your connection.' }
|
|
}
|
|
return { type: 'unknown', message: `Failed to update issue: ${stderr.trim()}` }
|
|
}
|
|
|
|
// Why: classifyGhError's copy is phrased for edit/update operations, but
|
|
// listIssues is a read op and renderer banners interpolate the message.
|
|
export function classifyListIssuesError(stderr: string): ClassifiedError {
|
|
const c = classifyGhError(stderr)
|
|
const trimmed = stderr.trim()
|
|
const readMessages: Record<ClassifiedError['type'], string> = {
|
|
permission_denied:
|
|
"You don't have permission to read issues for this repository. Check your GitHub token scopes.",
|
|
not_found: 'Repository not found.',
|
|
issues_disabled: 'Issues are disabled on this repository.',
|
|
validation_error: `Invalid request — ${trimmed}`,
|
|
rate_limited: 'GitHub rate limit hit. Try again in a few minutes.',
|
|
network_error: 'Network error — check your connection.',
|
|
unknown: `Failed to load issues: ${trimmed}`
|
|
}
|
|
return { type: c.type, message: readMessages[c.type] }
|
|
}
|