codetether_agent/session/context/
policy.rs1use std::env;
4use std::sync::Arc;
5
6use anyhow::Result;
7use tokio::sync::mpsc;
8
9use crate::provider::ToolDefinition;
10use crate::session::Session;
11use crate::session::SessionEvent;
12use crate::session::derive_policy::DerivePolicy;
13
14use super::derive::derive_context;
15use super::helpers::DerivedContext;
16use super::reset::derive_reset;
17use super::reset_helpers::latest_reset_marker_index;
18
19const DEFAULT_RESET_THRESHOLD_TOKENS: usize = 32_000;
20
21pub fn effective_policy(session: &Session) -> DerivePolicy {
35 let persisted = session.metadata.context_policy;
36 let Ok(raw) = env::var("CODETETHER_CONTEXT_POLICY") else {
37 if matches!(persisted, DerivePolicy::Legacy)
38 && latest_reset_marker_index(&session.messages).is_some()
39 {
40 return DerivePolicy::Reset {
41 threshold_tokens: resolve_reset_threshold(persisted),
42 };
43 }
44 return persisted;
45 };
46 let normalized = raw.trim().to_ascii_lowercase();
47 match normalized.as_str() {
48 "" => persisted,
49 "legacy" => DerivePolicy::Legacy,
50 "reset" => DerivePolicy::Reset {
51 threshold_tokens: resolve_reset_threshold(persisted),
52 },
53 _ => {
54 tracing::warn!(raw = %raw, "Unknown CODETETHER_CONTEXT_POLICY override; using persisted session policy");
55 persisted
56 }
57 }
58}
59
60fn resolve_reset_threshold(persisted: DerivePolicy) -> usize {
61 let default_threshold = match persisted {
62 DerivePolicy::Reset { threshold_tokens } => threshold_tokens,
63 DerivePolicy::Legacy => DEFAULT_RESET_THRESHOLD_TOKENS,
64 };
65 env::var("CODETETHER_CONTEXT_RESET_THRESHOLD_TOKENS")
66 .ok()
67 .and_then(|value| value.trim().parse::<usize>().ok())
68 .unwrap_or(default_threshold)
69}
70
71pub async fn derive_with_policy(
90 session: &Session,
91 provider: Arc<dyn crate::provider::Provider>,
92 model: &str,
93 system_prompt: &str,
94 tools: &[ToolDefinition],
95 event_tx: Option<&mpsc::Sender<SessionEvent>>,
96 policy: DerivePolicy,
97 force_keep_last: Option<usize>,
98) -> Result<DerivedContext> {
99 if force_keep_last.is_some() {
100 return derive_context(
101 session,
102 provider,
103 model,
104 system_prompt,
105 tools,
106 event_tx,
107 force_keep_last,
108 )
109 .await;
110 }
111 match policy {
112 DerivePolicy::Legacy => {
113 derive_context(
114 session,
115 provider,
116 model,
117 system_prompt,
118 tools,
119 event_tx,
120 force_keep_last,
121 )
122 .await
123 }
124 DerivePolicy::Reset { threshold_tokens } => {
125 derive_reset(
126 session,
127 provider,
128 model,
129 system_prompt,
130 tools,
131 threshold_tokens,
132 )
133 .await
134 }
135 }
136}