ripperdoc 0.2.6__tar.gz → 0.2.8__tar.gz

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 (153) hide show
  1. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/PKG-INFO +24 -3
  2. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/README.md +23 -2
  3. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/__init__.py +1 -1
  4. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/cli.py +5 -0
  5. ripperdoc-0.2.8/ripperdoc/cli/commands/__init__.py +147 -0
  6. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/clear_cmd.py +1 -0
  7. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/exit_cmd.py +1 -1
  8. ripperdoc-0.2.8/ripperdoc/cli/commands/help_cmd.py +30 -0
  9. ripperdoc-0.2.8/ripperdoc/cli/commands/hooks_cmd.py +636 -0
  10. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/permissions_cmd.py +36 -34
  11. ripperdoc-0.2.8/ripperdoc/cli/commands/resume_cmd.py +132 -0
  12. ripperdoc-0.2.8/ripperdoc/cli/ui/file_mention_completer.py +276 -0
  13. ripperdoc-0.2.8/ripperdoc/cli/ui/helpers.py +119 -0
  14. ripperdoc-0.2.8/ripperdoc/cli/ui/interrupt_handler.py +175 -0
  15. ripperdoc-0.2.8/ripperdoc/cli/ui/message_display.py +249 -0
  16. ripperdoc-0.2.8/ripperdoc/cli/ui/panels.py +63 -0
  17. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/ui/rich_ui.py +233 -648
  18. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/ui/tool_renderers.py +2 -2
  19. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/agents.py +4 -4
  20. ripperdoc-0.2.8/ripperdoc/core/custom_commands.py +411 -0
  21. ripperdoc-0.2.8/ripperdoc/core/hooks/__init__.py +99 -0
  22. ripperdoc-0.2.8/ripperdoc/core/hooks/config.py +303 -0
  23. ripperdoc-0.2.8/ripperdoc/core/hooks/events.py +540 -0
  24. ripperdoc-0.2.8/ripperdoc/core/hooks/executor.py +498 -0
  25. ripperdoc-0.2.8/ripperdoc/core/hooks/integration.py +353 -0
  26. ripperdoc-0.2.8/ripperdoc/core/hooks/manager.py +720 -0
  27. ripperdoc-0.2.8/ripperdoc/core/providers/anthropic.py +657 -0
  28. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/query.py +61 -4
  29. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/query_utils.py +1 -1
  30. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/tool.py +1 -1
  31. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/bash_tool.py +5 -5
  32. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/file_edit_tool.py +2 -2
  33. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/file_read_tool.py +2 -2
  34. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/multi_edit_tool.py +1 -1
  35. ripperdoc-0.2.8/ripperdoc/utils/conversation_compaction.py +476 -0
  36. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/message_compaction.py +109 -154
  37. ripperdoc-0.2.8/ripperdoc/utils/message_formatting.py +216 -0
  38. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/messages.py +31 -9
  39. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/path_ignore.py +3 -4
  40. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/session_history.py +19 -7
  41. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc.egg-info/PKG-INFO +24 -3
  42. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc.egg-info/SOURCES.txt +18 -0
  43. ripperdoc-0.2.8/tests/test_compact.py +159 -0
  44. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_context_limits.py +1 -1
  45. ripperdoc-0.2.8/tests/test_custom_commands.py +264 -0
  46. ripperdoc-0.2.8/tests/test_file_mention_completer.py +78 -0
  47. ripperdoc-0.2.8/tests/test_hooks_cmd.py +139 -0
  48. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_messages.py +35 -0
  49. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_path_ignore.py +0 -1
  50. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_sdk.py +3 -3
  51. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_skills.py +5 -5
  52. ripperdoc-0.2.6/ripperdoc/cli/commands/__init__.py +0 -82
  53. ripperdoc-0.2.6/ripperdoc/cli/commands/help_cmd.py +0 -20
  54. ripperdoc-0.2.6/ripperdoc/cli/commands/resume_cmd.py +0 -98
  55. ripperdoc-0.2.6/ripperdoc/cli/ui/helpers.py +0 -22
  56. ripperdoc-0.2.6/ripperdoc/core/providers/anthropic.py +0 -250
  57. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/LICENSE +0 -0
  58. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/pyproject.toml +0 -0
  59. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/__main__.py +0 -0
  60. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/__init__.py +0 -0
  61. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/agents_cmd.py +0 -0
  62. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/base.py +0 -0
  63. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/compact_cmd.py +0 -0
  64. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/config_cmd.py +0 -0
  65. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/context_cmd.py +0 -0
  66. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/cost_cmd.py +0 -0
  67. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/doctor_cmd.py +0 -0
  68. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/mcp_cmd.py +0 -0
  69. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/memory_cmd.py +0 -0
  70. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/models_cmd.py +0 -0
  71. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/status_cmd.py +0 -0
  72. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/tasks_cmd.py +0 -0
  73. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/todos_cmd.py +0 -0
  74. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/commands/tools_cmd.py +0 -0
  75. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/ui/__init__.py +0 -0
  76. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/ui/context_display.py +0 -0
  77. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/ui/spinner.py +0 -0
  78. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/cli/ui/thinking_spinner.py +0 -0
  79. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/__init__.py +0 -0
  80. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/commands.py +0 -0
  81. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/config.py +0 -0
  82. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/default_tools.py +0 -0
  83. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/permissions.py +0 -0
  84. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/providers/__init__.py +0 -0
  85. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/providers/base.py +0 -0
  86. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/providers/gemini.py +0 -0
  87. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/providers/openai.py +0 -0
  88. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/skills.py +0 -0
  89. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/core/system_prompt.py +0 -0
  90. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/sdk/__init__.py +0 -0
  91. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/sdk/client.py +0 -0
  92. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/__init__.py +0 -0
  93. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/ask_user_question_tool.py +0 -0
  94. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/background_shell.py +0 -0
  95. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/bash_output_tool.py +0 -0
  96. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/dynamic_mcp_tool.py +0 -0
  97. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/enter_plan_mode_tool.py +0 -0
  98. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/exit_plan_mode_tool.py +0 -0
  99. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/file_write_tool.py +0 -0
  100. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/glob_tool.py +0 -0
  101. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/grep_tool.py +0 -0
  102. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/kill_bash_tool.py +0 -0
  103. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/ls_tool.py +0 -0
  104. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/mcp_tools.py +0 -0
  105. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/notebook_edit_tool.py +0 -0
  106. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/skill_tool.py +0 -0
  107. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/task_tool.py +0 -0
  108. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/todo_tool.py +0 -0
  109. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/tools/tool_search_tool.py +0 -0
  110. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/__init__.py +0 -0
  111. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/bash_constants.py +0 -0
  112. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/bash_output_utils.py +0 -0
  113. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/coerce.py +0 -0
  114. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/context_length_errors.py +0 -0
  115. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/exit_code_handlers.py +0 -0
  116. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/file_watch.py +0 -0
  117. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/git_utils.py +0 -0
  118. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/json_utils.py +0 -0
  119. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/log.py +0 -0
  120. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/mcp.py +0 -0
  121. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/memory.py +0 -0
  122. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/output_utils.py +0 -0
  123. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/path_utils.py +0 -0
  124. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/permissions/__init__.py +0 -0
  125. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/permissions/path_validation_utils.py +0 -0
  126. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/permissions/shell_command_validation.py +0 -0
  127. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/permissions/tool_permission_utils.py +0 -0
  128. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/prompt.py +0 -0
  129. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/safe_get_cwd.py +0 -0
  130. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/sandbox_utils.py +0 -0
  131. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/session_usage.py +0 -0
  132. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/shell_token_utils.py +0 -0
  133. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/shell_utils.py +0 -0
  134. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/todo.py +0 -0
  135. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc/utils/token_estimation.py +0 -0
  136. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc.egg-info/dependency_links.txt +0 -0
  137. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc.egg-info/entry_points.txt +0 -0
  138. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc.egg-info/requires.txt +0 -0
  139. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/ripperdoc.egg-info/top_level.txt +0 -0
  140. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/setup.cfg +0 -0
  141. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/setup.py +0 -0
  142. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_background_shell_shutdown.py +0 -0
  143. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_cli_commands.py +0 -0
  144. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_config.py +0 -0
  145. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_context_length_errors.py +0 -0
  146. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_mcp_config.py +0 -0
  147. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_output_utils.py +0 -0
  148. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_permissions.py +0 -0
  149. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_query_abort.py +0 -0
  150. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_shell_permissions.py +0 -0
  151. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_todo.py +0 -0
  152. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_tool_search.py +0 -0
  153. {ripperdoc-0.2.6 → ripperdoc-0.2.8}/tests/test_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ripperdoc
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: AI-powered terminal assistant for coding tasks
5
5
  Author: Ripperdoc Team
