ripperdoc 0.2.8__py3-none-any.whl → 0.2.10__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 (94) hide show
  1. ripperdoc/__init__.py +1 -1
  2. ripperdoc/cli/cli.py +257 -123
  3. ripperdoc/cli/commands/__init__.py +2 -1
  4. ripperdoc/cli/commands/agents_cmd.py +138 -8
  5. ripperdoc/cli/commands/clear_cmd.py +9 -4
  6. ripperdoc/cli/commands/config_cmd.py +1 -1
  7. ripperdoc/cli/commands/context_cmd.py +3 -2
  8. ripperdoc/cli/commands/doctor_cmd.py +18 -4
  9. ripperdoc/cli/commands/exit_cmd.py +1 -0
  10. ripperdoc/cli/commands/hooks_cmd.py +27 -53
  11. ripperdoc/cli/commands/models_cmd.py +27 -10
  12. ripperdoc/cli/commands/permissions_cmd.py +27 -9
  13. ripperdoc/cli/commands/resume_cmd.py +9 -3
  14. ripperdoc/cli/commands/stats_cmd.py +244 -0
  15. ripperdoc/cli/commands/status_cmd.py +4 -4
  16. ripperdoc/cli/commands/tasks_cmd.py +8 -4
  17. ripperdoc/cli/ui/file_mention_completer.py +2 -1
  18. ripperdoc/cli/ui/interrupt_handler.py +2 -3
  19. ripperdoc/cli/ui/message_display.py +4 -2
  20. ripperdoc/cli/ui/panels.py +1 -0
  21. ripperdoc/cli/ui/provider_options.py +247 -0
  22. ripperdoc/cli/ui/rich_ui.py +403 -81
  23. ripperdoc/cli/ui/spinner.py +54 -18
  24. ripperdoc/cli/ui/thinking_spinner.py +1 -2
  25. ripperdoc/cli/ui/tool_renderers.py +8 -2
  26. ripperdoc/cli/ui/wizard.py +213 -0
  27. ripperdoc/core/agents.py +19 -6
  28. ripperdoc/core/config.py +51 -17
  29. ripperdoc/core/custom_commands.py +7 -6
  30. ripperdoc/core/default_tools.py +101 -12
  31. ripperdoc/core/hooks/config.py +1 -3
  32. ripperdoc/core/hooks/events.py +27 -28
  33. ripperdoc/core/hooks/executor.py +4 -6
  34. ripperdoc/core/hooks/integration.py +12 -21
  35. ripperdoc/core/hooks/llm_callback.py +59 -0
  36. ripperdoc/core/hooks/manager.py +40 -15
  37. ripperdoc/core/permissions.py +118 -12
  38. ripperdoc/core/providers/anthropic.py +109 -36
  39. ripperdoc/core/providers/gemini.py +70 -5
  40. ripperdoc/core/providers/openai.py +89 -24
  41. ripperdoc/core/query.py +273 -68
  42. ripperdoc/core/query_utils.py +2 -0
  43. ripperdoc/core/skills.py +9 -3
  44. ripperdoc/core/system_prompt.py +4 -2
  45. ripperdoc/core/tool.py +17 -8
  46. ripperdoc/sdk/client.py +79 -4
  47. ripperdoc/tools/ask_user_question_tool.py +5 -3
  48. ripperdoc/tools/background_shell.py +307 -135
  49. ripperdoc/tools/bash_output_tool.py +1 -1
  50. ripperdoc/tools/bash_tool.py +63 -24
  51. ripperdoc/tools/dynamic_mcp_tool.py +29 -8
  52. ripperdoc/tools/enter_plan_mode_tool.py +1 -1
  53. ripperdoc/tools/exit_plan_mode_tool.py +1 -1
  54. ripperdoc/tools/file_edit_tool.py +167 -54
  55. ripperdoc/tools/file_read_tool.py +28 -4
  56. ripperdoc/tools/file_write_tool.py +13 -10
  57. ripperdoc/tools/glob_tool.py +3 -2
  58. ripperdoc/tools/grep_tool.py +3 -2
  59. ripperdoc/tools/kill_bash_tool.py +1 -1
  60. ripperdoc/tools/ls_tool.py +1 -1
  61. ripperdoc/tools/lsp_tool.py +615 -0
  62. ripperdoc/tools/mcp_tools.py +13 -10
  63. ripperdoc/tools/multi_edit_tool.py +8 -7
  64. ripperdoc/tools/notebook_edit_tool.py +7 -4
  65. ripperdoc/tools/skill_tool.py +1 -1
  66. ripperdoc/tools/task_tool.py +519 -69
  67. ripperdoc/tools/todo_tool.py +2 -2
  68. ripperdoc/tools/tool_search_tool.py +3 -2
  69. ripperdoc/utils/conversation_compaction.py +9 -5
  70. ripperdoc/utils/file_watch.py +214 -5
  71. ripperdoc/utils/json_utils.py +2 -1
  72. ripperdoc/utils/lsp.py +806 -0
  73. ripperdoc/utils/mcp.py +11 -3
  74. ripperdoc/utils/memory.py +4 -2
  75. ripperdoc/utils/message_compaction.py +21 -7
  76. ripperdoc/utils/message_formatting.py +14 -7
  77. ripperdoc/utils/messages.py +126 -67
  78. ripperdoc/utils/path_ignore.py +35 -8
  79. ripperdoc/utils/permissions/path_validation_utils.py +2 -1
  80. ripperdoc/utils/permissions/shell_command_validation.py +427 -91
  81. ripperdoc/utils/permissions/tool_permission_utils.py +174 -15
  82. ripperdoc/utils/safe_get_cwd.py +2 -1
  83. ripperdoc/utils/session_heatmap.py +244 -0
  84. ripperdoc/utils/session_history.py +13 -6
  85. ripperdoc/utils/session_stats.py +293 -0
  86. ripperdoc/utils/todo.py +2 -1
  87. ripperdoc/utils/token_estimation.py +6 -1
  88. {ripperdoc-0.2.8.dist-info → ripperdoc-0.2.10.dist-info}/METADATA +8 -2
  89. ripperdoc-0.2.10.dist-info/RECORD +129 -0
  90. ripperdoc-0.2.8.dist-info/RECORD +0 -121
  91. {ripperdoc-0.2.8.dist-info → ripperdoc-0.2.10.dist-info}/WHEEL +0 -0
  92. {ripperdoc-0.2.8.dist-info → ripperdoc-0.2.10.dist-info}/entry_points.txt +0 -0
  93. {ripperdoc-0.2.8.dist-info → ripperdoc-0.2.10.dist-info}/licenses/LICENSE +0 -0
  94. {ripperdoc-0.2.8.dist-info → ripperdoc-0.2.10.dist-info}/top_level.txt +0 -0
