Repository navigation
feat(loop): richer Langfuse signals — OpenRouter cost/cache + optional input preview - #44
Merged
Conversation
…put preview Parse OpenRouter's richer `usage` shape off the SSE wire: top-level `cost`, plus cache tokens in both Anthropic-flat (`cache_read_input_tokens`, `cache_creation_input_tokens`) and OpenAI-nested (`prompt_tokens_details.cached_tokens`) forms. A custom `Deserialize` on `Usage` collapses both into the flat public shape (cache_read = max of the two sources). Previously-dropped data now flows into the Langfuse generation span (`metadata.cost_usd`, `cache_read_tokens`, `cache_creation_tokens`) and into `trace.finalize(...total_cost...)`. Add an opt-in `LANGFUSE_CAPTURE_INPUT` flag that attaches a redacted chat-log snapshot (ported from overfolder's `build_context_snapshot`) to the generation `input` field. Adapted for overloop's `Content` enum: non-text blocks render as `[image]`/`[audio]`/`[media]` placeholders so no base64/data-URI payload leaks. Off by default — the default posture keeps prompt content local. - New `loop/src/observability/preview.rs` + 7 unit tests. - 4 new deser tests covering Anthropic-flat, OpenAI-nested, both absent, and both-present-picks-max. - `test_langfuse.rs`: existing success test now asserts cost_usd round-trip; new test covers string-preview round-trip. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #44 +/- ##
==========================================
+ Coverage 91.62% 91.81% +0.19%
==========================================
Files 49 50 +1
Lines 6432 6685 +253
==========================================
+ Hits 5893 6138 +245
- Misses 539 547 +8
🚀 New features to boost your workflow:
|
angel-manuel
added a commit
that referenced
this pull request
Apr 18, 2026
Extract AgentRegistryProvider, MessageQueueProvider, and StreamBrokerProvider traits from the concrete in-memory implementations. Add a Redis/Valkey-backed implementation behind the `redis` cargo feature that enables multiple overacp-server instances to share routing state via: - Ownership leases (SET EX + Lua CAS heartbeat) for tunnel pinning - XREADGROUP inbox streams for cross-instance message delivery (produce-unconditionally pattern) - XAUTOCLAIM + DLQ for orphan recovery - Redis pub/sub for SSE fan-out and control signals (takeover, force-disconnect) Design aligned with overfolder-on-overacp vision doc: tunnel-holder is owner, no sticky LB required, lock-symmetric across deployment modes. Includes two-instance smoke test (tests/smoke-ha.sh) and design doc (docs/design/ha.md). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
angel-manuel
added a commit
that referenced
this pull request
Apr 18, 2026
Extract AgentRegistryProvider, MessageQueueProvider, and StreamBrokerProvider traits from the concrete in-memory implementations. Add a Redis/Valkey-backed implementation behind the `redis` cargo feature that enables multiple overacp-server instances to share routing state via: - Ownership leases (SET EX + Lua CAS heartbeat) for tunnel pinning - XREADGROUP inbox streams for cross-instance message delivery (produce-unconditionally pattern) - XAUTOCLAIM + DLQ for orphan recovery - Redis pub/sub for SSE fan-out and control signals (takeover, force-disconnect) Design aligned with overfolder-on-overacp vision doc: tunnel-holder is owner, no sticky LB required, lock-symmetric across deployment modes. Includes two-instance smoke test (tests/smoke-ha.sh) and design doc (docs/design/ha.md). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
angel-manuel
added a commit
that referenced
this pull request
Apr 18, 2026
* feat(server): optional Redis/Valkey backend for multi-instance HA (#44) Extract AgentRegistryProvider, MessageQueueProvider, and StreamBrokerProvider traits from the concrete in-memory implementations. Add a Redis/Valkey-backed implementation behind the `redis` cargo feature that enables multiple overacp-server instances to share routing state via: - Ownership leases (SET EX + Lua CAS heartbeat) for tunnel pinning - XREADGROUP inbox streams for cross-instance message delivery (produce-unconditionally pattern) - XAUTOCLAIM + DLQ for orphan recovery - Redis pub/sub for SSE fan-out and control signals (takeover, force-disconnect) Design aligned with overfolder-on-overacp vision doc: tunnel-holder is owner, no sticky LB required, lock-symmetric across deployment modes. Includes two-instance smoke test (tests/smoke-ha.sh) and design doc (docs/design/ha.md). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tests): skip smoke-ha when binary lacks redis feature The HA smoke test requires the server binary to be built with --features redis. When compiled without the feature, OVERACP_REDIS_URL is silently ignored and both instances run in-memory mode, causing cross-instance assertions to fail. Add a pre-flight check that greps the binary for the redis enablement log string and exits 0 (skip) if absent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(redis_backend): address PR review findings - inbox: fix XAUTOCLAIM deserialization for Redis 7.0+ (3-element response) and process pending entries before new messages so auto-claimed messages are actually delivered - queue: make drain atomic via Lua script to prevent XRANGE+DEL race where a concurrent push loses a message - registry: make deliver atomic via Lua script to prevent EXISTS+XADD race where agent disconnect between the two commands orphans the message Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: exclude redis_backend from codecov patch coverage The Redis backend module requires a live Redis/Valkey instance for integration testing and cannot be exercised by cargo test alone. Exclude it from the patch coverage target to prevent informational codecov checks from blocking PRs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
usageshape off the SSE wire: top-levelcost, plus cache tokens in both Anthropic-flat (cache_read_input_tokens,cache_creation_input_tokens) and OpenAI-nested (prompt_tokens_details.cached_tokens) forms. A customDeserializeonUsagecollapses both into the flat public shape (cache_read_tokens= max of the two sources). Fields flow into the Langfuse generation span (metadata.cost_usd,cache_read_tokens,cache_creation_tokens) and intotrace.finalize(...total_cost...)— previously all hardcoded to 0.LANGFUSE_CAPTURE_INPUTflag that attaches a redacted chat-log snapshot (ported from sister-repooverfolder/agent-runner'sbuild_context_snapshot) to the generationinput. Adapted for overloop'sContentenum: non-text blocks render as[image]/[audio]/[media]placeholders so no base64/data-URI payload leaks. Off by default — the default posture keeps prompt content local.Usagepublic shape stays flat (added fields default to 0 on absent input).Test plan
cargo test -p overloop— 184 tests pass (121 unit + integration suites)cargo clippy --workspace --all-targets -- -D warningscleancargo fmt --allUsagedeser tests cover Anthropic-flat, OpenAI-nested, both-absent, both-present-picks-maxpreview.rstests cover detail-window, skip-count summary, per-role truncation, multimodal placeholder rendering (no base64 leak), char-boundary safetytest_langfuse.rssuccess-generation test now assertsmetadata.cost_usdround-trip; newgeneration_input_preview_string_roundtripscovers the string-preview branchLANGFUSE_CAPTURE_INPUTtoggle parses1/true/yes/TRUEas truthy, everything else as falseLANGFUSE_CAPTURE_INPUT=1+ real creds, eyeball Langfuse UI for[USER]:/[AGENT]:snapshot + non-zerometadata.cost_usd🤖 Generated with Claude Code