calfkit 0.2.4__tar.gz → 0.2.5__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 (259) hide show
  1. calfkit-0.2.5/.release-please-manifest.json +3 -0
  2. {calfkit-0.2.4 → calfkit-0.2.5}/CHANGELOG.md +7 -0
  3. {calfkit-0.2.4 → calfkit-0.2.5}/PKG-INFO +1 -1
  4. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/client/base.py +3 -1
  5. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/client/client.py +14 -2
  6. calfkit-0.2.5/calfkit/models/node_schema.py +21 -0
  7. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/models/session_context.py +2 -1
  8. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/models/state.py +9 -0
  9. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/nodes/agent.py +9 -1
  10. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/nodes/base.py +15 -23
  11. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/nodes/tool.py +18 -15
  12. {calfkit-0.2.4 → calfkit-0.2.5}/pyproject.toml +1 -1
  13. calfkit-0.2.5/tests/conftest.py +374 -0
  14. {calfkit-0.2.4 → calfkit-0.2.5}/tests/providers.py +12 -1
  15. calfkit-0.2.5/tests/test_overrides.py +55 -0
  16. calfkit-0.2.5/tests/test_serializable.py +31 -0
  17. calfkit-0.2.4/.release-please-manifest.json +0 -3
  18. calfkit-0.2.4/tests/conftest.py +0 -157
  19. {calfkit-0.2.4 → calfkit-0.2.5}/.github/CODEOWNERS +0 -0
  20. {calfkit-0.2.4 → calfkit-0.2.5}/.github/dependabot.yml +0 -0
  21. {calfkit-0.2.4 → calfkit-0.2.5}/.github/workflows/build.yml +0 -0
  22. {calfkit-0.2.4 → calfkit-0.2.5}/.github/workflows/code-checks.yml +0 -0
  23. {calfkit-0.2.4 → calfkit-0.2.5}/.github/workflows/release.yml +0 -0
  24. {calfkit-0.2.4 → calfkit-0.2.5}/.github/workflows/security.yml +0 -0
  25. {calfkit-0.2.4 → calfkit-0.2.5}/.github/workflows/test.yml +0 -0
  26. {calfkit-0.2.4 → calfkit-0.2.5}/.gitignore +0 -0
  27. {calfkit-0.2.4 → calfkit-0.2.5}/LICENSE +0 -0
  28. {calfkit-0.2.4 → calfkit-0.2.5}/Makefile +0 -0
  29. {calfkit-0.2.4 → calfkit-0.2.5}/README.md +0 -0
  30. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/__init__.py +0 -0
  31. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_types.py +0 -0
  32. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/__init__.py +0 -0
  33. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/LICENSE +0 -0
  34. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/__init__.py +0 -0
  35. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/__main__.py +0 -0
  36. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_a2a.py +0 -0
  37. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_agent_graph.py +0 -0
  38. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_cli/__init__.py +0 -0
  39. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_cli/web.py +0 -0
  40. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_function_schema.py +0 -0
  41. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_griffe.py +0 -0
  42. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_instrumentation.py +0 -0
  43. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_json_schema.py +0 -0
  44. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_mcp.py +0 -0
  45. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_otel_messages.py +0 -0
  46. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_output.py +0 -0
  47. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_parts_manager.py +0 -0
  48. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_run_context.py +0 -0
  49. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_system_prompt.py +0 -0
  50. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_thinking_part.py +0 -0
  51. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_tool_manager.py +0 -0
  52. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/_utils.py +0 -0
  53. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ag_ui.py +0 -0
  54. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/agent/__init__.py +0 -0
  55. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/agent/abstract.py +0 -0
  56. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/agent/wrapper.py +0 -0
  57. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/builtin_tools.py +0 -0
  58. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/common_tools/__init__.py +0 -0
  59. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/common_tools/duckduckgo.py +0 -0
  60. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/common_tools/exa.py +0 -0
  61. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/common_tools/tavily.py +0 -0
  62. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/direct.py +0 -0
  63. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/__init__.py +0 -0
  64. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/__init__.py +0 -0
  65. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_agent.py +0 -0
  66. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_fastmcp_toolset.py +0 -0
  67. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_mcp.py +0 -0
  68. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_mcp_server.py +0 -0
  69. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_model.py +0 -0
  70. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_utils.py +0 -0
  71. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/__init__.py +0 -0
  72. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_agent.py +0 -0
  73. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_cache_policies.py +0 -0
  74. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_function_toolset.py +0 -0
  75. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_mcp_server.py +0 -0
  76. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_model.py +0 -0
  77. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_toolset.py +0 -0
  78. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_types.py +0 -0
  79. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/__init__.py +0 -0
  80. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_agent.py +0 -0
  81. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_dynamic_toolset.py +0 -0
  82. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_fastmcp_toolset.py +0 -0
  83. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_function_toolset.py +0 -0
  84. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_logfire.py +0 -0
  85. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_mcp.py +0 -0
  86. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_mcp_server.py +0 -0
  87. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_model.py +0 -0
  88. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_run_context.py +0 -0
  89. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_toolset.py +0 -0
  90. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_workflow.py +0 -0
  91. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/__init__.py +0 -0
  92. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/base.py +0 -0
  93. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/cohere.py +0 -0
  94. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/google.py +0 -0
  95. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/instrumented.py +0 -0
  96. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/openai.py +0 -0
  97. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/result.py +0 -0
  98. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/sentence_transformers.py +0 -0
  99. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/settings.py +0 -0
  100. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/test.py +0 -0
  101. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/voyageai.py +0 -0
  102. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/embeddings/wrapper.py +0 -0
  103. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/exceptions.py +0 -0
  104. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ext/__init__.py +0 -0
  105. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ext/aci.py +0 -0
  106. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ext/langchain.py +0 -0
  107. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/format_prompt.py +0 -0
  108. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/mcp.py +0 -0
  109. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/messages.py +0 -0
  110. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/__init__.py +0 -0
  111. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/anthropic.py +0 -0
  112. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/bedrock.py +0 -0
  113. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/cerebras.py +0 -0
  114. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/cohere.py +0 -0
  115. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/fallback.py +0 -0
  116. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/function.py +0 -0
  117. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/gemini.py +0 -0
  118. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/google.py +0 -0
  119. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/groq.py +0 -0
  120. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/huggingface.py +0 -0
  121. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/instrumented.py +0 -0
  122. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/mcp_sampling.py +0 -0
  123. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/mistral.py +0 -0
  124. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/openai.py +0 -0
  125. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/openrouter.py +0 -0
  126. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/outlines.py +0 -0
  127. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/test.py +0 -0
  128. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/wrapper.py +0 -0
  129. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/models/xai.py +0 -0
  130. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/output.py +0 -0
  131. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/__init__.py +0 -0
  132. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/amazon.py +0 -0
  133. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/anthropic.py +0 -0
  134. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/cohere.py +0 -0
  135. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/deepseek.py +0 -0
  136. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/google.py +0 -0
  137. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/grok.py +0 -0
  138. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/groq.py +0 -0
  139. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/harmony.py +0 -0
  140. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/meta.py +0 -0
  141. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/mistral.py +0 -0
  142. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/moonshotai.py +0 -0
  143. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/openai.py +0 -0
  144. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/qwen.py +0 -0
  145. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/profiles/zai.py +0 -0
  146. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/__init__.py +0 -0
  147. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/alibaba.py +0 -0
  148. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/anthropic.py +0 -0
  149. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/azure.py +0 -0
  150. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/bedrock.py +0 -0
  151. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/cerebras.py +0 -0
  152. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/cohere.py +0 -0
  153. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/deepseek.py +0 -0
  154. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/fireworks.py +0 -0
  155. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/gateway.py +0 -0
  156. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/github.py +0 -0
  157. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/google.py +0 -0
  158. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/google_gla.py +0 -0
  159. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/google_vertex.py +0 -0
  160. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/grok.py +0 -0
  161. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/groq.py +0 -0
  162. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/heroku.py +0 -0
  163. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/huggingface.py +0 -0
  164. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/litellm.py +0 -0
  165. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/mistral.py +0 -0
  166. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/moonshotai.py +0 -0
  167. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/nebius.py +0 -0
  168. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/ollama.py +0 -0
  169. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/openai.py +0 -0
  170. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/openrouter.py +0 -0
  171. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/outlines.py +0 -0
  172. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/ovhcloud.py +0 -0
  173. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/sambanova.py +0 -0
  174. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/sentence_transformers.py +0 -0
  175. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/together.py +0 -0
  176. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/vercel.py +0 -0
  177. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/voyageai.py +0 -0
  178. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/providers/xai.py +0 -0
  179. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/py.typed +0 -0
  180. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/result.py +0 -0
  181. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/retries.py +0 -0
  182. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/run.py +0 -0
  183. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/settings.py +0 -0
  184. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/tools.py +0 -0
  185. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/__init__.py +0 -0
  186. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/_dynamic.py +0 -0
  187. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/abstract.py +0 -0
  188. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/approval_required.py +0 -0
  189. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/combined.py +0 -0
  190. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/external.py +0 -0
  191. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/fastmcp.py +0 -0
  192. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/filtered.py +0 -0
  193. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/function.py +0 -0
  194. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/prefixed.py +0 -0
  195. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/prepared.py +0 -0
  196. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/renamed.py +0 -0
  197. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/toolsets/wrapper.py +0 -0
  198. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/__init__.py +0 -0
  199. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/_adapter.py +0 -0
  200. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/_event_stream.py +0 -0
  201. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/_messages_builder.py +0 -0
  202. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/_web/__init__.py +0 -0
  203. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/_web/api.py +0 -0
  204. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/_web/app.py +0 -0
  205. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/ag_ui/__init__.py +0 -0
  206. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/ag_ui/_adapter.py +0 -0
  207. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/ag_ui/_event_stream.py +0 -0
  208. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/ag_ui/app.py +0 -0
  209. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/__init__.py +0 -0
  210. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/_adapter.py +0 -0
  211. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/_event_stream.py +0 -0
  212. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/_models.py +0 -0
  213. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/_utils.py +0 -0
  214. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/request_types.py +0 -0
  215. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/response_types.py +0 -0
  216. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/pydantic_ai/usage.py +0 -0
  217. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/_vendor/vendor.txt +0 -0
  218. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/client/__init__.py +0 -0
  219. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/client/deserialize.py +0 -0
  220. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/client/invocation_handle.py +0 -0
  221. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/client/middleware.py +0 -0
  222. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/client/node_result.py +0 -0
  223. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/client/reply_dispatcher.py +0 -0
  224. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/exceptions.py +0 -0
  225. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/models/__init__.py +0 -0
  226. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/models/actions.py +0 -0
  227. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/models/envelope.py +0 -0
  228. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/models/payload.py +0 -0
  229. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/models/tool_context.py +0 -0
  230. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/nodes/__init__.py +0 -0
  231. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/nodes/node.py +0 -0
  232. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/providers/__init__.py +0 -0
  233. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/providers/pydantic_ai/__init__.py +0 -0
  234. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/providers/pydantic_ai/anthropic.py +0 -0
  235. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/providers/pydantic_ai/model_client.py +0 -0
  236. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/providers/pydantic_ai/openai.py +0 -0
  237. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/worker/__init__.py +0 -0
  238. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/worker/worker.py +0 -0
  239. {calfkit-0.2.4 → calfkit-0.2.5}/calfkit/worker/worker_config.py +0 -0
  240. {calfkit-0.2.4 → calfkit-0.2.5}/codecov.yml +0 -0
  241. {calfkit-0.2.4 → calfkit-0.2.5}/examples/__init__.py +0 -0
  242. {calfkit-0.2.4 → calfkit-0.2.5}/examples/deprecated/agent_dispatcher.py +0 -0
  243. {calfkit-0.2.4 → calfkit-0.2.5}/examples/deprecated/chat_node.py +0 -0
  244. {calfkit-0.2.4 → calfkit-0.2.5}/examples/deprecated/chat_repl_cli.py +0 -0
  245. {calfkit-0.2.4 → calfkit-0.2.5}/examples/deprecated/invoke_agent.py +0 -0
  246. {calfkit-0.2.4 → calfkit-0.2.5}/examples/deprecated/router_node.py +0 -0
  247. {calfkit-0.2.4 → calfkit-0.2.5}/examples/deprecated/tool_nodes.py +0 -0
  248. {calfkit-0.2.4 → calfkit-0.2.5}/examples/quickstart/agent_service.py +0 -0
  249. {calfkit-0.2.4 → calfkit-0.2.5}/examples/quickstart/invoke.py +0 -0
  250. {calfkit-0.2.4 → calfkit-0.2.5}/examples/quickstart/weather_tool.py +0 -0
  251. {calfkit-0.2.4 → calfkit-0.2.5}/examples/rpc_worker.py +0 -0
  252. {calfkit-0.2.4 → calfkit-0.2.5}/release-please-config.json +0 -0
  253. {calfkit-0.2.4 → calfkit-0.2.5}/tests/__init__.py +0 -0
  254. {calfkit-0.2.4 → calfkit-0.2.5}/tests/integration/__init__.py +0 -0
  255. {calfkit-0.2.4 → calfkit-0.2.5}/tests/integration/test_agent_output_types.py +0 -0
  256. {calfkit-0.2.4 → calfkit-0.2.5}/tests/integration/test_agent_workers.py +0 -0
  257. {calfkit-0.2.4 → calfkit-0.2.5}/tests/test_concurrent_tool_calls.py +0 -0
  258. {calfkit-0.2.4 → calfkit-0.2.5}/tests/test_instructions.py +0 -0
  259. {calfkit-0.2.4 → calfkit-0.2.5}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.2.5"
