Commit fc738ec
authored
fix(api-v1): return real task.status in CreateTaskResponse, not hardcoded "pending" (#426)
* fix(v1): return real task.status in CreateTaskResponse, not hardcoded "pending"
POST /v1/chat/tasks returned ``status="pending"`` in the response
body even though ``begin_turn`` had already atomically claimed the
row as RUNNING inside the same handler before the response was
sent. An SDK client doing POST followed by an immediate GET on the
same task would see two contradictory status values from
back-to-back calls (``pending`` then ``running``).
Read ``task.status.value`` after ``begin_turn`` returns instead --
``begin_turn`` refreshes the in-memory ``task`` after committing
the atomic claim, so the post-handler view reflects the row's real
state. ``AppendMessageResponse`` already followed this contract;
the create path now matches it.
Schema docstrings for CreateTaskResponse and AppendMessageResponse
updated to describe the post-claim ``running`` semantics; the
``test_create_task_happy_path`` assertion was checking for the old
``pending`` value and has been updated.
No behavior change in the orchestrator or scheduler -- this is a
response-payload correctness fix only. Twenty-eight v1 task tests
pass; pre-commit (ruff / mypy / isort / codespell) green.
* fix(v1): update create_chat_task docstring + unify AppendMessageResponse status read
Follow-up to the CreateTaskResponse status fix in the previous
commit. Two consistency cleanups within the same handler module:
1. ``create_chat_task`` function docstring still described the
return value as ``status='pending'`` -- inconsistent with the
schema docstring and the implementation that the previous commit
already moved to ``task.status.value`` (i.e. 'running'). Updated
the Returns section to match.
2. ``append_message_to_task`` returned ``status="running"`` hard-
coded while ``create_chat_task`` reads ``task.status.value``.
Unified both endpoints on the same pattern -- reading from the
refreshed in-memory row is defensive (any future ``begin_turn``
status-machine change is picked up automatically) and removes
the asymmetry where one endpoint reflected the DB and the other
asserted a fixed string.
No behavior change for the current contract -- the previous commit
already returned 'running' from CREATE; this commit makes APPEND
share the same expression form and fixes the docstring drift.
Twenty-eight v1 task tests pass; pre-commit green.
* fix(web): persist real exception text to task.error_message on bg failure
``execute_task_background`` previously logged and broadcast the
exception text on failure but never wrote it to ``task.error_message``.
The row's status stayed RUNNING, and ``finish_turn``'s
RUNNING-fallback branch then unconditionally set
``error_message`` to a generic placeholder ("Task execution failed
without status update; see /steps."), forcing SDK and web clients
to fetch ``/steps`` to discover what actually went wrong.
The fix writes the real exception text to ``task.error_message`` and
flips ``status`` to ``FAILED`` in the exception handler, using a
fresh session because the original may be in a failed-transaction
state. ``finish_turn``'s FAILED branch then only fills in a
placeholder when ``error_message`` is empty, so the real message is
preserved through to the final row state.
Same family of fix as the ``status="pending"`` correction above:
make the persisted task row reflect the real outcome rather than a
generic placeholder. Affects both SDK consumers (GET /v1/chat/tasks/
{id}) and web/WebSocket consumers reading the same row.
Twenty-eight v1 task tests pass; pre-commit (ruff / mypy / isort /
codespell) green.
* fix(web): scope bg-task failure handling by status, not by exception site
execute_task_background's outer except spans post-terminal steps
(assistant-message persistence and the completion/paused broadcasts)
that run after the task status was already committed COMPLETED. The
recently added FAILED-persistence wrote the row unconditionally, so a
failure in one of those best-effort steps -- e.g. the completion
broadcast losing its websocket -- rewrote an already-completed task as
FAILED and stored the broadcast error in error_message.
Branch the handler on the task's current status instead. Only a task
still RUNNING is a genuine execution failure: record the real exception
text, flip to FAILED, and emit task_error. A task already in a terminal
state tripped here in a best-effort post-completion step, so observe it
without touching the row or emitting a contradictory task_error;
finish_turn still reconciles the terminal fields afterward.
* fix(web): commit terminal task status only once the turn is durable
The success path committed COMPLETED/FAILED before persisting the
assistant message, which is a separate durable write. If that write
failed, the row was left COMPLETED with no message and no error_message
-- the status-gated failure handler treated it as a best-effort
post-completion step and left it untouched.
Leave the terminal status pending and let persist_assistant_message's
commit land it atomically with the message. A failure in that durable
write now leaves the status RUNNING, so the outer handler surfaces a
real task failure instead of a contradictory empty COMPLETED row. Only
notification broadcasts remain best-effort.
* fix(web): land terminal status on empty-reply turns too
The previous change rode the terminal-status commit on
persist_assistant_message's internal commit. But that helper
early-returns without committing when the assistant content is empty (a
valid empty-reply turn), which left the status pending -> RUNNING ->
finish_turn flipping a successful empty turn to FAILED.
Add an explicit commit after persistence. It lands the terminal status
whether or not a message row was written, while still surfacing a real
failure when persistence raises (control never reaches the explicit
commit, so the status stays uncommitted and the outer except fails it).1 parent 7e568ce commit fc738ec
5 files changed
Lines changed: 371 additions & 36 deletions
File tree
- src/xagent/web
- api
- v1
- schemas
- tests/web
- api/v1
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
95 | 95 | | |
96 | 96 | | |
97 | 97 | | |
98 | | - | |
99 | | - | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
100 | 102 | | |
101 | 103 | | |
102 | 104 | | |
| |||
160 | 162 | | |
161 | 163 | | |
162 | 164 | | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
163 | 173 | | |
164 | 174 | | |
165 | 175 | | |
166 | | - | |
| 176 | + | |
167 | 177 | | |
168 | 178 | | |
169 | 179 | | |
| |||
311 | 321 | | |
312 | 322 | | |
313 | 323 | | |
314 | | - | |
315 | | - | |
316 | | - | |
317 | | - | |
318 | | - | |
319 | | - | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
320 | 332 | | |
321 | 333 | | |
322 | 334 | | |
323 | | - | |
| 335 | + | |
324 | 336 | | |
325 | 337 | | |
326 | 338 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1442 | 1442 | | |
1443 | 1443 | | |
1444 | 1444 | | |
1445 | | - | |
| 1445 | + | |
| 1446 | + | |
| 1447 | + | |
| 1448 | + | |
| 1449 | + | |
| 1450 | + | |
| 1451 | + | |
| 1452 | + | |
| 1453 | + | |
1446 | 1454 | | |
1447 | | - | |
| 1455 | + | |
| 1456 | + | |
1448 | 1457 | | |
1449 | 1458 | | |
1450 | 1459 | | |
| |||
1482 | 1491 | | |
1483 | 1492 | | |
1484 | 1493 | | |
| 1494 | + | |
| 1495 | + | |
| 1496 | + | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
| 1503 | + | |
| 1504 | + | |
1485 | 1505 | | |
1486 | 1506 | | |
1487 | 1507 | | |
| |||
1596 | 1616 | | |
1597 | 1617 | | |
1598 | 1618 | | |
1599 | | - | |
1600 | | - | |
| 1619 | + | |
| 1620 | + | |
| 1621 | + | |
| 1622 | + | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
1601 | 1629 | | |
1602 | | - | |
1603 | | - | |
1604 | | - | |
1605 | | - | |
1606 | | - | |
1607 | | - | |
1608 | | - | |
1609 | | - | |
1610 | | - | |
1611 | | - | |
1612 | | - | |
1613 | | - | |
1614 | | - | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
| 1634 | + | |
| 1635 | + | |
| 1636 | + | |
| 1637 | + | |
| 1638 | + | |
| 1639 | + | |
| 1640 | + | |
| 1641 | + | |
| 1642 | + | |
| 1643 | + | |
| 1644 | + | |
| 1645 | + | |
| 1646 | + | |
| 1647 | + | |
| 1648 | + | |
| 1649 | + | |
1615 | 1650 | | |
1616 | | - | |
1617 | | - | |
| 1651 | + | |
| 1652 | + | |
| 1653 | + | |
| 1654 | + | |
| 1655 | + | |
| 1656 | + | |
| 1657 | + | |
| 1658 | + | |
| 1659 | + | |
| 1660 | + | |
| 1661 | + | |
| 1662 | + | |
| 1663 | + | |
| 1664 | + | |
| 1665 | + | |
| 1666 | + | |
| 1667 | + | |
| 1668 | + | |
| 1669 | + | |
1618 | 1670 | | |
1619 | 1671 | | |
1620 | 1672 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
177 | 177 | | |
178 | 178 | | |
179 | 179 | | |
180 | | - | |
181 | | - | |
182 | | - | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
183 | 184 | | |
184 | 185 | | |
185 | 186 | | |
186 | 187 | | |
187 | 188 | | |
188 | 189 | | |
189 | 190 | | |
190 | | - | |
191 | | - | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
192 | 195 | | |
193 | 196 | | |
194 | 197 | | |
| |||
230 | 233 | | |
231 | 234 | | |
232 | 235 | | |
233 | | - | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
234 | 241 | | |
235 | 242 | | |
236 | 243 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
116 | | - | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
117 | 119 | | |
118 | 120 | | |
119 | 121 | | |
| |||
0 commit comments