raggiecode 0.2.1__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.
- Agent/__init__.py +0 -0
- Agent/agent.py +891 -0
- Agent/chat_history_db.py +1500 -0
- Agent/command.py +49 -0
- Agent/config.py +46 -0
- Agent/effort_levels.py +33 -0
- Agent/git_manager.py +727 -0
- Agent/tools.py +35 -0
- Commands/__init__.py +18 -0
- Commands/effort.py +42 -0
- Commands/global_todo.py +23 -0
- Commands/help.py +22 -0
- Commands/reasoning.py +24 -0
- Commands/redo.py +11 -0
- Commands/reindex.py +27 -0
- Commands/shell.py +28 -0
- Commands/stream.py +24 -0
- Commands/undo.py +13 -0
- Commands/unlimited_effort.py +8 -0
- Commands/window_size.py +29 -0
- RAG/__init__.py +0 -0
- RAG/document.py +119 -0
- RAG/find.py +408 -0
- RAG/graph.py +231 -0
- Tools/GetFileCodeStructure.py +43 -0
- Tools/GetSymbolSourceCode.py +27 -0
- Tools/__init__.py +39 -0
- Tools/ask_user.py +102 -0
- Tools/dispatch_subagent.py +215 -0
- Tools/document.py +35 -0
- Tools/edit_symbol.py +250 -0
- Tools/fuzzy_search.py +119 -0
- Tools/list_dir.py +51 -0
- Tools/read.py +49 -0
- Tools/read_image.py +75 -0
- Tools/remove.py +75 -0
- Tools/replace.py +305 -0
- Tools/search.py +41 -0
- Tools/shell.py +149 -0
- Tools/shell_kill.py +87 -0
- Tools/temp_background_service.py +113 -0
- Tools/todo_list.py +481 -0
- Tools/utils.py +116 -0
- Tools/view_changes.py +179 -0
- Tools/walk_call_tree.py +30 -0
- Tools/web_fetch.py +175 -0
- Tools/web_search.py +69 -0
- Tools/write.py +48 -0
- cli.py +111 -0
- config/__init__.py +0 -0
- config/coder_system_prompt.md +119 -0
- config/roles.json +43 -0
- config/tools.json +709 -0
- indexing/__init__.py +0 -0
- indexing/cli.py +128 -0
- indexing/code_index_sdk.py +832 -0
- indexing/code_indexer.py +1763 -0
- indexing/db_schema.py +396 -0
- indexing/export_to_json.py +346 -0
- indexing/extractors.py +189 -0
- indexing/file_utils.py +97 -0
- indexing/frontend/__init__.py +0 -0
- indexing/frontend/css_extractor.py +195 -0
- indexing/frontend/css_parser.py +387 -0
- indexing/frontend/css_selector_utils.py +226 -0
- indexing/frontend/edit_safety.py +573 -0
- indexing/frontend/graph.py +838 -0
- indexing/frontend/html_extractor.py +496 -0
- indexing/frontend/html_parser.py +314 -0
- indexing/frontend/jsx_extractor.py +1204 -0
- indexing/frontend/location_lookup.py +247 -0
- indexing/frontend/resolver.py +485 -0
- indexing/frontend/runtime_resolver.py +862 -0
- indexing/frontend/semantic_output.py +705 -0
- indexing/frontend/source_location.py +69 -0
- indexing/frontend_config.py +72 -0
- indexing/frontend_models.py +347 -0
- indexing/language_config.py +360 -0
- indexing/models.py +284 -0
- indexing/node_utils.py +1112 -0
- indexing/parse_worker.py +1082 -0
- indexing/queries.py +1542 -0
- indexing/sdk_examples.py +426 -0
- interactive.py +248 -0
- raggie.py +673 -0
- raggiecode-0.2.1.dist-info/METADATA +944 -0
- raggiecode-0.2.1.dist-info/RECORD +93 -0
- raggiecode-0.2.1.dist-info/WHEEL +5 -0
- raggiecode-0.2.1.dist-info/entry_points.txt +2 -0
- raggiecode-0.2.1.dist-info/top_level.txt +10 -0
- skills/__init__.py +3 -0
- skills/manager.py +114 -0
- skills/tool.py +121 -0
indexing/sdk_examples.py
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Examples demonstrating the Code Index SDK for AI Agents.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from indexing.code_index_sdk import CodeIndexSDK
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def example_basic_queries():
|
|
10
|
+
"""Basic query examples."""
|
|
11
|
+
print("=== Basic Queries ===\n")
|
|
12
|
+
|
|
13
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
14
|
+
# Get all files
|
|
15
|
+
files = sdk.get_files()
|
|
16
|
+
print(f"Total files: {len(files)}")
|
|
17
|
+
for file in files[:5]:
|
|
18
|
+
print(f" - {file.path} ({file.language})")
|
|
19
|
+
|
|
20
|
+
# Get statistics
|
|
21
|
+
stats = sdk.get_statistics()
|
|
22
|
+
print(f"\nStatistics: {stats}")
|
|
23
|
+
|
|
24
|
+
# Get language breakdown
|
|
25
|
+
lang_stats = sdk.get_language_statistics()
|
|
26
|
+
print(f"Language breakdown: {lang_stats}")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def example_function_search():
|
|
30
|
+
"""Function search examples."""
|
|
31
|
+
print("\n=== Function Search ===\n")
|
|
32
|
+
|
|
33
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
34
|
+
# Search for functions by pattern
|
|
35
|
+
render_funcs = sdk.search_functions("render")
|
|
36
|
+
print(f"Functions matching 'render': {len(render_funcs)}")
|
|
37
|
+
for func in render_funcs[:3]:
|
|
38
|
+
print(f" - {func.name} in {func.file_path}")
|
|
39
|
+
print(f" Parameters: {[p['name'] for p in func.parameters]}")
|
|
40
|
+
|
|
41
|
+
# Get specific function by name
|
|
42
|
+
main_funcs = sdk.get_function_by_name("main")
|
|
43
|
+
print(f"\nFunctions named 'main': {len(main_funcs)}")
|
|
44
|
+
for func in main_funcs:
|
|
45
|
+
print(f" - {func.file_path}:{func.location.start_line}")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def example_class_exploration():
|
|
49
|
+
"""Class exploration examples."""
|
|
50
|
+
print("\n=== Class Exploration ===\n")
|
|
51
|
+
|
|
52
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
53
|
+
# Search for classes
|
|
54
|
+
classes = sdk.search_classes("Service")
|
|
55
|
+
print(f"Classes matching 'Service': {len(classes)}")
|
|
56
|
+
|
|
57
|
+
if classes:
|
|
58
|
+
cls = classes[0]
|
|
59
|
+
print(f"\nExploring class: {cls.name}")
|
|
60
|
+
print(f" File: {cls.file_path}")
|
|
61
|
+
print(f" Base classes: {cls.base_classes}")
|
|
62
|
+
|
|
63
|
+
# Get class methods
|
|
64
|
+
methods = sdk.get_class_methods(cls.id)
|
|
65
|
+
print(f" Methods ({len(methods)}):")
|
|
66
|
+
for method in methods[:5]:
|
|
67
|
+
print(f" - {method.name}({', '.join(p['name'] for p in method.parameters)})")
|
|
68
|
+
|
|
69
|
+
# Get class variables
|
|
70
|
+
variables = sdk.get_class_variables(cls.id)
|
|
71
|
+
print(f" Variables ({len(variables)}):")
|
|
72
|
+
for var in variables[:5]:
|
|
73
|
+
print(f" - {var.name}: {var.field_type or 'unknown'}")
|
|
74
|
+
|
|
75
|
+
# Get nested classes
|
|
76
|
+
nested = sdk.get_nested_classes(cls.id)
|
|
77
|
+
if nested:
|
|
78
|
+
print(f" Nested classes: {[c.name for c in nested]}")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def example_file_analysis():
|
|
82
|
+
"""File analysis examples."""
|
|
83
|
+
print("\n=== File Analysis ===\n")
|
|
84
|
+
|
|
85
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
86
|
+
# Get a specific file
|
|
87
|
+
file = sdk.get_files()[0]
|
|
88
|
+
print(f"Analyzing file: {file.path}")
|
|
89
|
+
|
|
90
|
+
# Get complete file summary
|
|
91
|
+
summary = sdk.get_file_summary(file.id)
|
|
92
|
+
print(f"\nFile summary:")
|
|
93
|
+
print(f" Functions: {len(summary['functions'])}")
|
|
94
|
+
print(f" Classes: {len(summary['classes'])}")
|
|
95
|
+
print(f" Variables: {len(summary['variables'])}")
|
|
96
|
+
print(f" Type aliases: {len(summary['type_aliases'])}")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def example_cross_reference():
|
|
100
|
+
"""Cross-reference examples."""
|
|
101
|
+
print("\n=== Cross-Reference ===\n")
|
|
102
|
+
|
|
103
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
104
|
+
# Find all usages of a pattern across different entity types
|
|
105
|
+
results = sdk.search_all("auth")
|
|
106
|
+
print(f"Results for 'auth' pattern:")
|
|
107
|
+
print(f" Functions: {len(results['functions'])}")
|
|
108
|
+
print(f" Classes: {len(results['classes'])}")
|
|
109
|
+
print(f" Variables: {len(results['variables'])}")
|
|
110
|
+
print(f" Type aliases: {len(results['type_aliases'])}")
|
|
111
|
+
|
|
112
|
+
# Show some results
|
|
113
|
+
if results['functions']:
|
|
114
|
+
print(f"\n Sample functions:")
|
|
115
|
+
for func in results['functions'][:3]:
|
|
116
|
+
print(f" - {func['name']} in {func['file_path']}")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def example_ai_agent_workflow():
|
|
120
|
+
"""Example workflow for an AI agent."""
|
|
121
|
+
print("\n=== AI Agent Workflow ===\n")
|
|
122
|
+
|
|
123
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
124
|
+
# Agent wants to understand the codebase structure
|
|
125
|
+
print("1. Understanding codebase structure...")
|
|
126
|
+
stats = sdk.get_statistics()
|
|
127
|
+
lang_stats = sdk.get_language_statistics()
|
|
128
|
+
print(f" Total files: {stats['total_files']}")
|
|
129
|
+
print(f" Languages: {list(lang_stats.keys())}")
|
|
130
|
+
|
|
131
|
+
# Agent wants to find authentication-related code
|
|
132
|
+
print("\n2. Finding authentication code...")
|
|
133
|
+
auth_funcs = sdk.search_functions("auth")
|
|
134
|
+
auth_classes = sdk.search_classes("Auth")
|
|
135
|
+
print(f" Found {len(auth_funcs)} auth-related functions")
|
|
136
|
+
print(f" Found {len(auth_classes)} auth-related classes")
|
|
137
|
+
|
|
138
|
+
# Agent wants to explore a specific class
|
|
139
|
+
if auth_classes:
|
|
140
|
+
print(f"\n3. Exploring {auth_classes[0].name} class...")
|
|
141
|
+
cls = auth_classes[0]
|
|
142
|
+
methods = sdk.get_class_methods(cls.id)
|
|
143
|
+
print(f" Class has {len(methods)} methods")
|
|
144
|
+
|
|
145
|
+
# Agent wants to understand method signatures
|
|
146
|
+
print(f"\n4. Method signatures:")
|
|
147
|
+
for method in methods[:5]:
|
|
148
|
+
params = ", ".join(f"{p['name']}: {p.get('type', 'any')}" for p in method.parameters)
|
|
149
|
+
return_type = method.return_type or "void"
|
|
150
|
+
print(f" {method.name}({params}) -> {return_type}")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def example_context_manager():
|
|
154
|
+
"""Context manager usage example."""
|
|
155
|
+
print("\n=== Context Manager ===\n")
|
|
156
|
+
|
|
157
|
+
# Using context manager for automatic cleanup
|
|
158
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
159
|
+
files = sdk.get_files()
|
|
160
|
+
print(f"Files in context: {len(files)}")
|
|
161
|
+
|
|
162
|
+
# Connection is automatically closed here
|
|
163
|
+
print("Connection closed automatically.")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def example_manual_connection():
|
|
167
|
+
"""Manual connection management example."""
|
|
168
|
+
print("\n=== Manual Connection ===\n")
|
|
169
|
+
|
|
170
|
+
sdk = CodeIndexSDK("code_index.db")
|
|
171
|
+
try:
|
|
172
|
+
files = sdk.get_files()
|
|
173
|
+
print(f"Files: {len(files)}")
|
|
174
|
+
finally:
|
|
175
|
+
sdk.close()
|
|
176
|
+
print("Connection closed manually.")
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def example_internal_external_imports():
|
|
180
|
+
"""Example of filtering imports by internal/external dependencies."""
|
|
181
|
+
print("\n=== Internal vs External Imports ===\n")
|
|
182
|
+
|
|
183
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
184
|
+
# Get all files
|
|
185
|
+
files = sdk.get_files()
|
|
186
|
+
if not files:
|
|
187
|
+
print("No files in database. Please run indexing first.")
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
# Analyze first file
|
|
191
|
+
file = files[0]
|
|
192
|
+
print(f"Analyzing file: {file.path}")
|
|
193
|
+
|
|
194
|
+
# Get all imports
|
|
195
|
+
all_imports = sdk.get_file_imports(file.id)
|
|
196
|
+
print(f"\nTotal imports: {len(all_imports)}")
|
|
197
|
+
|
|
198
|
+
# Get external imports
|
|
199
|
+
external_imports = sdk.get_external_imports(file.id)
|
|
200
|
+
print(f"External (third-party) imports: {len(external_imports)}")
|
|
201
|
+
for imp in external_imports[:5]:
|
|
202
|
+
print(f" - {imp.name}")
|
|
203
|
+
|
|
204
|
+
# Get internal imports
|
|
205
|
+
internal_imports = sdk.get_internal_imports(file.id)
|
|
206
|
+
print(f"\nInternal (project) imports: {len(internal_imports)}")
|
|
207
|
+
for imp in internal_imports[:5]:
|
|
208
|
+
print(f" - {imp.name}")
|
|
209
|
+
|
|
210
|
+
# Get all external imports across the entire codebase
|
|
211
|
+
print("\n--- All External Dependencies in Codebase ---")
|
|
212
|
+
all_external = sdk.get_external_imports()
|
|
213
|
+
# Group by import name to show unique external dependencies
|
|
214
|
+
unique_external = {}
|
|
215
|
+
for imp in all_external:
|
|
216
|
+
if imp.name not in unique_external:
|
|
217
|
+
unique_external[imp.name] = []
|
|
218
|
+
unique_external[imp.name].append(imp.file_path)
|
|
219
|
+
|
|
220
|
+
print(f"Unique external dependencies: {len(unique_external)}")
|
|
221
|
+
for dep_name, files in list(unique_external.items())[:10]:
|
|
222
|
+
print(f" - {dep_name} (used in {len(files)} file(s))")
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def example_source_body_reading():
|
|
226
|
+
"""Source body reading examples."""
|
|
227
|
+
print("\n=== Source Body Reading ===\n")
|
|
228
|
+
|
|
229
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
230
|
+
# Read a function body by name
|
|
231
|
+
funcs = sdk.get_functions()
|
|
232
|
+
if not funcs:
|
|
233
|
+
print("No functions in database. Please run indexing first.")
|
|
234
|
+
return
|
|
235
|
+
|
|
236
|
+
func_name = funcs[0].name
|
|
237
|
+
print(f"Reading body of function: {func_name}")
|
|
238
|
+
body = sdk.get_function_body(func_name)
|
|
239
|
+
if body:
|
|
240
|
+
preview = body[:200] + "..." if len(body) > 200 else body
|
|
241
|
+
print(f"\n{preview}")
|
|
242
|
+
else:
|
|
243
|
+
print(" (source file not resolvable)")
|
|
244
|
+
|
|
245
|
+
# Disambiguate by file path when the same name appears in multiple files
|
|
246
|
+
matches = sdk.get_function_by_name(func_name)
|
|
247
|
+
if len(matches) > 1:
|
|
248
|
+
print(f"\n'{func_name}' appears in {len(matches)} files — reading from first:")
|
|
249
|
+
body = sdk.get_function_body(func_name, file_path=matches[0].file_path)
|
|
250
|
+
if body:
|
|
251
|
+
print(body[:200])
|
|
252
|
+
|
|
253
|
+
# Read a class body
|
|
254
|
+
classes = sdk.get_classes()
|
|
255
|
+
if classes:
|
|
256
|
+
cls_name = classes[0].name
|
|
257
|
+
print(f"\nReading body of class: {cls_name}")
|
|
258
|
+
body = sdk.get_class_body(cls_name)
|
|
259
|
+
if body:
|
|
260
|
+
preview = body[:200] + "..." if len(body) > 200 else body
|
|
261
|
+
print(f"\n{preview}")
|
|
262
|
+
else:
|
|
263
|
+
print(" (source file not resolvable)")
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def example_complexity_filtering():
|
|
267
|
+
"""Filter symbols by complexity (branches and lines of code)."""
|
|
268
|
+
print("\n=== Complexity Filtering ===\n")
|
|
269
|
+
|
|
270
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
271
|
+
# Find functions with high branching complexity (5+ branches)
|
|
272
|
+
high_branch_funcs = sdk.get_functions_by_complexity(min_branches=5)
|
|
273
|
+
print(f"Functions with 5+ branches: {len(high_branch_funcs)}")
|
|
274
|
+
for func in high_branch_funcs[:5]:
|
|
275
|
+
lines = func.location.end_line - func.location.start_line + 1
|
|
276
|
+
print(f" - {func.name}: {func.branch_count} branches, {lines} LOC")
|
|
277
|
+
|
|
278
|
+
# Find long functions (30+ lines)
|
|
279
|
+
long_funcs = sdk.get_functions_by_complexity(min_lines=30)
|
|
280
|
+
print(f"\nFunctions with 30+ lines: {len(long_funcs)}")
|
|
281
|
+
for func in long_funcs[:5]:
|
|
282
|
+
lines = func.location.end_line - func.location.start_line + 1
|
|
283
|
+
print(f" - {func.name}: {lines} lines, {func.branch_count} branches")
|
|
284
|
+
|
|
285
|
+
# LOGICAL OR: Find functions that are EITHER high-branch OR long
|
|
286
|
+
# (good for finding "suspicious" code to review)
|
|
287
|
+
complex_funcs = sdk.get_functions_by_complexity(
|
|
288
|
+
min_branches=5,
|
|
289
|
+
min_lines=30,
|
|
290
|
+
match_any=True # LOGICAL OR
|
|
291
|
+
)
|
|
292
|
+
print(f"\nComplex functions (5+ branches OR 30+ lines): {len(complex_funcs)}")
|
|
293
|
+
|
|
294
|
+
# LOGICAL AND: Find functions that are BOTH high-branch AND long
|
|
295
|
+
# (the truly complex functions)
|
|
296
|
+
very_complex_funcs = sdk.get_functions_by_complexity(
|
|
297
|
+
min_branches=5,
|
|
298
|
+
min_lines=30,
|
|
299
|
+
match_any=False # LOGICAL AND
|
|
300
|
+
)
|
|
301
|
+
print(f"Very complex functions (5+ branches AND 30+ lines): {len(very_complex_funcs)}")
|
|
302
|
+
|
|
303
|
+
# Range filtering: medium complexity functions
|
|
304
|
+
medium_funcs = sdk.get_functions_by_complexity(
|
|
305
|
+
min_branches=2,
|
|
306
|
+
max_branches=5,
|
|
307
|
+
min_lines=10,
|
|
308
|
+
max_lines=30
|
|
309
|
+
)
|
|
310
|
+
print(f"\nMedium complexity functions (2-5 branches, 10-30 lines): {len(medium_funcs)}")
|
|
311
|
+
|
|
312
|
+
# Filter by file
|
|
313
|
+
files = sdk.get_files()
|
|
314
|
+
if files:
|
|
315
|
+
file_funcs = sdk.get_functions_by_complexity(
|
|
316
|
+
min_branches=3,
|
|
317
|
+
file_id=files[0].id
|
|
318
|
+
)
|
|
319
|
+
print(f"\nComplex functions in {files[0].path}: {len(file_funcs)}")
|
|
320
|
+
|
|
321
|
+
# Convenience method for finding complex code
|
|
322
|
+
complex_symbols = sdk.get_complex_symbols(min_branches=5, min_lines=30)
|
|
323
|
+
print(f"\nAll complex symbols: {len(complex_symbols)}")
|
|
324
|
+
|
|
325
|
+
# Filter class methods by complexity
|
|
326
|
+
classes = sdk.get_classes()
|
|
327
|
+
if classes:
|
|
328
|
+
complex_methods = sdk.get_methods_by_complexity(
|
|
329
|
+
class_id=classes[0].id,
|
|
330
|
+
min_branches=3,
|
|
331
|
+
match_any=True
|
|
332
|
+
)
|
|
333
|
+
print(f"\nComplex methods in class '{classes[0].name}': {len(complex_methods)}")
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def example_description_management():
|
|
337
|
+
"""Description management examples for AI-generated documentation."""
|
|
338
|
+
print("\n=== Description Management ===\n")
|
|
339
|
+
|
|
340
|
+
with CodeIndexSDK("code_index.db") as sdk:
|
|
341
|
+
# Get a function to work with
|
|
342
|
+
funcs = sdk.get_functions()
|
|
343
|
+
if funcs:
|
|
344
|
+
func = funcs[0]
|
|
345
|
+
print(f"Setting description for function: {func.name}")
|
|
346
|
+
|
|
347
|
+
# Set description by ID
|
|
348
|
+
success = sdk.set_function_description(func.id, "Handles user authentication flow")
|
|
349
|
+
print(f" Updated: {success}")
|
|
350
|
+
|
|
351
|
+
# Verify the description was set
|
|
352
|
+
updated_func = sdk.get_function_by_id(func.id)
|
|
353
|
+
print(f" Description: {updated_func.description}")
|
|
354
|
+
|
|
355
|
+
# Set description by name (with optional file path disambiguation)
|
|
356
|
+
success = sdk.set_function_description_by_name(
|
|
357
|
+
"main",
|
|
358
|
+
"Application entry point",
|
|
359
|
+
file_path="src/main.py" # Optional: disambiguate if multiple "main" functions exist
|
|
360
|
+
)
|
|
361
|
+
print(f"\nSet 'main' function description: {success}")
|
|
362
|
+
|
|
363
|
+
# Set description for a class
|
|
364
|
+
classes = sdk.get_classes()
|
|
365
|
+
if classes:
|
|
366
|
+
cls = classes[0]
|
|
367
|
+
print(f"\nSetting description for class: {cls.name}")
|
|
368
|
+
sdk.set_class_description(cls.id, "Service class for managing user accounts")
|
|
369
|
+
|
|
370
|
+
# Set by name
|
|
371
|
+
sdk.set_class_description_by_name("UserService", "Handles user operations")
|
|
372
|
+
|
|
373
|
+
# Set description for a variable
|
|
374
|
+
variables = sdk.get_variables()
|
|
375
|
+
if variables:
|
|
376
|
+
var = variables[0]
|
|
377
|
+
print(f"\nSetting description for variable: {var.name}")
|
|
378
|
+
sdk.set_variable_description(var.id, "Configuration timeout in seconds")
|
|
379
|
+
|
|
380
|
+
# Set description for a type alias
|
|
381
|
+
type_aliases = sdk.get_type_aliases()
|
|
382
|
+
if type_aliases:
|
|
383
|
+
alias = type_aliases[0]
|
|
384
|
+
print(f"\nSetting description for type alias: {alias.name}")
|
|
385
|
+
sdk.set_type_alias_description(alias.id, "User ID type alias for clarity")
|
|
386
|
+
|
|
387
|
+
# Set description for a struct (Go)
|
|
388
|
+
structs = sdk.get_structs()
|
|
389
|
+
if structs:
|
|
390
|
+
struct = structs[0]
|
|
391
|
+
print(f"\nSetting description for struct: {struct.name}")
|
|
392
|
+
sdk.set_struct_description(struct.id, "Represents a database connection pool")
|
|
393
|
+
|
|
394
|
+
# Set description for an interface (Go)
|
|
395
|
+
interfaces = sdk.get_interfaces()
|
|
396
|
+
if interfaces:
|
|
397
|
+
interface = interfaces[0]
|
|
398
|
+
print(f"\nSetting description for interface: {interface.name}")
|
|
399
|
+
sdk.set_interface_description(interface.id, "Defines storage backend interface")
|
|
400
|
+
|
|
401
|
+
# Generic method for any symbol type
|
|
402
|
+
if funcs:
|
|
403
|
+
print(f"\nUsing generic set_symbol_description for function {funcs[0].name}")
|
|
404
|
+
sdk.set_symbol_description(
|
|
405
|
+
symbol_type='function',
|
|
406
|
+
symbol_id=funcs[0].id,
|
|
407
|
+
description="Updated via generic method"
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
if __name__ == "__main__":
|
|
412
|
+
# Run all examples
|
|
413
|
+
example_basic_queries()
|
|
414
|
+
example_function_search()
|
|
415
|
+
example_class_exploration()
|
|
416
|
+
example_file_analysis()
|
|
417
|
+
example_cross_reference()
|
|
418
|
+
example_ai_agent_workflow()
|
|
419
|
+
example_context_manager()
|
|
420
|
+
example_manual_connection()
|
|
421
|
+
example_internal_external_imports()
|
|
422
|
+
example_source_body_reading()
|
|
423
|
+
example_complexity_filtering()
|
|
424
|
+
example_description_management()
|
|
425
|
+
|
|
426
|
+
print("\n=== All examples completed ===")
|
interactive.py
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent run loops for Raggie (interactive and non-interactive modes).
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import sys
|
|
7
|
+
from importlib.metadata import version
|
|
8
|
+
from prompt_toolkit import prompt
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
from rich.markdown import Markdown
|
|
11
|
+
from rich.live import Live
|
|
12
|
+
|
|
13
|
+
from Agent.effort_levels import EFFORT_LEVELS, DEFAULT_EFFORT, effort_name
|
|
14
|
+
from Agent.chat_history_db import set_session_effort, get_session_effort, get_session_depth
|
|
15
|
+
|
|
16
|
+
console = Console()
|
|
17
|
+
GREEN = "\033[32m"
|
|
18
|
+
DIM = "\033[2m"
|
|
19
|
+
RESET = "\033[0m"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _prompt_effort(session_id, value=None):
|
|
23
|
+
"""Ask the user to pick an effort level and store it on the session."""
|
|
24
|
+
current = get_session_effort(session_id)
|
|
25
|
+
default_num = current if current is not None else DEFAULT_EFFORT
|
|
26
|
+
|
|
27
|
+
for num, info in EFFORT_LEVELS.items():
|
|
28
|
+
marker = " (selected)" if num == default_num else ""
|
|
29
|
+
print(f" {num}. {info['name']}{marker}")
|
|
30
|
+
|
|
31
|
+
while True:
|
|
32
|
+
|
|
33
|
+
if value is None:
|
|
34
|
+
try:
|
|
35
|
+
print(f"\nEffort level:")
|
|
36
|
+
choice = prompt(f"Select effort (1-{len(EFFORT_LEVELS)}) [{default_num}]: ").strip()
|
|
37
|
+
except (EOFError, KeyboardInterrupt):
|
|
38
|
+
effort = default_num
|
|
39
|
+
set_session_effort(session_id, effort)
|
|
40
|
+
return effort
|
|
41
|
+
else:
|
|
42
|
+
choice = value
|
|
43
|
+
|
|
44
|
+
if not choice:
|
|
45
|
+
effort = default_num
|
|
46
|
+
break
|
|
47
|
+
try:
|
|
48
|
+
effort = int(choice)
|
|
49
|
+
except ValueError:
|
|
50
|
+
print("Invalid number. Try again.")
|
|
51
|
+
continue
|
|
52
|
+
if effort not in EFFORT_LEVELS:
|
|
53
|
+
print(f"Pick a number between 1 and {len(EFFORT_LEVELS)}.")
|
|
54
|
+
continue
|
|
55
|
+
break
|
|
56
|
+
|
|
57
|
+
set_session_effort(session_id, effort)
|
|
58
|
+
return effort
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class StreamState:
|
|
62
|
+
"""Holds streaming display state across event calls."""
|
|
63
|
+
__slots__ = ("reasoning_started", "response_started", "live", "accumulated")
|
|
64
|
+
|
|
65
|
+
def __init__(self):
|
|
66
|
+
self.reasoning_started = False
|
|
67
|
+
self.response_started = False
|
|
68
|
+
self.live = None
|
|
69
|
+
self.accumulated = ""
|
|
70
|
+
|
|
71
|
+
def _stop_live(self):
|
|
72
|
+
if self.live is not None:
|
|
73
|
+
self.live.stop()
|
|
74
|
+
self.live = None
|
|
75
|
+
self.response_started = False
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _print_event(event, state, depth=0, model=""):
|
|
79
|
+
"""Process a single agent event and update stream state.
|
|
80
|
+
|
|
81
|
+
Returns the StreamState (mutated in place).
|
|
82
|
+
"""
|
|
83
|
+
kind = event[0]
|
|
84
|
+
|
|
85
|
+
if kind == "tool_call":
|
|
86
|
+
state._stop_live()
|
|
87
|
+
if state.reasoning_started:
|
|
88
|
+
print(f"{RESET}")
|
|
89
|
+
state.reasoning_started = False
|
|
90
|
+
tool_name = event[1]
|
|
91
|
+
tool_args = event[2]
|
|
92
|
+
tool_name = tool_name.replace("Ugly", "")
|
|
93
|
+
try:
|
|
94
|
+
args_dict = json.loads(tool_args)
|
|
95
|
+
desc = ", ".join(f"{k}={str(v)[:40]}" for k, v in args_dict.items())
|
|
96
|
+
console.print(f"[dim][tool] {tool_name}({desc})[/dim]")
|
|
97
|
+
except Exception:
|
|
98
|
+
console.print(f"[dim][tool] {tool_name}[/dim]")
|
|
99
|
+
|
|
100
|
+
elif kind == "reasoning":
|
|
101
|
+
state._stop_live()
|
|
102
|
+
if state.reasoning_started:
|
|
103
|
+
print(f"{RESET}")
|
|
104
|
+
state.reasoning_started = False
|
|
105
|
+
content = event[1]
|
|
106
|
+
print(f"{DIM}")
|
|
107
|
+
console.print(Markdown(content))
|
|
108
|
+
print(f"{RESET}")
|
|
109
|
+
|
|
110
|
+
elif kind == "reasoning_chunk":
|
|
111
|
+
state._stop_live()
|
|
112
|
+
if not state.reasoning_started:
|
|
113
|
+
print(f"{DIM}", end="", flush=True)
|
|
114
|
+
state.reasoning_started = True
|
|
115
|
+
print(event[1], end="", flush=True)
|
|
116
|
+
|
|
117
|
+
elif kind == "response":
|
|
118
|
+
state._stop_live()
|
|
119
|
+
if state.reasoning_started:
|
|
120
|
+
print(f"{RESET}")
|
|
121
|
+
state.reasoning_started = False
|
|
122
|
+
content = event[1]
|
|
123
|
+
print(f"{GREEN}\n\nAgent ({model}:{depth}):{RESET}")
|
|
124
|
+
console.print(Markdown(content))
|
|
125
|
+
|
|
126
|
+
elif kind == "response_chunk":
|
|
127
|
+
if not state.response_started:
|
|
128
|
+
if state.reasoning_started:
|
|
129
|
+
print(f"{RESET}")
|
|
130
|
+
state.reasoning_started = False
|
|
131
|
+
print(f"{GREEN}\n\nAgent ({model}:{depth}):{RESET}")
|
|
132
|
+
state.response_started = True
|
|
133
|
+
state.live = Live(
|
|
134
|
+
Markdown(event[1]),
|
|
135
|
+
console=console,
|
|
136
|
+
refresh_per_second=12,
|
|
137
|
+
transient=True,
|
|
138
|
+
)
|
|
139
|
+
state.live.start()
|
|
140
|
+
state.accumulated = event[1]
|
|
141
|
+
else:
|
|
142
|
+
state.accumulated += event[1]
|
|
143
|
+
state.live.update(Markdown(state.accumulated))
|
|
144
|
+
|
|
145
|
+
elif kind == "response_end":
|
|
146
|
+
final_content = state.accumulated
|
|
147
|
+
state._stop_live()
|
|
148
|
+
if final_content:
|
|
149
|
+
console.print(Markdown(final_content))
|
|
150
|
+
|
|
151
|
+
elif kind == "error":
|
|
152
|
+
state._stop_live()
|
|
153
|
+
if state.reasoning_started:
|
|
154
|
+
print(f"{RESET}")
|
|
155
|
+
state.reasoning_started = False
|
|
156
|
+
print(f"Error: {event[1]}")
|
|
157
|
+
|
|
158
|
+
return state
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def run_interactive(agent, role):
|
|
162
|
+
"""Run the interactive agent loop.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
agent: An Agent instance with tools and commands already set up.
|
|
166
|
+
role: The role name string.
|
|
167
|
+
"""
|
|
168
|
+
model_name = agent.roles[role].get("model", "unknown")
|
|
169
|
+
print(f"{GREEN}Raggie Agent ({role}) v{version('raggiecode')} - Interactive Mode{RESET}")
|
|
170
|
+
print(f"{GREEN}Press Esc followed by Enter to send message, or type 'exit' to quit{RESET}")
|
|
171
|
+
print("-" * 50)
|
|
172
|
+
print("\nuse /help to see all available commands")
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
state = StreamState()
|
|
176
|
+
depth = get_session_depth(agent.session_id)
|
|
177
|
+
model_name = agent.roles[role].get("model", "unknown")
|
|
178
|
+
for event in agent.resume_dangling_tool_work():
|
|
179
|
+
state = _print_event(event, state, depth, model_name)
|
|
180
|
+
except KeyboardInterrupt:
|
|
181
|
+
print("\n[interrupted]")
|
|
182
|
+
except EOFError:
|
|
183
|
+
print("\n\nAgent: Goodbye!")
|
|
184
|
+
return
|
|
185
|
+
|
|
186
|
+
while True:
|
|
187
|
+
try:
|
|
188
|
+
current = get_session_effort(agent.session_id)
|
|
189
|
+
if current is None:
|
|
190
|
+
set_session_effort(agent.session_id, DEFAULT_EFFORT)
|
|
191
|
+
current = DEFAULT_EFFORT
|
|
192
|
+
print(f"\n{DIM}Effort: {effort_name(current)} - to change it use /effort{RESET}")
|
|
193
|
+
print(f"{GREEN}\n\nYou:{RESET}")
|
|
194
|
+
user_input = prompt("> ", multiline=True)
|
|
195
|
+
except (EOFError, KeyboardInterrupt):
|
|
196
|
+
print("\n\nAgent: Goodbye!")
|
|
197
|
+
break
|
|
198
|
+
|
|
199
|
+
if user_input.lower().strip() in ['exit', 'quit']:
|
|
200
|
+
break
|
|
201
|
+
|
|
202
|
+
if not user_input.strip():
|
|
203
|
+
continue
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
state = StreamState()
|
|
207
|
+
depth = get_session_depth(agent.session_id)
|
|
208
|
+
model_name = agent.roles[role].get("model", "unknown")
|
|
209
|
+
for event in agent.start(user_input):
|
|
210
|
+
state = _print_event(event, state, depth, model_name)
|
|
211
|
+
except KeyboardInterrupt:
|
|
212
|
+
print("\n[interrupted]")
|
|
213
|
+
continue
|
|
214
|
+
except EOFError:
|
|
215
|
+
print("\n\nAgent: Goodbye!")
|
|
216
|
+
break
|
|
217
|
+
|
|
218
|
+
print()
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def run_non_interactive(agent, prompt_text, effort=None):
|
|
222
|
+
"""Run the agent with a single prompt and exit.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
agent: An Agent instance with tools and commands already set up.
|
|
226
|
+
prompt_text: The user prompt string.
|
|
227
|
+
effort: Optional effort level number (1-5). Defaults to session's current or DEFAULT_EFFORT.
|
|
228
|
+
"""
|
|
229
|
+
if effort is not None:
|
|
230
|
+
set_session_effort(agent.session_id, effort)
|
|
231
|
+
elif get_session_effort(agent.session_id) is None:
|
|
232
|
+
set_session_effort(agent.session_id, DEFAULT_EFFORT)
|
|
233
|
+
|
|
234
|
+
try:
|
|
235
|
+
state = StreamState()
|
|
236
|
+
for event in agent.start(prompt_text):
|
|
237
|
+
if event[0] == "error":
|
|
238
|
+
state._stop_live()
|
|
239
|
+
if state.reasoning_started:
|
|
240
|
+
print()
|
|
241
|
+
state.reasoning_started = False
|
|
242
|
+
print(f"Error: {event[1]}", file=sys.stderr)
|
|
243
|
+
sys.exit(1)
|
|
244
|
+
state = _print_event(event, state, get_session_depth(agent.session_id), agent.roles[agent.agent_role].get("model", "unknown"))
|
|
245
|
+
except KeyboardInterrupt:
|
|
246
|
+
print("\n[interrupted]")
|
|
247
|
+
except EOFError:
|
|
248
|
+
print("\nAgent: Goodbye!")
|