ripperdoc 0.2.7__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.
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/PKG-INFO +24 -3
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/README.md +23 -2
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/__init__.py +1 -1
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/cli.py +5 -0
- ripperdoc-0.2.8/ripperdoc/cli/commands/__init__.py +147 -0
- ripperdoc-0.2.8/ripperdoc/cli/commands/help_cmd.py +30 -0
- ripperdoc-0.2.8/ripperdoc/cli/commands/hooks_cmd.py +636 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/permissions_cmd.py +36 -34
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/resume_cmd.py +1 -1
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/file_mention_completer.py +62 -7
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/interrupt_handler.py +1 -1
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/message_display.py +1 -1
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/panels.py +13 -10
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/rich_ui.py +92 -24
- ripperdoc-0.2.8/ripperdoc/core/custom_commands.py +411 -0
- ripperdoc-0.2.8/ripperdoc/core/hooks/__init__.py +99 -0
- ripperdoc-0.2.8/ripperdoc/core/hooks/config.py +303 -0
- ripperdoc-0.2.8/ripperdoc/core/hooks/events.py +540 -0
- ripperdoc-0.2.8/ripperdoc/core/hooks/executor.py +498 -0
- ripperdoc-0.2.8/ripperdoc/core/hooks/integration.py +353 -0
- ripperdoc-0.2.8/ripperdoc/core/hooks/manager.py +720 -0
- ripperdoc-0.2.8/ripperdoc/core/providers/anthropic.py +657 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/query.py +61 -4
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/bash_tool.py +4 -4
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/file_read_tool.py +1 -1
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/conversation_compaction.py +3 -3
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/path_ignore.py +3 -4
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc.egg-info/PKG-INFO +24 -3
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc.egg-info/SOURCES.txt +11 -0
- ripperdoc-0.2.8/tests/test_custom_commands.py +264 -0
- ripperdoc-0.2.8/tests/test_file_mention_completer.py +78 -0
- ripperdoc-0.2.8/tests/test_hooks_cmd.py +139 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_path_ignore.py +0 -1
- ripperdoc-0.2.7/ripperdoc/cli/commands/__init__.py +0 -82
- ripperdoc-0.2.7/ripperdoc/cli/commands/help_cmd.py +0 -20
- ripperdoc-0.2.7/ripperdoc/core/providers/anthropic.py +0 -250
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/LICENSE +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/pyproject.toml +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/__main__.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/__init__.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/agents_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/base.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/clear_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/compact_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/config_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/context_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/cost_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/doctor_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/exit_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/mcp_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/memory_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/models_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/status_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/tasks_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/todos_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/commands/tools_cmd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/__init__.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/context_display.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/helpers.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/spinner.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/thinking_spinner.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/cli/ui/tool_renderers.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/__init__.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/agents.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/commands.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/config.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/default_tools.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/permissions.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/providers/__init__.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/providers/base.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/providers/gemini.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/providers/openai.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/query_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/skills.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/system_prompt.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/core/tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/sdk/__init__.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/sdk/client.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/__init__.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/ask_user_question_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/background_shell.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/bash_output_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/dynamic_mcp_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/enter_plan_mode_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/exit_plan_mode_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/file_edit_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/file_write_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/glob_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/grep_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/kill_bash_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/ls_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/mcp_tools.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/multi_edit_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/notebook_edit_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/skill_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/task_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/todo_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/tools/tool_search_tool.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/__init__.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/bash_constants.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/bash_output_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/coerce.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/context_length_errors.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/exit_code_handlers.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/file_watch.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/git_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/json_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/log.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/mcp.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/memory.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/message_compaction.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/message_formatting.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/messages.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/output_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/path_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/permissions/__init__.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/permissions/path_validation_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/permissions/shell_command_validation.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/permissions/tool_permission_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/prompt.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/safe_get_cwd.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/sandbox_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/session_history.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/session_usage.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/shell_token_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/shell_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/todo.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc/utils/token_estimation.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc.egg-info/dependency_links.txt +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc.egg-info/entry_points.txt +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc.egg-info/requires.txt +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/ripperdoc.egg-info/top_level.txt +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/setup.cfg +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/setup.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_background_shell_shutdown.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_cli_commands.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_compact.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_config.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_context_length_errors.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_context_limits.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_mcp_config.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_messages.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_output_utils.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_permissions.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_query_abort.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_sdk.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_shell_permissions.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_skills.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_todo.py +0 -0
- {ripperdoc-0.2.7 → ripperdoc-0.2.8}/tests/test_tool_search.py +0 -0
- {ripperdoc-0.2.7 → 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.
|
|
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
|
-
|
|
38
|
+
<div align="center">
|
|
39
39
|
|
|
40
|
-
Ripperdoc
|
|
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
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
Ripperdoc
|
|
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
|
|
|
@@ -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
|
+
]
|
|
@@ -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"]
|