lean_ctx/core/gateway/adapters/
mod.rs1pub mod code_graph;
20pub mod code_symbols;
21pub mod codebase_pack;
22pub mod compression;
23pub mod memory;
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum IntegrationKind {
28 None,
30 CodebasePack,
32 CodeGraph,
34 CodeSymbols,
36 Memory,
38 Compression,
40}
41
42impl IntegrationKind {
43 #[must_use]
45 pub fn parse(s: &str) -> Self {
46 match s.trim().to_ascii_lowercase().replace('_', "-").as_str() {
47 "codebase-pack" | "pack" | "repomix" => Self::CodebasePack,
48 "code-graph" | "graph" | "callgraph" => Self::CodeGraph,
49 "code-symbols" | "symbols" | "lsp" => Self::CodeSymbols,
50 "memory" | "mem" => Self::Memory,
51 "compression" | "compress" | "compressor" => Self::Compression,
52 _ => Self::None,
53 }
54 }
55
56 #[must_use]
58 pub fn from_categories(categories: &[String]) -> Self {
59 categories
60 .iter()
61 .map(|c| Self::parse(c))
62 .find(|k| !k.is_none())
63 .unwrap_or(Self::None)
64 }
65
66 #[must_use]
68 pub fn as_str(self) -> &'static str {
69 match self {
70 Self::None => "none",
71 Self::CodebasePack => "codebase-pack",
72 Self::CodeGraph => "code-graph",
73 Self::CodeSymbols => "code-symbols",
74 Self::Memory => "memory",
75 Self::Compression => "compression",
76 }
77 }
78
79 #[must_use]
80 pub fn is_none(self) -> bool {
81 matches!(self, Self::None)
82 }
83}
84
85#[must_use]
89pub fn ingest_spawn(
90 kind: IntegrationKind,
91 server: &str,
92 tool: &str,
93 text: &str,
94 project_root: &str,
95) -> bool {
96 let (server, tool, text, root) = (
97 server.to_string(),
98 tool.to_string(),
99 text.to_string(),
100 project_root.to_string(),
101 );
102 match kind {
103 IntegrationKind::CodeGraph => {
104 std::thread::spawn(move || code_graph::ingest(&server, &tool, &text, &root));
105 true
106 }
107 IntegrationKind::CodeSymbols => {
108 std::thread::spawn(move || code_symbols::ingest(&server, &tool, &text, &root));
109 true
110 }
111 IntegrationKind::Memory => {
112 std::thread::spawn(move || memory::ingest(&server, &tool, &text, &root));
113 true
114 }
115 IntegrationKind::None | IntegrationKind::CodebasePack | IntegrationKind::Compression => {
117 false
118 }
119 }
120}
121
122#[must_use]
125pub fn transform(
126 kind: IntegrationKind,
127 server: &str,
128 tool: &str,
129 text: &str,
130 budget_tokens: usize,
131) -> Option<String> {
132 match kind {
133 IntegrationKind::CodebasePack => {
134 codebase_pack::transform(server, tool, text, budget_tokens)
135 }
136 _ => None,
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143
144 #[test]
145 fn parses_canonical_and_aliases() {
146 assert_eq!(
147 IntegrationKind::parse("codebase-pack"),
148 IntegrationKind::CodebasePack
149 );
150 assert_eq!(
151 IntegrationKind::parse("repomix"),
152 IntegrationKind::CodebasePack
153 );
154 assert_eq!(IntegrationKind::parse("GRAPH"), IntegrationKind::CodeGraph);
155 assert_eq!(IntegrationKind::parse("mem"), IntegrationKind::Memory);
156 assert_eq!(
157 IntegrationKind::parse("compressor"),
158 IntegrationKind::Compression
159 );
160 assert_eq!(IntegrationKind::parse("whatever"), IntegrationKind::None);
161 }
162
163 #[test]
164 fn slug_round_trips() {
165 for k in [
166 IntegrationKind::CodebasePack,
167 IntegrationKind::CodeGraph,
168 IntegrationKind::CodeSymbols,
169 IntegrationKind::Memory,
170 IntegrationKind::Compression,
171 ] {
172 assert_eq!(IntegrationKind::parse(k.as_str()), k);
173 }
174 }
175
176 #[test]
177 fn from_categories_finds_first_match() {
178 let cats = vec!["workflow".into(), "graph".into(), "search".into()];
179 assert_eq!(
180 IntegrationKind::from_categories(&cats),
181 IntegrationKind::CodeGraph
182 );
183 let none = vec!["workflow".into(), "plans".into()];
184 assert_eq!(
185 IntegrationKind::from_categories(&none),
186 IntegrationKind::None
187 );
188 }
189
190 #[test]
191 fn untyped_kinds_do_not_claim_ingestion() {
192 assert!(!ingest_spawn(IntegrationKind::None, "s", "t", "x", "/tmp"));
193 assert!(!ingest_spawn(
194 IntegrationKind::CodebasePack,
195 "s",
196 "t",
197 "x",
198 "/tmp"
199 ));
200 assert!(!ingest_spawn(
201 IntegrationKind::Compression,
202 "s",
203 "t",
204 "x",
205 "/tmp"
206 ));
207 }
208}