mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
fix(cli): preserve runtime recovery steps (#24800)
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
This commit is contained in:
+10
-2
@@ -76,7 +76,7 @@ export function formatCliError(error: unknown, context: CliErrorContext = {}): s
|
||||
if (hasOrchestrationRequestId(error.data)) {
|
||||
return message
|
||||
}
|
||||
return `${message}\nOrca is not running. Run 'orca open' first.`
|
||||
return formatRuntimeUnavailableError(message, error.data)
|
||||
}
|
||||
// Match before generic recovery; flattened errors may retain only the conflict token.
|
||||
const conflict = automationOwnerConflictRecovery(matchAutomationOwnerConflict(error))
|
||||
@@ -103,7 +103,7 @@ export function formatCliError(error: unknown, context: CliErrorContext = {}): s
|
||||
error instanceof RuntimeRpcFailureError &&
|
||||
error.response.error.code === 'runtime_unavailable'
|
||||
) {
|
||||
return `${message}\nOrca is not running. Run 'orca open' first.`
|
||||
return formatRuntimeUnavailableError(message, error.response.error.data)
|
||||
}
|
||||
if (error instanceof RuntimeRpcFailureError) {
|
||||
return formatMessageWithNextSteps(message, nextStepsFromData(error.response.error.data))
|
||||
@@ -119,6 +119,14 @@ function hasOrchestrationRequestId(data: unknown): boolean {
|
||||
)
|
||||
}
|
||||
|
||||
function formatRuntimeUnavailableError(message: string, data: unknown): string {
|
||||
const nextSteps = nextStepsFromData(data)
|
||||
if (nextSteps.length > 0) {
|
||||
return formatMessageWithNextSteps(message, nextSteps)
|
||||
}
|
||||
return `${message}\nOrca is not running. Run 'orca open' first.`
|
||||
}
|
||||
|
||||
export function reportCliError(error: unknown, json: boolean, context: CliErrorContext = {}): void {
|
||||
const selector = contextRecovery(errorCode(error), context)
|
||||
if (json) {
|
||||
|
||||
@@ -252,17 +252,97 @@ describe('CLI error recovery', () => {
|
||||
log.mockRestore()
|
||||
})
|
||||
|
||||
it('preserves structured recovery for a local runtime-unavailable error', () => {
|
||||
const error = new RuntimeClientError(
|
||||
'runtime_unavailable',
|
||||
'The local runtime has a recovery step.',
|
||||
{ nextSteps: ['Run `orca runtime status --json` and retry.'] }
|
||||
)
|
||||
|
||||
expect(formatCliError(error)).toBe(
|
||||
[
|
||||
'The local runtime has a recovery step.',
|
||||
'Next step: Run `orca runtime status --json` and retry.'
|
||||
].join('\n')
|
||||
)
|
||||
})
|
||||
|
||||
it('preserves structured recovery for an RPC runtime-unavailable error', () => {
|
||||
const error = new RuntimeRpcFailureError({
|
||||
id: 'req_runtime_recovery',
|
||||
ok: false,
|
||||
error: {
|
||||
code: 'runtime_unavailable',
|
||||
message: 'The runtime returned a recovery step.',
|
||||
data: { nextSteps: ['Reconnect the runtime, then retry.'] }
|
||||
},
|
||||
_meta: { runtimeId: 'runtime_local' }
|
||||
})
|
||||
|
||||
expect(formatCliError(error)).toBe(
|
||||
[
|
||||
'The runtime returned a recovery step.',
|
||||
'Next step: Reconnect the runtime, then retry.'
|
||||
].join('\n')
|
||||
)
|
||||
})
|
||||
|
||||
it('keeps startup guidance when a local runtime-unavailable error has no next steps', () => {
|
||||
const message = 'Could not connect to the running Orca app.'
|
||||
|
||||
expect(formatCliError(new RuntimeClientError('runtime_unavailable', message))).toBe(
|
||||
`${message}\nOrca is not running. Run 'orca open' first.`
|
||||
)
|
||||
})
|
||||
|
||||
it('keeps startup guidance when an RPC runtime-unavailable error has no next steps', () => {
|
||||
const message = 'The RPC runtime is unavailable.'
|
||||
const error = new RuntimeRpcFailureError({
|
||||
id: 'req_rpc_startup_fallback',
|
||||
ok: false,
|
||||
error: {
|
||||
code: 'runtime_unavailable',
|
||||
message
|
||||
},
|
||||
_meta: { runtimeId: 'runtime_local' }
|
||||
})
|
||||
|
||||
expect(formatCliError(error)).toBe(`${message}\nOrca is not running. Run 'orca open' first.`)
|
||||
})
|
||||
|
||||
it('preserves the local request-id protection for an RPC runtime-unavailable error', () => {
|
||||
const error = new RuntimeRpcFailureError({
|
||||
id: 'req_rpc_runtime_mutation',
|
||||
ok: false,
|
||||
error: {
|
||||
code: 'runtime_unavailable',
|
||||
message: 'Re-issue the same RPC command with --retry-request mutation_2.',
|
||||
data: {
|
||||
orchestrationRequestId: 'mutation_2',
|
||||
nextSteps: ['Read the RPC mutation status before retrying.']
|
||||
}
|
||||
},
|
||||
_meta: { runtimeId: 'runtime_local' }
|
||||
})
|
||||
|
||||
expect(formatCliError(error)).toBe(
|
||||
'Re-issue the same RPC command with --retry-request mutation_2.'
|
||||
)
|
||||
})
|
||||
|
||||
it('does not replace mutation recovery with generic runtime startup advice', () => {
|
||||
const error = new RuntimeClientError(
|
||||
'runtime_unavailable',
|
||||
'Re-issue the same command with --retry-request mutation_1.',
|
||||
{ orchestrationRequestId: 'mutation_1' }
|
||||
{
|
||||
orchestrationRequestId: 'mutation_1',
|
||||
nextSteps: ['Read the mutation request status before retrying.']
|
||||
}
|
||||
)
|
||||
|
||||
const output = formatCliError(error)
|
||||
|
||||
expect(output).toContain('--retry-request mutation_1')
|
||||
expect(output).not.toContain('orca open')
|
||||
expect(output).toBe('Re-issue the same command with --retry-request mutation_1.')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user