update: SessionId / SessionStart / SessionOrigin 等を Segment 系名称へ

- Type/Function/Variantを Segment* 系へ統一
  - SessionId/SessionStart/SessionOrigin/SessionStartState/SessionState/SessionLogSink/SessionLockInfo
  - new_session_id / session_id / create_session* / list_sessions / lookup_session / update_session / find_by_session
  - protocol Event::SessionRotated → SegmentRotated、CompactDone.new_session_id → new_segment_id
- Module: session_log → segment_log / session → segment (file mv 含む)
  pod 側の session_log_sink → segment_log_sink も同様
- crate 名 (session-store)、CLI flag (--session)、ResumeWithSession (CLI tied) は据え置き
- session-tests/session_metrics_test 等の Store impl も追従
This commit is contained in:
2026-05-20 05:06:04 +09:00
parent de549812ab
commit 22f5d02385
55 changed files with 611 additions and 610 deletions
+17 -17
View File
@@ -1,15 +1,15 @@
use llm_worker::WorkerResult;
use llm_worker::llm_client::types::{Item, RequestConfig};
use session_store::{FsStore, LogEntry, Store, TraceEntry, collect_state, new_session_id};
use session_store::{FsStore, LogEntry, Store, TraceEntry, collect_state, new_segment_id};
#[test]
fn round_trip_write_and_read() {
let dir = tempfile::tempdir().unwrap();
let store = FsStore::new(dir.path()).unwrap();
let id = new_session_id();
let id = new_segment_id();
let entries = vec![
LogEntry::SessionStart {
LogEntry::SegmentStart {
ts: 1000,
system_prompt: Some("You are helpful.".into()),
config: RequestConfig::default().with_max_tokens(1024),
@@ -56,9 +56,9 @@ fn round_trip_write_and_read() {
fn create_session_writes_all_entries() {
let dir = tempfile::tempdir().unwrap();
let store = FsStore::new(dir.path()).unwrap();
let id = new_session_id();
let id = new_segment_id();
let entries = [LogEntry::SessionStart {
let entries = [LogEntry::SegmentStart {
ts: 1000,
system_prompt: None,
config: RequestConfig::default(),
@@ -70,7 +70,7 @@ fn create_session_writes_all_entries() {
compacted_from: None,
}];
store.create_session(id, &entries).unwrap();
store.create_segment(id, &entries).unwrap();
let read_back = store.read_all(id).unwrap();
assert_eq!(read_back.len(), 1);
@@ -83,12 +83,12 @@ fn list_sessions_returns_newest_first() {
let dir = tempfile::tempdir().unwrap();
let store = FsStore::new(dir.path()).unwrap();
let id1 = new_session_id();
let id1 = new_segment_id();
// Small delay to ensure different UUID v7 timestamps
std::thread::sleep(std::time::Duration::from_millis(2));
let id2 = new_session_id();
let id2 = new_segment_id();
let entry = LogEntry::SessionStart {
let entry = LogEntry::SegmentStart {
ts: 1000,
system_prompt: None,
config: RequestConfig::default(),
@@ -100,7 +100,7 @@ fn list_sessions_returns_newest_first() {
store.append(id1, &entry).unwrap();
store.append(id2, &entry).unwrap();
let sessions = store.list_sessions().unwrap();
let sessions = store.list_segments().unwrap();
assert_eq!(sessions.len(), 2);
assert_eq!(sessions[0], id2); // newest first
assert_eq!(sessions[1], id1);
@@ -110,14 +110,14 @@ fn list_sessions_returns_newest_first() {
fn exists_returns_correct_state() {
let dir = tempfile::tempdir().unwrap();
let store = FsStore::new(dir.path()).unwrap();
let id = new_session_id();
let id = new_segment_id();
assert!(!store.exists(id).unwrap());
store
.append(
id,
&LogEntry::SessionStart {
&LogEntry::SegmentStart {
ts: 1000,
system_prompt: None,
config: RequestConfig::default(),
@@ -135,7 +135,7 @@ fn exists_returns_correct_state() {
fn not_found_error_for_missing_session() {
let dir = tempfile::tempdir().unwrap();
let store = FsStore::new(dir.path()).unwrap();
let id = new_session_id();
let id = new_segment_id();
let result = store.read_all(id);
assert!(result.is_err());
@@ -145,12 +145,12 @@ fn not_found_error_for_missing_session() {
fn trace_entries_in_separate_file() {
let dir = tempfile::tempdir().unwrap();
let store = FsStore::new(dir.path()).unwrap();
let id = new_session_id();
let id = new_segment_id();
store
.append(
id,
&LogEntry::SessionStart {
&LogEntry::SegmentStart {
ts: 1000,
system_prompt: None,
config: RequestConfig::default(),
@@ -183,10 +183,10 @@ fn trace_entries_in_separate_file() {
fn read_entry_count_matches_append_tally() {
let dir = tempfile::tempdir().unwrap();
let store = FsStore::new(dir.path()).unwrap();
let id = new_session_id();
let id = new_segment_id();
let entries = [
LogEntry::SessionStart {
LogEntry::SegmentStart {
ts: 1000,
system_prompt: None,
config: RequestConfig::default(),
+37 -37
View File
@@ -9,7 +9,7 @@ use llm_worker::interceptor::{Interceptor, TurnEndAction};
use llm_worker::llm_client::event::{Event, ResponseStatus, StatusEvent};
use llm_worker::llm_client::types::{Item, RequestConfig};
use llm_worker::tool::{Tool, ToolDefinition, ToolError, ToolMeta, ToolOutput};
use session_store::{FsStore, LogEntry, SessionStartState, Store, collect_state};
use session_store::{FsStore, LogEntry, SegmentStartState, Store, collect_state};
// =============================================================================
// Helpers
@@ -95,13 +95,13 @@ fn make_store() -> (tempfile::TempDir, FsStore) {
async fn run_and_persist(
worker: Worker<MockLlmClient>,
store: &FsStore,
session_id: session_store::SessionId,
segment_id: session_store::SegmentId,
input: &str,
) -> (Worker<MockLlmClient>, llm_worker::WorkerResult) {
// Mirror Pod's run-entry contract: log the user input as segments
// before the worker pushes its flattened user_message; save_delta
// skips the resulting user_message item to avoid double-write.
session_store::save_user_input(store, session_id, vec![protocol::Segment::text(input)])
session_store::save_user_input(store, segment_id, vec![protocol::Segment::text(input)])
.unwrap();
let history_before = worker.history().len();
@@ -111,14 +111,14 @@ async fn run_and_persist(
let worker = locked.unlock();
let new_items = &worker.history()[history_before..];
session_store::save_delta(store, session_id, new_items).unwrap();
session_store::save_turn_end(store, session_id, worker.turn_count()).unwrap();
session_store::save_delta(store, segment_id, new_items).unwrap();
session_store::save_turn_end(store, segment_id, worker.turn_count()).unwrap();
match &result {
Ok(r) => {
session_store::save_run_completed(
store,
session_id,
segment_id,
r.clone(),
worker.last_run_interrupted(),
)
@@ -127,7 +127,7 @@ async fn run_and_persist(
Err(e) => {
session_store::save_run_errored(
store,
session_id,
segment_id,
e.to_string(),
worker.last_run_interrupted(),
)
@@ -149,9 +149,9 @@ async fn session_run_logs_entries() {
let client = MockLlmClient::new(simple_text_events());
let worker = Worker::new(client);
let sid = session_store::create_session(
let sid = session_store::create_segment(
&store,
SessionStartState {
SegmentStartState {
system_prompt: worker.get_system_prompt(),
config: worker.request_config(),
history: worker.history(),
@@ -164,15 +164,15 @@ async fn session_run_logs_entries() {
let entries = store.read_all(sid).unwrap();
// SessionStart, UserInput, AssistantItems, TurnEnd, RunCompleted (at minimum)
// SegmentStart, UserInput, AssistantItems, TurnEnd, RunCompleted (at minimum)
assert!(
entries.len() >= 4,
"expected at least 4 entries, got {}",
entries.len()
);
// First entry is SessionStart
assert!(matches!(&entries[0], LogEntry::SessionStart { .. }));
// First entry is SegmentStart
assert!(matches!(&entries[0], LogEntry::SegmentStart { .. }));
// Has a RunCompleted with Finished
let has_finished = entries.iter().any(|e| {
@@ -194,9 +194,9 @@ async fn session_restore_round_trip() {
let mut worker = Worker::new(client);
worker.set_system_prompt("You are helpful.");
let sid = session_store::create_session(
let sid = session_store::create_segment(
&store,
SessionStartState {
SegmentStartState {
system_prompt: worker.get_system_prompt(),
config: worker.request_config(),
history: worker.history(),
@@ -225,9 +225,9 @@ async fn session_run_with_tool_call() {
let mut worker = Worker::new(client);
worker.register_tool(weather_tool_definition());
let sid = session_store::create_session(
let sid = session_store::create_segment(
&store,
SessionStartState {
SegmentStartState {
system_prompt: worker.get_system_prompt(),
config: worker.request_config(),
history: worker.history(),
@@ -260,9 +260,9 @@ async fn session_resume_after_pause() {
worker.register_tool(weather_tool_definition());
worker.set_interceptor(PausePolicy);
let sid = session_store::create_session(
let sid = session_store::create_segment(
&store,
SessionStartState {
SegmentStartState {
system_prompt: worker.get_system_prompt(),
config: worker.request_config(),
history: worker.history(),
@@ -298,9 +298,9 @@ async fn session_fork_preserves_state() {
let mut worker = Worker::new(client);
worker.set_system_prompt("System prompt");
let sid = session_store::create_session(
let sid = session_store::create_segment(
&store,
SessionStartState {
SegmentStartState {
system_prompt: worker.get_system_prompt(),
config: worker.request_config(),
history: worker.history(),
@@ -313,7 +313,7 @@ async fn session_fork_preserves_state() {
let original_history_len = worker.history().len();
let fork_id = session_store::fork(
&store,
SessionStartState {
SegmentStartState {
system_prompt: worker.get_system_prompt(),
config: worker.request_config(),
history: worker.history(),
@@ -321,10 +321,10 @@ async fn session_fork_preserves_state() {
)
.unwrap();
// Fork should have a SessionStart with the current history
// Fork should have a SegmentStart with the current history
let fork_entries = store.read_all(fork_id).unwrap();
assert_eq!(fork_entries.len(), 1);
assert!(matches!(&fork_entries[0], LogEntry::SessionStart { .. }));
assert!(matches!(&fork_entries[0], LogEntry::SegmentStart { .. }));
let fork_state = collect_state(&fork_entries);
assert_eq!(fork_state.history.len(), original_history_len);
@@ -337,9 +337,9 @@ async fn session_fork_at_truncates() {
let client = MockLlmClient::new(simple_text_events());
let worker = Worker::new(client);
let sid = session_store::create_session(
let sid = session_store::create_segment(
&store,
SessionStartState {
SegmentStartState {
system_prompt: worker.get_system_prompt(),
config: worker.request_config(),
history: worker.history(),
@@ -356,7 +356,7 @@ async fn session_fork_at_truncates() {
let fork_id = session_store::fork_at(&store, sid, worker.turn_count()).unwrap();
let fork_entries = store.read_all(fork_id).unwrap();
assert_eq!(fork_entries.len(), 1); // Just the new SessionStart
assert_eq!(fork_entries.len(), 1); // Just the new SegmentStart
let fork_state = collect_state(&fork_entries);
// History at fork point should match history right after the TurnEnd in
@@ -375,9 +375,9 @@ async fn session_config_changed_logged() {
let client = MockLlmClient::new(vec![]);
let mut worker = Worker::new(client);
let sid = session_store::create_session(
let sid = session_store::create_segment(
&store,
SessionStartState {
SegmentStartState {
system_prompt: worker.get_system_prompt(),
config: worker.request_config(),
history: worker.history(),
@@ -408,17 +408,17 @@ async fn session_auto_forks_on_conflict() {
let client_a = MockLlmClient::new(simple_text_events());
let worker_a = Worker::new(client_a);
let original_sid = session_store::create_session(
let original_sid = session_store::create_segment(
&store,
SessionStartState {
SegmentStartState {
system_prompt: worker_a.get_system_prompt(),
config: worker_a.request_config(),
history: worker_a.history(),
},
)
.unwrap();
let mut session_id = original_sid;
// Writer tracked: just the SessionStart we wrote.
let mut segment_id = original_sid;
// Writer tracked: just the SegmentStart we wrote.
let mut entries_written: usize = 1;
// Simulate another Pod writing to the same session behind our back.
@@ -431,9 +431,9 @@ async fn session_auto_forks_on_conflict() {
// Now the on-disk count exceeds our tally — ensure_head_or_fork should auto-fork.
session_store::ensure_head_or_fork(
&store,
&mut session_id,
&mut segment_id,
&mut entries_written,
SessionStartState {
SegmentStartState {
system_prompt: worker_a.get_system_prompt(),
config: worker_a.request_config(),
history: worker_a.history(),
@@ -441,11 +441,11 @@ async fn session_auto_forks_on_conflict() {
)
.unwrap();
// session_id should now be different
assert_ne!(session_id, original_sid);
// segment_id should now be different
assert_ne!(segment_id, original_sid);
// The fork session should exist and have entries
let fork_entries = store.read_all(session_id).unwrap();
let fork_entries = store.read_all(segment_id).unwrap();
assert!(!fork_entries.is_empty());
// Original session should still have the interloper entry