repositories / smith
smith
There are many coding harnesses - but this one is fast
owned by admin
smith-core/tests/trace_snapshot.rs
Raw//! The trace of a small session, pinned as a snapshot (`SMH-SPEC-SPEC0001`,
//! Sessions).
//!
//! Session, branch, entry, and message ids and entry timestamps differ every
//! run; they are redacted to placeholders before snapshotting. Call ids are
//! chosen by the test and stay literal.
use serde_json::Value;
use smith::id::ToolCallId;
use smith::message::{Message, Role};
use smith_core::session::{COMPACTION_KIND, EntryContent, EntryKind, Session};
use smith_core::trace::build_trace;
/// One JSON line per record, with every run-specific value replaced.
fn redacted_trace(session: &Session) -> String {
let branch = session.active_branch();
let mut placeholders = vec![
(session.id().to_string(), "<session>".to_string()),
(branch.id().to_string(), "<branch>".to_string()),
];
for (index, entry) in branch.entries().iter().enumerate() {
placeholders.push((entry.id.to_string(), format!("<entry-{index}>")));
if let EntryKind::Message { id, .. } = entry.kind {
placeholders.push((id.to_string(), format!("<message-{index}>")));
}
}
let redact = |text: &str| {
placeholders
.iter()
.fold(text.to_string(), |text, (id, placeholder)| {
text.replace(id, placeholder)
})
};
build_trace(session)
.iter()
.map(|record| {
let mut line = serde_json::to_value(record).unwrap();
if line["timestamp_ms"] != 0 {
line["timestamp_ms"] = Value::from("<timestamp>");
}
redact(&line.to_string())
})
.collect::<Vec<_>>()
.join("\n")
}
#[test]
fn trace_of_message_tool_round_trip_and_compaction() {
let call = ToolCallId::from_u128(1);
let failed_call = ToolCallId::from_u128(2);
let mut session = Session::new();
for content in [
EntryContent::Message(Message::with_text(Role::User, "list files")),
EntryContent::ToolCall {
name: "ls".to_string(),
input: serde_json::json!({"path": "."}),
call_id: call,
},
EntryContent::ToolResult {
ok: true,
output: "a.txt".to_string(),
call_id: call,
},
EntryContent::ToolCall {
name: "read".to_string(),
input: serde_json::json!({"path": "missing.txt"}),
call_id: failed_call,
},
EntryContent::ToolResult {
ok: false,
output: "not found".to_string(),
call_id: failed_call,
},
EntryContent::Message(Message::with_text(Role::Assistant, "a.txt")),
EntryContent::Meta {
kind: COMPACTION_KIND.to_string(),
detail: serde_json::json!({}),
},
EntryContent::Meta {
kind: "branch".to_string(),
detail: serde_json::json!({}),
},
] {
session.append(&content).unwrap();
}
insta::assert_snapshot!(redacted_trace(&session));
}