wizelit-sdk 0.1.30__py3-none-any.whl → 0.1.32__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.
- wizelit_sdk/__init__.py +37 -1
- wizelit_sdk/agent_wrapper/agent_wrapper.py +7 -1
- wizelit_sdk/cli.py +337 -0
- wizelit_sdk/exceptions.py +206 -0
- wizelit_sdk-0.1.32.dist-info/METADATA +222 -0
- {wizelit_sdk-0.1.30.dist-info → wizelit_sdk-0.1.32.dist-info}/RECORD +8 -5
- wizelit_sdk-0.1.32.dist-info/entry_points.txt +2 -0
- wizelit_sdk-0.1.30.dist-info/METADATA +0 -124
- {wizelit_sdk-0.1.30.dist-info → wizelit_sdk-0.1.32.dist-info}/WHEEL +0 -0
wizelit_sdk/__init__.py
CHANGED
|
@@ -6,6 +6,42 @@ from wizelit_sdk.agent_wrapper.job import Job
|
|
|
6
6
|
from wizelit_sdk.agent_wrapper.streaming import LogStreamer
|
|
7
7
|
from wizelit_sdk.models.base import BaseModel
|
|
8
8
|
from wizelit_sdk.models.job import JobModel, JobLogModel, JobStatus
|
|
9
|
+
from wizelit_sdk.exceptions import (
|
|
10
|
+
WizelitSDKException,
|
|
11
|
+
AgentInitializationError,
|
|
12
|
+
SignatureValidationError,
|
|
13
|
+
JobExecutionError,
|
|
14
|
+
JobNotFoundError,
|
|
15
|
+
ToolRegistrationError,
|
|
16
|
+
DatabaseManagerError,
|
|
17
|
+
StreamingError,
|
|
18
|
+
ContextVariableError,
|
|
19
|
+
InvalidConfigError,
|
|
20
|
+
TransportError,
|
|
21
|
+
TimeoutError,
|
|
22
|
+
)
|
|
9
23
|
|
|
10
|
-
__all__ = [
|
|
24
|
+
__all__ = [
|
|
25
|
+
"WizelitAgent",
|
|
26
|
+
"DatabaseManager",
|
|
27
|
+
"Job",
|
|
28
|
+
"LogStreamer",
|
|
29
|
+
"BaseModel",
|
|
30
|
+
"JobModel",
|
|
31
|
+
"JobLogModel",
|
|
32
|
+
"JobStatus",
|
|
33
|
+
# Exceptions
|
|
34
|
+
"WizelitSDKException",
|
|
35
|
+
"AgentInitializationError",
|
|
36
|
+
"SignatureValidationError",
|
|
37
|
+
"JobExecutionError",
|
|
38
|
+
"JobNotFoundError",
|
|
39
|
+
"ToolRegistrationError",
|
|
40
|
+
"DatabaseManagerError",
|
|
41
|
+
"StreamingError",
|
|
42
|
+
"ContextVariableError",
|
|
43
|
+
"InvalidConfigError",
|
|
44
|
+
"TransportError",
|
|
45
|
+
"TimeoutError",
|
|
46
|
+
]
|
|
11
47
|
|
|
@@ -13,6 +13,9 @@ from wizelit_sdk.agent_wrapper.signature_validation import (
|
|
|
13
13
|
bind_and_validate_arguments,
|
|
14
14
|
ensure_type_hints,
|
|
15
15
|
)
|
|
16
|
+
from wizelit_sdk.exceptions import (
|
|
17
|
+
StreamingError,
|
|
18
|
+
)
|
|
16
19
|
|
|
17
20
|
# Local Transport literal to avoid import issues when fastmcp.types is unavailable
|
|
18
21
|
Transport = Literal["stdio", "http", "sse", "streamable-http"]
|
|
@@ -92,7 +95,10 @@ class WizelitAgent:
|
|
|
92
95
|
except ImportError:
|
|
93
96
|
print("Warning: redis package not installed. Log streaming disabled.")
|
|
94
97
|
except Exception as e:
|
|
95
|
-
|
|
98
|
+
raise StreamingError(
|
|
99
|
+
"Failed to initialize log streaming",
|
|
100
|
+
f"Could not connect to Redis at {redis_url}: {str(e)}"
|
|
101
|
+
)
|
|
96
102
|
|
|
97
103
|
print(
|
|
98
104
|
f"WizelitAgent initialized with name: {name}, transport: {transport}, host: {host}, port: {port}"
|
wizelit_sdk/cli.py
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
"""Command-line utilities for Wizelit SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from textwrap import dedent
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
TRANSPORT_CHOICES = ["streamable-http", "sse", "stdio", "http"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _slugify(value: str) -> str:
|
|
16
|
+
value = value.strip().lower()
|
|
17
|
+
value = re.sub(r"[^a-z0-9]+", "-", value)
|
|
18
|
+
value = value.strip("-")
|
|
19
|
+
if not value:
|
|
20
|
+
raise click.ClickException("Agent name must contain letters or numbers.")
|
|
21
|
+
return value
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _write_file(path: Path, content: str, force: bool) -> None:
|
|
25
|
+
if path.exists() and not force:
|
|
26
|
+
raise click.ClickException(
|
|
27
|
+
f"File already exists: {path}. Use --force to overwrite."
|
|
28
|
+
)
|
|
29
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
30
|
+
path.write_text(content, encoding="utf-8")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _render_main_py(
|
|
34
|
+
agent_name: str, transport: str, host: str, port: int
|
|
35
|
+
) -> str:
|
|
36
|
+
return dedent(
|
|
37
|
+
f'''"""Wizelit Agent Scaffold
|
|
38
|
+
Generated by wizelit-agent CLI.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
from wizelit_sdk.agent_wrapper import WizelitAgent
|
|
42
|
+
|
|
43
|
+
mcp = WizelitAgent(
|
|
44
|
+
"{agent_name}",
|
|
45
|
+
transport="{transport}",
|
|
46
|
+
host="{host}",
|
|
47
|
+
port={port},
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@mcp.ingest(
|
|
52
|
+
is_long_running=False,
|
|
53
|
+
description="Describe your tool here.",
|
|
54
|
+
response_handling={{"mode": "json"}},
|
|
55
|
+
)
|
|
56
|
+
def example_tool(text: str) -> dict:
|
|
57
|
+
"""Example tool."""
|
|
58
|
+
return {{"echo": text}}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
if __name__ == "__main__":
|
|
62
|
+
mcp.run()
|
|
63
|
+
'''
|
|
64
|
+
).lstrip()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _render_readme(agent_name: str) -> str:
|
|
68
|
+
return dedent(
|
|
69
|
+
f"""
|
|
70
|
+
# {agent_name}
|
|
71
|
+
|
|
72
|
+
Generated Wizelit agent scaffold.
|
|
73
|
+
|
|
74
|
+
## Run
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
python main.py
|
|
78
|
+
```
|
|
79
|
+
"""
|
|
80
|
+
).lstrip()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _render_env_example() -> str:
|
|
84
|
+
return dedent(
|
|
85
|
+
"""
|
|
86
|
+
# Example environment variables
|
|
87
|
+
REDIS_URL=redis://localhost:6379
|
|
88
|
+
ENABLE_LOG_STREAMING=true
|
|
89
|
+
|
|
90
|
+
# AWS (if using Bedrock)
|
|
91
|
+
AWS_ACCESS_KEY_ID=
|
|
92
|
+
AWS_SECRET_ACCESS_KEY=
|
|
93
|
+
AWS_REGION=us-east-1
|
|
94
|
+
"""
|
|
95
|
+
).lstrip()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _render_requirements(template: str) -> str:
|
|
99
|
+
# Always include the SDK and click for CLI-based scaffolds
|
|
100
|
+
base = ["wizelit-sdk", "click>=8.1.0"]
|
|
101
|
+
if template == "fast":
|
|
102
|
+
extras = []
|
|
103
|
+
elif template == "slow":
|
|
104
|
+
extras = ["redis>=4.5.0"]
|
|
105
|
+
else: # hybrid
|
|
106
|
+
extras = ["redis>=4.5.0"]
|
|
107
|
+
return "\n".join(base + extras) + "\n"
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _render_main_for_template(agent_name: str, template: str) -> str:
|
|
111
|
+
# Fast agent: synchronous/simple
|
|
112
|
+
if template == "fast":
|
|
113
|
+
return dedent(
|
|
114
|
+
f'''
|
|
115
|
+
"""Fast Wizelit Agent
|
|
116
|
+
Generated by wizelit CLI
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
from wizelit_sdk.agent_wrapper import WizelitAgent
|
|
120
|
+
|
|
121
|
+
mcp = WizelitAgent(
|
|
122
|
+
"{agent_name}",
|
|
123
|
+
transport="streamable-http",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@mcp.ingest(is_long_running=False, description="Fast sync tool")
|
|
128
|
+
def analyze(text: str) -> dict:
|
|
129
|
+
"""A fast synchronous tool example."""
|
|
130
|
+
return {{"echo": text}}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
if __name__ == "__main__":
|
|
134
|
+
mcp.run()
|
|
135
|
+
'''
|
|
136
|
+
).lstrip()
|
|
137
|
+
|
|
138
|
+
# Slow agent: long-running async example
|
|
139
|
+
if template == "slow":
|
|
140
|
+
return dedent(
|
|
141
|
+
f'''
|
|
142
|
+
"""Slow Wizelit Agent (long-running)
|
|
143
|
+
Generated by wizelit CLI
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
import asyncio
|
|
147
|
+
from wizelit_sdk.agent_wrapper import WizelitAgent, Job
|
|
148
|
+
|
|
149
|
+
mcp = WizelitAgent(
|
|
150
|
+
"{agent_name}",
|
|
151
|
+
transport="streamable-http",
|
|
152
|
+
enable_streaming=True,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@mcp.ingest(is_long_running=True, description="Long-running refactor")
|
|
157
|
+
async def long_task(code: str, job: Job) -> dict:
|
|
158
|
+
job.logger.info("Starting long-running task")
|
|
159
|
+
# Simulate work and progress
|
|
160
|
+
for i in range(3):
|
|
161
|
+
await asyncio.sleep(1)
|
|
162
|
+
job.logger.info(f"Progress: {{i+1}}/3")
|
|
163
|
+
return {{"result": "done"}}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
if __name__ == "__main__":
|
|
167
|
+
mcp.run()
|
|
168
|
+
'''
|
|
169
|
+
).lstrip()
|
|
170
|
+
|
|
171
|
+
# Hybrid: both examples present
|
|
172
|
+
return dedent(
|
|
173
|
+
f'''
|
|
174
|
+
"""Hybrid Wizelit Agent
|
|
175
|
+
Generated by wizelit CLI
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
import asyncio
|
|
179
|
+
from wizelit_sdk.agent_wrapper import WizelitAgent, Job
|
|
180
|
+
|
|
181
|
+
mcp = WizelitAgent(
|
|
182
|
+
"{agent_name}",
|
|
183
|
+
transport="streamable-http",
|
|
184
|
+
enable_streaming=True,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@mcp.ingest(is_long_running=False, description="Fast helper")
|
|
189
|
+
def quick(text: str) -> dict:
|
|
190
|
+
return {{"echo": text}}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@mcp.ingest(is_long_running=True, description="Slow worker")
|
|
194
|
+
async def worker(payload: str, job: Job) -> dict:
|
|
195
|
+
job.logger.info("Hybrid worker starting")
|
|
196
|
+
await asyncio.sleep(1)
|
|
197
|
+
return {{"status": "ok"}}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
if __name__ == "__main__":
|
|
201
|
+
mcp.run()
|
|
202
|
+
'''
|
|
203
|
+
).lstrip()
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@click.group()
|
|
207
|
+
def cli() -> None:
|
|
208
|
+
"""Wizelit SDK command-line tools."""
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@cli.command("scaffold")
|
|
212
|
+
@click.argument("name")
|
|
213
|
+
@click.option(
|
|
214
|
+
"--output-dir",
|
|
215
|
+
"-o",
|
|
216
|
+
type=click.Path(file_okay=False, dir_okay=True, path_type=Path),
|
|
217
|
+
default=Path.cwd(),
|
|
218
|
+
show_default="current directory",
|
|
219
|
+
)
|
|
220
|
+
@click.option(
|
|
221
|
+
"--transport",
|
|
222
|
+
type=click.Choice(TRANSPORT_CHOICES),
|
|
223
|
+
default="streamable-http",
|
|
224
|
+
show_default=True,
|
|
225
|
+
)
|
|
226
|
+
@click.option("--host", default="0.0.0.0", show_default=True)
|
|
227
|
+
@click.option("--port", default=8080, show_default=True, type=int)
|
|
228
|
+
@click.option("--force", is_flag=True, help="Overwrite existing files.")
|
|
229
|
+
def scaffold(
|
|
230
|
+
name: str,
|
|
231
|
+
output_dir: Path,
|
|
232
|
+
transport: str,
|
|
233
|
+
host: str,
|
|
234
|
+
port: int,
|
|
235
|
+
force: bool,
|
|
236
|
+
) -> None:
|
|
237
|
+
"""Scaffold a new Wizelit agent project."""
|
|
238
|
+
slug = _slugify(name)
|
|
239
|
+
project_dir = output_dir / slug
|
|
240
|
+
|
|
241
|
+
project_dir.mkdir(parents=True, exist_ok=True)
|
|
242
|
+
|
|
243
|
+
_write_file(project_dir / "main.py", _render_main_py(name, transport, host, port), force)
|
|
244
|
+
_write_file(project_dir / "README.md", _render_readme(name), force)
|
|
245
|
+
# Ensure generated scaffold includes click as a runtime dependency
|
|
246
|
+
_write_file(
|
|
247
|
+
project_dir / "requirements.txt",
|
|
248
|
+
"wizelit-sdk\nclick>=8.1.0\n",
|
|
249
|
+
force,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
click.echo(f"✅ Scaffold created at: {project_dir}")
|
|
253
|
+
click.echo("Next steps:")
|
|
254
|
+
click.echo(" 1) Install dependencies: pip install -r requirements.txt")
|
|
255
|
+
click.echo(" 2) Run the agent: python main.py")
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@cli.command("init")
|
|
259
|
+
@click.argument("name")
|
|
260
|
+
@click.option("--template", type=click.Choice(["fast", "slow", "hybrid"]), default="fast")
|
|
261
|
+
@click.option(
|
|
262
|
+
"--output-dir",
|
|
263
|
+
"-o",
|
|
264
|
+
type=click.Path(file_okay=False, dir_okay=True, path_type=Path),
|
|
265
|
+
default=Path.cwd(),
|
|
266
|
+
show_default="current directory",
|
|
267
|
+
)
|
|
268
|
+
@click.option("--force", is_flag=True, help="Overwrite existing files.")
|
|
269
|
+
def init(name: str, template: str, output_dir: Path, force: bool) -> None:
|
|
270
|
+
"""Initialize a new Wizelit agent project using a template."""
|
|
271
|
+
slug = _slugify(name)
|
|
272
|
+
project_dir = output_dir / slug
|
|
273
|
+
project_dir.mkdir(parents=True, exist_ok=True)
|
|
274
|
+
|
|
275
|
+
# Write main.py for the selected template
|
|
276
|
+
_write_file(project_dir / "main.py", _render_main_for_template(name, template), force)
|
|
277
|
+
_write_file(project_dir / "README.md", _render_readme(name), force)
|
|
278
|
+
_write_file(project_dir / "requirements.txt", _render_requirements(template), force)
|
|
279
|
+
_write_file(project_dir / ".env.example", _render_env_example(), force)
|
|
280
|
+
|
|
281
|
+
click.echo(f"✅ Project initialized at: {project_dir}")
|
|
282
|
+
click.echo("Next steps:")
|
|
283
|
+
click.echo(" 1) Install dependencies: pip install -r requirements.txt")
|
|
284
|
+
click.echo(" 2) Run the agent: python main.py")
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@cli.command("validate")
|
|
288
|
+
@click.argument("path", type=click.Path(file_okay=True, dir_okay=True, path_type=Path), default=Path.cwd())
|
|
289
|
+
def validate(path: Path) -> None:
|
|
290
|
+
"""Validate a Wizelit agent project structure."""
|
|
291
|
+
if path.is_file():
|
|
292
|
+
project_dir = path.parent
|
|
293
|
+
else:
|
|
294
|
+
project_dir = path
|
|
295
|
+
|
|
296
|
+
required = ["main.py", "requirements.txt", "README.md"]
|
|
297
|
+
missing = [p for p in required if not (project_dir / p).exists()]
|
|
298
|
+
if missing:
|
|
299
|
+
click.echo(f"❌ Missing files: {missing}")
|
|
300
|
+
raise click.Abort()
|
|
301
|
+
click.echo("✅ Project looks valid")
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
@cli.command("list-tools")
|
|
305
|
+
@click.argument("path", type=click.Path(file_okay=True, dir_okay=True, path_type=Path), default=Path.cwd())
|
|
306
|
+
def list_tools(path: Path) -> None:
|
|
307
|
+
"""List tools (functions decorated with @mcp.ingest) in a project."""
|
|
308
|
+
if path.is_file():
|
|
309
|
+
project_dir = path.parent
|
|
310
|
+
else:
|
|
311
|
+
project_dir = path
|
|
312
|
+
|
|
313
|
+
py_files = list(project_dir.glob("*.py"))
|
|
314
|
+
tools = []
|
|
315
|
+
for f in py_files:
|
|
316
|
+
text = f.read_text(encoding="utf-8")
|
|
317
|
+
if "@mcp.ingest" in text:
|
|
318
|
+
# naive extraction: look for def <name>( after decorator
|
|
319
|
+
for line in text.splitlines():
|
|
320
|
+
if line.strip().startswith("def "):
|
|
321
|
+
name = line.strip().split()[1].split("(")[0]
|
|
322
|
+
tools.append((f.name, name))
|
|
323
|
+
|
|
324
|
+
if not tools:
|
|
325
|
+
click.echo("No tools found (no @mcp.ingest decorators detected).")
|
|
326
|
+
return
|
|
327
|
+
|
|
328
|
+
for file, name in tools:
|
|
329
|
+
click.echo(f"- {name} (in {file})")
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def main() -> None:
|
|
333
|
+
cli()
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
if __name__ == "__main__":
|
|
337
|
+
main()
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom exceptions for Wizelit SDK with helpful error messages and suggestions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class WizelitSDKException(Exception):
|
|
7
|
+
"""Base exception class for all Wizelit SDK errors."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, message: str, suggestion: str = ""):
|
|
10
|
+
self.message = message
|
|
11
|
+
self.suggestion = suggestion
|
|
12
|
+
full_message = message
|
|
13
|
+
if suggestion:
|
|
14
|
+
full_message = f"{message}\n💡 Suggestion: {suggestion}"
|
|
15
|
+
super().__init__(full_message)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AgentInitializationError(WizelitSDKException):
|
|
19
|
+
"""Raised when WizelitAgent cannot be initialized."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, reason: str = "", original_error: str = ""):
|
|
22
|
+
message = "Failed to initialize WizelitAgent"
|
|
23
|
+
if reason:
|
|
24
|
+
message += f": {reason}"
|
|
25
|
+
if original_error:
|
|
26
|
+
message += f" ({original_error})"
|
|
27
|
+
suggestion = (
|
|
28
|
+
"1. Verify all required dependencies are installed\n"
|
|
29
|
+
"2. Check that the name parameter is provided\n"
|
|
30
|
+
"3. Verify the transport mode is valid (sse, http, streamable-http, stdio)\n"
|
|
31
|
+
"4. Check that host and port are available and not in use\n"
|
|
32
|
+
"5. Review the initialization code for configuration errors"
|
|
33
|
+
)
|
|
34
|
+
super().__init__(message, suggestion)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class SignatureValidationError(WizelitSDKException):
|
|
38
|
+
"""Raised when a function signature doesn't meet requirements."""
|
|
39
|
+
|
|
40
|
+
def __init__(self, function_name: str, reason: str = ""):
|
|
41
|
+
message = f"Signature validation failed for function '{function_name}'"
|
|
42
|
+
if reason:
|
|
43
|
+
message += f": {reason}"
|
|
44
|
+
suggestion = (
|
|
45
|
+
f"1. Ensure all parameters of '{function_name}' have type hints\n"
|
|
46
|
+
f"2. Verify parameter names match between definition and usage\n"
|
|
47
|
+
f"3. Check that the function signature is compatible with the ingest decorator\n"
|
|
48
|
+
f"4. Ensure complex types are properly imported and defined\n"
|
|
49
|
+
f"5. Review the decorator parameters for compatibility"
|
|
50
|
+
)
|
|
51
|
+
super().__init__(message, suggestion)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class JobExecutionError(WizelitSDKException):
|
|
55
|
+
"""Raised when a job fails during execution."""
|
|
56
|
+
|
|
57
|
+
def __init__(self, job_id: str, reason: str = "", original_error: str = ""):
|
|
58
|
+
message = f"Job execution failed for job_id '{job_id}'"
|
|
59
|
+
if reason:
|
|
60
|
+
message += f": {reason}"
|
|
61
|
+
if original_error:
|
|
62
|
+
message += f" ({original_error})"
|
|
63
|
+
suggestion = (
|
|
64
|
+
"1. Check the job logs for detailed error information\n"
|
|
65
|
+
"2. Verify job inputs are valid and complete\n"
|
|
66
|
+
"3. Check if the underlying tool/function has dependencies\n"
|
|
67
|
+
"4. Try running the job again with the same inputs\n"
|
|
68
|
+
"5. Check application logs and database logs for more context"
|
|
69
|
+
)
|
|
70
|
+
super().__init__(message, suggestion)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class JobNotFoundError(WizelitSDKException):
|
|
74
|
+
"""Raised when a job cannot be found."""
|
|
75
|
+
|
|
76
|
+
def __init__(self, job_id: str):
|
|
77
|
+
message = f"Job not found: {job_id}"
|
|
78
|
+
suggestion = (
|
|
79
|
+
"1. Verify the job_id is correct and complete\n"
|
|
80
|
+
"2. Check if the job has expired or been deleted\n"
|
|
81
|
+
"3. Verify the job was created in the current session\n"
|
|
82
|
+
"4. Check the database for job records\n"
|
|
83
|
+
"5. Review job retention policies"
|
|
84
|
+
)
|
|
85
|
+
super().__init__(message, suggestion)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class ToolRegistrationError(WizelitSDKException):
|
|
89
|
+
"""Raised when a tool cannot be registered with the MCP server."""
|
|
90
|
+
|
|
91
|
+
def __init__(self, tool_name: str, reason: str = ""):
|
|
92
|
+
message = f"Failed to register tool '{tool_name}' with MCP server"
|
|
93
|
+
if reason:
|
|
94
|
+
message += f": {reason}"
|
|
95
|
+
suggestion = (
|
|
96
|
+
f"1. Verify '{tool_name}' function is properly decorated with @ingest\n"
|
|
97
|
+
f"2. Check that function name is unique across all registered tools\n"
|
|
98
|
+
f"3. Verify function signature is valid with type hints\n"
|
|
99
|
+
f"4. Check for duplicate tool registrations\n"
|
|
100
|
+
f"5. Ensure the FastMCP server is properly initialized"
|
|
101
|
+
)
|
|
102
|
+
super().__init__(message, suggestion)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class DatabaseManagerError(WizelitSDKException):
|
|
106
|
+
"""Raised when database operations fail."""
|
|
107
|
+
|
|
108
|
+
def __init__(self, operation: str, reason: str = ""):
|
|
109
|
+
message = f"Database operation failed: {operation}"
|
|
110
|
+
if reason:
|
|
111
|
+
message += f" ({reason})"
|
|
112
|
+
suggestion = (
|
|
113
|
+
"1. Verify the database is running and accessible\n"
|
|
114
|
+
"2. Check database connection parameters (host, port, credentials)\n"
|
|
115
|
+
"3. Verify the database has sufficient disk space\n"
|
|
116
|
+
"4. Check if the database tables are properly initialized\n"
|
|
117
|
+
"5. Review database logs for detailed error information"
|
|
118
|
+
)
|
|
119
|
+
super().__init__(message, suggestion)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class StreamingError(WizelitSDKException):
|
|
123
|
+
"""Raised when log streaming fails."""
|
|
124
|
+
|
|
125
|
+
def __init__(self, reason: str = "", original_error: str = ""):
|
|
126
|
+
message = "Error in log streaming"
|
|
127
|
+
if reason:
|
|
128
|
+
message += f": {reason}"
|
|
129
|
+
if original_error:
|
|
130
|
+
message += f" ({original_error})"
|
|
131
|
+
suggestion = (
|
|
132
|
+
"1. Verify Redis is running and accessible\n"
|
|
133
|
+
"2. Check REDIS_URL environment variable is set correctly\n"
|
|
134
|
+
"3. Verify network connectivity to Redis\n"
|
|
135
|
+
"4. Check Redis logs for connection errors\n"
|
|
136
|
+
"5. Log streaming is optional - the SDK will continue without it"
|
|
137
|
+
)
|
|
138
|
+
super().__init__(message, suggestion)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class ContextVariableError(WizelitSDKException):
|
|
142
|
+
"""Raised when context variable operations fail."""
|
|
143
|
+
|
|
144
|
+
def __init__(self, variable_name: str, reason: str = ""):
|
|
145
|
+
message = f"Error accessing context variable '{variable_name}'"
|
|
146
|
+
if reason:
|
|
147
|
+
message += f": {reason}"
|
|
148
|
+
suggestion = (
|
|
149
|
+
f"1. Ensure '{variable_name}' is set before accessing\n"
|
|
150
|
+
f"2. Verify the context is active in the current async task\n"
|
|
151
|
+
f"3. Check if using the decorator or dependency injection correctly\n"
|
|
152
|
+
f"4. Ensure context propagation across async calls\n"
|
|
153
|
+
f"5. Review context variable usage documentation"
|
|
154
|
+
)
|
|
155
|
+
super().__init__(message, suggestion)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class InvalidConfigError(WizelitSDKException):
|
|
159
|
+
"""Raised when configuration is invalid or missing."""
|
|
160
|
+
|
|
161
|
+
def __init__(self, config_key: str, expected_type: str = "", reason: str = ""):
|
|
162
|
+
message = f"Invalid configuration for '{config_key}'"
|
|
163
|
+
if expected_type:
|
|
164
|
+
message += f" (expected: {expected_type})"
|
|
165
|
+
if reason:
|
|
166
|
+
message += f": {reason}"
|
|
167
|
+
suggestion = (
|
|
168
|
+
f"1. Verify {config_key} is set in environment variables\n"
|
|
169
|
+
f"2. Check the value format and type\n"
|
|
170
|
+
f"3. Review configuration documentation for valid values\n"
|
|
171
|
+
f"4. Check .env file or deployment configuration\n"
|
|
172
|
+
f"5. Restart the application after fixing configuration"
|
|
173
|
+
)
|
|
174
|
+
super().__init__(message, suggestion)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class TransportError(WizelitSDKException):
|
|
178
|
+
"""Raised when transport/communication errors occur."""
|
|
179
|
+
|
|
180
|
+
def __init__(self, transport_type: str, reason: str = ""):
|
|
181
|
+
message = f"Transport error with '{transport_type}'"
|
|
182
|
+
if reason:
|
|
183
|
+
message += f": {reason}"
|
|
184
|
+
suggestion = (
|
|
185
|
+
f"1. Verify the {transport_type} transport is properly configured\n"
|
|
186
|
+
f"2. Check network connectivity and firewall rules\n"
|
|
187
|
+
f"3. Verify server ports are open and accessible\n"
|
|
188
|
+
f"4. Check if there are proxy or routing issues\n"
|
|
189
|
+
f"5. Review transport-specific logs for detailed information"
|
|
190
|
+
)
|
|
191
|
+
super().__init__(message, suggestion)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class TimeoutError(WizelitSDKException):
|
|
195
|
+
"""Raised when an operation exceeds the timeout limit."""
|
|
196
|
+
|
|
197
|
+
def __init__(self, operation: str, timeout_seconds: float):
|
|
198
|
+
message = f"Operation '{operation}' exceeded timeout of {timeout_seconds} seconds"
|
|
199
|
+
suggestion = (
|
|
200
|
+
f"1. The {operation} took too long to complete\n"
|
|
201
|
+
f"2. Check if there are resource constraints (CPU, memory)\n"
|
|
202
|
+
f"3. Simplify the job inputs or query\n"
|
|
203
|
+
f"4. Check application and system logs for bottlenecks\n"
|
|
204
|
+
f"5. Consider increasing timeout if the operation is expected to be slow"
|
|
205
|
+
)
|
|
206
|
+
super().__init__(message, suggestion)
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wizelit-sdk
|
|
3
|
+
Version: 0.1.32
|
|
4
|
+
Summary: Wizelit Agent Wrapper - Internal utility package
|
|
5
|
+
Author-email: Your Name <your.email@company.com>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: asyncpg>=0.26.0
|
|
8
|
+
Requires-Dist: click>=8.1.0
|
|
9
|
+
Requires-Dist: fastmcp>=0.1.0
|
|
10
|
+
Requires-Dist: redis>=4.5.0
|
|
11
|
+
Requires-Dist: sqlalchemy>=1.4
|
|
12
|
+
Requires-Dist: typeguard>=4.3.0
|
|
13
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: black>=22.0.0; extra == 'dev'
|
|
16
|
+
Requires-Dist: build>=1.0.0; extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
18
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
19
|
+
Provides-Extra: streaming
|
|
20
|
+
Requires-Dist: redis>=4.5.0; extra == 'streaming'
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# wizelit-sdk
|
|
24
|
+
|
|
25
|
+
Internal utility package for Wizelit Agent operations.
|
|
26
|
+
|
|
27
|
+
> **New to Wizelit?** Start with the [**Quick Start Guide**](./QUICKSTART.md) to build your first agent in under 30 minutes!
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
### Install from PyPI
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv pip install wizelit-sdk
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Add to pyproject.toml
|
|
38
|
+
|
|
39
|
+
```toml
|
|
40
|
+
[project]
|
|
41
|
+
dependencies = [
|
|
42
|
+
"wizelit-sdk"
|
|
43
|
+
]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quickstart
|
|
47
|
+
|
|
48
|
+
1. Install the package (see above).
|
|
49
|
+
2. Configure environment variables (see Configuration).
|
|
50
|
+
3. Import and use the SDK from your app.
|
|
51
|
+
|
|
52
|
+
### CLI
|
|
53
|
+
|
|
54
|
+
The package also installs a small command-line tool named `wizelit-sdk` which helps scaffold and manage agent projects.
|
|
55
|
+
|
|
56
|
+
Install and run the CLI:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Install package (global or in virtualenv)
|
|
60
|
+
pip install wizelit-sdk
|
|
61
|
+
|
|
62
|
+
# Create a new project using a template (fast|slow|hybrid)
|
|
63
|
+
wizelit-sdk init "My Agent" --template hybrid
|
|
64
|
+
|
|
65
|
+
# Alternative (without wrapper):
|
|
66
|
+
python -m wizelit_sdk.cli init "My Agent" --template hybrid
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Useful commands:
|
|
70
|
+
|
|
71
|
+
- `wizelit-sdk init <name> [--template fast|slow|hybrid]` — scaffold a new agent project
|
|
72
|
+
- `wizelit-sdk scaffold <name>` — basic scaffold (older command)
|
|
73
|
+
- `wizelit-sdk validate [path]` — validate project structure
|
|
74
|
+
- `wizelit-sdk list-tools [path]` — list functions decorated with `@mcp.ingest`
|
|
75
|
+
|
|
76
|
+
If you are developing locally, install editable and use the wrapper from your virtualenv:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# from repo root
|
|
80
|
+
pip install -e .
|
|
81
|
+
source .venv/bin/activate
|
|
82
|
+
wizelit-sdk init "My Agent"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Usage
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from wizelit_agent_wrapper import your_module
|
|
89
|
+
|
|
90
|
+
# Use the wrapper
|
|
91
|
+
result = your_module.function()
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## SDK Guide
|
|
95
|
+
|
|
96
|
+
### Basic import patterns
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from wizelit_sdk import database, exceptions
|
|
100
|
+
from wizelit_sdk.agent_wrapper import agent_wrapper
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Initialize and call
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
# Example: create a wrapper and call a method
|
|
107
|
+
wrapper = agent_wrapper.WizelitAgentWrapper()
|
|
108
|
+
result = wrapper.run()
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Error handling
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from wizelit_sdk.exceptions import WizelitError
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
wrapper.run()
|
|
118
|
+
except WizelitError as exc:
|
|
119
|
+
# handle SDK-specific errors
|
|
120
|
+
print(exc)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Configuration
|
|
124
|
+
|
|
125
|
+
The SDK reads database configuration from the hosting application's environment. Provide these variables in the consuming project (e.g., via your app's .env or deployment secrets):
|
|
126
|
+
|
|
127
|
+
- POSTGRES_USER
|
|
128
|
+
- POSTGRES_PASSWORD
|
|
129
|
+
- POSTGRES_HOST
|
|
130
|
+
- POSTGRES_PORT
|
|
131
|
+
- POSTGRES_DB
|
|
132
|
+
|
|
133
|
+
You can also supply a full connection string via `DATABASE_URL` (overrides the individual fields). If using streaming/logging with Redis, set `REDIS_HOST`, `REDIS_PORT`, and optionally `REDIS_PASSWORD`.
|
|
134
|
+
|
|
135
|
+
## Development
|
|
136
|
+
|
|
137
|
+
### Setup Development Environment
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Clone repository
|
|
141
|
+
git clone https://github.com/your-org/wizelit-sdk.git
|
|
142
|
+
cd wizelit-sdk
|
|
143
|
+
|
|
144
|
+
# Set up environment
|
|
145
|
+
make setup
|
|
146
|
+
|
|
147
|
+
# Activate virtual environment
|
|
148
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
149
|
+
|
|
150
|
+
# Install in development mode
|
|
151
|
+
make install-dev
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Available Make Commands
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
make setup # Set up development environment
|
|
158
|
+
make install # Install package (production mode)
|
|
159
|
+
make install-dev # Install in development mode
|
|
160
|
+
make test # Run tests
|
|
161
|
+
make lint # Run code linting
|
|
162
|
+
make format # Format code with black
|
|
163
|
+
make check # Run tests and linting
|
|
164
|
+
make clean # Clean build artifacts
|
|
165
|
+
make build # Build package
|
|
166
|
+
make release x.x.x # Create new release (updates version, tags, pushes)
|
|
167
|
+
make tag VERSION=x.x.x # Create and push git tag
|
|
168
|
+
make push # Push code and tags to remote
|
|
169
|
+
make publish # Publish package (run checks, build, push to remote)
|
|
170
|
+
make publish-pypi # Publish package to public PyPI
|
|
171
|
+
make publish-artifactory # Publish package to private Artifactory/PyPI
|
|
172
|
+
make version # Show current version
|
|
173
|
+
make versions # List all available versions
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Deploy to PyPI
|
|
177
|
+
|
|
178
|
+
Use the built-in Makefile target (recommended):
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
make publish-pypi
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
This target will:
|
|
185
|
+
|
|
186
|
+
1. Verify the git working tree is clean.
|
|
187
|
+
2. Run tests and linting (`make check`).
|
|
188
|
+
3. Build the package (`make build`).
|
|
189
|
+
4. Upload the artifacts in `dist/` to PyPI via `twine`.
|
|
190
|
+
|
|
191
|
+
Optional release/tag flow (before publishing):
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Interactive release flow (updates version, tags, pushes)
|
|
195
|
+
make release x.x.x
|
|
196
|
+
|
|
197
|
+
# Or tag a specific version
|
|
198
|
+
make tag VERSION=x.x.x
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Notes:
|
|
202
|
+
|
|
203
|
+
- Ensure your PyPI credentials are configured locally (e.g., via $HOME/.pypirc or your preferred environment variables).
|
|
204
|
+
- The package version must be unique on PyPI; if a version already exists, bump it and rebuild.
|
|
205
|
+
|
|
206
|
+
## Contributing
|
|
207
|
+
|
|
208
|
+
1. Create a feature branch
|
|
209
|
+
2. Make your changes
|
|
210
|
+
3. Run tests and linting: `make check`
|
|
211
|
+
4. Commit your changes
|
|
212
|
+
5. Push and create a pull request
|
|
213
|
+
|
|
214
|
+
## Versioning
|
|
215
|
+
|
|
216
|
+
We use [Semantic Versioning](https://semver.org/):
|
|
217
|
+
|
|
218
|
+
- **MAJOR** version for incompatible API changes
|
|
219
|
+
- **MINOR** version for new functionality (backward compatible)
|
|
220
|
+
- **PATCH** version for bug fixes
|
|
221
|
+
|
|
222
|
+
See [CHANGELOG.md](CHANGELOG.md) for version history.
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
wizelit_sdk/__init__.py,sha256=
|
|
1
|
+
wizelit_sdk/__init__.py,sha256=GRV3STJaNUg2KelKmvU60nhpYMdQ5lX0_FQyV_e5g1I,1168
|
|
2
|
+
wizelit_sdk/cli.py,sha256=9leN1OHMj9IszbEtmldJDd09epg5KCji6RiQ6xjzraI,9541
|
|
2
3
|
wizelit_sdk/database.py,sha256=HzvMY-KZQBkGs-Ey_wKAIPOJEb5BqGjEi98Tip7CQBo,4830
|
|
4
|
+
wizelit_sdk/exceptions.py,sha256=KHkexTbD5t05nD-t9RnrJIFcqOsATBOUX9y5uHVfQeE,8557
|
|
3
5
|
wizelit_sdk/agent_wrapper/__init__.py,sha256=srVcHZfvpf3q8m2nzIST6Ofl2V8Vv5GRtcNXudOLiD8,333
|
|
4
|
-
wizelit_sdk/agent_wrapper/agent_wrapper.py,sha256=
|
|
6
|
+
wizelit_sdk/agent_wrapper/agent_wrapper.py,sha256=2IE1RXTpwzJJMnpEgetU8OCkR7txG_NMqJ-1W-rv9j0,23650
|
|
5
7
|
wizelit_sdk/agent_wrapper/job.py,sha256=jW2Cl7QvSgZDUqWqZSND-V1XphGdISJuh9ViHgCn7iU,13770
|
|
6
8
|
wizelit_sdk/agent_wrapper/signature_validation.py,sha256=Njplwofw36jXoWgBooaZCbwhkf72pR-UoRQ3Q6-biro,3729
|
|
7
9
|
wizelit_sdk/agent_wrapper/streaming.py,sha256=l7SbvPuQYMdGO38t1upyI5wTVdd5eB-2BSwU-BQSlvc,6673
|
|
8
10
|
wizelit_sdk/models/__init__.py,sha256=UB7nfHoE6hGcjfzy7w8AmuKVmYrTg9wIgGjG8GWziJ0,143
|
|
9
11
|
wizelit_sdk/models/base.py,sha256=11XyxLUG0VjdiNxe4zmzGDUjKEOsjSvUjA8yaQgfCa0,758
|
|
10
12
|
wizelit_sdk/models/job.py,sha256=HD8ohVqzakC8J7VAwmh8UCi_BLLiqx85TbR0FjO2rlg,2494
|
|
11
|
-
wizelit_sdk-0.1.
|
|
12
|
-
wizelit_sdk-0.1.
|
|
13
|
-
wizelit_sdk-0.1.
|
|
13
|
+
wizelit_sdk-0.1.32.dist-info/METADATA,sha256=94NCVGl52cRNM7Z7z93l-jwh-OAdmMx-uBx_dPymBAg,5787
|
|
14
|
+
wizelit_sdk-0.1.32.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
15
|
+
wizelit_sdk-0.1.32.dist-info/entry_points.txt,sha256=XRtYie5Jhxb5xv0Kda2OwA1k6fuf4utEttjo29sJ2FM,53
|
|
16
|
+
wizelit_sdk-0.1.32.dist-info/RECORD,,
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: wizelit-sdk
|
|
3
|
-
Version: 0.1.30
|
|
4
|
-
Summary: Wizelit Agent Wrapper - Internal utility package
|
|
5
|
-
Author-email: Your Name <your.email@company.com>
|
|
6
|
-
Requires-Python: >=3.10
|
|
7
|
-
Requires-Dist: asyncpg>=0.26.0
|
|
8
|
-
Requires-Dist: fastmcp>=0.1.0
|
|
9
|
-
Requires-Dist: redis>=4.5.0
|
|
10
|
-
Requires-Dist: sqlalchemy>=1.4
|
|
11
|
-
Requires-Dist: typeguard>=4.3.0
|
|
12
|
-
Requires-Dist: typing-extensions>=4.0.0
|
|
13
|
-
Provides-Extra: dev
|
|
14
|
-
Requires-Dist: black>=22.0.0; extra == 'dev'
|
|
15
|
-
Requires-Dist: build>=1.0.0; extra == 'dev'
|
|
16
|
-
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
17
|
-
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
18
|
-
Provides-Extra: streaming
|
|
19
|
-
Requires-Dist: redis>=4.5.0; extra == 'streaming'
|
|
20
|
-
Description-Content-Type: text/markdown
|
|
21
|
-
|
|
22
|
-
# wizelit-sdk
|
|
23
|
-
|
|
24
|
-
Internal utility package for Wizelit Agent operations.
|
|
25
|
-
|
|
26
|
-
## Installation
|
|
27
|
-
|
|
28
|
-
### Install from Git Repository
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
# Install latest version from main branch
|
|
32
|
-
uv pip install git+https://github.com/your-org/wizelit-sdk.git
|
|
33
|
-
|
|
34
|
-
# Install specific version
|
|
35
|
-
uv pip install git+https://github.com/your-org/wizelit-sdk.git@v0.1.0
|
|
36
|
-
|
|
37
|
-
# Install with SSH (Recommended for Private Repos)
|
|
38
|
-
uv pip install git+ssh://git@github.com/your-org/wizelit-sdk.git@v0.1.0
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Add to pyproject.toml
|
|
42
|
-
|
|
43
|
-
```toml
|
|
44
|
-
[project]
|
|
45
|
-
dependencies = [
|
|
46
|
-
"wizelit-sdk @ git+ssh://git@github.com/your-org/wizelit-sdk.git@v0.1.0"
|
|
47
|
-
]
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Usage
|
|
51
|
-
|
|
52
|
-
```python
|
|
53
|
-
from wizelit_agent_wrapper import your_module
|
|
54
|
-
|
|
55
|
-
# Use the wrapper
|
|
56
|
-
result = your_module.function()
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Configuration
|
|
60
|
-
|
|
61
|
-
The SDK reads database configuration from the hosting application's environment. Provide these variables in the consuming project (e.g., via your app's .env or deployment secrets):
|
|
62
|
-
|
|
63
|
-
- POSTGRES_USER
|
|
64
|
-
- POSTGRES_PASSWORD
|
|
65
|
-
- POSTGRES_HOST
|
|
66
|
-
- POSTGRES_PORT
|
|
67
|
-
- POSTGRES_DB
|
|
68
|
-
|
|
69
|
-
You can also supply a full connection string via `DATABASE_URL` (overrides the individual fields). If using streaming/logging with Redis, set `REDIS_HOST`, `REDIS_PORT`, and optionally `REDIS_PASSWORD`.
|
|
70
|
-
|
|
71
|
-
## Development
|
|
72
|
-
|
|
73
|
-
### Setup Development Environment
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
# Clone repository
|
|
77
|
-
git clone https://github.com/your-org/wizelit-sdk.git
|
|
78
|
-
cd wizelit-sdk
|
|
79
|
-
|
|
80
|
-
# Set up environment
|
|
81
|
-
make setup
|
|
82
|
-
|
|
83
|
-
# Activate virtual environment
|
|
84
|
-
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
85
|
-
|
|
86
|
-
# Install in development mode
|
|
87
|
-
make install-dev
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### Available Make Commands
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
make setup # Set up development environment
|
|
94
|
-
make install-dev # Install in development mode
|
|
95
|
-
make test # Run tests
|
|
96
|
-
make format # Format code with black
|
|
97
|
-
make lint # Lint code with ruff
|
|
98
|
-
make check # Run tests and linting
|
|
99
|
-
make clean # Clean build artifacts
|
|
100
|
-
make build # Build package
|
|
101
|
-
make release # Create new release (interactive)
|
|
102
|
-
make tag VERSION=x.x.x # Create specific version tag
|
|
103
|
-
make push # Push code and tags
|
|
104
|
-
make version # Show current version
|
|
105
|
-
make versions # List all available versions
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## Contributing
|
|
109
|
-
|
|
110
|
-
1. Create a feature branch
|
|
111
|
-
2. Make your changes
|
|
112
|
-
3. Run tests and linting: `make check`
|
|
113
|
-
4. Commit your changes
|
|
114
|
-
5. Push and create a pull request
|
|
115
|
-
|
|
116
|
-
## Versioning
|
|
117
|
-
|
|
118
|
-
We use [Semantic Versioning](https://semver.org/):
|
|
119
|
-
|
|
120
|
-
- **MAJOR** version for incompatible API changes
|
|
121
|
-
- **MINOR** version for new functionality (backward compatible)
|
|
122
|
-
- **PATCH** version for bug fixes
|
|
123
|
-
|
|
124
|
-
See [CHANGELOG.md](CHANGELOG.md) for version history.
|
|
File without changes
|