ripperdoc 0.2.6__py3-none-any.whl → 0.2.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ripperdoc/__init__.py +1 -1
- ripperdoc/cli/cli.py +5 -0
- ripperdoc/cli/commands/__init__.py +71 -6
- ripperdoc/cli/commands/clear_cmd.py +1 -0
- ripperdoc/cli/commands/exit_cmd.py +1 -1
- ripperdoc/cli/commands/help_cmd.py +11 -1
- ripperdoc/cli/commands/hooks_cmd.py +636 -0
- ripperdoc/cli/commands/permissions_cmd.py +36 -34
- ripperdoc/cli/commands/resume_cmd.py +71 -37
- ripperdoc/cli/ui/file_mention_completer.py +276 -0
- ripperdoc/cli/ui/helpers.py +100 -3
- ripperdoc/cli/ui/interrupt_handler.py +175 -0
- ripperdoc/cli/ui/message_display.py +249 -0
- ripperdoc/cli/ui/panels.py +63 -0
- ripperdoc/cli/ui/rich_ui.py +233 -648
- ripperdoc/cli/ui/tool_renderers.py +2 -2
- ripperdoc/core/agents.py +4 -4
- ripperdoc/core/custom_commands.py +411 -0
- ripperdoc/core/hooks/__init__.py +99 -0
- ripperdoc/core/hooks/config.py +303 -0
- ripperdoc/core/hooks/events.py +540 -0
- ripperdoc/core/hooks/executor.py +498 -0
- ripperdoc/core/hooks/integration.py +353 -0
- ripperdoc/core/hooks/manager.py +720 -0
- ripperdoc/core/providers/anthropic.py +476 -69
- ripperdoc/core/query.py +61 -4
- ripperdoc/core/query_utils.py +1 -1
- ripperdoc/core/tool.py +1 -1
- ripperdoc/tools/bash_tool.py +5 -5
- ripperdoc/tools/file_edit_tool.py +2 -2
- ripperdoc/tools/file_read_tool.py +2 -2
- ripperdoc/tools/multi_edit_tool.py +1 -1
- ripperdoc/utils/conversation_compaction.py +476 -0
- ripperdoc/utils/message_compaction.py +109 -154
- ripperdoc/utils/message_formatting.py +216 -0
- ripperdoc/utils/messages.py +31 -9
- ripperdoc/utils/path_ignore.py +3 -4
- ripperdoc/utils/session_history.py +19 -7
- {ripperdoc-0.2.6.dist-info → ripperdoc-0.2.8.dist-info}/METADATA +24 -3
- {ripperdoc-0.2.6.dist-info → ripperdoc-0.2.8.dist-info}/RECORD +44 -30
- {ripperdoc-0.2.6.dist-info → ripperdoc-0.2.8.dist-info}/WHEEL +0 -0
- {ripperdoc-0.2.6.dist-info → ripperdoc-0.2.8.dist-info}/entry_points.txt +0 -0
- {ripperdoc-0.2.6.dist-info → ripperdoc-0.2.8.dist-info}/licenses/LICENSE +0 -0
- {ripperdoc-0.2.6.dist-info → ripperdoc-0.2.8.dist-info}/top_level.txt +0 -0
ripperdoc/__init__.py
CHANGED
ripperdoc/cli/cli.py
CHANGED
|
@@ -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
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
"""Slash command registry."""
|
|
1
|
+
"""Slash command registry with custom command support."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Dict, List, Optional, Tuple, Union
|
|
6
7
|
|
|
7
8
|
from .base import SlashCommand
|
|
8
9
|
from .agents_cmd import command as agents_command
|
|
@@ -14,6 +15,7 @@ from .context_cmd import command as context_command
|
|
|
14
15
|
from .doctor_cmd import command as doctor_command
|
|
15
16
|
from .exit_cmd import command as exit_command
|
|
16
17
|
from .help_cmd import command as help_command
|
|
18
|
+
from .hooks_cmd import command as hooks_command
|
|
17
19
|
from .memory_cmd import command as memory_command
|
|
18
20
|
from .mcp_cmd import command as mcp_command
|
|
19
21
|
from .models_cmd import command as models_command
|
|
@@ -24,6 +26,13 @@ from .status_cmd import command as status_command
|
|
|
24
26
|
from .todos_cmd import command as todos_command
|
|
25
27
|
from .tools_cmd import command as tools_command
|
|
26
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
|
+
|
|
27
36
|
|
|
28
37
|
def _build_registry(commands: List[SlashCommand]) -> Dict[str, SlashCommand]:
|
|
29
38
|
"""Map command names and aliases to SlashCommand entries."""
|
|
@@ -49,6 +58,7 @@ ALL_COMMANDS: List[SlashCommand] = [
|
|
|
49
58
|
tasks_command,
|
|
50
59
|
todos_command,
|
|
51
60
|
mcp_command,
|
|
61
|
+
hooks_command,
|
|
52
62
|
cost_command,
|
|
53
63
|
context_command,
|
|
54
64
|
compact_command,
|
|
@@ -58,25 +68,80 @@ ALL_COMMANDS: List[SlashCommand] = [
|
|
|
58
68
|
|
|
59
69
|
COMMAND_REGISTRY: Dict[str, SlashCommand] = _build_registry(ALL_COMMANDS)
|
|
60
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
|
+
|
|
61
96
|
|
|
62
97
|
def list_slash_commands() -> List[SlashCommand]:
|
|
63
98
|
"""Return the ordered list of base slash commands (no aliases)."""
|
|
64
99
|
return ALL_COMMANDS
|
|
65
100
|
|
|
66
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
|
+
|
|
67
107
|
def get_slash_command(name: str) -> SlashCommand | None:
|
|
68
|
-
"""Return a command by name or alias."""
|
|
108
|
+
"""Return a built-in command by name or alias."""
|
|
69
109
|
return COMMAND_REGISTRY.get(name)
|
|
70
110
|
|
|
71
111
|
|
|
72
|
-
def
|
|
73
|
-
|
|
74
|
-
|
|
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
|
|
75
135
|
|
|
76
136
|
|
|
77
137
|
__all__ = [
|
|
78
138
|
"SlashCommand",
|
|
139
|
+
"CustomCommandDefinition",
|
|
79
140
|
"list_slash_commands",
|
|
141
|
+
"list_custom_commands",
|
|
80
142
|
"get_slash_command",
|
|
143
|
+
"get_custom_command",
|
|
81
144
|
"slash_command_completions",
|
|
145
|
+
"refresh_custom_commands",
|
|
146
|
+
"expand_command_content",
|
|
82
147
|
]
|
|
@@ -6,7 +6,17 @@ def _handle(ui: Any, _: str) -> bool:
|
|
|
6
6
|
ui.console.print("\n[bold]Available Slash Commands:[/bold]")
|
|
7
7
|
for cmd in ui.command_list:
|
|
8
8
|
alias_text = f" (aliases: {', '.join(cmd.aliases)})" if cmd.aliases else ""
|
|
9
|
-
ui.console.print(f" /{cmd.name:<
|
|
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
|
+
|
|
10
20
|
return True
|
|
11
21
|
|
|
12
22
|
|