Eai. System
(eai v1.0.2)
Copy Markdown
Step 4 — whole-runtime snapshot and restore.
Owns the "lock + serialize" logic for the global export/import tools
(Eai.Tool.ExportGlobalContext, Eai.Tool.ReplaceGlobalContext). The
per-session variants (export_chat_session_context,
replace_chat_session_context) are still served directly by
Eai.Chat.export_history/2 and Eai.Chat.replace_history/3.
This module does NOT add a force parameter, does NOT install any auto-snapshot trigger, and does NOT add cron / periodic jobs. The caller (an LLM tool call or a human) is the only thing that can invoke it.
Summary
Functions
Block until every chat session and PTY session is idle, then return
:ok. If the deadline expires first, return {:error, :timeout}.
Restore the entire Eai runtime state from a gzip file written by
snapshot_to_gzip/1.
Snapshot the entire Eai runtime state to a gzip file.
Types
@type await_result() :: :ok | {:error, :timeout}
@type restore_info() :: %{ chat_sessions_restored: non_neg_integer(), cache_entries_restored: non_neg_integer() }
@type snapshot_info() :: %{ file: String.t(), chat_session_count: non_neg_integer(), cache_entry_count: non_neg_integer() }
Functions
@spec await_idle(timeout()) :: await_result()
Block until every chat session and PTY session is idle, then return
:ok. If the deadline expires first, return {:error, :timeout}.
Polls every 50ms. After both sides report all-idle
once, sleeps one more 50ms to absorb any in-flight
Task.Supervisor spawn that hasn't appeared in the listing yet, then
returns :ok.
Options
timeout— Max wait in ms. Default:30000.
@spec restore_from_gzip(Path.t()) :: {:ok, restore_info()} | {:error, term()}
Restore the entire Eai runtime state from a gzip file written by
snapshot_to_gzip/1.
Awaits system-idle first. Reads the file, gunzips, binary_to_terms.
Validates the version field (must equal 1; an
unknown version is an error rather than a silent compat fall-back).
For every chat_session in the snapshot, writes its gzip blob to a
temp file, calls Eai.Chat.replace_history/3 with format: "converse",
then deletes the temp file. For every cache_entry, calls
Eai.Naming.cache().put/2. Cache restore is a MERGE — keys that
exist in the runtime but not in the snapshot are NOT deleted.
Options
file_path— Source.gzpath.
Returns
{:ok, %{chat_sessions_restored, cache_entries_restored}}on success{:error, :timeout}ifawait_idle/1times out{:error, term}for any other failure
@spec snapshot_to_gzip(Path.t()) :: {:ok, snapshot_info()} | {:error, term()}
Snapshot the entire Eai runtime state to a gzip file.
Awaits system-idle first. Then, for every chat session, calls
Eai.Chat.snapshot_messages_bytes/1 to get the gzip blob of its
messages in the exact same format as the per-session
export_chat_session_context tool. Iterates the Nebulex cache
(skipping chat_session:* and chat_history:* keys as a defensive
measure — those names are reserved for future per-session cache
storage) and captures every other entry. Writes the top-level
%{version, exported_at, chat_sessions, cache_entries} map as a
gzipped :erlang.term_to_binary/1 to file_path.
Options
file_path— Destination.gzpath.
Returns
{:ok, %{file, chat_session_count, cache_entry_count}}on success{:error, :timeout}ifawait_idle/1times out{:error, term}for any other failure