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.
Files changed (65) hide show
  1. ripperdoc/__init__.py +1 -1
  2. ripperdoc/cli/cli.py +74 -9
  3. ripperdoc/cli/commands/__init__.py +4 -0
  4. ripperdoc/cli/commands/agents_cmd.py +30 -4
  5. ripperdoc/cli/commands/context_cmd.py +11 -1
  6. ripperdoc/cli/commands/cost_cmd.py +5 -0
  7. ripperdoc/cli/commands/doctor_cmd.py +208 -0
  8. ripperdoc/cli/commands/memory_cmd.py +202 -0
  9. ripperdoc/cli/commands/models_cmd.py +61 -6
  10. ripperdoc/cli/commands/resume_cmd.py +4 -2
  11. ripperdoc/cli/commands/status_cmd.py +1 -1
  12. ripperdoc/cli/commands/tasks_cmd.py +27 -0
  13. ripperdoc/cli/ui/rich_ui.py +258 -11
  14. ripperdoc/cli/ui/thinking_spinner.py +128 -0
  15. ripperdoc/core/agents.py +14 -4
  16. ripperdoc/core/config.py +56 -3
  17. ripperdoc/core/default_tools.py +16 -2
  18. ripperdoc/core/permissions.py +19 -0
  19. ripperdoc/core/providers/__init__.py +31 -0
  20. ripperdoc/core/providers/anthropic.py +136 -0
  21. ripperdoc/core/providers/base.py +187 -0
  22. ripperdoc/core/providers/gemini.py +172 -0
  23. ripperdoc/core/providers/openai.py +142 -0
  24. ripperdoc/core/query.py +510 -386
  25. ripperdoc/core/query_utils.py +578 -0
  26. ripperdoc/core/system_prompt.py +2 -1
  27. ripperdoc/core/tool.py +16 -1
  28. ripperdoc/sdk/client.py +12 -1
  29. ripperdoc/tools/background_shell.py +63 -21
  30. ripperdoc/tools/bash_tool.py +48 -13
  31. ripperdoc/tools/file_edit_tool.py +20 -0
  32. ripperdoc/tools/file_read_tool.py +23 -0
  33. ripperdoc/tools/file_write_tool.py +20 -0
  34. ripperdoc/tools/glob_tool.py +59 -15
  35. ripperdoc/tools/grep_tool.py +7 -0
  36. ripperdoc/tools/ls_tool.py +246 -73
  37. ripperdoc/tools/mcp_tools.py +32 -10
  38. ripperdoc/tools/multi_edit_tool.py +23 -0
  39. ripperdoc/tools/notebook_edit_tool.py +18 -3
  40. ripperdoc/tools/task_tool.py +7 -0
  41. ripperdoc/tools/todo_tool.py +157 -25
  42. ripperdoc/tools/tool_search_tool.py +17 -4
  43. ripperdoc/utils/file_watch.py +134 -0
  44. ripperdoc/utils/git_utils.py +274 -0
  45. ripperdoc/utils/json_utils.py +27 -0
  46. ripperdoc/utils/log.py +129 -29
  47. ripperdoc/utils/mcp.py +71 -6
  48. ripperdoc/utils/memory.py +12 -1
  49. ripperdoc/utils/message_compaction.py +22 -5
  50. ripperdoc/utils/messages.py +72 -17
  51. ripperdoc/utils/output_utils.py +34 -9
  52. ripperdoc/utils/permissions/path_validation_utils.py +6 -0
  53. ripperdoc/utils/prompt.py +17 -0
  54. ripperdoc/utils/safe_get_cwd.py +4 -0
  55. ripperdoc/utils/session_history.py +27 -9
  56. ripperdoc/utils/session_usage.py +7 -0
  57. ripperdoc/utils/shell_utils.py +159 -0
  58. ripperdoc/utils/todo.py +2 -2
  59. {ripperdoc-0.2.0.dist-info → ripperdoc-0.2.3.dist-info}/METADATA +4 -2
  60. ripperdoc-0.2.3.dist-info/RECORD +95 -0
  61. ripperdoc-0.2.0.dist-info/RECORD +0 -81
  62. {ripperdoc-0.2.0.dist-info → ripperdoc-0.2.3.dist-info}/WHEEL +0 -0
  63. {ripperdoc-0.2.0.dist-info → ripperdoc-0.2.3.dist-info}/entry_points.txt +0 -0
  64. {ripperdoc-0.2.0.dist-info → ripperdoc-0.2.3.dist-info}/licenses/LICENSE +0 -0
  65. {ripperdoc-0.2.0.dist-info → ripperdoc-0.2.3.dist-info}/top_level.txt +0 -0
@@ -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
- # Truncate: keep start and end
135
- start_chars = min(TRUNCATE_KEEP_START, max_chars // 2)
136
- end_chars = min(TRUNCATE_KEEP_END, max_chars - start_chars - 100)
137
-
138
- truncated = (
139
- text[:start_chars]
140
- + f"\n\n... [Output truncated: {original_length - start_chars - end_chars} characters omitted] ...\n\n"
141
- + text[-end_chars:]
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)
@@ -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(f"Failed to parse session history line: {exc}")
105
+ logger.debug(
106
+ f"Failed to parse session history line: {exc}",
107
+ exc_info=True,
108
+ )
106
109
  continue
107
- except Exception as exc:
108
- logger.error(f"Failed to load seen IDs from session {self.session_id}: {exc}")
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 as exc:
137
+ except Exception:
132
138
  # Avoid crashing the UI if logging fails
133
- logger.error(f"Failed to append message to session {self.session_id}: {exc}")
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.error(f"Failed to load session summary from {jsonl_path}: {exc}")
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(f"Failed to deserialize message in session {session_id}: {exc}")
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 as exc:
212
- logger.error(f"Failed to load session messages for {session_id}: {exc}")
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
@@ -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 as exc:
87
- logger.error(f"Failed to load todos from {path}: {exc}")
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.0
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,,
@@ -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,,