jaf-py 2.5.10__py3-none-any.whl → 2.5.11__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.
- jaf/__init__.py +154 -57
- jaf/a2a/__init__.py +42 -21
- jaf/a2a/agent.py +79 -126
- jaf/a2a/agent_card.py +87 -78
- jaf/a2a/client.py +30 -66
- jaf/a2a/examples/client_example.py +12 -12
- jaf/a2a/examples/integration_example.py +38 -47
- jaf/a2a/examples/server_example.py +56 -53
- jaf/a2a/memory/__init__.py +0 -4
- jaf/a2a/memory/cleanup.py +28 -21
- jaf/a2a/memory/factory.py +155 -133
- jaf/a2a/memory/providers/composite.py +21 -26
- jaf/a2a/memory/providers/in_memory.py +89 -83
- jaf/a2a/memory/providers/postgres.py +117 -115
- jaf/a2a/memory/providers/redis.py +128 -121
- jaf/a2a/memory/serialization.py +77 -87
- jaf/a2a/memory/tests/run_comprehensive_tests.py +112 -83
- jaf/a2a/memory/tests/test_cleanup.py +211 -94
- jaf/a2a/memory/tests/test_serialization.py +73 -68
- jaf/a2a/memory/tests/test_stress_concurrency.py +186 -133
- jaf/a2a/memory/tests/test_task_lifecycle.py +138 -120
- jaf/a2a/memory/types.py +91 -53
- jaf/a2a/protocol.py +95 -125
- jaf/a2a/server.py +90 -118
- jaf/a2a/standalone_client.py +30 -43
- jaf/a2a/tests/__init__.py +16 -33
- jaf/a2a/tests/run_tests.py +17 -53
- jaf/a2a/tests/test_agent.py +40 -140
- jaf/a2a/tests/test_client.py +54 -117
- jaf/a2a/tests/test_integration.py +28 -82
- jaf/a2a/tests/test_protocol.py +54 -139
- jaf/a2a/tests/test_types.py +50 -136
- jaf/a2a/types.py +58 -34
- jaf/cli.py +21 -41
- jaf/core/__init__.py +7 -1
- jaf/core/agent_tool.py +93 -72
- jaf/core/analytics.py +257 -207
- jaf/core/checkpoint.py +223 -0
- jaf/core/composition.py +249 -235
- jaf/core/engine.py +817 -519
- jaf/core/errors.py +55 -42
- jaf/core/guardrails.py +276 -202
- jaf/core/handoff.py +47 -31
- jaf/core/parallel_agents.py +69 -75
- jaf/core/performance.py +75 -73
- jaf/core/proxy.py +43 -44
- jaf/core/proxy_helpers.py +24 -27
- jaf/core/regeneration.py +220 -129
- jaf/core/state.py +68 -66
- jaf/core/streaming.py +115 -108
- jaf/core/tool_results.py +111 -101
- jaf/core/tools.py +114 -116
- jaf/core/tracing.py +269 -210
- jaf/core/types.py +371 -151
- jaf/core/workflows.py +209 -168
- jaf/exceptions.py +46 -38
- jaf/memory/__init__.py +1 -6
- jaf/memory/approval_storage.py +54 -77
- jaf/memory/factory.py +4 -4
- jaf/memory/providers/in_memory.py +216 -180
- jaf/memory/providers/postgres.py +216 -146
- jaf/memory/providers/redis.py +173 -116
- jaf/memory/types.py +70 -51
- jaf/memory/utils.py +36 -34
- jaf/plugins/__init__.py +12 -12
- jaf/plugins/base.py +105 -96
- jaf/policies/__init__.py +0 -1
- jaf/policies/handoff.py +37 -46
- jaf/policies/validation.py +76 -52
- jaf/providers/__init__.py +6 -3
- jaf/providers/mcp.py +97 -51
- jaf/providers/model.py +360 -279
- jaf/server/__init__.py +1 -1
- jaf/server/main.py +7 -11
- jaf/server/server.py +514 -359
- jaf/server/types.py +208 -52
- jaf/utils/__init__.py +17 -18
- jaf/utils/attachments.py +111 -116
- jaf/utils/document_processor.py +175 -174
- jaf/visualization/__init__.py +1 -1
- jaf/visualization/example.py +111 -110
- jaf/visualization/functional_core.py +46 -71
- jaf/visualization/graphviz.py +154 -189
- jaf/visualization/imperative_shell.py +7 -16
- jaf/visualization/types.py +8 -4
- {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/METADATA +2 -2
- jaf_py-2.5.11.dist-info/RECORD +97 -0
- jaf_py-2.5.10.dist-info/RECORD +0 -96
- {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/WHEEL +0 -0
- {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/entry_points.txt +0 -0
- {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/licenses/LICENSE +0 -0
- {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/top_level.txt +0 -0
jaf/core/errors.py
CHANGED
|
@@ -28,10 +28,10 @@ class JAFErrorHandler:
|
|
|
28
28
|
def format_error(error: JAFError) -> str:
|
|
29
29
|
"""
|
|
30
30
|
Format an error into a human-readable string.
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
Args:
|
|
33
33
|
error: The JAF error to format
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
Returns:
|
|
36
36
|
Formatted error message
|
|
37
37
|
"""
|
|
@@ -46,9 +46,13 @@ class JAFErrorHandler:
|
|
|
46
46
|
issues = []
|
|
47
47
|
for e in error.errors:
|
|
48
48
|
if isinstance(e, dict):
|
|
49
|
-
message = e.get(
|
|
50
|
-
if
|
|
51
|
-
path =
|
|
49
|
+
message = e.get("message", "Unknown error")
|
|
50
|
+
if "path" in e:
|
|
51
|
+
path = (
|
|
52
|
+
".".join(str(p) for p in e["path"])
|
|
53
|
+
if isinstance(e["path"], list)
|
|
54
|
+
else str(e["path"])
|
|
55
|
+
)
|
|
52
56
|
issues.append(f"{path}: {message}")
|
|
53
57
|
else:
|
|
54
58
|
issues.append(message)
|
|
@@ -79,101 +83,110 @@ class JAFErrorHandler:
|
|
|
79
83
|
def is_retryable(error: JAFError) -> bool:
|
|
80
84
|
"""
|
|
81
85
|
Determine if an error is retryable.
|
|
82
|
-
|
|
86
|
+
|
|
83
87
|
Args:
|
|
84
88
|
error: The JAF error to check
|
|
85
|
-
|
|
89
|
+
|
|
86
90
|
Returns:
|
|
87
91
|
True if the error is retryable, False otherwise
|
|
88
92
|
"""
|
|
89
93
|
if isinstance(error, (ModelBehaviorError, ToolCallError)):
|
|
90
94
|
return True
|
|
91
95
|
|
|
92
|
-
elif isinstance(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
elif isinstance(
|
|
97
|
+
error,
|
|
98
|
+
(
|
|
99
|
+
MaxTurnsExceeded,
|
|
100
|
+
DecodeError,
|
|
101
|
+
InputGuardrailTripwire,
|
|
102
|
+
OutputGuardrailTripwire,
|
|
103
|
+
HandoffError,
|
|
104
|
+
AgentNotFound,
|
|
105
|
+
),
|
|
106
|
+
):
|
|
96
107
|
return False
|
|
97
108
|
|
|
98
109
|
else:
|
|
99
110
|
return False
|
|
100
111
|
|
|
101
112
|
@staticmethod
|
|
102
|
-
def get_severity(error: JAFError) -> Literal[
|
|
113
|
+
def get_severity(error: JAFError) -> Literal["low", "medium", "high", "critical"]:
|
|
103
114
|
"""
|
|
104
115
|
Get the severity level of an error.
|
|
105
|
-
|
|
116
|
+
|
|
106
117
|
Args:
|
|
107
118
|
error: The JAF error to classify
|
|
108
|
-
|
|
119
|
+
|
|
109
120
|
Returns:
|
|
110
121
|
Severity level: 'low', 'medium', 'high', or 'critical'
|
|
111
122
|
"""
|
|
112
123
|
if isinstance(error, (ModelBehaviorError, ToolCallError)):
|
|
113
|
-
return
|
|
124
|
+
return "medium"
|
|
114
125
|
|
|
115
126
|
elif isinstance(error, DecodeError):
|
|
116
|
-
return
|
|
127
|
+
return "high"
|
|
117
128
|
|
|
118
129
|
elif isinstance(error, MaxTurnsExceeded):
|
|
119
|
-
return
|
|
130
|
+
return "low"
|
|
120
131
|
|
|
121
132
|
elif isinstance(error, (InputGuardrailTripwire, OutputGuardrailTripwire)):
|
|
122
|
-
return
|
|
133
|
+
return "high"
|
|
123
134
|
|
|
124
135
|
elif isinstance(error, (HandoffError, AgentNotFound)):
|
|
125
|
-
return
|
|
136
|
+
return "critical"
|
|
126
137
|
|
|
127
138
|
else:
|
|
128
|
-
return
|
|
139
|
+
return "medium"
|
|
140
|
+
|
|
129
141
|
|
|
130
142
|
def create_jaf_error(tag: str, details: Any) -> JAFError:
|
|
131
143
|
"""
|
|
132
144
|
Create a JAF error from a tag and details.
|
|
133
|
-
|
|
145
|
+
|
|
134
146
|
Args:
|
|
135
147
|
tag: The error tag/type
|
|
136
148
|
details: Error details (can be dict or simple value)
|
|
137
|
-
|
|
149
|
+
|
|
138
150
|
Returns:
|
|
139
151
|
Appropriate JAF error instance
|
|
140
|
-
|
|
152
|
+
|
|
141
153
|
Raises:
|
|
142
154
|
ValueError: If the error tag is unknown
|
|
143
155
|
"""
|
|
144
156
|
# Normalize details to dict if it's a simple value
|
|
145
157
|
if not isinstance(details, dict):
|
|
146
158
|
if isinstance(details, str):
|
|
147
|
-
details = {
|
|
159
|
+
details = {"detail": details}
|
|
148
160
|
else:
|
|
149
|
-
details = {
|
|
161
|
+
details = {"value": details}
|
|
150
162
|
|
|
151
|
-
if tag ==
|
|
152
|
-
return MaxTurnsExceeded(turns=details.get(
|
|
163
|
+
if tag == "MaxTurnsExceeded":
|
|
164
|
+
return MaxTurnsExceeded(turns=details.get("turns", 0))
|
|
153
165
|
|
|
154
|
-
elif tag ==
|
|
155
|
-
return ModelBehaviorError(detail=details.get(
|
|
166
|
+
elif tag == "ModelBehaviorError":
|
|
167
|
+
return ModelBehaviorError(detail=details.get("detail", str(details)))
|
|
156
168
|
|
|
157
|
-
elif tag ==
|
|
158
|
-
return DecodeError(errors=details.get(
|
|
169
|
+
elif tag == "DecodeError":
|
|
170
|
+
return DecodeError(errors=details.get("errors", []))
|
|
159
171
|
|
|
160
|
-
elif tag ==
|
|
161
|
-
return InputGuardrailTripwire(reason=details.get(
|
|
172
|
+
elif tag == "InputGuardrailTripwire":
|
|
173
|
+
return InputGuardrailTripwire(reason=details.get("reason", str(details)))
|
|
162
174
|
|
|
163
|
-
elif tag ==
|
|
164
|
-
return OutputGuardrailTripwire(reason=details.get(
|
|
175
|
+
elif tag == "OutputGuardrailTripwire":
|
|
176
|
+
return OutputGuardrailTripwire(reason=details.get("reason", str(details)))
|
|
165
177
|
|
|
166
|
-
elif tag ==
|
|
178
|
+
elif tag == "ToolCallError":
|
|
167
179
|
return ToolCallError(
|
|
168
|
-
tool=details.get(
|
|
169
|
-
detail=details.get('detail', str(details))
|
|
180
|
+
tool=details.get("tool", ""), detail=details.get("detail", str(details))
|
|
170
181
|
)
|
|
171
182
|
|
|
172
|
-
elif tag ==
|
|
173
|
-
return HandoffError(detail=details.get(
|
|
183
|
+
elif tag == "HandoffError":
|
|
184
|
+
return HandoffError(detail=details.get("detail", str(details)))
|
|
174
185
|
|
|
175
|
-
elif tag ==
|
|
176
|
-
return AgentNotFound(
|
|
186
|
+
elif tag == "AgentNotFound":
|
|
187
|
+
return AgentNotFound(
|
|
188
|
+
agent_name=details.get("agentName", details.get("agent_name", str(details)))
|
|
189
|
+
)
|
|
177
190
|
|
|
178
191
|
else:
|
|
179
192
|
raise ValueError(f"Unknown error tag: {tag}")
|