soorma-core 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,209 @@
1
+ """
2
+ Utility functions for converting JSON Schema to Pydantic models.
3
+
4
+ This module provides helpers to dynamically generate Pydantic models from JSON Schema
5
+ definitions stored in the event registry, enabling type-safe event payload construction
6
+ and validation.
7
+ """
8
+ from typing import Any, Dict, Optional, Tuple, Type, Union, get_args, get_origin, List
9
+ from pydantic import create_model, Field, ValidationError
10
+ from soorma_common import BaseDTO, EventDefinition
11
+
12
+
13
+ def json_schema_to_pydantic(
14
+ schema: Dict[str, Any],
15
+ model_name: str = "DynamicModel",
16
+ base_class: Type[BaseDTO] = BaseDTO
17
+ ) -> Type[BaseDTO]:
18
+ """
19
+ Convert a JSON Schema (Draft 7) to a Pydantic model dynamically.
20
+
21
+ This function creates a Pydantic model class that inherits from BaseDTO,
22
+ providing automatic camelCase JSON serialization and validation.
23
+
24
+ Args:
25
+ schema: JSON Schema dictionary (must be type "object")
26
+ model_name: Name for the generated Pydantic model class
27
+ base_class: Base class to inherit from (default: BaseDTO)
28
+
29
+ Returns:
30
+ A dynamically created Pydantic model class
31
+
32
+ Raises:
33
+ ValueError: If schema is not of type "object" or is invalid
34
+
35
+ Example:
36
+ >>> schema = {
37
+ ... "type": "object",
38
+ ... "properties": {
39
+ ... "user_name": {"type": "string"},
40
+ ... "age": {"type": "integer"}
41
+ ... },
42
+ ... "required": ["user_name"]
43
+ ... }
44
+ >>> UserModel = json_schema_to_pydantic(schema, "User")
45
+ >>> user = UserModel(user_name="Alice", age=30)
46
+ >>> user.model_dump_json() # Will use camelCase: {"userName": "Alice", "age": 30}
47
+ """
48
+ if not isinstance(schema, dict):
49
+ raise ValueError("Schema must be a dictionary")
50
+
51
+ schema_type = schema.get("type")
52
+ if schema_type != "object":
53
+ raise ValueError(f"Only 'object' type schemas are supported, got: {schema_type}")
54
+
55
+ properties = schema.get("properties", {})
56
+ required_fields = set(schema.get("required", []))
57
+
58
+ if not properties:
59
+ # Empty object schema
60
+ return create_model(model_name, __base__=base_class)
61
+
62
+ # Build field definitions for Pydantic
63
+ field_definitions = {}
64
+
65
+ for field_name, field_schema in properties.items():
66
+ field_type = _json_type_to_python_type(field_schema, f"{model_name}_{field_name}")
67
+
68
+ # Determine if field is required
69
+ is_required = field_name in required_fields
70
+
71
+ # Get field metadata
72
+ description = field_schema.get("description", "")
73
+
74
+ # Set default value
75
+ if is_required:
76
+ default = ... # Ellipsis means required in Pydantic
77
+ else:
78
+ # Optional fields default to None
79
+ default = None
80
+ # Wrap type in Optional
81
+ field_type = Optional[field_type]
82
+
83
+ # Create Field with metadata
84
+ field_definitions[field_name] = (
85
+ field_type,
86
+ Field(default=default, description=description)
87
+ )
88
+
89
+ # Create the model dynamically
90
+ return create_model(
91
+ model_name,
92
+ __base__=base_class,
93
+ **field_definitions
94
+ )
95
+
96
+
97
+ def _json_type_to_python_type(
98
+ field_schema: Dict[str, Any],
99
+ nested_name: str = "NestedModel"
100
+ ) -> Type:
101
+ """
102
+ Recursively convert JSON Schema types to Python types.
103
+ """
104
+ json_type = field_schema.get("type")
105
+
106
+ if json_type == "string":
107
+ return str
108
+ elif json_type == "integer":
109
+ return int
110
+ elif json_type == "number":
111
+ return float
112
+ elif json_type == "boolean":
113
+ return bool
114
+ elif json_type == "array":
115
+ item_schema = field_schema.get("items", {})
116
+ item_type = _json_type_to_python_type(item_schema, f"{nested_name}_Item")
117
+ return List[item_type]
118
+ elif json_type == "object":
119
+ # Recursive call for nested objects
120
+ return json_schema_to_pydantic(field_schema, nested_name)
121
+ else:
122
+ # Fallback for unknown types or 'any'
123
+ return Any
124
+
125
+
126
+ def pydantic_to_json_schema(model_class: Type[BaseDTO]) -> Dict[str, Any]:
127
+ """
128
+ Convert a Pydantic model to JSON Schema.
129
+
130
+ Args:
131
+ model_class: Pydantic model class
132
+
133
+ Returns:
134
+ JSON Schema dictionary
135
+ """
136
+ return model_class.model_json_schema()
137
+
138
+
139
+ def create_event_models(event_def: EventDefinition) -> Tuple[Type[BaseDTO], Optional[Type[BaseDTO]]]:
140
+ """
141
+ Create Pydantic models for an event's payload and response.
142
+
143
+ Args:
144
+ event_def: Event definition from registry
145
+
146
+ Returns:
147
+ Tuple of (PayloadModel, ResponseModel)
148
+ ResponseModel will be None if no response schema is defined.
149
+ """
150
+ # Create payload model
151
+ payload_model_name = f"{_snake_to_pascal(event_def.event_name)}Payload"
152
+ payload_model = json_schema_to_pydantic(
153
+ event_def.payload_schema,
154
+ payload_model_name
155
+ )
156
+
157
+ # Create response model if exists
158
+ response_model = None
159
+ if event_def.response_schema:
160
+ response_model_name = f"{_snake_to_pascal(event_def.event_name)}Response"
161
+ response_model = json_schema_to_pydantic(
162
+ event_def.response_schema,
163
+ response_model_name
164
+ )
165
+
166
+ return payload_model, response_model
167
+
168
+
169
+ def validate_against_schema(data: Dict[str, Any], schema: Dict[str, Any]) -> Dict[str, Any]:
170
+ """
171
+ Validate a dictionary against a JSON schema using Pydantic.
172
+
173
+ Args:
174
+ data: Data to validate
175
+ schema: JSON schema to validate against
176
+
177
+ Returns:
178
+ Validated data (potentially with type coercion)
179
+
180
+ Raises:
181
+ ValidationError: If validation fails
182
+ """
183
+ DynamicModel = json_schema_to_pydantic(schema)
184
+ model_instance = DynamicModel.model_validate(data)
185
+ return model_instance.model_dump(by_alias=True)
186
+
187
+
188
+ def get_schema_field_names(schema: Dict[str, Any]) -> List[str]:
189
+ """Get list of field names from a schema."""
190
+ return list(schema.get("properties", {}).keys())
191
+
192
+
193
+ def get_required_fields(schema: Dict[str, Any]) -> List[str]:
194
+ """Get list of required fields from a schema."""
195
+ return schema.get("required", [])
196
+
197
+
198
+ def is_valid_json_schema(schema: Dict[str, Any]) -> bool:
199
+ """Check if a dictionary is a valid JSON schema object."""
200
+ return (
201
+ isinstance(schema, dict) and
202
+ schema.get("type") == "object" and
203
+ "properties" in schema
204
+ )
205
+
206
+
207
+ def _snake_to_pascal(snake_str: str) -> str:
208
+ """Convert snake_case to PascalCase."""
209
+ return "".join(word.capitalize() for word in snake_str.replace(".", "_").split("_"))
@@ -0,0 +1,454 @@
1
+ Metadata-Version: 2.4
2
+ Name: soorma-core
3
+ Version: 0.3.0
4
+ Summary: The Open Source Foundation for AI Agents. Powered by the DisCo (Distributed Cognition) architecture.
5
+ License: MIT
6
+ License-File: LICENSE.txt
7
+ Keywords: ai,agents,disco,distributed-systems,llm,orchestration
8
+ Author: Soorma AI
9
+ Author-email: founders@soorma.ai
10
+ Requires-Python: >=3.11,<4.0
11
+ Classifier: Development Status :: 2 - Pre-Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
20
+ Requires-Dist: httpx (>=0.26.0)
21
+ Requires-Dist: pydantic (>=2.0.0,<3.0.0)
22
+ Requires-Dist: rich (>=10.11.0)
23
+ Requires-Dist: soorma-common (>=0.3.0,<0.4.0)
24
+ Requires-Dist: typer (>=0.13.0)
25
+ Project-URL: Homepage, https://soorma.ai
26
+ Project-URL: Repository, https://github.com/soorma-ai/soorma-core
27
+ Description-Content-Type: text/markdown
28
+
29
+ # Soorma Core
30
+
31
+ **The Open Source Foundation for AI Agents.**
32
+
33
+ Soorma is an agentic infrastructure platform based on the **DisCo (Distributed Cognition)** architecture. It provides a standardized **Control Plane** (Gateway, Registry, Event Bus, State Tracker, Memory) for building production-grade multi-agent systems.
34
+
35
+ ## 🚧 Status: Pre-Alpha
36
+
37
+ We are currently building the core runtime. This package provides early access to the SDK and CLI.
38
+
39
+ **Join the waitlist:** [soorma.ai](https://soorma.ai)
40
+
41
+ ## Prerequisites
42
+
43
+ - **Python 3.11+** is required.
44
+
45
+ ## Quick Start
46
+
47
+ > **Note:** Docker images are not yet published. You must clone the repo and build locally.
48
+
49
+ ### 1. Clone Repository and Build Infrastructure
50
+
51
+ ```bash
52
+ # Clone the repository (needed for Docker images)
53
+ git clone https://github.com/soorma-ai/soorma-core.git
54
+ cd soorma-core
55
+
56
+ # Create and activate virtual environment
57
+ python -m venv .venv
58
+ source .venv/bin/activate # On Windows: .venv\Scripts\activate
59
+
60
+ # Install the SDK from PyPI
61
+ pip install soorma-core
62
+
63
+ # Build infrastructure containers (required first time)
64
+ soorma dev --build
65
+ ```
66
+
67
+ > 💡 **Alternative:** To install SDK from local source (for development/customization):
68
+ > ```bash
69
+ > pip install -e sdk/python
70
+ > ```
71
+
72
+ ### 2. Run the Hello World Example
73
+
74
+ ```bash
75
+ # Start infrastructure
76
+ soorma dev --infra-only
77
+
78
+ # In separate terminals:
79
+ python examples/hello-world/planner_agent.py
80
+ python examples/hello-world/worker_agent.py
81
+ python examples/hello-world/tool_agent.py
82
+ python examples/hello-world/client.py
83
+ ```
84
+
85
+ ### 3. Create a New Agent Project
86
+
87
+ ```bash
88
+ # Create a Worker agent (default)
89
+ soorma init my-worker
90
+
91
+ # Create a Planner agent (goal decomposition)
92
+ soorma init my-planner --type planner
93
+
94
+ # Create a Tool service (stateless operations)
95
+ soorma init my-tool --type tool
96
+
97
+ cd my-worker
98
+ python -m venv .venv
99
+ source .venv/bin/activate
100
+ pip install -e ".[dev]"
101
+ ```
102
+
103
+ ### Start Local Development
104
+
105
+ ```bash
106
+ # Start infrastructure and run your agent (auto-detects agent in current directory)
107
+ soorma dev
108
+ ```
109
+
110
+ Or run infrastructure separately:
111
+
112
+ ```bash
113
+ # Start only infrastructure
114
+ soorma dev --infra-only
115
+
116
+ # In another terminal, run your agent manually
117
+ python -m my_worker.agent
118
+ ```
119
+
120
+ ### Deploy to Soorma Cloud
121
+
122
+ ```bash
123
+ soorma deploy # Coming soon!
124
+ ```
125
+
126
+ ## The DisCo "Trinity"
127
+
128
+ Soorma implements the **DisCo (Distributed Cognition)** architecture with three domain service types:
129
+
130
+ | Type | Class | Purpose | Example Use Cases |
131
+ |------|-------|---------|-------------------|
132
+ | **Planner** | `Planner` | Strategic reasoning, goal decomposition | Research planning, workflow orchestration |
133
+ | **Worker** | `Worker` | Domain-specific task execution | Data processing, analysis, content generation |
134
+ | **Tool** | `Tool` | Atomic, stateless operations | API calls, calculations, file parsing |
135
+
136
+ ### Planner Agent
137
+
138
+ Planners are the "brain" - they receive high-level goals and decompose them into tasks:
139
+
140
+ ```python
141
+ from soorma import Planner, PlatformContext
142
+ from soorma.agents.planner import Goal, Plan, Task
143
+
144
+ planner = Planner(
145
+ name="research-planner",
146
+ description="Plans research workflows",
147
+ capabilities=["research_planning"],
148
+ )
149
+
150
+ @planner.on_goal("research.goal")
151
+ async def plan_research(goal: Goal, context: PlatformContext) -> Plan:
152
+ # Discover available workers
153
+ workers = await context.registry.find_all("paper_search")
154
+
155
+ # Decompose goal into tasks
156
+ return Plan(
157
+ goal=goal,
158
+ tasks=[
159
+ Task(name="search", assigned_to="paper_search", data=goal.data),
160
+ Task(name="summarize", assigned_to="summarizer", depends_on=["search"]),
161
+ ],
162
+ )
163
+
164
+ planner.run()
165
+ ```
166
+
167
+ ### Worker Agent
168
+
169
+ Workers are the "hands" - they execute domain-specific cognitive tasks:
170
+
171
+ ```python
172
+ from soorma import Worker, PlatformContext
173
+ from soorma.agents.worker import TaskContext
174
+
175
+ worker = Worker(
176
+ name="research-worker",
177
+ description="Searches and analyzes papers",
178
+ capabilities=["paper_search", "citation_analysis"],
179
+ )
180
+
181
+ @worker.on_task("paper_search")
182
+ async def search_papers(task: TaskContext, context: PlatformContext):
183
+ # Report progress
184
+ await task.report_progress(0.5, "Searching...")
185
+
186
+ # Access shared memory
187
+ prefs = await context.memory.retrieve(f"user:{task.session_id}:prefs")
188
+
189
+ # Your task logic
190
+ results = await search_academic_papers(task.data["query"], prefs)
191
+
192
+ # Store for downstream workers
193
+ await context.memory.store(f"results:{task.task_id}", results)
194
+
195
+ return {"papers": results, "count": len(results)}
196
+
197
+ worker.run()
198
+ ```
199
+
200
+ ### Tool Service
201
+
202
+ Tools are the "utilities" - stateless, deterministic operations:
203
+
204
+ ```python
205
+ from soorma import Tool, PlatformContext
206
+ from soorma.agents.tool import ToolRequest
207
+
208
+ tool = Tool(
209
+ name="calculator",
210
+ description="Performs calculations",
211
+ capabilities=["arithmetic", "unit_conversion"],
212
+ )
213
+
214
+ @tool.on_invoke("calculate")
215
+ async def calculate(request: ToolRequest, context: PlatformContext):
216
+ expression = request.data["expression"]
217
+ result = safe_eval(expression)
218
+ return {"result": result, "expression": expression}
219
+
220
+ tool.run()
221
+ ```
222
+
223
+ ## Platform Context
224
+
225
+ Every handler receives a `PlatformContext` that provides access to all platform services:
226
+
227
+ ```python
228
+ @worker.on_task("my_task")
229
+ async def handler(task: TaskContext, context: PlatformContext):
230
+ # Service Discovery
231
+ tool = await context.registry.find("calculator")
232
+
233
+ # Shared Memory
234
+ data = await context.memory.retrieve(f"cache:{task.data['key']}")
235
+ await context.memory.store("result:123", {"value": 42})
236
+
237
+ # Event Publishing
238
+ await context.bus.publish("task.completed", {"result": "done"})
239
+
240
+ # Progress Tracking (automatic for workers, manual available)
241
+ await context.tracker.emit_progress(
242
+ plan_id=task.plan_id,
243
+ task_id=task.task_id,
244
+ status="running",
245
+ progress=0.75,
246
+ )
247
+ ```
248
+
249
+ | Service | Purpose | Methods |
250
+ |---------|---------|---------|
251
+ | `context.registry` | Service Discovery | `find()`, `register()`, `query_schemas()` |
252
+ | `context.memory` | Distributed State | `retrieve()`, `store()`, `search()` |
253
+ | `context.bus` | Event Choreography | `publish()`, `subscribe()`, `request()` |
254
+ | `context.tracker` | Observability | `start_plan()`, `emit_progress()`, `complete_task()` |
255
+
256
+ ## Advanced Usage
257
+
258
+ ### Structured Agent Registration
259
+
260
+ For simple agents, you can pass a list of strings as capabilities. For more control, use `AgentCapability` objects to define schemas and descriptions.
261
+
262
+ ```python
263
+ from soorma import Agent, Context
264
+ from soorma.models import AgentCapability
265
+
266
+ async def main(context: Context):
267
+ # Define structured capabilities
268
+ capabilities = [
269
+ AgentCapability(
270
+ name="analyze_sentiment",
271
+ description="Analyzes the sentiment of a given text",
272
+ input_schema={
273
+ "type": "object",
274
+ "properties": {
275
+ "text": {"type": "string", "description": "Text to analyze"}
276
+ },
277
+ "required": ["text"]
278
+ },
279
+ output_schema={
280
+ "type": "object",
281
+ "properties": {
282
+ "score": {"type": "number", "description": "Sentiment score (-1 to 1)"}
283
+ }
284
+ }
285
+ )
286
+ ]
287
+
288
+ # Register with structured capabilities
289
+ await context.register(
290
+ name="sentiment-analyzer",
291
+ capabilities=capabilities
292
+ )
293
+
294
+ # ... rest of agent logic
295
+ ```
296
+
297
+ ### Event Registration
298
+
299
+ You can register custom event schemas that your agent produces or consumes.
300
+
301
+ ```python
302
+ from soorma.models import EventDefinition
303
+
304
+ async def main(context: Context):
305
+ # Register a custom event schema
306
+ await context.registry.register_event(
307
+ EventDefinition(
308
+ event_type="analysis.completed",
309
+ description="Emitted when text analysis is complete",
310
+ schema={
311
+ "type": "object",
312
+ "properties": {
313
+ "text_id": {"type": "string"},
314
+ "result": {"type": "object"}
315
+ },
316
+ "required": ["text_id", "result"]
317
+ }
318
+ )
319
+ )
320
+ ```
321
+
322
+ ### AI Integration
323
+
324
+ The SDK provides specialized tools for AI agents (like LLMs) to interact with the system dynamically.
325
+
326
+ #### AI Event Toolkit
327
+
328
+ The `EventToolkit` allows agents to discover events and generate valid payloads without hardcoded DTOs.
329
+
330
+ ```python
331
+ from soorma.ai.event_toolkit import EventToolkit
332
+
333
+ async with EventToolkit() as toolkit:
334
+ # 1. Discover events
335
+ events = await toolkit.discover_events(topic="action-requests")
336
+
337
+ # 2. Get detailed info
338
+ info = await toolkit.get_event_info("web.search.request")
339
+
340
+ # 3. Create validated payload (handles schema validation)
341
+ payload = await toolkit.create_payload(
342
+ "web.search.request",
343
+ {"query": "AI trends 2025"}
344
+ )
345
+ ```
346
+
347
+ #### OpenAI Function Calling
348
+
349
+ You can expose Registry capabilities directly to OpenAI-compatible LLMs using `get_tool_definitions()`.
350
+
351
+ ```python
352
+ from soorma.ai.tools import get_tool_definitions, execute_ai_tool
353
+ import openai
354
+
355
+ # 1. Get tool definitions
356
+ tools = get_tool_definitions()
357
+
358
+ # 2. Call LLM
359
+ response = await openai.ChatCompletion.create(
360
+ model="gpt-4",
361
+ messages=[{"role": "user", "content": "Find events related to search"}],
362
+ tools=tools
363
+ )
364
+
365
+ # 3. Execute tool calls
366
+ tool_call = response.choices[0].message.tool_calls[0]
367
+ result = await execute_ai_tool(
368
+ tool_call.function.name,
369
+ json.loads(tool_call.function.arguments)
370
+ )
371
+ ```
372
+
373
+ ## CLI Commands
374
+
375
+ > **First-time setup:** Run `soorma dev --build --infra-only` to build Docker images before using other commands.
376
+
377
+ | Command | Description |
378
+ |---------|-------------|
379
+ | `soorma init <name>` | Scaffold a new agent project |
380
+ | `soorma init <name> --type planner` | Create a Planner agent |
381
+ | `soorma init <name> --type worker` | Create a Worker agent (default) |
382
+ | `soorma init <name> --type tool` | Create a Tool service |
383
+ | `soorma dev` | Start infra + run agent with hot reload |
384
+ | `soorma dev --build` | Build service images from source first |
385
+ | `soorma dev --build --infra-only` | Build images without running agent (first-time setup) |
386
+ | `soorma dev --infra-only` | Start infra without running agent |
387
+ | `soorma dev --stop` | Stop the development stack |
388
+ | `soorma dev --status` | Show stack status |
389
+ | `soorma dev --logs` | View infrastructure logs |
390
+ | `soorma deploy` | Deploy to Soorma Cloud (coming soon) |
391
+ | `soorma version` | Show CLI version |
392
+
393
+ ## How `soorma dev` Works
394
+
395
+ The CLI implements an **"Infra in Docker, Code on Host"** pattern for optimal DX:
396
+
397
+ ```
398
+ ┌─────────────────────────────────────────────────────────────┐
399
+ │ Your Machine │
400
+ ├─────────────────────────────────────────────────────────────┤
401
+ │ Docker Containers (Infrastructure) │
402
+ │ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
403
+ │ │ Registry │ │ NATS │ │ Event Service │ │
404
+ │ │ :8081 │ │ :4222 │ │ :8082 │ │
405
+ │ └──────────┘ └──────────┘ └───────────────┘ │
406
+ │ ▲ ▲ ▲ │
407
+ │ └────── localhost ───────────┘ │
408
+ │ ▲ │
409
+ │ ┌──────────────────┴──────────────────┐ │
410
+ │ │ Native Python (Your Agent) │ │
411
+ │ │ • Hot reload on file change │ │
412
+ │ │ • Full debugger support │ │
413
+ │ │ • Auto-connects to Event Service │ │
414
+ │ └─────────────────────────────────────┘ │
415
+ └─────────────────────────────────────────────────────────────┘
416
+ ```
417
+
418
+ **Benefits:**
419
+ - ⚡ **Fast iteration** - No docker build cycle, instant reload
420
+ - 🔍 **Debuggable** - Attach VS Code/PyCharm debugger
421
+ - 🎯 **Production parity** - Same infrastructure as prod
422
+
423
+ ## Event-Driven Architecture
424
+
425
+ Unlike single-threaded agent loops, Soorma enables **Autonomous Choreography** via events:
426
+
427
+ ```
428
+ Client Planner Worker Tool
429
+ │ │ │ │
430
+ │ goal.submitted │ │ │
431
+ │────────────────────>│ │ │
432
+ │ │ action.request │ │
433
+ │ │───────────────────>│ │
434
+ │ │ │ tool.request │
435
+ │ │ │──────────────────>│
436
+ │ │ │ tool.response │
437
+ │ │ │<──────────────────│
438
+ │ │ action.result │ │
439
+ │ │<───────────────────│ │
440
+ │ goal.completed │ │ │
441
+ │<────────────────────│ │ │
442
+ ```
443
+
444
+ ## Roadmap
445
+
446
+ * [x] **v0.1.0**: Core SDK & CLI (`soorma init`, `soorma dev`)
447
+ * [x] **v0.1.1**: Event Service & DisCo Trinity (Planner, Worker, Tool)
448
+ * [x] **v0.2.0**: Subscriber Groups & Unified Versioning
449
+ * [ ] **v0.3.0**: Memory Service & State Tracker
450
+ * [ ] **v1.0.0**: Enterprise GA
451
+
452
+ ## License
453
+
454
+ MIT
@@ -0,0 +1,23 @@
1
+ soorma/__init__.py,sha256=uJOnSx0HA_LVzNL2Xh20aU39CPqPDbEZE3vbbNZs9yE,3822
2
+ soorma/agents/__init__.py,sha256=wG-kw7_CABdvSwRnt23xJiPfa-XFndofebk2jAO_Qh0,568
3
+ soorma/agents/base.py,sha256=ZvAy1TV7fMS3RC7XNFqdgSbnYQ_Guk4chiHrlq8qIbE,17629
4
+ soorma/agents/planner.py,sha256=l_1IGoX_Rq45YCAlc-bApJgtRLEQXc1W6_L6IyVBvbY,12378
5
+ soorma/agents/tool.py,sha256=36662wVahv3xU2SMzytlY1zQ6lK-Q-XT3OwaXIbggLY,12042
6
+ soorma/agents/worker.py,sha256=C3DiqJrA25ZQMToRP5sa15K0LU7Vy_v_YtOwQeGgMJE,12473
7
+ soorma/ai/event_toolkit.py,sha256=DYTjacpsspc7-DEhx4_wqlv-_src3uKuKFrA6BQPmOE,9841
8
+ soorma/ai/tools.py,sha256=M2V-mW2-VN9EC-C8ExPY1_mj3wsVn5Zn6i8iy0PhDuk,10524
9
+ soorma/cli/__init__.py,sha256=hOZIt11jO7S0a0oaMnjqac1ImW6N-WlqroCRZogHQ9w,110
10
+ soorma/cli/commands/__init__.py,sha256=LBGQrRtXXHuH-AJTls2ixSPdKvdniPdklE5Kg9RCQ_I,29
11
+ soorma/cli/commands/dev.py,sha256=IveJ_mdwZd5-CHS0XyyIGoHydrrvB7GWVKMgBS-vf50,26261
12
+ soorma/cli/commands/init.py,sha256=CYcs6Xp9eD33jtdqaeo2eGnHBPBjfVG-iphK916nqBc,18246
13
+ soorma/cli/main.py,sha256=T8Iby9dI8qXE-rQWMCRM9jSi0tZ1TyHTM2NamMGZlSA,1192
14
+ soorma/context.py,sha256=5XyweaidTeA-HbXERUp0MVjqLl8Diyani7l3I6V2G4U,27549
15
+ soorma/events.py,sha256=pfJEYoBbrt0AnrzJHlkw7Aeim5M6ozfADmDsPI3MMWs,17838
16
+ soorma/models.py,sha256=tL7y35RFAc68y2RC39otVZSYLRhKLD-vtBLM5oqG-b4,475
17
+ soorma/registry/client.py,sha256=XVPtoY31oqM-a47_6FpmoWF-D4CQ6llPHtGums4IQWk,5846
18
+ soorma/utils/schema_utils.py,sha256=87CKf8k6Wxaoqn31Soio9HMKqrV7QvTKAk7kbK9rITc,6696
19
+ soorma_core-0.3.0.dist-info/METADATA,sha256=nocKehjMb4oymU5CNW07QQ8LiPwSeMzlKCReyE9AqnM,15678
20
+ soorma_core-0.3.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
21
+ soorma_core-0.3.0.dist-info/entry_points.txt,sha256=dS70Bhj_cKGGZssAqp9cYDeq0xUPisUPOQ_x4pLrlb8,47
22
+ soorma_core-0.3.0.dist-info/licenses/LICENSE.txt,sha256=I770PdJI7JQBfJbPw5UpEzBLIMys-xDM7xO0P_ZZG0Y,1066
23
+ soorma_core-0.3.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.2.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ soorma=soorma.cli.main:main
3
+