Skip to content

Commit 7074fe2

Browse files
authored
Merge pull request #788 from finitecomputer/claude/hermes-ledger-charge-wait
e2e hermes: the owner's ledger is read once each call's charge has landed
2 parents df7b144 + 9783d57 commit 7074fe2

1 file changed

Lines changed: 18 additions & 7 deletions

File tree

‎crates/e2e/src/lanes/hermes.rs‎

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,14 @@ fn run(s: &mut Suite, api: &Api) -> Result<()> {
302302
!calls.is_empty() && calls.iter().all(|c| c.model.contains("flash") && c.metadata["agent_id"].is_string()),
303303
json!(calls.iter().map(|c| json!({ "model": c.model, "metadata": c.metadata })).collect::<Vec<_>>()),
304304
);
305-
let aig = super::ledger::entries(api, &owner_id, "aig:");
306-
s.ok("and each is charged on its owner's ledger", !aig.is_empty() && aig.iter().all(|e| super::ledger::charged(e).is_some()), json!(aig));
305+
// a call is charged after its answer, through the ledger's queue (meter.rs
306+
// `charge`), whose batch waits up to a second: each call's row, once there
307+
let mut aig = Vec::new();
308+
let charged = s.eventually(TURN, || {
309+
aig = super::ledger::entries(api, &owner_id, "aig:");
310+
aig.len() >= calls.len() && aig.iter().all(|e| super::ledger::charged(e).is_some())
311+
});
312+
s.ok("and each is charged on its owner's ledger", charged && !aig.is_empty(), json!({ "calls": calls.len(), "entries": aig }));
307313

308314
// a tool step, then the answer that names it
309315
let r = say(2, "run: echo tool-ran")?;
@@ -783,13 +789,18 @@ fn run(s: &mut Suite, api: &Api) -> Result<()> {
783789
maple_reply(&looked).is_some_and(|t| t.contains("the screen: I see an image, a ")),
784790
json!({ "reply": maple_reply(&looked), "work": work_of(&records(api, &owner, &grove_name, "work"), &looked) }),
785791
);
786-
let vision_entries: Vec<Value> = super::ledger::entries(api, &owner_id, "aig:")
787-
.into_iter()
788-
.filter(|e| e["entry"]["row"]["agent"] == maple_id.as_str() && super::ledger::usage(e)["model"] == fragment_core::models::VISION_MODEL_DEFAULT)
789-
.collect();
792+
// charged after their answers, through the ledger's queue: once there
793+
let mut vision_entries: Vec<Value> = Vec::new();
794+
let metered = s.eventually(TURN, || {
795+
vision_entries = super::ledger::entries(api, &owner_id, "aig:")
796+
.into_iter()
797+
.filter(|e| e["entry"]["row"]["agent"] == maple_id.as_str() && super::ledger::usage(e)["model"] == fragment_core::models::VISION_MODEL_DEFAULT)
798+
.collect();
799+
vision_entries.len() >= looks.len() && vision_entries.iter().all(|e| super::ledger::charged(e).is_some())
800+
});
790801
s.ok(
791802
"each vision call is metered to the agent's owner, as the agent, charged at the vision model's price",
792-
vision_entries.len() >= looks.len() && !looks.is_empty() && vision_entries.iter().all(|e| super::ledger::charged(e).is_some()),
803+
metered && !looks.is_empty(),
793804
json!(vision_entries),
794805
);
795806

0 commit comments

Comments
 (0)