Skip to content

Commit 47bcaeb

Browse files
authored
Merge pull request #750 from finitecomputer/claude/session-archive-hermes
sessions: Hermes' own state.db as a source for `fragment session import`
2 parents 9ef2dae + 49f93f9 commit 47bcaeb

9 files changed

Lines changed: 1494 additions & 12 deletions

File tree

‎Cargo.lock‎

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎cli/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ ignore = "=0.4.25"
3434
notify = "=8.2.0"
3535
notify-debouncer-full = "=0.7.0"
3636
fs2 = "=0.4.3"
37+
# Hermes' session database (`fragment session import`), read-only; the
38+
# bundled SQLite, as crates/core's host side pins it
39+
rusqlite = { version = "0.40", default-features = false, features = ["bundled"] }
3740
tungstenite = { version = "=0.29.0", features = ["rustls-tls-webpki-roots", "rustls-tls-native-roots"] }
3841

3942

‎cli/GUIDE.md‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -858,16 +858,23 @@ The conversations you had with an agent somewhere else, kept in a
858858
private fragment of yours (kind `sessions`, titled Session Archive, made
859859
the first time you import): one file a conversation, under `sessions/`,
860860
and one index a kind, under `index/`, newest first. Bring them in from
861-
the old Finite's export (its `chats/`, or the folder holding it):
861+
the old Finite's export (its `chats/`, or the folder holding it), or
862+
from Hermes' own `state.db` (or the Hermes home holding it), read-only:
862863
863864
```
864865
fragment session import ~/finite-import/export # the old Finite's export, unpacked
865-
fragment session import ~/finite-import/export --kind chat # only chats (also: cron, subagent)
866+
fragment session import ~/.hermes # a Hermes home, or its state.db
867+
fragment session import ~/.hermes --kind chat # only chats (also: cron, subagent)
866868
```
867869
870+
A `state.db` copied from elsewhere needs its `state.db-wal` beside it, or
871+
its newest messages are not in it. On an agent's computer here, its own
872+
Hermes databases are refused: their conversations are your chats here
873+
already.
874+
868875
Each conversation is kept by its own id, so importing again adds
869-
nothing twice, and a newer copy of one (a later export) replaces the
870-
older; an older copy never does. It says what it added, updated and
876+
nothing twice, and a newer copy of one (a later export, the same chats
877+
from Hermes' database) replaces the older; an older copy never does. It says what it added, updated and
871878
already had, and what it left out and why: at most 18,000 conversations
872879
and 1 GiB an archive (an import past either adds nothing), 8 MiB a
873880
conversation. A tool's output and an agent's reasoning are cut to 2,000

‎cli/src/session/hermes-v0.21.7.sql‎

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
CREATE TABLE sessions (
2+
id TEXT PRIMARY KEY,
3+
source TEXT NOT NULL,
4+
created_source TEXT,
5+
user_id TEXT,
6+
session_key TEXT,
7+
chat_id TEXT,
8+
chat_type TEXT,
9+
thread_id TEXT,
10+
display_name TEXT,
11+
origin_json TEXT,
12+
expiry_finalized INTEGER DEFAULT 0,
13+
model TEXT,
14+
model_config TEXT,
15+
system_prompt TEXT,
16+
system_prompt_hash TEXT,
17+
parent_session_id TEXT,
18+
started_at REAL NOT NULL,
19+
ended_at REAL,
20+
end_reason TEXT,
21+
message_count INTEGER DEFAULT 0,
22+
tool_call_count INTEGER DEFAULT 0,
23+
input_tokens INTEGER DEFAULT 0,
24+
output_tokens INTEGER DEFAULT 0,
25+
cache_read_tokens INTEGER DEFAULT 0,
26+
cache_write_tokens INTEGER DEFAULT 0,
27+
reasoning_tokens INTEGER DEFAULT 0,
28+
cwd TEXT,
29+
git_branch TEXT,
30+
git_repo_root TEXT,
31+
git_metadata_generation INTEGER NOT NULL DEFAULT 0,
32+
billing_provider TEXT,
33+
billing_base_url TEXT,
34+
billing_mode TEXT,
35+
estimated_cost_usd REAL,
36+
actual_cost_usd REAL,
37+
cost_status TEXT,
38+
cost_source TEXT,
39+
pricing_version TEXT,
40+
title TEXT,
41+
title_source TEXT,
42+
last_activity_at REAL,
43+
last_activity_description TEXT,
44+
last_activity_provenance TEXT,
45+
api_call_count INTEGER DEFAULT 0,
46+
handoff_state TEXT,
47+
handoff_platform TEXT,
48+
handoff_error TEXT,
49+
compression_failure_cooldown_until REAL,
50+
compression_failure_error TEXT,
51+
compression_fallback_streak INTEGER NOT NULL DEFAULT 0,
52+
compression_ineffective_count INTEGER NOT NULL DEFAULT 0,
53+
compression_recovery_deadline REAL,
54+
compression_overload_streak INTEGER NOT NULL DEFAULT 0,
55+
profile_name TEXT,
56+
transport_profile TEXT,
57+
rewind_count INTEGER NOT NULL DEFAULT 0,
58+
archived INTEGER NOT NULL DEFAULT 0,
59+
auto_archived INTEGER NOT NULL DEFAULT 0,
60+
pinned INTEGER NOT NULL DEFAULT 0,
61+
hidden INTEGER NOT NULL DEFAULT 0,
62+
last_read_at REAL,
63+
tool_names TEXT,
64+
FOREIGN KEY (parent_session_id) REFERENCES sessions(id),
65+
FOREIGN KEY (system_prompt_hash) REFERENCES system_prompts(hash)
66+
);
67+
CREATE TABLE messages (
68+
id INTEGER PRIMARY KEY AUTOINCREMENT,
69+
session_id TEXT NOT NULL REFERENCES sessions(id),
70+
role TEXT NOT NULL,
71+
content TEXT,
72+
tool_call_id TEXT,
73+
tool_calls TEXT,
74+
tool_name TEXT,
75+
effect_disposition TEXT,
76+
timestamp REAL NOT NULL,
77+
token_count INTEGER,
78+
finish_reason TEXT,
79+
reasoning TEXT,
80+
reasoning_content TEXT,
81+
reasoning_details TEXT,
82+
codex_reasoning_items TEXT,
83+
codex_message_items TEXT,
84+
platform_message_id TEXT,
85+
observed INTEGER DEFAULT 0,
86+
_compressed_summary INTEGER NOT NULL DEFAULT 0,
87+
active INTEGER NOT NULL DEFAULT 1,
88+
compacted INTEGER NOT NULL DEFAULT 0,
89+
api_content TEXT,
90+
display_kind TEXT,
91+
display_metadata TEXT,
92+
display_identity BLOB,
93+
display_order INTEGER,
94+
message_uid TEXT,
95+
absorbed_message_uids TEXT,
96+
tool_call_uids TEXT,
97+
tool_call_uid TEXT
98+
);
99+
INSERT INTO sessions VALUES('20261001_090000_root01','telegram','telegram',NULL,'tg:1',NULL,NULL,NULL,'Ann',NULL,0,'m1',NULL,NULL,NULL,NULL,1793399746.8818233,1793399746.924113,'compression',5,1,0,0,0,0,0,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'Beans','user',NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,0,0,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL);
100+
INSERT INTO sessions VALUES('20261001_091000_cont01','telegram','telegram',NULL,'tg:1',NULL,NULL,NULL,'Ann',NULL,0,'m2',NULL,NULL,NULL,'20261001_090000_root01',1793399746.9262304,NULL,NULL,4,0,0,0,0,0,0,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,0,0,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL);
101+
INSERT INTO sessions VALUES('20261001_100000_branch','cli','cli',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,'{"_branched_from": "20261001_090000_root01"}',NULL,NULL,'20261001_090000_root01',1793399746.9374292,NULL,NULL,1,0,0,0,0,0,0,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,0,0,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL);
102+
INSERT INTO sessions VALUES('20261002_090000_reset1','telegram','telegram',NULL,'tg:1',NULL,NULL,NULL,NULL,NULL,0,NULL,'{"_reset_from": "20261001_091000_cont01"}',NULL,NULL,'20261001_091000_cont01',1793399746.9418957,1793399746.946435,'compression',1,0,0,0,0,0,0,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,0,0,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL);
103+
INSERT INTO sessions VALUES('20261002_093000_reset2','telegram','telegram',NULL,'tg:1',NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,'20261002_090000_reset1',1793399746.9490545,NULL,NULL,1,0,0,0,0,0,0,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,0,0,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL);
104+
INSERT INTO sessions VALUES('cron_digest_20261003_0600','cron','cron',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,1793399746.9536676,NULL,NULL,1,0,0,0,0,0,0,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,0,0,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL);
105+
INSERT INTO sessions VALUES('20261001_091500_dlg001','cli','cli',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,'{"_delegate_from": "20261001_091000_cont01"}',NULL,NULL,'20261001_091000_cont01',1793399746.9583423,NULL,NULL,1,0,0,0,0,0,0,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,0,0,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL);
106+
INSERT INTO sessions VALUES('20261001_092000_dlg002','cli','cli',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,'{"_delegate_from": "20261001_091000_cont01"}',NULL,NULL,NULL,1793399746.96299,NULL,NULL,1,0,0,0,0,0,0,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,0,0,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL);
107+
INSERT INTO messages VALUES(1,'20261001_090000_root01','user','plant beans?',NULL,NULL,NULL,NULL,1790845200.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'04d690c92235188eb8c56dcdc5f53d80fe89a3fb2e3c33bb0366b57d3ef60c04',1,'707f051322ac446b85896f05b0679b39',NULL,NULL,NULL);
108+
INSERT INTO messages VALUES(2,'20261001_090000_root01','assistant',NULL,NULL,'[{"id": "call_1", "type": "function", "function": {"name": "web_search", "arguments": "{\"q\": \"beans\"}"}}]',NULL,NULL,1790845201.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'222692f2ea5313cadd497e8ec94d6262159fa0ea4baa5311bea52dd1199e1d36',2,'4e61496094244e579163b38141a12161',NULL,'{"call_1": "1af303be9f174ea58ad2f0c6f73f3e1c"}',NULL);
109+
INSERT INTO messages VALUES(3,'20261001_090000_root01','tool','beans like warm soil','call_1',NULL,'web_search',NULL,1790845202.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'28e604c3929ebd352b74c365c2388b937d234c27f23cb41e1cb99c56bb14e071',3,'a22b390e7e1048499eda9e44e92cfe53',NULL,NULL,NULL);
110+
INSERT INTO messages VALUES(4,'20261001_090000_root01','assistant','In spring, once the soil is warm.',NULL,NULL,NULL,NULL,1790845203.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'33fe6b65b5631452300ced9a6fdc3941032aad34c4e638f95fca88badab22634',4,'2b64eca7445847e18707ae75040d400e',NULL,NULL,NULL);
111+
INSERT INTO messages VALUES(5,'20261001_090000_root01','user','' || char(0) || 'json:[{"type": "text", "text": "here is my plot"}, {"type": "image_url", "image_url": {"url": "data:image/png;base64,AAAA"}}]',NULL,NULL,NULL,NULL,1790845204.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'90d2bef20830b1b4d7c331c3906a85f87d5b9f66a638d3edff89d55396bc619e',5,'19f80a759d904783a315bc0940b92ea4',NULL,NULL,NULL);
112+
INSERT INTO messages VALUES(6,'20261001_091000_cont01','user','Summary: we talked about beans.
113+
--- END OF CONTEXT SUMMARY — respond to the message below, not the summary above ---
114+
and peas?',NULL,NULL,NULL,NULL,1790845800.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1,1,0,NULL,'hidden',NULL,X'4e8df5c654d8377143b485e082698470fb05d8fb2d414168625f44e326fb7fed',6,'0accbc8a08af4481a1df34cc30745c8e',NULL,NULL,NULL);
115+
INSERT INTO messages VALUES(7,'20261001_091000_cont01','assistant','In spring, once the soil is warm.',NULL,NULL,NULL,NULL,1790845203.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'33fe6b65b5631452300ced9a6fdc3941032aad34c4e638f95fca88badab22634',7,'10671086a4054f0c9afe468dcc331739',NULL,NULL,NULL);
116+
INSERT INTO messages VALUES(8,'20261001_091000_cont01','assistant','Peas too.',NULL,NULL,NULL,NULL,1790845801.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'8cd470f11ecdd06a37546e99a9afc5deedda91f7e2870c5fb21fcc90234ce1a8',8,'7b61451217664276adc0c0b4140c0d69',NULL,NULL,NULL);
117+
INSERT INTO messages VALUES(9,'20261001_091000_cont01','user','for the model only',NULL,NULL,NULL,NULL,1790845802.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,'{"model_only": true}',X'1b27ae7aa3a6ef4ccb00d714a6f54643646feeb378b454d835726280cc2994a5',9,'bc8cb2dc6de74735b9f9cc27b20d2b4e',NULL,NULL,NULL);
118+
INSERT INTO messages VALUES(10,'20261001_100000_branch','user','what about corn?',NULL,NULL,NULL,NULL,1790848800.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'7c5ce8cab080c26a063bed471c5e337916cc33be2b70d729fbc5fb0ef67bc8bb',10,'498c9232b4234ecaae3e3454872b05e9',NULL,NULL,NULL);
119+
INSERT INTO messages VALUES(11,'20261002_090000_reset1','user','new day, new plan',NULL,NULL,NULL,NULL,1790931600.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'67f6e20ef6def8bfd1b5b44f644f39af5d9332c3699a09fd23261d3f0b5a3ea2',11,'f9203ac148ab47329bea8bf55b51c168',NULL,NULL,NULL);
120+
INSERT INTO messages VALUES(12,'20261002_093000_reset2','assistant','here is the plan',NULL,NULL,NULL,NULL,1790933400.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'5d0efb5bfed69a00fc19edefca838aac2abd6a355d22fec68922da6f22aee822',12,'2bc3ec8b7db24967afd3bb09da24a4ed',NULL,NULL,NULL);
121+
INSERT INTO messages VALUES(13,'cron_digest_20261003_0600','user','the morning digest',NULL,NULL,NULL,NULL,1791018000.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'2c2f98475fa13242a73cab8c007bc468032a22526df661fc16cc3e367d3a1826',13,'9fecfd69311b40f0bb42ebca6039a639',NULL,NULL,NULL);
122+
INSERT INTO messages VALUES(14,'20261001_091500_dlg001','user','look up pea varieties',NULL,NULL,NULL,NULL,1790846100.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'efc03e9d88404f886d599cf09b109918ea056b44b018adffcba5721fe95cc258',14,'9ee1fa5ea19442cd9ec18ff283611663',NULL,NULL,NULL);
123+
INSERT INTO messages VALUES(15,'20261001_092000_dlg002','user','a pruned side task',NULL,NULL,NULL,NULL,1790846400.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,1,0,NULL,NULL,NULL,X'fa24472750f9747c90ab1136b6aed78ac9c111f752175933485eeb87fe6f2f7a',15,'8b8d5734d50246c69658076a994c1ad9',NULL,NULL,NULL);

0 commit comments

Comments
 (0)