Hotfix — prod migrations + chat assistant persistence + chat truncation
1. POST /api/bots/:id/strategy 500 (Change Strategy)
Root cause: The actual prod Neon database (ep-patient-glade-akbt9n8k,
configured as the DATABASE_URL Cloudflare secret on the quantago-api
worker) was missing the bot_strategies table and bots.feed_provider
column. Earlier migration runs targeted a stale Neon endpoint
(ep-gentle-bar-a4xaaekv) that the root .env pointed at, but the worker
itself reads a different secret value.
Fix:
- Applied
0013_bot_strategies.sqland0014_bot_feed_provider.sqlto the real prod DB. - Backfilled a
bot_strategiesrow for every existing bot so the resolver finds an active version on first read. - Updated root
.envto point at the actual prod endpoint so futuremigrate-neon.shruns land on the right DB.
2. AI assistant responses not persisted
Root cause: INSERT INTO bot_chat_messages (... tool_calls ...) passed
JSON.stringify(toolTimeline) as a text parameter into a jsonb column
without an explicit ::jsonb cast. Postgres has no implicit text→jsonb
cast, so every assistant insert silently failed (the try/catch swallowed
the error). User turns persisted (no jsonb columns), so reload showed only
user messages.
Fix: Add the ::jsonb cast back and store null (not the string
"null") when there are no tool calls.
const toolCallsJson = toolTimeline.length > 0 ? JSON.stringify(toolTimeline) : null;
await sql`
INSERT INTO bot_chat_messages (...)
VALUES (..., ${toolCallsJson}::jsonb, ${model}, 'done')
`;
3 & 4. Streaming + truncation
Root cause: max_completion_tokens: 2048 clipped longer answers
mid-sentence; combined with the OpenAI auto-fallback warning when
gpt-5-mini was rejected this also masked the "no streaming" complaint
because chunks arrived all at once after the API errored out.
Fix: Bump cap to 8192, keep max_completion_tokens only (the canonical
param across all current OpenAI chat models). The Hono streamSSE writer
already flushes per writeSSE, so once the upstream stream is healthy the
deltas reach the client incrementally.
5. Match SaaS Stack chat bubble + input styles
Status: Deferred to follow-up. The current StreamingChatPanel
(packages/chat-ui) is functional but visually distinct from the
saas-stack ChatInput / ChatMessage components (~1000 LOC, with
framer-motion, multi-block hydration, inline tool cards, choice cards,
etc.). Porting that UX cleanly is a dedicated task — tracked as a
follow-up; this hotfix focuses on the data-loss / functionality bugs
above.