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 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__ = ["WizelitAgent", "DatabaseManager", "Job", "LogStreamer", "BaseModel", "JobModel", "JobLogModel", "JobStatus"]
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
- print(f"Warning: Failed to initialize log streamer: {e}")
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=76Dt-WxNbEJwOCPqu2P9AooVSQoGmc8-CH1fxIWJ5Lo,471
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=qkskmRRjhIooXVeyZHbH5q1OIp30zw29bBRUoqTPYLE,23476
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.30.dist-info/METADATA,sha256=zCb8i8TbnbAVCtHzcBxhgvQOlNIyNehCKQUWVCYpeqA,3297
12
- wizelit_sdk-0.1.30.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
13
- wizelit_sdk-0.1.30.dist-info/RECORD,,
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,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ wizelit-sdk = wizelit_sdk.cli:main
@@ -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.