codetether_rlm/router/
should_route.rs1use crate::capability::{OutputCapability, output_capability};
4use crate::chunker::RlmChunker;
5use crate::config::RlmConfig;
6
7use super::types::{RoutingContext, RoutingResult};
8
9pub fn should_route(output: &str, ctx: &RoutingContext, config: &RlmConfig) -> RoutingResult {
15 let estimated = RlmChunker::estimate_tokens(output);
16
17 if config.mode == "off" {
18 return no_route("rlm_mode_off", estimated);
19 }
20
21 let cap = output_capability(ctx.tool_id.as_str());
22 if !matches!(cap, OutputCapability::BulkSummarizable) {
23 let reason = match cap {
24 OutputCapability::ExactContent => "tool_exact_content_no_route",
25 OutputCapability::Unknown => "tool_unknown_capability_no_route",
26 OutputCapability::BulkSummarizable => "tool_eligible",
27 };
28 return no_route(reason, estimated);
29 }
30
31 if config.mode == "always" {
32 return RoutingResult {
33 should_route: true,
34 reason: "rlm_mode_always".into(),
35 estimated_tokens: estimated,
36 };
37 }
38
39 let threshold = (ctx.model_context_limit as f64 * config.threshold) as usize;
40 if estimated > threshold {
41 return RoutingResult {
42 should_route: true,
43 reason: "exceeds_threshold".into(),
44 estimated_tokens: estimated,
45 };
46 }
47
48 overflow_check(ctx, estimated)
49}
50
51fn no_route(reason: &str, tokens: usize) -> RoutingResult {
52 RoutingResult {
53 should_route: false,
54 reason: reason.into(),
55 estimated_tokens: tokens,
56 }
57}
58
59fn overflow_check(ctx: &RoutingContext, estimated: usize) -> RoutingResult {
60 let Some(current) = ctx.current_context_tokens else {
61 return no_route("within_threshold", estimated);
62 };
63 let projected = current + estimated;
64 let limit = (ctx.model_context_limit as f64 * 0.8) as usize;
65 let dominates = estimated * 2 >= projected;
66 if projected > limit && dominates {
67 RoutingResult {
68 should_route: true,
69 reason: "would_overflow".into(),
70 estimated_tokens: estimated,
71 }
72 } else {
73 no_route("within_threshold", estimated)
74 }
75}