getThread ordered purely by created_at, which is second-granular on MySQL
and SQLite. A user turn and the assistant reply routinely land in the same
second, so their relative order was whatever the storage engine returned.
The client rebuilds the conversation tree from parent_id, so a child ahead
of its parent corrupts the thread.
Adds an id tiebreaker for a deterministic database order, then a stable
topological pass that guarantees parents precede children while preserving
sibling order. Dangling parent references are treated as roots and cycles
are appended, so no message is ever dropped.
0042_snapshot.json spelled one table's check-constraint key
`checkConstraints` instead of `checkConstraint`. drizzle-kit rejects the
whole folder over it and exits 0 with only a printed message, so
`migration:mysql:generate` has silently produced nothing since #6192.
Every mysql migration authored since then was therefore hand-written with
no snapshot, including 0044 and 0045. Without those snapshots the next
generate diffs against 0043 and re-emits the assistant tables.
Adds the two missing snapshots and a test covering the invariants: journal
and .sql files agree both ways, every entry has a snapshot, indexes are
gap-free, and snapshots agree on the key spelling. The same test would have
caught the v1.70.0 release that shipped 0042_add_widget_secret.sql without
a journal entry, leaving upgraded MySQL instances with no widget_secret
table.
MySQL caps `text` at 65,535 bytes. A single base64 image attachment is
allowed up to ~1.34MB by the chat route, so appending such a message fails
with ER_DATA_TOO_LONG under the default strict mode. SQLite and PostgreSQL
are unaffected because their text types are effectively unbounded.
`mediumtext` holds 16MB, comfortably above the 2MB request cap.
The migration keeps the parenthesised default expression that every other
text default in this folder uses, because MySQL rejects a literal default
on TEXT columns.