roma-debug 0.1.0__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.
- roma_debug/__init__.py +3 -0
- roma_debug/config.py +79 -0
- roma_debug/core/__init__.py +5 -0
- roma_debug/core/engine.py +423 -0
- roma_debug/core/models.py +313 -0
- roma_debug/main.py +753 -0
- roma_debug/parsers/__init__.py +21 -0
- roma_debug/parsers/base.py +189 -0
- roma_debug/parsers/python_ast_parser.py +268 -0
- roma_debug/parsers/registry.py +196 -0
- roma_debug/parsers/traceback_patterns.py +314 -0
- roma_debug/parsers/treesitter_parser.py +598 -0
- roma_debug/prompts.py +153 -0
- roma_debug/server.py +247 -0
- roma_debug/tracing/__init__.py +28 -0
- roma_debug/tracing/call_chain.py +278 -0
- roma_debug/tracing/context_builder.py +672 -0
- roma_debug/tracing/dependency_graph.py +298 -0
- roma_debug/tracing/error_analyzer.py +399 -0
- roma_debug/tracing/import_resolver.py +315 -0
- roma_debug/tracing/project_scanner.py +569 -0
- roma_debug/utils/__init__.py +5 -0
- roma_debug/utils/context.py +422 -0
- roma_debug-0.1.0.dist-info/METADATA +34 -0
- roma_debug-0.1.0.dist-info/RECORD +36 -0
- roma_debug-0.1.0.dist-info/WHEEL +5 -0
- roma_debug-0.1.0.dist-info/entry_points.txt +2 -0
- roma_debug-0.1.0.dist-info/licenses/LICENSE +201 -0
- roma_debug-0.1.0.dist-info/top_level.txt +2 -0
- tests/__init__.py +1 -0
- tests/test_context.py +208 -0
- tests/test_engine.py +296 -0
- tests/test_parsers.py +534 -0
- tests/test_project_scanner.py +275 -0
- tests/test_traceback_patterns.py +222 -0
- tests/test_tracing.py +296 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
"""Smart context extraction for ROMA Debug.
|
|
2
|
+
|
|
3
|
+
Uses AST parsing to extract full function/class definitions around errors,
|
|
4
|
+
with graceful fallback strategies for non-parseable or missing files.
|
|
5
|
+
|
|
6
|
+
V2: Now supports multi-language parsing via parser registry.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import ast
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from typing import Optional, List, Tuple
|
|
14
|
+
|
|
15
|
+
from roma_debug.core.models import Language, FileContext as FileContextV2, Import, Symbol
|
|
16
|
+
from roma_debug.parsers.registry import get_parser, detect_language
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class FileContext:
|
|
21
|
+
"""Extracted context from a source file.
|
|
22
|
+
|
|
23
|
+
This is the V1 interface maintained for backward compatibility.
|
|
24
|
+
Internally delegates to FileContextV2 when possible.
|
|
25
|
+
"""
|
|
26
|
+
filepath: str
|
|
27
|
+
line_number: int
|
|
28
|
+
context_type: str # 'ast', 'lines', 'missing', 'treesitter'
|
|
29
|
+
content: str
|
|
30
|
+
function_name: Optional[str] = None
|
|
31
|
+
class_name: Optional[str] = None
|
|
32
|
+
# V2 additions (optional for backward compat)
|
|
33
|
+
language: Language = Language.UNKNOWN
|
|
34
|
+
imports: List[Import] = None
|
|
35
|
+
symbol: Optional[Symbol] = None
|
|
36
|
+
|
|
37
|
+
def __post_init__(self):
|
|
38
|
+
if self.imports is None:
|
|
39
|
+
self.imports = []
|
|
40
|
+
|
|
41
|
+
def to_v2(self) -> FileContextV2:
|
|
42
|
+
"""Convert to V2 FileContext."""
|
|
43
|
+
return FileContextV2(
|
|
44
|
+
filepath=self.filepath,
|
|
45
|
+
line_number=self.line_number,
|
|
46
|
+
context_type=self.context_type,
|
|
47
|
+
content=self.content,
|
|
48
|
+
function_name=self.function_name,
|
|
49
|
+
class_name=self.class_name,
|
|
50
|
+
language=self.language,
|
|
51
|
+
imports=self.imports or [],
|
|
52
|
+
symbol=self.symbol,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _resolve_file_path(file_path: str) -> Optional[str]:
|
|
57
|
+
"""Resolve file path, checking both absolute and cwd-relative locations.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
file_path: Path from traceback (may be absolute or relative)
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Resolved path if file exists, None otherwise
|
|
64
|
+
"""
|
|
65
|
+
# 1. Try the path as-is (absolute or relative to cwd)
|
|
66
|
+
if os.path.isfile(file_path):
|
|
67
|
+
return file_path
|
|
68
|
+
|
|
69
|
+
# 2. Try relative to current working directory
|
|
70
|
+
cwd = os.getcwd()
|
|
71
|
+
cwd_relative = os.path.join(cwd, file_path)
|
|
72
|
+
if os.path.isfile(cwd_relative):
|
|
73
|
+
return cwd_relative
|
|
74
|
+
|
|
75
|
+
# 3. Try just the filename in cwd (for logs from different machines)
|
|
76
|
+
filename = os.path.basename(file_path)
|
|
77
|
+
cwd_filename = os.path.join(cwd, filename)
|
|
78
|
+
if os.path.isfile(cwd_filename):
|
|
79
|
+
return cwd_filename
|
|
80
|
+
|
|
81
|
+
# 4. Try extracting relative path after common prefixes
|
|
82
|
+
# e.g., "/app/src/main.py" -> "src/main.py"
|
|
83
|
+
common_prefixes = ["/app/", "/home/", "/usr/", "/var/"]
|
|
84
|
+
for prefix in common_prefixes:
|
|
85
|
+
if file_path.startswith(prefix):
|
|
86
|
+
relative = file_path[len(prefix):]
|
|
87
|
+
cwd_relative = os.path.join(cwd, relative)
|
|
88
|
+
if os.path.isfile(cwd_relative):
|
|
89
|
+
return cwd_relative
|
|
90
|
+
|
|
91
|
+
# 5. Search for the file in common project subdirectories
|
|
92
|
+
search_dirs = [".", "src", "lib", "app", "tests", "test"]
|
|
93
|
+
for search_dir in search_dirs:
|
|
94
|
+
search_path = os.path.join(cwd, search_dir, filename)
|
|
95
|
+
if os.path.isfile(search_path):
|
|
96
|
+
return search_path
|
|
97
|
+
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def get_file_context(error_log: str) -> Tuple[str, List[FileContext]]:
|
|
102
|
+
"""Extract file context from a Python traceback.
|
|
103
|
+
|
|
104
|
+
Uses AST parsing to extract full function/class definitions.
|
|
105
|
+
Falls back to line-based extraction if AST fails.
|
|
106
|
+
Searches for files relative to os.getcwd() for project awareness.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
error_log: The error log or traceback string
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Tuple of (formatted context string, list of FileContext objects)
|
|
113
|
+
"""
|
|
114
|
+
# Pattern to match Python traceback file references
|
|
115
|
+
pattern = re.compile(r'File ["\'](.+?)["\'], line (\d+)')
|
|
116
|
+
matches = pattern.findall(error_log)
|
|
117
|
+
|
|
118
|
+
if not matches:
|
|
119
|
+
return "", []
|
|
120
|
+
|
|
121
|
+
contexts: List[FileContext] = []
|
|
122
|
+
context_parts: List[str] = []
|
|
123
|
+
|
|
124
|
+
for file_path, line_num_str in matches:
|
|
125
|
+
line_num = int(line_num_str)
|
|
126
|
+
file_context = _extract_context(file_path, line_num)
|
|
127
|
+
contexts.append(file_context)
|
|
128
|
+
|
|
129
|
+
# Build formatted output
|
|
130
|
+
filename = os.path.basename(file_path)
|
|
131
|
+
if file_context.context_type == "missing":
|
|
132
|
+
context_parts.append(file_context.content)
|
|
133
|
+
else:
|
|
134
|
+
header = f"Context from {filename}"
|
|
135
|
+
if file_context.function_name:
|
|
136
|
+
header += f" (function: {file_context.function_name})"
|
|
137
|
+
if file_context.class_name:
|
|
138
|
+
header += f" (class: {file_context.class_name})"
|
|
139
|
+
context_parts.append(f"{header}:\n{file_context.content}")
|
|
140
|
+
|
|
141
|
+
return "\n\n".join(context_parts), contexts
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _extract_context(file_path: str, error_line: int) -> FileContext:
|
|
145
|
+
"""Extract context from a file using parser or fallback.
|
|
146
|
+
|
|
147
|
+
Strategy:
|
|
148
|
+
1. Resolve file path (check cwd-relative paths)
|
|
149
|
+
2. Detect language from file extension
|
|
150
|
+
3. Try language-specific parser to get full function/class
|
|
151
|
+
4. Fallback to +/- 50 lines if parser fails
|
|
152
|
+
5. Return friendly message if file missing
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
file_path: Path to the source file (from traceback)
|
|
156
|
+
error_line: Line number where error occurred
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
FileContext with extracted content
|
|
160
|
+
"""
|
|
161
|
+
# Resolve the file path (try cwd-relative if absolute doesn't exist)
|
|
162
|
+
resolved_path = _resolve_file_path(file_path)
|
|
163
|
+
|
|
164
|
+
if resolved_path is None:
|
|
165
|
+
return FileContext(
|
|
166
|
+
filepath=file_path,
|
|
167
|
+
line_number=error_line,
|
|
168
|
+
context_type="missing",
|
|
169
|
+
content=f"[System] Local file not found at {file_path}. Debugging based on logs only.",
|
|
170
|
+
language=detect_language(file_path),
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# Read file content
|
|
174
|
+
try:
|
|
175
|
+
with open(resolved_path, 'r', encoding='utf-8', errors='replace') as f:
|
|
176
|
+
source = f.read()
|
|
177
|
+
lines = source.splitlines()
|
|
178
|
+
except (IOError, OSError) as e:
|
|
179
|
+
return FileContext(
|
|
180
|
+
filepath=file_path,
|
|
181
|
+
line_number=error_line,
|
|
182
|
+
context_type="missing",
|
|
183
|
+
content=f"[System] Cannot read file {file_path}: {e}. Debugging based on logs only.",
|
|
184
|
+
language=detect_language(file_path),
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Detect language
|
|
188
|
+
language = detect_language(resolved_path)
|
|
189
|
+
|
|
190
|
+
# Try parser-based extraction
|
|
191
|
+
parser_context = _try_parser_extraction(source, lines, error_line, resolved_path, language)
|
|
192
|
+
if parser_context:
|
|
193
|
+
return parser_context
|
|
194
|
+
|
|
195
|
+
# Fallback: +/- 50 lines
|
|
196
|
+
return _line_based_extraction(resolved_path, lines, error_line, language, context_lines=50)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _try_parser_extraction(
|
|
200
|
+
source: str,
|
|
201
|
+
lines: List[str],
|
|
202
|
+
error_line: int,
|
|
203
|
+
file_path: str,
|
|
204
|
+
language: Language,
|
|
205
|
+
) -> Optional[FileContext]:
|
|
206
|
+
"""Try to extract full function/class definition using a parser.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
source: Full source code
|
|
210
|
+
lines: Source split into lines
|
|
211
|
+
error_line: Target line number
|
|
212
|
+
file_path: Path to file
|
|
213
|
+
language: Detected language
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
FileContext if successful, None if parsing fails
|
|
217
|
+
"""
|
|
218
|
+
# Get appropriate parser
|
|
219
|
+
parser = get_parser(language, create_new=True)
|
|
220
|
+
|
|
221
|
+
if parser is None:
|
|
222
|
+
# No parser available for this language, try Python AST as fallback
|
|
223
|
+
if language == Language.PYTHON or file_path.endswith('.py'):
|
|
224
|
+
return _try_ast_extraction(source, lines, error_line, file_path)
|
|
225
|
+
return None
|
|
226
|
+
|
|
227
|
+
# Try parsing
|
|
228
|
+
if not parser.parse(source, file_path):
|
|
229
|
+
# Parser failed, try Python AST as last resort for .py files
|
|
230
|
+
if language == Language.PYTHON:
|
|
231
|
+
return _try_ast_extraction(source, lines, error_line, file_path)
|
|
232
|
+
return None
|
|
233
|
+
|
|
234
|
+
# Find enclosing symbol
|
|
235
|
+
symbol = parser.find_enclosing_symbol(error_line)
|
|
236
|
+
|
|
237
|
+
if symbol is None:
|
|
238
|
+
return None
|
|
239
|
+
|
|
240
|
+
# Extract the full function/class with some buffer
|
|
241
|
+
start_line = max(1, symbol.start_line - 2) # 2 lines before for decorators
|
|
242
|
+
end_line = min(len(lines), symbol.end_line + 2)
|
|
243
|
+
|
|
244
|
+
# Build snippet with line numbers
|
|
245
|
+
snippet = parser.format_snippet(start_line, end_line, highlight_line=error_line)
|
|
246
|
+
|
|
247
|
+
# Determine names
|
|
248
|
+
function_name = None
|
|
249
|
+
class_name = None
|
|
250
|
+
if symbol.kind in ("function", "method", "async_function"):
|
|
251
|
+
function_name = symbol.name
|
|
252
|
+
if symbol.parent and symbol.parent.kind == "class":
|
|
253
|
+
class_name = symbol.parent.name
|
|
254
|
+
elif symbol.kind == "class":
|
|
255
|
+
class_name = symbol.name
|
|
256
|
+
|
|
257
|
+
# Extract imports
|
|
258
|
+
imports = parser.extract_imports()
|
|
259
|
+
|
|
260
|
+
context_type = "treesitter" if "treesitter" in type(parser).__module__ else "ast"
|
|
261
|
+
|
|
262
|
+
return FileContext(
|
|
263
|
+
filepath=file_path,
|
|
264
|
+
line_number=error_line,
|
|
265
|
+
context_type=context_type,
|
|
266
|
+
content=snippet,
|
|
267
|
+
function_name=function_name,
|
|
268
|
+
class_name=class_name,
|
|
269
|
+
language=language,
|
|
270
|
+
imports=imports,
|
|
271
|
+
symbol=symbol,
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def _try_ast_extraction(
|
|
276
|
+
source: str,
|
|
277
|
+
lines: List[str],
|
|
278
|
+
error_line: int,
|
|
279
|
+
file_path: str
|
|
280
|
+
) -> Optional[FileContext]:
|
|
281
|
+
"""Try to extract full function/class definition using AST.
|
|
282
|
+
|
|
283
|
+
Legacy method for backward compatibility. Kept as fallback.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
source: Full source code
|
|
287
|
+
lines: Source split into lines
|
|
288
|
+
error_line: Target line number
|
|
289
|
+
file_path: Path to file
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
FileContext if successful, None if AST parsing fails
|
|
293
|
+
"""
|
|
294
|
+
try:
|
|
295
|
+
tree = ast.parse(source)
|
|
296
|
+
except SyntaxError:
|
|
297
|
+
return None
|
|
298
|
+
|
|
299
|
+
# Find the innermost function or class containing the error line
|
|
300
|
+
best_match = None
|
|
301
|
+
best_match_size = float('inf')
|
|
302
|
+
|
|
303
|
+
for node in ast.walk(tree):
|
|
304
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
|
|
305
|
+
# Check if error line is within this node
|
|
306
|
+
if hasattr(node, 'lineno') and hasattr(node, 'end_lineno'):
|
|
307
|
+
if node.lineno <= error_line <= (node.end_lineno or node.lineno):
|
|
308
|
+
# Prefer smaller (more specific) matches
|
|
309
|
+
size = (node.end_lineno or node.lineno) - node.lineno
|
|
310
|
+
if size < best_match_size:
|
|
311
|
+
best_match = node
|
|
312
|
+
best_match_size = size
|
|
313
|
+
|
|
314
|
+
if not best_match:
|
|
315
|
+
return None
|
|
316
|
+
|
|
317
|
+
# Extract the full function/class with some buffer
|
|
318
|
+
start_line = max(1, best_match.lineno - 2) # 2 lines before for decorators
|
|
319
|
+
end_line = min(len(lines), (best_match.end_lineno or best_match.lineno) + 2)
|
|
320
|
+
|
|
321
|
+
# Build snippet with line numbers
|
|
322
|
+
snippet_lines = []
|
|
323
|
+
for i in range(start_line - 1, end_line):
|
|
324
|
+
line_num = i + 1
|
|
325
|
+
line_content = lines[i]
|
|
326
|
+
marker = " >> " if line_num == error_line else " "
|
|
327
|
+
snippet_lines.append(f"{marker}{line_num:4d} | {line_content}")
|
|
328
|
+
|
|
329
|
+
# Determine names
|
|
330
|
+
function_name = None
|
|
331
|
+
class_name = None
|
|
332
|
+
if isinstance(best_match, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
333
|
+
function_name = best_match.name
|
|
334
|
+
elif isinstance(best_match, ast.ClassDef):
|
|
335
|
+
class_name = best_match.name
|
|
336
|
+
|
|
337
|
+
return FileContext(
|
|
338
|
+
filepath=file_path,
|
|
339
|
+
line_number=error_line,
|
|
340
|
+
context_type="ast",
|
|
341
|
+
content="\n".join(snippet_lines),
|
|
342
|
+
function_name=function_name,
|
|
343
|
+
class_name=class_name,
|
|
344
|
+
language=Language.PYTHON,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def _line_based_extraction(
|
|
349
|
+
file_path: str,
|
|
350
|
+
lines: List[str],
|
|
351
|
+
error_line: int,
|
|
352
|
+
language: Language = Language.UNKNOWN,
|
|
353
|
+
context_lines: int = 50
|
|
354
|
+
) -> FileContext:
|
|
355
|
+
"""Fallback: extract +/- N lines around error.
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
file_path: Path to file
|
|
359
|
+
lines: Source lines
|
|
360
|
+
error_line: Target line number
|
|
361
|
+
language: Detected language
|
|
362
|
+
context_lines: Lines before/after to include
|
|
363
|
+
|
|
364
|
+
Returns:
|
|
365
|
+
FileContext with line-based extraction
|
|
366
|
+
"""
|
|
367
|
+
total_lines = len(lines)
|
|
368
|
+
start_line = max(1, error_line - context_lines)
|
|
369
|
+
end_line = min(total_lines, error_line + context_lines)
|
|
370
|
+
|
|
371
|
+
snippet_lines = []
|
|
372
|
+
for i in range(start_line - 1, end_line):
|
|
373
|
+
line_num = i + 1
|
|
374
|
+
line_content = lines[i]
|
|
375
|
+
marker = " >> " if line_num == error_line else " "
|
|
376
|
+
snippet_lines.append(f"{marker}{line_num:4d} | {line_content}")
|
|
377
|
+
|
|
378
|
+
return FileContext(
|
|
379
|
+
filepath=file_path,
|
|
380
|
+
line_number=error_line,
|
|
381
|
+
context_type="lines",
|
|
382
|
+
content="\n".join(snippet_lines),
|
|
383
|
+
language=language,
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def get_primary_file(contexts: List[FileContext]) -> Optional[FileContext]:
|
|
388
|
+
"""Get the primary file from contexts (last non-missing entry).
|
|
389
|
+
|
|
390
|
+
Usually the last file in the traceback is the most relevant.
|
|
391
|
+
|
|
392
|
+
Args:
|
|
393
|
+
contexts: List of FileContext objects
|
|
394
|
+
|
|
395
|
+
Returns:
|
|
396
|
+
The primary FileContext or None
|
|
397
|
+
"""
|
|
398
|
+
for ctx in reversed(contexts):
|
|
399
|
+
if ctx.context_type != "missing":
|
|
400
|
+
return ctx
|
|
401
|
+
return None
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def extract_context_v2(
|
|
405
|
+
error_log: str,
|
|
406
|
+
project_root: Optional[str] = None,
|
|
407
|
+
) -> Tuple[str, List[FileContextV2]]:
|
|
408
|
+
"""V2 context extraction with full language support.
|
|
409
|
+
|
|
410
|
+
Args:
|
|
411
|
+
error_log: The error log or traceback string
|
|
412
|
+
project_root: Optional project root for import resolution
|
|
413
|
+
|
|
414
|
+
Returns:
|
|
415
|
+
Tuple of (formatted context string, list of FileContextV2 objects)
|
|
416
|
+
"""
|
|
417
|
+
# Use the same extraction logic but return V2 objects
|
|
418
|
+
context_str, contexts = get_file_context(error_log)
|
|
419
|
+
|
|
420
|
+
v2_contexts = [ctx.to_v2() for ctx in contexts]
|
|
421
|
+
|
|
422
|
+
return context_str, v2_contexts
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: roma-debug
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Standalone CLI debugging tool powered by Gemini
|
|
5
|
+
Author: ROMA Team
|
|
6
|
+
Classifier: Development Status :: 3 - Alpha
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: click>=8.0.0
|
|
16
|
+
Requires-Dist: pydantic>=2.5.0
|
|
17
|
+
Requires-Dist: google-genai>=1.0.0
|
|
18
|
+
Requires-Dist: rich>=13.0.0
|
|
19
|
+
Requires-Dist: fastapi>=0.109.0
|
|
20
|
+
Requires-Dist: uvicorn>=0.27.0
|
|
21
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
22
|
+
Requires-Dist: tree-sitter>=0.23.0
|
|
23
|
+
Requires-Dist: tree-sitter-python>=0.23.0
|
|
24
|
+
Requires-Dist: tree-sitter-javascript>=0.23.0
|
|
25
|
+
Requires-Dist: tree-sitter-typescript>=0.23.0
|
|
26
|
+
Requires-Dist: tree-sitter-go>=0.23.0
|
|
27
|
+
Requires-Dist: tree-sitter-rust>=0.23.0
|
|
28
|
+
Requires-Dist: tree-sitter-java>=0.23.0
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
Dynamic: requires-dist
|
|
33
|
+
Dynamic: requires-python
|
|
34
|
+
Dynamic: summary
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
roma_debug/__init__.py,sha256=nduW0_uiplK4TqgBEihMu9gbcZiYmQH95rwhQlt1O5U,73
|
|
2
|
+
roma_debug/config.py,sha256=ynIlTUQb95x_WtEsM7R4G0kgioBm2UsAhhZzSAAZkI0,2052
|
|
3
|
+
roma_debug/main.py,sha256=h_JoaXD1Tt236UtMGY7jftgqZoG7WU8W1EnjQf1ZHuY,25697
|
|
4
|
+
roma_debug/prompts.py,sha256=gICok5kamF6QOeo14eNKdvp8TeuDBAjB5KQapMlLrgU,7141
|
|
5
|
+
roma_debug/server.py,sha256=8v6qIy25T9d9Y1dB_zBeIMEsGe1vcImEXQ3LV38Eo1U,7446
|
|
6
|
+
roma_debug/core/__init__.py,sha256=m7Nus3vI9QeZhwZWHSs8-p4F338JRjE8XSz-OOvt_Co,114
|
|
7
|
+
roma_debug/core/engine.py,sha256=L0fFrNKZZ5zET_m5kbIcQxqGW3KikGNiO-giCwQXAeU,13282
|
|
8
|
+
roma_debug/core/models.py,sha256=8wqlsx_N8lYjZ4rLq7S3-AcbLiaTy7u7gv6QLW77tkI,10545
|
|
9
|
+
roma_debug/parsers/__init__.py,sha256=B1Xk6zYvghqRwcIEcZy3eX3JtOc0IbIQqpTVu3Ivdc4,491
|
|
10
|
+
roma_debug/parsers/base.py,sha256=eXS888T8K-PVXzGPIFp-asTUOwCEjSRr38DohiwPV_U,5465
|
|
11
|
+
roma_debug/parsers/python_ast_parser.py,sha256=-92VDCkIPvz2eqMXDsBdfFrtCKcVIrrqpgh8AdC9BaM,9079
|
|
12
|
+
roma_debug/parsers/registry.py,sha256=JEVLASy6Bq__Yb3xokH8uOlo9OEXB47aVlsjtuBIBZg,5578
|
|
13
|
+
roma_debug/parsers/traceback_patterns.py,sha256=0Vf3UeW0-iJVLS4_IJchb556tEzhDIIGg9VRgTEVK5A,10880
|
|
14
|
+
roma_debug/parsers/treesitter_parser.py,sha256=6U1UU1tLcbdBUec_Q6niwUUF15J5MenZCfGwiyRhaTU,21297
|
|
15
|
+
roma_debug/tracing/__init__.py,sha256=Za80mYx08DK4cICq_kJiOp6QHL_zVmZMcSJi1rdRgbw,952
|
|
16
|
+
roma_debug/tracing/call_chain.py,sha256=coFOexGZOiiAmry6gc_o-AK9SoAdhoJuNwUBEBCNwKM,8853
|
|
17
|
+
roma_debug/tracing/context_builder.py,sha256=EevjP5NjPcH8_TA8r-hlFQFMpQBM5K6IqHP2TN-_5d8,25392
|
|
18
|
+
roma_debug/tracing/dependency_graph.py,sha256=kC9bP9g_HR-5dPIjTBQ6GGvlkrhdX_sLF1b-cdjtDkA,9399
|
|
19
|
+
roma_debug/tracing/error_analyzer.py,sha256=nTIFXDGceRX1K7QkBSFTG7tse01XRATZDJm32yoRE7c,12595
|
|
20
|
+
roma_debug/tracing/import_resolver.py,sha256=HBiL17ojN1MvjI_-dA5HWJ7E0Ie-2cIhRcVEuJM4V3c,10357
|
|
21
|
+
roma_debug/tracing/project_scanner.py,sha256=q1jmO5Wm5Dpaab58kfQ_EIX4NVRS87FETGITXHueIbw,18067
|
|
22
|
+
roma_debug/utils/__init__.py,sha256=XxTYoo8gCFrcEx6_LvKDTxKhD0CnSmeiub8bPW0mZOg,125
|
|
23
|
+
roma_debug/utils/context.py,sha256=VtnCwGV_d4n05KZ6McH_0HTvbROMeSWvfKV5ZcI4WRU,13545
|
|
24
|
+
roma_debug-0.1.0.dist-info/licenses/LICENSE,sha256=83lDVbRoeUNHeZi_xRYBuCVePZtbGCRcKt_leGlRFs8,11348
|
|
25
|
+
tests/__init__.py,sha256=a9m7ixR4qxbxJZjdpc3GJFp4rErm1BZN6cGOPlAfjm0,28
|
|
26
|
+
tests/test_context.py,sha256=WVrAwuqvmkhoJMWrF0I18-VV5bmXDwbegsck2XOVasw,7132
|
|
27
|
+
tests/test_engine.py,sha256=bhu8Lc6IwkCbCZy3nzcyHUq7ecSbN9gKbI-r2qXPSqA,9977
|
|
28
|
+
tests/test_parsers.py,sha256=7tsOlcBuv_8RJcUvA0TqPb92FehtXPLaC8nNBbuZp1k,16056
|
|
29
|
+
tests/test_project_scanner.py,sha256=cN5ZSoxqyT9ZUfxC4LHeYtNB5j68j8bUVzPyySrYKfA,9268
|
|
30
|
+
tests/test_traceback_patterns.py,sha256=dL8gzmCEyBx5WchvceB98YwMIf6Z5_FmWzBxrC7nSfU,6779
|
|
31
|
+
tests/test_tracing.py,sha256=N53hX3Mh1C8Q9HDzAusW6-8BRSDwEUkT7ipswiT2rvM,9522
|
|
32
|
+
roma_debug-0.1.0.dist-info/METADATA,sha256=O1RyReLjg7Xr7-xEnbHqFZEljoKVGsQsNgz8wdZBJeA,1146
|
|
33
|
+
roma_debug-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
34
|
+
roma_debug-0.1.0.dist-info/entry_points.txt,sha256=z7vb9CzOFmKWg_JwpzOIxpstebIzqeiOmaHiEqM6HbI,45
|
|
35
|
+
roma_debug-0.1.0.dist-info/top_level.txt,sha256=aL4bhVn3nECTAeTcxWQZkogEKOnI57eWiLNoQWARIRk,17
|
|
36
|
+
roma_debug-0.1.0.dist-info/RECORD,,
|