6
6
  License: Apache-2.0
@@ -35,9 +35,28 @@ Requires-Dist: black>=23.0.0; extra == "dev"
35
35
  Requires-Dist: ruff>=0.1.0; extra == "dev"
36
36
  Dynamic: license-file
37
37
 
38
- # Ripperdoc - AI-Powered Terminal Assistant
38
+ <div align="center">
39
39
 
40
- Ripperdoc is an AI-powered terminal assistant for coding tasks, providing an interactive interface for AI-assisted development, file management, and command execution.
40
+ # Ripperdoc
41
+
42
+ _an open-source, extensible AI coding agent that runs in your terminal_
43
+
44
+ <p align="center">
45
+ <a href="https://opensource.org/licenses/Apache-2.0">
46
+ <img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg">
47
+ </a>
48
+ <a href="https://www.python.org/downloads/">
49
+ <img src="https://img.shields.io/badge/python-3.10+-blue.svg">
50
+ </a>
51
+ <a href="https://github.com/quantmew/ripperdoc/stargazers">
52
+ <img src="https://img.shields.io/github/stars/quantmew/ripperdoc.svg" alt="GitHub stars">
53
+ </a>
54
+ </p>
55
+ </div>
56
+
57
+ Ripperdoc is your on-machine AI coding assistant, similar to [Claude Code](https://claude.com/claude-code), [Codex](https://github.com/openai/codex), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Aider](https://github.com/paul-gauthier/aider), and [Goose](https://github.com/block/goose). It can write code, refactor projects, execute shell commands, and manage files - all through natural language conversations in your terminal.
58
+
59
+ Designed for maximum flexibility, Ripperdoc works with **any LLM** (Anthropic Claude, OpenAI, DeepSeek, local models via OpenAI-compatible APIs), supports **custom hooks** to intercept and control tool execution, and offers both an interactive CLI and a **Python SDK** for headless automation.
41
60
 
42
61
  [中文文档](README_CN.md) | [Contributing](CONTRIBUTING.md) | [Documentation](docs/)
43
62
 
@@ -60,6 +79,8 @@ Ripperdoc is an AI-powered terminal assistant for coding tasks, providing an int
60
79
  - **MCP Server Support** - Integration with Model Context Protocol servers
61
80
  - **Session Management** - Persistent session history and usage tracking
62
81
  - **Jupyter Notebook Support** - Edit .ipynb files directly
82
+ - **Hooks System** - Execute custom scripts at lifecycle events with decision control
83
+ - **Custom Commands** - Define reusable slash commands with parameter substitution
63
84
 
64
85
  ## Installation
65
86
 
@@ -1,6 +1,25 @@
1
- # Ripperdoc - AI-Powered Terminal Assistant
1
+ <div align="center">
2
2
 
3
- Ripperdoc is an AI-powered terminal assistant for coding tasks, providing an interactive interface for AI-assisted development, file management, and command execution.
3
+ # Ripperdoc
4
+
5
+ _an open-source, extensible AI coding agent that runs in your terminal_
6
+
7
+ <p align="center">
8
+ <a href="https://opensource.org/licenses/Apache-2.0">
9
+ <img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg">
10
+ </a>
11
+ <a href="https://www.python.org/downloads/">
12
+ <img src="https://img.shields.io/badge/python-3.10+-blue.svg">
13
+ </a>
14
+ <a href="https://github.com/quantmew/ripperdoc/stargazers">
15
+ <img src="https://img.shields.io/github/stars/quantmew/ripperdoc.svg" alt="GitHub stars">
16
+ </a>
17
+ </p>
18
+ </div>
19
+
20
+ Ripperdoc is your on-machine AI coding assistant, similar to [Claude Code](https://claude.com/claude-code), [Codex](https://github.com/openai/codex), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Aider](https://github.com/paul-gauthier/aider), and [Goose](https://github.com/block/goose). It can write code, refactor projects, execute shell commands, and manage files - all through natural language conversations in your terminal.
21
+
22
+ Designed for maximum flexibility, Ripperdoc works with **any LLM** (Anthropic Claude, OpenAI, DeepSeek, local models via OpenAI-compatible APIs), supports **custom hooks** to intercept and control tool execution, and offers both an interactive CLI and a **Python SDK** for headless automation.
4
23
 
5
24
  [中文文档](README_CN.md) | [Contributing](CONTRIBUTING.md) | [Documentation](docs/)
6
25
 
@@ -23,6 +42,8 @@ Ripperdoc is an AI-powered terminal assistant for coding tasks, providing an int
23
42
  - **MCP Server Support** - Integration with Model Context Protocol servers
24
43
  - **Session Management** - Persistent session history and usage tracking
25
44
  - **Jupyter Notebook Support** - Edit .ipynb files directly
45
+ - **Hooks System** - Execute custom scripts at lifecycle events with decision control
46
+ - **Custom Commands** - Define reusable slash commands with parameter substitution
26
47
 
27
48
  ## Installation
28
49
 
@@ -1,3 +1,3 @@
1
1
  """Ripperdoc - AI-powered coding agent."""
2
2
 
3
- __version__ = "0.2.6"
3
+ __version__ = "0.2.8"
@@ -22,6 +22,7 @@ from ripperdoc.core.default_tools import get_default_tools
22
22
  from ripperdoc.core.query import query, QueryContext
23
23
  from ripperdoc.core.system_prompt import build_system_prompt
24
24
  from ripperdoc.core.skills import build_skill_summary, load_all_skills
25
+ from ripperdoc.core.hooks.manager import hook_manager
25
26
  from ripperdoc.utils.messages import create_user_message
26
27
  from ripperdoc.utils.memory import build_memory_instructions
27
28
  from ripperdoc.core.permissions import make_permission_checker
@@ -70,6 +71,10 @@ async def run_query(
70
71
  project_path = Path.cwd()
71
72
  can_use_tool = make_permission_checker(project_path, safe_mode) if safe_mode else None
72
73
 
74
+ # Initialize hook manager
75
+ hook_manager.set_project_dir(project_path)
76
+ hook_manager.set_session_id(session_id)
77
+
73
78
  # Create initial user message
74
79
  from ripperdoc.utils.messages import UserMessage, AssistantMessage, ProgressMessage
75
80
 
@@ -0,0 +1,147 @@
1
+ """Slash command registry with custom command support."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Dict, List, Optional, Tuple, Union
7
+
8
+ from .base import SlashCommand
9
+ from .agents_cmd import command as agents_command
10
+ from .clear_cmd import command as clear_command
11
+ from .compact_cmd import command as compact_command
12
+ from .config_cmd import command as config_command
13
+ from .cost_cmd import command as cost_command
14
+ from .context_cmd import command as context_command
15
+ from .doctor_cmd import command as doctor_command
16
+ from .exit_cmd import command as exit_command
17
+ from .help_cmd import command as help_command
18
+ from .hooks_cmd import command as hooks_command
19
+ from .memory_cmd import command as memory_command
20
+ from .mcp_cmd import command as mcp_command
21
+ from .models_cmd import command as models_command
22
+ from .permissions_cmd import command as permissions_command
23
+ from .resume_cmd import command as resume_command
24
+ from .tasks_cmd import command as tasks_command
25
+ from .status_cmd import command as status_command
26
+ from .todos_cmd import command as todos_command
27
+ from .tools_cmd import command as tools_command
28
+
29
+ from ripperdoc.core.custom_commands import (
30
+ CustomCommandDefinition,
31
+ load_all_custom_commands,
32
+ find_custom_command,
33
+ expand_command_content,
34
+ )
35
+
36
+
37
+ def _build_registry(commands: List[SlashCommand]) -> Dict[str, SlashCommand]:
38
+ """Map command names and aliases to SlashCommand entries."""
39
+ registry: Dict[str, SlashCommand] = {}
40
+ for cmd in commands:
41
+ registry[cmd.name] = cmd
42
+ for alias in cmd.aliases:
43
+ registry[alias] = cmd
44
+ return registry
45
+
46
+
47
+ ALL_COMMANDS: List[SlashCommand] = [
48
+ help_command,
49
+ clear_command,
50
+ config_command,
51
+ tools_command,
52
+ models_command,
53
+ exit_command,
54
+ status_command,
55
+ doctor_command,
56
+ memory_command,
57
+ permissions_command,
58
+ tasks_command,
59
+ todos_command,
60
+ mcp_command,
61
+ hooks_command,
62
+ cost_command,
63
+ context_command,
64
+ compact_command,
65
+ resume_command,
66
+ agents_command,
67
+ ]
68
+
69
+ COMMAND_REGISTRY: Dict[str, SlashCommand] = _build_registry(ALL_COMMANDS)
70
+
71
+ # Cache for custom commands
72
+ _custom_commands_cache: Optional[Tuple[Path, List[CustomCommandDefinition]]] = None
73
+
74
+
75
+ def _get_custom_commands(project_path: Optional[Path] = None) -> List[CustomCommandDefinition]:
76
+ """Get custom commands with caching."""
77
+ global _custom_commands_cache
78
+ current_path = (project_path or Path.cwd()).resolve()
79
+
80
+ # Return cached commands if same project
81
+ if _custom_commands_cache and _custom_commands_cache[0] == current_path:
82
+ return _custom_commands_cache[1]
83
+
84
+ # Load and cache
85
+ result = load_all_custom_commands(project_path=current_path)
86
+ _custom_commands_cache = (current_path, result.commands)
87
+ return result.commands
88
+
89
+
90
+ def refresh_custom_commands(project_path: Optional[Path] = None) -> List[CustomCommandDefinition]:
91
+ """Force reload custom commands."""
92
+ global _custom_commands_cache
93
+ _custom_commands_cache = None
94
+ return _get_custom_commands(project_path)
95
+
96
+
97
+ def list_slash_commands() -> List[SlashCommand]:
98
+ """Return the ordered list of base slash commands (no aliases)."""
99
+ return ALL_COMMANDS
100
+
101
+
102
+ def list_custom_commands(project_path: Optional[Path] = None) -> List[CustomCommandDefinition]:
103
+ """Return all loaded custom commands."""
104
+ return _get_custom_commands(project_path)
105
+
106
+
107
+ def get_slash_command(name: str) -> SlashCommand | None:
108
+ """Return a built-in command by name or alias."""
109
+ return COMMAND_REGISTRY.get(name)
110
+
111
+
112
+ def get_custom_command(
113
+ name: str, project_path: Optional[Path] = None
114
+ ) -> CustomCommandDefinition | None:
115
+ """Return a custom command by name."""
116
+ commands = _get_custom_commands(project_path)
117
+ return next((cmd for cmd in commands if cmd.name == name), None)
118
+
119
+
120
+ def slash_command_completions(
121
+ project_path: Optional[Path] = None,
122
+ ) -> List[Tuple[str, Union[SlashCommand, CustomCommandDefinition]]]:
123
+ """Return (name, command) pairs for completion including aliases and custom commands."""
124
+ completions: List[Tuple[str, Union[SlashCommand, CustomCommandDefinition]]] = []
125
+
126
+ # Add built-in commands
127
+ completions.extend(list(COMMAND_REGISTRY.items()))
128
+
129
+ # Add custom commands
130
+ custom_cmds = _get_custom_commands(project_path)
131
+ for cmd in custom_cmds:
132
+ completions.append((cmd.name, cmd))
133
+
134
+ return completions
135
+
136
+
137
+ __all__ = [
138
+ "SlashCommand",
139
+ "CustomCommandDefinition",
140
+ "list_slash_commands",
141
+ "list_custom_commands",
142
+ "get_slash_command",
143
+ "get_custom_command",
144
+ "slash_command_completions",
145
+ "refresh_custom_commands",
146
+ "expand_command_content",
147
+ ]
@@ -12,6 +12,7 @@ command = SlashCommand(
12
12
  name="clear",
13
13
  description="Clear conversation history",
14
14
  handler=_handle,
15
+ aliases=("new",)
15
16
  )
16
17
 
17
18
 
@@ -12,7 +12,7 @@ command = SlashCommand(
12
12
  name="exit",
13
13
  description="Exit Ripperdoc",
14
14
  handler=_handle,
15
- aliases=(),
15
+ aliases=("quit",),
16
16
  )
17
17
 
18
18
 
@@ -0,0 +1,30 @@
1
+ from typing import Any
2
+ from .base import SlashCommand
3
+
4
+
5
+ def _handle(ui: Any, _: str) -> bool:
6
+ ui.console.print("\n[bold]Available Slash Commands:[/bold]")
7
+ for cmd in ui.command_list:
8
+ alias_text = f" (aliases: {', '.join(cmd.aliases)})" if cmd.aliases else ""
9
+ ui.console.print(f" /{cmd.name:<12} - {cmd.description}{alias_text}")
10
+
11
+ # Show custom commands if any
12
+ custom_cmds = getattr(ui, "_custom_command_list", [])
13
+ if custom_cmds:
14
+ ui.console.print("\n[bold]Custom Commands:[/bold]")
15
+ for cmd in sorted(custom_cmds, key=lambda c: c.name):
16
+ hint = f" {cmd.argument_hint}" if cmd.argument_hint else ""
17
+ location = f" ({cmd.location.value})" if cmd.location else ""
18
+ ui.console.print(f" /{cmd.name:<12}{hint} - {cmd.description}{location}")
19
+
20
+ return True
21
+
22
+
23
+ command = SlashCommand(
24
+ name="help",
25
+ description="Show available slash commands",
26
+ handler=_handle,
27
+ )
28
+
29
+
30
+ __all__ = ["command"]