Merge updated origin/master into feat/tui-master-port

This commit is contained in:
Tianyi Cui
2026-07-27 23:55:53 +08:00
118 changed files with 2540 additions and 848 deletions

View File

@@ -675,8 +675,9 @@ export function createTuiChat(
break
case 'llm/retry': {
retractFailedStreaming()
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

View File

@@ -15,7 +15,7 @@ buffer
style 0-2 fg=bright-blue bold underline
5| "Start then cancel. "
6| <blank>
7| "Retrying model request (1/2) in 1000ms: temporary transport failure "
7| "Retrying model request (1/) in 1000ms: temporary transport failure "
style 0-66 fg=yellow
8| <blank>
9| "Turn cancelled. "

View File

@@ -308,6 +308,9 @@ describe('TUI terminal-state snapshots', () => {
harness.session.append('llm/retry', {
turn: 1,
step: 1,
provider: 'mock',
mode: 'normal',
policyKey: '["normal",2,["RATE_LIMIT"],1,10000,0]',
retry: 1,
maxRetries: 2,
delayMs: 500,
@@ -334,8 +337,10 @@ describe('TUI terminal-state snapshots', () => {
harness.session.append('llm/retry', {
turn: 1,
step: 1,
provider: 'mock',
mode: 'always',
policyKey: '["always",1,10000,0]',
retry: 1,
maxRetries: 2,
delayMs: 1_000,
failure: { message: 'temporary transport failure', code: 'TRANSPORT' },
})

View File

@@ -1334,6 +1334,9 @@ describe('pi-tui chat lifecycle and transcript', () => {
result.session.append('llm/retry', {
turn: 1,
step: 1,
provider: 'mock',
mode: 'normal',
policyKey: '["normal",2,["RATE_LIMIT"],1,10000,0]',
retry: 1,
maxRetries: 2,
delayMs: 500,
@@ -1367,6 +1370,9 @@ describe('pi-tui chat lifecycle and transcript', () => {
result.session.append('llm/retry', {
turn: 1,
step: 1,
provider: 'mock',
mode: 'normal',
policyKey: '["normal",2,["RATE_LIMIT"],1,10000,0]',
retry: 1,
maxRetries: 2,
delayMs: 500,
@@ -1375,16 +1381,30 @@ describe('pi-tui chat lifecycle and transcript', () => {
result.session.append('llm/retry', {
turn: 1,
step: 2,
provider: 'mock',
mode: 'normal',
policyKey: '["normal",2,["RATE_LIMIT"],1,10000,0]',
retry: 2,
maxRetries: 2,
delayMs: 1_000,
failure: { message: 'failed before chunks', code: 'SERVER', status: 503 },
})
result.session.append('llm/retry', {
turn: 1,
step: 3,
provider: 'mock',
mode: 'always',
policyKey: '["always",1,10000,0]',
retry: 1,
delayMs: 2_000,
failure: { message: 'retry without limit', code: 'AUTH', status: 401 },
})
await tick()
expect(result.terminal.output).toContain('Retrying model request (1/2) in 500ms: rate limited')
expect(result.terminal.output).toContain('Retrying model request (2/2) in 1000ms: failed before chunks')
expect(result.terminal.output).not.toContain('discarded partial answer')
expect(result.terminal.output).toContain('Retrying model request (1/∞) in 2000ms: retry without limit')
await dispose(result)
})