calfkit 0.2.2__tar.gz → 0.2.4__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.
- {calfkit-0.2.2 → calfkit-0.2.4}/.github/workflows/test.yml +1 -1
- calfkit-0.2.4/.release-please-manifest.json +3 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/CHANGELOG.md +14 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/PKG-INFO +6 -6
- {calfkit-0.2.2 → calfkit-0.2.4}/README.md +4 -4
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/__init__.py +3 -5
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/anthropic.py +2 -2
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/vendor.txt +1 -0
- calfkit-0.2.4/calfkit/providers/__init__.py +5 -0
- calfkit-0.2.4/calfkit/providers/pydantic_ai/__init__.py +4 -0
- calfkit-0.2.4/calfkit/providers/pydantic_ai/anthropic.py +51 -0
- calfkit-0.2.4/calfkit/providers/pydantic_ai/openai.py +142 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/deprecated/router_node.py +0 -1
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/quickstart/agent_service.py +2 -2
- {calfkit-0.2.2 → calfkit-0.2.4}/pyproject.toml +2 -2
- {calfkit-0.2.2 → calfkit-0.2.4}/tests/conftest.py +56 -15
- {calfkit-0.2.2 → calfkit-0.2.4}/tests/providers.py +0 -37
- {calfkit-0.2.2 → calfkit-0.2.4}/tests/test_concurrent_tool_calls.py +1 -1
- calfkit-0.2.2/.release-please-manifest.json +0 -3
- calfkit-0.2.2/calfkit/providers/__init__.py +0 -5
- calfkit-0.2.2/calfkit/providers/pydantic_ai/__init__.py +0 -3
- calfkit-0.2.2/calfkit/providers/pydantic_ai/openai.py +0 -63
- calfkit-0.2.2/calfkit/stores/__init__.py +0 -38
- calfkit-0.2.2/calfkit/stores/base.py +0 -60
- calfkit-0.2.2/calfkit/stores/in_memory.py +0 -38
- {calfkit-0.2.2 → calfkit-0.2.4}/.github/CODEOWNERS +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/.github/dependabot.yml +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/.github/workflows/build.yml +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/.github/workflows/code-checks.yml +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/.github/workflows/release.yml +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/.github/workflows/security.yml +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/.gitignore +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/LICENSE +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/Makefile +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_types.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/LICENSE +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/__main__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_a2a.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_agent_graph.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_cli/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_cli/web.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_function_schema.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_griffe.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_instrumentation.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_json_schema.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_mcp.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_otel_messages.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_output.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_parts_manager.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_run_context.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_system_prompt.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_thinking_part.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_tool_manager.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/_utils.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ag_ui.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/agent/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/agent/abstract.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/agent/wrapper.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/builtin_tools.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/common_tools/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/common_tools/duckduckgo.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/common_tools/exa.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/common_tools/tavily.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/direct.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_agent.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_fastmcp_toolset.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_mcp.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_mcp_server.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_model.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/dbos/_utils.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_agent.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_cache_policies.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_function_toolset.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_mcp_server.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_model.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_toolset.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/prefect/_types.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_agent.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_dynamic_toolset.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_fastmcp_toolset.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_function_toolset.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_logfire.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_mcp.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_mcp_server.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_model.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_run_context.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_toolset.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/durable_exec/temporal/_workflow.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/base.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/cohere.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/google.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/instrumented.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/openai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/result.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/sentence_transformers.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/settings.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/test.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/voyageai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/embeddings/wrapper.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/exceptions.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ext/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ext/aci.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ext/langchain.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/format_prompt.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/mcp.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/messages.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/bedrock.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/cerebras.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/cohere.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/fallback.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/function.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/gemini.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/google.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/groq.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/huggingface.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/instrumented.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/mcp_sampling.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/mistral.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/openai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/openrouter.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/outlines.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/test.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/wrapper.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/models/xai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/output.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/amazon.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/anthropic.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/cohere.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/deepseek.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/google.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/grok.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/groq.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/harmony.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/meta.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/mistral.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/moonshotai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/openai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/qwen.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/profiles/zai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/alibaba.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/anthropic.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/azure.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/bedrock.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/cerebras.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/cohere.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/deepseek.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/fireworks.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/gateway.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/github.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/google.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/google_gla.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/google_vertex.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/grok.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/groq.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/heroku.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/huggingface.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/litellm.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/mistral.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/moonshotai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/nebius.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/ollama.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/openai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/openrouter.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/outlines.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/ovhcloud.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/sambanova.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/sentence_transformers.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/together.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/vercel.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/voyageai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/providers/xai.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/py.typed +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/result.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/retries.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/run.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/settings.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/tools.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/_dynamic.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/abstract.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/approval_required.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/combined.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/external.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/fastmcp.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/filtered.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/function.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/prefixed.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/prepared.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/renamed.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/toolsets/wrapper.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/_adapter.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/_event_stream.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/_messages_builder.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/_web/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/_web/api.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/_web/app.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/ag_ui/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/ag_ui/_adapter.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/ag_ui/_event_stream.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/ag_ui/app.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/_adapter.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/_event_stream.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/_models.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/_utils.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/request_types.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/ui/vercel_ai/response_types.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/_vendor/pydantic_ai/usage.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/client/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/client/base.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/client/client.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/client/deserialize.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/client/invocation_handle.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/client/middleware.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/client/node_result.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/client/reply_dispatcher.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/exceptions.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/models/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/models/actions.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/models/envelope.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/models/payload.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/models/session_context.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/models/state.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/models/tool_context.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/nodes/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/nodes/agent.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/nodes/base.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/nodes/node.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/nodes/tool.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/providers/pydantic_ai/model_client.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/worker/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/worker/worker.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/calfkit/worker/worker_config.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/codecov.yml +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/deprecated/agent_dispatcher.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/deprecated/chat_node.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/deprecated/chat_repl_cli.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/deprecated/invoke_agent.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/deprecated/tool_nodes.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/quickstart/invoke.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/quickstart/weather_tool.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/examples/rpc_worker.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/release-please-config.json +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/tests/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/tests/integration/__init__.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/tests/integration/test_agent_output_types.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/tests/integration/test_agent_workers.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/tests/test_instructions.py +0 -0
- {calfkit-0.2.2 → calfkit-0.2.4}/tests/utils.py +0 -0
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.4](https://github.com/calf-ai/calfkit-sdk/compare/v0.2.3...v0.2.4) (2026-04-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add OpenAI Responses API support ([#119](https://github.com/calf-ai/calfkit-sdk/issues/119)) ([fa1c1a7](https://github.com/calf-ai/calfkit-sdk/commit/fa1c1a7336014a1da3a40de0a1651fdeee722fe4))
|
|
9
|
+
|
|
10
|
+
## [0.2.3](https://github.com/calf-ai/calfkit-sdk/compare/v0.2.2...v0.2.3) (2026-04-02)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* update vendored anthropic imports and add AnthropicModelClient ([#116](https://github.com/calf-ai/calfkit-sdk/issues/116)) ([06c3cc3](https://github.com/calf-ai/calfkit-sdk/commit/06c3cc3749ee9c620ddb91a4bc3dc7d7564842fb))
|
|
16
|
+
|
|
3
17
|
## [0.2.2](https://github.com/calf-ai/calfkit-sdk/compare/v0.2.1...v0.2.2) (2026-04-01)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: calfkit
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
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
|
|
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
20
|
Requires-Python: >=3.10
|
|
21
|
-
Requires-Dist: anthropic>=0.
|
|
21
|
+
Requires-Dist: anthropic>=0.80.0
|
|
22
22
|
Requires-Dist: dishka>=1.9.1
|
|
23
23
|
Requires-Dist: exceptiongroup>=1.2.2; python_version < '3.11'
|
|
24
24
|
Requires-Dist: faststream[kafka]>=0.6.6
|
|
@@ -173,7 +173,7 @@ Deploy the agent as its own service. The `Agent` handles LLM chat, tool orchestr
|
|
|
173
173
|
# agent_service.py
|
|
174
174
|
import asyncio
|
|
175
175
|
from calfkit.nodes import Agent
|
|
176
|
-
from calfkit.providers import
|
|
176
|
+
from calfkit.providers import OpenAIResponsesModelClient
|
|
177
177
|
from calfkit.client import Client
|
|
178
178
|
from calfkit.worker import Worker
|
|
179
179
|
from weather_tool import get_weather # Import the tool definition (reusable)
|
|
@@ -182,7 +182,7 @@ agent = Agent(
|
|
|
182
182
|
"weather_agent",
|
|
183
183
|
system_prompt="You are a helpful assistant.",
|
|
184
184
|
subscribe_topics="weather_agent.input",
|
|
185
|
-
model_client=
|
|
185
|
+
model_client=OpenAIResponsesModelClient(model_name="gpt-5.4-nano"),
|
|
186
186
|
tools=[get_weather], # Register tool definitions with the agent
|
|
187
187
|
)
|
|
188
188
|
|
|
@@ -247,7 +247,7 @@ Agents can be deployed with a `final_output_type` to enforce structured output f
|
|
|
247
247
|
```python
|
|
248
248
|
from dataclasses import dataclass
|
|
249
249
|
from calfkit.nodes import Agent
|
|
250
|
-
from calfkit.providers import
|
|
250
|
+
from calfkit.providers import OpenAIResponsesModelClient
|
|
251
251
|
|
|
252
252
|
@dataclass
|
|
253
253
|
class WeatherReport:
|
|
@@ -258,7 +258,7 @@ agent = Agent(
|
|
|
258
258
|
"weather_agent",
|
|
259
259
|
system_prompt="You are a helpful assistant.",
|
|
260
260
|
subscribe_topics="weather_agent.input",
|
|
261
|
-
model_client=
|
|
261
|
+
model_client=OpenAIResponsesModelClient(model_name="gpt-5.4-nano"),
|
|
262
262
|
final_output_type=WeatherReport, # Enforce structured output
|
|
263
263
|
)
|
|
264
264
|
```
|
|
@@ -135,7 +135,7 @@ Deploy the agent as its own service. The `Agent` handles LLM chat, tool orchestr
|
|
|
135
135
|
# agent_service.py
|
|
136
136
|
import asyncio
|
|
137
137
|
from calfkit.nodes import Agent
|
|
138
|
-
from calfkit.providers import
|
|
138
|
+
from calfkit.providers import OpenAIResponsesModelClient
|
|
139
139
|
from calfkit.client import Client
|
|
140
140
|
from calfkit.worker import Worker
|
|
141
141
|
from weather_tool import get_weather # Import the tool definition (reusable)
|
|
@@ -144,7 +144,7 @@ agent = Agent(
|
|
|
144
144
|
"weather_agent",
|
|
145
145
|
system_prompt="You are a helpful assistant.",
|
|
146
146
|
subscribe_topics="weather_agent.input",
|
|
147
|
-
model_client=
|
|
147
|
+
model_client=OpenAIResponsesModelClient(model_name="gpt-5.4-nano"),
|
|
148
148
|
tools=[get_weather], # Register tool definitions with the agent
|
|
149
149
|
)
|
|
150
150
|
|
|
@@ -209,7 +209,7 @@ Agents can be deployed with a `final_output_type` to enforce structured output f
|
|
|
209
209
|
```python
|
|
210
210
|
from dataclasses import dataclass
|
|
211
211
|
from calfkit.nodes import Agent
|
|
212
|
-
from calfkit.providers import
|
|
212
|
+
from calfkit.providers import OpenAIResponsesModelClient
|
|
213
213
|
|
|
214
214
|
@dataclass
|
|
215
215
|
class WeatherReport:
|
|
@@ -220,7 +220,7 @@ agent = Agent(
|
|
|
220
220
|
"weather_agent",
|
|
221
221
|
system_prompt="You are a helpful assistant.",
|
|
222
222
|
subscribe_topics="weather_agent.input",
|
|
223
|
-
model_client=
|
|
223
|
+
model_client=OpenAIResponsesModelClient(model_name="gpt-5.4-nano"),
|
|
224
224
|
final_output_type=WeatherReport, # Enforce structured output
|
|
225
225
|
)
|
|
226
226
|
```
|
|
@@ -3,8 +3,7 @@ from importlib.metadata import version
|
|
|
3
3
|
from calfkit.client import Client, InvocationHandle, NodeResult
|
|
4
4
|
from calfkit.models import ToolContext
|
|
5
5
|
from calfkit.nodes import Agent, BaseNodeDef, NodeDef, ToolNodeDef, agent_tool
|
|
6
|
-
from calfkit.providers import OpenAIModelClient
|
|
7
|
-
from calfkit.stores import InMemoryMessageHistoryStore, MessageHistoryStore
|
|
6
|
+
from calfkit.providers import AnthropicModelClient, OpenAIModelClient, OpenAIResponsesModelClient
|
|
8
7
|
from calfkit.worker import Worker
|
|
9
8
|
|
|
10
9
|
__version__ = version("calfkit")
|
|
@@ -23,10 +22,9 @@ __all__ = [
|
|
|
23
22
|
"ToolNodeDef",
|
|
24
23
|
"agent_tool",
|
|
25
24
|
# providers
|
|
25
|
+
"AnthropicModelClient",
|
|
26
26
|
"OpenAIModelClient",
|
|
27
|
-
|
|
28
|
-
"InMemoryMessageHistoryStore",
|
|
29
|
-
"MessageHistoryStore",
|
|
27
|
+
"OpenAIResponsesModelClient",
|
|
30
28
|
# worker
|
|
31
29
|
"Worker",
|
|
32
30
|
]
|
|
@@ -136,7 +136,7 @@ try:
|
|
|
136
136
|
from anthropic.types.beta.beta_web_fetch_tool_result_block_param import (
|
|
137
137
|
Content as WebFetchToolResultBlockParamContent,
|
|
138
138
|
)
|
|
139
|
-
from anthropic.types.beta.
|
|
139
|
+
from anthropic.types.beta.beta_user_location_param import BetaUserLocationParam
|
|
140
140
|
from anthropic.types.model_param import ModelParam
|
|
141
141
|
|
|
142
142
|
except ImportError as _import_error:
|
|
@@ -619,7 +619,7 @@ class AnthropicModel(Model):
|
|
|
619
619
|
mcp_servers: list[BetaRequestMCPServerURLDefinitionParam] = []
|
|
620
620
|
for tool in model_request_parameters.builtin_tools:
|
|
621
621
|
if isinstance(tool, WebSearchTool):
|
|
622
|
-
user_location =
|
|
622
|
+
user_location = BetaUserLocationParam(type='approximate', **tool.user_location) if tool.user_location else None
|
|
623
623
|
tools.append(
|
|
624
624
|
BetaWebSearchTool20250305Param(
|
|
625
625
|
name='web_search',
|
|
@@ -11,3 +11,4 @@ pydantic-ai-slim==1.47.0 https://github.com/pydantic/pydantic-ai
|
|
|
11
11
|
# - _run_context.py: Made model/usage optional with defaults for ToolContext construction
|
|
12
12
|
# - _function_schema.py: _is_call_ctx() recognizes RunContext subclasses
|
|
13
13
|
# - messages.py: Added `retry_prompt` classmethod to ModelRequest
|
|
14
|
+
# - models/anthropic.py: UserLocation -> BetaUserLocationParam (anthropic SDK 0.80.0 rename)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from typing import Any, Literal
|
|
2
|
+
|
|
3
|
+
from httpx import Timeout
|
|
4
|
+
|
|
5
|
+
from calfkit._vendor.pydantic_ai.models.anthropic import AnthropicModel, AnthropicModelSettings
|
|
6
|
+
from calfkit._vendor.pydantic_ai.providers.anthropic import AnthropicProvider
|
|
7
|
+
from calfkit.providers.pydantic_ai.model_client import PydanticModelClient
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AnthropicModelClient(AnthropicModel, PydanticModelClient):
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
model_name: str,
|
|
14
|
+
*,
|
|
15
|
+
base_url: str | None = None,
|
|
16
|
+
api_key: str | None = None,
|
|
17
|
+
max_tokens: int | None = None,
|
|
18
|
+
temperature: float | None = None,
|
|
19
|
+
top_p: float | None = None,
|
|
20
|
+
timeout: float | Timeout | None = None,
|
|
21
|
+
parallel_tool_calls: bool | None = None,
|
|
22
|
+
anthropic_thinking: dict[str, Any] | None = None,
|
|
23
|
+
anthropic_cache_tool_definitions: bool | Literal["5m", "1h"] | None = None,
|
|
24
|
+
anthropic_cache_instructions: bool | Literal["5m", "1h"] | None = None,
|
|
25
|
+
anthropic_cache_messages: bool | Literal["5m", "1h"] | None = None,
|
|
26
|
+
**kwargs: Any,
|
|
27
|
+
):
|
|
28
|
+
settings_kwargs: dict[str, object] = {}
|
|
29
|
+
if max_tokens is not None:
|
|
30
|
+
settings_kwargs["max_tokens"] = max_tokens
|
|
31
|
+
if temperature is not None:
|
|
32
|
+
settings_kwargs["temperature"] = temperature
|
|
33
|
+
if top_p is not None:
|
|
34
|
+
settings_kwargs["top_p"] = top_p
|
|
35
|
+
if timeout is not None:
|
|
36
|
+
settings_kwargs["timeout"] = timeout
|
|
37
|
+
if parallel_tool_calls is not None:
|
|
38
|
+
settings_kwargs["parallel_tool_calls"] = parallel_tool_calls
|
|
39
|
+
if anthropic_thinking is not None:
|
|
40
|
+
settings_kwargs["anthropic_thinking"] = anthropic_thinking
|
|
41
|
+
if anthropic_cache_tool_definitions is not None:
|
|
42
|
+
settings_kwargs["anthropic_cache_tool_definitions"] = anthropic_cache_tool_definitions
|
|
43
|
+
if anthropic_cache_instructions is not None:
|
|
44
|
+
settings_kwargs["anthropic_cache_instructions"] = anthropic_cache_instructions
|
|
45
|
+
if anthropic_cache_messages is not None:
|
|
46
|
+
settings_kwargs["anthropic_cache_messages"] = anthropic_cache_messages
|
|
47
|
+
model_settings: AnthropicModelSettings = AnthropicModelSettings(**settings_kwargs, **kwargs) # type: ignore[typeddict-item]
|
|
48
|
+
|
|
49
|
+
anthropic_client = AnthropicProvider(api_key=api_key, base_url=base_url)
|
|
50
|
+
self.model_settings = model_settings
|
|
51
|
+
super().__init__(model_name, provider=anthropic_client, settings=model_settings)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
from typing import Any, Literal
|
|
2
|
+
|
|
3
|
+
from httpx import Timeout
|
|
4
|
+
|
|
5
|
+
from calfkit._vendor.pydantic_ai.models.openai import (
|
|
6
|
+
OpenAIChatModel,
|
|
7
|
+
OpenAIChatModelSettings,
|
|
8
|
+
OpenAIResponsesModel,
|
|
9
|
+
OpenAIResponsesModelSettings,
|
|
10
|
+
)
|
|
11
|
+
from calfkit._vendor.pydantic_ai.providers.openai import OpenAIProvider
|
|
12
|
+
from calfkit.providers.pydantic_ai.model_client import PydanticModelClient
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class OpenAIModelClient(OpenAIChatModel, PydanticModelClient):
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
model_name: str,
|
|
19
|
+
*,
|
|
20
|
+
base_url: str | None = None,
|
|
21
|
+
api_key: str | None = None,
|
|
22
|
+
reasoning_effort: str | None = None,
|
|
23
|
+
max_tokens: int | None = None,
|
|
24
|
+
temperature: float | None = None,
|
|
25
|
+
top_p: float | None = None,
|
|
26
|
+
timeout: float | Timeout | None = None,
|
|
27
|
+
parallel_tool_calls: bool | None = None,
|
|
28
|
+
seed: int | None = None,
|
|
29
|
+
presence_penalty: float | None = None,
|
|
30
|
+
frequency_penalty: float | None = None,
|
|
31
|
+
logit_bias: dict[str, int] | None = None,
|
|
32
|
+
stop_sequences: list[str] | None = None,
|
|
33
|
+
extra_headers: dict[str, str] | None = None,
|
|
34
|
+
extra_body: object | None = None,
|
|
35
|
+
**kwargs: Any,
|
|
36
|
+
):
|
|
37
|
+
settings_kwargs: dict[str, object] = {}
|
|
38
|
+
if reasoning_effort is not None:
|
|
39
|
+
settings_kwargs["openai_reasoning_effort"] = reasoning_effort
|
|
40
|
+
if max_tokens is not None:
|
|
41
|
+
settings_kwargs["max_tokens"] = max_tokens
|
|
42
|
+
if temperature is not None:
|
|
43
|
+
settings_kwargs["temperature"] = temperature
|
|
44
|
+
if top_p is not None:
|
|
45
|
+
settings_kwargs["top_p"] = top_p
|
|
46
|
+
if timeout is not None:
|
|
47
|
+
settings_kwargs["timeout"] = timeout
|
|
48
|
+
if parallel_tool_calls is not None:
|
|
49
|
+
settings_kwargs["parallel_tool_calls"] = parallel_tool_calls
|
|
50
|
+
if seed is not None:
|
|
51
|
+
settings_kwargs["seed"] = seed
|
|
52
|
+
if presence_penalty is not None:
|
|
53
|
+
settings_kwargs["presence_penalty"] = presence_penalty
|
|
54
|
+
if frequency_penalty is not None:
|
|
55
|
+
settings_kwargs["frequency_penalty"] = frequency_penalty
|
|
56
|
+
if logit_bias is not None:
|
|
57
|
+
settings_kwargs["logit_bias"] = logit_bias
|
|
58
|
+
if stop_sequences is not None:
|
|
59
|
+
settings_kwargs["stop_sequences"] = stop_sequences
|
|
60
|
+
if extra_headers is not None:
|
|
61
|
+
settings_kwargs["extra_headers"] = extra_headers
|
|
62
|
+
if extra_body is not None:
|
|
63
|
+
settings_kwargs["extra_body"] = extra_body
|
|
64
|
+
model_settings: OpenAIChatModelSettings = OpenAIChatModelSettings(**settings_kwargs, **kwargs) # type: ignore[typeddict-item]
|
|
65
|
+
|
|
66
|
+
openai_client = OpenAIProvider(base_url=base_url, api_key=api_key)
|
|
67
|
+
self.model_settings = model_settings
|
|
68
|
+
super().__init__(model_name, provider=openai_client, settings=model_settings)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class OpenAIResponsesModelClient(OpenAIResponsesModel, PydanticModelClient):
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
model_name: str,
|
|
75
|
+
*,
|
|
76
|
+
base_url: str | None = None,
|
|
77
|
+
api_key: str | None = None,
|
|
78
|
+
reasoning_effort: str | None = None,
|
|
79
|
+
reasoning_summary: Literal["detailed", "concise", "auto"] | None = None,
|
|
80
|
+
max_tokens: int | None = None,
|
|
81
|
+
temperature: float | None = None,
|
|
82
|
+
top_p: float | None = None,
|
|
83
|
+
timeout: float | Timeout | None = None,
|
|
84
|
+
parallel_tool_calls: bool | None = None,
|
|
85
|
+
truncation: Literal["disabled", "auto"] | None = None,
|
|
86
|
+
text_verbosity: Literal["low", "medium", "high"] | None = None,
|
|
87
|
+
previous_response_id: Literal["auto"] | str | None = None,
|
|
88
|
+
send_reasoning_ids: bool | None = None,
|
|
89
|
+
user: str | None = None,
|
|
90
|
+
service_tier: Literal["auto", "default", "flex", "priority"] | None = None,
|
|
91
|
+
logprobs: bool | None = None,
|
|
92
|
+
top_logprobs: int | None = None,
|
|
93
|
+
prompt_cache_key: str | None = None,
|
|
94
|
+
prompt_cache_retention: Literal["in-memory", "24h"] | None = None,
|
|
95
|
+
extra_headers: dict[str, str] | None = None,
|
|
96
|
+
extra_body: object | None = None,
|
|
97
|
+
**kwargs: Any,
|
|
98
|
+
):
|
|
99
|
+
settings_kwargs: dict[str, object] = {}
|
|
100
|
+
if reasoning_effort is not None:
|
|
101
|
+
settings_kwargs["openai_reasoning_effort"] = reasoning_effort
|
|
102
|
+
if reasoning_summary is not None:
|
|
103
|
+
settings_kwargs["openai_reasoning_summary"] = reasoning_summary
|
|
104
|
+
if max_tokens is not None:
|
|
105
|
+
settings_kwargs["max_tokens"] = max_tokens
|
|
106
|
+
if temperature is not None:
|
|
107
|
+
settings_kwargs["temperature"] = temperature
|
|
108
|
+
if top_p is not None:
|
|
109
|
+
settings_kwargs["top_p"] = top_p
|
|
110
|
+
if timeout is not None:
|
|
111
|
+
settings_kwargs["timeout"] = timeout
|
|
112
|
+
if parallel_tool_calls is not None:
|
|
113
|
+
settings_kwargs["parallel_tool_calls"] = parallel_tool_calls
|
|
114
|
+
if truncation is not None:
|
|
115
|
+
settings_kwargs["openai_truncation"] = truncation
|
|
116
|
+
if text_verbosity is not None:
|
|
117
|
+
settings_kwargs["openai_text_verbosity"] = text_verbosity
|
|
118
|
+
if previous_response_id is not None:
|
|
119
|
+
settings_kwargs["openai_previous_response_id"] = previous_response_id
|
|
120
|
+
if send_reasoning_ids is not None:
|
|
121
|
+
settings_kwargs["openai_send_reasoning_ids"] = send_reasoning_ids
|
|
122
|
+
if user is not None:
|
|
123
|
+
settings_kwargs["openai_user"] = user
|
|
124
|
+
if service_tier is not None:
|
|
125
|
+
settings_kwargs["openai_service_tier"] = service_tier
|
|
126
|
+
if logprobs is not None:
|
|
127
|
+
settings_kwargs["openai_logprobs"] = logprobs
|
|
128
|
+
if top_logprobs is not None:
|
|
129
|
+
settings_kwargs["openai_top_logprobs"] = top_logprobs
|
|
130
|
+
if prompt_cache_key is not None:
|
|
131
|
+
settings_kwargs["openai_prompt_cache_key"] = prompt_cache_key
|
|
132
|
+
if prompt_cache_retention is not None:
|
|
133
|
+
settings_kwargs["openai_prompt_cache_retention"] = prompt_cache_retention
|
|
134
|
+
if extra_headers is not None:
|
|
135
|
+
settings_kwargs["extra_headers"] = extra_headers
|
|
136
|
+
if extra_body is not None:
|
|
137
|
+
settings_kwargs["extra_body"] = extra_body
|
|
138
|
+
model_settings: OpenAIResponsesModelSettings = OpenAIResponsesModelSettings(**settings_kwargs, **kwargs) # type: ignore[typeddict-item]
|
|
139
|
+
|
|
140
|
+
openai_client = OpenAIProvider(base_url=base_url, api_key=api_key)
|
|
141
|
+
self.model_settings = model_settings
|
|
142
|
+
super().__init__(model_name, provider=openai_client, settings=model_settings)
|
|
@@ -4,7 +4,6 @@ from calfkit.broker.broker import BrokerClient
|
|
|
4
4
|
from calfkit.nodes.agent_router_node import AgentRouterNode
|
|
5
5
|
from calfkit.nodes.chat_node import ChatNode
|
|
6
6
|
from calfkit.runners.service import NodesService
|
|
7
|
-
|
|
8
7
|
from calfkit.stores.in_memory import InMemoryMessageHistoryStore
|
|
9
8
|
|
|
10
9
|
# Import tools from tool_nodes - router needs schemas for LLM and topic routing
|
|
@@ -4,14 +4,14 @@ from weather_tool import get_weather # Import the tool definition (reusable)
|
|
|
4
4
|
|
|
5
5
|
from calfkit.client import Client
|
|
6
6
|
from calfkit.nodes import Agent
|
|
7
|
-
from calfkit.providers import
|
|
7
|
+
from calfkit.providers import OpenAIResponsesModelClient
|
|
8
8
|
from calfkit.worker import Worker
|
|
9
9
|
|
|
10
10
|
agent = Agent(
|
|
11
11
|
"weather_agent",
|
|
12
12
|
system_prompt="You are a helpful assistant.",
|
|
13
13
|
subscribe_topics="weather_agent.input",
|
|
14
|
-
model_client=
|
|
14
|
+
model_client=OpenAIResponsesModelClient(model_name="gpt-5.4-nano"),
|
|
15
15
|
tools=[get_weather], # Register tool definitions with the agent
|
|
16
16
|
)
|
|
17
17
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "calfkit"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.4"
|
|
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"
|
|
@@ -33,7 +33,7 @@ dependencies = [
|
|
|
33
33
|
"exceptiongroup>=1.2.2; python_version < '3.11'",
|
|
34
34
|
# Provider SDKs
|
|
35
35
|
"openai>=1.0.0",
|
|
36
|
-
"anthropic>=0.
|
|
36
|
+
"anthropic>=0.80.0",
|
|
37
37
|
"typing-extensions>=4.15.0",
|
|
38
38
|
"dishka>=1.9.1",
|
|
39
39
|
]
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
+
import os
|
|
1
2
|
from collections.abc import Callable
|
|
3
|
+
from typing import Any
|
|
2
4
|
|
|
3
5
|
import pytest
|
|
4
6
|
from dishka import make_container
|
|
7
|
+
from dotenv import load_dotenv
|
|
5
8
|
|
|
6
9
|
from calfkit._types import OutputT
|
|
7
10
|
from calfkit._vendor.pydantic_ai.models.function import FunctionModel
|
|
8
11
|
from calfkit.nodes import Agent, ToolNodeDef
|
|
9
|
-
from calfkit.providers.pydantic_ai.
|
|
12
|
+
from calfkit.providers.pydantic_ai.openai import OpenAIModelClient, OpenAIResponsesModelClient
|
|
10
13
|
from calfkit.worker import Worker
|
|
11
14
|
from tests.providers import (
|
|
12
15
|
INSTRUCTIONS_TEST_SYSTEM_PROMPT,
|
|
13
16
|
AgentProvider,
|
|
14
17
|
ClientProvider,
|
|
15
18
|
ContextualTool,
|
|
19
|
+
Response,
|
|
16
20
|
SimpleAgent,
|
|
17
21
|
StructuredAgent,
|
|
18
22
|
WorkerProvider,
|
|
@@ -20,6 +24,8 @@ from tests.providers import (
|
|
|
20
24
|
echo_instructions,
|
|
21
25
|
)
|
|
22
26
|
|
|
27
|
+
load_dotenv()
|
|
28
|
+
|
|
23
29
|
|
|
24
30
|
@pytest.fixture
|
|
25
31
|
def container():
|
|
@@ -29,25 +35,40 @@ def container():
|
|
|
29
35
|
|
|
30
36
|
|
|
31
37
|
@pytest.fixture(params=["parallel", "sequential"])
|
|
32
|
-
def
|
|
38
|
+
def agent_constructor_args_sequential_modes(request) -> dict[str, bool]:
|
|
33
39
|
mode: str = request.param
|
|
40
|
+
return {"sequential_only_mode": mode == "sequential"}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@pytest.fixture(params=["openai_responses", "openai_chat"])
|
|
44
|
+
def agent_constructor_args_model_client(request) -> dict[str, Any]:
|
|
45
|
+
model_type: str = request.param
|
|
46
|
+
if model_type == "openai_chat":
|
|
47
|
+
model_client = OpenAIModelClient(os.environ["TEST_LLM_MODEL_NAME"], reasoning_effort=os.getenv("TEST_REASONING_EFFORT"))
|
|
48
|
+
return {"model_client": model_client}
|
|
49
|
+
elif model_type == "openai_responses":
|
|
50
|
+
model_client = OpenAIResponsesModelClient(os.environ["TEST_LLM_MODEL_NAME"], reasoning_effort=os.getenv("TEST_REASONING_EFFORT"))
|
|
51
|
+
return {"model_client": model_client}
|
|
52
|
+
else:
|
|
53
|
+
raise RuntimeError(f"Invalid model client: {model_type}")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@pytest.fixture
|
|
57
|
+
def deploy_agent(agent_constructor_args_model_client, container) -> SimpleAgent:
|
|
34
58
|
worker = container.get(Worker)
|
|
35
|
-
model_client = container.get(PydanticModelClient)
|
|
36
59
|
agent = SimpleAgent(
|
|
37
60
|
"test_simple_agent",
|
|
38
61
|
system_prompt=f"You are a helpful AI assistant. Your name is {agent_name}. Help the user with their questions as much as possible.",
|
|
39
62
|
subscribe_topics="test_agent.input",
|
|
40
63
|
publish_topic="test_agent.output",
|
|
41
|
-
|
|
42
|
-
sequential_only_mode=mode == "sequential",
|
|
64
|
+
**agent_constructor_args_model_client,
|
|
43
65
|
)
|
|
44
66
|
worker.add_nodes(agent)
|
|
45
67
|
return agent
|
|
46
68
|
|
|
47
69
|
|
|
48
|
-
@pytest.fixture
|
|
49
|
-
def deploy_function_agent(
|
|
50
|
-
mode: str = request.param
|
|
70
|
+
@pytest.fixture
|
|
71
|
+
def deploy_function_agent(agent_constructor_args_sequential_modes, container) -> Agent:
|
|
51
72
|
worker = container.get(Worker)
|
|
52
73
|
model = container.get(FunctionModel)
|
|
53
74
|
agent = Agent(
|
|
@@ -56,25 +77,45 @@ def deploy_function_agent(request, container) -> Agent:
|
|
|
56
77
|
subscribe_topics="test_function_agent.input",
|
|
57
78
|
publish_topic="test_function_agent.output",
|
|
58
79
|
model_client=model,
|
|
59
|
-
|
|
80
|
+
**agent_constructor_args_sequential_modes,
|
|
60
81
|
)
|
|
61
|
-
print(f"\nDeployed agent with sequential_only_mode={
|
|
82
|
+
print(f"\nDeployed agent with sequential_only_mode={agent_constructor_args_sequential_modes}")
|
|
62
83
|
worker.add_nodes(agent)
|
|
63
84
|
return agent
|
|
64
85
|
|
|
65
86
|
|
|
66
87
|
@pytest.fixture
|
|
67
|
-
def deploy_structured_agent(container) -> StructuredAgent:
|
|
88
|
+
def deploy_structured_agent(agent_constructor_args_model_client, container) -> StructuredAgent:
|
|
68
89
|
worker = container.get(Worker)
|
|
69
|
-
agent =
|
|
90
|
+
agent = StructuredAgent(
|
|
91
|
+
"test_structured_agent",
|
|
92
|
+
system_prompt=f"You are a helpful AI assistant. Your name is {agent_name}. Help the user with their questions as much as possible.",
|
|
93
|
+
subscribe_topics="test_agent.input",
|
|
94
|
+
publish_topic="test_agent.output",
|
|
95
|
+
final_output_type=Response,
|
|
96
|
+
**agent_constructor_args_model_client,
|
|
97
|
+
)
|
|
70
98
|
worker.add_nodes(agent)
|
|
71
99
|
return agent
|
|
72
100
|
|
|
73
101
|
|
|
74
102
|
@pytest.fixture
|
|
75
|
-
def deploy_structured_agent_factory(container) -> Callable[..., Agent[OutputT]]:
|
|
76
|
-
|
|
77
|
-
|
|
103
|
+
def deploy_structured_agent_factory(agent_constructor_args_model_client, container) -> Callable[..., Agent[OutputT]]:
|
|
104
|
+
worker = container.get(Worker)
|
|
105
|
+
|
|
106
|
+
def agent_factory(output_type: type[OutputT]) -> Agent[OutputT]:
|
|
107
|
+
agent = Agent[output_type](
|
|
108
|
+
"test_custom_structured_agent",
|
|
109
|
+
system_prompt=f"You are a helpful AI assistant. Your name is {agent_name}. Help the user with their questions as much as possible.",
|
|
110
|
+
subscribe_topics="test_agent.input",
|
|
111
|
+
publish_topic="test_agent.output",
|
|
112
|
+
final_output_type=output_type,
|
|
113
|
+
**agent_constructor_args_model_client,
|
|
114
|
+
)
|
|
115
|
+
worker.add_nodes(agent)
|
|
116
|
+
return agent
|
|
117
|
+
|
|
118
|
+
return agent_factory
|
|
78
119
|
|
|
79
120
|
|
|
80
121
|
@pytest.fixture
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from collections.abc import Callable
|
|
3
1
|
from dataclasses import dataclass
|
|
4
2
|
from typing import NewType
|
|
5
3
|
|
|
@@ -7,14 +5,11 @@ from dishka import AnyOf, Provider, Scope, provide
|
|
|
7
5
|
from dotenv import load_dotenv
|
|
8
6
|
from faststream.kafka import KafkaBroker
|
|
9
7
|
|
|
10
|
-
from calfkit._types import OutputT
|
|
11
8
|
from calfkit._vendor.pydantic_ai.messages import ModelMessage, ModelRequest, ModelResponse, TextPart, ToolCallPart, ToolReturnPart
|
|
12
9
|
from calfkit._vendor.pydantic_ai.models.function import AgentInfo, FunctionModel
|
|
13
10
|
from calfkit.client import Client
|
|
14
11
|
from calfkit.models.tool_context import ToolContext
|
|
15
12
|
from calfkit.nodes import Agent, BaseToolNodeDef, ToolNodeDef, agent_tool
|
|
16
|
-
from calfkit.providers.pydantic_ai.model_client import PydanticModelClient
|
|
17
|
-
from calfkit.providers.pydantic_ai.openai import OpenAIModelClient
|
|
18
13
|
from calfkit.worker import Worker
|
|
19
14
|
|
|
20
15
|
load_dotenv()
|
|
@@ -120,42 +115,10 @@ ContextualTool = NewType("ContextualTool", ToolNodeDef)
|
|
|
120
115
|
class AgentProvider(Provider):
|
|
121
116
|
scope = Scope.APP
|
|
122
117
|
|
|
123
|
-
@provide
|
|
124
|
-
def get_model_client(self) -> PydanticModelClient:
|
|
125
|
-
return OpenAIModelClient(os.environ["TEST_LLM_MODEL_NAME"], reasoning_effort=os.getenv("TEST_REASONING_EFFORT"))
|
|
126
|
-
|
|
127
118
|
@provide
|
|
128
119
|
def get_function_model(self) -> FunctionModel:
|
|
129
120
|
return FunctionModel(call_all_tools_concurrently)
|
|
130
121
|
|
|
131
|
-
@provide
|
|
132
|
-
def get_structured_agent_factory(self, model_client: PydanticModelClient, worker: Worker) -> Callable:
|
|
133
|
-
def factory(output_type: type[OutputT]) -> Agent[OutputT]:
|
|
134
|
-
agent = Agent[output_type](
|
|
135
|
-
"test_custom_structured_agent",
|
|
136
|
-
system_prompt=f"You are a helpful AI assistant. Your name is {agent_name}. Help the user with their questions as much as possible.",
|
|
137
|
-
subscribe_topics="test_agent.input",
|
|
138
|
-
publish_topic="test_agent.output",
|
|
139
|
-
model_client=model_client,
|
|
140
|
-
final_output_type=output_type,
|
|
141
|
-
)
|
|
142
|
-
worker.add_nodes(agent)
|
|
143
|
-
|
|
144
|
-
return agent
|
|
145
|
-
|
|
146
|
-
return factory
|
|
147
|
-
|
|
148
|
-
@provide
|
|
149
|
-
def get_structured_agent(self, model_client: PydanticModelClient) -> StructuredAgent:
|
|
150
|
-
return StructuredAgent(
|
|
151
|
-
"test_structured_agent",
|
|
152
|
-
system_prompt=f"You are a helpful AI assistant. Your name is {agent_name}. Help the user with their questions as much as possible.",
|
|
153
|
-
subscribe_topics="test_agent.input",
|
|
154
|
-
publish_topic="test_agent.output",
|
|
155
|
-
model_client=model_client,
|
|
156
|
-
final_output_type=Response,
|
|
157
|
-
)
|
|
158
|
-
|
|
159
122
|
@provide
|
|
160
123
|
def get_multiple_tools(self) -> AnyOf[list[BaseToolNodeDef], list[ToolNodeDef]]:
|
|
161
124
|
return [agent_tool(get_users_name), agent_tool(weather), agent_tool(get_users_birthday)]
|
|
@@ -20,7 +20,7 @@ async def test_concurrent_tool_calling(container, deploy_function_agent, deploy_
|
|
|
20
20
|
random_str = "".join(random.choices(string.ascii_letters, k=20)) # 20 char random string
|
|
21
21
|
random_city = Faker().city()
|
|
22
22
|
result = await client.execute_node(
|
|
23
|
-
"Hey! Call all your tools
|
|
23
|
+
"Hey! Call all your tools concurrently right now",
|
|
24
24
|
deploy_function_agent.subscribe_topics[0],
|
|
25
25
|
deps={"random_number": random_num, "random_string": random_str, "random_city": random_city},
|
|
26
26
|
)
|