ripperdoc 0.2.0__py3-none-any.whl → 0.2.3__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.
- ripperdoc/__init__.py +1 -1
- ripperdoc/cli/cli.py +74 -9
- ripperdoc/cli/commands/__init__.py +4 -0
- ripperdoc/cli/commands/agents_cmd.py +30 -4
- ripperdoc/cli/commands/context_cmd.py +11 -1
- ripperdoc/cli/commands/cost_cmd.py +5 -0
- ripperdoc/cli/commands/doctor_cmd.py +208 -0
- ripperdoc/cli/commands/memory_cmd.py +202 -0
- ripperdoc/cli/commands/models_cmd.py +61 -6
- ripperdoc/cli/commands/resume_cmd.py +4 -2
- ripperdoc/cli/commands/status_cmd.py +1 -1
- ripperdoc/cli/commands/tasks_cmd.py +27 -0
- ripperdoc/cli/ui/rich_ui.py +258 -11
- ripperdoc/cli/ui/thinking_spinner.py +128 -0
- ripperdoc/core/agents.py +14 -4
- ripperdoc/core/config.py +56 -3
- ripperdoc/core/default_tools.py +16 -2
- ripperdoc/core/permissions.py +19 -0
- ripperdoc/core/providers/__init__.py +31 -0
- ripperdoc/core/providers/anthropic.py +136 -0
- ripperdoc/core/providers/base.py +187 -0
- ripperdoc/core/providers/gemini.py +172 -0
- ripperdoc/core/providers/openai.py +142 -0
- ripperdoc/core/query.py +510 -386
- ripperdoc/core/query_utils.py +578 -0
- ripperdoc/core/system_prompt.py +2 -1
- ripperdoc/core/tool.py +16 -1
- ripperdoc/sdk/client.py +12 -1
- ripperdoc/tools/background_shell.py +63 -21
- ripperdoc/tools/bash_tool.py +48 -13
- ripperdoc/tools/file_edit_tool.py +20 -0
- ripperdoc/tools/file_read_tool.py +23 -0
- ripperdoc/tools/file_write_tool.py +20 -0
- ripperdoc/tools/glob_tool.py +59 -15
- ripperdoc/tools/grep_tool.py +7 -0
- ripperdoc/tools/ls_tool.py +246 -73
- ripperdoc/tools/mcp_tools.py +32 -10
- ripperdoc/tools/multi_edit_tool.py +23 -0
- ripperdoc/tools/notebook_edit_tool.py +18 -3
- ripperdoc/tools/task_tool.py +7 -0
- ripperdoc/tools/todo_tool.py +157 -25
- ripperdoc/tools/tool_search_tool.py +17 -4
- ripperdoc/utils/file_watch.py +134 -0
- ripperdoc/utils/git_utils.py +274 -0
- ripperdoc/utils/json_utils.py +27 -0
- ripperdoc/utils/log.py +129 -29
- ripperdoc/utils/mcp.py +71 -6
- ripperdoc/utils/memory.py +12 -1
- ripperdoc/utils/message_compaction.py +22 -5
- ripperdoc/utils/messages.py +72 -17
- ripperdoc/utils/output_utils.py +34 -9
- ripperdoc/utils/permissions/path_validation_utils.py +6 -0
- ripperdoc/utils/prompt.py +17 -0
- ripperdoc/utils/safe_get_cwd.py +4 -0
- ripperdoc/utils/session_history.py +27 -9
- ripperdoc/utils/session_usage.py +7 -0
- ripperdoc/utils/shell_utils.py +159 -0
- ripperdoc/utils/todo.py +2 -2
- {ripperdoc-0.2.0.dist-info → ripperdoc-0.2.3.dist-info}/METADATA +4 -2
- ripperdoc-0.2.3.dist-info/RECORD +95 -0
- ripperdoc-0.2.0.dist-info/RECORD +0 -81
- {ripperdoc-0.2.0.dist-info → ripperdoc-0.2.3.dist-info}/WHEEL +0 -0
- {ripperdoc-0.2.0.dist-info → ripperdoc-0.2.3.dist-info}/entry_points.txt +0 -0
- {ripperdoc-0.2.0.dist-info → ripperdoc-0.2.3.dist-info}/licenses/LICENSE +0 -0
- {ripperdoc-0.2.0.dist-info → ripperdoc-0.2.3.dist-info}/top_level.txt +0 -0
ripperdoc/utils/output_utils.py
CHANGED
|
@@ -131,15 +131,40 @@ def truncate_output(text: str, max_chars: int = MAX_OUTPUT_CHARS) -> dict[str, A
|
|
|
131
131
|
"is_image": False,
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
134
|
+
marker_template = "\n\n... [Output truncated: {omitted} characters omitted] ...\n\n"
|
|
135
|
+
short_marker = "... [truncated] ..."
|
|
136
|
+
|
|
137
|
+
def _choose_marker(omitted: int, budget: int) -> str:
|
|
138
|
+
"""Pick the most informative marker that fits within the budget."""
|
|
139
|
+
full_marker = marker_template.format(omitted=omitted)
|
|
140
|
+
if len(full_marker) <= budget:
|
|
141
|
+
return full_marker
|
|
142
|
+
if len(short_marker) <= budget:
|
|
143
|
+
return short_marker
|
|
144
|
+
# Last resort: squeeze an ellipsis into the budget (may be empty for tiny budgets)
|
|
145
|
+
return "..."[: max(budget, 0)]
|
|
146
|
+
|
|
147
|
+
# Iteratively balance how much of the start/end to keep while ensuring we never exceed max_chars.
|
|
148
|
+
marker = _choose_marker(original_length - max_chars, max_chars)
|
|
149
|
+
keep_start = keep_end = 0
|
|
150
|
+
for _ in range(2):
|
|
151
|
+
available = max(0, max_chars - len(marker))
|
|
152
|
+
keep_start = min(TRUNCATE_KEEP_START, available // 2)
|
|
153
|
+
keep_end = min(TRUNCATE_KEEP_END, available - keep_start)
|
|
154
|
+
marker = _choose_marker(max(0, original_length - (keep_start + keep_end)), max_chars)
|
|
155
|
+
|
|
156
|
+
available = max(0, max_chars - len(marker))
|
|
157
|
+
# Ensure kept sections fit the final budget; trim end first, then start if needed.
|
|
158
|
+
if keep_start + keep_end > available:
|
|
159
|
+
overflow = keep_start + keep_end - available
|
|
160
|
+
trim_end = min(overflow, keep_end)
|
|
161
|
+
keep_end -= trim_end
|
|
162
|
+
overflow -= trim_end
|
|
163
|
+
keep_start = max(0, keep_start - overflow)
|
|
164
|
+
|
|
165
|
+
truncated = text[:keep_start] + marker + (text[-keep_end:] if keep_end else "")
|
|
166
|
+
if len(truncated) > max_chars:
|
|
167
|
+
truncated = truncated[:max_chars]
|
|
143
168
|
|
|
144
169
|
return {
|
|
145
170
|
"truncated_content": truncated,
|
|
@@ -10,6 +10,9 @@ from typing import Iterable, List, Set
|
|
|
10
10
|
|
|
11
11
|
from ripperdoc.utils.safe_get_cwd import safe_get_cwd
|
|
12
12
|
from ripperdoc.utils.shell_token_utils import parse_and_clean_shell_tokens
|
|
13
|
+
from ripperdoc.utils.log import get_logger
|
|
14
|
+
|
|
15
|
+
logger = get_logger()
|
|
13
16
|
|
|
14
17
|
_GLOB_PATTERN = re.compile(r"[*?\[\]{}]")
|
|
15
18
|
_MAX_VISIBLE_ITEMS = 5
|
|
@@ -46,6 +49,9 @@ def _resolve_path(raw_path: str, cwd: str) -> Path:
|
|
|
46
49
|
try:
|
|
47
50
|
return candidate.resolve()
|
|
48
51
|
except Exception:
|
|
52
|
+
logger.exception(
|
|
53
|
+
"[path_validation] Failed to resolve path", extra={"raw_path": raw_path, "cwd": cwd}
|
|
54
|
+
)
|
|
49
55
|
return candidate
|
|
50
56
|
|
|
51
57
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Prompt helpers for interactive input."""
|
|
2
|
+
|
|
3
|
+
from getpass import getpass
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def prompt_secret(prompt_text: str, prompt_suffix: str = ": ") -> str:
|
|
7
|
+
"""Prompt for sensitive input, masking characters when possible.
|
|
8
|
+
|
|
9
|
+
Falls back to getpass (no echo) if prompt_toolkit is unavailable.
|
|
10
|
+
"""
|
|
11
|
+
full_prompt = f"{prompt_text}{prompt_suffix}"
|
|
12
|
+
try:
|
|
13
|
+
from prompt_toolkit import prompt as pt_prompt
|
|
14
|
+
|
|
15
|
+
return pt_prompt(full_prompt, is_password=True)
|
|
16
|
+
except Exception:
|
|
17
|
+
return getpass(full_prompt)
|
ripperdoc/utils/safe_get_cwd.py
CHANGED
|
@@ -4,6 +4,9 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
from pathlib import Path
|
|
7
|
+
from ripperdoc.utils.log import get_logger
|
|
8
|
+
|
|
9
|
+
logger = get_logger()
|
|
7
10
|
|
|
8
11
|
_ORIGINAL_CWD = Path(os.getcwd()).resolve()
|
|
9
12
|
|
|
@@ -18,6 +21,7 @@ def safe_get_cwd() -> str:
|
|
|
18
21
|
try:
|
|
19
22
|
return str(Path(os.getcwd()).resolve())
|
|
20
23
|
except Exception:
|
|
24
|
+
logger.exception("[safe_get_cwd] Failed to resolve cwd")
|
|
21
25
|
return get_original_cwd()
|
|
22
26
|
|
|
23
27
|
|
|
@@ -102,10 +102,16 @@ class SessionHistory:
|
|
|
102
102
|
if isinstance(msg_uuid, str):
|
|
103
103
|
self._seen_ids.add(msg_uuid)
|
|
104
104
|
except Exception as exc:
|
|
105
|
-
logger.debug(
|
|
105
|
+
logger.debug(
|
|
106
|
+
f"Failed to parse session history line: {exc}",
|
|
107
|
+
exc_info=True,
|
|
108
|
+
)
|
|
106
109
|
continue
|
|
107
|
-
except Exception
|
|
108
|
-
logger.
|
|
110
|
+
except Exception:
|
|
111
|
+
logger.exception(
|
|
112
|
+
"Failed to load seen IDs from session",
|
|
113
|
+
extra={"session_id": self.session_id, "path": str(self.path)},
|
|
114
|
+
)
|
|
109
115
|
return
|
|
110
116
|
|
|
111
117
|
def append(self, message: ConversationMessage) -> None:
|
|
@@ -128,9 +134,12 @@ class SessionHistory:
|
|
|
128
134
|
fh.write("\n")
|
|
129
135
|
if isinstance(msg_uuid, str):
|
|
130
136
|
self._seen_ids.add(msg_uuid)
|
|
131
|
-
except Exception
|
|
137
|
+
except Exception:
|
|
132
138
|
# Avoid crashing the UI if logging fails
|
|
133
|
-
logger.
|
|
139
|
+
logger.exception(
|
|
140
|
+
"Failed to append message to session log",
|
|
141
|
+
extra={"session_id": self.session_id, "path": str(self.path)},
|
|
142
|
+
)
|
|
134
143
|
return
|
|
135
144
|
|
|
136
145
|
|
|
@@ -146,7 +155,10 @@ def list_session_summaries(project_path: Path) -> List[SessionSummary]:
|
|
|
146
155
|
with jsonl_path.open("r", encoding="utf-8") as fh:
|
|
147
156
|
messages = [json.loads(line) for line in fh if line.strip()]
|
|
148
157
|
except Exception as exc:
|
|
149
|
-
logger.
|
|
158
|
+
logger.exception(
|
|
159
|
+
"Failed to load session summary",
|
|
160
|
+
extra={"path": str(jsonl_path), "error": str(exc)},
|
|
161
|
+
)
|
|
150
162
|
continue
|
|
151
163
|
|
|
152
164
|
payloads = [entry.get("payload") or {} for entry in messages]
|
|
@@ -206,10 +218,16 @@ def load_session_messages(project_path: Path, session_id: str) -> List[Conversat
|
|
|
206
218
|
if msg is not None and getattr(msg, "type", None) != "progress":
|
|
207
219
|
messages.append(msg)
|
|
208
220
|
except Exception as exc:
|
|
209
|
-
logger.debug(
|
|
221
|
+
logger.debug(
|
|
222
|
+
f"Failed to deserialize message in session {session_id}: {exc}",
|
|
223
|
+
exc_info=True,
|
|
224
|
+
)
|
|
210
225
|
continue
|
|
211
|
-
except Exception
|
|
212
|
-
logger.
|
|
226
|
+
except Exception:
|
|
227
|
+
logger.exception(
|
|
228
|
+
"Failed to load session messages",
|
|
229
|
+
extra={"session_id": session_id, "path": str(path)},
|
|
230
|
+
)
|
|
213
231
|
return []
|
|
214
232
|
|
|
215
233
|
return messages
|
ripperdoc/utils/session_usage.py
CHANGED
|
@@ -17,6 +17,7 @@ class ModelUsage:
|
|
|
17
17
|
cache_creation_input_tokens: int = 0
|
|
18
18
|
requests: int = 0
|
|
19
19
|
duration_ms: float = 0.0
|
|
20
|
+
cost_usd: float = 0.0
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
@dataclass
|
|
@@ -49,6 +50,10 @@ class SessionUsage:
|
|
|
49
50
|
def total_duration_ms(self) -> float:
|
|
50
51
|
return sum(usage.duration_ms for usage in self.models.values())
|
|
51
52
|
|
|
53
|
+
@property
|
|
54
|
+
def total_cost_usd(self) -> float:
|
|
55
|
+
return sum(usage.cost_usd for usage in self.models.values())
|
|
56
|
+
|
|
52
57
|
|
|
53
58
|
_SESSION_USAGE = SessionUsage()
|
|
54
59
|
|
|
@@ -76,6 +81,7 @@ def record_usage(
|
|
|
76
81
|
cache_read_input_tokens: int = 0,
|
|
77
82
|
cache_creation_input_tokens: int = 0,
|
|
78
83
|
duration_ms: float = 0.0,
|
|
84
|
+
cost_usd: float = 0.0,
|
|
79
85
|
) -> None:
|
|
80
86
|
"""Record a single model invocation."""
|
|
81
87
|
global _SESSION_USAGE
|
|
@@ -88,6 +94,7 @@ def record_usage(
|
|
|
88
94
|
usage.cache_creation_input_tokens += _as_int(cache_creation_input_tokens)
|
|
89
95
|
usage.duration_ms += float(duration_ms) if duration_ms and duration_ms > 0 else 0.0
|
|
90
96
|
usage.requests += 1
|
|
97
|
+
usage.cost_usd += float(cost_usd) if cost_usd and cost_usd > 0 else 0.0
|
|
91
98
|
|
|
92
99
|
|
|
93
100
|
def get_session_usage() -> SessionUsage:
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""Shell detection helpers.
|
|
2
|
+
|
|
3
|
+
Selects a suitable interactive shell for running commands, preferring bash/zsh
|
|
4
|
+
over the system's /bin/sh default to ensure features like brace expansion.
|
|
5
|
+
On Windows, prefers Git Bash and falls back to cmd.exe if no bash is available.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import shutil
|
|
12
|
+
from typing import Iterable, List
|
|
13
|
+
|
|
14
|
+
from ripperdoc.utils.log import get_logger
|
|
15
|
+
|
|
16
|
+
logger = get_logger()
|
|
17
|
+
|
|
18
|
+
# Common locations to probe if shutil.which misses an otherwise standard path.
|
|
19
|
+
_COMMON_BIN_DIRS: tuple[str, ...] = ("/bin", "/usr/bin", "/usr/local/bin", "/opt/homebrew/bin")
|
|
20
|
+
_IS_WINDOWS = os.name == "nt"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _is_executable(path: str) -> bool:
|
|
24
|
+
return bool(path) and os.path.isfile(path) and os.access(path, os.X_OK)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _dedupe_preserve_order(items: Iterable[str]) -> list[str]:
|
|
28
|
+
seen = set()
|
|
29
|
+
ordered: list[str] = []
|
|
30
|
+
for item in items:
|
|
31
|
+
if item and item not in seen:
|
|
32
|
+
ordered.append(item)
|
|
33
|
+
seen.add(item)
|
|
34
|
+
return ordered
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _find_git_bash_windows() -> str | None:
|
|
38
|
+
env_path = os.environ.get("GIT_BASH_PATH") or os.environ.get("GITBASH")
|
|
39
|
+
if env_path and _is_executable(env_path):
|
|
40
|
+
return env_path
|
|
41
|
+
|
|
42
|
+
bash_in_path = shutil.which("bash")
|
|
43
|
+
if bash_in_path and "git" in bash_in_path.lower():
|
|
44
|
+
return bash_in_path
|
|
45
|
+
|
|
46
|
+
common = [
|
|
47
|
+
r"C:\Program Files\Git\bin\bash.exe",
|
|
48
|
+
r"C:\Program Files\Git\usr\bin\bash.exe",
|
|
49
|
+
r"C:\Program Files (x86)\Git\bin\bash.exe",
|
|
50
|
+
r"C:\Program Files (x86)\Git\usr\bin\bash.exe",
|
|
51
|
+
]
|
|
52
|
+
for path in common:
|
|
53
|
+
if _is_executable(path):
|
|
54
|
+
return path
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _windows_cmd_path() -> str | None:
|
|
59
|
+
comspec = os.environ.get("ComSpec")
|
|
60
|
+
if _is_executable(comspec or ""):
|
|
61
|
+
return comspec
|
|
62
|
+
which_cmd = shutil.which("cmd.exe") or shutil.which("cmd")
|
|
63
|
+
if which_cmd and _is_executable(which_cmd):
|
|
64
|
+
return which_cmd
|
|
65
|
+
system32 = os.path.join(os.environ.get("SystemRoot", r"C:\Windows"), "System32", "cmd.exe")
|
|
66
|
+
if _is_executable(system32):
|
|
67
|
+
return system32
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def find_suitable_shell() -> str:
|
|
72
|
+
"""Return a best-effort shell path, preferring bash/zsh (Git Bash on Windows).
|
|
73
|
+
|
|
74
|
+
Priority on Unix:
|
|
75
|
+
1) $SHELL if it's bash/zsh and executable
|
|
76
|
+
2) bash/zsh from PATH
|
|
77
|
+
3) bash/zsh in common bin directories
|
|
78
|
+
|
|
79
|
+
Priority on Windows:
|
|
80
|
+
1) Git Bash (env override or known locations / PATH)
|
|
81
|
+
2) cmd.exe as a last resort
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
RuntimeError: if no suitable shell is found.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
env_override = os.environ.get("RIPPERDOC_SHELL") or os.environ.get("RIPPERDOC_SHELL_PATH")
|
|
88
|
+
if env_override and _is_executable(env_override):
|
|
89
|
+
logger.debug("Using shell from RIPPERDOC_SHELL*: %s", env_override)
|
|
90
|
+
return env_override
|
|
91
|
+
|
|
92
|
+
current_shell = os.environ.get("SHELL", "")
|
|
93
|
+
current_is_bash = "bash" in current_shell
|
|
94
|
+
current_is_zsh = "zsh" in current_shell
|
|
95
|
+
|
|
96
|
+
if not _IS_WINDOWS:
|
|
97
|
+
if (current_is_bash or current_is_zsh) and _is_executable(current_shell):
|
|
98
|
+
logger.debug("Using SHELL from environment: %s", current_shell)
|
|
99
|
+
return current_shell
|
|
100
|
+
|
|
101
|
+
bash_path = shutil.which("bash") or ""
|
|
102
|
+
zsh_path = shutil.which("zsh") or ""
|
|
103
|
+
preferred_order = ["bash", "zsh"] if current_is_bash else ["zsh", "bash"]
|
|
104
|
+
|
|
105
|
+
candidates: list[str] = []
|
|
106
|
+
for name in preferred_order:
|
|
107
|
+
if name == "bash" and bash_path:
|
|
108
|
+
candidates.append(bash_path)
|
|
109
|
+
if name == "zsh" and zsh_path:
|
|
110
|
+
candidates.append(zsh_path)
|
|
111
|
+
|
|
112
|
+
for bin_dir in _COMMON_BIN_DIRS:
|
|
113
|
+
candidates.append(os.path.join(bin_dir, "bash"))
|
|
114
|
+
candidates.append(os.path.join(bin_dir, "zsh"))
|
|
115
|
+
|
|
116
|
+
for candidate in _dedupe_preserve_order(candidates):
|
|
117
|
+
if _is_executable(candidate):
|
|
118
|
+
logger.debug("Selected shell: %s", candidate)
|
|
119
|
+
return candidate
|
|
120
|
+
|
|
121
|
+
error_message = (
|
|
122
|
+
"No suitable shell found. Please install bash or zsh and ensure $SHELL is set. "
|
|
123
|
+
"Tried bash/zsh in PATH and common locations."
|
|
124
|
+
)
|
|
125
|
+
logger.error(error_message)
|
|
126
|
+
raise RuntimeError(error_message)
|
|
127
|
+
|
|
128
|
+
git_bash = _find_git_bash_windows()
|
|
129
|
+
if git_bash:
|
|
130
|
+
logger.debug("Using Git Bash: %s", git_bash)
|
|
131
|
+
return git_bash
|
|
132
|
+
|
|
133
|
+
cmd_path = _windows_cmd_path()
|
|
134
|
+
if cmd_path:
|
|
135
|
+
logger.warning("Falling back to cmd.exe; bash not found. Using: %s", cmd_path)
|
|
136
|
+
return cmd_path
|
|
137
|
+
|
|
138
|
+
error_message = (
|
|
139
|
+
"No suitable shell found on Windows. Install Git for Windows to provide bash "
|
|
140
|
+
"or ensure cmd.exe is available."
|
|
141
|
+
)
|
|
142
|
+
logger.error(error_message)
|
|
143
|
+
raise RuntimeError(error_message)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def build_shell_command(shell_path: str, command: str) -> List[str]:
|
|
147
|
+
"""Build argv for running a command with the selected shell.
|
|
148
|
+
|
|
149
|
+
For bash/zsh (including Git Bash), use -lc to run as login shell.
|
|
150
|
+
For cmd.exe fallback, use /d /s /c.
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
lower = shell_path.lower()
|
|
154
|
+
if lower.endswith("cmd.exe") or lower.endswith("\\cmd"):
|
|
155
|
+
return [shell_path, "/d", "/s", "/c", command]
|
|
156
|
+
return [shell_path, "-lc", command]
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
__all__ = ["find_suitable_shell", "build_shell_command"]
|
ripperdoc/utils/todo.py
CHANGED
|
@@ -83,8 +83,8 @@ def load_todos(project_root: Optional[Path] = None) -> List[TodoItem]:
|
|
|
83
83
|
|
|
84
84
|
try:
|
|
85
85
|
raw = json.loads(path.read_text())
|
|
86
|
-
except Exception
|
|
87
|
-
logger.
|
|
86
|
+
except Exception:
|
|
87
|
+
logger.exception("Failed to load todos from disk", extra={"path": str(path)})
|
|
88
88
|
return []
|
|
89
89
|
|
|
90
90
|
todos: List[TodoItem] = []
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ripperdoc
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: AI-powered terminal assistant for coding tasks
|
|
5
5
|
Author: Ripperdoc Team
|
|
6
6
|
License: Apache-2.0
|
|
@@ -24,6 +24,7 @@ Requires-Dist: aiofiles>=23.0.0
|
|
|
24
24
|
Requires-Dist: prompt-toolkit>=3.0.0
|
|
25
25
|
Requires-Dist: PyYAML>=6.0.0
|
|
26
26
|
Requires-Dist: mcp[cli]>=1.22.0
|
|
27
|
+
Requires-Dist: json_repair>=0.54.2
|
|
27
28
|
Provides-Extra: dev
|
|
28
29
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
29
30
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
@@ -37,10 +38,12 @@ Dynamic: license-file
|
|
|
37
38
|
Ripperdoc is an AI-powered terminal assistant for coding tasks, providing an interactive interface for AI-assisted development, file management, and command execution.
|
|
38
39
|
|
|
39
40
|
[中文文档](README_CN.md) | [Contributing](CONTRIBUTING.md) | [Documentation](docs/)
|
|
41
|
+
|
|
40
42
|
## Features
|
|
41
43
|
|
|
42
44
|
- **AI-Powered Assistance** - Uses AI models to understand and respond to coding requests
|
|
43
45
|
- **Multi-Model Support** - Support for Anthropic Claude and OpenAI models
|
|
46
|
+
- **Rich UI** - Beautiful terminal interface with syntax highlighting
|
|
44
47
|
- **Code Editing** - Directly edit files with intelligent suggestions
|
|
45
48
|
- **Codebase Understanding** - Analyzes project structure and code relationships
|
|
46
49
|
- **Command Execution** - Run shell commands with real-time feedback
|
|
@@ -52,7 +55,6 @@ Ripperdoc is an AI-powered terminal assistant for coding tasks, providing an int
|
|
|
52
55
|
- **Permission System** - Safe mode with permission prompts for operations
|
|
53
56
|
- **Multi-Edit Support** - Batch edit operations on files
|
|
54
57
|
- **MCP Server Support** - Integration with Model Context Protocol servers
|
|
55
|
-
- **Subagent System** - Delegate tasks to specialized agents
|
|
56
58
|
- **Session Management** - Persistent session history and usage tracking
|
|
57
59
|
- **Jupyter Notebook Support** - Edit .ipynb files directly
|
|
58
60
|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
ripperdoc/__init__.py,sha256=UNSvPbYxqTbZJseto7Btn4nFqfZkKezUBuwPQuI2yOk,66
|
|
2
|
+
ripperdoc/__main__.py,sha256=7oIFEXI2irIoZ_dhcMd3hCs4Dj8tmMBbwiVACAoeE-k,506
|
|
3
|
+
ripperdoc/cli/__init__.py,sha256=03wf6gXBcEgXJrDJS-W_5BEG_DdJ_ep7CxQFPML-73g,35
|
|
4
|
+
ripperdoc/cli/cli.py,sha256=fszg31t6QyWeBEM6PkoidpwamYXvYQScKCSSq8F8uHM,13043
|
|
5
|
+
ripperdoc/cli/commands/__init__.py,sha256=J13i7g-69PVLhO5IJH5OvVK0FJLIFj0b84mm33JvpcE,2329
|
|
6
|
+
ripperdoc/cli/commands/agents_cmd.py,sha256=Iq_sycFhLnEK8o1agdxy0yFXt38DhLIQoxETXM4aVRs,10183
|
|
7
|
+
ripperdoc/cli/commands/base.py,sha256=4KUjxCM04MwbSMUKVNEBph_jeAKPI8b5MHsUFoz7l5g,386
|
|
8
|
+
ripperdoc/cli/commands/clear_cmd.py,sha256=zSYT0Nn_htZzLWTTQ4E5KWHfRg0Q5CYvRO4e--7thBY,345
|
|
9
|
+
ripperdoc/cli/commands/compact_cmd.py,sha256=C_qdPTPdg1cOHdmODkaYoRusosgiqRK6c6KID_Gwq0k,330
|
|
10
|
+
ripperdoc/cli/commands/config_cmd.py,sha256=ebIQk7zUFv353liWfbBSSfPiOaaCR7rQsd_eTw7nsvY,884
|
|
11
|
+
ripperdoc/cli/commands/context_cmd.py,sha256=d0KiJyjbuDNXYlfSzVTFmxmkLXJZe3pUDg_Tt67OWqs,4359
|
|
12
|
+
ripperdoc/cli/commands/cost_cmd.py,sha256=yD9LSqgxVvYNTDPnEHxugjyLWcmbtH5dXim7DIW9zXc,2822
|
|
13
|
+
ripperdoc/cli/commands/doctor_cmd.py,sha256=JQVexktceKTBMml5MO-V86IsDsSqXcSA8igw2zf3Qpo,6655
|
|
14
|
+
ripperdoc/cli/commands/exit_cmd.py,sha256=B0CNKQos2eRC4LSjizLdKsFYzFfwRkrUur6Afu3Fh9M,334
|
|
15
|
+
ripperdoc/cli/commands/help_cmd.py,sha256=iz1vR-rmWsvvfzdebLiIWEWrcMZo5_Eb55_wLr4Ufno,508
|
|
16
|
+
ripperdoc/cli/commands/mcp_cmd.py,sha256=S0iQxclxqgbIxbKcC9oFrckLalzk-1eyAYwkfEZQsGU,2307
|
|
17
|
+
ripperdoc/cli/commands/memory_cmd.py,sha256=Wu8Mh72jBY_9A-hEnW430by0piSOOlGx9PJd4IdpVVs,6494
|
|
18
|
+
ripperdoc/cli/commands/models_cmd.py,sha256=WM4UYEISQkSOqquNIftzkciscqjaj8DNyq9Oa-b6CMU,14367
|
|
19
|
+
ripperdoc/cli/commands/resume_cmd.py,sha256=dJNZ44UvJImGKMrVrgiYw5NSK-vTUnp9GxduvIXtmf8,3013
|
|
20
|
+
ripperdoc/cli/commands/status_cmd.py,sha256=yM_c_GgoAL7CMH_ucGSwUhlbHggxYuvCEb4AXtpN-8s,5534
|
|
21
|
+
ripperdoc/cli/commands/tasks_cmd.py,sha256=lgVzN6_KFQGltb7bgn4Wwmkuq91H_mgzCrga67hgjT4,8292
|
|
22
|
+
ripperdoc/cli/commands/todos_cmd.py,sha256=7Q0B1NVqGtB3R29ndbn4m0VQQm-YQ7d4Wlk7vJ7dLQI,1848
|
|
23
|
+
ripperdoc/cli/commands/tools_cmd.py,sha256=3cMi0vN4mAUhpKqJtRgNvZfcKzRPaMs_pkYYXlyvSSU,384
|
|
24
|
+
ripperdoc/cli/ui/__init__.py,sha256=TxSzTYdITlrYmYVfins_w_jzPqqWRpqky5u1ikwvmtM,43
|
|
25
|
+
ripperdoc/cli/ui/context_display.py,sha256=3ezdtHVwltkPQ5etYwfqUh-fjnpPu8B3P81UzrdHxZs,10020
|
|
26
|
+
ripperdoc/cli/ui/helpers.py,sha256=TJCipP0neh-96ETQfGhusCJ4aWt5gLw1HZbI-3bWDpw,739
|
|
27
|
+
ripperdoc/cli/ui/rich_ui.py,sha256=Qs0rzd-P56Bkd6W7uHXjV2R3pCFAloZOwe2F6fds_L4,51991
|
|
28
|
+
ripperdoc/cli/ui/spinner.py,sha256=XsPRwJ-70InLX9Qw50CEgSHn5oKA5PFIue8Un4edhUk,1449
|
|
29
|
+
ripperdoc/cli/ui/thinking_spinner.py,sha256=9Et5EqPChfkmkiOO8w1OPs8t-sHaisgjn9A__kEYLyg,2824
|
|
30
|
+
ripperdoc/core/__init__.py,sha256=UemJCA-Y8df1466AX-YbRFj071zKajmqO1mi40YVW2g,40
|
|
31
|
+
ripperdoc/core/agents.py,sha256=kGVLTcXVwOwrRBvvC9E_tKaQJ5u-wChIYE2VqYMJx00,10348
|
|
32
|
+
ripperdoc/core/commands.py,sha256=NXCkljYbAP4dDoRy-_3semFNWxG4YAk9q82u8FTKH60,835
|
|
33
|
+
ripperdoc/core/config.py,sha256=DRPi8uzfBmRKefcqlRKLDf4zYYsj0sxF42ROUZ10GN8,15709
|
|
34
|
+
ripperdoc/core/default_tools.py,sha256=t8cLZBOVReF5hvmyhUTziUSnnDMyKDjS7YjuSd_yolw,2568
|
|
35
|
+
ripperdoc/core/permissions.py,sha256=qWaVIaps9Ht0M4jgDk9J0gDErptvf6jzEZ2t48lZ_1I,9187
|
|
36
|
+
ripperdoc/core/query.py,sha256=nxi8Q2JH2VHfCsb5FbwQ1k-ZObt2xeAqovsYQVJ9Yjc,29190
|
|
37
|
+
ripperdoc/core/query_utils.py,sha256=dmbuFM_PZOntBHBLkyzq0-OubH1z3GF_Nn80aChT_TA,22940
|
|
38
|
+
ripperdoc/core/system_prompt.py,sha256=QH7Wg8QqwzvAzjuBayr57w-BazqIQrHfuGvC2KqVkgI,24190
|
|
39
|
+
ripperdoc/core/tool.py,sha256=QEmkygAiXsBK3NBnJnL2NevrcgRpG83OIA0TAwuc7OQ,7027
|
|
40
|
+
ripperdoc/core/providers/__init__.py,sha256=CSqOeET3UowMQV3esmAHI7JfsyYV-m-C5vC6VutI-fY,888
|
|
41
|
+
ripperdoc/core/providers/anthropic.py,sha256=vqQfbGOGKpPEHVc7x4uJFE_nHtWCgiK65KGslVarJkU,5139
|
|
42
|
+
ripperdoc/core/providers/base.py,sha256=cwkWUvLzWxesKI-xzvj1STIlMPNgyKGvCBCLIpZgV9c,6604
|
|
43
|
+
ripperdoc/core/providers/gemini.py,sha256=aS93WBcLzk871DavETNmS5IYaodQEsVWbS19GhGBYOk,6409
|
|
44
|
+
ripperdoc/core/providers/openai.py,sha256=pYMeTQvmnAfT-BimnymDp_7zieNShkfd9573A4S0U7k,5594
|
|
45
|
+
ripperdoc/sdk/__init__.py,sha256=aDSgI4lcCDs9cV3bxNmEEV3SuYx2aCd4VnUjs6H-R7E,213
|
|
46
|
+
ripperdoc/sdk/client.py,sha256=gkduot4gvN1k41WVkHCpiuU7wGLL-SFG-KTTQrMomWc,10814
|
|
47
|
+
ripperdoc/tools/__init__.py,sha256=RBFz0DDnztDXMqv_zRxFHVY-ez2HYcncx8zh_y-BX6w,42
|
|
48
|
+
ripperdoc/tools/background_shell.py,sha256=1PEdlzOBzRKSOmzO_OViDMXcdXzW9grTzukGzRocYb0,10362
|
|
49
|
+
ripperdoc/tools/bash_output_tool.py,sha256=ljIOzTOnkbQfe3jExlhpUlMiLT6HpeD-1QI-D1CwHh8,3379
|
|
50
|
+
ripperdoc/tools/bash_tool.py,sha256=s4FrJTqC_bIN7gqBtbBUr9gt11LsVmWWkplp1ljlzmw,37461
|
|
51
|
+
ripperdoc/tools/file_edit_tool.py,sha256=3fLBcXpwX_SumZRiP-1TJ1qIfWA-AQF88Ji_MCI1Ldo,11871
|
|
52
|
+
ripperdoc/tools/file_read_tool.py,sha256=kKdhj6BXIyKCSxbB063BDAKNjAd36xtTUH-fixWhwHE,6721
|
|
53
|
+
ripperdoc/tools/file_write_tool.py,sha256=fxh4qUGNqby7iFWuADImF4AyOAskMTzqC7CZLHCqcpo,5296
|
|
54
|
+
ripperdoc/tools/glob_tool.py,sha256=e7yS1RvE3VJw5aOwoEPk8fLUSUr6mUmFsi8u8_3TV9Y,5856
|
|
55
|
+
ripperdoc/tools/grep_tool.py,sha256=LfLpPmqD9CIPk6kFYDDmIcykj7uN0xoKtyodc2412FA,8340
|
|
56
|
+
ripperdoc/tools/kill_bash_tool.py,sha256=36F8w2Rm1IVQitwOAwS-D8NTnyQdWfKWIam44qlXErk,4625
|
|
57
|
+
ripperdoc/tools/ls_tool.py,sha256=RlaTciHmjgNFopzUEOJjBp1NqNYhr8F1VIekRgqDwSg,15249
|
|
58
|
+
ripperdoc/tools/mcp_tools.py,sha256=ejofb2UEwH0r-ZAEvvq9nWvCgRGTAqiOws_X2T0YBU0,31263
|
|
59
|
+
ripperdoc/tools/multi_edit_tool.py,sha256=63xircd2ovrk9n1YJ8tfkLDFLvSRFtWAJh3aURmELcE,15829
|
|
60
|
+
ripperdoc/tools/notebook_edit_tool.py,sha256=zGFLRoIUCYEQUUcAiV4izJ09YFKUjaY2zGUJAjucq8c,12656
|
|
61
|
+
ripperdoc/tools/task_tool.py,sha256=bKvJy0hMJcY4MEmWDXqYH0CKfgMKEtaCO9UF9xdngc0,11983
|
|
62
|
+
ripperdoc/tools/todo_tool.py,sha256=QqgWW7LjylD8nmeeO_rkgjnzs8o1O-UVDD-rXObcVuE,19954
|
|
63
|
+
ripperdoc/tools/tool_search_tool.py,sha256=YmSGCviaHiMmYghmPO0Km6ZOI5kkQrjz7qb3G_EFjiI,13763
|
|
64
|
+
ripperdoc/utils/__init__.py,sha256=gdso60znB2hsYZ_YZBKVcuOY3QVfoqD2wHQ4pvr5lSw,37
|
|
65
|
+
ripperdoc/utils/bash_constants.py,sha256=KNn8bzB6nVU5jid9jvjiH4FAu8pP3DZONJ-OknJypAQ,1641
|
|
66
|
+
ripperdoc/utils/bash_output_utils.py,sha256=3Cf5wKJzRbUesmCNy5HtXIBtv0Z2BxklTfFHJ9q1T3w,1210
|
|
67
|
+
ripperdoc/utils/exit_code_handlers.py,sha256=QtO1iDxVAb8Xp03D6_QixPoJC-RQlcp3ssIo_rm4two,7973
|
|
68
|
+
ripperdoc/utils/file_watch.py,sha256=idleNFevHctDSJd23d4Y25XdJooFRpgepOcOEmp9pDg,3970
|
|
69
|
+
ripperdoc/utils/git_utils.py,sha256=Hq-Zx-KPyX4lp_i8ozhic15LyYdX_IfCRm-EyoFu59A,9047
|
|
70
|
+
ripperdoc/utils/json_utils.py,sha256=Ayv4h0aafTbzhpoN4FMPaBxLx9MfoK2PuOVd1_52-k0,706
|
|
71
|
+
ripperdoc/utils/log.py,sha256=98JbVkZQd2OsFo789pgf9q96D6A5IcyT5ubzrPAEoWs,6176
|
|
72
|
+
ripperdoc/utils/mcp.py,sha256=aIGmJLErQ1xRSzTj9Hm3ns2gW8oTvfrFBIukyNXaURk,17037
|
|
73
|
+
ripperdoc/utils/memory.py,sha256=gRhVTRaCo0YOQeXm1i-sndnTku7qhTB-PSYdFD0OzxU,7872
|
|
74
|
+
ripperdoc/utils/message_compaction.py,sha256=307IXnYqGYmj2iZUbfhNULj0BOVSlSTeOUg0Sik79EA,24797
|
|
75
|
+
ripperdoc/utils/messages.py,sha256=8iRolxS6VoJtcaFU41tzKSdsfBSJMXMGUnUTLXKkfnw,17334
|
|
76
|
+
ripperdoc/utils/output_utils.py,sha256=R3wqFh9Dko_GK00Exx7XI0DnnldRWMsxZypYX5y6SJo,7448
|
|
77
|
+
ripperdoc/utils/path_utils.py,sha256=C45Q3OeXnj-0FVEtvf_tdG5922XB6HthUzlUCvfc17Y,1626
|
|
78
|
+
ripperdoc/utils/prompt.py,sha256=BV87KXX4aPdv63zsZdtD169ZAqat5wxltgUCcN1vIuk,523
|
|
79
|
+
ripperdoc/utils/safe_get_cwd.py,sha256=hZXQ1oJBCXuk1QBmmfqgDsr1icVOAfGSxABp032GauI,716
|
|
80
|
+
ripperdoc/utils/sandbox_utils.py,sha256=G91P8dw2VFcCiCpjXZ4LvzbAPiO8REqMhw39eI5Z4dU,1123
|
|
81
|
+
ripperdoc/utils/session_history.py,sha256=Z-stx88yaWzJ5iqOLCeS_z8gg1G4w6j4OMoff9r7JvA,7965
|
|
82
|
+
ripperdoc/utils/session_usage.py,sha256=p8_s46zDTzV1qzP4HR4PuZmLeJvSfq9mG_Y5rCnRYyA,3213
|
|
83
|
+
ripperdoc/utils/shell_token_utils.py,sha256=SduoSU-RERJdM_7gBn0urr5UXtl4XOpPgydBd2fwzWg,2500
|
|
84
|
+
ripperdoc/utils/shell_utils.py,sha256=t-neFPy_VhEmWZ79J7hh1ULBEdX116Rb9_pnXvir1Jw,5235
|
|
85
|
+
ripperdoc/utils/todo.py,sha256=ejWd42AAVT15GJvCqb21GERSIbsdY-bwZDNnst4xebQ,6903
|
|
86
|
+
ripperdoc/utils/permissions/__init__.py,sha256=-1aKvRC05kuvLacbeu7w1W5ANamOTAho4Y0lY2vz0W0,522
|
|
87
|
+
ripperdoc/utils/permissions/path_validation_utils.py,sha256=jWcvBWUOgiEOncn_b2Fz7FBJL3XiPlyPQhNT4ZJ7p10,5681
|
|
88
|
+
ripperdoc/utils/permissions/shell_command_validation.py,sha256=BkK-wEwAuJPoC4XIx2Zj6MF3gXcWReozIwigXgib0z0,2446
|
|
89
|
+
ripperdoc/utils/permissions/tool_permission_utils.py,sha256=6Fdu9-dMKhLsUExjEjoS0EUeRpEVN5UkqyseIC05YmM,9207
|
|
90
|
+
ripperdoc-0.2.3.dist-info/licenses/LICENSE,sha256=bRv9UhBor6GhnQDj12RciDcRfu0R7sB-lqCy1sWF75c,9242
|
|
91
|
+
ripperdoc-0.2.3.dist-info/METADATA,sha256=0ko9dUoMiBntF-XdI7oD70VpbU7-GWpDBiZy_oAknq8,5362
|
|
92
|
+
ripperdoc-0.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
93
|
+
ripperdoc-0.2.3.dist-info/entry_points.txt,sha256=79aohFxFPJmrQ3-Mhain04vb3EWpuc0EyzvDDUnwAu4,81
|
|
94
|
+
ripperdoc-0.2.3.dist-info/top_level.txt,sha256=u8LbdTr1a-laHgCO0Utl_R3QGFUhLxWelCDnP2ZgpCU,10
|
|
95
|
+
ripperdoc-0.2.3.dist-info/RECORD,,
|
ripperdoc-0.2.0.dist-info/RECORD
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
ripperdoc/__init__.py,sha256=8uE0Wb2dqhd3j7g6jm1ObxZ2cn3yf5E3SoVpLzYcFJs,66
|
|
2
|
-
ripperdoc/__main__.py,sha256=7oIFEXI2irIoZ_dhcMd3hCs4Dj8tmMBbwiVACAoeE-k,506
|
|
3
|
-
ripperdoc/cli/__init__.py,sha256=03wf6gXBcEgXJrDJS-W_5BEG_DdJ_ep7CxQFPML-73g,35
|
|
4
|
-
ripperdoc/cli/cli.py,sha256=ldVNPsZIEdwaNwbrwbgAZMfQFQ1tEXw5uz26fP7avGc,10928
|
|
5
|
-
ripperdoc/cli/commands/__init__.py,sha256=2ymRdOj3EekyIioOxhJNMZyjWaSNVixNZZ6DONfTXtc,2189
|
|
6
|
-
ripperdoc/cli/commands/agents_cmd.py,sha256=_4Cf1onhtgVrT4PnVPqHLueiAEbJcM9VP-_usPs77xE,9277
|
|
7
|
-
ripperdoc/cli/commands/base.py,sha256=4KUjxCM04MwbSMUKVNEBph_jeAKPI8b5MHsUFoz7l5g,386
|
|
8
|
-
ripperdoc/cli/commands/clear_cmd.py,sha256=zSYT0Nn_htZzLWTTQ4E5KWHfRg0Q5CYvRO4e--7thBY,345
|
|
9
|
-
ripperdoc/cli/commands/compact_cmd.py,sha256=C_qdPTPdg1cOHdmODkaYoRusosgiqRK6c6KID_Gwq0k,330
|
|
10
|
-
ripperdoc/cli/commands/config_cmd.py,sha256=ebIQk7zUFv353liWfbBSSfPiOaaCR7rQsd_eTw7nsvY,884
|
|
11
|
-
ripperdoc/cli/commands/context_cmd.py,sha256=8PpTi4b0-tcxuxf4Qh59HOyH4eGmGe8TV7T_KrS_9yw,4007
|
|
12
|
-
ripperdoc/cli/commands/cost_cmd.py,sha256=AoGRDDu48qsMGuS5zgScg_YdNqkwoj33D2PTh-1uZ34,2637
|
|
13
|
-
ripperdoc/cli/commands/exit_cmd.py,sha256=B0CNKQos2eRC4LSjizLdKsFYzFfwRkrUur6Afu3Fh9M,334
|
|
14
|
-
ripperdoc/cli/commands/help_cmd.py,sha256=iz1vR-rmWsvvfzdebLiIWEWrcMZo5_Eb55_wLr4Ufno,508
|
|
15
|
-
ripperdoc/cli/commands/mcp_cmd.py,sha256=S0iQxclxqgbIxbKcC9oFrckLalzk-1eyAYwkfEZQsGU,2307
|
|
16
|
-
ripperdoc/cli/commands/models_cmd.py,sha256=fQOwb_5_vNPNKF2NHepvLrsE25qTETPC9zlkvnrRjxs,11915
|
|
17
|
-
ripperdoc/cli/commands/resume_cmd.py,sha256=F99haT29dUHYlgrIYKk2cadSOTrwkLOEs_D2RotNZXI,2977
|
|
18
|
-
ripperdoc/cli/commands/status_cmd.py,sha256=rAhHksegqdLGy551Hh22oVwR6ZSfkDvAPOjNiNQJ9_s,5494
|
|
19
|
-
ripperdoc/cli/commands/tasks_cmd.py,sha256=oCGEdfjCqPSHJOAWGQUABl7X5ltYJWtRPB69b8d6m4w,7286
|
|
20
|
-
ripperdoc/cli/commands/todos_cmd.py,sha256=7Q0B1NVqGtB3R29ndbn4m0VQQm-YQ7d4Wlk7vJ7dLQI,1848
|
|
21
|
-
ripperdoc/cli/commands/tools_cmd.py,sha256=3cMi0vN4mAUhpKqJtRgNvZfcKzRPaMs_pkYYXlyvSSU,384
|
|
22
|
-
ripperdoc/cli/ui/__init__.py,sha256=TxSzTYdITlrYmYVfins_w_jzPqqWRpqky5u1ikwvmtM,43
|
|
23
|
-
ripperdoc/cli/ui/context_display.py,sha256=3ezdtHVwltkPQ5etYwfqUh-fjnpPu8B3P81UzrdHxZs,10020
|
|
24
|
-
ripperdoc/cli/ui/helpers.py,sha256=TJCipP0neh-96ETQfGhusCJ4aWt5gLw1HZbI-3bWDpw,739
|
|
25
|
-
ripperdoc/cli/ui/rich_ui.py,sha256=jBTcJc5hTXEgeih7CtJUqo6sB7nVwEg3NGZ4DvJI9QA,43907
|
|
26
|
-
ripperdoc/cli/ui/spinner.py,sha256=XsPRwJ-70InLX9Qw50CEgSHn5oKA5PFIue8Un4edhUk,1449
|
|
27
|
-
ripperdoc/core/__init__.py,sha256=UemJCA-Y8df1466AX-YbRFj071zKajmqO1mi40YVW2g,40
|
|
28
|
-
ripperdoc/core/agents.py,sha256=sLgMeoDYXciBszRLCdbVCZRfxzXjlwGpWcx8qFk1Xm4,10240
|
|
29
|
-
ripperdoc/core/commands.py,sha256=NXCkljYbAP4dDoRy-_3semFNWxG4YAk9q82u8FTKH60,835
|
|
30
|
-
ripperdoc/core/config.py,sha256=gxR0uOhX11nv9fUQpcnQ1fHRtUEpt6v1GHSItyYxQYA,13240
|
|
31
|
-
ripperdoc/core/default_tools.py,sha256=PpZ49yjDzV5vtSkYq_quxY8u-nk5uJPp25RfMa9wZtA,2086
|
|
32
|
-
ripperdoc/core/permissions.py,sha256=lEKAUX9ksQxOFrPUkwwQe_3PMAr2xKgGBwjTOz8a8hM,8398
|
|
33
|
-
ripperdoc/core/query.py,sha256=f3sfzM9vSZJGbCUMg2wmT7iESCgFrNv2DqGYL38mJK0,26329
|
|
34
|
-
ripperdoc/core/system_prompt.py,sha256=OG_GUm9E30FnvL4p2L3_1A7oG54V0Kw5xRJPRzJrx2o,24066
|
|
35
|
-
ripperdoc/core/tool.py,sha256=GbmQSVc8XQXw4aDVwFpYGZV3OFbU5wIz7n3xNWlNeyI,6446
|
|
36
|
-
ripperdoc/sdk/__init__.py,sha256=aDSgI4lcCDs9cV3bxNmEEV3SuYx2aCd4VnUjs6H-R7E,213
|
|
37
|
-
ripperdoc/sdk/client.py,sha256=21f8viIh3BhSjXcI_MvgzfAcy7r289Thyhc_qgnQrB0,10556
|
|
38
|
-
ripperdoc/tools/__init__.py,sha256=RBFz0DDnztDXMqv_zRxFHVY-ez2HYcncx8zh_y-BX6w,42
|
|
39
|
-
ripperdoc/tools/background_shell.py,sha256=zdea03hpSGHEsVreyApn2bWMLzMQYo5ZmaHDp_Q11SA,9235
|
|
40
|
-
ripperdoc/tools/bash_output_tool.py,sha256=ljIOzTOnkbQfe3jExlhpUlMiLT6HpeD-1QI-D1CwHh8,3379
|
|
41
|
-
ripperdoc/tools/bash_tool.py,sha256=Ww92WIybH_5fqCJTEyR6JcIL6OQgj283uqvkFa1paqU,36071
|
|
42
|
-
ripperdoc/tools/file_edit_tool.py,sha256=zJib_Lqh9MlgPbNat9-LK1TTt8GsAXIuBEusuGWw8v8,11153
|
|
43
|
-
ripperdoc/tools/file_read_tool.py,sha256=EKA-OvDgRRzIMeK4t5ZFavB5ZTk0TzOJwxg-vD5ggho,5868
|
|
44
|
-
ripperdoc/tools/file_write_tool.py,sha256=X4b8PDJszRtp_B6daCsUsQAwUc-4PsNbXpm3FUG5sR0,4569
|
|
45
|
-
ripperdoc/tools/glob_tool.py,sha256=WxTz-cOz-whMxbQGCLpNmXfLgnxH9dh-1EFh11id64Q,4309
|
|
46
|
-
ripperdoc/tools/grep_tool.py,sha256=KyR5abvzy780evWu6tuMv9v6xGyGrTlLliJHan1N3S4,8098
|
|
47
|
-
ripperdoc/tools/kill_bash_tool.py,sha256=36F8w2Rm1IVQitwOAwS-D8NTnyQdWfKWIam44qlXErk,4625
|
|
48
|
-
ripperdoc/tools/ls_tool.py,sha256=H9pYsZKwx7j7Ow98eTx67KNKFbNO0yY-JUX34lAuhy8,8928
|
|
49
|
-
ripperdoc/tools/mcp_tools.py,sha256=msGNVKx8aDoLhs7Xvta1XMdLNP78W8Pi_CqLhwIjKiM,30309
|
|
50
|
-
ripperdoc/tools/multi_edit_tool.py,sha256=EpkCsjVTXTa4fOfETABjXNoKvQ6LRK8Xnv_t22N_Mcg,14968
|
|
51
|
-
ripperdoc/tools/notebook_edit_tool.py,sha256=y7_NuB7NrmUu-KkRQfkSegHRuiyPYdGxpjD9pFb_f5M,12064
|
|
52
|
-
ripperdoc/tools/task_tool.py,sha256=qp8jYLy8VMriny4fqmobYXh1dac2UyCBSAXZNk4iI0w,11739
|
|
53
|
-
ripperdoc/tools/todo_tool.py,sha256=aB0ejA_np3zLWTNUmC7yEVlx46tTtT_WgHEsqrbXIn4,12855
|
|
54
|
-
ripperdoc/tools/tool_search_tool.py,sha256=l3DU2UuCPU-XSvFDsdIrl0VkdwtR_E5dMk0idAP2p2w,13333
|
|
55
|
-
ripperdoc/utils/__init__.py,sha256=gdso60znB2hsYZ_YZBKVcuOY3QVfoqD2wHQ4pvr5lSw,37
|
|
56
|
-
ripperdoc/utils/bash_constants.py,sha256=KNn8bzB6nVU5jid9jvjiH4FAu8pP3DZONJ-OknJypAQ,1641
|
|
57
|
-
ripperdoc/utils/bash_output_utils.py,sha256=3Cf5wKJzRbUesmCNy5HtXIBtv0Z2BxklTfFHJ9q1T3w,1210
|
|
58
|
-
ripperdoc/utils/exit_code_handlers.py,sha256=QtO1iDxVAb8Xp03D6_QixPoJC-RQlcp3ssIo_rm4two,7973
|
|
59
|
-
ripperdoc/utils/log.py,sha256=QoqIxTctArJ3L5dwL6v4AZkMTGQozhDlNdM5BAn3QL8,2361
|
|
60
|
-
ripperdoc/utils/mcp.py,sha256=w2yHygSWNUKyM4AU2xZmfEMyfN3oZAHuswtEAD0v1Dc,14652
|
|
61
|
-
ripperdoc/utils/memory.py,sha256=5Shv8O8VjlUz0JHbIYm6oPLP5GAzzhJ3ZJIf3-GHXnE,7336
|
|
62
|
-
ripperdoc/utils/message_compaction.py,sha256=NVyDU58wsFuW85XWemKJqvtA1BMR-J8qCx10BIYKwnw,24112
|
|
63
|
-
ripperdoc/utils/messages.py,sha256=1vAYabUXbuywYQETH7GStQGehPnkxrZ7ZkzeXbv4JC4,14725
|
|
64
|
-
ripperdoc/utils/output_utils.py,sha256=9vROdxdZ_8FO1I_OxuTuTeUPWcJoWy9laTUFzTCDths,6162
|
|
65
|
-
ripperdoc/utils/path_utils.py,sha256=C45Q3OeXnj-0FVEtvf_tdG5922XB6HthUzlUCvfc17Y,1626
|
|
66
|
-
ripperdoc/utils/safe_get_cwd.py,sha256=R0zQYhM8kHpZDz12-JHx6ryF3Os2wncOOHXY45ZD7kg,585
|
|
67
|
-
ripperdoc/utils/sandbox_utils.py,sha256=G91P8dw2VFcCiCpjXZ4LvzbAPiO8REqMhw39eI5Z4dU,1123
|
|
68
|
-
ripperdoc/utils/session_history.py,sha256=xo4_Qaoy0odzElYcdnzU70TGlIak5e8uybkgFs9kSPQ,7478
|
|
69
|
-
ripperdoc/utils/session_usage.py,sha256=iz4B9MRhPbwemo9-beeZ8axcpGEe0kEc-Jghlexd_xU,2961
|
|
70
|
-
ripperdoc/utils/shell_token_utils.py,sha256=SduoSU-RERJdM_7gBn0urr5UXtl4XOpPgydBd2fwzWg,2500
|
|
71
|
-
ripperdoc/utils/todo.py,sha256=ZnYqCBX28U7viC7TPuNIf86TWmONMeHgsH7HrG_euPc,6889
|
|
72
|
-
ripperdoc/utils/permissions/__init__.py,sha256=-1aKvRC05kuvLacbeu7w1W5ANamOTAho4Y0lY2vz0W0,522
|
|
73
|
-
ripperdoc/utils/permissions/path_validation_utils.py,sha256=0saGffF-IwCHc_GrDimU8Vz_SAczJb_Ui29ea_hkj4E,5482
|
|
74
|
-
ripperdoc/utils/permissions/shell_command_validation.py,sha256=BkK-wEwAuJPoC4XIx2Zj6MF3gXcWReozIwigXgib0z0,2446
|
|
75
|
-
ripperdoc/utils/permissions/tool_permission_utils.py,sha256=6Fdu9-dMKhLsUExjEjoS0EUeRpEVN5UkqyseIC05YmM,9207
|
|
76
|
-
ripperdoc-0.2.0.dist-info/licenses/LICENSE,sha256=bRv9UhBor6GhnQDj12RciDcRfu0R7sB-lqCy1sWF75c,9242
|
|
77
|
-
ripperdoc-0.2.0.dist-info/METADATA,sha256=dwxYrx56ASM7ZbKyF5n6ZfZq9DwGfHU8sJWnOVCTY7M,5317
|
|
78
|
-
ripperdoc-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
79
|
-
ripperdoc-0.2.0.dist-info/entry_points.txt,sha256=79aohFxFPJmrQ3-Mhain04vb3EWpuc0EyzvDDUnwAu4,81
|
|
80
|
-
ripperdoc-0.2.0.dist-info/top_level.txt,sha256=u8LbdTr1a-laHgCO0Utl_R3QGFUhLxWelCDnP2ZgpCU,10
|
|
81
|
-
ripperdoc-0.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|