3
+ }
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.5](https://github.com/calf-ai/calfkit-sdk/compare/v0.2.4...v0.2.5) (2026-04-11)
4
+
5
+
6
+ ### Features
7
+
8
+ * add serializable node schemas and runtime tool overrides ([#121](https://github.com/calf-ai/calfkit-sdk/issues/121)) ([e464c08](https://github.com/calf-ai/calfkit-sdk/commit/e464c08e4f179e0cd622789a067718fdbd043c1f))
9
+
3
10
  ## [0.2.4](https://github.com/calf-ai/calfkit-sdk/compare/v0.2.3...v0.2.4) (2026-04-08)
4
11
 
5
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: calfkit
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: Build AI workflows and agents as fully-distributed and event-driven microservices.
5
5
  Project-URL: Homepage, https://github.com/calf-ai/calf-sdk
6
6
  Project-URL: Repository, https://github.com/calf-ai/calf-sdk
@@ -20,6 +20,7 @@ from calfkit.models.session_context import (
20
20
  SessionRunContext,
21
21
  WorkflowState,
22
22
  )
23
+ from calfkit.models.state import OverridesState
23
24
 
24
25
  logger = logging.getLogger(__name__)
25
26
 
@@ -111,6 +112,7 @@ class BaseClient:
111
112
  reply_topic: str,
112
113
  correlation_id: str,
113
114
  state: State,
115
+ overrides: OverridesState | None = None,
114
116
  run_args: Sequence[Any] | None = None,
115
117
  deps: dict[str, Any] | None = None,
116
118
  output_type: type[Any] = _UNSET,
@@ -136,7 +138,7 @@ class BaseClient:
136
138
  await self._connection.start()
137
139
 
138
140
  call_stack = CallFrameStack()
139
- call_stack.push(CallFrame(target_topic=topic, callback_topic=reply_topic, input_args=run_args))
141
+ call_stack.push(CallFrame(target_topic=topic, callback_topic=reply_topic, input_args=run_args, overrides=overrides))
140
142
 
141
143
  envelope = Envelope(
142
144
  internal_workflow_state=WorkflowState(call_stack=call_stack),
@@ -12,6 +12,8 @@ from calfkit.client.deserialize import _UNSET
12
12
  from calfkit.client.invocation_handle import InvocationHandle
13
13
  from calfkit.client.node_result import NodeResult
14
14
  from calfkit.models import State
15
+ from calfkit.models.node_schema import BaseToolNodeSchema
16
+ from calfkit.models.state import OverridesState
15
17
 
16
18
 
17
19
  class Client(BaseClient):
@@ -30,6 +32,7 @@ class Client(BaseClient):
30
32
  topic: str,
31
33
  *,
32
34
  output_type: type[OutputT],
35
+ tool_overrides: list[BaseToolNodeSchema] | None = ...,
33
36
  reply_topic: str | None = ...,
34
37
  correlation_id: str | None = ...,
35
38
  temp_instructions: str | None = ...,
@@ -44,6 +47,7 @@ class Client(BaseClient):
44
47
  user_prompt: str,
45
48
  topic: str,
46
49
  *,
50
+ tool_overrides: list[BaseToolNodeSchema] | None = ...,
47
51
  reply_topic: str | None = ...,
48
52
  correlation_id: str | None = ...,
49
53
  temp_instructions: str | None = ...,
@@ -57,6 +61,7 @@ class Client(BaseClient):
57
61
  user_prompt: str,
58
62
  topic: str,
59
63
  *,
64
+ tool_overrides: list[BaseToolNodeSchema] | None = None,
60
65
  output_type: type[Any] = _UNSET,
61
66
  reply_topic: str | None = None,
62
67
  correlation_id: str | None = None,
@@ -74,6 +79,7 @@ class Client(BaseClient):
74
79
  Args:
75
80
  user_prompt: The user message to send to the agent node.
76
81
  topic: The Kafka topic the target node subscribes to.
82
+ tool_overrides: Runtime agent tool overrides.
77
83
  output_type: The expected Python type for deserializing the agent's
78
84
  output. When omitted, auto-detection is used (``DataPart`` →
79
85
  ``TextPart`` fallback).
@@ -82,7 +88,7 @@ class Client(BaseClient):
82
88
  correlation_id: Unique identifier to correlate this request with its
83
89
  reply. Auto-generated (uuid7) when ``None``.
84
90
  temp_instructions: Optional system-level instructions injected into
85
- the user prompt as a one-shot override.
91
+ the user prompt as a temporary prompt addition.
86
92
  message_history: Prior conversation messages to include for
87
93
  multi-turn context. Defaults to an empty history.
88
94
  run_args: Positional arguments forwarded to the node's ``run()``
@@ -107,6 +113,7 @@ class Client(BaseClient):
107
113
  correlation_id=correlation_id,
108
114
  run_args=run_args,
109
115
  state=state,
116
+ overrides=OverridesState(override_agent_tools=tool_overrides) if tool_overrides is not None else None,
110
117
  deps=deps,
111
118
  output_type=output_type,
112
119
  )
@@ -118,6 +125,7 @@ class Client(BaseClient):
118
125
  topic: str,
119
126
  *,
120
127
  output_type: type[OutputT],
128
+ tool_overrides: list[BaseToolNodeSchema] | None = ...,
121
129
  reply_topic: str | None = ...,
122
130
  correlation_id: str | None = ...,
123
131
  temp_instructions: str | None = ...,
@@ -133,6 +141,7 @@ class Client(BaseClient):
133
141
  user_prompt: str,
134
142
  topic: str,
135
143
  *,
144
+ tool_overrides: list[BaseToolNodeSchema] | None = ...,
136
145
  reply_topic: str | None = ...,
137
146
  correlation_id: str | None = ...,
138
147
  temp_instructions: str | None = ...,
@@ -147,6 +156,7 @@ class Client(BaseClient):
147
156
  user_prompt: str,
148
157
  topic: str,
149
158
  *,
159
+ tool_overrides: list[BaseToolNodeSchema] | None = None,
150
160
  output_type: type[Any] = _UNSET,
151
161
  reply_topic: str | None = None,
152
162
  correlation_id: str | None = None,
@@ -168,6 +178,7 @@ class Client(BaseClient):
168
178
  Args:
169
179
  user_prompt: The user message to send to the agent node.
170
180
  topic: The Kafka topic the target node subscribes to.
181
+ tool_overrides: Runtime agent tool overrides.
171
182
  output_type: The expected Python type for deserializing the agent's
172
183
  output. When omitted, auto-detection is used.
173
184
  reply_topic: Topic the node should publish its reply to.
@@ -175,7 +186,7 @@ class Client(BaseClient):
175
186
  correlation_id: Unique identifier to correlate this request with its
176
187
  reply. Auto-generated (uuid7) when ``None``.
177
188
  temp_instructions: Optional system-level instructions injected into
178
- the user prompt as a one-shot override.
189
+ the user prompt as a temporary prompt addition.
179
190
  message_history: Prior conversation messages to include for
180
191
  multi-turn context. Defaults to an empty history.
181
192
  run_args: Positional arguments forwarded to the node's ``run()``
@@ -195,6 +206,7 @@ class Client(BaseClient):
195
206
  handle = await self.invoke_node(
196
207
  user_prompt,
197
208
  topic,
209
+ tool_overrides=tool_overrides,
198
210
  output_type=output_type,
199
211
  reply_topic=reply_topic,
200
212
  correlation_id=correlation_id,
@@ -0,0 +1,21 @@
1
+ from dataclasses import KW_ONLY, dataclass
2
+
3
+ from calfkit._vendor.pydantic_ai.tools import ToolDefinition
4
+
5
+
6
+ @dataclass
7
+ class BaseNodeSchema:
8
+ _: KW_ONLY
9
+ node_id: str
10
+ subscribe_topics: list[str]
11
+ publish_topic: str | None
12
+
13
+ def __post_init__(self) -> None:
14
+ if not isinstance(self.subscribe_topics, (list, tuple)):
15
+ self.subscribe_topics = [self.subscribe_topics]
16
+
17
+
18
+ @dataclass
19
+ class BaseToolNodeSchema(BaseNodeSchema):
20
+ _: KW_ONLY
21
+ tool_schema: ToolDefinition
@@ -7,7 +7,7 @@ from pydantic import BaseModel, ConfigDict, Field
7
7
 
8
8
  from calfkit._types import DepsT, StackItemT, StateT
9
9
  from calfkit.models.actions import _Call
10
- from calfkit.models.state import State
10
+ from calfkit.models.state import OverridesState, State
11
11
 
12
12
 
13
13
  @dataclass
@@ -36,6 +36,7 @@ class CallFrame:
36
36
  callback_topic: str # return address
37
37
  input_args: Sequence[Any] | None = field(default=None)
38
38
  frame_id: str = field(default_factory=lambda: uuid_utils.uuid7().hex)
39
+ overrides: OverridesState | None = field(default=None)
39
40
 
40
41
 
41
42
  CallFrameStack = Stack[CallFrame]
@@ -11,6 +11,7 @@ from calfkit._vendor.pydantic_ai.messages import (
11
11
  ToolCallPart,
12
12
  )
13
13
  from calfkit._vendor.pydantic_ai.tools import DeferredToolCallResult as ToolCallResult
14
+ from calfkit.models.node_schema import BaseToolNodeSchema
14
15
  from calfkit.models.payload import ContentPart
15
16
 
16
17
 
@@ -18,6 +19,13 @@ class BaseAgentActivityState(BaseModel):
18
19
  model_config = ConfigDict(extra="ignore")
19
20
 
20
21
 
22
+ class OverridesState(BaseAgentActivityState):
23
+ """State for storing any override objects"""
24
+
25
+ model_config = ConfigDict(extra="ignore")
26
+ override_agent_tools: list[BaseToolNodeSchema] | None
27
+
28
+
21
29
  class CoreMessageState(BaseAgentActivityState):
22
30
  """The state for committed messages and structured objects"""
23
31
 
@@ -90,6 +98,7 @@ class State(CoreMessageState, InFlightToolsState):
90
98
  default=None,
91
99
  description="Additional data that can be accessed programmatically by the application but is not sent to the LLM.", # noqa: E501
92
100
  )
101
+ overrides: OverridesState | None = None
93
102
 
94
103
 
95
104
  # class State(BaseModel):
@@ -11,6 +11,7 @@ from calfkit._vendor.pydantic_ai.tools import DeferredToolResults
11
11
  from calfkit._vendor.pydantic_ai.toolsets.external import ExternalToolset
12
12
  from calfkit.models import Call, DataPart, NodeResult, ReturnCall, State, TailCall, TextPart
13
13
  from calfkit.models.actions import Silent
14
+ from calfkit.models.node_schema import BaseToolNodeSchema
14
15
  from calfkit.models.session_context import SessionRunContext
15
16
  from calfkit.models.state import PendingToolBatch
16
17
  from calfkit.nodes.base import BaseNodeDef
@@ -44,6 +45,9 @@ class BaseAgentNodeDef(
44
45
  self.sequential_only_mode = sequential_only_mode
45
46
  self._pending_batches: dict[str, PendingToolBatch] = dict()
46
47
 
48
+ if not isinstance(subscribe_topics, (list, tuple)):
49
+ subscribe_topics = [subscribe_topics]
50
+
47
51
  super().__init__(node_id=node_id, subscribe_topics=subscribe_topics, publish_topic=publish_topic)
48
52
 
49
53
  self._agent_loop: InternalAgentLoop[dict[str, Any], AgentOutputT | DeferredToolRequests] = InternalAgentLoop(
@@ -64,7 +68,11 @@ class BaseAgentNodeDef(
64
68
  del self._pending_batches[ctx.deps.correlation_id]
65
69
 
66
70
  async def run(self, ctx: SessionRunContext) -> NodeResult[State]:
67
- tools_registry = {tool.tool_schema.name: tool for tool in self.tools} if self.tools else dict[str, ToolNodeDef]()
71
+ tools_registry = dict[str, BaseToolNodeSchema]()
72
+ if ctx.state.overrides is not None and ctx.state.overrides.override_agent_tools is not None:
73
+ tools_registry = {tool.tool_schema.name: tool for tool in ctx.state.overrides.override_agent_tools}
74
+ elif self.tools:
75
+ tools_registry = {tool.tool_schema.name: tool for tool in self.tools}
68
76
 
69
77
  logger.debug(
70
78
  "[%s] agent run entered node=%s pending_tool_calls=%d history_len=%d",
@@ -17,6 +17,7 @@ from calfkit.models import (
17
17
  TailCall,
18
18
  )
19
19
  from calfkit.models.envelope import Envelope
20
+ from calfkit.models.node_schema import BaseNodeSchema
20
21
  from calfkit.models.session_context import SessionRunContext
21
22
 
22
23
  logger = logging.getLogger(__name__)
@@ -27,7 +28,7 @@ logger = logging.getLogger(__name__)
27
28
  # ---------------------------------------------------------------------------
28
29
 
29
30
 
30
- class BaseNodeDef:
31
+ class BaseNodeDef(BaseNodeSchema):
31
32
  _run_accepts_input: bool
32
33
 
33
34
  def __init_subclass__(cls, **kwargs: Any) -> None:
@@ -37,21 +38,6 @@ class BaseNodeDef:
37
38
  # If > 2, the subclass declared an input parameter (any name).
38
39
  cls._run_accepts_input = len(sig.parameters) > 2
39
40
 
40
- def __init__(
41
- self,
42
- node_id: str,
43
- *,
44
- subscribe_topics: str | list[str],
45
- publish_topic: str | None,
46
- ):
47
- self._node_id = node_id
48
- if isinstance(subscribe_topics, str):
49
- self.subscribe_topics = [subscribe_topics]
50
- elif subscribe_topics is not None:
51
- self.subscribe_topics = list(subscribe_topics)
52
- self.publish_topic = publish_topic
53
- self._return_topic = f"{node_id}.private.return"
54
-
55
41
  # TODO: consider multiple abstract methods per node based on the incoming communication pattern,
56
42
  # like a delgation or emit. So the communication-specific handler can properly handle it
57
43
  @abstractmethod
@@ -77,6 +63,8 @@ class BaseNodeDef:
77
63
 
78
64
  async def prepare_context(self, envelope: Envelope) -> SessionRunContext:
79
65
  ctx = envelope.context.model_copy(deep=True)
66
+ if envelope.internal_workflow_state.current_frame.overrides:
67
+ ctx.state.overrides = envelope.internal_workflow_state.current_frame.overrides
80
68
  return ctx
81
69
 
82
70
  async def _publish_action(self, output: NodeResult[State], envelope: Envelope, correlation_id: str, broker: BrokerAnnotation) -> Envelope:
@@ -107,7 +95,7 @@ class BaseNodeDef:
107
95
  internal_workflow_state=envelope.internal_workflow_state,
108
96
  )
109
97
  target_topic = envelope.internal_workflow_state.current_frame.target_topic
110
- logger.debug("[%s] Call target=%s frame_pushed node=%s", correlation_id[:8], target_topic, self._node_id)
98
+ logger.debug("[%s] Call target=%s frame_pushed node=%s", correlation_id[:8], target_topic, self.node_id)
111
99
  await broker.publish(
112
100
  publish_envelope,
113
101
  topic=target_topic,
@@ -121,7 +109,7 @@ class BaseNodeDef:
121
109
  context=SessionRunContext(state=output.state, deps=envelope.context.deps),
122
110
  internal_workflow_state=envelope.internal_workflow_state,
123
111
  )
124
- logger.debug("[%s] ReturnCall callback=%s node=%s", correlation_id[:8], frame.callback_topic, self._node_id)
112
+ logger.debug("[%s] ReturnCall callback=%s node=%s", correlation_id[:8], frame.callback_topic, self.node_id)
125
113
  await broker.publish(
126
114
  publish_envelope,
127
115
  topic=frame.callback_topic,
@@ -138,7 +126,7 @@ class BaseNodeDef:
138
126
  internal_workflow_state=envelope.internal_workflow_state,
139
127
  )
140
128
  target_topic = envelope.internal_workflow_state.current_frame.target_topic
141
- logger.debug("[%s] TailCall target=%s node=%s", correlation_id[:8], target_topic, self._node_id)
129
+ logger.debug("[%s] TailCall target=%s node=%s", correlation_id[:8], target_topic, self.node_id)
142
130
  await broker.publish(
143
131
  publish_envelope,
144
132
  topic=target_topic,
@@ -164,21 +152,25 @@ class BaseNodeDef:
164
152
  correlation_id: Annotated[str, Context()],
165
153
  broker: BrokerAnnotation,
166
154
  ) -> Envelope:
167
- logger.debug("[%s] handler entered node=%s", correlation_id[:8], self._node_id)
155
+ logger.debug("[%s] handler entered node=%s", correlation_id[:8], self.node_id)
168
156
  ctx = await self.prepare_context(envelope)
169
157
  if self._run_accepts_input and envelope.internal_workflow_state.current_frame.input_args is not None:
170
158
  output = await self.run(ctx, *envelope.internal_workflow_state.current_frame.input_args)
171
159
  else:
172
160
  output = await self.run(ctx)
173
161
 
174
- logger.debug("[%s] run() returned action=%s node=%s", correlation_id[:8], type(output).__name__, self._node_id)
162
+ logger.debug("[%s] run() returned action=%s node=%s", correlation_id[:8], type(output).__name__, self.node_id)
175
163
 
176
164
  return await self._publish_action(output, envelope, correlation_id, broker)
177
165
 
178
166
  @property
179
167
  def id(self) -> str:
180
- return self._node_id
168
+ return self.node_id
181
169
 
182
170
  @property
183
171
  def name(self) -> str:
184
- return self._node_id
172
+ return self.node_id
173
+
174
+ @property
175
+ def _return_topic(self) -> str:
176
+ return f"{self.node_id}.private.return"
@@ -1,30 +1,37 @@
1
1
  import logging
2
- from abc import ABC, abstractmethod
3
2
  from collections.abc import Awaitable, Callable
4
- from typing import Any, cast
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
5
 
6
- from calfkit._vendor.pydantic_ai import Tool, ToolDefinition
6
+ from typing_extensions import Self
7
+
8
+ from calfkit._vendor.pydantic_ai import Tool
7
9
  from calfkit._vendor.pydantic_ai.messages import ToolReturn
8
10
  from calfkit.models import SessionRunContext, Silent, State, ToolContext
9
11
  from calfkit.models.actions import NodeResult, ReturnCall
12
+ from calfkit.models.node_schema import BaseToolNodeSchema
10
13
  from calfkit.nodes.base import BaseNodeDef
11
14
 
12
15
  logger = logging.getLogger(__name__)
13
16
 
14
17
 
15
- class BaseToolNodeDef(BaseNodeDef, ABC):
16
- @property
17
- @abstractmethod
18
- def tool_schema(self) -> ToolDefinition: ...
18
+ @dataclass
19
+ class BaseToolNodeDef(BaseToolNodeSchema, BaseNodeDef):
20
+ _tool: Tool
19
21
 
20
22
 
21
23
  class ToolNodeDef(BaseToolNodeDef):
22
- def __init__(self, func: Callable[..., Any], subscribe_topics: str | list[str], publish_topic: str):
23
- self._tool = Tool(func)
24
- super().__init__(
24
+ @classmethod
25
+ def create_tool_node(cls, func: Callable[..., Any], subscribe_topics: str | list[str], publish_topic: str) -> Self:
26
+ if not isinstance(subscribe_topics, (list, tuple)):
27
+ subscribe_topics = [subscribe_topics]
28
+ tool = Tool(func)
29
+ return cls(
25
30
  node_id=f"tool_{func.__name__}",
31
+ tool_schema=tool.tool_def,
26
32
  subscribe_topics=subscribe_topics,
27
33
  publish_topic=publish_topic,
34
+ _tool=tool,
28
35
  )
29
36
 
30
37
  async def run(self, ctx: SessionRunContext, tool_call_id: str, source_node_name: str) -> NodeResult[State]:
@@ -78,15 +85,11 @@ class ToolNodeDef(BaseToolNodeDef):
78
85
  logger.debug("[%s] tool completed tool=%s", ctx.deps.correlation_id[:8], self.name)
79
86
  return ReturnCall[State](state=ctx.state)
80
87
 
81
- @property
82
- def tool_schema(self) -> ToolDefinition:
83
- return cast(ToolDefinition, self._tool.tool_def)
84
-
85
88
 
86
89
  def agent_tool(func: Callable[..., Any] | Callable[..., Awaitable[Any]]) -> ToolNodeDef:
87
90
  """Decorator to turn a function into a deployable tool node that agents can call"""
88
91
  subscribe_topic = f"tool.{func.__name__}.input"
89
92
  publish_topic = f"tool.{func.__name__}.output"
90
- tool_node = ToolNodeDef(func=func, subscribe_topics=subscribe_topic, publish_topic=publish_topic)
93
+ tool_node = ToolNodeDef.create_tool_node(func=func, subscribe_topics=subscribe_topic, publish_topic=publish_topic)
91
94
 
92
95
  return tool_node
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "calfkit"
3
- version = "0.2.4"
3
+ version = "0.2.5"
4
4
  description = "Build AI workflows and agents as fully-distributed and event-driven microservices."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"