sqlsaber 0.14.0__py3-none-any.whl → 0.16.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.
Potentially problematic release.
This version of sqlsaber might be problematic. Click here for more details.
- sqlsaber/agents/__init__.py +2 -4
- sqlsaber/agents/base.py +18 -221
- sqlsaber/agents/mcp.py +2 -2
- sqlsaber/agents/pydantic_ai_agent.py +170 -0
- sqlsaber/cli/auth.py +146 -79
- sqlsaber/cli/commands.py +22 -7
- sqlsaber/cli/database.py +1 -1
- sqlsaber/cli/interactive.py +65 -30
- sqlsaber/cli/models.py +58 -29
- sqlsaber/cli/streaming.py +114 -77
- sqlsaber/config/api_keys.py +9 -11
- sqlsaber/config/providers.py +116 -0
- sqlsaber/config/settings.py +50 -30
- sqlsaber/database/connection.py +3 -3
- sqlsaber/mcp/mcp.py +43 -51
- sqlsaber/models/__init__.py +0 -3
- sqlsaber/tools/__init__.py +25 -0
- sqlsaber/tools/base.py +85 -0
- sqlsaber/tools/enums.py +21 -0
- sqlsaber/tools/instructions.py +251 -0
- sqlsaber/tools/registry.py +130 -0
- sqlsaber/tools/sql_tools.py +275 -0
- sqlsaber/tools/visualization_tools.py +144 -0
- {sqlsaber-0.14.0.dist-info → sqlsaber-0.16.0.dist-info}/METADATA +20 -39
- sqlsaber-0.16.0.dist-info/RECORD +51 -0
- sqlsaber/agents/anthropic.py +0 -579
- sqlsaber/agents/streaming.py +0 -16
- sqlsaber/clients/__init__.py +0 -6
- sqlsaber/clients/anthropic.py +0 -285
- sqlsaber/clients/base.py +0 -31
- sqlsaber/clients/exceptions.py +0 -117
- sqlsaber/clients/models.py +0 -282
- sqlsaber/clients/streaming.py +0 -257
- sqlsaber/models/events.py +0 -28
- sqlsaber-0.14.0.dist-info/RECORD +0 -51
- {sqlsaber-0.14.0.dist-info → sqlsaber-0.16.0.dist-info}/WHEEL +0 -0
- {sqlsaber-0.14.0.dist-info → sqlsaber-0.16.0.dist-info}/entry_points.txt +0 -0
- {sqlsaber-0.14.0.dist-info → sqlsaber-0.16.0.dist-info}/licenses/LICENSE +0 -0
sqlsaber/clients/models.py
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
"""Data models for LLM client requests and responses."""
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from enum import Enum
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class MessageRole(str, Enum):
|
|
9
|
-
"""Message roles in a conversation."""
|
|
10
|
-
|
|
11
|
-
USER = "user"
|
|
12
|
-
ASSISTANT = "assistant"
|
|
13
|
-
SYSTEM = "system"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class ContentType(str, Enum):
|
|
17
|
-
"""Content block types."""
|
|
18
|
-
|
|
19
|
-
TEXT = "text"
|
|
20
|
-
IMAGE = "image"
|
|
21
|
-
TOOL_USE = "tool_use"
|
|
22
|
-
TOOL_RESULT = "tool_result"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class ToolChoiceType(str, Enum):
|
|
26
|
-
"""Tool choice types."""
|
|
27
|
-
|
|
28
|
-
AUTO = "auto"
|
|
29
|
-
ANY = "any"
|
|
30
|
-
TOOL = "tool"
|
|
31
|
-
NONE = "none"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class StopReason(str, Enum):
|
|
35
|
-
"""Stop reasons for message completion."""
|
|
36
|
-
|
|
37
|
-
END_TURN = "end_turn"
|
|
38
|
-
MAX_TOKENS = "max_tokens"
|
|
39
|
-
STOP_SEQUENCE = "stop_sequence"
|
|
40
|
-
TOOL_USE = "tool_use"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@dataclass
|
|
44
|
-
class ContentBlock:
|
|
45
|
-
"""A content block in a message."""
|
|
46
|
-
|
|
47
|
-
type: ContentType
|
|
48
|
-
content: str | dict[str, Any]
|
|
49
|
-
|
|
50
|
-
def to_dict(self) -> dict[str, Any]:
|
|
51
|
-
"""Convert to dictionary format."""
|
|
52
|
-
if self.type == ContentType.TEXT:
|
|
53
|
-
return {"type": "text", "text": self.content}
|
|
54
|
-
elif self.type == ContentType.TOOL_USE:
|
|
55
|
-
return {
|
|
56
|
-
"type": "tool_use",
|
|
57
|
-
"id": self.content["id"],
|
|
58
|
-
"name": self.content["name"],
|
|
59
|
-
"input": self.content["input"],
|
|
60
|
-
}
|
|
61
|
-
elif self.type == ContentType.TOOL_RESULT:
|
|
62
|
-
return {
|
|
63
|
-
"type": "tool_result",
|
|
64
|
-
"tool_use_id": self.content["tool_use_id"],
|
|
65
|
-
"content": self.content["content"],
|
|
66
|
-
}
|
|
67
|
-
else:
|
|
68
|
-
return {"type": self.type.value, **self.content}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
@dataclass
|
|
72
|
-
class Message:
|
|
73
|
-
"""A message in a conversation."""
|
|
74
|
-
|
|
75
|
-
role: MessageRole
|
|
76
|
-
content: str | list[ContentBlock]
|
|
77
|
-
|
|
78
|
-
def to_dict(self) -> dict[str, Any]:
|
|
79
|
-
"""Convert to dictionary format for API requests."""
|
|
80
|
-
if isinstance(self.content, str):
|
|
81
|
-
return {"role": self.role.value, "content": self.content}
|
|
82
|
-
else:
|
|
83
|
-
return {
|
|
84
|
-
"role": self.role.value,
|
|
85
|
-
"content": [block.to_dict() for block in self.content],
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
@dataclass
|
|
90
|
-
class ToolDefinition:
|
|
91
|
-
"""Definition of a tool that can be called."""
|
|
92
|
-
|
|
93
|
-
name: str
|
|
94
|
-
description: str
|
|
95
|
-
input_schema: dict[str, Any]
|
|
96
|
-
|
|
97
|
-
def to_dict(self) -> dict[str, Any]:
|
|
98
|
-
"""Convert to dictionary format for API requests."""
|
|
99
|
-
return {
|
|
100
|
-
"name": self.name,
|
|
101
|
-
"description": self.description,
|
|
102
|
-
"input_schema": self.input_schema,
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
@dataclass
|
|
107
|
-
class ToolChoice:
|
|
108
|
-
"""Tool choice configuration."""
|
|
109
|
-
|
|
110
|
-
type: ToolChoiceType
|
|
111
|
-
name: str | None = None
|
|
112
|
-
disable_parallel_tool_use: bool = False
|
|
113
|
-
|
|
114
|
-
def to_dict(self) -> dict[str, Any]:
|
|
115
|
-
"""Convert to dictionary format for API requests."""
|
|
116
|
-
result = {"type": self.type.value}
|
|
117
|
-
if self.name:
|
|
118
|
-
result["name"] = self.name
|
|
119
|
-
if self.disable_parallel_tool_use:
|
|
120
|
-
result["disable_parallel_tool_use"] = True
|
|
121
|
-
return result
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
@dataclass
|
|
125
|
-
class CreateMessageRequest:
|
|
126
|
-
"""Request to create a message."""
|
|
127
|
-
|
|
128
|
-
model: str
|
|
129
|
-
messages: list[Message]
|
|
130
|
-
max_tokens: int
|
|
131
|
-
system: str | None = None
|
|
132
|
-
tools: list[ToolDefinition] | None = None
|
|
133
|
-
tool_choice: ToolChoice | None = None
|
|
134
|
-
temperature: float | None = None
|
|
135
|
-
stream: bool = False
|
|
136
|
-
stop_sequences: list[str] | None = None
|
|
137
|
-
|
|
138
|
-
def to_dict(self) -> dict[str, Any]:
|
|
139
|
-
"""Convert to dictionary format for API requests."""
|
|
140
|
-
data = {
|
|
141
|
-
"model": self.model,
|
|
142
|
-
"messages": [msg.to_dict() for msg in self.messages],
|
|
143
|
-
"max_tokens": self.max_tokens,
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if self.system:
|
|
147
|
-
data["system"] = self.system
|
|
148
|
-
if self.tools:
|
|
149
|
-
data["tools"] = [tool.to_dict() for tool in self.tools]
|
|
150
|
-
if self.tool_choice:
|
|
151
|
-
data["tool_choice"] = self.tool_choice.to_dict()
|
|
152
|
-
if self.temperature is not None:
|
|
153
|
-
data["temperature"] = self.temperature
|
|
154
|
-
if self.stream:
|
|
155
|
-
data["stream"] = True
|
|
156
|
-
if self.stop_sequences:
|
|
157
|
-
data["stop_sequences"] = self.stop_sequences
|
|
158
|
-
|
|
159
|
-
return data
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
@dataclass
|
|
163
|
-
class Usage:
|
|
164
|
-
"""Token usage information."""
|
|
165
|
-
|
|
166
|
-
input_tokens: int
|
|
167
|
-
output_tokens: int
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
@dataclass
|
|
171
|
-
class MessageResponse:
|
|
172
|
-
"""Response from message creation."""
|
|
173
|
-
|
|
174
|
-
id: str
|
|
175
|
-
model: str
|
|
176
|
-
role: MessageRole
|
|
177
|
-
content: list[ContentBlock]
|
|
178
|
-
stop_reason: StopReason
|
|
179
|
-
stop_sequence: str | None
|
|
180
|
-
usage: Usage
|
|
181
|
-
|
|
182
|
-
@classmethod
|
|
183
|
-
def from_dict(cls, data: dict[str, Any]) -> "MessageResponse":
|
|
184
|
-
"""Create from API response dictionary."""
|
|
185
|
-
content_blocks = []
|
|
186
|
-
for block_data in data["content"]:
|
|
187
|
-
if block_data["type"] == "text":
|
|
188
|
-
content_blocks.append(
|
|
189
|
-
ContentBlock(ContentType.TEXT, block_data["text"])
|
|
190
|
-
)
|
|
191
|
-
elif block_data["type"] == "tool_use":
|
|
192
|
-
content_blocks.append(
|
|
193
|
-
ContentBlock(
|
|
194
|
-
ContentType.TOOL_USE,
|
|
195
|
-
{
|
|
196
|
-
"id": block_data["id"],
|
|
197
|
-
"name": block_data["name"],
|
|
198
|
-
"input": block_data["input"],
|
|
199
|
-
},
|
|
200
|
-
)
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
return cls(
|
|
204
|
-
id=data["id"],
|
|
205
|
-
model=data["model"],
|
|
206
|
-
role=MessageRole(data["role"]),
|
|
207
|
-
content=content_blocks,
|
|
208
|
-
stop_reason=StopReason(data["stop_reason"]),
|
|
209
|
-
stop_sequence=data.get("stop_sequence"),
|
|
210
|
-
usage=Usage(
|
|
211
|
-
input_tokens=data["usage"]["input_tokens"],
|
|
212
|
-
output_tokens=data["usage"]["output_tokens"],
|
|
213
|
-
),
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
# Stream event types and data models for streaming
|
|
218
|
-
@dataclass
|
|
219
|
-
class StreamEventData:
|
|
220
|
-
"""Base class for stream event data."""
|
|
221
|
-
|
|
222
|
-
pass
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
@dataclass
|
|
226
|
-
class TextDeltaData(StreamEventData):
|
|
227
|
-
"""Text delta stream event data."""
|
|
228
|
-
|
|
229
|
-
text: str
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
@dataclass
|
|
233
|
-
class ToolUseStartData(StreamEventData):
|
|
234
|
-
"""Tool use start stream event data."""
|
|
235
|
-
|
|
236
|
-
id: str
|
|
237
|
-
name: str
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
@dataclass
|
|
241
|
-
class ToolUseInputData(StreamEventData):
|
|
242
|
-
"""Tool use input stream event data."""
|
|
243
|
-
|
|
244
|
-
partial_json: str
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
@dataclass
|
|
248
|
-
class MessageStartData(StreamEventData):
|
|
249
|
-
"""Message start stream event data."""
|
|
250
|
-
|
|
251
|
-
message: dict[str, Any]
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
@dataclass
|
|
255
|
-
class MessageDeltaData(StreamEventData):
|
|
256
|
-
"""Message delta stream event data."""
|
|
257
|
-
|
|
258
|
-
delta: dict[str, Any]
|
|
259
|
-
usage: dict[str, Any] | None = None
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
@dataclass
|
|
263
|
-
class ContentBlockStartData(StreamEventData):
|
|
264
|
-
"""Content block start stream event data."""
|
|
265
|
-
|
|
266
|
-
index: int
|
|
267
|
-
content_block: dict[str, Any]
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
@dataclass
|
|
271
|
-
class ContentBlockDeltaData(StreamEventData):
|
|
272
|
-
"""Content block delta stream event data."""
|
|
273
|
-
|
|
274
|
-
index: int
|
|
275
|
-
delta: dict[str, Any]
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
@dataclass
|
|
279
|
-
class ContentBlockStopData(StreamEventData):
|
|
280
|
-
"""Content block stop stream event data."""
|
|
281
|
-
|
|
282
|
-
index: int
|
sqlsaber/clients/streaming.py
DELETED
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
"""Streaming adapters and utilities for LLM clients."""
|
|
2
|
-
|
|
3
|
-
import asyncio
|
|
4
|
-
import json
|
|
5
|
-
import logging
|
|
6
|
-
from typing import Any, AsyncIterator
|
|
7
|
-
|
|
8
|
-
logger = logging.getLogger(__name__)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class AnthropicStreamAdapter:
|
|
12
|
-
"""Adapter to convert raw Anthropic stream events to standardized format.
|
|
13
|
-
|
|
14
|
-
This adapter converts the raw SSE events from Anthropic API into objects
|
|
15
|
-
that match the structure expected by the current AnthropicSQLAgent.
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
def __init__(self):
|
|
19
|
-
self.content_blocks: list[dict[str, Any]] = []
|
|
20
|
-
self.tool_use_blocks: list[dict[str, Any]] = []
|
|
21
|
-
|
|
22
|
-
async def process_stream(
|
|
23
|
-
self,
|
|
24
|
-
raw_stream: AsyncIterator[dict[str, Any]],
|
|
25
|
-
cancellation_token: asyncio.Event | None = None,
|
|
26
|
-
) -> AsyncIterator[Any]:
|
|
27
|
-
"""Process raw stream events and yield adapted events.
|
|
28
|
-
|
|
29
|
-
Args:
|
|
30
|
-
raw_stream: Raw stream events from the API
|
|
31
|
-
cancellation_token: Optional cancellation token
|
|
32
|
-
|
|
33
|
-
Yields:
|
|
34
|
-
Adapted stream events that match the SDK format
|
|
35
|
-
"""
|
|
36
|
-
async for raw_event in raw_stream:
|
|
37
|
-
# Check for cancellation
|
|
38
|
-
if cancellation_token is not None and cancellation_token.is_set():
|
|
39
|
-
return
|
|
40
|
-
|
|
41
|
-
# Convert raw event to SDK-like event
|
|
42
|
-
adapted_event = self._adapt_event(raw_event)
|
|
43
|
-
if adapted_event:
|
|
44
|
-
yield adapted_event
|
|
45
|
-
|
|
46
|
-
def _adapt_event(self, raw_event: dict[str, Any]) -> Any | None:
|
|
47
|
-
"""Adapt a raw stream event to match SDK format.
|
|
48
|
-
|
|
49
|
-
Args:
|
|
50
|
-
raw_event: Raw event from the API
|
|
51
|
-
|
|
52
|
-
Returns:
|
|
53
|
-
Adapted event object or None if event should be filtered
|
|
54
|
-
"""
|
|
55
|
-
event_type = raw_event.get("type")
|
|
56
|
-
event_data = raw_event.get("data", {})
|
|
57
|
-
|
|
58
|
-
if event_type == "ping":
|
|
59
|
-
# Create a ping event object
|
|
60
|
-
return PingEvent()
|
|
61
|
-
|
|
62
|
-
elif event_type == "message_start":
|
|
63
|
-
# Create message start event
|
|
64
|
-
return MessageStartEvent(event_data.get("message", {}))
|
|
65
|
-
|
|
66
|
-
elif event_type == "content_block_start":
|
|
67
|
-
# Create content block start event
|
|
68
|
-
index = event_data.get("index", 0)
|
|
69
|
-
content_block = event_data.get("content_block", {})
|
|
70
|
-
|
|
71
|
-
# Initialize content blocks list if needed
|
|
72
|
-
while len(self.content_blocks) <= index:
|
|
73
|
-
self.content_blocks.append({"type": "text", "text": ""})
|
|
74
|
-
|
|
75
|
-
if content_block.get("type") == "tool_use":
|
|
76
|
-
# Add to tool use blocks tracking
|
|
77
|
-
tool_block = {
|
|
78
|
-
"id": content_block.get("id"),
|
|
79
|
-
"name": content_block.get("name"),
|
|
80
|
-
"input": {},
|
|
81
|
-
"_partial": "",
|
|
82
|
-
}
|
|
83
|
-
self.tool_use_blocks.append(tool_block)
|
|
84
|
-
|
|
85
|
-
return ContentBlockStartEvent(index, content_block)
|
|
86
|
-
|
|
87
|
-
elif event_type == "content_block_delta":
|
|
88
|
-
# Create content block delta event
|
|
89
|
-
index = event_data.get("index", 0)
|
|
90
|
-
delta = event_data.get("delta", {})
|
|
91
|
-
|
|
92
|
-
# Update content blocks tracking
|
|
93
|
-
if index < len(self.content_blocks):
|
|
94
|
-
if delta.get("type") == "text_delta":
|
|
95
|
-
self.content_blocks[index]["text"] += delta.get("text", "")
|
|
96
|
-
elif delta.get("type") == "input_json_delta":
|
|
97
|
-
# Update tool use input tracking
|
|
98
|
-
if self.tool_use_blocks:
|
|
99
|
-
current_tool = self.tool_use_blocks[-1]
|
|
100
|
-
current_tool["_partial"] += delta.get("partial_json", "")
|
|
101
|
-
try:
|
|
102
|
-
current_tool["input"] = json.loads(current_tool["_partial"])
|
|
103
|
-
except json.JSONDecodeError:
|
|
104
|
-
pass # Partial JSON, continue accumulating
|
|
105
|
-
|
|
106
|
-
return ContentBlockDeltaEvent(index, delta)
|
|
107
|
-
|
|
108
|
-
elif event_type == "content_block_stop":
|
|
109
|
-
# Create content block stop event
|
|
110
|
-
index = event_data.get("index", 0)
|
|
111
|
-
return ContentBlockStopEvent(index)
|
|
112
|
-
|
|
113
|
-
elif event_type == "message_delta":
|
|
114
|
-
# Create message delta event
|
|
115
|
-
delta = event_data.get("delta", {})
|
|
116
|
-
usage = event_data.get("usage", {})
|
|
117
|
-
return MessageDeltaEvent(delta, usage)
|
|
118
|
-
|
|
119
|
-
elif event_type == "message_stop":
|
|
120
|
-
# Finalize tool blocks
|
|
121
|
-
self._finalize_tool_blocks()
|
|
122
|
-
return MessageStopEvent()
|
|
123
|
-
|
|
124
|
-
elif event_type == "error":
|
|
125
|
-
# Create error event
|
|
126
|
-
return ErrorEvent(event_data)
|
|
127
|
-
|
|
128
|
-
else:
|
|
129
|
-
# Unknown event type, log and ignore
|
|
130
|
-
logger.debug(f"Unknown event type: {event_type}")
|
|
131
|
-
return None
|
|
132
|
-
|
|
133
|
-
def _finalize_tool_blocks(self):
|
|
134
|
-
"""Finalize tool use blocks by cleaning up and adding to content blocks."""
|
|
135
|
-
for block in self.tool_use_blocks:
|
|
136
|
-
block["type"] = "tool_use"
|
|
137
|
-
if "_partial" in block:
|
|
138
|
-
del block["_partial"]
|
|
139
|
-
self.content_blocks.append(block)
|
|
140
|
-
|
|
141
|
-
def get_stop_reason(self) -> str:
|
|
142
|
-
"""Get the stop reason based on current state."""
|
|
143
|
-
if self.tool_use_blocks:
|
|
144
|
-
return "tool_use"
|
|
145
|
-
return "stop"
|
|
146
|
-
|
|
147
|
-
def get_content_blocks(self) -> list[dict[str, Any]]:
|
|
148
|
-
"""Get the current content blocks."""
|
|
149
|
-
return self.content_blocks.copy()
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
# Event classes that match the SDK structure
|
|
153
|
-
class BaseStreamEvent:
|
|
154
|
-
"""Base class for stream events."""
|
|
155
|
-
|
|
156
|
-
def __init__(self, event_type: str):
|
|
157
|
-
self.type = event_type
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
class PingEvent(BaseStreamEvent):
|
|
161
|
-
"""Ping event."""
|
|
162
|
-
|
|
163
|
-
def __init__(self):
|
|
164
|
-
super().__init__("ping")
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
class MessageStartEvent(BaseStreamEvent):
|
|
168
|
-
"""Message start event."""
|
|
169
|
-
|
|
170
|
-
def __init__(self, message: dict[str, Any]):
|
|
171
|
-
super().__init__("message_start")
|
|
172
|
-
self.message = message
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
class ContentBlockStartEvent(BaseStreamEvent):
|
|
176
|
-
"""Content block start event."""
|
|
177
|
-
|
|
178
|
-
def __init__(self, index: int, content_block: dict[str, Any]):
|
|
179
|
-
super().__init__("content_block_start")
|
|
180
|
-
self.index = index
|
|
181
|
-
self.content_block = MockContentBlock(content_block)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
class ContentBlockDeltaEvent(BaseStreamEvent):
|
|
185
|
-
"""Content block delta event."""
|
|
186
|
-
|
|
187
|
-
def __init__(self, index: int, delta: dict[str, Any]):
|
|
188
|
-
super().__init__("content_block_delta")
|
|
189
|
-
self.index = index
|
|
190
|
-
self.delta = MockDelta(delta)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
class ContentBlockStopEvent(BaseStreamEvent):
|
|
194
|
-
"""Content block stop event."""
|
|
195
|
-
|
|
196
|
-
def __init__(self, index: int):
|
|
197
|
-
super().__init__("content_block_stop")
|
|
198
|
-
self.index = index
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
class MessageDeltaEvent(BaseStreamEvent):
|
|
202
|
-
"""Message delta event."""
|
|
203
|
-
|
|
204
|
-
def __init__(self, delta: dict[str, Any], usage: dict[str, Any]):
|
|
205
|
-
super().__init__("message_delta")
|
|
206
|
-
self.delta = delta
|
|
207
|
-
self.usage = usage
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
class MessageStopEvent(BaseStreamEvent):
|
|
211
|
-
"""Message stop event."""
|
|
212
|
-
|
|
213
|
-
def __init__(self):
|
|
214
|
-
super().__init__("message_stop")
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
class ErrorEvent(BaseStreamEvent):
|
|
218
|
-
"""Error event."""
|
|
219
|
-
|
|
220
|
-
def __init__(self, error_data: dict[str, Any]):
|
|
221
|
-
super().__init__("error")
|
|
222
|
-
self.error = error_data
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
# Mock classes to match SDK object structure
|
|
226
|
-
class MockContentBlock:
|
|
227
|
-
"""Mock content block object that matches SDK structure."""
|
|
228
|
-
|
|
229
|
-
def __init__(self, data: dict[str, Any]):
|
|
230
|
-
self.type = data.get("type")
|
|
231
|
-
self.id = data.get("id")
|
|
232
|
-
self.name = data.get("name")
|
|
233
|
-
self.input = data.get("input", {})
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
class MockDelta:
|
|
237
|
-
"""Mock delta object that matches SDK structure."""
|
|
238
|
-
|
|
239
|
-
def __init__(self, data: dict[str, Any]):
|
|
240
|
-
self.data = data
|
|
241
|
-
# Set attributes based on delta type
|
|
242
|
-
if data.get("type") == "text_delta":
|
|
243
|
-
self.text = data.get("text", "")
|
|
244
|
-
elif data.get("type") == "input_json_delta":
|
|
245
|
-
self.partial_json = data.get("partial_json", "")
|
|
246
|
-
|
|
247
|
-
def __getattr__(self, name):
|
|
248
|
-
"""Allow access to any attribute from the data."""
|
|
249
|
-
return self.data.get(name)
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
class StreamingResponse:
|
|
253
|
-
"""Response object for streaming that matches the current agent's expectations."""
|
|
254
|
-
|
|
255
|
-
def __init__(self, content: list[dict[str, Any]], stop_reason: str):
|
|
256
|
-
self.content = content
|
|
257
|
-
self.stop_reason = stop_reason
|
sqlsaber/models/events.py
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"""Event models for streaming and responses."""
|
|
2
|
-
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class StreamEvent:
|
|
7
|
-
"""Event emitted during streaming processing."""
|
|
8
|
-
|
|
9
|
-
def __init__(self, event_type: str, data: Any = None):
|
|
10
|
-
# 'tool_use', 'text', 'query_result', 'plot_result', 'error', 'processing'
|
|
11
|
-
self.type = event_type
|
|
12
|
-
self.data = data
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class SQLResponse:
|
|
16
|
-
"""Response from the SQL agent."""
|
|
17
|
-
|
|
18
|
-
def __init__(
|
|
19
|
-
self,
|
|
20
|
-
query: str | None = None,
|
|
21
|
-
explanation: str = "",
|
|
22
|
-
results: list[dict[str, Any]] | None = None,
|
|
23
|
-
error: str | None = None,
|
|
24
|
-
):
|
|
25
|
-
self.query = query
|
|
26
|
-
self.explanation = explanation
|
|
27
|
-
self.results = results
|
|
28
|
-
self.error = error
|
sqlsaber-0.14.0.dist-info/RECORD
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
sqlsaber/__init__.py,sha256=HjS8ULtP4MGpnTL7njVY45NKV9Fi4e_yeYuY-hyXWQc,73
|
|
2
|
-
sqlsaber/__main__.py,sha256=RIHxWeWh2QvLfah-2OkhI5IJxojWfy4fXpMnVEJYvxw,78
|
|
3
|
-
sqlsaber/agents/__init__.py,sha256=LWeSeEUE4BhkyAYFF3TE-fx8TtLud3oyEtyB8ojFJgo,167
|
|
4
|
-
sqlsaber/agents/anthropic.py,sha256=xH4xY1lq5idDgY8Vklgu5hGLoKLHWQMMfPgjvQjfG7I,23615
|
|
5
|
-
sqlsaber/agents/base.py,sha256=9A-iceb93eHrQHTdLoeSicP3ZqDHOFTx3Fe5OvHvUkg,14093
|
|
6
|
-
sqlsaber/agents/mcp.py,sha256=FKtXgDrPZ2-xqUYCw2baI5JzrWekXaC5fjkYW1_Mg50,827
|
|
7
|
-
sqlsaber/agents/streaming.py,sha256=LaSeMTlxuJFRArJVqDly5-_KgcePiCCKPKfMxfB4oGs,521
|
|
8
|
-
sqlsaber/cli/__init__.py,sha256=qVSLVJLLJYzoC6aj6y9MFrzZvAwc4_OgxU9DlkQnZ4M,86
|
|
9
|
-
sqlsaber/cli/auth.py,sha256=1yvawtS5NGj9dWMRZ8I5T6sqBiRqZpPsjEPrJSQBJAs,4979
|
|
10
|
-
sqlsaber/cli/commands.py,sha256=VX7pqQnf-85A9zkjXqzytVNeCG8KO0mB2TyIEzB4sh8,6241
|
|
11
|
-
sqlsaber/cli/completers.py,sha256=HsUPjaZweLSeYCWkAcgMl8FylQ1xjWBWYTEL_9F6xfU,6430
|
|
12
|
-
sqlsaber/cli/database.py,sha256=tJ8rqGrafZpg3VgDmSiq7eZoPscoGAW3XLTYGoQw8LE,12910
|
|
13
|
-
sqlsaber/cli/display.py,sha256=HtXwPe3VPUh2EJpyvpJVWyisCanu9O7w-rkqq7Y4UaY,9791
|
|
14
|
-
sqlsaber/cli/interactive.py,sha256=7RjUMMPJ49RUuUGn-gP6vgiW6Ccvin9mzmRL-9p6eto,8171
|
|
15
|
-
sqlsaber/cli/memory.py,sha256=OufHFJFwV0_GGn7LvKRTJikkWhV1IwNIUDOxFPHXOaQ,7794
|
|
16
|
-
sqlsaber/cli/models.py,sha256=HByezaeKqj65GzB_FmWuugjkgTq2Pvab_mzNZnHxya0,7690
|
|
17
|
-
sqlsaber/cli/streaming.py,sha256=WfhFd5ntq2HStpJZwWJ0C5uyXKc3aU14eo8HdjzW1o0,3767
|
|
18
|
-
sqlsaber/clients/__init__.py,sha256=jcMoVsT92U6nQrfotCp1h0ggskJPAcgeYarqQl1qEBg,171
|
|
19
|
-
sqlsaber/clients/anthropic.py,sha256=umRmuzpmJdYO7hO3biAZXO9T_sb6Vv010o6zqn03is8,9947
|
|
20
|
-
sqlsaber/clients/base.py,sha256=RLFJ3NV75Z6keiu9mnh9zrMZK1HwdeUby0e3oeJMtyw,935
|
|
21
|
-
sqlsaber/clients/exceptions.py,sha256=6OoCSxvuA13I3dML2Zngygl9MdaObISh1UHvBB3yUq0,3408
|
|
22
|
-
sqlsaber/clients/models.py,sha256=fOvnkW8NQSdn8Oqfk3-5dP4TylLh7C9wOvuNQYw184A,7016
|
|
23
|
-
sqlsaber/clients/streaming.py,sha256=CwdoocLAyW_GjZm2XcLb33Sa99w5fyb7dU-27FFpePQ,8319
|
|
24
|
-
sqlsaber/config/__init__.py,sha256=olwC45k8Nc61yK0WmPUk7XHdbsZH9HuUAbwnmKe3IgA,100
|
|
25
|
-
sqlsaber/config/api_keys.py,sha256=wnWlYy26AkkevZ1Vln6avYRBDLPRzfrHkj-fPojkxaQ,3624
|
|
26
|
-
sqlsaber/config/auth.py,sha256=b5qB2h1doXyO9Bn8z0CcL8LAR2jF431gGXBGKLgTmtQ,2756
|
|
27
|
-
sqlsaber/config/database.py,sha256=c6q3l4EvoBch1ckYHA70hf6L7fSOY-sItnLCpvJiPrA,11357
|
|
28
|
-
sqlsaber/config/oauth_flow.py,sha256=A3bSXaBLzuAfXV2ZPA94m9NV33c2MyL6M4ii9oEkswQ,10291
|
|
29
|
-
sqlsaber/config/oauth_tokens.py,sha256=C9z35hyx-PvSAYdC1LNf3rg9_wsEIY56hkEczelbad0,6015
|
|
30
|
-
sqlsaber/config/settings.py,sha256=gKhGlErzsBk39RoRSy1b8pb-bN2K7HIaPaBgbJDhY4M,4753
|
|
31
|
-
sqlsaber/conversation/__init__.py,sha256=xa-1gX6NsZpVGg_LDrsZAtDtsDo5FZc1SO8gwtm_IPk,302
|
|
32
|
-
sqlsaber/conversation/manager.py,sha256=LDfmKGIMvTzsL7S0aXGWw6Ve54CHIeTGLU4qwes2NgU,7046
|
|
33
|
-
sqlsaber/conversation/models.py,sha256=fq4wpIB2yxLCQtsXhdpDji4FpscG2ayrOBACrNvgF14,3510
|
|
34
|
-
sqlsaber/conversation/storage.py,sha256=phpGEnZjXVFTmV5PalCKZpiO9VFHubMMfWA9OJCDbwc,11626
|
|
35
|
-
sqlsaber/database/__init__.py,sha256=a_gtKRJnZVO8-fEZI7g3Z8YnGa6Nio-5Y50PgVp07ss,176
|
|
36
|
-
sqlsaber/database/connection.py,sha256=sZVGNMzMwiM11GrsLLPwR8A5ugzJ5O0TCdkrt0KVRuI,15123
|
|
37
|
-
sqlsaber/database/resolver.py,sha256=RPXF5EoKzvQDDLmPGNHYd2uG_oNICH8qvUjBp6iXmNY,3348
|
|
38
|
-
sqlsaber/database/schema.py,sha256=OC93dnZkijCoVNqb6itSpQ2XsiZ85PjVUW-VZDwrPrk,25989
|
|
39
|
-
sqlsaber/mcp/__init__.py,sha256=COdWq7wauPBp5Ew8tfZItFzbcLDSEkHBJSMhxzy8C9c,112
|
|
40
|
-
sqlsaber/mcp/mcp.py,sha256=YH4crygqb5_Y94nsns6d-26FZCTlDPOh3tf-ghihzDM,4440
|
|
41
|
-
sqlsaber/memory/__init__.py,sha256=GiWkU6f6YYVV0EvvXDmFWe_CxarmDCql05t70MkTEWs,63
|
|
42
|
-
sqlsaber/memory/manager.py,sha256=p3fybMVfH-E4ApT1ZRZUnQIWSk9dkfUPCyfkmA0HALs,2739
|
|
43
|
-
sqlsaber/memory/storage.py,sha256=ne8szLlGj5NELheqLnI7zu21V8YS4rtpYGGC7tOmi-s,5745
|
|
44
|
-
sqlsaber/models/__init__.py,sha256=RJ7p3WtuSwwpFQ1Iw4_DHV2zzCtHqIzsjJzxv8kUjUE,287
|
|
45
|
-
sqlsaber/models/events.py,sha256=89SXKb5GGpH01yTr2kPEBhzp9xv35RFIYuFdAZSIPoE,721
|
|
46
|
-
sqlsaber/models/types.py,sha256=w-zk81V2dtveuteej36_o1fDK3So428j3P2rAejU62U,862
|
|
47
|
-
sqlsaber-0.14.0.dist-info/METADATA,sha256=xAj3wcH-3OJWud9grNykoiHhuVp2LIdMV5bbxNUQOEk,6877
|
|
48
|
-
sqlsaber-0.14.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
49
|
-
sqlsaber-0.14.0.dist-info/entry_points.txt,sha256=qEbOB7OffXPFgyJc7qEIJlMEX5RN9xdzLmWZa91zCQQ,162
|
|
50
|
-
sqlsaber-0.14.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
51
|
-
sqlsaber-0.14.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|