ripperdoc 0.2.7__py3-none-any.whl → 0.2.9__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 +33 -115
- ripperdoc/cli/commands/__init__.py +70 -6
- ripperdoc/cli/commands/agents_cmd.py +6 -3
- ripperdoc/cli/commands/clear_cmd.py +1 -4
- ripperdoc/cli/commands/config_cmd.py +1 -1
- ripperdoc/cli/commands/context_cmd.py +3 -2
- ripperdoc/cli/commands/doctor_cmd.py +18 -4
- ripperdoc/cli/commands/help_cmd.py +11 -1
- ripperdoc/cli/commands/hooks_cmd.py +610 -0
- ripperdoc/cli/commands/models_cmd.py +26 -9
- ripperdoc/cli/commands/permissions_cmd.py +57 -37
- ripperdoc/cli/commands/resume_cmd.py +6 -4
- ripperdoc/cli/commands/status_cmd.py +4 -4
- ripperdoc/cli/commands/tasks_cmd.py +8 -4
- ripperdoc/cli/ui/file_mention_completer.py +64 -8
- ripperdoc/cli/ui/interrupt_handler.py +3 -4
- ripperdoc/cli/ui/message_display.py +5 -3
- ripperdoc/cli/ui/panels.py +13 -10
- ripperdoc/cli/ui/provider_options.py +247 -0
- ripperdoc/cli/ui/rich_ui.py +196 -77
- ripperdoc/cli/ui/spinner.py +25 -1
- ripperdoc/cli/ui/tool_renderers.py +8 -2
- ripperdoc/cli/ui/wizard.py +215 -0
- ripperdoc/core/agents.py +9 -3
- ripperdoc/core/config.py +49 -12
- ripperdoc/core/custom_commands.py +412 -0
- ripperdoc/core/default_tools.py +11 -2
- ripperdoc/core/hooks/__init__.py +99 -0
- ripperdoc/core/hooks/config.py +301 -0
- ripperdoc/core/hooks/events.py +535 -0
- ripperdoc/core/hooks/executor.py +496 -0
- ripperdoc/core/hooks/integration.py +344 -0
- ripperdoc/core/hooks/manager.py +745 -0
- ripperdoc/core/permissions.py +40 -8
- ripperdoc/core/providers/anthropic.py +548 -68
- ripperdoc/core/providers/gemini.py +70 -5
- ripperdoc/core/providers/openai.py +60 -5
- ripperdoc/core/query.py +140 -39
- ripperdoc/core/query_utils.py +2 -0
- ripperdoc/core/skills.py +9 -3
- ripperdoc/core/system_prompt.py +4 -2
- ripperdoc/core/tool.py +9 -5
- ripperdoc/sdk/client.py +2 -2
- ripperdoc/tools/ask_user_question_tool.py +5 -3
- ripperdoc/tools/background_shell.py +2 -1
- ripperdoc/tools/bash_output_tool.py +1 -1
- ripperdoc/tools/bash_tool.py +30 -20
- ripperdoc/tools/dynamic_mcp_tool.py +29 -8
- ripperdoc/tools/enter_plan_mode_tool.py +1 -1
- ripperdoc/tools/exit_plan_mode_tool.py +1 -1
- ripperdoc/tools/file_edit_tool.py +8 -4
- ripperdoc/tools/file_read_tool.py +9 -5
- ripperdoc/tools/file_write_tool.py +9 -5
- ripperdoc/tools/glob_tool.py +3 -2
- ripperdoc/tools/grep_tool.py +3 -2
- ripperdoc/tools/kill_bash_tool.py +1 -1
- ripperdoc/tools/ls_tool.py +1 -1
- ripperdoc/tools/mcp_tools.py +13 -10
- ripperdoc/tools/multi_edit_tool.py +8 -7
- ripperdoc/tools/notebook_edit_tool.py +7 -4
- ripperdoc/tools/skill_tool.py +1 -1
- ripperdoc/tools/task_tool.py +5 -4
- ripperdoc/tools/todo_tool.py +2 -2
- ripperdoc/tools/tool_search_tool.py +3 -2
- ripperdoc/utils/conversation_compaction.py +11 -7
- ripperdoc/utils/file_watch.py +8 -2
- ripperdoc/utils/json_utils.py +2 -1
- ripperdoc/utils/mcp.py +11 -3
- ripperdoc/utils/memory.py +4 -2
- ripperdoc/utils/message_compaction.py +21 -7
- ripperdoc/utils/message_formatting.py +11 -7
- ripperdoc/utils/messages.py +105 -66
- ripperdoc/utils/path_ignore.py +38 -12
- ripperdoc/utils/permissions/path_validation_utils.py +2 -1
- ripperdoc/utils/permissions/shell_command_validation.py +427 -91
- ripperdoc/utils/safe_get_cwd.py +2 -1
- ripperdoc/utils/session_history.py +13 -6
- ripperdoc/utils/todo.py +2 -1
- ripperdoc/utils/token_estimation.py +6 -1
- {ripperdoc-0.2.7.dist-info → ripperdoc-0.2.9.dist-info}/METADATA +24 -3
- ripperdoc-0.2.9.dist-info/RECORD +123 -0
- ripperdoc-0.2.7.dist-info/RECORD +0 -113
- {ripperdoc-0.2.7.dist-info → ripperdoc-0.2.9.dist-info}/WHEEL +0 -0
- {ripperdoc-0.2.7.dist-info → ripperdoc-0.2.9.dist-info}/entry_points.txt +0 -0
- {ripperdoc-0.2.7.dist-info → ripperdoc-0.2.9.dist-info}/licenses/LICENSE +0 -0
- {ripperdoc-0.2.7.dist-info → ripperdoc-0.2.9.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Provider metadata used by interactive UI flows.
|
|
3
|
+
|
|
4
|
+
Each provider option represents exactly one protocol endpoint. Vendors that
|
|
5
|
+
offer multiple protocols (for example, DeepSeek exposing both OpenAI-style and
|
|
6
|
+
Anthropic-style APIs on different URLs) should be modeled as distinct provider
|
|
7
|
+
options so that protocol-specific defaults stay unambiguous.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import Dict, List, Optional, Sequence, Tuple
|
|
12
|
+
|
|
13
|
+
from ripperdoc.core.config import ProviderType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class ProviderOption:
|
|
18
|
+
"""A single provider choice with protocol and UX defaults."""
|
|
19
|
+
|
|
20
|
+
key: str
|
|
21
|
+
protocol: ProviderType
|
|
22
|
+
default_model: str
|
|
23
|
+
model_suggestions: Tuple[str, ...] = ()
|
|
24
|
+
default_api_base: Optional[str] = None
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def label(self) -> str:
|
|
28
|
+
"""Display label shown to the user."""
|
|
29
|
+
return self.key
|
|
30
|
+
|
|
31
|
+
def with_api_base(self, api_base: Optional[str]) -> "ProviderOption":
|
|
32
|
+
"""Return a copy that overrides the default API base."""
|
|
33
|
+
return ProviderOption(
|
|
34
|
+
key=self.key,
|
|
35
|
+
protocol=self.protocol,
|
|
36
|
+
default_model=self.default_model,
|
|
37
|
+
model_suggestions=self.model_suggestions,
|
|
38
|
+
default_api_base=api_base if api_base else self.default_api_base,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ProviderRegistry:
|
|
43
|
+
"""Registry for known providers to keep wizard logic declarative."""
|
|
44
|
+
|
|
45
|
+
def __init__(self, providers: Sequence[ProviderOption], default_key: str) -> None:
|
|
46
|
+
if not providers:
|
|
47
|
+
raise ValueError("Provider registry cannot be empty")
|
|
48
|
+
self._providers: List[ProviderOption] = list(providers)
|
|
49
|
+
self._index: Dict[str, ProviderOption] = {p.key: p for p in providers}
|
|
50
|
+
if default_key not in self._index:
|
|
51
|
+
raise ValueError(f"Default provider '{default_key}' not found in registry")
|
|
52
|
+
self._default_key = default_key
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def providers(self) -> List[ProviderOption]:
|
|
56
|
+
"""Return providers in display order."""
|
|
57
|
+
return list(self._providers)
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def default_choice(self) -> ProviderOption:
|
|
61
|
+
"""Return the default provider selection."""
|
|
62
|
+
return self._index[self._default_key]
|
|
63
|
+
|
|
64
|
+
def get(self, key: str) -> Optional[ProviderOption]:
|
|
65
|
+
"""Look up a provider option by key."""
|
|
66
|
+
return self._index.get(key)
|
|
67
|
+
|
|
68
|
+
def keys(self) -> List[str]:
|
|
69
|
+
"""Return provider keys in display order."""
|
|
70
|
+
return [p.key for p in self._providers]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def default_model_for_protocol(protocol: ProviderType) -> str:
|
|
74
|
+
"""Reasonable default model per protocol family."""
|
|
75
|
+
if protocol == ProviderType.ANTHROPIC:
|
|
76
|
+
return "claude-3-5-sonnet-20241022"
|
|
77
|
+
if protocol == ProviderType.GEMINI:
|
|
78
|
+
return "gemini-1.5-pro"
|
|
79
|
+
return "gpt-4o-mini"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
KNOWN_PROVIDERS = ProviderRegistry(
|
|
83
|
+
providers=[
|
|
84
|
+
ProviderOption(
|
|
85
|
+
key="deepseek",
|
|
86
|
+
protocol=ProviderType.OPENAI_COMPATIBLE,
|
|
87
|
+
default_model="deepseek-chat",
|
|
88
|
+
model_suggestions=("deepseek-chat", "deepseek-reasoner"),
|
|
89
|
+
default_api_base="https://api.deepseek.com/v1",
|
|
90
|
+
),
|
|
91
|
+
ProviderOption(
|
|
92
|
+
key="openai",
|
|
93
|
+
protocol=ProviderType.OPENAI_COMPATIBLE,
|
|
94
|
+
default_model="gpt-4o-mini",
|
|
95
|
+
model_suggestions=(
|
|
96
|
+
"gpt-5.1",
|
|
97
|
+
"gpt-5.1-chat",
|
|
98
|
+
"gpt-5.1-codex",
|
|
99
|
+
"gpt-4o",
|
|
100
|
+
"gpt-4-turbo",
|
|
101
|
+
"o1-preview",
|
|
102
|
+
"o1-mini",
|
|
103
|
+
),
|
|
104
|
+
default_api_base="https://api.openai.com/v1",
|
|
105
|
+
),
|
|
106
|
+
ProviderOption(
|
|
107
|
+
key="openrouter",
|
|
108
|
+
protocol=ProviderType.OPENAI_COMPATIBLE,
|
|
109
|
+
default_model="openai/gpt-4o-mini",
|
|
110
|
+
model_suggestions=(
|
|
111
|
+
"openai/gpt-4o-mini",
|
|
112
|
+
"meta-llama/llama-3.1-8b-instruct",
|
|
113
|
+
"google/gemini-flash-1.5",
|
|
114
|
+
),
|
|
115
|
+
default_api_base="https://openrouter.ai/api/v1",
|
|
116
|
+
),
|
|
117
|
+
ProviderOption(
|
|
118
|
+
key="anthropic",
|
|
119
|
+
protocol=ProviderType.ANTHROPIC,
|
|
120
|
+
default_model="claude-3-5-sonnet-20241022",
|
|
121
|
+
model_suggestions=(
|
|
122
|
+
"claude-3-5-sonnet-20241022",
|
|
123
|
+
"claude-3-5-haiku-20241022",
|
|
124
|
+
"claude-3-opus-20240229",
|
|
125
|
+
"claude-3-sonnet-20240229",
|
|
126
|
+
"claude-3-haiku-20240307",
|
|
127
|
+
),
|
|
128
|
+
default_api_base=None,
|
|
129
|
+
),
|
|
130
|
+
ProviderOption(
|
|
131
|
+
key="openai_compatible",
|
|
132
|
+
protocol=ProviderType.OPENAI_COMPATIBLE,
|
|
133
|
+
default_model="gpt-4o-mini",
|
|
134
|
+
model_suggestions=(
|
|
135
|
+
"gpt-4o-mini",
|
|
136
|
+
"gpt-4o",
|
|
137
|
+
"gpt-3.5-turbo",
|
|
138
|
+
),
|
|
139
|
+
default_api_base=None,
|
|
140
|
+
),
|
|
141
|
+
ProviderOption(
|
|
142
|
+
key="mistralai",
|
|
143
|
+
protocol=ProviderType.OPENAI_COMPATIBLE,
|
|
144
|
+
default_model="mistral-small-creative",
|
|
145
|
+
model_suggestions=(
|
|
146
|
+
"mistral-small-creative",
|
|
147
|
+
"mistral-large-latest",
|
|
148
|
+
"mistral-small-latest",
|
|
149
|
+
"devstral-2512",
|
|
150
|
+
"ministral-14b-2512",
|
|
151
|
+
"ministral-8b-2512",
|
|
152
|
+
"codestral-latest",
|
|
153
|
+
"pixtral-large-latest",
|
|
154
|
+
),
|
|
155
|
+
default_api_base="https://api.mistral.ai/v1",
|
|
156
|
+
),
|
|
157
|
+
ProviderOption(
|
|
158
|
+
key="google",
|
|
159
|
+
protocol=ProviderType.GEMINI,
|
|
160
|
+
default_model="gemini-1.5-pro",
|
|
161
|
+
model_suggestions=(
|
|
162
|
+
"gemini-2.5-pro",
|
|
163
|
+
"gemini-2.5-flash-lite",
|
|
164
|
+
"gemini-2.5-flash",
|
|
165
|
+
"gemini-3-pro-preview",
|
|
166
|
+
"gemini-3-flash-preview",
|
|
167
|
+
),
|
|
168
|
+
default_api_base="https://generativelanguage.googleapis.com/v1beta",
|
|
169
|
+
),
|
|
170
|
+
ProviderOption(
|
|
171
|
+
key="moonshot",
|
|
172
|
+
protocol=ProviderType.OPENAI_COMPATIBLE,
|
|
173
|
+
default_model="kimi-k2-turbo-preview",
|
|
174
|
+
model_suggestions=(
|
|
175
|
+
"kimi-k2-0905-preview",
|
|
176
|
+
"kimi-k2-0711-preview",
|
|
177
|
+
"kimi-k2-turbo-preview",
|
|
178
|
+
"kimi-k2-thinking",
|
|
179
|
+
"kimi-k2-thinking-turbo",
|
|
180
|
+
),
|
|
181
|
+
default_api_base="https://api.moonshot.cn/v1",
|
|
182
|
+
),
|
|
183
|
+
ProviderOption(
|
|
184
|
+
key="qwen",
|
|
185
|
+
protocol=ProviderType.OPENAI_COMPATIBLE,
|
|
186
|
+
default_model="qwen-turbo",
|
|
187
|
+
model_suggestions=(
|
|
188
|
+
"qwen-turbo",
|
|
189
|
+
"qwen-plus",
|
|
190
|
+
"qwen-max",
|
|
191
|
+
"qwen2.5-32b",
|
|
192
|
+
"qwen2.5-coder-32b",
|
|
193
|
+
),
|
|
194
|
+
default_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
195
|
+
),
|
|
196
|
+
ProviderOption(
|
|
197
|
+
key="zhipu",
|
|
198
|
+
protocol=ProviderType.OPENAI_COMPATIBLE,
|
|
199
|
+
default_model="glm-4-flash",
|
|
200
|
+
model_suggestions=(
|
|
201
|
+
"glm-4-plus",
|
|
202
|
+
"glm-4-air-250414",
|
|
203
|
+
"glm-4-airx",
|
|
204
|
+
"glm-4-long",
|
|
205
|
+
"glm-4-flashx",
|
|
206
|
+
"glm-4-flash-250414",
|
|
207
|
+
"glm-4.6",
|
|
208
|
+
"glm-4.5",
|
|
209
|
+
"glm-4.5-air",
|
|
210
|
+
"glm-4.5-airx",
|
|
211
|
+
"glm-4.5-x",
|
|
212
|
+
"glm-4.5-flash",
|
|
213
|
+
),
|
|
214
|
+
default_api_base="https://open.bigmodel.cn/api/paas/v4",
|
|
215
|
+
),
|
|
216
|
+
ProviderOption(
|
|
217
|
+
key="minimax",
|
|
218
|
+
protocol=ProviderType.OPENAI_COMPATIBLE,
|
|
219
|
+
default_model="MiniMax-M2",
|
|
220
|
+
model_suggestions=("MiniMax-M2",),
|
|
221
|
+
default_api_base="https://api.minimax.chat/v1",
|
|
222
|
+
),
|
|
223
|
+
ProviderOption(
|
|
224
|
+
key="siliconflow",
|
|
225
|
+
protocol=ProviderType.OPENAI_COMPATIBLE,
|
|
226
|
+
default_model="deepseek-ai/DeepSeek-V3.2",
|
|
227
|
+
model_suggestions=(
|
|
228
|
+
"deepseek-ai/DeepSeek-V3.2",
|
|
229
|
+
"Qwen/Qwen2.5-32B-Instruct",
|
|
230
|
+
"Qwen/Qwen3-Coder-480B-A35B-Instruct",
|
|
231
|
+
"zai-org/GLM-4.6",
|
|
232
|
+
"moonshotai/Kimi-K2-Thinking",
|
|
233
|
+
"MiniMaxAI/MiniMax-M2",
|
|
234
|
+
),
|
|
235
|
+
default_api_base="https://api.siliconflow.cn/v1",
|
|
236
|
+
),
|
|
237
|
+
],
|
|
238
|
+
default_key="deepseek",
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
__all__ = [
|
|
243
|
+
"KNOWN_PROVIDERS",
|
|
244
|
+
"ProviderOption",
|
|
245
|
+
"ProviderRegistry",
|
|
246
|
+
"default_model_for_protocol",
|
|
247
|
+
]
|