relayburn-sdk: implement five sync query verbs#301
Conversation
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThe module-level documentation in ChangesModule Documentation & Organization
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 969affebb6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if !looks_like_iso(raw) { | ||
| anyhow::bail!( | ||
| "invalid since: {raw} (expected ISO timestamp or relative range like 7d)" | ||
| ); | ||
| } | ||
| Ok(Some(raw.to_string())) |
There was a problem hiding this comment.
Canonicalize
since timestamps before storing in query
normalize_since accepts any string with a YYYY-MM-DD prefix and returns it unchanged, but ledger filtering is a lexical string comparison on turn.ts. This means valid inputs that are not in canonical ledger format (for example 2026-04-01T00:00:00Z without milliseconds, or timestamps with timezone offsets) can be ordered incorrectly and silently include/exclude the wrong turns near the boundary. The TS SDK normalizes parsed timestamps to UTC ISO (toISOString()), so this Rust path should parse and re-emit canonical ISO (or reject invalid dates) instead of passing raw input through.
Useful? React with 👍 / 👎.
Fill in `query_verbs.rs` with the embedding-API surface for `summary`,
`session_cost`, `overhead`, `overhead_trim`, and `hotspots`. Each verb
appears in two forms:
- `impl LedgerHandle { fn <verb>(&self, opts) -> Result<…> }` for
callers that already hold a handle (the common embedding path).
- A free function that opens its own `LedgerHandle` from
`LedgerOpenOptions::with_home(opts.ledger_home)`, mirroring the TS
`withHome(opts.ledgerHome, …)` wrapper without mutating process env.
Result types derive `Serialize` + `#[serde(rename_all = "camelCase")]`
so the JSON shape matches `@relayburn/sdk` byte-for-byte; the discriminated
`HotspotsResult` uses `#[serde(tag = "kind")]` to mirror the TS union.
`normalize_since` accepts both ISO timestamps and the relative ranges
(`24h`, `7d`, `4w`, `2m`) the CLI/SDK take, formatting via a hand-rolled
proleptic-Gregorian helper to avoid pulling in chrono. The hotspots
findings path runs the core `detect_patterns` pipeline plus the
side-channel `tool-output-bloat` and `tool-call-pattern` detectors;
`ghost-surface` is deferred (its TS sibling drives a filesystem-mining
pipeline that goes beyond the ledger surface).
Unit tests inside `query_verbs.rs` build a fixture ledger via
`tempfile::TempDir`, append a couple of synthetic `TurnRecord`s, and
assert each verb's wrapper plumbs through with structurally non-empty
results — coverage of the JS sibling's behavioral parity is left for
the integration test in PR5.
Part of #246.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
969affe to
bcb182b
Compare
Summary
Fill in
crates/relayburn-sdk/src/query_verbs.rswith the five sync query verbs:summary,session_cost,overhead,overhead_trim,hotspots. Each is callable both as aLedgerHandlemethod and as a free function (which opens its own ledger fromLedgerOpenOptions).The verbs are thin wrappers over
relayburn-analyze+relayburn-ledger. Behavior mirrors the TS sibling inpackages/sdk/index.js.sinceaccepts both ISO timestamps and CLI-style relative ranges (24h,7d,4w,2m); a small proleptic-Gregorian helper avoids pulling inchrono/time.hotspotsreturns a discriminated union (HotspotsResult) covering attribution + the four narrow group-by axes + the findings shape.ghost-surfacepattern is intentionally deferred — the TS sibling drives an async filesystem-mining pipeline that's outside the ledger surface and would balloon this PR.Part of #246.
Test plan
Stacking
Stacked on #300 (module stubs) — base is `claude/sdk-module-stubs` and will rebase to `main` once that lands.
🤖 Generated with Claude Code