ripperdoc 0.2.9__py3-none-any.whl → 0.3.0__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 +379 -51
- ripperdoc/cli/commands/__init__.py +6 -0
- ripperdoc/cli/commands/agents_cmd.py +128 -5
- ripperdoc/cli/commands/clear_cmd.py +8 -0
- ripperdoc/cli/commands/doctor_cmd.py +29 -0
- ripperdoc/cli/commands/exit_cmd.py +1 -0
- ripperdoc/cli/commands/memory_cmd.py +2 -1
- ripperdoc/cli/commands/models_cmd.py +63 -7
- ripperdoc/cli/commands/resume_cmd.py +5 -0
- ripperdoc/cli/commands/skills_cmd.py +103 -0
- ripperdoc/cli/commands/stats_cmd.py +244 -0
- ripperdoc/cli/commands/status_cmd.py +10 -0
- ripperdoc/cli/commands/tasks_cmd.py +6 -3
- ripperdoc/cli/commands/themes_cmd.py +139 -0
- ripperdoc/cli/ui/file_mention_completer.py +63 -13
- ripperdoc/cli/ui/helpers.py +6 -3
- ripperdoc/cli/ui/interrupt_handler.py +34 -0
- ripperdoc/cli/ui/panels.py +14 -8
- ripperdoc/cli/ui/rich_ui.py +737 -47
- ripperdoc/cli/ui/spinner.py +93 -18
- ripperdoc/cli/ui/thinking_spinner.py +1 -2
- ripperdoc/cli/ui/tool_renderers.py +10 -9
- ripperdoc/cli/ui/wizard.py +24 -19
- ripperdoc/core/agents.py +14 -3
- ripperdoc/core/config.py +238 -6
- ripperdoc/core/default_tools.py +91 -10
- ripperdoc/core/hooks/events.py +4 -0
- ripperdoc/core/hooks/llm_callback.py +58 -0
- ripperdoc/core/hooks/manager.py +6 -0
- ripperdoc/core/permissions.py +160 -9
- ripperdoc/core/providers/openai.py +84 -28
- ripperdoc/core/query.py +489 -87
- ripperdoc/core/query_utils.py +17 -14
- ripperdoc/core/skills.py +1 -0
- ripperdoc/core/theme.py +298 -0
- ripperdoc/core/tool.py +15 -5
- ripperdoc/protocol/__init__.py +14 -0
- ripperdoc/protocol/models.py +300 -0
- ripperdoc/protocol/stdio.py +1453 -0
- ripperdoc/tools/background_shell.py +354 -139
- ripperdoc/tools/bash_tool.py +117 -22
- ripperdoc/tools/file_edit_tool.py +228 -50
- ripperdoc/tools/file_read_tool.py +154 -3
- ripperdoc/tools/file_write_tool.py +53 -11
- ripperdoc/tools/grep_tool.py +98 -8
- ripperdoc/tools/lsp_tool.py +609 -0
- ripperdoc/tools/multi_edit_tool.py +26 -3
- ripperdoc/tools/skill_tool.py +52 -1
- ripperdoc/tools/task_tool.py +539 -65
- ripperdoc/utils/conversation_compaction.py +1 -1
- ripperdoc/utils/file_watch.py +216 -7
- ripperdoc/utils/image_utils.py +125 -0
- ripperdoc/utils/log.py +30 -3
- ripperdoc/utils/lsp.py +812 -0
- ripperdoc/utils/mcp.py +80 -18
- ripperdoc/utils/message_formatting.py +7 -4
- ripperdoc/utils/messages.py +198 -33
- ripperdoc/utils/pending_messages.py +50 -0
- ripperdoc/utils/permissions/shell_command_validation.py +3 -3
- ripperdoc/utils/permissions/tool_permission_utils.py +180 -15
- ripperdoc/utils/platform.py +198 -0
- ripperdoc/utils/session_heatmap.py +242 -0
- ripperdoc/utils/session_history.py +2 -2
- ripperdoc/utils/session_stats.py +294 -0
- ripperdoc/utils/shell_utils.py +8 -5
- ripperdoc/utils/todo.py +0 -6
- {ripperdoc-0.2.9.dist-info → ripperdoc-0.3.0.dist-info}/METADATA +55 -17
- ripperdoc-0.3.0.dist-info/RECORD +136 -0
- {ripperdoc-0.2.9.dist-info → ripperdoc-0.3.0.dist-info}/WHEEL +1 -1
- ripperdoc/sdk/__init__.py +0 -9
- ripperdoc/sdk/client.py +0 -333
- ripperdoc-0.2.9.dist-info/RECORD +0 -123
- {ripperdoc-0.2.9.dist-info → ripperdoc-0.3.0.dist-info}/entry_points.txt +0 -0
- {ripperdoc-0.2.9.dist-info → ripperdoc-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {ripperdoc-0.2.9.dist-info → ripperdoc-0.3.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"""Pydantic models for stdio protocol messages.
|
|
2
|
+
|
|
3
|
+
This module defines type-safe models for all JSON messages exchanged
|
|
4
|
+
over the stdio protocol, replacing raw dictionary construction with
|
|
5
|
+
validated, self-documenting Pydantic models.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any, Literal
|
|
11
|
+
from pydantic import BaseModel, Field, ConfigDict
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# ============================================================================
|
|
15
|
+
# Content Block Models
|
|
16
|
+
# ============================================================================
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ContentBlock(BaseModel):
|
|
20
|
+
"""Base class for content blocks in messages."""
|
|
21
|
+
|
|
22
|
+
model_config = ConfigDict(
|
|
23
|
+
extra="allow",
|
|
24
|
+
populate_by_name=True,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TextContentBlock(ContentBlock):
|
|
29
|
+
"""A text content block."""
|
|
30
|
+
|
|
31
|
+
type: Literal["text"] = "text"
|
|
32
|
+
text: str
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ThinkingContentBlock(ContentBlock):
|
|
36
|
+
"""A thinking/reasoning content block."""
|
|
37
|
+
|
|
38
|
+
type: str = Field(default="thinking")
|
|
39
|
+
thinking: str = Field(alias="text")
|
|
40
|
+
signature: str | None = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ToolUseContentBlock(ContentBlock):
|
|
44
|
+
"""A tool use content block."""
|
|
45
|
+
|
|
46
|
+
type: str = Field(default="tool_use")
|
|
47
|
+
id: str = Field(default="")
|
|
48
|
+
name: str
|
|
49
|
+
input: dict[str, Any] = Field(default_factory=dict)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ToolResultContentBlock(ContentBlock):
|
|
53
|
+
"""A tool result content block."""
|
|
54
|
+
|
|
55
|
+
type: str = Field(default="tool_result")
|
|
56
|
+
tool_use_id: str = Field(default="")
|
|
57
|
+
content: str = Field(default="")
|
|
58
|
+
is_error: bool | None = None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class ImageSource(BaseModel):
|
|
62
|
+
"""Image source data."""
|
|
63
|
+
|
|
64
|
+
type: str = Field(default="base64")
|
|
65
|
+
media_type: str = Field(default="image/jpeg")
|
|
66
|
+
data: str
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ImageContentBlock(ContentBlock):
|
|
70
|
+
"""An image content block."""
|
|
71
|
+
|
|
72
|
+
type: str = Field(default="image")
|
|
73
|
+
source: ImageSource
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Union type for all content blocks
|
|
77
|
+
ContentBlockType = (
|
|
78
|
+
TextContentBlock
|
|
79
|
+
| ThinkingContentBlock
|
|
80
|
+
| ToolUseContentBlock
|
|
81
|
+
| ToolResultContentBlock
|
|
82
|
+
| ImageContentBlock
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# ============================================================================
|
|
87
|
+
# Message Models
|
|
88
|
+
# ============================================================================
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class MessageData(BaseModel):
|
|
92
|
+
"""Base message data."""
|
|
93
|
+
|
|
94
|
+
model_config = ConfigDict(
|
|
95
|
+
extra="allow",
|
|
96
|
+
populate_by_name=True,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class AssistantMessageData(MessageData):
|
|
101
|
+
"""Assistant message data."""
|
|
102
|
+
|
|
103
|
+
content: list[dict[str, Any]] | str
|
|
104
|
+
model: str = "main"
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class UserMessageData(MessageData):
|
|
108
|
+
"""User message data."""
|
|
109
|
+
|
|
110
|
+
content: str = ""
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class AssistantStreamMessage(BaseModel):
|
|
114
|
+
"""An assistant message sent to the SDK."""
|
|
115
|
+
|
|
116
|
+
type: str = Field(default="assistant")
|
|
117
|
+
message: AssistantMessageData
|
|
118
|
+
parent_tool_use_id: str | None = None
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class UserStreamMessage(BaseModel):
|
|
122
|
+
"""A user message sent to the SDK."""
|
|
123
|
+
|
|
124
|
+
type: str = Field(default="user")
|
|
125
|
+
message: UserMessageData
|
|
126
|
+
uuid: str | None = None
|
|
127
|
+
parent_tool_use_id: str | None = None
|
|
128
|
+
tool_use_result: Any = None
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# Union type for stream messages
|
|
132
|
+
StreamMessage = AssistantStreamMessage | UserStreamMessage
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# ============================================================================
|
|
136
|
+
# Control Protocol Models
|
|
137
|
+
# ============================================================================
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class ControlResponseData(BaseModel):
|
|
141
|
+
"""Base class for control response data."""
|
|
142
|
+
|
|
143
|
+
model_config = ConfigDict(
|
|
144
|
+
extra="allow",
|
|
145
|
+
populate_by_name=True,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class ControlResponseSuccess(ControlResponseData):
|
|
150
|
+
"""A successful control response."""
|
|
151
|
+
|
|
152
|
+
subtype: str = Field(default="success")
|
|
153
|
+
request_id: str
|
|
154
|
+
response: dict[str, Any] | None = None
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class ControlResponseError(ControlResponseData):
|
|
158
|
+
"""An error control response."""
|
|
159
|
+
|
|
160
|
+
subtype: str = Field(default="error")
|
|
161
|
+
request_id: str
|
|
162
|
+
error: str
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class ControlResponseMessage(BaseModel):
|
|
166
|
+
"""A control response message wrapper."""
|
|
167
|
+
|
|
168
|
+
type: str = Field(default="control_response")
|
|
169
|
+
response: ControlResponseSuccess | ControlResponseError
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
# ============================================================================
|
|
173
|
+
# Result/Usage Models
|
|
174
|
+
# ============================================================================
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class UsageInfo(BaseModel):
|
|
178
|
+
"""Token usage information."""
|
|
179
|
+
|
|
180
|
+
input_tokens: int = 0
|
|
181
|
+
cache_creation_input_tokens: int = 0
|
|
182
|
+
cache_read_input_tokens: int = 0
|
|
183
|
+
output_tokens: int = 0
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class MCPServerInfo(BaseModel):
|
|
187
|
+
"""MCP server information."""
|
|
188
|
+
|
|
189
|
+
name: str
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class InitializeResponseData(BaseModel):
|
|
193
|
+
"""Response data for initialize request."""
|
|
194
|
+
|
|
195
|
+
session_id: str
|
|
196
|
+
system_prompt: str
|
|
197
|
+
tools: list[str]
|
|
198
|
+
mcp_servers: list[MCPServerInfo] = Field(default_factory=list)
|
|
199
|
+
slash_commands: list[Any] = Field(default_factory=list)
|
|
200
|
+
apiKeySource: str = "none"
|
|
201
|
+
claude_code_version: str = "0.1.0"
|
|
202
|
+
output_style: str = "default"
|
|
203
|
+
agents: list[str] = Field(default_factory=list)
|
|
204
|
+
skills: list[Any] = Field(default_factory=list)
|
|
205
|
+
plugins: list[Any] = Field(default_factory=list)
|
|
206
|
+
|
|
207
|
+
model_config = ConfigDict(
|
|
208
|
+
extra="allow",
|
|
209
|
+
populate_by_name=True,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class ResultMessage(BaseModel):
|
|
214
|
+
"""A result message sent at the end of a query."""
|
|
215
|
+
|
|
216
|
+
type: str = Field(default="result")
|
|
217
|
+
subtype: str = Field(default="result")
|
|
218
|
+
duration_ms: int
|
|
219
|
+
duration_api_ms: int
|
|
220
|
+
is_error: bool
|
|
221
|
+
num_turns: int
|
|
222
|
+
session_id: str
|
|
223
|
+
total_cost_usd: float | None = None
|
|
224
|
+
usage: UsageInfo | None = None
|
|
225
|
+
result: str | None = None
|
|
226
|
+
structured_output: Any = None
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
# ============================================================================
|
|
230
|
+
# Permission Response Models
|
|
231
|
+
# ============================================================================
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class PermissionResponseAllow(BaseModel):
|
|
235
|
+
"""A permission allow response."""
|
|
236
|
+
|
|
237
|
+
decision: str = Field(default="allow")
|
|
238
|
+
updatedInput: dict[str, Any] | None = None
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class PermissionResponseDeny(BaseModel):
|
|
242
|
+
"""A permission deny response."""
|
|
243
|
+
|
|
244
|
+
decision: str = Field(default="deny")
|
|
245
|
+
message: str = ""
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
# ============================================================================
|
|
249
|
+
# Helper Functions
|
|
250
|
+
# ============================================================================
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def model_to_dict(model: BaseModel) -> dict[str, Any]:
|
|
254
|
+
"""Convert a Pydantic model to a JSON-serializable dictionary.
|
|
255
|
+
|
|
256
|
+
This handles exclude_none=True and ensures proper serialization,
|
|
257
|
+
while always including type/subtype fields for protocol messages.
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
model: The Pydantic model to convert.
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
A JSON-serializable dictionary.
|
|
264
|
+
"""
|
|
265
|
+
return model.model_dump(exclude_none=True, by_alias=True, mode="json")
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
__all__ = [
|
|
269
|
+
# Content Blocks
|
|
270
|
+
"ContentBlock",
|
|
271
|
+
"TextContentBlock",
|
|
272
|
+
"ThinkingContentBlock",
|
|
273
|
+
"ToolUseContentBlock",
|
|
274
|
+
"ToolResultContentBlock",
|
|
275
|
+
"ImageContentBlock",
|
|
276
|
+
"ImageSource",
|
|
277
|
+
"ContentBlockType",
|
|
278
|
+
# Messages
|
|
279
|
+
"MessageData",
|
|
280
|
+
"AssistantMessageData",
|
|
281
|
+
"UserMessageData",
|
|
282
|
+
"AssistantStreamMessage",
|
|
283
|
+
"UserStreamMessage",
|
|
284
|
+
"StreamMessage",
|
|
285
|
+
# Control Protocol
|
|
286
|
+
"ControlResponseData",
|
|
287
|
+
"ControlResponseSuccess",
|
|
288
|
+
"ControlResponseError",
|
|
289
|
+
"ControlResponseMessage",
|
|
290
|
+
# Result/Usage
|
|
291
|
+
"UsageInfo",
|
|
292
|
+
"MCPServerInfo",
|
|
293
|
+
"InitializeResponseData",
|
|
294
|
+
"ResultMessage",
|
|
295
|
+
# Permissions
|
|
296
|
+
"PermissionResponseAllow",
|
|
297
|
+
"PermissionResponseDeny",
|
|
298
|
+
# Helpers
|
|
299
|
+
"model_to_dict",
|
|
300
|
+
]
|