Promote chat-workflow cutover stack to main

Merged
SW
5mo ago
+1848-485

Promotes the chat-workflow cutover stack from test to main. This is the api half of the recoupable/chat#1747 bundle — pairs with recoupable/chat#TBD (the chat-side test→main PR).

What this ships

13 PRs since the original Phase 2 work began:

PRWhat
#562feat(api): migrate /api/sessions/[sessionId]/chats/[chatId] from open-agents
#578feat(sessions): enhance session patching with sandbox state management
#603feat(chat-workflow): persist assistant message per step
#614feat(chat-workflow): auto-commit + push after natural finish
#618feat(sessions): ensure personal repo on POST /api/sessions
#620feat(sessions): replace body cloneUrl+branch with organizationId
#623feat(backfill): Phase 2 rooms→sessions/chats/chat_messages script
#624feat: migrate POST /api/sessions/{sid}/chats/{cid}/read (workflow read receipts)
#626feat: migrate GET /api/chats to session-scoped shape (matches docs#227)
#627fix(backfill): store full UIMessage in chat_messages.parts
#628feat(sessions): accept artistId on POST /api/sessions
#629feat(backfill): include artist_id in session migration (straggler-aware)
#630feat(chats): exclude archived sessions from GET /api/chats

23 commits ahead of main, 0 behind.

Wire-contract verification

All new/changed endpoints match their merged docs counterparts (recoupable/docs#227, docs#228) — verified live on preview deployments and on test-recoup-api.vercel.app.

  • GET /api/chats returns {id, title, accountId, sessionId, artistId, updatedAt} per row, no extras, no missing fields. Archived sessions excluded.
  • POST /api/sessions accepts optional artistId; persists on sessions.artist_id.
  • GET /api/sessions/{sid}/chats/{cid} returns full message history from chat_messages.

Data state in prod

  • Phase 2 backfill: 23,252 rooms migrated, 46,212 well-formed memories → chat_messages.
  • Straggler backfill ran via SQL today: 6 additional rooms migrated, 16 messages, all artist_ids carried through (api#629).
  • 347 deleted-account rooms intentionally unmigrated.
  • sessions.artist_id populated for 17,991 of 17,991 rooms with an artist (100%).

Known accepted regressions

Per the chat#1747 issue body — these ship as-is and will be re-addressed post-promotion:

  • No MCP tools (artist data, music industry APIs) inside the workflow sandbox
  • No Composio tools (Sheets, Drive, Docs, TikTok)
  • No artist context in system prompt
  • No automatic chat title generation
  • No send_email tool inside chat
  • No Telegram new-conversation notifications (re-scoped into a future credit-spend digest)
  • Legacy /api/chat endpoint still serves traffic from legacy /chat/[roomId] URLs (intentional dual-write to rooms/memories during the cutover; readers of rooms/memories get cleaned up in Phase 4)

Ordering requirement

Merge api first. Wait for https://recoup-api.vercel.app to deploy. Then merge the chat test→main PR.

The chat side depends on endpoints that only exist in this PR:

  • Canonical reader GET /api/sessions/{sid}/chats/{cid} (#562)
  • Session-scoped chat update PATCH /api/sessions/{sid}/chats/{cid}
  • Session archive PATCH /api/sessions/{sid} { status: "archived" } (#578)
  • New GET /api/chats response shape + artist_account_id filter (#626, #630)
  • artistId on POST /api/sessions (#628)

If chat promotes first, every new chat 404s or hits the wrong shape on prod api.

Rollback plan

Revert the merge commit. No schema rollback needed — database#27 (sessions.artist_id column + inline backfill) is forward-compatible; legacy code paths still work with the column present-but-unused.

Test plan

  • CI green on the merge commit
  • curl https://recoup-api.vercel.app/api/chats -H "x-api-key: ..." returns the session-scoped shape (no account_id, topic, updated_at legacy fields; has accountId, sessionId, artistId, updatedAt)
  • Spot-check: archive a session via PATCH /api/sessions/{sid} {"status":"archived"} and confirm its chats drop from GET /api/chats
  • Then proceed to merge the chat test→main PR

Summary by cubic

Promotes the chat‑workflow cutover stack to main, delivering session‑scoped chats, read receipts, artist‑aware sessions, and the Phase 2 backfill. This is the API half of recoupable/chat#1747 — merge this first to unblock the chat test→main cutover.

  • New Features

    • Session‑scoped chats: GET /api/chats joins sessions and returns { id, title, accountId, sessionId, artistId, updatedAt }; excludes archived sessions; supports artist filter; admin scope fixed for Bearer tokens.
    • Session chats: GET/PATCH/DELETE /api/sessions/{sid}/chats/{cid} plus POST /api/sessions/{sid}/chats/{cid}/read for read receipts.
    • Sessions create: POST /api/sessions accepts organizationId and optional artistId, auto‑provisions the workspace repo, and returns artistId.
    • Workflow reliability: persist assistant messages per step, auto‑commit + push on natural finish, and atomic credit deduction per turn.
    • Backfill: idempotent rooms→sessions/chats/chat_messages script with pagination and batched writes.
  • Migration

    • Merge order: merge API first, wait for https://recoup-api.vercel.app to deploy, then merge the chat test→main PR.
    • Smoke checks: GET /api/chats returns the new shape; archiving a session removes its chats from the list.
    • Rollback: revert the merge commit (schema is forward‑compatible).