fix: stop stuck loading after session run conflict

This commit is contained in:
john
2026-07-23 11:48:56 +08:00
parent baa383548c
commit 6ee8542da2
2 changed files with 10 additions and 2 deletions
+2 -1
View File
@@ -40,12 +40,13 @@ export function shouldPromoteSessionIdToStreaming(chatState) {
* @returns {boolean}
*/
export function shouldKeepStreamingAfterRunError(status, message = '', code = '') {
if (status === 0 || status === 409 || Number(status) >= 500) return true;
if (status === 0 || Number(status) >= 500) return true;
// Goose can surface the session-level concurrency guard as a failed agent
// run (rather than an HTTP 409). The request may already be streaming and
// the session SSE is still the source of truth, so recover from the session
// instead of showing a terminal error in the chat composer.
const text = `${String(code ?? '')} ${String(message ?? '')}`.toLowerCase();
if (String(code ?? '').trim() === 'SESSION_RUN_CONFLICT') return false;
return text.includes('session already has an active request')
|| text.includes('active request. cancel it first');
}
+8 -1
View File
@@ -50,10 +50,17 @@ test('completed run wins when the direct-chat snapshot is not ready', () => {
test('only ambiguous transport failures keep the chat streaming', () => {
assert.equal(shouldKeepStreamingAfterRunError(0), true);
assert.equal(shouldKeepStreamingAfterRunError(409), true);
assert.equal(shouldKeepStreamingAfterRunError(409), false);
assert.equal(shouldKeepStreamingAfterRunError(503), true);
assert.equal(shouldKeepStreamingAfterRunError(400), false);
assert.equal(shouldKeepStreamingAfterRunError(undefined), false);
assert.equal(
shouldKeepStreamingAfterRunError(
409,
'Session already has an active request. Cancel it first.',
),
true,
);
assert.equal(
shouldKeepStreamingAfterRunError(
undefined,