@@ -149,7 +149,7 @@ class MultiEditTool(Tool[MultiEditToolInput, MultiEditToolOutput]):
149
149
  ),
150
150
  ]
151
151
 
152
- async def prompt(self, safe_mode: bool = False) -> str:
152
+ async def prompt(self, yolo_mode: bool = False) -> str:
153
153
  return MULTI_EDIT_DESCRIPTION
154
154
 
155
155
  def is_read_only(self) -> bool:
@@ -190,9 +190,7 @@ class MultiEditTool(Tool[MultiEditToolInput, MultiEditToolOutput]):
190
190
 
191
191
  # Check if this is a file creation (first edit has empty old_string)
192
192
  is_creation = (
193
- not path.exists()
194
- and len(input_data.edits) > 0
195
- and input_data.edits[0].old_string == ""
193
+ not path.exists() and len(input_data.edits) > 0 and input_data.edits[0].old_string == ""
196
194
  )
197
195
 
198
196
  # If file exists, check if it has been read before editing
@@ -350,7 +348,8 @@ class MultiEditTool(Tool[MultiEditToolInput, MultiEditToolOutput]):
350
348
  # pragma: no cover - unlikely permission issue
351
349
  logger.warning(
352
350
  "[multi_edit_tool] Error reading file before edits: %s: %s",
353
- type(exc).__name__, exc,
351
+ type(exc).__name__,
352
+ exc,
354
353
  extra={"file_path": str(file_path)},
355
354
  )
