Module-owned versioned migrations for phoenix_kit_agent — the protocol core's
mix phoenix_kit.update discovers through PhoenixKitAgent.migration_module/0
(current_version/0, migrated_version_runtime/1, up/1, down/1). Same
shape as PhoenixKitDashboards.Migrations: two version readers, up/1
re-reading the version before it changes anything, the SQL kept as data
(up_statements/2, down_statements/2).
Tables (V1)
phoenix_kit_agent_conversations— a user's chats; the chat list reads them by(user_uuid, status, last_message_at DESC).phoenix_kit_agent_messages— every message of a chat, the tool calls and their outcomes included;ai_request_uuidlinks thephoenix_kit_ai_requestsrow of a model call.phoenix_kit_agent_attachments— files attached to a message; the bytes live in Storage (file_uuid).phoenix_kit_agent_user_settings— one row per user,NULLmeaning "the module default"; also the per-user "turn in flight" lock.phoenix_kit_agent_limit_events— one limit notice per user, kind and period.
V2 — the confirmation of a write (spec §5.2, I6)
phoenix_kit_agent_messages.tool_outcomealso takesexpired,changedandfailed(the outcomes of a confirmation card, kept on itsnotice);assistant_message_uuid— on atoolmessage, theassistantmessage whose tool call it answers (the arguments a confirmation is redeemed with). No foreign key: both rows are in the same chat and go with it;confirmation_uuid— the confirmation core holds the write in (PhoenixKit.API.Confirm), on thetoolmessage that asks for it and on thenoticethat says how it ended; partial indexphoenix_kit_agent_messages_confirmation_uuid_index, through which the chat panel finds the cards still waiting. No foreign key: core deletes its rows on its own schedule.
down/1 to V1 drops the two columns and the index, and clears an outcome
V1 cannot hold (the notice stays, without it).
Deleting a user deletes their rows of every table (ON DELETE CASCADE); a
deleted phoenix_kit_ai_requests row, AI endpoint or Storage file leaves the
link NULL and never blocks the delete. Money is in micro-dollars
(*_micro_usd, $1 = 1_000_000); the AI journal keeps dollars
(phoenix_kit_ai_requests.cost), turned into micro-dollars by
PhoenixKitAgent.Config.cost_to_micro/1.
Version marker
COMMENT ON TABLE phoenix_kit_agent_conversations IS 'pk_agent_schema:<N>'.
No table, or one without a pk_agent_schema: comment, reads as version 0.
Idempotency and rollback
Every statement guards itself (IF NOT EXISTS / IF EXISTS), so the chain
can be re-run. These tables belong to this module alone: down/1 to version
0 drops them with every chat, message, attachment link and per-user
setting in them (the Storage files of the attachments stay). Back up the
database first.
Ordering
The foreign keys reach core's phoenix_kit_users, phoenix_kit_files,
phoenix_kit_ai_endpoints and phoenix_kit_ai_requests, so this chain runs
after core's (mix phoenix_kit.update generates the module migrations after
core's own).
Summary
Functions
The version this code expects the schema to be at.
Rolls back to opts[:version] (default 0). Migration context only. To 0 it
drops every table of the module — see the moduledoc.
The SQL down/1 runs, as data. To 0 it drops every table of the module;
to a version still in the chain it undoes every later version (each
statement guards itself) and re-stamps the marker.
The installed version, read inside a migration through Ecto.Migration's
repo(). No rescue: a version that cannot be read aborts the migration.
The installed version, read outside a migration (what mix phoenix_kit.update
calls) through PhoenixKit's configured repo. An invalid prefix raises; a
database that cannot be reached reads as 0, which only costs a redundant
migration file because up/1 re-reads the version before it changes
anything.
Applies the chain up to opts[:version] (default current_version/0).
Migration context only. Re-reads the installed version first: a database
already at (or past) the target is left alone.
The SQL up/1 runs, as data. target is how far to go (default
current_version/0); 0 is nothing. Every version from V1 on is in it:
each statement guards itself, so the versions already applied change
nothing.
The table carrying the pk_agent_schema:<N> marker.
Functions
@spec current_version() :: pos_integer()
The version this code expects the schema to be at.
Rolls back to opts[:version] (default 0). Migration context only. To 0 it
drops every table of the module — see the moduledoc.
@spec down_statements(String.t(), non_neg_integer()) :: [String.t()]
The SQL down/1 runs, as data. To 0 it drops every table of the module;
to a version still in the chain it undoes every later version (each
statement guards itself) and re-stamps the marker.
@spec migrated_version(keyword() | map()) :: non_neg_integer()
The installed version, read inside a migration through Ecto.Migration's
repo(). No rescue: a version that cannot be read aborts the migration.
@spec migrated_version_runtime(keyword() | map()) :: non_neg_integer()
The installed version, read outside a migration (what mix phoenix_kit.update
calls) through PhoenixKit's configured repo. An invalid prefix raises; a
database that cannot be reached reads as 0, which only costs a redundant
migration file because up/1 re-reads the version before it changes
anything.
Applies the chain up to opts[:version] (default current_version/0).
Migration context only. Re-reads the installed version first: a database
already at (or past) the target is left alone.
@spec up_statements(String.t(), non_neg_integer()) :: [String.t()]
The SQL up/1 runs, as data. target is how far to go (default
current_version/0); 0 is nothing. Every version from V1 on is in it:
each statement guards itself, so the versions already applied change
nothing.
@spec version_table() :: String.t()
The table carrying the pk_agent_schema:<N> marker.