simple-agents-py 0.1.10__tar.gz → 0.1.14__tar.gz

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 (135) hide show
  1. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/Cargo.lock +29 -12
  2. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/Cargo.toml +1 -1
  3. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/PKG-INFO +116 -1
  4. {simple_agents_py-0.1.10/crates/simple-agents-py → simple_agents_py-0.1.14}/README.md +115 -0
  5. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/lib.rs +7 -0
  6. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/message.rs +20 -0
  7. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/provider.rs +50 -5
  8. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/request.rs +23 -0
  9. simple_agents_py-0.1.14/crates/simple-agent-type/src/tool.rs +93 -0
  10. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-core/Cargo.toml +4 -3
  11. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-core/src/client.rs +24 -2
  12. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-core/src/routing.rs +22 -1
  13. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/Cargo.toml +1 -1
  14. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/Cargo.toml +3 -3
  15. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/anthropic/mod.rs +7 -0
  16. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/openai/mod.rs +2 -0
  17. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/openai/models.rs +10 -0
  18. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/openrouter/mod.rs +2 -0
  19. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-py/Cargo.toml +9 -3
  20. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14/crates/simple-agents-py}/README.md +115 -0
  21. simple_agents_py-0.1.14/crates/simple-agents-py/examples/client_builder_demo.py +298 -0
  22. simple_agents_py-0.1.14/crates/simple-agents-py/examples/direct_healing_demo.py +73 -0
  23. simple_agents_py-0.1.14/crates/simple-agents-py/examples/healing_demo.py +48 -0
  24. simple_agents_py-0.1.14/crates/simple-agents-py/examples/routing_config_demo.py +469 -0
  25. simple_agents_py-0.1.14/crates/simple-agents-py/examples/streaming_demo.py +121 -0
  26. simple_agents_py-0.1.14/crates/simple-agents-py/examples/streaming_parser_demo.py +192 -0
  27. simple_agents_py-0.1.14/crates/simple-agents-py/examples/structured_streaming_demo.py +244 -0
  28. simple_agents_py-0.1.14/crates/simple-agents-py/src/lib.rs +2494 -0
  29. simple_agents_py-0.1.14/crates/simple-agents-py/tests/test_client_builder.py +312 -0
  30. simple_agents_py-0.1.14/crates/simple-agents-py/tests/test_direct_healing.py +109 -0
  31. simple_agents_py-0.1.14/crates/simple-agents-py/tests/test_healing.py +79 -0
  32. simple_agents_py-0.1.14/crates/simple-agents-py/tests/test_integration_openai.py +78 -0
  33. simple_agents_py-0.1.14/crates/simple-agents-py/tests/test_routing_config.py +402 -0
  34. simple_agents_py-0.1.14/crates/simple-agents-py/tests/test_streaming.py +118 -0
  35. simple_agents_py-0.1.14/crates/simple-agents-py/tests/test_streaming_parser.py +178 -0
  36. simple_agents_py-0.1.14/crates/simple-agents-py/tests/test_structured_streaming.py +184 -0
  37. simple_agents_py-0.1.14/crates/simple-agents-py/uv.lock +199 -0
  38. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/Cargo.toml +1 -0
  39. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/src/cost.rs +13 -2
  40. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/src/fallback.rs +22 -1
  41. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/src/latency.rs +13 -2
  42. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/src/round_robin.rs +17 -1
  43. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/pyproject.toml +1 -1
  44. simple_agents_py-0.1.10/crates/simple-agents-py/src/lib.rs +0 -411
  45. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/Cargo.toml +0 -0
  46. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/README.md +0 -0
  47. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/TEST_GUIDE.md +0 -0
  48. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/TODO.md +0 -0
  49. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/examples/basic_usage.rs +0 -0
  50. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/examples/mock_provider.rs +0 -0
  51. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/cache.rs +0 -0
  52. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/coercion.rs +0 -0
  53. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/config.rs +0 -0
  54. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/error.rs +0 -0
  55. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/response.rs +0 -0
  56. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/router.rs +0 -0
  57. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/src/validation.rs +0 -0
  58. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agent-type/tests/integration_test.rs +0 -0
  59. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-cache/Cargo.toml +0 -0
  60. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-cache/src/lib.rs +0 -0
  61. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-cache/src/memory.rs +0 -0
  62. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-cache/src/noop.rs +0 -0
  63. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-core/README.md +0 -0
  64. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-core/examples/basic_client.rs +0 -0
  65. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-core/src/healing.rs +0 -0
  66. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-core/src/lib.rs +0 -0
  67. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-core/src/middleware.rs +0 -0
  68. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-core/tests/client_integration.rs +0 -0
  69. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/README.md +0 -0
  70. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/benches/parser_benchmarks.rs +0 -0
  71. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/examples/basic_healing.rs +0 -0
  72. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/examples/coercion_demo.rs +0 -0
  73. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/examples/streaming_annotations.rs +0 -0
  74. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/examples/streaming_partial_types.rs +0 -0
  75. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/src/coercion.rs +0 -0
  76. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/src/lib.rs +0 -0
  77. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/src/parser.rs +0 -0
  78. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/src/schema.rs +0 -0
  79. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/src/streaming.rs +0 -0
  80. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/src/string_utils.rs +0 -0
  81. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/tests/parser_tests.rs +0 -0
  82. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/tests/property_tests.rs +0 -0
  83. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/tests/stream_annotations_tests.rs +0 -0
  84. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-healing/tests/streaming_tests.rs +0 -0
  85. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-macros/Cargo.toml +0 -0
  86. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-macros/README.md +0 -0
  87. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-macros/src/lib.rs +0 -0
  88. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-macros/src/partial.rs +0 -0
  89. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-macros/tests/partial_type_tests.rs +0 -0
  90. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/README.md +0 -0
  91. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/anthropic_basic.rs +0 -0
  92. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/anthropic_structured_output.rs +0 -0
  93. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/cache_usage.rs +0 -0
  94. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/custom_api.rs +0 -0
  95. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/healing_fallback.rs +0 -0
  96. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/openai_basic.rs +0 -0
  97. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/openai_structured_output.rs +0 -0
  98. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/openrouter_basic.rs +0 -0
  99. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/retry_demo.rs +0 -0
  100. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/streaming.rs +0 -0
  101. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/streaming_structured.rs +0 -0
  102. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/streaming_with_healing.rs +0 -0
  103. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/test_local_api.rs +0 -0
  104. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/examples/test_reqwest.rs +0 -0
  105. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/run_integration_tests.sh +0 -0
  106. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/anthropic/error.rs +0 -0
  107. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/anthropic/models.rs +0 -0
  108. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/anthropic/streaming.rs +0 -0
  109. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/common/error.rs +0 -0
  110. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/common/http_client.rs +0 -0
  111. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/common/mod.rs +0 -0
  112. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/healing_integration.rs +0 -0
  113. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/lib.rs +0 -0
  114. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/metrics.rs +0 -0
  115. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/openai/error.rs +0 -0
  116. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/openai/streaming.rs +0 -0
  117. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/rate_limit.rs +0 -0
  118. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/retry.rs +0 -0
  119. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/schema_converter.rs +0 -0
  120. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/streaming_structured.rs +0 -0
  121. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/src/utils.rs +0 -0
  122. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/tests/README.md +0 -0
  123. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/tests/healing_integration_tests.rs +0 -0
  124. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-providers/tests/openai_integration.rs +0 -0
  125. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-py/py.typed +0 -0
  126. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-py/simple_agents_py.pyi +0 -0
  127. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-py/tests/test_client.py +0 -0
  128. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/examples/round_robin_router.rs +0 -0
  129. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/src/circuit_breaker.rs +0 -0
  130. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/src/health.rs +0 -0
  131. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/src/lib.rs +0 -0
  132. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/src/retry.rs +0 -0
  133. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/crates/simple-agents-router/tests/health_tracker_integration.rs +0 -0
  134. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/py.typed +0 -0
  135. {simple_agents_py-0.1.10 → simple_agents_py-0.1.14}/simple_agents_py.pyi +0 -0
