3 Commits

Author SHA1 Message Date
Ryan Chen 746aaa4844 Index conversation, message, memory and artifact foreign keys
Postgres had only primary keys on these tables, so loading a
conversation, listing conversations, checking for a first message on
every send, and fetching memories/artifacts were sequential scans.
Migration generated with aerich; index-only apart from the no-op JSONB
re-casts aerich emits on every run (as in migrations 16 and 18), which
were checked not to rewrite tables. Upgrade and downgrade verified on a
throwaway pgvector database.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:57:35 -04:00
Ryan Chen 1c1ae9f158 Validate artifact ids before querying; match artifacts by str id
asyncpg raises OperationalError (not ValueError) on malformed UUIDs, so
bad artifact ids now 404 and a bad conversation_id 400s before any query.
get_conversation keys artifacts by str(message_id) so matching doesn't
depend on the driver's UUID types.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:56:26 -04:00
Ryan Chen 0cf6229441 Add Artifact model and owner-scoped artifacts API
GET /api/artifacts?conversation_id= lists ArtifactRefs without data;
GET /api/artifacts/<id> returns the full artifact. Both 404 for other
users. create_artifact_from_output persists ToolArtifact dicts and drops
ones over 256 KB serialised.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:53:22 -04:00