356
355
  output = MultiEditToolOutput(
@@ -408,13 +407,15 @@ class MultiEditTool(Tool[MultiEditToolInput, MultiEditToolOutput]):
408
407
  except (OSError, IOError, RuntimeError) as exc:
409
408
  logger.warning(
410
409
  "[multi_edit_tool] Failed to record file snapshot: %s: %s",
411
- type(exc).__name__, exc,
410
+ type(exc).__name__,
411
+ exc,
412
412
  extra={"file_path": str(file_path)},
413
413
  )
414
414
  except (OSError, IOError, PermissionError, UnicodeDecodeError) as exc:
415
415
  logger.warning(
416
416
  "[multi_edit_tool] Error writing edited file: %s: %s",
417
- type(exc).__name__, exc,
417
+ type(exc).__name__,
418
+ exc,
418
419
  extra={"file_path": str(file_path)},
419
420
  )
420
421
  output = MultiEditToolOutput(
@@ -122,7 +122,7 @@ class NotebookEditTool(Tool[NotebookEditInput, NotebookEditOutput]):
122
122
  ),
123
123
  ]
124
124
 
125
- async def prompt(self, safe_mode: bool = False) -> str:
125
+ async def prompt(self, yolo_mode: bool = False) -> str:
126
126
  return NOTEBOOK_EDIT_DESCRIPTION
127
127
 
128
128
  def is_read_only(self) -> bool:
@@ -204,7 +204,8 @@ class NotebookEditTool(Tool[NotebookEditInput, NotebookEditOutput]):
204
204
  except (OSError, json.JSONDecodeError, UnicodeDecodeError) as exc:
205
205
  logger.warning(
206
206
  "Failed to parse notebook: %s: %s",
207
- type(exc).__name__, exc,
207
+ type(exc).__name__,
208
+ exc,
208
209
  extra={"path": str(path)},
209
210
  )
210
211
  return ValidationResult(
@@ -325,7 +326,8 @@ class NotebookEditTool(Tool[NotebookEditInput, NotebookEditOutput]):
325
326
  except (OSError, IOError, RuntimeError) as exc:
326
327
  logger.warning(
327
328
  "[notebook_edit_tool] Failed to record file snapshot: %s: %s",
328
- type(exc).__name__, exc,
329
+ type(exc).__name__,
330
+ exc,
329
331
  extra={"file_path": abs_notebook_path},
330
332
  )
331
333
 
@@ -344,7 +346,8 @@ class NotebookEditTool(Tool[NotebookEditInput, NotebookEditOutput]):
344
346
  # pragma: no cover - error path
345
347
  logger.warning(
346
348
  "Error editing notebook: %s: %s",
347
- type(exc).__name__, exc,
349
+ type(exc).__name__,
350
+ exc,
348
351
  extra={"path": input_data.notebook_path},
349
352
  )
350
353
  output = NotebookEditOutput(
@@ -82,7 +82,7 @@ class SkillTool(Tool[SkillToolInput, SkillToolOutput]):
82
82
  ),
83
83
  ]
84
84
 
85
- async def prompt(self, safe_mode: bool = False) -> str: # noqa: ARG002
85
+ async def prompt(self, yolo_mode: bool = False) -> str: # noqa: ARG002
86
86
  return (
87
87
  "Load a skill by name to read its SKILL.md content. "
88
88
  "Only call this when the skill description is clearly relevant. "