swarmkit 0.1.34__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.
swarmkit/schema.py ADDED
@@ -0,0 +1,107 @@
1
+ """Schema utilities for Pydantic models, dataclasses, and JSON Schema.
2
+
3
+ Provides unified detection, conversion, and validation for schema types.
4
+ Uses Pydantic's TypeAdapter for dataclass support.
5
+ """
6
+
7
+ import dataclasses
8
+ from typing import Any, Dict, Optional
9
+
10
+
11
+ # =============================================================================
12
+ # DETECTION
13
+ # =============================================================================
14
+
15
+
16
+ def is_pydantic_model(obj: Any) -> bool:
17
+ """Check if object is a Pydantic model class."""
18
+ try:
19
+ from pydantic import BaseModel
20
+ return isinstance(obj, type) and issubclass(obj, BaseModel)
21
+ except ImportError:
22
+ return False
23
+
24
+
25
+ def is_dataclass(obj: Any) -> bool:
26
+ """Check if object is a dataclass."""
27
+ return dataclasses.is_dataclass(obj) and isinstance(obj, type)
28
+
29
+
30
+ def is_json_schema(obj: Any) -> bool:
31
+ """Check if object is a JSON Schema dict."""
32
+ return isinstance(obj, dict)
33
+
34
+
35
+ # =============================================================================
36
+ # CONVERSION
37
+ # =============================================================================
38
+
39
+
40
+ def to_json_schema(schema: Any) -> Optional[Dict[str, Any]]:
41
+ """Convert a schema to JSON Schema format.
42
+
43
+ Supports:
44
+ - Dict (JSON Schema) - passed through
45
+ - Pydantic models - uses model_json_schema()
46
+ - Dataclasses - uses Pydantic TypeAdapter
47
+
48
+ Args:
49
+ schema: Pydantic model, dataclass, or JSON Schema dict
50
+
51
+ Returns:
52
+ JSON Schema dict, or None if schema is None
53
+ """
54
+ if schema is None:
55
+ return None
56
+
57
+ if is_json_schema(schema):
58
+ return schema
59
+
60
+ if is_pydantic_model(schema):
61
+ return schema.model_json_schema()
62
+
63
+ if is_dataclass(schema):
64
+ from pydantic import TypeAdapter
65
+ return TypeAdapter(schema).json_schema()
66
+
67
+ raise TypeError(
68
+ f"Schema must be a Pydantic model, dataclass, or dict. "
69
+ f"Got {type(schema).__name__}"
70
+ )
71
+
72
+
73
+ # =============================================================================
74
+ # VALIDATION
75
+ # =============================================================================
76
+
77
+
78
+ def validate_and_parse(
79
+ raw_json: str,
80
+ schema: Any,
81
+ strict: bool = False,
82
+ ) -> Any:
83
+ """Validate JSON string and parse into schema type.
84
+
85
+ Args:
86
+ raw_json: Raw JSON string to validate
87
+ schema: Pydantic model or dataclass (returns instance)
88
+ strict: Use strict validation mode
89
+
90
+ Returns:
91
+ Model/dataclass instance, or None for dict schemas
92
+
93
+ Raises:
94
+ ValidationError: If validation fails
95
+ """
96
+ if schema is None or is_json_schema(schema):
97
+ # JSON Schema validation is handled by TS SDK
98
+ return None
99
+
100
+ if is_pydantic_model(schema):
101
+ return schema.model_validate_json(raw_json, strict=strict)
102
+
103
+ if is_dataclass(schema):
104
+ from pydantic import TypeAdapter
105
+ return TypeAdapter(schema).validate_json(raw_json, strict=strict)
106
+
107
+ return None
@@ -0,0 +1,75 @@
1
+ """Swarm abstractions for parallel AI agent execution."""
2
+
3
+ from .swarm import Swarm
4
+ from .types import (
5
+ FileMap,
6
+ SwarmConfig,
7
+ BestOfConfig,
8
+ VerifyConfig,
9
+ IndexedMeta,
10
+ ReduceMeta,
11
+ JudgeMeta,
12
+ VerifyMeta,
13
+ BaseMeta,
14
+ OperationType,
15
+ Prompt,
16
+ PromptFn,
17
+ ItemInput,
18
+ SchemaType,
19
+ JudgeDecision,
20
+ VerifyDecision,
21
+ # Callback types
22
+ OnCandidateCompleteCallback,
23
+ OnJudgeCompleteCallback,
24
+ OnWorkerCompleteCallback,
25
+ OnVerifierCompleteCallback,
26
+ )
27
+ from .results import (
28
+ SwarmResult,
29
+ SwarmResultList,
30
+ ReduceResult,
31
+ BestOfResult,
32
+ BestOfInfo,
33
+ VerifyInfo,
34
+ is_swarm_result,
35
+ SWARM_RESULT_BRAND,
36
+ )
37
+
38
+ __all__ = [
39
+ # Main class
40
+ 'Swarm',
41
+ # Config types
42
+ 'SwarmConfig',
43
+ 'BestOfConfig',
44
+ 'VerifyConfig',
45
+ # Result types
46
+ 'SwarmResult',
47
+ 'SwarmResultList',
48
+ 'ReduceResult',
49
+ 'BestOfResult',
50
+ 'BestOfInfo',
51
+ 'VerifyInfo',
52
+ # Meta types
53
+ 'IndexedMeta',
54
+ 'ReduceMeta',
55
+ 'JudgeMeta',
56
+ 'VerifyMeta',
57
+ 'BaseMeta',
58
+ 'OperationType',
59
+ # Other types
60
+ 'FileMap',
61
+ 'Prompt',
62
+ 'PromptFn',
63
+ 'ItemInput',
64
+ 'SchemaType',
65
+ 'JudgeDecision',
66
+ 'VerifyDecision',
67
+ # Callback types
68
+ 'OnCandidateCompleteCallback',
69
+ 'OnJudgeCompleteCallback',
70
+ 'OnWorkerCompleteCallback',
71
+ 'OnVerifierCompleteCallback',
72
+ # Helpers
73
+ 'is_swarm_result',
74
+ 'SWARM_RESULT_BRAND',
75
+ ]
@@ -0,0 +1,140 @@
1
+ """Result types for Swarm abstractions."""
2
+
3
+ from dataclasses import dataclass, field
4
+ from typing import Any, Dict, Generic, List, Literal, Optional, TypeVar, Union
5
+
6
+ from .types import FileMap, IndexedMeta, ReduceMeta, JudgeMeta, VerifyMeta
7
+
8
+
9
+ T = TypeVar('T')
10
+
11
+ # Brand for runtime detection of SwarmResult (for chaining)
12
+ SWARM_RESULT_BRAND = "__swarm_result__"
13
+
14
+
15
+ # =============================================================================
16
+ # SWARM RESULT
17
+ # =============================================================================
18
+
19
+ @dataclass
20
+ class SwarmResult(Generic[T]):
21
+ """Result from a single worker (map, filter, bestof candidate).
22
+
23
+ Status meanings:
24
+ - "success": Positive outcome (agent succeeded / condition passed)
25
+ - "filtered": Neutral outcome (evaluated but didn't pass condition) - filter only
26
+ - "error": Negative outcome (agent error)
27
+ """
28
+ status: Literal["success", "filtered", "error"]
29
+ data: Optional[T]
30
+ files: FileMap
31
+ meta: IndexedMeta
32
+ error: Optional[str] = None
33
+ raw_data: Optional[str] = None
34
+ best_of: Optional['BestOfInfo'] = None
35
+ verify: Optional['VerifyInfo'] = None
36
+
37
+ # Brand for runtime detection (used by is_swarm_result() function)
38
+ __swarm_result__: bool = field(default=True, repr=False)
39
+
40
+
41
+ @dataclass
42
+ class BestOfInfo(Generic[T]):
43
+ """BestOf information attached to SwarmResult when map used bestOf option."""
44
+ winner_index: int
45
+ judge_reasoning: str
46
+ judge_meta: JudgeMeta
47
+ candidates: List[SwarmResult[T]]
48
+
49
+
50
+ @dataclass
51
+ class VerifyInfo:
52
+ """Verification info attached to results when verify option used."""
53
+ passed: bool
54
+ reasoning: str
55
+ verify_meta: VerifyMeta
56
+ attempts: int
57
+
58
+
59
+ # =============================================================================
60
+ # SWARM RESULT LIST
61
+ # =============================================================================
62
+
63
+ class SwarmResultList(List[SwarmResult[T]], Generic[T]):
64
+ """List of SwarmResults with helper properties.
65
+
66
+ Extends list so all normal list operations work.
67
+
68
+ Getters:
69
+ - `.success` - items with positive outcome
70
+ - `.filtered` - items that didn't pass condition (filter only)
71
+ - `.error` - items that encountered errors
72
+
73
+ Chaining examples:
74
+ - `swarm.reduce(results.success, ...)` - forward only successful
75
+ - `swarm.reduce([*results.success, *results.filtered], ...)` - forward all evaluated
76
+ """
77
+
78
+ @property
79
+ def success(self) -> List[SwarmResult[T]]:
80
+ """Returns items with status 'success'."""
81
+ return [r for r in self if r.status == "success"]
82
+
83
+ @property
84
+ def filtered(self) -> List[SwarmResult[T]]:
85
+ """Returns items with status 'filtered' (didn't pass condition)."""
86
+ return [r for r in self if r.status == "filtered"]
87
+
88
+ @property
89
+ def error(self) -> List[SwarmResult[T]]:
90
+ """Returns items with status 'error'."""
91
+ return [r for r in self if r.status == "error"]
92
+
93
+ @classmethod
94
+ def from_results(cls, results: List[SwarmResult[T]]) -> 'SwarmResultList[T]':
95
+ """Create SwarmResultList from a list of SwarmResults."""
96
+ result_list = cls()
97
+ result_list.extend(results)
98
+ return result_list
99
+
100
+
101
+ # =============================================================================
102
+ # REDUCE RESULT
103
+ # =============================================================================
104
+
105
+ @dataclass
106
+ class ReduceResult(Generic[T]):
107
+ """Result from reduce operation."""
108
+ status: Literal["success", "error"]
109
+ data: Optional[T]
110
+ files: FileMap
111
+ meta: ReduceMeta
112
+ error: Optional[str] = None
113
+ raw_data: Optional[str] = None
114
+ verify: Optional['VerifyInfo'] = None
115
+
116
+
117
+ # =============================================================================
118
+ # BESTOF RESULT
119
+ # =============================================================================
120
+
121
+ @dataclass
122
+ class BestOfResult(Generic[T]):
123
+ """Result from bestOf operation."""
124
+ winner: SwarmResult[T]
125
+ winner_index: int
126
+ judge_reasoning: str
127
+ judge_meta: JudgeMeta
128
+ candidates: List[SwarmResult[T]]
129
+
130
+
131
+ # =============================================================================
132
+ # HELPER FUNCTIONS
133
+ # =============================================================================
134
+
135
+ def is_swarm_result(obj: Any) -> bool:
136
+ """Check if an object is a SwarmResult (for chaining detection)."""
137
+ return (
138
+ isinstance(obj, SwarmResult) or
139
+ (hasattr(obj, SWARM_RESULT_BRAND) and getattr(obj, SWARM_RESULT_BRAND) is True)
140
+ )