Commit 6027a2e
feat: structured AgentError + classified error UX with Retry (#693)
* docs(chat): design spec for backend-failure error UX
Structured AgentError (extends Error; kind/retryable/status/cause) + a shared
toAgentError() classifier (5-class: connection/auth/server/interrupted/aborted),
normalized in both adapters; neutral Agent.error re-typed to Signal<AgentError>;
new neutral retry(); ChatErrorComponent renders legible per-kind copy + a
conditional Retry. Fixes the cryptic 'HTTP 500:' surfacing + langgraph abort
inconsistency the audit flagged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(chat): TDD implementation plan for backend-failure error UX
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(chat): AgentError + toAgentError 5-class classifier (connection/auth/server/interrupted/aborted)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(chat): re-type Agent.error as Signal<AgentError|undefined> + add neutral retry()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(langgraph): classify errors via toAgentError, abort→idle, neutral retry()
- Thread `userAbortRequested` flag in the bridge; stop() sets it before
aborting so the runStream() catch can distinguish user-stop (→ Idle, no
error) from a mid-stream abort (→ interrupted AgentError) or fresh
connect abort (→ toAgentError classification).
- Thread `streamingStarted` flag in runStream() (set on first event);
AbortError after streaming has begun → kind:'interrupted'/retryable:true;
AbortError with no events yet falls through to toAgentError.
- Normalize all non-abort catch errors through toAgentError from
@threadplane/chat so agent.error() is always AgentError | undefined.
- Add retry() to agent.fn.ts: no-op while loading, clears error$, then
calls resubmitLast() — implements the neutral Agent contract method.
- Tighten errorSig to Signal<AgentError | undefined> via a documented cast
(BehaviorSubject stays unknown to satisfy StreamSubjects invariance).
- MockLangGraphAgent.error re-typed to WritableSignal<AgentError|undefined>.
- Update bridge + agent.fn specs: stop()→Idle assertion; four new error-UX
tests (server error kind, user-stop→idle, retry() clears+resubmits,
retry() no-op while loading); fix pre-existing empty-gen lint error.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(langgraph): classify non-user aborts (connection/interrupted) + normalize all error$ sites via toAgentError
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(ag-ui): classify errors via toAgentError + neutral retry() (re-run last input, no duplicate message)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(chat): ChatErrorComponent renders legible AgentError message + conditional Retry
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(examples/chat): assert legible error message + Retry button + retry recovery
Split the error-handling e2e into two focused tests: one that asserts the
alert shows human-legible copy (matching /can't reach|connection|server|
interrupted|try again/i and NOT /HTTP \d{3}/) with a visible Retry button,
and a second that clicks Retry after unrouting and confirms a final
assistant bubble appears.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(chat): tighten error status parsing to HTTP-shaped tokens + connection-before-text; dedup isAbortError/messages
* docs(api): regenerate api-docs for AgentError/toAgentError/retry surface
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent 05cd321 commit 6027a2e
35 files changed
Lines changed: 1368 additions & 113 deletions
File tree
- apps/website/content/docs
- ag-ui/api
- chat/api
- langgraph/api
- docs/superpowers
- plans
- specs
- examples/chat/angular/e2e
- libs
- ag-ui/src/lib
- chat
- src
- lib
- agent
- client-tools
- primitives/chat-error
- styles
- testing
- testing
- langgraph/src/lib
- internals
- testing
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
421 | 421 | | |
422 | 422 | | |
423 | 423 | | |
424 | | - | |
| 424 | + | |
425 | 425 | | |
426 | 426 | | |
427 | 427 | | |
| |||
455 | 455 | | |
456 | 456 | | |
457 | 457 | | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
458 | 464 | | |
459 | 465 | | |
460 | 466 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1426 | 1426 | | |
1427 | 1427 | | |
1428 | 1428 | | |
| 1429 | + | |
| 1430 | + | |
| 1431 | + | |
| 1432 | + | |
| 1433 | + | |
| 1434 | + | |
| 1435 | + | |
| 1436 | + | |
| 1437 | + | |
| 1438 | + | |
| 1439 | + | |
| 1440 | + | |
| 1441 | + | |
| 1442 | + | |
| 1443 | + | |
| 1444 | + | |
| 1445 | + | |
| 1446 | + | |
| 1447 | + | |
| 1448 | + | |
| 1449 | + | |
| 1450 | + | |
| 1451 | + | |
| 1452 | + | |
| 1453 | + | |
| 1454 | + | |
| 1455 | + | |
| 1456 | + | |
| 1457 | + | |
| 1458 | + | |
| 1459 | + | |
| 1460 | + | |
| 1461 | + | |
| 1462 | + | |
| 1463 | + | |
| 1464 | + | |
| 1465 | + | |
| 1466 | + | |
| 1467 | + | |
| 1468 | + | |
| 1469 | + | |
| 1470 | + | |
| 1471 | + | |
| 1472 | + | |
| 1473 | + | |
| 1474 | + | |
| 1475 | + | |
| 1476 | + | |
| 1477 | + | |
| 1478 | + | |
| 1479 | + | |
| 1480 | + | |
| 1481 | + | |
| 1482 | + | |
| 1483 | + | |
| 1484 | + | |
| 1485 | + | |
| 1486 | + | |
| 1487 | + | |
1429 | 1488 | | |
1430 | 1489 | | |
1431 | 1490 | | |
| |||
2118 | 2177 | | |
2119 | 2178 | | |
2120 | 2179 | | |
2121 | | - | |
2122 | | - | |
2123 | | - | |
2124 | | - | |
2125 | | - | |
2126 | | - | |
2127 | 2180 | | |
2128 | 2181 | | |
2129 | 2182 | | |
| |||
5354 | 5407 | | |
5355 | 5408 | | |
5356 | 5409 | | |
5357 | | - | |
| 5410 | + | |
5358 | 5411 | | |
5359 | 5412 | | |
5360 | 5413 | | |
| |||
5388 | 5441 | | |
5389 | 5442 | | |
5390 | 5443 | | |
| 5444 | + | |
| 5445 | + | |
| 5446 | + | |
| 5447 | + | |
| 5448 | + | |
| 5449 | + | |
5391 | 5450 | | |
5392 | 5451 | | |
5393 | 5452 | | |
| |||
5648 | 5707 | | |
5649 | 5708 | | |
5650 | 5709 | | |
5651 | | - | |
| 5710 | + | |
5652 | 5711 | | |
5653 | 5712 | | |
5654 | 5713 | | |
| |||
5694 | 5753 | | |
5695 | 5754 | | |
5696 | 5755 | | |
| 5756 | + | |
| 5757 | + | |
| 5758 | + | |
| 5759 | + | |
| 5760 | + | |
| 5761 | + | |
5697 | 5762 | | |
5698 | 5763 | | |
5699 | 5764 | | |
| |||
6307 | 6372 | | |
6308 | 6373 | | |
6309 | 6374 | | |
6310 | | - | |
| 6375 | + | |
6311 | 6376 | | |
6312 | 6377 | | |
6313 | 6378 | | |
| |||
6353 | 6418 | | |
6354 | 6419 | | |
6355 | 6420 | | |
| 6421 | + | |
| 6422 | + | |
| 6423 | + | |
| 6424 | + | |
| 6425 | + | |
| 6426 | + | |
6356 | 6427 | | |
6357 | 6428 | | |
6358 | 6429 | | |
| |||
6411 | 6482 | | |
6412 | 6483 | | |
6413 | 6484 | | |
6414 | | - | |
| 6485 | + | |
6415 | 6486 | | |
6416 | 6487 | | |
6417 | 6488 | | |
| |||
6990 | 7061 | | |
6991 | 7062 | | |
6992 | 7063 | | |
| 7064 | + | |
| 7065 | + | |
| 7066 | + | |
| 7067 | + | |
| 7068 | + | |
| 7069 | + | |
| 7070 | + | |
6993 | 7071 | | |
6994 | 7072 | | |
6995 | 7073 | | |
| |||
7144 | 7222 | | |
7145 | 7223 | | |
7146 | 7224 | | |
| 7225 | + | |
| 7226 | + | |
| 7227 | + | |
| 7228 | + | |
| 7229 | + | |
| 7230 | + | |
| 7231 | + | |
7147 | 7232 | | |
7148 | 7233 | | |
7149 | 7234 | | |
| |||
7578 | 7663 | | |
7579 | 7664 | | |
7580 | 7665 | | |
| 7666 | + | |
| 7667 | + | |
| 7668 | + | |
| 7669 | + | |
| 7670 | + | |
| 7671 | + | |
| 7672 | + | |
| 7673 | + | |
| 7674 | + | |
| 7675 | + | |
| 7676 | + | |
| 7677 | + | |
| 7678 | + | |
| 7679 | + | |
| 7680 | + | |
| 7681 | + | |
| 7682 | + | |
| 7683 | + | |
| 7684 | + | |
7581 | 7685 | | |
7582 | 7686 | | |
7583 | 7687 | | |
| |||
7881 | 7985 | | |
7882 | 7986 | | |
7883 | 7987 | | |
| 7988 | + | |
| 7989 | + | |
| 7990 | + | |
| 7991 | + | |
| 7992 | + | |
| 7993 | + | |
| 7994 | + | |
| 7995 | + | |
| 7996 | + | |
| 7997 | + | |
| 7998 | + | |
| 7999 | + | |
| 8000 | + | |
| 8001 | + | |
| 8002 | + | |
| 8003 | + | |
| 8004 | + | |
| 8005 | + | |
| 8006 | + | |
7884 | 8007 | | |
7885 | 8008 | | |
7886 | 8009 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1439 | 1439 | | |
1440 | 1440 | | |
1441 | 1441 | | |
1442 | | - | |
| 1442 | + | |
1443 | 1443 | | |
1444 | 1444 | | |
1445 | 1445 | | |
| |||
1581 | 1581 | | |
1582 | 1582 | | |
1583 | 1583 | | |
| 1584 | + | |
| 1585 | + | |
| 1586 | + | |
| 1587 | + | |
| 1588 | + | |
| 1589 | + | |
1584 | 1590 | | |
1585 | 1591 | | |
1586 | 1592 | | |
| |||
1861 | 1867 | | |
1862 | 1868 | | |
1863 | 1869 | | |
1864 | | - | |
| 1870 | + | |
1865 | 1871 | | |
1866 | 1872 | | |
1867 | 1873 | | |
| |||
2003 | 2009 | | |
2004 | 2010 | | |
2005 | 2011 | | |
| 2012 | + | |
| 2013 | + | |
| 2014 | + | |
| 2015 | + | |
| 2016 | + | |
| 2017 | + | |
2006 | 2018 | | |
2007 | 2019 | | |
2008 | 2020 | | |
| |||
0 commit comments