MigrateFromJSON previously called AddFullMessage in a loop, then
renamed the .json file to .json.migrated. If the process crashed
after appending some messages but before the rename, a retry would
re-read the same .json and append all messages again — duplicating
whatever was written before the crash.
Switch to SetHistory which atomically replaces the session contents.
A retry after crash overwrites the partial data instead of appending.
Read existing sessions/*.json files, convert to JSONL format, and
rename originals to .json.migrated as backup. The migration is
idempotent — second runs skip already-migrated files.
Session keys are read from JSON content (not filenames) so that
sanitized names like telegram_123 correctly map back to telegram:123.