Skip to main content

lash_protocol_rlm/plugin/
config.rs

1use lash_plugin_tool_output_budget::ToolOutputBudgetConfig;
2
3#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
4#[serde(default, deny_unknown_fields)]
5pub struct RlmProtocolPluginConfig {
6    pub observe_projection: ToolOutputBudgetConfig,
7    #[serde(default)]
8    pub prompt_features: crate::protocol::RlmPromptFeatures,
9    #[serde(default)]
10    pub lashlang_abilities: lashlang::LashlangAbilities,
11    #[serde(default)]
12    pub lashlang_language_features: lashlang::LashlangLanguageFeatures,
13    #[serde(default = "default_max_output_chars")]
14    pub max_output_chars: usize,
15    #[serde(default = "default_continue_as_soft_warn_tokens")]
16    pub continue_as_soft_warn_tokens: Option<usize>,
17    /// In the "Bound Variables" prompt section, render a variable's value
18    /// inline (so the model can read it directly) when its compact JSON form
19    /// fits within this many characters; larger values fall back to a
20    /// type + size hint. Set to 0 to always use hints.
21    #[serde(default = "default_bound_variables_inline_char_limit")]
22    pub bound_variables_inline_char_limit: usize,
23}
24
25fn default_max_output_chars() -> usize {
26    10_000
27}
28
29fn default_continue_as_soft_warn_tokens() -> Option<usize> {
30    Some(100_000)
31}
32
33fn default_bound_variables_inline_char_limit() -> usize {
34    1_024
35}
36
37impl Default for RlmProtocolPluginConfig {
38    fn default() -> Self {
39        Self {
40            observe_projection: ToolOutputBudgetConfig::default(),
41            prompt_features: crate::protocol::RlmPromptFeatures::default(),
42            lashlang_abilities: lashlang::LashlangAbilities::default(),
43            lashlang_language_features: lashlang::LashlangLanguageFeatures::default(),
44            max_output_chars: default_max_output_chars(),
45            continue_as_soft_warn_tokens: default_continue_as_soft_warn_tokens(),
46            bound_variables_inline_char_limit: default_bound_variables_inline_char_limit(),
47        }
48    }
49}
50
51impl RlmProtocolPluginConfig {
52    pub fn with_lashlang_abilities(mut self, abilities: lashlang::LashlangAbilities) -> Self {
53        self.lashlang_abilities = abilities;
54        self
55    }
56
57    pub fn with_bound_variables_inline_char_limit(mut self, limit: usize) -> Self {
58        self.bound_variables_inline_char_limit = limit;
59        self
60    }
61
62    pub fn with_lashlang_language_features(
63        mut self,
64        language_features: lashlang::LashlangLanguageFeatures,
65    ) -> Self {
66        self.lashlang_language_features = language_features;
67        self
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn rlm_config_defaults_soft_budget_threshold() {
77        let config = RlmProtocolPluginConfig::default();
78
79        assert_eq!(config.continue_as_soft_warn_tokens, Some(100_000));
80    }
81}