@@ -1494,7 +1494,6 @@ dependencies = [
1494
1494
  "pyo3-build-config",
1495
1495
  "pyo3-ffi",
1496
1496
  "pyo3-macros",
1497
- "serde",
1498
1497
  "unindent",
1499
1498
  ]
1500
1499
 
@@ -1543,6 +1542,16 @@ dependencies = [
1543
1542
  "syn",
1544
1543
  ]
1545
1544
 
1545
+ [[package]]
1546
+ name = "pythonize"
1547
+ version = "0.22.0"
1548
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1549
+ checksum = "90fcf491425978bd889015d5430f6473d91bdfa2097262f1e731aadcf6c2113e"
1550
+ dependencies = [
1551
+ "pyo3",
1552
+ "serde",
1553
+ ]
1554
+
1546
1555
  [[package]]
1547
1556
  name = "quanta"
1548
1557
  version = "0.12.6"
@@ -2026,7 +2035,7 @@ dependencies = [
2026
2035
 
2027
2036
  [[package]]
2028
2037
  name = "simple-agent-type"
2029
- version = "0.1.10"
2038
+ version = "0.1.14"
2030
2039
  dependencies = [
2031
2040
  "async-trait",
2032
2041
  "blake3",
@@ -2041,7 +2050,7 @@ dependencies = [
2041
2050
 
2042
2051
  [[package]]
2043
2052
  name = "simple-agents-cache"
2044
- version = "0.1.10"
2053
+ version = "0.1.14"
2045
2054
  dependencies = [
2046
2055
  "async-trait",
2047
2056
  "simple-agent-type",
@@ -2050,7 +2059,7 @@ dependencies = [
2050
2059
 
2051
2060
  [[package]]
2052
2061
  name = "simple-agents-cli"
2053
- version = "0.1.10"
2062
+ version = "0.1.14"
2054
2063
  dependencies = [
2055
2064
  "clap",
2056
2065
  "serde",
@@ -2067,9 +2076,10 @@ dependencies = [
2067
2076
 
2068
2077
  [[package]]
2069
2078
  name = "simple-agents-core"
2070
- version = "0.1.10"
2079
+ version = "0.1.14"
2071
2080
  dependencies = [
2072
2081
  "async-trait",
2082
+ "futures-core",
2073
2083
  "serde",
2074
2084
  "serde_json",
2075
2085
  "simple-agent-type",
@@ -2094,7 +2104,7 @@ dependencies = [
2094
2104
 
2095
2105
  [[package]]
2096
2106
  name = "simple-agents-ffi"
2097
- version = "0.1.10"
2107
+ version = "0.1.14"
2098
2108
  dependencies = [
2099
2109
  "async-trait",
2100
2110
  "simple-agent-type",
@@ -2105,7 +2115,7 @@ dependencies = [
2105
2115
 
2106
2116
  [[package]]
2107
2117
  name = "simple-agents-healing"
2108
- version = "0.1.10"
2118
+ version = "0.1.14"
2109
2119
  dependencies = [
2110
2120
  "criterion",
2111
2121
  "proptest",
@@ -2121,7 +2131,7 @@ dependencies = [
2121
2131
 
2122
2132
  [[package]]
2123
2133
  name = "simple-agents-macros"
2124
- version = "0.1.10"
2134
+ version = "0.1.14"
2125
2135
  dependencies = [
2126
2136
  "proc-macro2",
2127
2137
  "quote",
@@ -2133,7 +2143,7 @@ dependencies = [
2133
2143
 
2134
2144
  [[package]]
2135
2145
  name = "simple-agents-napi"
2136
- version = "0.1.10"
2146
+ version = "0.1.14"
2137
2147
  dependencies = [
2138
2148
  "napi",
2139
2149
  "napi-derive",
@@ -2145,7 +2155,7 @@ dependencies = [
2145
2155
 
2146
2156
  [[package]]
2147
2157
  name = "simple-agents-providers"
2148
- version = "0.1.10"
2158
+ version = "0.1.14"
2149
2159
  dependencies = [
2150
2160
  "async-trait",
2151
2161
  "bytes",
@@ -2173,22 +2183,29 @@ dependencies = [
2173
2183
 
2174
2184
  [[package]]
2175
2185
  name = "simple-agents-py"
2176
- version = "0.1.10"
2186
+ version = "0.1.14"
2177
2187
  dependencies = [
2188
+ "async-trait",
2189
+ "futures-util",
2178
2190
  "pyo3",
2191
+ "pythonize",
2179
2192
  "reqwest",
2180
2193
  "serde_json",
2181
2194
  "simple-agent-type",
2195
+ "simple-agents-cache",
2182
2196
  "simple-agents-core",
2197
+ "simple-agents-healing",
2183
2198
  "simple-agents-providers",
2199
+ "simple-agents-router",
2184
2200
  "tokio",
2185
2201
  ]
2186
2202
 
2187
2203
  [[package]]
2188
2204
  name = "simple-agents-router"
2189
- version = "0.1.10"
2205
+ version = "0.1.14"
2190
2206
  dependencies = [
2191
2207
  "async-trait",
2208
+ "futures-core",
2192
2209
  "rand 0.8.5",
2193
2210
  "serde_json",
2194
2211
  "simple-agent-type",
@@ -3,7 +3,7 @@ members = ["crates/*"]
3
3
  resolver = "2"
4
4
 
5
5
  [workspace.package]
6
- version = "0.1.10"
6
+ version = "0.1.14"
7
7
  edition = "2021"
8
8
  rust-version = "1.75"
9
9
  authors = ["SimpleAgents Contributors"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simple-agents-py
3
- Version: 0.1.10
3
+ Version: 0.1.14
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -60,6 +60,121 @@ response = client.complete("gpt-4", "Hello from Python!", max_tokens=128, temper
60
60
  print(response)
61
61
  ```
62
62
 
63
+ ## Feature Guide
64
+
65
+ ### Streaming
66
+
67
+ ```python
68
+ from simple_agents_py import Client
69
+
70
+ client = Client("openai")
71
+ messages = [{"role": "user", "content": "Say hello in one sentence."}]
72
+ for chunk in client.stream("gpt-4o-mini", messages, max_tokens=64):
73
+ if chunk.content:
74
+ print(chunk.content, end="", flush=True)
75
+ print()
76
+ ```
77
+
78
+ ### Structured Output (JSON Mode)
79
+
80
+ ```python
81
+ from simple_agents_py import Client
82
+ import json
83
+
84
+ client = Client("openai")
85
+ schema = {
86
+ "type": "object",
87
+ "properties": {
88
+ "name": {"type": "string"},
89
+ "age": {"type": "number"},
90
+ },
91
+ "required": ["name", "age"],
92
+ }
93
+ messages = [{"role": "user", "content": "Extract name and age: Alice is 28."}]
94
+ json_text = client.complete_json_schema("gpt-4o-mini", messages, schema, "person")
95
+ print(json.loads(json_text))
96
+ ```
97
+
98
+ ### Structured Streaming
99
+
100
+ ```python
101
+ from simple_agents_py import Client
102
+
103
+ client = Client("openai")
104
+ schema = {
105
+ "type": "object",
106
+ "properties": {"name": {"type": "string"}, "age": {"type": "number"}},
107
+ "required": ["name", "age"],
108
+ }
109
+ messages = [{"role": "user", "content": "Extract name and age: Alice is 28."}]
110
+ for event in client.stream_structured("gpt-4o-mini", messages, schema, max_tokens=64):
111
+ if event.is_partial:
112
+ print("partial:", event.partial_value)
113
+ else:
114
+ print("complete:", event.value)
115
+ ```
116
+
117
+ ### Response Healing
118
+
119
+ ```python
120
+ from simple_agents_py import Client
121
+
122
+ client = Client("openai")
123
+ messages = [{"role": "user", "content": "Return JSON: {\"name\":\"Sam\",\"age\":30}"}]
124
+ healed = client.complete_json_healed("gpt-4o-mini", messages, max_tokens=64)
125
+ print(healed.content)
126
+ print(healed.was_healed, healed.confidence)
127
+ ```
128
+
129
+ ### Tool Calling
130
+
131
+ ```python
132
+ from simple_agents_py import Client
133
+
134
+ client = Client("openai")
135
+ tools = [
136
+ {
137
+ "type": "function",
138
+ "function": {
139
+ "name": "get_weather",
140
+ "description": "Get the weather for a city",
141
+ "parameters": {
142
+ "type": "object",
143
+ "properties": {
144
+ "city": {"type": "string"},
145
+ "unit": {"type": "string", "enum": ["c", "f"]},
146
+ },
147
+ "required": ["city"],
148
+ },
149
+ },
150
+ }
151
+ ]
152
+ messages = [{"role": "user", "content": "What's the weather in Tokyo?"}]
153
+ response = client.complete_with_tools("gpt-4o-mini", messages, tools)
154
+ print(response.tool_calls)
155
+ ```
156
+
157
+ ### ClientBuilder (Routing, Cache, Healing, Middleware)
158
+
159
+ ```python
160
+ from simple_agents_py import ClientBuilder
161
+
162
+ class TimingMiddleware:
163
+ def before_request(self, request):
164
+ print("sending", request.model)
165
+
166
+ builder = (
167
+ ClientBuilder()
168
+ .add_provider("openai", api_key="sk-...")
169
+ .with_routing("direct")
170
+ .with_cache(ttl_seconds=60)
171
+ .with_healing_config({"enabled": True, "min_confidence": 0.7})
172
+ .add_middleware(TimingMiddleware())
173
+ )
174
+ client = builder.build()
175
+ print(client.complete("gpt-4o-mini", "Give me one idea."))
176
+ ```
177
+
63
178
  ## Examples
64
179
 
65
180
  OpenAI with a short prompt:
@@ -45,6 +45,121 @@ response = client.complete("gpt-4", "Hello from Python!", max_tokens=128, temper
45
45
  print(response)
46
46
  ```
47
47
 
48
+ ## Feature Guide
49
+
50
+ ### Streaming
51
+
52
+ ```python
53
+ from simple_agents_py import Client
54
+
55
+ client = Client("openai")
56
+ messages = [{"role": "user", "content": "Say hello in one sentence."}]
57
+ for chunk in client.stream("gpt-4o-mini", messages, max_tokens=64):
58
+ if chunk.content:
59
+ print(chunk.content, end="", flush=True)
60
+ print()
61
+ ```
62
+
63
+ ### Structured Output (JSON Mode)
64
+
65
+ ```python
66
+ from simple_agents_py import Client
67
+ import json
68
+
69
+ client = Client("openai")
70
+ schema = {
71
+ "type": "object",
72
+ "properties": {
73
+ "name": {"type": "string"},
74
+ "age": {"type": "number"},
75
+ },
76
+ "required": ["name", "age"],
77
+ }
78
+ messages = [{"role": "user", "content": "Extract name and age: Alice is 28."}]
79
+ json_text = client.complete_json_schema("gpt-4o-mini", messages, schema, "person")
80
+ print(json.loads(json_text))
81
+ ```
82
+
83
+ ### Structured Streaming
84
+
85
+ ```python
86
+ from simple_agents_py import Client
87
+
88
+ client = Client("openai")
89
+ schema = {
90
+ "type": "object",
91
+ "properties": {"name": {"type": "string"}, "age": {"type": "number"}},
92
+ "required": ["name", "age"],
93
+ }
94
+ messages = [{"role": "user", "content": "Extract name and age: Alice is 28."}]
95
+ for event in client.stream_structured("gpt-4o-mini", messages, schema, max_tokens=64):
96
+ if event.is_partial:
97
+ print("partial:", event.partial_value)
98
+ else:
99
+ print("complete:", event.value)
100
+ ```
101
+
102
+ ### Response Healing
103
+
104
+ ```python
105
+ from simple_agents_py import Client
106
+
107
+ client = Client("openai")
108
+ messages = [{"role": "user", "content": "Return JSON: {\"name\":\"Sam\",\"age\":30}"}]
109
+ healed = client.complete_json_healed("gpt-4o-mini", messages, max_tokens=64)
110
+ print(healed.content)
111
+ print(healed.was_healed, healed.confidence)
112
+ ```
113
+
114
+ ### Tool Calling
115
+
116
+ ```python
117
+ from simple_agents_py import Client
118
+
119
+ client = Client("openai")
120
+ tools = [
121
+ {
122
+ "type": "function",
123
+ "function": {
124
+ "name": "get_weather",
125
+ "description": "Get the weather for a city",
126
+ "parameters": {
127
+ "type": "object",
128
+ "properties": {
129
+ "city": {"type": "string"},
130
+ "unit": {"type": "string", "enum": ["c", "f"]},
131
+ },
132
+ "required": ["city"],
133
+ },
134
+ },
135
+ }
136
+ ]
137
+ messages = [{"role": "user", "content": "What's the weather in Tokyo?"}]
138
+ response = client.complete_with_tools("gpt-4o-mini", messages, tools)
139
+ print(response.tool_calls)
140
+ ```
141
+
142
+ ### ClientBuilder (Routing, Cache, Healing, Middleware)
143
+
144
+ ```python
145
+ from simple_agents_py import ClientBuilder
146
+
147
+ class TimingMiddleware:
148
+ def before_request(self, request):
149
+ print("sending", request.model)
150
+
151
+ builder = (
152
+ ClientBuilder()
153
+ .add_provider("openai", api_key="sk-...")
154
+ .with_routing("direct")
155
+ .with_cache(ttl_seconds=60)
156
+ .with_healing_config({"enabled": True, "min_confidence": 0.7})
157
+ .add_middleware(TimingMiddleware())
158
+ )
159
+ client = builder.build()
160
+ print(client.complete("gpt-4o-mini", "Give me one idea."))
161
+ ```
162
+
48
163
  ## Examples
49
164
 
50
165
  OpenAI with a short prompt:
@@ -58,6 +58,7 @@ pub mod provider;
58
58
  pub mod request;
59
59
  pub mod response;
60
60
  pub mod router;
61
+ pub mod tool;
61
62
  pub mod validation;
62
63
 
63
64
  // Re-export commonly used types at crate root
@@ -101,6 +102,12 @@ pub mod prelude {
101
102
  // Coercion
102
103
  pub use crate::coercion::{CoercionFlag, CoercionResult};
103
104
 
105
+ // Tool calling
106
+ pub use crate::tool::{
107
+ ToolCall, ToolCallFunction, ToolChoice, ToolChoiceFunction, ToolChoiceMode, ToolChoiceTool,
108
+ ToolDefinition, ToolFunction, ToolType,
109
+ };
110
+
104
111
  // Traits
105
112
  pub use crate::cache::Cache;
106
113
  pub use crate::provider::Provider;
@@ -4,6 +4,8 @@
4
4
 
5
5
  use serde::{Deserialize, Serialize};
6
6
 
7
+ use crate::tool::ToolCall;
8
+
7
9
  /// Role of a message in a conversation.
8
10
  #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9
11
  #[serde(rename_all = "lowercase")]
@@ -32,6 +34,9 @@ pub struct Message {
32
34
  /// Tool call ID (for tool role messages)
33
35
  #[serde(skip_serializing_if = "Option::is_none")]
34
36
  pub tool_call_id: Option<String>,
37
+ /// Tool calls emitted by the assistant.
38
+ #[serde(skip_serializing_if = "Option::is_none")]
39
+ pub tool_calls: Option<Vec<ToolCall>>,
35
40
  }
36
41
 
37
42
  impl Message {
@@ -51,6 +56,7 @@ impl Message {
51
56
  content: content.into(),
52
57
  name: None,
53
58
  tool_call_id: None,
59
+ tool_calls: None,
54
60
  }
55
61
  }
56
62
 
@@ -69,6 +75,7 @@ impl Message {
69
75
  content: content.into(),
70
76
  name: None,
71
77
  tool_call_id: None,
78
+ tool_calls: None,
72
79
  }
73
80
  }
74
81
 
@@ -87,6 +94,7 @@ impl Message {
87
94
  content: content.into(),
88
95
  name: None,
89
96
  tool_call_id: None,
97
+ tool_calls: None,
90
98
  }
91
99
  }
92
100
 
@@ -106,6 +114,7 @@ impl Message {
106
114
  content: content.into(),
107
115
  name: None,
108
116
  tool_call_id: Some(tool_call_id.into()),
117
+ tool_calls: None,
109
118
  }
110
119
  }
111
120
 
@@ -122,6 +131,12 @@ impl Message {
122
131
  self.name = Some(name.into());
123
132
  self
124
133
  }
134
+
135
+ /// Set tool calls for assistant messages.
136
+ pub fn with_tool_calls(mut self, tool_calls: Vec<ToolCall>) -> Self {
137
+ self.tool_calls = Some(tool_calls);
138
+ self
139
+ }
125
140
  }
126
141
 
127
142
  #[cfg(test)]
@@ -135,6 +150,7 @@ mod tests {
135
150
  assert_eq!(msg.content, "test");
136
151
  assert_eq!(msg.name, None);
137
152
  assert_eq!(msg.tool_call_id, None);
153
+ assert_eq!(msg.tool_calls, None);
138
154
  }
139
155
 
140
156
  #[test]
@@ -142,6 +158,7 @@ mod tests {
142
158
  let msg = Message::assistant("response");
143
159
  assert_eq!(msg.role, Role::Assistant);
144
160
  assert_eq!(msg.content, "response");
161
+ assert_eq!(msg.tool_calls, None);
145
162
  }
146
163
 
147
164
  #[test]
@@ -149,6 +166,7 @@ mod tests {
149
166
  let msg = Message::system("instruction");
150
167
  assert_eq!(msg.role, Role::System);
151
168
  assert_eq!(msg.content, "instruction");
169
+ assert_eq!(msg.tool_calls, None);
152
170
  }
153
171
 
154
172
  #[test]
@@ -157,6 +175,7 @@ mod tests {
157
175
  assert_eq!(msg.role, Role::Tool);
158
176
  assert_eq!(msg.content, "result");
159
177
  assert_eq!(msg.tool_call_id, Some("call_123".to_string()));
178
+ assert_eq!(msg.tool_calls, None);
160
179
  }
161
180
 
162
181
  #[test]
@@ -194,6 +213,7 @@ mod tests {
194
213
  let json = serde_json::to_value(&msg).unwrap();
195
214
  assert!(json.get("name").is_none());
196
215
  assert!(json.get("tool_call_id").is_none());
216
+ assert!(json.get("tool_calls").is_none());
197
217
  }
198
218
 
199
219
  #[test]
@@ -3,11 +3,12 @@
3
3
  //! Defines the interface for LLM providers with transformation hooks.
4
4
 
5
5
  use crate::config::{Capabilities, RetryConfig};
6
- use crate::error::{ProviderError, Result, SimpleAgentsError};
6
+ use crate::error::Result;
7
7
  use crate::request::CompletionRequest;
8
8
  use crate::response::{CompletionChunk, CompletionResponse};
9
9
  use async_trait::async_trait;
10
10
  use serde::{Deserialize, Serialize};
11
+ use serde_json::Value;
11
12
  use std::borrow::Cow;
12
13
  use std::time::Duration;
13
14
 
@@ -236,11 +237,55 @@ pub trait Provider: Send + Sync {
236
237
  /// ```
237
238
  async fn execute_stream(
238
239
  &self,
239
- _req: ProviderRequest,
240
+ mut req: ProviderRequest,
240
241
  ) -> Result<Box<dyn futures_core::Stream<Item = Result<CompletionChunk>> + Send + Unpin>> {
241
- Err(SimpleAgentsError::Provider(
242
- ProviderError::UnsupportedFeature("streaming".to_string()),
243
- ))
242
+ if let Value::Object(map) = &mut req.body {
243
+ if let Some(stream_value) = map.get_mut("stream") {
244
+ *stream_value = Value::Bool(false);
245
+ }
246
+ }
247
+
248
+ let provider_response = self.execute(req).await?;
249
+ let response = self.transform_response(provider_response)?;
250
+
251
+ struct SingleChunkStream {
252
+ chunk: Option<Result<CompletionChunk>>,
253
+ }
254
+
255
+ impl futures_core::Stream for SingleChunkStream {
256
+ type Item = Result<CompletionChunk>;
257
+
258
+ fn poll_next(
259
+ mut self: std::pin::Pin<&mut Self>,
260
+ _cx: &mut std::task::Context<'_>,
261
+ ) -> std::task::Poll<Option<Self::Item>> {
262
+ std::task::Poll::Ready(self.chunk.take())
263
+ }
264
+ }
265
+
266
+ let choices = response
267
+ .choices
268
+ .into_iter()
269
+ .map(|choice| crate::response::ChoiceDelta {
270
+ index: choice.index,
271
+ delta: crate::response::MessageDelta {
272
+ role: Some(choice.message.role),
273
+ content: Some(choice.message.content),
274
+ },
275
+ finish_reason: Some(choice.finish_reason),
276
+ })
277
+ .collect();
278
+
279
+ let chunk = CompletionChunk {
280
+ id: response.id,
281
+ model: response.model,
282
+ choices,
283
+ created: response.created,
284
+ };
285
+
286
+ Ok(Box::new(SingleChunkStream {
287
+ chunk: Some(Ok(chunk)),
288
+ }))
244
289
  }
245
290
  }
246
291
 
@@ -4,6 +4,7 @@
4
4
 
5
5
  use crate::error::{Result, ValidationError};
6
6
  use crate::message::Message;
7
+ use crate::tool::{ToolChoice, ToolDefinition};
7
8
  use serde::{Deserialize, Serialize};
8
9
  use serde_json::Value;
9
10
 
@@ -72,6 +73,12 @@ pub struct CompletionRequest {
72
73
  /// Response format for structured outputs (OpenAI only)
73
74
  #[serde(skip_serializing_if = "Option::is_none")]
74
75
  pub response_format: Option<ResponseFormat>,
76
+ /// Tool definitions for tool calling.
77
+ #[serde(skip_serializing_if = "Option::is_none")]
78
+ pub tools: Option<Vec<ToolDefinition>>,
79
+ /// Tool choice configuration.
80
+ #[serde(skip_serializing_if = "Option::is_none")]
81
+ pub tool_choice: Option<ToolChoice>,
75
82
  }
76
83
 
77
84
  impl CompletionRequest {
@@ -237,6 +244,8 @@ pub struct CompletionRequestBuilder {
237
244
  frequency_penalty: Option<f32>,
238
245
  user: Option<String>,
239
246
  response_format: Option<ResponseFormat>,
247
+ tools: Option<Vec<ToolDefinition>>,
248
+ tool_choice: Option<ToolChoice>,
240
249
  }
241
250
 
242
251
  impl CompletionRequestBuilder {
@@ -318,6 +327,18 @@ impl CompletionRequestBuilder {
318
327
  self
319
328
  }
320
329
 
330
+ /// Set tool definitions for tool calling.
331
+ pub fn tools(mut self, tools: Vec<ToolDefinition>) -> Self {
332
+ self.tools = Some(tools);
333
+ self
334
+ }
335
+
336
+ /// Set tool choice configuration.
337
+ pub fn tool_choice(mut self, tool_choice: ToolChoice) -> Self {
338
+ self.tool_choice = Some(tool_choice);
339
+ self
340
+ }
341
+
321
342
  /// Enable JSON object mode (no schema validation).
322
343
  pub fn json_mode(mut self) -> Self {
323
344
  self.response_format = Some(ResponseFormat::JsonObject);
@@ -355,6 +376,8 @@ impl CompletionRequestBuilder {
355
376
  frequency_penalty: self.frequency_penalty,
356
377
  user: self.user,
357
378
  response_format: self.response_format,
379
+ tools: self.tools,
380
+ tool_choice: self.tool_choice,
358
381
  };
359
382
 
360
383
  request.validate()?;