uipath-langchain 0.0.144__tar.gz → 0.0.146__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.
Potentially problematic release.
This version of uipath-langchain might be problematic. Click here for more details.
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/PKG-INFO +2 -2
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/pyproject.toml +3 -3
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_runtime/_runtime.py +19 -0
- uipath_langchain-0.0.146/src/uipath_langchain/_cli/_utils/_schema.py +137 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/cli_eval.py +3 -9
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/cli_init.py +13 -86
- uipath_langchain-0.0.146/src/uipath_langchain/runtime_factories.py +21 -0
- uipath_langchain-0.0.146/tests/cli/test_schema.py +266 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/uv.lock +138 -124
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.cursorrules +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.editorconfig +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.gitattributes +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/cd.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/ci.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/commitlint.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/integration_tests.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/lint-custom-version.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/lint.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/publish-dev.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/publish-docs.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/publish-prior-stable-version.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/slack.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/test-custom-version.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.github/workflows/test.yml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.gitignore +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.pre-commit-config.yaml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.python-version +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.vscode/extensions.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/.vscode/settings.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/CONTRIBUTING.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/LICENSE +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/chat_models.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/context_grounding.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/human_in_the_loop.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/quick_start.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/quick_start_images/cloud_env_var_dark.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/quick_start_images/cloud_env_var_light.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/quick_start_images/invoke_output_dark.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/quick_start_images/invoke_output_light.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/click-storage-bucket.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/create-index-1.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/create-index-2.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/create-process.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/create-quiz-generator.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/create-storage-bucket-1.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/create-storage-bucket-2.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/folder-path.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/job-info.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/output.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/process-page.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/researcher-1.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/researcher-2.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/run-process-1.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/run-process-2.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/RAG/storage-bucket-content.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/multi-agent-distributed/coder-agent-package-overview.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/multi-agent-distributed/coder-agent-process-configuration.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/multi-agent-distributed/planner-agent-package-overview.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/multi-agent-distributed/planner-agent-process-configuration.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/multi-agent-distributed/researcher-agent-package-overview.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/multi-agent-distributed/researcher-agent-process-configuration.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/activate-apps.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/activate-deployment.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/copy-folder-path.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/deploy-solution-package-wizard.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/deploy-solution-package.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/monitor-agent.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/navigate-to-solution-folder.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/resume-condition.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/run-agent.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/solution-destination-folder.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/start-job.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/docs/sample_images/ticket-classification/upload-solution-package.png +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/env.example +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/input.example/quiz-generator-debug-input.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/input.example/researcher-debug-input.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/quiz-generator-RAG-agent.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/researcher-RAG-agent.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/src/agents/quiz-generator-RAG-agent.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/src/agents/researcher-RAG-agent.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/RAG-quiz-generator/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/calculator-agent/graph.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/calculator-agent/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/calculator-agent/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/calculator-agent/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/calculator-agent/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/chat-agent/.env.example +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/chat-agent/agent.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/chat-agent/graph.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/chat-agent/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/chat-agent/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/chat-agent/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/chat-agent/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/company-research-agent/.env.example +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/company-research-agent/agent.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/company-research-agent/graph.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/company-research-agent/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/company-research-agent/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/company-research-agent/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/company-research-agent/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/.env.template +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/.python-version +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/.vscode/launch.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/agent.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/input.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/src/email_organizer/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/src/email_organizer/main.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/src/email_organizer/outlook_client.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/email-organizer-agent/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/hitl-inbox-server/database.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/hitl-inbox-server/main.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/hitl-inbox-server/models.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/hitl-inbox-server/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/hitl-inbox-server/schemas.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/hitl-inbox-server/templates/index.html +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/hitl-inbox-server/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/.env.example +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/coder.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/planner.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/researcher.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/src/multi-agent-distributed/coder.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/src/multi-agent-distributed/planner.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/src/multi-agent-distributed/researcher.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-planner-researcher-coder-distributed/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-supervisor-researcher-coder/.env.example +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-supervisor-researcher-coder/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-supervisor-researcher-coder/agent.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-supervisor-researcher-coder/graph.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-supervisor-researcher-coder/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-supervisor-researcher-coder/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-supervisor-researcher-coder/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/multi-agent-supervisor-researcher-coder/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/oauth-external-apps-agent/.env.example +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/oauth-external-apps-agent/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/oauth-external-apps-agent/input.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/oauth-external-apps-agent/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/oauth-external-apps-agent/main.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/oauth-external-apps-agent/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/oauth-external-apps-agent/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/retrieval-chain/.env.example +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/retrieval-chain/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/retrieval-chain/main.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/retrieval-chain/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/retrieval-chain/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/retrieval-chain/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-local-mcp/.env.example +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-local-mcp/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-local-mcp/agent.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-local-mcp/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-local-mcp/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-local-mcp/src/simple-local-mcp/graph.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-local-mcp/src/simple-local-mcp/math_server.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-local-mcp/src/simple-local-mcp/weather_server.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-local-mcp/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-local-mcp/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-remote-mcp/.env.example +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-remote-mcp/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-remote-mcp/agent.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-remote-mcp/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-remote-mcp/main.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-remote-mcp/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-remote-mcp/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/simple-remote-mcp/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/ticket-classification/.env.example +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/ticket-classification/README.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/ticket-classification/agent.mermaid +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/ticket-classification/escalation_app_solution/generic-escalation-app-solution-1.0.0.zip +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/ticket-classification/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/ticket-classification/main.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/ticket-classification/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/ticket-classification/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/samples/ticket-classification/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_runtime/_context.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_runtime/_conversation.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_runtime/_exception.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_runtime/_graph_resolver.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_runtime/_input.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_runtime/_output.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_templates/langgraph.json.template +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_templates/main.py.template +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_utils/_graph.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/cli_debug.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/cli_dev.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/cli_new.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/cli_run.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_resources/AGENTS.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_resources/REQUIRED_STRUCTURE.md +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_tracing/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_tracing/_instrument_traceable.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_tracing/_utils.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_utils/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_utils/_request_mixin.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_utils/_settings.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_utils/_sleep_policy.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/agent.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/constants.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/exceptions.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/init_node.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/llm_node.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/router.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/state.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/terminate_node.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/tools/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/tools/tools.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/react/utils.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/tools/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/tools/context_tool.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/tools/process_tool.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/tools/tool_factory.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/tools/tool_node.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/agent/tools/utils.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/chat/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/chat/models.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/embeddings/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/embeddings/embeddings.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/middlewares.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/py.typed +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/retrievers/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/retrievers/context_grounding_retriever.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/tools/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/tools/preconfigured.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/vectorstores/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/vectorstores/context_grounding_vectorstore.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/common/trace_assert.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/common/validate_output.sh +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/company-research-agent/expected_raw.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/company-research-agent/expected_traces.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/company-research-agent/input.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/company-research-agent/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/company-research-agent/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/company-research-agent/run.sh +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/company-research-agent/src/assert.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/company-research-agent/src/graph.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/company-research-agent/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/init-flow/expected_traces.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/init-flow/input.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/init-flow/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/init-flow/run.sh +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/init-flow/src/assert.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/simple-local-mcp/expected_traces.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/simple-local-mcp/input.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/simple-local-mcp/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/simple-local-mcp/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/simple-local-mcp/run.sh +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/simple-local-mcp/src/assert.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/simple-local-mcp/src/simple-local-mcp/graph.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/simple-local-mcp/src/simple-local-mcp/math_server.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/simple-local-mcp/src/simple-local-mcp/weather_server.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/simple-local-mcp/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/ticket-classification/expected_traces.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/ticket-classification/input.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/ticket-classification/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/ticket-classification/pyproject.toml +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/ticket-classification/raw_traces.jsonl +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/ticket-classification/run.sh +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/ticket-classification/src/assert.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/ticket-classification/src/main.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/testcases/ticket-classification/uv.lock +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/agent/react/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/agent/react/test_utils.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/cli/conftest.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/cli/mocks/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/cli/mocks/simple_agent.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/cli/mocks/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/cli/test_init.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/cli/test_run.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/conftest.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/mocks/action_trigger_hitl.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/mocks/api_trigger_hitl.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/mocks/job_trigger_hitl.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/mocks/langgraph.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/mocks/uipath-default-escalation.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/mocks/uipath.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/test_action_trigger.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/test_hitl_api_trigger.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/test_hitl_default_escalation.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/hitl/test_hitl_job_trigger.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/test_dummy.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/tools/__init__.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/tools/conftest.py +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/tools/mocks/agent_definition.json +0 -0
- {uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/tests/tools/test_preconfigured.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uipath-langchain
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.146
|
|
4
4
|
Summary: UiPath Langchain
|
|
5
5
|
Project-URL: Homepage, https://uipath.com
|
|
6
6
|
Project-URL: Repository, https://github.com/UiPath/uipath-langchain-python
|
|
@@ -26,7 +26,7 @@ Requires-Dist: openai>=1.65.5
|
|
|
26
26
|
Requires-Dist: openinference-instrumentation-langchain>=0.1.50
|
|
27
27
|
Requires-Dist: pydantic-settings>=2.6.0
|
|
28
28
|
Requires-Dist: python-dotenv>=1.0.1
|
|
29
|
-
Requires-Dist: uipath<2.2.0,>=2.1.
|
|
29
|
+
Requires-Dist: uipath<2.2.0,>=2.1.110
|
|
30
30
|
Provides-Extra: langchain
|
|
31
31
|
Description-Content-Type: text/markdown
|
|
32
32
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "uipath-langchain"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.146"
|
|
4
4
|
description = "UiPath Langchain"
|
|
5
5
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
6
6
|
requires-python = ">=3.10"
|
|
7
7
|
dependencies = [
|
|
8
|
-
"uipath>=2.1.
|
|
8
|
+
"uipath>=2.1.110, <2.2.0",
|
|
9
9
|
"langgraph>=0.5.0, <0.7.0",
|
|
10
10
|
"langchain-core>=0.3.34",
|
|
11
11
|
"langgraph-checkpoint-sqlite>=2.0.3",
|
|
@@ -111,4 +111,4 @@ asyncio_mode = "auto"
|
|
|
111
111
|
name = "testpypi"
|
|
112
112
|
url = "https://test.pypi.org/simple/"
|
|
113
113
|
publish-url = "https://test.pypi.org/legacy/"
|
|
114
|
-
explicit = true
|
|
114
|
+
explicit = true
|
{uipath_langchain-0.0.144 → uipath_langchain-0.0.146}/src/uipath_langchain/_cli/_runtime/_runtime.py
RENAMED
|
@@ -2,12 +2,14 @@ import logging
|
|
|
2
2
|
import os
|
|
3
3
|
from contextlib import asynccontextmanager
|
|
4
4
|
from typing import Any, AsyncGenerator, AsyncIterator, Optional, Sequence
|
|
5
|
+
from uuid import uuid4
|
|
5
6
|
|
|
6
7
|
from langchain_core.runnables.config import RunnableConfig
|
|
7
8
|
from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
|
|
8
9
|
from langgraph.errors import EmptyInputError, GraphRecursionError, InvalidUpdateError
|
|
9
10
|
from langgraph.graph.state import CompiledStateGraph, StateGraph
|
|
10
11
|
from langgraph.types import Interrupt, StateSnapshot
|
|
12
|
+
from typing_extensions import override
|
|
11
13
|
from uipath._cli._runtime._contracts import (
|
|
12
14
|
UiPathBaseRuntime,
|
|
13
15
|
UiPathBreakpointResult,
|
|
@@ -17,12 +19,14 @@ from uipath._cli._runtime._contracts import (
|
|
|
17
19
|
UiPathRuntimeResult,
|
|
18
20
|
UiPathRuntimeStatus,
|
|
19
21
|
)
|
|
22
|
+
from uipath._cli.models.runtime_schema import Entrypoint
|
|
20
23
|
from uipath._events._events import (
|
|
21
24
|
UiPathAgentMessageEvent,
|
|
22
25
|
UiPathAgentStateEvent,
|
|
23
26
|
UiPathRuntimeEvent,
|
|
24
27
|
)
|
|
25
28
|
|
|
29
|
+
from .._utils._schema import generate_schema_from_graph
|
|
26
30
|
from ._context import LangGraphRuntimeContext
|
|
27
31
|
from ._exception import LangGraphErrorCode, LangGraphRuntimeError
|
|
28
32
|
from ._graph_resolver import AsyncResolver, LangGraphJsonResolver
|
|
@@ -481,6 +485,21 @@ class LangGraphScriptRuntime(LangGraphRuntime):
|
|
|
481
485
|
self.resolver = LangGraphJsonResolver(entrypoint=entrypoint)
|
|
482
486
|
super().__init__(context, self.resolver)
|
|
483
487
|
|
|
488
|
+
@override
|
|
489
|
+
async def get_entrypoint(self) -> Entrypoint:
|
|
490
|
+
"""Get entrypoint for this LangGraph runtime."""
|
|
491
|
+
graph = await self.resolver()
|
|
492
|
+
compiled_graph = graph.compile()
|
|
493
|
+
schema_details = generate_schema_from_graph(compiled_graph)
|
|
494
|
+
|
|
495
|
+
return Entrypoint(
|
|
496
|
+
file_path=self.context.entrypoint, # type: ignore[call-arg]
|
|
497
|
+
unique_id=str(uuid4()),
|
|
498
|
+
type="agent",
|
|
499
|
+
input=schema_details.schema["input"],
|
|
500
|
+
output=schema_details.schema["output"],
|
|
501
|
+
)
|
|
502
|
+
|
|
484
503
|
async def cleanup(self) -> None:
|
|
485
504
|
"""Cleanup runtime resources including resolver."""
|
|
486
505
|
await super().cleanup()
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any, Dict
|
|
3
|
+
|
|
4
|
+
from langgraph.graph.state import CompiledStateGraph
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class SchemaDetails:
|
|
9
|
+
schema: dict[str, Any]
|
|
10
|
+
has_input_circular_dependency: bool
|
|
11
|
+
has_output_circular_dependency: bool
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def resolve_refs(schema, root=None, visited=None):
|
|
15
|
+
"""Recursively resolves $ref references in a JSON schema, handling circular references.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
tuple: (resolved_schema, has_circular_dependency)
|
|
19
|
+
"""
|
|
20
|
+
if root is None:
|
|
21
|
+
root = schema
|
|
22
|
+
|
|
23
|
+
if visited is None:
|
|
24
|
+
visited = set()
|
|
25
|
+
|
|
26
|
+
has_circular = False
|
|
27
|
+
|
|
28
|
+
if isinstance(schema, dict):
|
|
29
|
+
if "$ref" in schema:
|
|
30
|
+
ref_path = schema["$ref"]
|
|
31
|
+
|
|
32
|
+
if ref_path in visited:
|
|
33
|
+
# Circular dependency detected
|
|
34
|
+
return {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"description": f"Circular reference to {ref_path}",
|
|
37
|
+
}, True
|
|
38
|
+
|
|
39
|
+
visited.add(ref_path)
|
|
40
|
+
|
|
41
|
+
# Resolve the reference
|
|
42
|
+
ref_parts = ref_path.lstrip("#/").split("/")
|
|
43
|
+
ref_schema = root
|
|
44
|
+
for part in ref_parts:
|
|
45
|
+
ref_schema = ref_schema.get(part, {})
|
|
46
|
+
|
|
47
|
+
result, circular = resolve_refs(ref_schema, root, visited)
|
|
48
|
+
has_circular = has_circular or circular
|
|
49
|
+
|
|
50
|
+
# Remove from visited after resolution (allows the same ref in different branches)
|
|
51
|
+
visited.discard(ref_path)
|
|
52
|
+
|
|
53
|
+
return result, has_circular
|
|
54
|
+
|
|
55
|
+
resolved_dict = {}
|
|
56
|
+
for k, v in schema.items():
|
|
57
|
+
resolved_value, circular = resolve_refs(v, root, visited)
|
|
58
|
+
resolved_dict[k] = resolved_value
|
|
59
|
+
has_circular = has_circular or circular
|
|
60
|
+
return resolved_dict, has_circular
|
|
61
|
+
|
|
62
|
+
elif isinstance(schema, list):
|
|
63
|
+
resolved_list = []
|
|
64
|
+
for item in schema:
|
|
65
|
+
resolved_item, circular = resolve_refs(item, root, visited)
|
|
66
|
+
resolved_list.append(resolved_item)
|
|
67
|
+
has_circular = has_circular or circular
|
|
68
|
+
return resolved_list, has_circular
|
|
69
|
+
|
|
70
|
+
return schema, False
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def process_nullable_types(
|
|
74
|
+
schema: Dict[str, Any] | list[Any] | Any,
|
|
75
|
+
) -> Dict[str, Any] | list[Any]:
|
|
76
|
+
"""Process the schema to handle nullable types by removing anyOf with null and keeping the base type."""
|
|
77
|
+
if isinstance(schema, dict):
|
|
78
|
+
if "anyOf" in schema and len(schema["anyOf"]) == 2:
|
|
79
|
+
types = [t.get("type") for t in schema["anyOf"]]
|
|
80
|
+
if "null" in types:
|
|
81
|
+
non_null_type = next(
|
|
82
|
+
t for t in schema["anyOf"] if t.get("type") != "null"
|
|
83
|
+
)
|
|
84
|
+
return non_null_type
|
|
85
|
+
|
|
86
|
+
return {k: process_nullable_types(v) for k, v in schema.items()}
|
|
87
|
+
elif isinstance(schema, list):
|
|
88
|
+
return [process_nullable_types(item) for item in schema]
|
|
89
|
+
return schema
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def generate_schema_from_graph(
|
|
93
|
+
graph: CompiledStateGraph[Any, Any, Any],
|
|
94
|
+
) -> SchemaDetails:
|
|
95
|
+
"""Extract input/output schema from a LangGraph graph"""
|
|
96
|
+
input_circular_dependency = False
|
|
97
|
+
output_circular_dependency = False
|
|
98
|
+
schema = {
|
|
99
|
+
"input": {"type": "object", "properties": {}, "required": []},
|
|
100
|
+
"output": {"type": "object", "properties": {}, "required": []},
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if hasattr(graph, "input_schema"):
|
|
104
|
+
if hasattr(graph.input_schema, "model_json_schema"):
|
|
105
|
+
input_schema = graph.input_schema.model_json_schema()
|
|
106
|
+
unpacked_ref_def_properties, input_circular_dependency = resolve_refs(
|
|
107
|
+
input_schema
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
# Process the schema to handle nullable types
|
|
111
|
+
processed_properties = process_nullable_types(
|
|
112
|
+
unpacked_ref_def_properties.get("properties", {})
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
schema["input"]["properties"] = processed_properties
|
|
116
|
+
schema["input"]["required"] = unpacked_ref_def_properties.get(
|
|
117
|
+
"required", []
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if hasattr(graph, "output_schema"):
|
|
121
|
+
if hasattr(graph.output_schema, "model_json_schema"):
|
|
122
|
+
output_schema = graph.output_schema.model_json_schema()
|
|
123
|
+
unpacked_ref_def_properties, output_circular_dependency = resolve_refs(
|
|
124
|
+
output_schema
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Process the schema to handle nullable types
|
|
128
|
+
processed_properties = process_nullable_types(
|
|
129
|
+
unpacked_ref_def_properties.get("properties", {})
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
schema["output"]["properties"] = processed_properties
|
|
133
|
+
schema["output"]["required"] = unpacked_ref_def_properties.get(
|
|
134
|
+
"required", []
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
return SchemaDetails(schema, input_circular_dependency, output_circular_dependency)
|
|
@@ -6,8 +6,9 @@ from openinference.instrumentation.langchain import (
|
|
|
6
6
|
get_current_span,
|
|
7
7
|
)
|
|
8
8
|
from uipath._cli._evals._console_progress_reporter import ConsoleProgressReporter
|
|
9
|
+
from uipath._cli._evals._evaluate import evaluate
|
|
9
10
|
from uipath._cli._evals._progress_reporter import StudioWebProgressReporter
|
|
10
|
-
from uipath._cli._evals._runtime import UiPathEvalContext
|
|
11
|
+
from uipath._cli._evals._runtime import UiPathEvalContext
|
|
11
12
|
from uipath._cli._runtime._contracts import (
|
|
12
13
|
UiPathRuntimeFactory,
|
|
13
14
|
)
|
|
@@ -82,14 +83,7 @@ def langgraph_eval_middleware(
|
|
|
82
83
|
|
|
83
84
|
runtime_factory.add_instrumentor(LangChainInstrumentor, get_current_span)
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
async with UiPathEvalRuntime.from_eval_context(
|
|
87
|
-
factory=runtime_factory, context=eval_context, event_bus=event_bus
|
|
88
|
-
) as eval_runtime:
|
|
89
|
-
await eval_runtime.execute()
|
|
90
|
-
await event_bus.wait_for_all()
|
|
91
|
-
|
|
92
|
-
asyncio.run(execute())
|
|
86
|
+
asyncio.run(evaluate(runtime_factory, eval_context, event_bus))
|
|
93
87
|
return MiddlewareResult(should_continue=False)
|
|
94
88
|
|
|
95
89
|
except Exception as e:
|
|
@@ -6,7 +6,7 @@ import shutil
|
|
|
6
6
|
import uuid
|
|
7
7
|
from collections.abc import Generator
|
|
8
8
|
from enum import Enum
|
|
9
|
-
from typing import Any, Callable,
|
|
9
|
+
from typing import Any, Callable, overload
|
|
10
10
|
|
|
11
11
|
import click
|
|
12
12
|
from langgraph.graph.state import CompiledStateGraph
|
|
@@ -14,6 +14,8 @@ from uipath._cli._utils._console import ConsoleLogger
|
|
|
14
14
|
from uipath._cli._utils._parse_ast import generate_bindings_json # type: ignore
|
|
15
15
|
from uipath._cli.middlewares import MiddlewareResult
|
|
16
16
|
|
|
17
|
+
from uipath_langchain._cli._utils._schema import generate_schema_from_graph
|
|
18
|
+
|
|
17
19
|
from ._utils._graph import LangGraphConfig
|
|
18
20
|
|
|
19
21
|
console = ConsoleLogger()
|
|
@@ -27,88 +29,6 @@ class FileOperationStatus(str, Enum):
|
|
|
27
29
|
SKIPPED = "skipped"
|
|
28
30
|
|
|
29
31
|
|
|
30
|
-
def resolve_refs(schema, root=None):
|
|
31
|
-
"""Recursively resolves $ref references in a JSON schema."""
|
|
32
|
-
if root is None:
|
|
33
|
-
root = schema # Store the root schema to resolve $refs
|
|
34
|
-
|
|
35
|
-
if isinstance(schema, dict):
|
|
36
|
-
if "$ref" in schema:
|
|
37
|
-
ref_path = schema["$ref"].lstrip("#/").split("/")
|
|
38
|
-
ref_schema = root
|
|
39
|
-
for part in ref_path:
|
|
40
|
-
ref_schema = ref_schema.get(part, {})
|
|
41
|
-
return resolve_refs(ref_schema, root)
|
|
42
|
-
|
|
43
|
-
return {k: resolve_refs(v, root) for k, v in schema.items()}
|
|
44
|
-
|
|
45
|
-
elif isinstance(schema, list):
|
|
46
|
-
return [resolve_refs(item, root) for item in schema]
|
|
47
|
-
|
|
48
|
-
return schema
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def process_nullable_types(
|
|
52
|
-
schema: Dict[str, Any] | list[Any] | Any,
|
|
53
|
-
) -> Dict[str, Any] | list[Any]:
|
|
54
|
-
"""Process the schema to handle nullable types by removing anyOf with null and keeping the base type."""
|
|
55
|
-
if isinstance(schema, dict):
|
|
56
|
-
if "anyOf" in schema and len(schema["anyOf"]) == 2:
|
|
57
|
-
types = [t.get("type") for t in schema["anyOf"]]
|
|
58
|
-
if "null" in types:
|
|
59
|
-
non_null_type = next(
|
|
60
|
-
t for t in schema["anyOf"] if t.get("type") != "null"
|
|
61
|
-
)
|
|
62
|
-
return non_null_type
|
|
63
|
-
|
|
64
|
-
return {k: process_nullable_types(v) for k, v in schema.items()}
|
|
65
|
-
elif isinstance(schema, list):
|
|
66
|
-
return [process_nullable_types(item) for item in schema]
|
|
67
|
-
return schema
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def generate_schema_from_graph(
|
|
71
|
-
graph: CompiledStateGraph[Any, Any, Any],
|
|
72
|
-
) -> Dict[str, Any]:
|
|
73
|
-
"""Extract input/output schema from a LangGraph graph"""
|
|
74
|
-
schema = {
|
|
75
|
-
"input": {"type": "object", "properties": {}, "required": []},
|
|
76
|
-
"output": {"type": "object", "properties": {}, "required": []},
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if hasattr(graph, "input_schema"):
|
|
80
|
-
if hasattr(graph.input_schema, "model_json_schema"):
|
|
81
|
-
input_schema = graph.input_schema.model_json_schema()
|
|
82
|
-
unpacked_ref_def_properties = resolve_refs(input_schema)
|
|
83
|
-
|
|
84
|
-
# Process the schema to handle nullable types
|
|
85
|
-
processed_properties = process_nullable_types(
|
|
86
|
-
unpacked_ref_def_properties.get("properties", {})
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
schema["input"]["properties"] = processed_properties
|
|
90
|
-
schema["input"]["required"] = unpacked_ref_def_properties.get(
|
|
91
|
-
"required", []
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
if hasattr(graph, "output_schema"):
|
|
95
|
-
if hasattr(graph.output_schema, "model_json_schema"):
|
|
96
|
-
output_schema = graph.output_schema.model_json_schema()
|
|
97
|
-
unpacked_ref_def_properties = resolve_refs(output_schema)
|
|
98
|
-
|
|
99
|
-
# Process the schema to handle nullable types
|
|
100
|
-
processed_properties = process_nullable_types(
|
|
101
|
-
unpacked_ref_def_properties.get("properties", {})
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
schema["output"]["properties"] = processed_properties
|
|
105
|
-
schema["output"]["required"] = unpacked_ref_def_properties.get(
|
|
106
|
-
"required", []
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
return schema
|
|
110
|
-
|
|
111
|
-
|
|
112
32
|
def generate_agent_md_file(
|
|
113
33
|
target_directory: str,
|
|
114
34
|
file_name: str,
|
|
@@ -255,7 +175,7 @@ async def langgraph_init_middleware_async(
|
|
|
255
175
|
else loaded_graph
|
|
256
176
|
)
|
|
257
177
|
compiled_graph = state_graph.compile()
|
|
258
|
-
|
|
178
|
+
schema_details = generate_schema_from_graph(compiled_graph)
|
|
259
179
|
|
|
260
180
|
mermaids[graph.name] = compiled_graph.get_graph(xray=1).draw_mermaid()
|
|
261
181
|
|
|
@@ -277,11 +197,17 @@ async def langgraph_init_middleware_async(
|
|
|
277
197
|
"filePath": graph.name,
|
|
278
198
|
"uniqueId": str(uuid.uuid4()),
|
|
279
199
|
"type": "agent",
|
|
280
|
-
"input":
|
|
281
|
-
"output":
|
|
200
|
+
"input": schema_details.schema["input"],
|
|
201
|
+
"output": schema_details.schema["output"],
|
|
282
202
|
}
|
|
283
203
|
entrypoints.append(new_entrypoint)
|
|
284
204
|
|
|
205
|
+
warning_circular_deps = f" schema of graph '{graph.name}' contains circular dependencies. Some types might not be correctly inferred."
|
|
206
|
+
if schema_details.has_input_circular_dependency:
|
|
207
|
+
console.warning("Input" + warning_circular_deps)
|
|
208
|
+
if schema_details.has_output_circular_dependency:
|
|
209
|
+
console.warning("Output" + warning_circular_deps)
|
|
210
|
+
|
|
285
211
|
except Exception as e:
|
|
286
212
|
console.error(f"Error during graph load: {e}")
|
|
287
213
|
return MiddlewareResult(
|
|
@@ -323,6 +249,7 @@ async def langgraph_init_middleware_async(
|
|
|
323
249
|
should_continue=False,
|
|
324
250
|
should_include_stacktrace=True,
|
|
325
251
|
)
|
|
252
|
+
|
|
326
253
|
console.success(f"Created {click.style(config_path, fg='cyan')} file.")
|
|
327
254
|
|
|
328
255
|
generate_agents_md_files(options)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Runtime factory for LangGraph projects."""
|
|
2
|
+
|
|
3
|
+
from uipath._cli._runtime._contracts import UiPathRuntimeFactory
|
|
4
|
+
|
|
5
|
+
from ._cli._runtime._context import LangGraphRuntimeContext
|
|
6
|
+
from ._cli._runtime._runtime import LangGraphScriptRuntime
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class LangGraphRuntimeFactory(
|
|
10
|
+
UiPathRuntimeFactory[LangGraphScriptRuntime, LangGraphRuntimeContext]
|
|
11
|
+
):
|
|
12
|
+
"""Factory for LangGraph runtimes."""
|
|
13
|
+
|
|
14
|
+
def __init__(self):
|
|
15
|
+
super().__init__(
|
|
16
|
+
LangGraphScriptRuntime,
|
|
17
|
+
LangGraphRuntimeContext,
|
|
18
|
+
context_generator=lambda **kwargs: LangGraphRuntimeContext.with_defaults(
|
|
19
|
+
**kwargs
|
|
20
|
+
),
|
|
21
|
+
)
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"""Tests for schema utility functions."""
|
|
2
|
+
|
|
3
|
+
from unittest.mock import MagicMock
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
from uipath_langchain._cli._utils._schema import (
|
|
8
|
+
generate_schema_from_graph,
|
|
9
|
+
resolve_refs,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestResolveRefs:
|
|
14
|
+
"""Tests for the resolve_refs function."""
|
|
15
|
+
|
|
16
|
+
def test_simple_schema_without_refs(self):
|
|
17
|
+
"""Should return schema unchanged when no $refs exist."""
|
|
18
|
+
schema = {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"properties": {"name": {"type": "string"}, "age": {"type": "integer"}},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
result, has_circular = resolve_refs(schema)
|
|
24
|
+
|
|
25
|
+
assert result == schema
|
|
26
|
+
assert has_circular is False
|
|
27
|
+
|
|
28
|
+
def test_simple_ref_resolution(self):
|
|
29
|
+
"""Should resolve a simple $ref to its definition."""
|
|
30
|
+
schema = {
|
|
31
|
+
"properties": {"user": {"$ref": "#/$defs/User"}},
|
|
32
|
+
"$defs": {
|
|
33
|
+
"User": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"properties": {"name": {"type": "string"}},
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
result, has_circular = resolve_refs(schema)
|
|
41
|
+
|
|
42
|
+
assert result["properties"]["user"]["type"] == "object"
|
|
43
|
+
assert result["properties"]["user"]["properties"]["name"]["type"] == "string"
|
|
44
|
+
assert has_circular is False
|
|
45
|
+
|
|
46
|
+
def test_circular_dependency_detection(self):
|
|
47
|
+
"""Should detect circular dependencies in schema."""
|
|
48
|
+
schema = {
|
|
49
|
+
"properties": {"node": {"$ref": "#/$defs/Node"}},
|
|
50
|
+
"$defs": {
|
|
51
|
+
"Node": {
|
|
52
|
+
"type": "object",
|
|
53
|
+
"properties": {
|
|
54
|
+
"value": {"type": "string"},
|
|
55
|
+
"next": {"$ref": "#/$defs/Node"},
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
result, has_circular = resolve_refs(schema)
|
|
62
|
+
|
|
63
|
+
assert has_circular is True
|
|
64
|
+
# Check that circular ref was replaced with simplified schema
|
|
65
|
+
assert result["properties"]["node"]["properties"]["next"]["type"] == "object"
|
|
66
|
+
assert (
|
|
67
|
+
"Circular reference"
|
|
68
|
+
in result["properties"]["node"]["properties"]["next"]["description"]
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def test_nested_refs_in_properties(self):
|
|
72
|
+
"""Should resolve nested $refs in object properties."""
|
|
73
|
+
schema = {
|
|
74
|
+
"properties": {
|
|
75
|
+
"person": {"$ref": "#/$defs/Person"},
|
|
76
|
+
"address": {"$ref": "#/$defs/Address"},
|
|
77
|
+
},
|
|
78
|
+
"$defs": {
|
|
79
|
+
"Person": {
|
|
80
|
+
"type": "object",
|
|
81
|
+
"properties": {"name": {"type": "string"}},
|
|
82
|
+
},
|
|
83
|
+
"Address": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"properties": {"street": {"type": "string"}},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
result, has_circular = resolve_refs(schema)
|
|
91
|
+
|
|
92
|
+
assert result["properties"]["person"]["type"] == "object"
|
|
93
|
+
assert result["properties"]["person"]["properties"]["name"]["type"] == "string"
|
|
94
|
+
assert result["properties"]["address"]["type"] == "object"
|
|
95
|
+
assert (
|
|
96
|
+
result["properties"]["address"]["properties"]["street"]["type"] == "string"
|
|
97
|
+
)
|
|
98
|
+
assert has_circular is False
|
|
99
|
+
|
|
100
|
+
def test_refs_in_arrays(self):
|
|
101
|
+
"""Should resolve $refs inside array items."""
|
|
102
|
+
schema = {
|
|
103
|
+
"properties": {
|
|
104
|
+
"users": {
|
|
105
|
+
"type": "array",
|
|
106
|
+
"items": {"$ref": "#/$defs/User"},
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"$defs": {
|
|
110
|
+
"User": {
|
|
111
|
+
"type": "object",
|
|
112
|
+
"properties": {"id": {"type": "integer"}},
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
result, has_circular = resolve_refs(schema)
|
|
118
|
+
|
|
119
|
+
assert result["properties"]["users"]["items"]["type"] == "object"
|
|
120
|
+
assert (
|
|
121
|
+
result["properties"]["users"]["items"]["properties"]["id"]["type"]
|
|
122
|
+
== "integer"
|
|
123
|
+
)
|
|
124
|
+
assert has_circular is False
|
|
125
|
+
|
|
126
|
+
def test_multiple_circular_dependencies(self):
|
|
127
|
+
"""Should handle multiple circular dependencies in same schema."""
|
|
128
|
+
schema = {
|
|
129
|
+
"properties": {
|
|
130
|
+
"node1": {"$ref": "#/$defs/Node"},
|
|
131
|
+
"node2": {"$ref": "#/$defs/Node"},
|
|
132
|
+
},
|
|
133
|
+
"$defs": {
|
|
134
|
+
"Node": {
|
|
135
|
+
"type": "object",
|
|
136
|
+
"properties": {
|
|
137
|
+
"next": {"$ref": "#/$defs/Node"},
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
result, has_circular = resolve_refs(schema)
|
|
144
|
+
|
|
145
|
+
assert has_circular is True
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class TestGenerateSchemaFromGraph:
|
|
149
|
+
"""Tests for the generate_schema_from_graph function."""
|
|
150
|
+
|
|
151
|
+
def test_graph_without_schemas(self):
|
|
152
|
+
"""Should return empty schemas when graph has no input/output schemas."""
|
|
153
|
+
mock_graph = MagicMock()
|
|
154
|
+
del mock_graph.input_schema
|
|
155
|
+
del mock_graph.output_schema
|
|
156
|
+
|
|
157
|
+
result = generate_schema_from_graph(mock_graph)
|
|
158
|
+
|
|
159
|
+
assert result.schema["input"] == {
|
|
160
|
+
"type": "object",
|
|
161
|
+
"properties": {},
|
|
162
|
+
"required": [],
|
|
163
|
+
}
|
|
164
|
+
assert result.schema["output"] == {
|
|
165
|
+
"type": "object",
|
|
166
|
+
"properties": {},
|
|
167
|
+
"required": [],
|
|
168
|
+
}
|
|
169
|
+
assert result.has_input_circular_dependency is False
|
|
170
|
+
assert result.has_output_circular_dependency is False
|
|
171
|
+
|
|
172
|
+
def test_graph_with_simple_schemas(self):
|
|
173
|
+
"""Should extract input and output schemas from graph."""
|
|
174
|
+
|
|
175
|
+
class InputModel(BaseModel):
|
|
176
|
+
query: str = Field(description="User query")
|
|
177
|
+
max_results: int = Field(default=10)
|
|
178
|
+
|
|
179
|
+
class OutputModel(BaseModel):
|
|
180
|
+
response: str = Field(description="Agent response")
|
|
181
|
+
|
|
182
|
+
mock_graph = MagicMock()
|
|
183
|
+
mock_graph.input_schema = InputModel
|
|
184
|
+
mock_graph.output_schema = OutputModel
|
|
185
|
+
|
|
186
|
+
result = generate_schema_from_graph(mock_graph)
|
|
187
|
+
|
|
188
|
+
assert "query" in result.schema["input"]["properties"]
|
|
189
|
+
assert "max_results" in result.schema["input"]["properties"]
|
|
190
|
+
assert result.schema["input"]["properties"]["query"]["type"] == "string"
|
|
191
|
+
assert "response" in result.schema["output"]["properties"]
|
|
192
|
+
assert result.schema["output"]["properties"]["response"]["type"] == "string"
|
|
193
|
+
assert result.has_input_circular_dependency is False
|
|
194
|
+
assert result.has_output_circular_dependency is False
|
|
195
|
+
|
|
196
|
+
def test_graph_with_circular_input_schema(self):
|
|
197
|
+
"""Should detect circular dependencies in input schema."""
|
|
198
|
+
|
|
199
|
+
class NodeInput(BaseModel):
|
|
200
|
+
value: str
|
|
201
|
+
children: list["NodeInput"] = Field(default_factory=list)
|
|
202
|
+
|
|
203
|
+
mock_graph = MagicMock()
|
|
204
|
+
mock_graph.input_schema = NodeInput
|
|
205
|
+
del mock_graph.output_schema
|
|
206
|
+
|
|
207
|
+
result = generate_schema_from_graph(mock_graph)
|
|
208
|
+
|
|
209
|
+
assert result.has_input_circular_dependency is True
|
|
210
|
+
assert result.has_output_circular_dependency is False
|
|
211
|
+
assert "value" in result.schema["input"]["properties"]
|
|
212
|
+
|
|
213
|
+
def test_graph_with_circular_output_schema(self):
|
|
214
|
+
"""Should detect circular dependencies in output schema."""
|
|
215
|
+
|
|
216
|
+
class TreeOutput(BaseModel):
|
|
217
|
+
name: str
|
|
218
|
+
parent: "TreeOutput | None" = None
|
|
219
|
+
|
|
220
|
+
mock_graph = MagicMock()
|
|
221
|
+
del mock_graph.input_schema
|
|
222
|
+
mock_graph.output_schema = TreeOutput
|
|
223
|
+
|
|
224
|
+
result = generate_schema_from_graph(mock_graph)
|
|
225
|
+
|
|
226
|
+
assert result.has_input_circular_dependency is False
|
|
227
|
+
assert result.has_output_circular_dependency is True
|
|
228
|
+
assert "name" in result.schema["output"]["properties"]
|
|
229
|
+
|
|
230
|
+
def test_graph_with_both_circular_schemas(self):
|
|
231
|
+
"""Should detect circular dependencies in both input and output schemas."""
|
|
232
|
+
|
|
233
|
+
class CircularInput(BaseModel):
|
|
234
|
+
data: str
|
|
235
|
+
ref: "CircularInput | None" = None
|
|
236
|
+
|
|
237
|
+
class CircularOutput(BaseModel):
|
|
238
|
+
result: str
|
|
239
|
+
next: "CircularOutput | None" = None
|
|
240
|
+
|
|
241
|
+
mock_graph = MagicMock()
|
|
242
|
+
mock_graph.input_schema = CircularInput
|
|
243
|
+
mock_graph.output_schema = CircularOutput
|
|
244
|
+
|
|
245
|
+
result = generate_schema_from_graph(mock_graph)
|
|
246
|
+
|
|
247
|
+
assert result.has_input_circular_dependency is True
|
|
248
|
+
assert result.has_output_circular_dependency is True
|
|
249
|
+
assert "data" in result.schema["input"]["properties"]
|
|
250
|
+
assert "result" in result.schema["output"]["properties"]
|
|
251
|
+
|
|
252
|
+
def test_graph_with_required_fields(self):
|
|
253
|
+
"""Should extract required fields from schemas."""
|
|
254
|
+
|
|
255
|
+
class StrictModel(BaseModel):
|
|
256
|
+
required_field: str
|
|
257
|
+
optional_field: str | None = None
|
|
258
|
+
|
|
259
|
+
mock_graph = MagicMock()
|
|
260
|
+
mock_graph.input_schema = StrictModel
|
|
261
|
+
del mock_graph.output_schema
|
|
262
|
+
|
|
263
|
+
result = generate_schema_from_graph(mock_graph)
|
|
264
|
+
|
|
265
|
+
assert "required_field" in result.schema["input"]["required"]
|
|
266
|
+
assert "optional_field" not in result.schema["input"]["required"]
|