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
Tools/search.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from ripgrep_rs import search
|
|
2
|
+
from .utils import is_within_cwd
|
|
3
|
+
|
|
4
|
+
def handle(arguments, toolcall_id, parent_session_id=None):
|
|
5
|
+
search_term = arguments.get("search_term")
|
|
6
|
+
directory = arguments.get("directory")
|
|
7
|
+
|
|
8
|
+
# Check if the directory is outside the current working directory
|
|
9
|
+
if directory and not is_within_cwd(directory):
|
|
10
|
+
return {
|
|
11
|
+
"role": "tool",
|
|
12
|
+
"tool_call_id": toolcall_id,
|
|
13
|
+
"content": "Error: access denied - path is outside the current working directory",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
print(f"Searching for '{search_term}' in '{directory}'")
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
results = search(
|
|
20
|
+
patterns=[search_term],
|
|
21
|
+
paths=[directory]
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# ripgrep_rs returns a list of strings
|
|
25
|
+
if not results:
|
|
26
|
+
result = "No matches found."
|
|
27
|
+
else:
|
|
28
|
+
result = "".join(results)
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
"role": "tool",
|
|
32
|
+
"tool_call_id": toolcall_id,
|
|
33
|
+
"content": result.strip(),
|
|
34
|
+
}
|
|
35
|
+
except Exception as e:
|
|
36
|
+
print(f"Search error: {str(e)}")
|
|
37
|
+
return {
|
|
38
|
+
"role": "tool",
|
|
39
|
+
"tool_call_id": toolcall_id,
|
|
40
|
+
"content": f"Error executing search: {str(e)}",
|
|
41
|
+
}
|
Tools/shell.py
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
from .utils import is_ignored_by_gitignore, is_within_cwd, BLUE, RESET, reindex_after_change, remove_em_dashes
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _extract_paths(command):
|
|
9
|
+
"""Extract potential file paths from a shell command string.
|
|
10
|
+
|
|
11
|
+
Uses a simple heuristic: find tokens that look like paths (contain '/'
|
|
12
|
+
or a known extension) and resolve them relative to cwd. This catches
|
|
13
|
+
common cases like 'cat .env', 'sed -i file', 'rm -rf dir/', etc.
|
|
14
|
+
"""
|
|
15
|
+
paths = set()
|
|
16
|
+
cwd = os.getcwd()
|
|
17
|
+
|
|
18
|
+
# Split on whitespace and common shell operators
|
|
19
|
+
tokens = re.split(r'[\s;|&<>`$()]+', command)
|
|
20
|
+
for token in tokens:
|
|
21
|
+
token = token.strip().strip("'\"")
|
|
22
|
+
if not token or len(token) < 2:
|
|
23
|
+
continue
|
|
24
|
+
# Skip flags and options
|
|
25
|
+
if token.startswith('-'):
|
|
26
|
+
continue
|
|
27
|
+
# Resolve relative to cwd
|
|
28
|
+
candidate = os.path.join(cwd, token)
|
|
29
|
+
if os.path.lexists(candidate):
|
|
30
|
+
paths.add(os.path.normpath(candidate))
|
|
31
|
+
elif os.path.lexists(token):
|
|
32
|
+
paths.add(os.path.normpath(token))
|
|
33
|
+
|
|
34
|
+
return paths
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def handle(arguments, toolcall_id, code_indexer=None):
|
|
38
|
+
|
|
39
|
+
command = arguments["command"]
|
|
40
|
+
timeout = arguments.get("timeout", 30)
|
|
41
|
+
print(f"{BLUE}Shell{RESET}")
|
|
42
|
+
|
|
43
|
+
# Enforce sandbox: block commands that touch paths outside cwd
|
|
44
|
+
for path in _extract_paths(command):
|
|
45
|
+
if not is_within_cwd(path):
|
|
46
|
+
return {
|
|
47
|
+
"role": "tool",
|
|
48
|
+
"tool_call_id": toolcall_id,
|
|
49
|
+
"content": (
|
|
50
|
+
f"Error: The command would operate on '{path}', "
|
|
51
|
+
"which is outside the current working directory. "
|
|
52
|
+
"Access to paths outside the project is not allowed."
|
|
53
|
+
),
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Enforce gitignore: block commands that touch gitignored files
|
|
57
|
+
for path in _extract_paths(command):
|
|
58
|
+
if is_ignored_by_gitignore(path):
|
|
59
|
+
return {
|
|
60
|
+
"role": "tool",
|
|
61
|
+
"tool_call_id": toolcall_id,
|
|
62
|
+
"content": (
|
|
63
|
+
f"Error: The command would operate on '{path}', "
|
|
64
|
+
"which is matched by .gitignore. Use the dedicated "
|
|
65
|
+
"tools (WriteFile, ReplaceText, RemoveFile) for "
|
|
66
|
+
"non-gitignored files, or instruct the user to make "
|
|
67
|
+
"this change themselves."
|
|
68
|
+
),
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
confirmation = ""
|
|
73
|
+
try:
|
|
74
|
+
confirmation = input(f"{BLUE}Execute command: {command}\n? (y/n): {RESET}")
|
|
75
|
+
except KeyboardInterrupt:
|
|
76
|
+
print()
|
|
77
|
+
exit(0)
|
|
78
|
+
except EOFError:
|
|
79
|
+
print()
|
|
80
|
+
exit(0)
|
|
81
|
+
|
|
82
|
+
if confirmation.lower() != "y":
|
|
83
|
+
print("Command execution cancelled by user.")
|
|
84
|
+
try:
|
|
85
|
+
reason = input(f"{BLUE}Reason for refusal (optional, press Enter to skip): {RESET}").strip()
|
|
86
|
+
except (KeyboardInterrupt, EOFError):
|
|
87
|
+
reason = ""
|
|
88
|
+
if reason:
|
|
89
|
+
return {
|
|
90
|
+
"role": "tool",
|
|
91
|
+
"tool_call_id": toolcall_id,
|
|
92
|
+
"content": f"The user refused running this command. Reason: {reason}",
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
"role": "tool",
|
|
96
|
+
"tool_call_id": toolcall_id,
|
|
97
|
+
"content": "The user refused running this command.",
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
result = subprocess.run(
|
|
102
|
+
command,
|
|
103
|
+
shell=True,
|
|
104
|
+
capture_output=True,
|
|
105
|
+
text=True,
|
|
106
|
+
check=False,
|
|
107
|
+
timeout=timeout,
|
|
108
|
+
)
|
|
109
|
+
except subprocess.TimeoutExpired as e:
|
|
110
|
+
output = (e.stdout or "").strip()
|
|
111
|
+
error_msg = (e.stderr or "").strip()
|
|
112
|
+
msg = f"Command timed out after {timeout} seconds and was killed."
|
|
113
|
+
if output:
|
|
114
|
+
msg += f"\nPartial stdout:\n{output}"
|
|
115
|
+
if error_msg:
|
|
116
|
+
msg += f"\nPartial stderr:\n{error_msg}"
|
|
117
|
+
print(msg)
|
|
118
|
+
return {
|
|
119
|
+
"role": "tool",
|
|
120
|
+
"tool_call_id": toolcall_id,
|
|
121
|
+
"content": msg,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
output = result.stdout
|
|
125
|
+
if result.returncode != 0:
|
|
126
|
+
error_msg = result.stderr.strip()
|
|
127
|
+
if output:
|
|
128
|
+
output += f"\n(exit code {result.returncode})\nstderr: {error_msg}"
|
|
129
|
+
else:
|
|
130
|
+
output = f"Command failed with exit code {result.returncode}\n{error_msg}"
|
|
131
|
+
|
|
132
|
+
output = remove_em_dashes(output)
|
|
133
|
+
stripped = output.strip()
|
|
134
|
+
if stripped:
|
|
135
|
+
print(stripped)
|
|
136
|
+
|
|
137
|
+
reindex_after_change(code_indexer)
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
"role": "tool",
|
|
141
|
+
"tool_call_id": toolcall_id,
|
|
142
|
+
"content": f"{output.strip()}",
|
|
143
|
+
}
|
|
144
|
+
except Exception as e:
|
|
145
|
+
return {
|
|
146
|
+
"role": "tool",
|
|
147
|
+
"tool_call_id": toolcall_id,
|
|
148
|
+
"content": f"Error executing command: {str(e)}",
|
|
149
|
+
}
|
Tools/shell_kill.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from .utils import BLUE, RED, RESET
|
|
4
|
+
from .temp_background_service import _background_processes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def handle(arguments, toolcall_id):
|
|
8
|
+
pid = arguments.get("pid")
|
|
9
|
+
print(f"{BLUE}ShellKill{RESET}")
|
|
10
|
+
|
|
11
|
+
if pid is None:
|
|
12
|
+
return {
|
|
13
|
+
"role": "tool",
|
|
14
|
+
"tool_call_id": toolcall_id,
|
|
15
|
+
"content": "Error: 'pid' parameter is required.",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pid = int(pid)
|
|
19
|
+
|
|
20
|
+
if pid not in _background_processes:
|
|
21
|
+
return {
|
|
22
|
+
"role": "tool",
|
|
23
|
+
"tool_call_id": toolcall_id,
|
|
24
|
+
"content": f"Error: No background process found with PID {pid}.",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
entry = _background_processes[pid]
|
|
28
|
+
process = entry["process"]
|
|
29
|
+
command = entry["command"]
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
process.terminate()
|
|
33
|
+
try:
|
|
34
|
+
process.wait(timeout=5)
|
|
35
|
+
except Exception:
|
|
36
|
+
process.kill()
|
|
37
|
+
process.wait(timeout=5)
|
|
38
|
+
|
|
39
|
+
# Read any captured output
|
|
40
|
+
output = ""
|
|
41
|
+
stdout_path = entry.get("stdout_path")
|
|
42
|
+
stderr_path = entry.get("stderr_path")
|
|
43
|
+
|
|
44
|
+
if stdout_path and os.path.exists(stdout_path):
|
|
45
|
+
with open(stdout_path, "r") as f:
|
|
46
|
+
stdout_content = f.read().strip()
|
|
47
|
+
if stdout_content:
|
|
48
|
+
output += stdout_content
|
|
49
|
+
|
|
50
|
+
if stderr_path and os.path.exists(stderr_path):
|
|
51
|
+
with open(stderr_path, "r") as f:
|
|
52
|
+
stderr_content = f.read().strip()
|
|
53
|
+
if stderr_content:
|
|
54
|
+
if output:
|
|
55
|
+
output += f"\nstderr: {stderr_content}"
|
|
56
|
+
else:
|
|
57
|
+
output = f"stderr: {stderr_content}"
|
|
58
|
+
|
|
59
|
+
# Clean up temp files
|
|
60
|
+
for path in [stdout_path, stderr_path]:
|
|
61
|
+
if path and os.path.exists(path):
|
|
62
|
+
try:
|
|
63
|
+
os.unlink(path)
|
|
64
|
+
except OSError as e:
|
|
65
|
+
print(f"{RED}Warning: Failed to clean up temp file {path}: {e}{RESET}")
|
|
66
|
+
|
|
67
|
+
del _background_processes[pid]
|
|
68
|
+
|
|
69
|
+
return_code = process.returncode
|
|
70
|
+
result = (
|
|
71
|
+
f"Process {pid} terminated (exit code {return_code}).\n"
|
|
72
|
+
f"Command: {command}"
|
|
73
|
+
)
|
|
74
|
+
if output:
|
|
75
|
+
result += f"\nOutput:\n{output}"
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
"role": "tool",
|
|
79
|
+
"tool_call_id": toolcall_id,
|
|
80
|
+
"content": result,
|
|
81
|
+
}
|
|
82
|
+
except Exception as e:
|
|
83
|
+
return {
|
|
84
|
+
"role": "tool",
|
|
85
|
+
"tool_call_id": toolcall_id,
|
|
86
|
+
"content": f"Error killing process {pid}: {str(e)}",
|
|
87
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import tempfile
|
|
3
|
+
|
|
4
|
+
from .utils import is_ignored_by_gitignore, is_within_cwd, BLUE, RESET
|
|
5
|
+
from .shell import _extract_paths
|
|
6
|
+
|
|
7
|
+
# Module-level registry of background processes
|
|
8
|
+
_background_processes = {}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def handle(arguments, toolcall_id):
|
|
12
|
+
command = arguments["command"]
|
|
13
|
+
print(f"{BLUE}TempBackgroundService{RESET}")
|
|
14
|
+
|
|
15
|
+
# Enforce sandbox: block commands that touch paths outside cwd
|
|
16
|
+
for path in _extract_paths(command):
|
|
17
|
+
if not is_within_cwd(path):
|
|
18
|
+
return {
|
|
19
|
+
"role": "tool",
|
|
20
|
+
"tool_call_id": toolcall_id,
|
|
21
|
+
"content": (
|
|
22
|
+
f"Error: The command would operate on '{path}', "
|
|
23
|
+
"which is outside the current working directory. "
|
|
24
|
+
"Access to paths outside the project is not allowed."
|
|
25
|
+
),
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# Enforce gitignore: block commands that touch gitignored files
|
|
29
|
+
for path in _extract_paths(command):
|
|
30
|
+
if is_ignored_by_gitignore(path):
|
|
31
|
+
return {
|
|
32
|
+
"role": "tool",
|
|
33
|
+
"tool_call_id": toolcall_id,
|
|
34
|
+
"content": (
|
|
35
|
+
f"Error: The command would operate on '{path}', "
|
|
36
|
+
"which is matched by .gitignore. Use the dedicated "
|
|
37
|
+
"tools (WriteFile, ReplaceText, RemoveFile) for "
|
|
38
|
+
"non-gitignored files, or instruct the user to make "
|
|
39
|
+
"this change themselves."
|
|
40
|
+
),
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
confirmation = ""
|
|
45
|
+
try:
|
|
46
|
+
confirmation = input(f"{BLUE}Start background service: {command}\n? (y/n): {RESET}")
|
|
47
|
+
except KeyboardInterrupt:
|
|
48
|
+
print()
|
|
49
|
+
exit(0)
|
|
50
|
+
except EOFError:
|
|
51
|
+
print()
|
|
52
|
+
exit(0)
|
|
53
|
+
|
|
54
|
+
if confirmation.lower() != "y":
|
|
55
|
+
print("Command execution cancelled by user.")
|
|
56
|
+
try:
|
|
57
|
+
reason = input(f"{BLUE}Reason for refusal (optional, press Enter to skip): {RESET}").strip()
|
|
58
|
+
except (KeyboardInterrupt, EOFError):
|
|
59
|
+
reason = ""
|
|
60
|
+
if reason:
|
|
61
|
+
return {
|
|
62
|
+
"role": "tool",
|
|
63
|
+
"tool_call_id": toolcall_id,
|
|
64
|
+
"content": f"The user refused running this command. Reason: {reason}",
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
"role": "tool",
|
|
68
|
+
"tool_call_id": toolcall_id,
|
|
69
|
+
"content": "The user refused running this command.",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Create temp files for stdout and stderr
|
|
73
|
+
stdout_file = tempfile.NamedTemporaryFile(
|
|
74
|
+
mode="w+", delete=False, suffix=".out", prefix="raggie_bg_"
|
|
75
|
+
)
|
|
76
|
+
stderr_file = tempfile.NamedTemporaryFile(
|
|
77
|
+
mode="w+", delete=False, suffix=".err", prefix="raggie_bg_"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
process = subprocess.Popen(
|
|
81
|
+
command,
|
|
82
|
+
shell=True,
|
|
83
|
+
stdout=stdout_file,
|
|
84
|
+
stderr=stderr_file,
|
|
85
|
+
text=True,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
pid = process.pid
|
|
89
|
+
_background_processes[pid] = {
|
|
90
|
+
"process": process,
|
|
91
|
+
"command": command,
|
|
92
|
+
"stdout_path": stdout_file.name,
|
|
93
|
+
"stderr_path": stderr_file.name,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
stdout_file.close()
|
|
97
|
+
stderr_file.close()
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
"role": "tool",
|
|
101
|
+
"tool_call_id": toolcall_id,
|
|
102
|
+
"content": (
|
|
103
|
+
f"Background process started with PID {pid}.\n"
|
|
104
|
+
f"Command: {command}\n"
|
|
105
|
+
f"Use ShellKill with pid={pid} to terminate it."
|
|
106
|
+
),
|
|
107
|
+
}
|
|
108
|
+
except Exception as e:
|
|
109
|
+
return {
|
|
110
|
+
"role": "tool",
|
|
111
|
+
"tool_call_id": toolcall_id,
|
|
112
|
+
"content": f"Error starting background command: {str(e)}",
|
|
113
|
+
}
|