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.
Files changed (92) hide show
  1. jaf/__init__.py +154 -57
  2. jaf/a2a/__init__.py +42 -21
  3. jaf/a2a/agent.py +79 -126
  4. jaf/a2a/agent_card.py +87 -78
  5. jaf/a2a/client.py +30 -66
  6. jaf/a2a/examples/client_example.py +12 -12
  7. jaf/a2a/examples/integration_example.py +38 -47
  8. jaf/a2a/examples/server_example.py +56 -53
  9. jaf/a2a/memory/__init__.py +0 -4
  10. jaf/a2a/memory/cleanup.py +28 -21
  11. jaf/a2a/memory/factory.py +155 -133
  12. jaf/a2a/memory/providers/composite.py +21 -26
  13. jaf/a2a/memory/providers/in_memory.py +89 -83
  14. jaf/a2a/memory/providers/postgres.py +117 -115
  15. jaf/a2a/memory/providers/redis.py +128 -121
  16. jaf/a2a/memory/serialization.py +77 -87
  17. jaf/a2a/memory/tests/run_comprehensive_tests.py +112 -83
  18. jaf/a2a/memory/tests/test_cleanup.py +211 -94
  19. jaf/a2a/memory/tests/test_serialization.py +73 -68
  20. jaf/a2a/memory/tests/test_stress_concurrency.py +186 -133
  21. jaf/a2a/memory/tests/test_task_lifecycle.py +138 -120
  22. jaf/a2a/memory/types.py +91 -53
  23. jaf/a2a/protocol.py +95 -125
  24. jaf/a2a/server.py +90 -118
  25. jaf/a2a/standalone_client.py +30 -43
  26. jaf/a2a/tests/__init__.py +16 -33
  27. jaf/a2a/tests/run_tests.py +17 -53
  28. jaf/a2a/tests/test_agent.py +40 -140
  29. jaf/a2a/tests/test_client.py +54 -117
  30. jaf/a2a/tests/test_integration.py +28 -82
  31. jaf/a2a/tests/test_protocol.py +54 -139
  32. jaf/a2a/tests/test_types.py +50 -136
  33. jaf/a2a/types.py +58 -34
  34. jaf/cli.py +21 -41
  35. jaf/core/__init__.py +7 -1
  36. jaf/core/agent_tool.py +93 -72
  37. jaf/core/analytics.py +257 -207
  38. jaf/core/checkpoint.py +223 -0
  39. jaf/core/composition.py +249 -235
  40. jaf/core/engine.py +817 -519
  41. jaf/core/errors.py +55 -42
  42. jaf/core/guardrails.py +276 -202
  43. jaf/core/handoff.py +47 -31
  44. jaf/core/parallel_agents.py +69 -75
  45. jaf/core/performance.py +75 -73
  46. jaf/core/proxy.py +43 -44
  47. jaf/core/proxy_helpers.py +24 -27
  48. jaf/core/regeneration.py +220 -129
  49. jaf/core/state.py +68 -66
  50. jaf/core/streaming.py +115 -108
  51. jaf/core/tool_results.py +111 -101
  52. jaf/core/tools.py +114 -116
  53. jaf/core/tracing.py +269 -210
  54. jaf/core/types.py +371 -151
  55. jaf/core/workflows.py +209 -168
  56. jaf/exceptions.py +46 -38
  57. jaf/memory/__init__.py +1 -6
  58. jaf/memory/approval_storage.py +54 -77
  59. jaf/memory/factory.py +4 -4
  60. jaf/memory/providers/in_memory.py +216 -180
  61. jaf/memory/providers/postgres.py +216 -146
  62. jaf/memory/providers/redis.py +173 -116
  63. jaf/memory/types.py +70 -51
  64. jaf/memory/utils.py +36 -34
  65. jaf/plugins/__init__.py +12 -12
  66. jaf/plugins/base.py +105 -96
  67. jaf/policies/__init__.py +0 -1
  68. jaf/policies/handoff.py +37 -46
  69. jaf/policies/validation.py +76 -52
  70. jaf/providers/__init__.py +6 -3
  71. jaf/providers/mcp.py +97 -51
  72. jaf/providers/model.py +360 -279
  73. jaf/server/__init__.py +1 -1
  74. jaf/server/main.py +7 -11
  75. jaf/server/server.py +514 -359
  76. jaf/server/types.py +208 -52
  77. jaf/utils/__init__.py +17 -18
  78. jaf/utils/attachments.py +111 -116
  79. jaf/utils/document_processor.py +175 -174
  80. jaf/visualization/__init__.py +1 -1
  81. jaf/visualization/example.py +111 -110
  82. jaf/visualization/functional_core.py +46 -71
  83. jaf/visualization/graphviz.py +154 -189
  84. jaf/visualization/imperative_shell.py +7 -16
  85. jaf/visualization/types.py +8 -4
  86. {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/METADATA +2 -2
  87. jaf_py-2.5.11.dist-info/RECORD +97 -0
  88. jaf_py-2.5.10.dist-info/RECORD +0 -96
  89. {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/WHEEL +0 -0
  90. {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/entry_points.txt +0 -0
  91. {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/licenses/LICENSE +0 -0
  92. {jaf_py-2.5.10.dist-info → jaf_py-2.5.11.dist-info}/top_level.txt +0 -0
@@ -2,7 +2,7 @@
2
2
  JAF Visualization - Functional Core
3
3
 
4
4
  Pure functional operations for graph creation that separate data transformation
5
- from the imperative Graphviz operations. This follows the functional core,
5
+ from the imperative Graphviz operations. This follows the functional core,
6
6
  imperative shell pattern.
7
7
  """
8
8
 
@@ -14,9 +14,11 @@ from .types import GraphOptions
14
14
 
15
15
  # ========== Pure Data Structures ==========
16
16
 
17
+
17
18
  @dataclass(frozen=True)
18
19
  class NodeSpec:
19
20
  """Immutable specification for a graph node."""
21
+
20
22
  id: str
21
23
  label: str
22
24
  attributes: Dict[str, str]
@@ -25,6 +27,7 @@ class NodeSpec:
25
27
  @dataclass(frozen=True)
26
28
  class EdgeSpec:
27
29
  """Immutable specification for a graph edge."""
30
+
28
31
  from_node: str
29
32
  to_node: str
30
33
  attributes: Dict[str, str]
@@ -33,6 +36,7 @@ class EdgeSpec:
33
36
  @dataclass(frozen=True)
34
37
  class GraphSpec:
35
38
  """Immutable specification for a complete graph."""
39
+
36
40
  title: str
37
41
  graph_attributes: Dict[str, str]
38
42
  nodes: Tuple[NodeSpec, ...]
@@ -41,22 +45,23 @@ class GraphSpec:
41
45
 
42
46
  # ========== Pure Functions ==========
43
47
 
48
+
44
49
  def create_graph_attributes(options: GraphOptions) -> Dict[str, str]:
45
50
  """Pure function to create graph attributes from options."""
46
51
  return {
47
- 'rankdir': options.rankdir,
48
- 'label': options.title or '',
49
- 'labelloc': 't',
50
- 'fontsize': '16',
51
- 'fontname': 'Arial Bold',
52
- 'bgcolor': 'white',
53
- 'pad': '0.5'
52
+ "rankdir": options.rankdir,
53
+ "label": options.title or "",
54
+ "labelloc": "t",
55
+ "fontsize": "16",
56
+ "fontname": "Arial Bold",
57
+ "bgcolor": "white",
58
+ "pad": "0.5",
54
59
  }
55
60
 
56
61
 
57
62
  def create_agent_label(agent: Agent, show_tool_details: bool) -> str:
58
63
  """Pure function to create agent label."""
59
- model_name = getattr(agent.model_config, 'name', 'default') if agent.model_config else 'default'
64
+ model_name = getattr(agent.model_config, "name", "default") if agent.model_config else "default"
60
65
  label = f"{agent.name}\\n({model_name})"
61
66
 
62
67
  if show_tool_details and agent.tools:
@@ -78,98 +83,70 @@ def create_tool_label(tool: Tool) -> str:
78
83
 
79
84
 
80
85
  def create_agent_node_spec(
81
- agent: Agent,
82
- styles: Dict[str, Any],
83
- show_tool_details: bool
86
+ agent: Agent, styles: Dict[str, Any], show_tool_details: bool
84
87
  ) -> NodeSpec:
85
88
  """Pure function to create agent node specification."""
86
- agent_style = styles['agent']
89
+ agent_style = styles["agent"]
87
90
  label = create_agent_label(agent, show_tool_details)
88
91
 
89
92
  attributes = {
90
- 'label': label,
91
- 'shape': agent_style['shape'],
92
- 'fillcolor': agent_style['fillcolor'],
93
- 'fontcolor': agent_style['fontcolor'],
94
- 'style': agent_style['style']
93
+ "label": label,
94
+ "shape": agent_style["shape"],
95
+ "fillcolor": agent_style["fillcolor"],
96
+ "fontcolor": agent_style["fontcolor"],
97
+ "style": agent_style["style"],
95
98
  }
96
99
 
97
- if 'fontname' in agent_style:
98
- attributes['fontname'] = agent_style['fontname']
100
+ if "fontname" in agent_style:
101
+ attributes["fontname"] = agent_style["fontname"]
99
102
 
100
- return NodeSpec(
101
- id=agent.name,
102
- label=label,
103
- attributes=attributes
104
- )
103
+ return NodeSpec(id=agent.name, label=label, attributes=attributes)
105
104
 
106
105
 
107
106
  def create_tool_node_spec(tool: Tool, styles: Dict[str, Any]) -> NodeSpec:
108
107
  """Pure function to create tool node specification."""
109
- tool_style = styles['tool']
108
+ tool_style = styles["tool"]
110
109
  label = create_tool_label(tool)
111
110
 
112
111
  attributes = {
113
- 'label': label,
114
- 'shape': tool_style['shape'],
115
- 'fillcolor': tool_style['fillcolor'],
116
- 'fontcolor': tool_style['fontcolor'],
117
- 'style': tool_style['style']
112
+ "label": label,
113
+ "shape": tool_style["shape"],
114
+ "fillcolor": tool_style["fillcolor"],
115
+ "fontcolor": tool_style["fontcolor"],
116
+ "style": tool_style["style"],
118
117
  }
119
118
 
120
- if 'fontname' in tool_style:
121
- attributes['fontname'] = tool_style['fontname']
119
+ if "fontname" in tool_style:
120
+ attributes["fontname"] = tool_style["fontname"]
122
121
 
123
- return NodeSpec(
124
- id=tool.schema.name,
125
- label=label,
126
- attributes=attributes
127
- )
122
+ return NodeSpec(id=tool.schema.name, label=label, attributes=attributes)
128
123
 
129
124
 
130
- def create_tool_edge_spec(
131
- agent_name: str,
132
- tool_name: str,
133
- styles: Dict[str, Any]
134
- ) -> EdgeSpec:
125
+ def create_tool_edge_spec(agent_name: str, tool_name: str, styles: Dict[str, Any]) -> EdgeSpec:
135
126
  """Pure function to create tool edge specification."""
136
127
  edge_attrs = {
137
- 'color': styles['tool_edge']['color'],
138
- 'style': styles['tool_edge']['style'],
139
- 'penwidth': styles['tool_edge']['penwidth']
128
+ "color": styles["tool_edge"]["color"],
129
+ "style": styles["tool_edge"]["style"],
130
+ "penwidth": styles["tool_edge"]["penwidth"],
140
131
  }
141
132
 
142
- if 'arrowhead' in styles['tool_edge']:
143
- edge_attrs['arrowhead'] = styles['tool_edge']['arrowhead']
133
+ if "arrowhead" in styles["tool_edge"]:
134
+ edge_attrs["arrowhead"] = styles["tool_edge"]["arrowhead"]
144
135
 
145
- return EdgeSpec(
146
- from_node=agent_name,
147
- to_node=tool_name,
148
- attributes=edge_attrs
149
- )
136
+ return EdgeSpec(from_node=agent_name, to_node=tool_name, attributes=edge_attrs)
150
137
 
151
138
 
152
- def create_handoff_edge_spec(
153
- from_agent: str,
154
- to_agent: str,
155
- styles: Dict[str, Any]
156
- ) -> EdgeSpec:
139
+ def create_handoff_edge_spec(from_agent: str, to_agent: str, styles: Dict[str, Any]) -> EdgeSpec:
157
140
  """Pure function to create handoff edge specification."""
158
141
  return EdgeSpec(
159
142
  from_node=from_agent,
160
143
  to_node=to_agent,
161
- attributes={
162
- 'color': styles['edge']['color'],
163
- 'style': 'dashed',
164
- 'label': 'handoff'
165
- }
144
+ attributes={"color": styles["edge"]["color"], "style": "dashed", "label": "handoff"},
166
145
  )
167
146
 
168
147
 
169
148
  def create_agent_graph_spec(
170
- agents: List[Agent],
171
- options: GraphOptions,
172
- styles: Dict[str, Any]
149
+ agents: List[Agent], options: GraphOptions, styles: Dict[str, Any]
173
150
  ) -> GraphSpec:
174
151
  """Pure function to create complete agent graph specification."""
175
152
  nodes = []
@@ -200,14 +177,12 @@ def create_agent_graph_spec(
200
177
  title=options.title or "JAF Graph",
201
178
  graph_attributes=create_graph_attributes(options),
202
179
  nodes=tuple(nodes),
203
- edges=tuple(edges)
180
+ edges=tuple(edges),
204
181
  )
205
182
 
206
183
 
207
184
  def create_tool_graph_spec(
208
- tools: List[Tool],
209
- options: GraphOptions,
210
- styles: Dict[str, Any]
185
+ tools: List[Tool], options: GraphOptions, styles: Dict[str, Any]
211
186
  ) -> GraphSpec:
212
187
  """Pure function to create tool graph specification."""
213
188
  nodes = []
@@ -220,5 +195,5 @@ def create_tool_graph_spec(
220
195
  title=options.title or "JAF Tool Graph",
221
196
  graph_attributes=create_graph_attributes(options),
222
197
  nodes=tuple(nodes),
223
- edges=tuple() # No edges in pure tool graph
198
+ edges=tuple(), # No edges in pure tool graph
224
199
  )