feat(llm): add per-provider retry policies
This commit is contained in:
@@ -1366,8 +1366,9 @@ export function streamSessionEventUpdate(
|
||||
return
|
||||
}
|
||||
case 'llm/retry': {
|
||||
const retryLimit = event.data.mode === 'always' ? '∞' : String(event.data.maxRetries)
|
||||
const text = '\n\n[Previous model attempt discarded; retrying '
|
||||
+ `${event.data.retry}/${event.data.maxRetries} in ${event.data.delayMs}ms: `
|
||||
+ `${event.data.retry}/${retryLimit} in ${event.data.delayMs}ms: `
|
||||
+ `${event.data.failure.message}]\n\n`
|
||||
notify({ sessionId, update: { sessionUpdate: 'agent_message_chunk', content: { type: 'text', text } } })
|
||||
return
|
||||
|
||||
@@ -103,6 +103,8 @@ describe('streamSessionEventUpdate', () => {
|
||||
expect(updatesFor(evt('llm/retry', {
|
||||
turn: 1,
|
||||
step: 1,
|
||||
provider: 'mock',
|
||||
mode: 'normal',
|
||||
retry: 1,
|
||||
maxRetries: 2,
|
||||
delayMs: 500,
|
||||
@@ -114,6 +116,21 @@ describe('streamSessionEventUpdate', () => {
|
||||
text: '\n\n[Previous model attempt discarded; retrying 1/2 in 500ms: backend busy]\n\n',
|
||||
},
|
||||
}])
|
||||
expect(updatesFor(evt('llm/retry', {
|
||||
turn: 1,
|
||||
step: 2,
|
||||
provider: 'mock',
|
||||
mode: 'always',
|
||||
retry: 7,
|
||||
delayMs: 1_000,
|
||||
failure: { message: 'still unavailable', code: 'AUTH' },
|
||||
}))).toEqual([{
|
||||
sessionUpdate: 'agent_message_chunk',
|
||||
content: {
|
||||
type: 'text',
|
||||
text: '\n\n[Previous model attempt discarded; retrying 7/∞ in 1000ms: still unavailable]\n\n',
|
||||
},
|
||||
}])
|
||||
expect(updatesFor(evt('turn/end', {
|
||||
turn: 1,
|
||||
reason: { kind: 'error', step: 2, failure: { message: 'still busy', code: 'SERVER' } },
|
||||
|
||||
@@ -2298,8 +2298,9 @@ export function createTuiChat(
|
||||
}
|
||||
case 'llm/retry': {
|
||||
clearStreaming()
|
||||
const retryLimit = event.data.mode === 'always' ? '∞' : String(event.data.maxRetries)
|
||||
appendNotice(
|
||||
`Retrying model request (${event.data.retry}/${event.data.maxRetries}) in ${event.data.delayMs}ms: ${event.data.failure.message}`,
|
||||
`Retrying model request (${event.data.retry}/${retryLimit}) in ${event.data.delayMs}ms: ${event.data.failure.message}`,
|
||||
'warning',
|
||||
)
|
||||
break
|
||||
|
||||
@@ -21,7 +21,7 @@ buffer
|
||||
7| "▌ "
|
||||
style 0-0 fg=bright-blue
|
||||
8| <blank>
|
||||
9| " Retrying model request (1/2) in 1000ms: temporary transport failure "
|
||||
9| " Retrying model request (1/∞) in 1000ms: temporary transport failure "
|
||||
style 1-67 fg=yellow
|
||||
10| <blank>
|
||||
11| " Turn cancelled. "
|
||||
|
||||
@@ -269,6 +269,8 @@ describe('TUI terminal-state snapshots', () => {
|
||||
harness.session.append('llm/retry', {
|
||||
turn: 1,
|
||||
step: 1,
|
||||
provider: 'mock',
|
||||
mode: 'normal',
|
||||
retry: 1,
|
||||
maxRetries: 2,
|
||||
delayMs: 500,
|
||||
@@ -297,8 +299,9 @@ describe('TUI terminal-state snapshots', () => {
|
||||
harness.session.append('llm/retry', {
|
||||
turn: 1,
|
||||
step: 1,
|
||||
provider: 'mock',
|
||||
mode: 'always',
|
||||
retry: 1,
|
||||
maxRetries: 2,
|
||||
delayMs: 1_000,
|
||||
failure: { message: 'temporary transport failure', code: 'TRANSPORT' },
|
||||
})
|
||||
|
||||
@@ -1290,6 +1290,8 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
result.session.append('llm/retry', {
|
||||
turn: 1,
|
||||
step: 1,
|
||||
provider: 'mock',
|
||||
mode: 'normal',
|
||||
retry: 1,
|
||||
maxRetries: 2,
|
||||
delayMs: 500,
|
||||
@@ -1322,6 +1324,8 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
result.session.append('llm/retry', {
|
||||
turn: 1,
|
||||
step: 1,
|
||||
provider: 'mock',
|
||||
mode: 'normal',
|
||||
retry: 1,
|
||||
maxRetries: 2,
|
||||
delayMs: 500,
|
||||
@@ -1330,6 +1334,8 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
result.session.append('llm/retry', {
|
||||
turn: 1,
|
||||
step: 2,
|
||||
provider: 'mock',
|
||||
mode: 'normal',
|
||||
retry: 2,
|
||||
maxRetries: 2,
|
||||
delayMs: 1_000,
|
||||
|
||||
Reference in New Issue
Block a user