karrio-cli 2025.5rc3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- karrio_cli/__init__.py +0 -0
- karrio_cli/__main__.py +105 -0
- karrio_cli/ai/README.md +335 -0
- karrio_cli/ai/__init__.py +0 -0
- karrio_cli/ai/commands.py +102 -0
- karrio_cli/ai/karrio_ai/__init__.py +1 -0
- karrio_cli/ai/karrio_ai/agent.py +972 -0
- karrio_cli/ai/karrio_ai/architecture/INTEGRATION_AGENT_PROMPT.md +497 -0
- karrio_cli/ai/karrio_ai/architecture/MAPPING_AGENT_PROMPT.md +355 -0
- karrio_cli/ai/karrio_ai/architecture/REAL_WORLD_TESTING.md +305 -0
- karrio_cli/ai/karrio_ai/architecture/SCHEMA_AGENT_PROMPT.md +183 -0
- karrio_cli/ai/karrio_ai/architecture/TESTING_AGENT_PROMPT.md +448 -0
- karrio_cli/ai/karrio_ai/architecture/TESTING_GUIDE.md +271 -0
- karrio_cli/ai/karrio_ai/enhanced_tools.py +943 -0
- karrio_cli/ai/karrio_ai/rag_system.py +503 -0
- karrio_cli/ai/karrio_ai/tests/test_agent.py +350 -0
- karrio_cli/ai/karrio_ai/tests/test_real_integration.py +360 -0
- karrio_cli/ai/karrio_ai/tests/test_real_world_scenarios.py +513 -0
- karrio_cli/commands/__init__.py +0 -0
- karrio_cli/commands/codegen.py +336 -0
- karrio_cli/commands/login.py +139 -0
- karrio_cli/commands/plugins.py +168 -0
- karrio_cli/commands/sdk.py +870 -0
- karrio_cli/common/queries.py +101 -0
- karrio_cli/common/utils.py +368 -0
- karrio_cli/resources/__init__.py +0 -0
- karrio_cli/resources/carriers.py +91 -0
- karrio_cli/resources/connections.py +207 -0
- karrio_cli/resources/events.py +151 -0
- karrio_cli/resources/logs.py +151 -0
- karrio_cli/resources/orders.py +144 -0
- karrio_cli/resources/shipments.py +210 -0
- karrio_cli/resources/trackers.py +287 -0
- karrio_cli/templates/__init__.py +9 -0
- karrio_cli/templates/__pycache__/__init__.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/__init__.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/address.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/address.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/docs.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/docs.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/documents.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/documents.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/manifest.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/manifest.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/pickup.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/pickup.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/rates.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/rates.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/sdk.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/sdk.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/shipments.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/shipments.cpython-312.pyc +0 -0
- karrio_cli/templates/__pycache__/tracking.cpython-311.pyc +0 -0
- karrio_cli/templates/__pycache__/tracking.cpython-312.pyc +0 -0
- karrio_cli/templates/address.py +308 -0
- karrio_cli/templates/docs.py +150 -0
- karrio_cli/templates/documents.py +428 -0
- karrio_cli/templates/manifest.py +396 -0
- karrio_cli/templates/pickup.py +839 -0
- karrio_cli/templates/rates.py +638 -0
- karrio_cli/templates/sdk.py +947 -0
- karrio_cli/templates/shipments.py +892 -0
- karrio_cli/templates/tracking.py +437 -0
- karrio_cli-2025.5rc3.dist-info/METADATA +165 -0
- karrio_cli-2025.5rc3.dist-info/RECORD +68 -0
- karrio_cli-2025.5rc3.dist-info/WHEEL +5 -0
- karrio_cli-2025.5rc3.dist-info/entry_points.txt +2 -0
- karrio_cli-2025.5rc3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,503 @@
|
|
1
|
+
"""
|
2
|
+
RAG (Retrieval-Augmented Generation) System for Karrio Carrier Integration
|
3
|
+
|
4
|
+
This module provides semantic search and pattern extraction capabilities
|
5
|
+
for analyzing existing Karrio connectors and SDK components.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import os
|
9
|
+
import json
|
10
|
+
import typing
|
11
|
+
from pathlib import Path
|
12
|
+
from dataclasses import dataclass
|
13
|
+
from typing import Dict, List, Any, Optional, Tuple
|
14
|
+
import hashlib
|
15
|
+
|
16
|
+
|
17
|
+
@dataclass
|
18
|
+
class CodeFragment:
|
19
|
+
"""Represents a fragment of code with metadata."""
|
20
|
+
file_path: str
|
21
|
+
content: str
|
22
|
+
start_line: int
|
23
|
+
end_line: int
|
24
|
+
fragment_type: str # 'class', 'function', 'import', 'comment'
|
25
|
+
context: str
|
26
|
+
embedding_hash: Optional[str] = None
|
27
|
+
|
28
|
+
|
29
|
+
@dataclass
|
30
|
+
class ConnectorPattern:
|
31
|
+
"""Extracted pattern from existing connectors."""
|
32
|
+
pattern_type: str # 'auth', 'mapping', 'schema', 'error_handling'
|
33
|
+
carrier_name: str
|
34
|
+
description: str
|
35
|
+
code_example: str
|
36
|
+
usage_context: str
|
37
|
+
related_files: List[str]
|
38
|
+
confidence_score: float = 0.0
|
39
|
+
|
40
|
+
|
41
|
+
class KarrioRAGSystem:
|
42
|
+
"""RAG system for Karrio connector analysis and pattern extraction."""
|
43
|
+
|
44
|
+
def __init__(self, workspace_root: Path):
|
45
|
+
self.workspace_root = workspace_root.resolve() # Ensure we have absolute path
|
46
|
+
self.connectors_dir = self.workspace_root / "modules" / "connectors"
|
47
|
+
self.sdk_dir = self.workspace_root / "modules" / "sdk"
|
48
|
+
self.templates_dir = self.workspace_root / "modules" / "cli" / "karrio_cli" / "templates"
|
49
|
+
|
50
|
+
# In-memory knowledge base
|
51
|
+
self.code_fragments: List[CodeFragment] = []
|
52
|
+
self.patterns: List[ConnectorPattern] = []
|
53
|
+
self.indexed_files: Dict[str, str] = {} # file_path -> content_hash
|
54
|
+
|
55
|
+
# Initialize the knowledge base
|
56
|
+
self._build_knowledge_base()
|
57
|
+
|
58
|
+
def _build_knowledge_base(self):
|
59
|
+
"""Build the knowledge base by indexing existing connectors and SDK."""
|
60
|
+
print("Building RAG knowledge base...")
|
61
|
+
print(f"Workspace root: {self.workspace_root}")
|
62
|
+
print(f"Connectors dir: {self.connectors_dir} (exists: {self.connectors_dir.exists()})")
|
63
|
+
print(f"SDK dir: {self.sdk_dir} (exists: {self.sdk_dir.exists()})")
|
64
|
+
|
65
|
+
# Index connector implementations
|
66
|
+
self._index_connectors()
|
67
|
+
|
68
|
+
# Index SDK patterns
|
69
|
+
self._index_sdk()
|
70
|
+
|
71
|
+
# Index CLI templates
|
72
|
+
self._index_templates()
|
73
|
+
|
74
|
+
# Extract common patterns
|
75
|
+
self._extract_patterns()
|
76
|
+
|
77
|
+
print(f"Knowledge base built with {len(self.code_fragments)} fragments and {len(self.patterns)} patterns")
|
78
|
+
|
79
|
+
def _index_connectors(self):
|
80
|
+
"""Index all existing connector implementations."""
|
81
|
+
if not self.connectors_dir.exists():
|
82
|
+
return
|
83
|
+
|
84
|
+
for carrier_dir in self.connectors_dir.iterdir():
|
85
|
+
if carrier_dir.is_dir() and not carrier_dir.name.startswith('.'):
|
86
|
+
self._index_connector(carrier_dir)
|
87
|
+
|
88
|
+
def _index_connector(self, carrier_dir: Path):
|
89
|
+
"""Index a specific connector directory."""
|
90
|
+
carrier_name = carrier_dir.name
|
91
|
+
|
92
|
+
# Index Python files
|
93
|
+
for py_file in carrier_dir.rglob("*.py"):
|
94
|
+
if py_file.is_file():
|
95
|
+
self._index_python_file(py_file, carrier_name)
|
96
|
+
|
97
|
+
# Index configuration files
|
98
|
+
for config_file in carrier_dir.glob("*.toml"):
|
99
|
+
if config_file.is_file():
|
100
|
+
self._index_config_file(config_file, carrier_name)
|
101
|
+
|
102
|
+
def _index_python_file(self, file_path: Path, context: str):
|
103
|
+
"""Index a Python file and extract code fragments."""
|
104
|
+
try:
|
105
|
+
content = file_path.read_text(encoding='utf-8')
|
106
|
+
content_hash = hashlib.md5(content.encode()).hexdigest()
|
107
|
+
|
108
|
+
# Skip if already indexed and unchanged
|
109
|
+
file_key = str(file_path)
|
110
|
+
if file_key in self.indexed_files and self.indexed_files[file_key] == content_hash:
|
111
|
+
return
|
112
|
+
|
113
|
+
self.indexed_files[file_key] = content_hash
|
114
|
+
|
115
|
+
# Extract different types of code fragments
|
116
|
+
fragments = self._extract_code_fragments(file_path, content, context)
|
117
|
+
self.code_fragments.extend(fragments)
|
118
|
+
|
119
|
+
except Exception as e:
|
120
|
+
print(f"Error indexing {file_path}: {e}")
|
121
|
+
|
122
|
+
def _extract_code_fragments(self, file_path: Path, content: str, context: str) -> List[CodeFragment]:
|
123
|
+
"""Extract meaningful code fragments from Python content."""
|
124
|
+
fragments = []
|
125
|
+
lines = content.split('\n')
|
126
|
+
|
127
|
+
# Extract imports
|
128
|
+
for i, line in enumerate(lines):
|
129
|
+
if line.strip().startswith(('import ', 'from ')):
|
130
|
+
fragments.append(CodeFragment(
|
131
|
+
file_path=str(file_path),
|
132
|
+
content=line.strip(),
|
133
|
+
start_line=i + 1,
|
134
|
+
end_line=i + 1,
|
135
|
+
fragment_type='import',
|
136
|
+
context=context
|
137
|
+
))
|
138
|
+
|
139
|
+
# Extract class definitions
|
140
|
+
fragments.extend(self._extract_classes(file_path, content, context))
|
141
|
+
|
142
|
+
# Extract function definitions
|
143
|
+
fragments.extend(self._extract_functions(file_path, content, context))
|
144
|
+
|
145
|
+
return fragments
|
146
|
+
|
147
|
+
def _extract_classes(self, file_path: Path, content: str, context: str) -> List[CodeFragment]:
|
148
|
+
"""Extract class definitions and their methods."""
|
149
|
+
fragments = []
|
150
|
+
lines = content.split('\n')
|
151
|
+
|
152
|
+
i = 0
|
153
|
+
while i < len(lines):
|
154
|
+
line = lines[i]
|
155
|
+
if line.strip().startswith('class '):
|
156
|
+
# Find the end of the class
|
157
|
+
class_start = i
|
158
|
+
indent_level = len(line) - len(line.lstrip())
|
159
|
+
|
160
|
+
j = i + 1
|
161
|
+
while j < len(lines):
|
162
|
+
if lines[j].strip() and (len(lines[j]) - len(lines[j].lstrip())) <= indent_level:
|
163
|
+
if not lines[j].strip().startswith(('"""', "'''")):
|
164
|
+
break
|
165
|
+
j += 1
|
166
|
+
|
167
|
+
class_content = '\n'.join(lines[class_start:j])
|
168
|
+
fragments.append(CodeFragment(
|
169
|
+
file_path=str(file_path),
|
170
|
+
content=class_content,
|
171
|
+
start_line=class_start + 1,
|
172
|
+
end_line=j,
|
173
|
+
fragment_type='class',
|
174
|
+
context=context
|
175
|
+
))
|
176
|
+
|
177
|
+
i = j
|
178
|
+
else:
|
179
|
+
i += 1
|
180
|
+
|
181
|
+
return fragments
|
182
|
+
|
183
|
+
def _extract_functions(self, file_path: Path, content: str, context: str) -> List[CodeFragment]:
|
184
|
+
"""Extract function definitions."""
|
185
|
+
fragments = []
|
186
|
+
lines = content.split('\n')
|
187
|
+
|
188
|
+
i = 0
|
189
|
+
while i < len(lines):
|
190
|
+
line = lines[i]
|
191
|
+
if line.strip().startswith('def '):
|
192
|
+
# Find the end of the function
|
193
|
+
func_start = i
|
194
|
+
indent_level = len(line) - len(line.lstrip())
|
195
|
+
|
196
|
+
j = i + 1
|
197
|
+
while j < len(lines):
|
198
|
+
if lines[j].strip() and (len(lines[j]) - len(lines[j].lstrip())) <= indent_level:
|
199
|
+
break
|
200
|
+
j += 1
|
201
|
+
|
202
|
+
func_content = '\n'.join(lines[func_start:j])
|
203
|
+
fragments.append(CodeFragment(
|
204
|
+
file_path=str(file_path),
|
205
|
+
content=func_content,
|
206
|
+
start_line=func_start + 1,
|
207
|
+
end_line=j,
|
208
|
+
fragment_type='function',
|
209
|
+
context=context
|
210
|
+
))
|
211
|
+
|
212
|
+
i = j
|
213
|
+
else:
|
214
|
+
i += 1
|
215
|
+
|
216
|
+
return fragments
|
217
|
+
|
218
|
+
def _index_config_file(self, file_path: Path, context: str):
|
219
|
+
"""Index configuration files."""
|
220
|
+
try:
|
221
|
+
content = file_path.read_text(encoding='utf-8')
|
222
|
+
self.code_fragments.append(CodeFragment(
|
223
|
+
file_path=str(file_path),
|
224
|
+
content=content,
|
225
|
+
start_line=1,
|
226
|
+
end_line=len(content.split('\n')),
|
227
|
+
fragment_type='config',
|
228
|
+
context=context
|
229
|
+
))
|
230
|
+
except Exception as e:
|
231
|
+
print(f"Error indexing config {file_path}: {e}")
|
232
|
+
|
233
|
+
def _index_sdk(self):
|
234
|
+
"""Index SDK patterns and utilities."""
|
235
|
+
if not self.sdk_dir.exists():
|
236
|
+
return
|
237
|
+
|
238
|
+
for py_file in self.sdk_dir.rglob("*.py"):
|
239
|
+
if py_file.is_file():
|
240
|
+
self._index_python_file(py_file, "sdk")
|
241
|
+
|
242
|
+
def _index_templates(self):
|
243
|
+
"""Index CLI templates."""
|
244
|
+
if not self.templates_dir.exists():
|
245
|
+
return
|
246
|
+
|
247
|
+
for template_file in self.templates_dir.glob("*.py"):
|
248
|
+
if template_file.is_file():
|
249
|
+
self._index_python_file(template_file, "template")
|
250
|
+
|
251
|
+
def _extract_patterns(self):
|
252
|
+
"""Extract common patterns from indexed code fragments."""
|
253
|
+
# Group fragments by functionality
|
254
|
+
auth_patterns = self._find_auth_patterns()
|
255
|
+
mapping_patterns = self._find_mapping_patterns()
|
256
|
+
schema_patterns = self._find_schema_patterns()
|
257
|
+
error_patterns = self._find_error_patterns()
|
258
|
+
|
259
|
+
self.patterns.extend(auth_patterns)
|
260
|
+
self.patterns.extend(mapping_patterns)
|
261
|
+
self.patterns.extend(schema_patterns)
|
262
|
+
self.patterns.extend(error_patterns)
|
263
|
+
|
264
|
+
def _find_auth_patterns(self) -> List[ConnectorPattern]:
|
265
|
+
"""Find authentication patterns across connectors."""
|
266
|
+
patterns = []
|
267
|
+
|
268
|
+
# Look for authentication-related code
|
269
|
+
auth_keywords = ['auth', 'token', 'api_key', 'credential', 'login', 'bearer', 'oauth']
|
270
|
+
|
271
|
+
for fragment in self.code_fragments:
|
272
|
+
if any(keyword in fragment.content.lower() for keyword in auth_keywords):
|
273
|
+
if fragment.fragment_type in ['function', 'class']:
|
274
|
+
patterns.append(ConnectorPattern(
|
275
|
+
pattern_type='auth',
|
276
|
+
carrier_name=fragment.context,
|
277
|
+
description=f"Authentication pattern from {fragment.context}",
|
278
|
+
code_example=fragment.content,
|
279
|
+
usage_context=f"Lines {fragment.start_line}-{fragment.end_line} in {fragment.file_path}",
|
280
|
+
related_files=[fragment.file_path],
|
281
|
+
confidence_score=0.8
|
282
|
+
))
|
283
|
+
|
284
|
+
return patterns
|
285
|
+
|
286
|
+
def _find_mapping_patterns(self) -> List[ConnectorPattern]:
|
287
|
+
"""Find mapping patterns across connectors."""
|
288
|
+
patterns = []
|
289
|
+
|
290
|
+
# Look for mapping-related functions
|
291
|
+
mapping_keywords = ['parse_', 'request', 'response', 'transform', 'map_', 'convert']
|
292
|
+
|
293
|
+
for fragment in self.code_fragments:
|
294
|
+
if fragment.fragment_type == 'function':
|
295
|
+
if any(keyword in fragment.content.lower() for keyword in mapping_keywords):
|
296
|
+
patterns.append(ConnectorPattern(
|
297
|
+
pattern_type='mapping',
|
298
|
+
carrier_name=fragment.context,
|
299
|
+
description=f"Mapping pattern from {fragment.context}",
|
300
|
+
code_example=fragment.content,
|
301
|
+
usage_context=f"Lines {fragment.start_line}-{fragment.end_line} in {fragment.file_path}",
|
302
|
+
related_files=[fragment.file_path],
|
303
|
+
confidence_score=0.7
|
304
|
+
))
|
305
|
+
|
306
|
+
return patterns
|
307
|
+
|
308
|
+
def _find_schema_patterns(self) -> List[ConnectorPattern]:
|
309
|
+
"""Find schema patterns across connectors."""
|
310
|
+
patterns = []
|
311
|
+
|
312
|
+
# Look for schema-related classes
|
313
|
+
schema_keywords = ['@attr.s', 'class.*Type:', 'dataclass', 'jstruct']
|
314
|
+
|
315
|
+
for fragment in self.code_fragments:
|
316
|
+
if fragment.fragment_type == 'class':
|
317
|
+
if any(keyword.lower() in fragment.content.lower() for keyword in schema_keywords):
|
318
|
+
patterns.append(ConnectorPattern(
|
319
|
+
pattern_type='schema',
|
320
|
+
carrier_name=fragment.context,
|
321
|
+
description=f"Schema pattern from {fragment.context}",
|
322
|
+
code_example=fragment.content,
|
323
|
+
usage_context=f"Lines {fragment.start_line}-{fragment.end_line} in {fragment.file_path}",
|
324
|
+
related_files=[fragment.file_path],
|
325
|
+
confidence_score=0.9
|
326
|
+
))
|
327
|
+
|
328
|
+
return patterns
|
329
|
+
|
330
|
+
def _find_error_patterns(self) -> List[ConnectorPattern]:
|
331
|
+
"""Find error handling patterns across connectors."""
|
332
|
+
patterns = []
|
333
|
+
|
334
|
+
# Look for error handling code
|
335
|
+
error_keywords = ['error', 'exception', 'message', 'parse_error', 'handle_error']
|
336
|
+
|
337
|
+
for fragment in self.code_fragments:
|
338
|
+
if any(keyword in fragment.content.lower() for keyword in error_keywords):
|
339
|
+
if fragment.fragment_type in ['function', 'class']:
|
340
|
+
patterns.append(ConnectorPattern(
|
341
|
+
pattern_type='error_handling',
|
342
|
+
carrier_name=fragment.context,
|
343
|
+
description=f"Error handling pattern from {fragment.context}",
|
344
|
+
code_example=fragment.content,
|
345
|
+
usage_context=f"Lines {fragment.start_line}-{fragment.end_line} in {fragment.file_path}",
|
346
|
+
related_files=[fragment.file_path],
|
347
|
+
confidence_score=0.6
|
348
|
+
))
|
349
|
+
|
350
|
+
return patterns
|
351
|
+
|
352
|
+
def search_patterns(self,
|
353
|
+
pattern_type: Optional[str] = None,
|
354
|
+
carrier_name: Optional[str] = None,
|
355
|
+
keywords: Optional[List[str]] = None,
|
356
|
+
limit: int = 10) -> List[ConnectorPattern]:
|
357
|
+
"""Search for patterns based on criteria."""
|
358
|
+
filtered_patterns = self.patterns
|
359
|
+
|
360
|
+
# Filter by pattern type
|
361
|
+
if pattern_type:
|
362
|
+
filtered_patterns = [p for p in filtered_patterns if p.pattern_type == pattern_type]
|
363
|
+
|
364
|
+
# Filter by carrier name
|
365
|
+
if carrier_name:
|
366
|
+
filtered_patterns = [p for p in filtered_patterns if carrier_name.lower() in p.carrier_name.lower()]
|
367
|
+
|
368
|
+
# Filter by keywords
|
369
|
+
if keywords:
|
370
|
+
def matches_keywords(pattern: ConnectorPattern) -> bool:
|
371
|
+
text = f"{pattern.description} {pattern.code_example}".lower()
|
372
|
+
return any(keyword.lower() in text for keyword in keywords)
|
373
|
+
|
374
|
+
filtered_patterns = [p for p in filtered_patterns if matches_keywords(p)]
|
375
|
+
|
376
|
+
# Sort by confidence score
|
377
|
+
filtered_patterns.sort(key=lambda p: p.confidence_score, reverse=True)
|
378
|
+
|
379
|
+
return filtered_patterns[:limit]
|
380
|
+
|
381
|
+
def get_similar_carriers(self, carrier_characteristics: Dict[str, Any]) -> List[str]:
|
382
|
+
"""Find carriers with similar characteristics."""
|
383
|
+
# Simple similarity based on common patterns
|
384
|
+
api_type = carrier_characteristics.get('api_type', 'REST')
|
385
|
+
auth_type = carrier_characteristics.get('auth_type', 'API_KEY')
|
386
|
+
operations = set(carrier_characteristics.get('operations', []))
|
387
|
+
|
388
|
+
similar_carriers = []
|
389
|
+
carrier_scores = {}
|
390
|
+
|
391
|
+
for pattern in self.patterns:
|
392
|
+
carrier = pattern.carrier_name
|
393
|
+
if carrier not in carrier_scores:
|
394
|
+
carrier_scores[carrier] = 0
|
395
|
+
|
396
|
+
# Score based on pattern matches
|
397
|
+
if api_type.lower() in pattern.code_example.lower():
|
398
|
+
carrier_scores[carrier] += 1
|
399
|
+
|
400
|
+
if auth_type.lower() in pattern.code_example.lower():
|
401
|
+
carrier_scores[carrier] += 2
|
402
|
+
|
403
|
+
# Check for operation matches
|
404
|
+
for op in operations:
|
405
|
+
if op.lower() in pattern.code_example.lower():
|
406
|
+
carrier_scores[carrier] += 1
|
407
|
+
|
408
|
+
# Sort by score and return top carriers
|
409
|
+
sorted_carriers = sorted(carrier_scores.items(), key=lambda x: x[1], reverse=True)
|
410
|
+
return [carrier for carrier, score in sorted_carriers[:5] if score > 0]
|
411
|
+
|
412
|
+
def get_implementation_examples(self,
|
413
|
+
operation: str,
|
414
|
+
carrier_names: List[str] = None) -> List[CodeFragment]:
|
415
|
+
"""Get implementation examples for specific operations."""
|
416
|
+
examples = []
|
417
|
+
|
418
|
+
for fragment in self.code_fragments:
|
419
|
+
if operation.lower() in fragment.content.lower():
|
420
|
+
if carrier_names is None or fragment.context in carrier_names:
|
421
|
+
examples.append(fragment)
|
422
|
+
|
423
|
+
return examples[:10] # Limit results
|
424
|
+
|
425
|
+
def analyze_carrier_structure(self, carrier_name: str) -> Dict[str, Any]:
|
426
|
+
"""Analyze the structure of an existing carrier implementation."""
|
427
|
+
analysis = {
|
428
|
+
'carrier_name': carrier_name,
|
429
|
+
'files': [],
|
430
|
+
'patterns': [],
|
431
|
+
'structure': {
|
432
|
+
'has_schemas': False,
|
433
|
+
'has_mappings': False,
|
434
|
+
'has_tests': False,
|
435
|
+
'has_providers': False
|
436
|
+
}
|
437
|
+
}
|
438
|
+
|
439
|
+
# Find all fragments for this carrier
|
440
|
+
carrier_fragments = [f for f in self.code_fragments if f.context == carrier_name]
|
441
|
+
|
442
|
+
for fragment in carrier_fragments:
|
443
|
+
analysis['files'].append({
|
444
|
+
'path': fragment.file_path,
|
445
|
+
'type': fragment.fragment_type,
|
446
|
+
'lines': f"{fragment.start_line}-{fragment.end_line}"
|
447
|
+
})
|
448
|
+
|
449
|
+
# Determine structure components
|
450
|
+
if 'schemas' in fragment.file_path:
|
451
|
+
analysis['structure']['has_schemas'] = True
|
452
|
+
elif 'mappers' in fragment.file_path:
|
453
|
+
analysis['structure']['has_mappings'] = True
|
454
|
+
elif 'test' in fragment.file_path:
|
455
|
+
analysis['structure']['has_tests'] = True
|
456
|
+
elif 'providers' in fragment.file_path:
|
457
|
+
analysis['structure']['has_providers'] = True
|
458
|
+
|
459
|
+
# Find patterns for this carrier
|
460
|
+
analysis['patterns'] = [p for p in self.patterns if p.carrier_name == carrier_name]
|
461
|
+
|
462
|
+
return analysis
|
463
|
+
|
464
|
+
|
465
|
+
# Global RAG system instance
|
466
|
+
_rag_system: Optional[KarrioRAGSystem] = None
|
467
|
+
|
468
|
+
|
469
|
+
def get_rag_system(workspace_root: Path) -> KarrioRAGSystem:
|
470
|
+
"""Get or create the global RAG system instance."""
|
471
|
+
global _rag_system
|
472
|
+
if _rag_system is None:
|
473
|
+
_rag_system = KarrioRAGSystem(workspace_root)
|
474
|
+
return _rag_system
|
475
|
+
|
476
|
+
|
477
|
+
def search_implementation_patterns(pattern_type: str,
|
478
|
+
carrier_name: str = None,
|
479
|
+
keywords: List[str] = None) -> List[Dict[str, Any]]:
|
480
|
+
"""Search for implementation patterns using the RAG system."""
|
481
|
+
from pathlib import Path
|
482
|
+
|
483
|
+
# Get workspace root - resolve relative to this file's location
|
484
|
+
workspace_root = Path(__file__).resolve().parents[5] # Use resolve() for consistent path handling
|
485
|
+
rag = get_rag_system(workspace_root)
|
486
|
+
|
487
|
+
patterns = rag.search_patterns(
|
488
|
+
pattern_type=pattern_type,
|
489
|
+
carrier_name=carrier_name,
|
490
|
+
keywords=keywords
|
491
|
+
)
|
492
|
+
|
493
|
+
return [
|
494
|
+
{
|
495
|
+
'pattern_type': p.pattern_type,
|
496
|
+
'carrier_name': p.carrier_name,
|
497
|
+
'description': p.description,
|
498
|
+
'code_example': p.code_example,
|
499
|
+
'usage_context': p.usage_context,
|
500
|
+
'confidence_score': p.confidence_score
|
501
|
+
}
|
502
|
+
for p in patterns
|
503
|
+
]
|