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.
Files changed (93) hide show
  1. Agent/__init__.py +0 -0
  2. Agent/agent.py +891 -0
  3. Agent/chat_history_db.py +1500 -0
  4. Agent/command.py +49 -0
  5. Agent/config.py +46 -0
  6. Agent/effort_levels.py +33 -0
  7. Agent/git_manager.py +727 -0
  8. Agent/tools.py +35 -0
  9. Commands/__init__.py +18 -0
  10. Commands/effort.py +42 -0
  11. Commands/global_todo.py +23 -0
  12. Commands/help.py +22 -0
  13. Commands/reasoning.py +24 -0
  14. Commands/redo.py +11 -0
  15. Commands/reindex.py +27 -0
  16. Commands/shell.py +28 -0
  17. Commands/stream.py +24 -0
  18. Commands/undo.py +13 -0
  19. Commands/unlimited_effort.py +8 -0
  20. Commands/window_size.py +29 -0
  21. RAG/__init__.py +0 -0
  22. RAG/document.py +119 -0
  23. RAG/find.py +408 -0
  24. RAG/graph.py +231 -0
  25. Tools/GetFileCodeStructure.py +43 -0
  26. Tools/GetSymbolSourceCode.py +27 -0
  27. Tools/__init__.py +39 -0
  28. Tools/ask_user.py +102 -0
  29. Tools/dispatch_subagent.py +215 -0
  30. Tools/document.py +35 -0
  31. Tools/edit_symbol.py +250 -0
  32. Tools/fuzzy_search.py +119 -0
  33. Tools/list_dir.py +51 -0
  34. Tools/read.py +49 -0
  35. Tools/read_image.py +75 -0
  36. Tools/remove.py +75 -0
  37. Tools/replace.py +305 -0
  38. Tools/search.py +41 -0
  39. Tools/shell.py +149 -0
  40. Tools/shell_kill.py +87 -0
  41. Tools/temp_background_service.py +113 -0
  42. Tools/todo_list.py +481 -0
  43. Tools/utils.py +116 -0
  44. Tools/view_changes.py +179 -0
  45. Tools/walk_call_tree.py +30 -0
  46. Tools/web_fetch.py +175 -0
  47. Tools/web_search.py +69 -0
  48. Tools/write.py +48 -0
  49. cli.py +111 -0
  50. config/__init__.py +0 -0
  51. config/coder_system_prompt.md +119 -0
  52. config/roles.json +43 -0
  53. config/tools.json +709 -0
  54. indexing/__init__.py +0 -0
  55. indexing/cli.py +128 -0
  56. indexing/code_index_sdk.py +832 -0
  57. indexing/code_indexer.py +1763 -0
  58. indexing/db_schema.py +396 -0
  59. indexing/export_to_json.py +346 -0
  60. indexing/extractors.py +189 -0
  61. indexing/file_utils.py +97 -0
  62. indexing/frontend/__init__.py +0 -0
  63. indexing/frontend/css_extractor.py +195 -0
  64. indexing/frontend/css_parser.py +387 -0
  65. indexing/frontend/css_selector_utils.py +226 -0
  66. indexing/frontend/edit_safety.py +573 -0
  67. indexing/frontend/graph.py +838 -0
  68. indexing/frontend/html_extractor.py +496 -0
  69. indexing/frontend/html_parser.py +314 -0
  70. indexing/frontend/jsx_extractor.py +1204 -0
  71. indexing/frontend/location_lookup.py +247 -0
  72. indexing/frontend/resolver.py +485 -0
  73. indexing/frontend/runtime_resolver.py +862 -0
  74. indexing/frontend/semantic_output.py +705 -0
  75. indexing/frontend/source_location.py +69 -0
  76. indexing/frontend_config.py +72 -0
  77. indexing/frontend_models.py +347 -0
  78. indexing/language_config.py +360 -0
  79. indexing/models.py +284 -0
  80. indexing/node_utils.py +1112 -0
  81. indexing/parse_worker.py +1082 -0
  82. indexing/queries.py +1542 -0
  83. indexing/sdk_examples.py +426 -0
  84. interactive.py +248 -0
  85. raggie.py +673 -0
  86. raggiecode-0.2.1.dist-info/METADATA +944 -0
  87. raggiecode-0.2.1.dist-info/RECORD +93 -0
  88. raggiecode-0.2.1.dist-info/WHEEL +5 -0
  89. raggiecode-0.2.1.dist-info/entry_points.txt +2 -0
  90. raggiecode-0.2.1.dist-info/top_level.txt +10 -0
  91. skills/__init__.py +3 -0
  92. skills/manager.py +114 -0
  93. 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
+ }