diff --git a/.github/workflows/label-title-prefix.yml b/.github/workflows/label-title-prefix.yml new file mode 100644 index 0000000000..a5c3659dd9 --- /dev/null +++ b/.github/workflows/label-title-prefix.yml @@ -0,0 +1,72 @@ +name: Label title prefix +on: + issues: + types: [labeled] + pull_request_target: + types: [labeled] + +jobs: + add_title_prefix: + name: "Issue/PR: add title prefix" + continue-on-error: true + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/github-script@v6 + name: "Issue/PR: update title" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + let prefixLabels = { + "python": "Python", + ".NET": ".Net" + }; + + function addTitlePrefix(title, prefix) + { + // Update the title based on the label and prefix + // Check if the title starts with the prefix (case-sensitive) + if (!title.startsWith(prefix + ": ")) { + // If not, check if the first word is the label (case-insensitive) + if (title.match(new RegExp(`^${prefix}`, 'i'))) { + // If yes, replace it with the prefix (case-sensitive) + title = title.replace(new RegExp(`^${prefix}`, 'i'), prefix); + } else { + // If not, prepend the prefix to the title + title = prefix + ": " + title; + } + } + + return title; + } + + labelAdded = context.payload.label.name + + // Check if the issue or PR has the label + if (labelAdded in prefixLabels) { + let prefix = prefixLabels[labelAdded]; + switch(context.eventName) { + case 'issues': + github.rest.issues.update({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + title: addTitlePrefix(context.payload.issue.title, prefix) + }); + break + + case 'pull_request_target': + github.rest.pulls.update({ + pull_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + title: addTitlePrefix(context.payload.pull_request.title, prefix) + }); + break + default: + core.setFailed('Unrecognited eventName: ' + context.eventName); + } + } diff --git a/.github/workflows/python-code-quality.yml b/.github/workflows/python-code-quality.yml index 97df4a5431..b6b0591216 100644 --- a/.github/workflows/python-code-quality.yml +++ b/.github/workflows/python-code-quality.yml @@ -7,6 +7,9 @@ on: paths: - "python/**" +env: + UV_SEMVER: "0.8.x" + jobs: pre-commit: name: Checks @@ -29,7 +32,7 @@ jobs: - name: Set up uv uses: astral-sh/setup-uv@v6 with: - version: "0.7.x" + version: ${{ env.UV_SEMVER }} enable-cache: true cache-suffix: ${{ runner.os }}-${{ matrix.python-version }} cache-dependency-glob: "**/uv.lock" diff --git a/.github/workflows/python-merge-tests.yml b/.github/workflows/python-merge-tests.yml index 11fcca8d1f..f17ce5e8da 100644 --- a/.github/workflows/python-merge-tests.yml +++ b/.github/workflows/python-merge-tests.yml @@ -13,6 +13,7 @@ env: # Configure a constant location for the uv cache UV_CACHE_DIR: /tmp/.uv-cache RUN_INTEGRATION_TESTS: "true" + UV_SEMVER: "0.8.x" jobs: python-tests-main: @@ -38,7 +39,7 @@ jobs: - name: Set up uv uses: astral-sh/setup-uv@v6 with: - version: "0.7.x" + version: ${{ env.UV_SEMVER }} enable-cache: true cache-suffix: ${{ runner.os }}-${{ matrix.python-version }} cache-dependency-glob: "**/uv.lock" @@ -91,7 +92,7 @@ jobs: - name: Set up uv uses: astral-sh/setup-uv@v6 with: - version: "0.7.x" + version: ${{ env.UV_SEMVER }} enable-cache: true cache-suffix: ${{ runner.os }}-${{ matrix.python-version }} cache-dependency-glob: "**/uv.lock" @@ -151,7 +152,7 @@ jobs: - name: Set up uv uses: astral-sh/setup-uv@v6 with: - version: "0.7.x" + version: ${{ env.UV_SEMVER }} enable-cache: true cache-suffix: ${{ runner.os }}-${{ matrix.python-version }} cache-dependency-glob: "**/uv.lock" diff --git a/.github/workflows/python-release.yml b/.github/workflows/python-release.yml new file mode 100644 index 0000000000..3c57e01b55 --- /dev/null +++ b/.github/workflows/python-release.yml @@ -0,0 +1,60 @@ +name: Python - Build Release Assets + +on: + release: + types: [published] + +permissions: + contents: write + id-token: write + +env: + UV_SEMVER: "0.8.x" + +jobs: + python-build-assets: + if: github.event_name == 'release' && startsWith(github.event.release.tag_name, 'python-') + name: Python Build Assets and add to Release + runs-on: ubuntu-latest + environment: "integration" + env: + UV_PYTHON: "3.13" + defaults: + run: + working-directory: python + steps: + - uses: actions/checkout@v4 + - name: Set up uv + uses: astral-sh/setup-uv@v6 + with: + version: ${{ env.UV_SEMVER }} + enable-cache: true + cache-suffix: ${{ runner.os }}-${{ env.UV_PYTHON }} + cache-dependency-glob: "**/uv.lock" + - name: Set environment variables + run: | + # Extract package name from tag (format: python--) + TAG="${{ github.event.release.tag_name }}" + PACKAGE=$(echo "$TAG" | sed 's/^python-\([^-]*\)-.*$/\1/') + + # Validate package exists + if [[ ! -d "packages/$PACKAGE" ]]; then + echo "Error: Package '$PACKAGE' not found in packages/ directory" + echo "Available packages: $(ls packages/)" + exit 1 + fi + + echo "PACKAGE=$PACKAGE" >> $GITHUB_ENV + echo "Building package: $PACKAGE" + + - name: Check version + run: | + echo "Building and uploading Python package version: ${{ github.event.release.tag_name }}" + echo "Package directory: packages/${{ env.PACKAGE }}" + - name: Build the package + run: uv run poe --directory packages/${{ env.PACKAGE }} build + - name: Release + uses: softprops/action-gh-release@v2 + with: + files: | + python/dist/* diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 3267b08cea..5989408bba 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -8,6 +8,7 @@ on: env: # Configure a constant location for the uv cache UV_CACHE_DIR: /tmp/.uv-cache + UV_SEMVER: "0.8.x" jobs: python-tests: @@ -30,7 +31,7 @@ jobs: - name: Set up uv uses: astral-sh/setup-uv@v6 with: - version: "0.7.x" + version: ${{ env.UV_SEMVER }} enable-cache: true cache-suffix: ${{ runner.os }}-${{ matrix.python-version }} cache-dependency-glob: "**/uv.lock" diff --git a/README.md b/README.md index 5cd7cecfc8..665f4610df 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,235 @@ -# Project +# Get Started with Microsoft Agent Framework -> This repo has been populated by an initial template to help get you started. Please -> make sure to update the content to build a great experience for community-building. +Highlights +- Flexible Agent Framework: build, orchestrate, and deploy AI agents and multi-agent systems +- Multi-Agent Orchestration: Group chat, sequential, concurrent, and handoff patterns +- Plugin Ecosystem: Extend with native functions, OpenAPI, Model Context Protocol (MCP), and more +- LLM Support: OpenAI, Azure OpenAI, Azure AI Foundry, and more +- Runtime Support: In-process and distributed agent execution +- Multimodal: Text, vision, and function calling +- Cross-Platform: .NET and Python implementations -As the maintainer of this project, please make a few updates: +## Quick Install -- Improving this README.MD file to provide a great experience -- Updating SUPPORT.MD with content about this project's support experience -- Understanding the security reporting process in SECURITY.MD -- Remove this section from the README +```bash +pip install agent-framework +# Optional: Add Azure integration +pip install agent-framework[azure] +# Optional: Add Foundry integration +pip install agent-framework[foundry] +# Optional: Both +pip install agent-framework[azure,foundry] +``` -## Contributing +Supported Platforms: +- Python: 3.10+ +- OS: Windows, macOS, Linux -This project welcomes contributions and suggestions. Most contributions require you to agree to a -Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. +## 1. Setup API Keys -When you submit a pull request, a CLA bot will automatically determine whether you need to provide -a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions -provided by the bot. You will only need to do this once across all repos using our CLA. +Set as environment variables, or create a .env file at your project root: -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +```bash +OPENAI_API_KEY=sk-... +OPENAI_CHAT_MODEL_ID=... +... +AZURE_OPENAI_API_KEY=... +AZURE_OPENAI_ENDPOINT=... +AZURE_OPENAI_CHAT_DEPLOYMENT_NAME=... +... +FOUNDRY_PROJECT_ENDPOINT=... +FOUNDRY_MODEL_DEPLOYMENT_NAME=... +``` -## Trademarks +You can also override environment variables by explicitly passing configuration parameters to the chat client constructor: -This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft -trademarks or logos is subject to and must follow -[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). -Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. -Any use of third-party trademarks or logos are subject to those third-party's policies. +```python +from agent_framework.azure import AzureChatClient + +chat_client = AzureChatClient( + api_key=..., + endpoint=..., + deployment_name=..., + api_version=..., +) +``` + +See the following [setup guide](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started) for more information. + +## 2. Create a Simple Agent + +Create agents and invoke them directly: + +```python +import asyncio +from agent_framework import ChatClientAgent +from agent_framework.openai import OpenAIChatClient + +async def main(): + agent = ChatClientAgent( + chat_client=OpenAIChatClient(), + instructions=""" + 1) A robot may not injure a human being... + 2) A robot must obey orders given it by human beings... + 3) A robot must protect its own existence... + + Give me the TLDR in exactly 5 words. + """ + ) + + result = await agent.run("Summarize the Three Laws of Robotics") + print(result) + +asyncio.run(main()) +# Output: Protect humans, obey, self-preserve, prioritized. +``` + +## 3. Directly Use Chat Clients (No Agent Required) + +You can use the chat client classes directly for advanced workflows: + +```python +import asyncio +from agent_framework.openai import OpenAIChatClient +from agent_framework import ChatMessage, ChatRole + +async def main(): + client = OpenAIChatClient() + + messages = [ + ChatMessage(role=ChatRole.SYSTEM, text="You are a helpful assistant."), + ChatMessage(role=ChatRole.USER, text="Write a haiku about Agent Framework.") + ] + + response = await client.get_response(messages) + print(response.messages[0].text) + + """ + Output: + + Agents work in sync, + Framework threads through each task— + Code sparks collaboration. + """ + +asyncio.run(main()) +``` + +## 4. Build an Agent with Tools and Functions + +Enhance your agent with custom tools and function calling: + +```python +import asyncio +from typing import Annotated +from random import randint +from pydantic import Field +from agent_framework import ChatClientAgent +from agent_framework.openai import OpenAIChatClient + + +def get_weather( + location: Annotated[str, Field(description="The location to get the weather for.")], +) -> str: + """Get the weather for a given location.""" + conditions = ["sunny", "cloudy", "rainy", "stormy"] + return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C." + + +def get_menu_specials() -> str: + """Get today's menu specials.""" + return """ + Special Soup: Clam Chowder + Special Salad: Cobb Salad + Special Drink: Chai Tea + """ + + +async def main(): + agent = ChatClientAgent( + chat_client=OpenAIChatClient(), + instructions="You are a helpful assistant that can provide weather and restaurant information.", + tools=[get_weather, get_menu_specials] + ) + + response = await agent.run("What's the weather in Amsterdam and what are today's specials?") + print(response) + + """ + Output: + The weather in Amsterdam is sunny with a high of 22°C. Today's specials include + Clam Chowder soup, Cobb Salad, and Chai Tea as the special drink. + """ + +if __name__ == "__main__": + asyncio.run(main()) +``` + +You can explore additional agent samples [here](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started/agents). + +## 5. Multi-Agent Orchestration + +Coordinate multiple agents to collaborate on complex tasks using orchestration patterns: + +```python +import asyncio +from agent_framework import ChatClientAgent +from agent_framework.openai import OpenAIChatClient + + +async def main(): + # Create specialized agents + writer = ChatClientAgent( + chat_client=OpenAIChatClient(), + name="Writer", + instructions="You are a creative content writer. Generate and refine slogans based on feedback." + ) + + reviewer = ChatClientAgent( + chat_client=OpenAIChatClient(), + name="Reviewer", + instructions="You are a critical reviewer. Provide detailed feedback on proposed slogans." + ) + + # Sequential workflow: Writer creates, Reviewer provides feedback + task = "Create a slogan for a new electric SUV that is affordable and fun to drive." + + # Step 1: Writer creates initial slogan + initial_result = await writer.run(task) + print(f"Writer: {initial_result}") + + # Step 2: Reviewer provides feedback + feedback_request = f"Please review this slogan: {initial_result}" + feedback = await reviewer.run(feedback_request) + print(f"Reviewer: {feedback}") + + # Step 3: Writer refines based on feedback + refinement_request = f"Please refine this slogan based on the feedback: {initial_result}\nFeedback: {feedback}" + final_result = await writer.run(refinement_request) + print(f"Final Slogan: {final_result}") + + # Example Output: + # Writer: "Charge Forward: Affordable Adventure Awaits!" + # Reviewer: "Good energy, but 'Charge Forward' is overused in EV marketing..." + # Final Slogan: "Power Up Your Adventure: Premium Feel, Smart Price!" + +if __name__ == "__main__": + asyncio.run(main()) +``` + +**Note**: Advanced orchestration patterns like GroupChat, Sequential, and Concurrent orchestrations are coming soon. + +## More Examples & Samples + +- [Getting Started with Agents](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started/agents): Basic agent creation and tool usage +- [Chat Client Examples](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started/chat_client): Direct chat client usage patterns +- [Azure Integration](https://github.com/microsoft/agent-framework/tree/main/python/packages/azure): Azure OpenAI and AI Foundry integration +- [.NET Orchestration Samples](https://github.com/microsoft/agent-framework/tree/main/dotnet/samples/GettingStarted/Orchestration): Advanced multi-agent patterns (.NET) + +## Agent Framework Documentation + +- [Agent Framework Repository](https://github.com/microsoft/agent-framework) +- [Python Package Documentation](https://github.com/microsoft/agent-framework/tree/main/python) +- [.NET Package Documentation](https://github.com/microsoft/agent-framework/tree/main/dotnet) +- [Design Documents](https://github.com/microsoft/agent-framework/tree/main/docs/design) +- Learn docs are coming soon. diff --git a/python/docs/agent-framework/reference/index.md b/python/docs/agent-framework/reference/index.md index 3069549160..bf306dea5d 100644 --- a/python/docs/agent-framework/reference/index.md +++ b/python/docs/agent-framework/reference/index.md @@ -13,4 +13,5 @@ myst: python/agent_framework python/agent_framework.exceptions +python/agent_framework.openai ``` diff --git a/python/LICENSE b/python/packages/azure/LICENSE similarity index 100% rename from python/LICENSE rename to python/packages/azure/LICENSE diff --git a/python/packages/azure/README.md b/python/packages/azure/README.md index e69de29bb2..a1a5e05847 100644 --- a/python/packages/azure/README.md +++ b/python/packages/azure/README.md @@ -0,0 +1,9 @@ +# Get Started with Microsoft Agent Framework Azure + +Please install this package as the extra for `agent-framework`: + +```bash +pip install agent-framework[azure] +``` + +and see the [README](https://github.com/microsoft/agent-framework/tree/main/python/README.md) for more information. diff --git a/python/packages/azure/pyproject.toml b/python/packages/azure/pyproject.toml index c411e44592..3a048cb1d7 100644 --- a/python/packages/azure/pyproject.toml +++ b/python/packages/azure/pyproject.toml @@ -5,7 +5,7 @@ authors = [{ name = "Microsoft", email = "SK-Support@microsoft.com"}] readme = "README.md" requires-python = ">=3.10" version = "0.1.0b1" -license = {file = "../../LICENSE"} +license-files = ["LICENSE"] urls.homepage = "https://learn.microsoft.com/en-us/semantic-kernel/overview/" urls.source = "https://github.com/microsoft/agent-framework/tree/main/python" urls.release_notes = "https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true" @@ -24,44 +24,7 @@ classifiers = [ ] dependencies = [ "agent-framework", - "azure-identity >= 1.13", - "openai>=1.94.0", -] - -[dependency-groups] -dev = [ - "pre-commit >= 3.7", - "ruff>=0.11.8", - "pytest>=8.4.1", - "pytest-asyncio>=1.0.0", - "pytest-cov>=6.2.1", - "pytest-xdist[psutil]>=3.8.0", - "pytest-timeout>=2.3.1", - "mypy>=1.16.1", - "pyright>=1.1.402", - - #tasks - "poethepoet>=0.36.0", - "rich", - "tomli", - "tomli-w", - "markdownify", - # Documentation - "myst-nb==1.1.2", - "pydata-sphinx-theme==0.16.0", - "sphinx-copybutton", - "sphinx-design", - "sphinx", - "sphinxcontrib-apidoc", - "autodoc_pydantic~=2.2", - "pygments", - "sphinxext-rediraffe", - "opentelemetry-instrumentation-openai", - "markdown-it-py[linkify]", - # Documentation tooling - "diskcache", - "redis", - "sphinx-autobuild", + "azure-identity >= 1.13" ] [tool.uv] @@ -117,5 +80,5 @@ module-name = "agent_framework_azure" module-root = "" [build-system] -requires = ["uv_build>=0.7.19,<0.8.0"] +requires = ["uv_build>=0.8.2,<0.9.0"] build-backend = "uv_build" diff --git a/python/packages/foundry/LICENSE b/python/packages/foundry/LICENSE new file mode 100644 index 0000000000..9e841e7a26 --- /dev/null +++ b/python/packages/foundry/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/python/packages/foundry/README.md b/python/packages/foundry/README.md index e69de29bb2..021a83b574 100644 --- a/python/packages/foundry/README.md +++ b/python/packages/foundry/README.md @@ -0,0 +1,9 @@ +# Get Started with Microsoft Agent Framework Foundry + +Please install this package as the extra for `agent-framework`: + +```bash +pip install agent-framework[foundry] +``` + +and see the [README](https://github.com/microsoft/agent-framework/tree/main/python/README.md) for more information. diff --git a/python/packages/foundry/pyproject.toml b/python/packages/foundry/pyproject.toml index 6ea935129e..ce6828400f 100644 --- a/python/packages/foundry/pyproject.toml +++ b/python/packages/foundry/pyproject.toml @@ -5,7 +5,7 @@ authors = [{ name = "Microsoft", email = "SK-Support@microsoft.com"}] readme = "README.md" requires-python = ">=3.10" version = "0.1.0b1" -license = {file = "../../LICENSE"} +license-files = ["LICENSE"] urls.homepage = "https://learn.microsoft.com/en-us/semantic-kernel/overview/" urls.source = "https://github.com/microsoft/agent-framework/tree/main/python" urls.release_notes = "https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true" @@ -29,42 +29,6 @@ dependencies = [ "aiohttp ~= 3.8" ] -[dependency-groups] -dev = [ - "pre-commit >= 3.7", - "ruff>=0.11.8", - "pytest>=8.4.1", - "pytest-asyncio>=1.0.0", - "pytest-cov>=6.2.1", - "pytest-xdist[psutil]>=3.8.0", - "pytest-timeout>=2.3.1", - "mypy>=1.16.1", - "pyright>=1.1.402", - - #tasks - "poethepoet>=0.36.0", - "rich", - "tomli", - "tomli-w", - "markdownify", - # Documentation - "myst-nb==1.1.2", - "pydata-sphinx-theme==0.16.0", - "sphinx-copybutton", - "sphinx-design", - "sphinx", - "sphinxcontrib-apidoc", - "autodoc_pydantic~=2.2", - "pygments", - "sphinxext-rediraffe", - "opentelemetry-instrumentation-openai", - "markdown-it-py[linkify]", - # Documentation tooling - "diskcache", - "redis", - "sphinx-autobuild", -] - [tool.uv] prerelease = "if-necessary-or-explicit" environments = [ @@ -118,5 +82,5 @@ module-name = "agent_framework_foundry" module-root = "" [build-system] -requires = ["uv_build>=0.7.19,<0.8.0"] +requires = ["uv_build>=0.8.2,<0.9.0"] build-backend = "uv_build" diff --git a/python/packages/main/LICENSE b/python/packages/main/LICENSE new file mode 100644 index 0000000000..9e841e7a26 --- /dev/null +++ b/python/packages/main/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/python/packages/main/README.md b/python/packages/main/README.md new file mode 100644 index 0000000000..a0b3ad9840 --- /dev/null +++ b/python/packages/main/README.md @@ -0,0 +1,232 @@ +# Get Started with Microsoft Agent Framework + +Highlights +- Flexible Agent Framework: build, orchestrate, and deploy AI agents and multi-agent systems +- Multi-Agent Orchestration: Group chat, sequential, concurrent, and handoff patterns +- Plugin Ecosystem: Extend with native functions, OpenAPI, Model Context Protocol (MCP), and more +- LLM Support: OpenAI, Azure OpenAI, Azure AI Foundry, and more +- Runtime Support: In-process and distributed agent execution +- Multimodal: Text, vision, and function calling +- Cross-Platform: .NET and Python implementations + +## Quick Install + +```bash +pip install agent-framework +# Optional: Add Azure integration +pip install agent-framework[azure] +# Optional: Add Foundry integration +pip install agent-framework[foundry] +# Optional: Both +pip install agent-framework[azure,foundry] +``` + +Supported Platforms: +- Python: 3.10+ +- OS: Windows, macOS, Linux + +## 1. Setup API Keys + +Set as environment variables, or create a .env file at your project root: + +```bash +OPENAI_API_KEY=sk-... +OPENAI_CHAT_MODEL_ID=... +... +AZURE_OPENAI_API_KEY=... +AZURE_OPENAI_ENDPOINT=... +AZURE_OPENAI_CHAT_DEPLOYMENT_NAME=... +... +FOUNDRY_PROJECT_ENDPOINT=... +FOUNDRY_MODEL_DEPLOYMENT_NAME=... +``` + +You can also override environment variables by explicitly passing configuration parameters to the chat client constructor: + +```python +from agent_framework.azure import AzureChatClient + +chat_client = AzureChatClient( + api_key=..., + endpoint=..., + deployment_name=..., + api_version=..., +) +``` + +See the following [setup guide](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started) for more information. + +## 2. Create a Simple Agent + +Create agents and invoke them directly: + +```python +import asyncio +from agent_framework import ChatClientAgent +from agent_framework.openai import OpenAIChatClient + +async def main(): + agent = ChatClientAgent( + chat_client=OpenAIChatClient(), + instructions=""" + 1) A robot may not injure a human being... + 2) A robot must obey orders given it by human beings... + 3) A robot must protect its own existence... + + Give me the TLDR in exactly 5 words. + """ + ) + + result = await agent.run("Summarize the Three Laws of Robotics") + print(result) + +asyncio.run(main()) +# Output: Protect humans, obey, self-preserve, prioritized. +``` + +## 3. Directly Use Chat Clients (No Agent Required) + +You can use the chat client classes directly for advanced workflows: + +```python +import asyncio +from agent_framework.openai import OpenAIChatClient +from agent_framework import ChatMessage, ChatRole + +async def main(): + client = OpenAIChatClient() + + messages = [ + ChatMessage(role=ChatRole.SYSTEM, text="You are a helpful assistant."), + ChatMessage(role=ChatRole.USER, text="Write a haiku about Agent Framework.") + ] + + response = await client.get_response(messages) + print(response.messages[0].text) + + """ + Output: + + Agents work in sync, + Framework threads through each task— + Code sparks collaboration. + """ + +asyncio.run(main()) +``` + +## 4. Build an Agent with Tools and Functions + +Enhance your agent with custom tools and function calling: + +```python +import asyncio +from typing import Annotated +from random import randint +from pydantic import Field +from agent_framework import ChatClientAgent +from agent_framework.openai import OpenAIChatClient + + +def get_weather( + location: Annotated[str, Field(description="The location to get the weather for.")], +) -> str: + """Get the weather for a given location.""" + conditions = ["sunny", "cloudy", "rainy", "stormy"] + return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C." + + +def get_menu_specials() -> str: + """Get today's menu specials.""" + return """ + Special Soup: Clam Chowder + Special Salad: Cobb Salad + Special Drink: Chai Tea + """ + + +async def main(): + agent = ChatClientAgent( + chat_client=OpenAIChatClient(), + instructions="You are a helpful assistant that can provide weather and restaurant information.", + tools=[get_weather, get_menu_specials] + ) + + response = await agent.run("What's the weather in Amsterdam and what are today's specials?") + print(response) + + # Output: + # The weather in Amsterdam is sunny with a high of 22°C. Today's specials include + # Clam Chowder soup, Cobb Salad, and Chai Tea as the special drink. + +asyncio.run(main()) +``` + +You can explore additional agent samples [here](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started/agents). + +## 5. Multi-Agent Orchestration + +Coordinate multiple agents to collaborate on complex tasks using orchestration patterns: + +```python +import asyncio +from agent_framework import ChatClientAgent +from agent_framework.openai import OpenAIChatClient + + +async def main(): + # Create specialized agents + writer = ChatClientAgent( + chat_client=OpenAIChatClient(), + name="Writer", + instructions="You are a creative content writer. Generate and refine slogans based on feedback." + ) + + reviewer = ChatClientAgent( + chat_client=OpenAIChatClient(), + name="Reviewer", + instructions="You are a critical reviewer. Provide detailed feedback on proposed slogans." + ) + + # Sequential workflow: Writer creates, Reviewer provides feedback + task = "Create a slogan for a new electric SUV that is affordable and fun to drive." + + # Step 1: Writer creates initial slogan + initial_result = await writer.run(task) + print(f"Writer: {initial_result}") + + # Step 2: Reviewer provides feedback + feedback_request = f"Please review this slogan: {initial_result}" + feedback = await reviewer.run(feedback_request) + print(f"Reviewer: {feedback}") + + # Step 3: Writer refines based on feedback + refinement_request = f"Please refine this slogan based on the feedback: {initial_result}\nFeedback: {feedback}" + final_result = await writer.run(refinement_request) + print(f"Final Slogan: {final_result}") + + # Example Output: + # Writer: "Charge Forward: Affordable Adventure Awaits!" + # Reviewer: "Good energy, but 'Charge Forward' is overused in EV marketing..." + # Final Slogan: "Power Up Your Adventure: Premium Feel, Smart Price!" + +if __name__ == "__main__": + asyncio.run(main()) +``` + +**Note**: Advanced orchestration patterns like GroupChat, Sequential, and Concurrent orchestrations are coming soon. + +## More Examples & Samples + +- [Getting Started with Agents](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started/agents): Basic agent creation and tool usage +- [Chat Client Examples](https://github.com/microsoft/agent-framework/tree/main/python/samples/getting_started/chat_client): Direct chat client usage patterns +- [Azure Integration](https://github.com/microsoft/agent-framework/tree/main/python/packages/azure): Azure OpenAI and AI Foundry integration +- [.NET Orchestration Samples](https://github.com/microsoft/agent-framework/tree/main/dotnet/samples/GettingStarted/Orchestration): Advanced multi-agent patterns (.NET) + +## Agent Framework Documentation + +- [Agent Framework Repository](https://github.com/microsoft/agent-framework) +- [Python Package Documentation](https://github.com/microsoft/agent-framework/tree/main/python) +- [.NET Package Documentation](https://github.com/microsoft/agent-framework/tree/main/dotnet) +- [Design Documents](https://github.com/microsoft/agent-framework/tree/main/docs/design) +- Learn docs are coming soon. diff --git a/python/packages/main/pyproject.toml b/python/packages/main/pyproject.toml index 593c3c8589..789ad70c29 100644 --- a/python/packages/main/pyproject.toml +++ b/python/packages/main/pyproject.toml @@ -2,10 +2,10 @@ name = "agent-framework" description = "Microsoft Agent Framework for building AI Agents with Python." authors = [{ name = "Microsoft", email = "SK-Support@microsoft.com"}] -readme = "../../README.md" +readme = "README.md" requires-python = ">=3.10" version = "0.1.0b1" -license = {file = "../../LICENSE"} +license-files = ["LICENSE"] urls.homepage = "https://learn.microsoft.com/en-us/semantic-kernel/overview/" urls.source = "https://github.com/microsoft/agent-framework/tree/main/python" urls.release_notes = "https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true" @@ -37,42 +37,6 @@ foundry = [ "agent-framework-foundry" ] -[dependency-groups] -dev = [ - "pre-commit >= 3.7", - "ruff>=0.11.8", - "pytest>=8.4.1", - "pytest-asyncio>=1.0.0", - "pytest-cov>=6.2.1", - "pytest-xdist[psutil]>=3.8.0", - "pytest-timeout>=2.3.1", - "mypy>=1.16.1", - "pyright>=1.1.402", - - #tasks - "poethepoet>=0.36.0", - "rich", - "tomli", - "tomli-w", - "markdownify", - # Documentation - "myst-nb==1.1.2", - "pydata-sphinx-theme==0.16.0", - "sphinx-copybutton", - "sphinx-design", - "sphinx", - "sphinxcontrib-apidoc", - "autodoc_pydantic~=2.2", - "pygments", - "sphinxext-rediraffe", - "opentelemetry-instrumentation-openai", - "markdown-it-py[linkify]", - # Documentation tooling - "diskcache", - "redis", - "sphinx-autobuild", -] - [tool.uv] prerelease = "if-necessary-or-explicit" environments = [ @@ -127,5 +91,5 @@ module-name = "agent_framework" module-root = "" [build-system] -requires = ["uv_build>=0.7.19,<0.8.0"] +requires = ["uv_build>=0.8.2,<0.9.0"] build-backend = "uv_build" diff --git a/python/pyproject.toml b/python/pyproject.toml index e8425f091b..2ee0a1e95d 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -11,6 +11,7 @@ dependencies = [ [dependency-groups] dev = [ + "uv>=0.8.2,<0.9.0", "pre-commit >= 3.7", "ruff>=0.11.8", "pytest>=8.4.1", @@ -42,8 +43,6 @@ dev = [ "diskcache", "redis", "sphinx-autobuild", - "tox>=4.27.0", - "tox-uv>=1.26.1", ] [tool.uv] @@ -152,7 +151,7 @@ exclude_dirs = ["tests", "./run_tasks_in_packages_if_exists.py", "./check_md_cod executor.type = "uv" [tool.poe.tasks] -markdown-code-lint = """python check_md_code_blocks.py ../README.md ./docs/agent-framework/**/*.md README.md""" +markdown-code-lint = """python check_md_code_blocks.py ./docs/agent-framework/**/*.md README.md""" samples-code-check = """pyright ./samples""" docs-clean = "rm -rf docs/build" docs-build = "sphinx-build docs/agent-framework docs/build" @@ -173,7 +172,7 @@ check = ["fmt", "lint", "pyright", "mypy", "test", "markdown-code-lint", "sample pre-commit-check = ["fmt", "lint", "pyright", "markdown-code-lint", "samples-code-check"] [tool.poe.tasks.venv] -cmd = "uv venv --python $python" +cmd = "uv venv --clear --python $python" args = [{ name = "python", default = "3.13", options = ['-p', '--python'] }] [tool.poe.tasks.setup] sequence = [ @@ -204,4 +203,3 @@ deps = [ "-e packages/main" ] commands = [["pytest", { replace = "posargs", default = ["packages/main/tests"], extend = true }]] - diff --git a/python/uv.lock b/python/uv.lock index ac1a17c89a..68139b1197 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -54,39 +54,6 @@ foundry = [ { name = "agent-framework-foundry", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -[package.dev-dependencies] -dev = [ - { name = "autodoc-pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "diskcache", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "markdown-it-py", extra = ["linkify"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "markdownify", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "mypy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "myst-nb", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "opentelemetry-instrumentation-openai", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "poethepoet", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pre-commit", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pydata-sphinx-theme", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pygments", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyright", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-asyncio", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-cov", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-timeout", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-xdist", extra = ["psutil"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "redis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "rich", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "ruff", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "sphinx-autobuild", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx-copybutton", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx-design", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinxcontrib-apidoc", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinxext-rediraffe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli-w", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, -] - [package.metadata] requires-dist = [ { name = "agent-framework-azure", marker = "extra == 'azure'", editable = "packages/azure" }, @@ -98,38 +65,6 @@ requires-dist = [ ] provides-extras = ["azure", "foundry"] -[package.metadata.requires-dev] -dev = [ - { name = "autodoc-pydantic", specifier = "~=2.2" }, - { name = "diskcache" }, - { name = "markdown-it-py", extras = ["linkify"] }, - { name = "markdownify" }, - { name = "mypy", specifier = ">=1.16.1" }, - { name = "myst-nb", specifier = "==1.1.2" }, - { name = "opentelemetry-instrumentation-openai" }, - { name = "poethepoet", specifier = ">=0.36.0" }, - { name = "pre-commit", specifier = ">=3.7" }, - { name = "pydata-sphinx-theme", specifier = "==0.16.0" }, - { name = "pygments" }, - { name = "pyright", specifier = ">=1.1.402" }, - { name = "pytest", specifier = ">=8.4.1" }, - { name = "pytest-asyncio", specifier = ">=1.0.0" }, - { name = "pytest-cov", specifier = ">=6.2.1" }, - { name = "pytest-timeout", specifier = ">=2.3.1" }, - { name = "pytest-xdist", extras = ["psutil"], specifier = ">=3.8.0" }, - { name = "redis" }, - { name = "rich" }, - { name = "ruff", specifier = ">=0.11.8" }, - { name = "sphinx" }, - { name = "sphinx-autobuild" }, - { name = "sphinx-copybutton" }, - { name = "sphinx-design" }, - { name = "sphinxcontrib-apidoc" }, - { name = "sphinxext-rediraffe" }, - { name = "tomli" }, - { name = "tomli-w" }, -] - [[package]] name = "agent-framework-azure" version = "0.1.0b1" @@ -137,79 +72,12 @@ source = { editable = "packages/azure" } dependencies = [ { name = "agent-framework", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "azure-identity", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "openai", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, -] - -[package.dev-dependencies] -dev = [ - { name = "autodoc-pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "diskcache", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "markdown-it-py", extra = ["linkify"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "markdownify", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "mypy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "myst-nb", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "opentelemetry-instrumentation-openai", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "poethepoet", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pre-commit", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pydata-sphinx-theme", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pygments", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyright", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-asyncio", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-cov", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-timeout", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-xdist", extra = ["psutil"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "redis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "rich", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "ruff", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "sphinx-autobuild", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx-copybutton", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx-design", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinxcontrib-apidoc", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinxext-rediraffe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli-w", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] [package.metadata] requires-dist = [ { name = "agent-framework", editable = "packages/main" }, { name = "azure-identity", specifier = ">=1.13" }, - { name = "openai", specifier = ">=1.94.0" }, -] - -[package.metadata.requires-dev] -dev = [ - { name = "autodoc-pydantic", specifier = "~=2.2" }, - { name = "diskcache" }, - { name = "markdown-it-py", extras = ["linkify"] }, - { name = "markdownify" }, - { name = "mypy", specifier = ">=1.16.1" }, - { name = "myst-nb", specifier = "==1.1.2" }, - { name = "opentelemetry-instrumentation-openai" }, - { name = "poethepoet", specifier = ">=0.36.0" }, - { name = "pre-commit", specifier = ">=3.7" }, - { name = "pydata-sphinx-theme", specifier = "==0.16.0" }, - { name = "pygments" }, - { name = "pyright", specifier = ">=1.1.402" }, - { name = "pytest", specifier = ">=8.4.1" }, - { name = "pytest-asyncio", specifier = ">=1.0.0" }, - { name = "pytest-cov", specifier = ">=6.2.1" }, - { name = "pytest-timeout", specifier = ">=2.3.1" }, - { name = "pytest-xdist", extras = ["psutil"], specifier = ">=3.8.0" }, - { name = "redis" }, - { name = "rich" }, - { name = "ruff", specifier = ">=0.11.8" }, - { name = "sphinx" }, - { name = "sphinx-autobuild" }, - { name = "sphinx-copybutton" }, - { name = "sphinx-design" }, - { name = "sphinxcontrib-apidoc" }, - { name = "sphinxext-rediraffe" }, - { name = "tomli" }, - { name = "tomli-w" }, ] [[package]] @@ -223,39 +91,6 @@ dependencies = [ { name = "azure-ai-projects", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -[package.dev-dependencies] -dev = [ - { name = "autodoc-pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "diskcache", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "markdown-it-py", extra = ["linkify"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "markdownify", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "mypy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "myst-nb", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "opentelemetry-instrumentation-openai", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "poethepoet", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pre-commit", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pydata-sphinx-theme", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pygments", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyright", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-asyncio", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-cov", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-timeout", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pytest-xdist", extra = ["psutil"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "redis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "rich", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "ruff", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, - { name = "sphinx-autobuild", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx-copybutton", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinx-design", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinxcontrib-apidoc", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "sphinxext-rediraffe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli-w", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, -] - [package.metadata] requires-dist = [ { name = "agent-framework", editable = "packages/main" }, @@ -264,38 +99,6 @@ requires-dist = [ { name = "azure-ai-projects", specifier = ">=1.0.0b11" }, ] -[package.metadata.requires-dev] -dev = [ - { name = "autodoc-pydantic", specifier = "~=2.2" }, - { name = "diskcache" }, - { name = "markdown-it-py", extras = ["linkify"] }, - { name = "markdownify" }, - { name = "mypy", specifier = ">=1.16.1" }, - { name = "myst-nb", specifier = "==1.1.2" }, - { name = "opentelemetry-instrumentation-openai" }, - { name = "poethepoet", specifier = ">=0.36.0" }, - { name = "pre-commit", specifier = ">=3.7" }, - { name = "pydata-sphinx-theme", specifier = "==0.16.0" }, - { name = "pygments" }, - { name = "pyright", specifier = ">=1.1.402" }, - { name = "pytest", specifier = ">=8.4.1" }, - { name = "pytest-asyncio", specifier = ">=1.0.0" }, - { name = "pytest-cov", specifier = ">=6.2.1" }, - { name = "pytest-timeout", specifier = ">=2.3.1" }, - { name = "pytest-xdist", extras = ["psutil"], specifier = ">=3.8.0" }, - { name = "redis" }, - { name = "rich" }, - { name = "ruff", specifier = ">=0.11.8" }, - { name = "sphinx" }, - { name = "sphinx-autobuild" }, - { name = "sphinx-copybutton" }, - { name = "sphinx-design" }, - { name = "sphinxcontrib-apidoc" }, - { name = "sphinxext-rediraffe" }, - { name = "tomli" }, - { name = "tomli-w" }, -] - [[package]] name = "agent-framework-project" version = "0.0.0" @@ -337,8 +140,7 @@ dev = [ { name = "sphinxext-rediraffe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "tomli", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "tomli-w", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tox", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tox-uv", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "uv", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] [package.metadata] @@ -378,8 +180,7 @@ dev = [ { name = "sphinxext-rediraffe" }, { name = "tomli" }, { name = "tomli-w" }, - { name = "tox", specifier = ">=4.27.0" }, - { name = "tox-uv", specifier = ">=1.26.1" }, + { name = "uv", specifier = ">=0.8.2,<0.9.0" }, ] [[package]] @@ -679,15 +480,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/50/cd/30110dc0ffcf3b131156077b90e9f60ed75711223f306da4db08eff8403b/beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", size = 187285, upload-time = "2025-04-15T17:05:12.221Z" }, ] -[[package]] -name = "cachetools" -version = "6.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/89/817ad5d0411f136c484d535952aef74af9b25e0d99e90cdffbe121e6d628/cachetools-6.1.0.tar.gz", hash = "sha256:b4c4f404392848db3ce7aac34950d17be4d864da4b8b66911008e430bc544587", size = 30714, upload-time = "2025-06-16T18:51:03.07Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/00/f0/2ef431fe4141f5e334759d73e81120492b23b2824336883a91ac04ba710b/cachetools-6.1.0-py3-none-any.whl", hash = "sha256:1c7bb3cf9193deaf3508b7c5f2a79986c13ea38965c5adcff1f84519cf39163e", size = 11189, upload-time = "2025-06-16T18:51:01.514Z" }, -] - [[package]] name = "certifi" version = "2025.7.14" @@ -763,15 +555,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, ] -[[package]] -name = "chardet" -version = "5.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618, upload-time = "2023-08-01T19:23:02.662Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385, upload-time = "2023-08-01T19:23:00.661Z" }, -] - [[package]] name = "charset-normalizer" version = "3.4.2" @@ -1737,16 +1520,16 @@ wheels = [ [[package]] name = "msal" -version = "1.32.3" +version = "1.33.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cryptography", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "pyjwt", extra = ["crypto"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3f/90/81dcc50f0be11a8c4dcbae1a9f761a26e5f905231330a7cacc9f04ec4c61/msal-1.32.3.tar.gz", hash = "sha256:5eea038689c78a5a70ca8ecbe1245458b55a857bd096efb6989c69ba15985d35", size = 151449, upload-time = "2025-04-25T13:12:34.204Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d5/da/81acbe0c1fd7e9e4ec35f55dadeba9833a847b9a6ba2e2d1e4432da901dd/msal-1.33.0.tar.gz", hash = "sha256:836ad80faa3e25a7d71015c990ce61f704a87328b1e73bcbb0623a18cbf17510", size = 153801, upload-time = "2025-07-22T19:36:33.693Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/04/bf/81516b9aac7fd867709984d08eb4db1d2e3fe1df795c8e442cde9b568962/msal-1.32.3-py3-none-any.whl", hash = "sha256:b2798db57760b1961b142f027ffb7c8169536bf77316e99a0df5c4aaebb11569", size = 115358, upload-time = "2025-04-25T13:12:33.034Z" }, + { url = "https://files.pythonhosted.org/packages/86/5b/fbc73e91f7727ae1e79b21ed833308e99dc11cc1cd3d4717f579775de5e9/msal-1.33.0-py3-none-any.whl", hash = "sha256:c0cd41cecf8eaed733ee7e3be9e040291eba53b0f262d3ae9c58f38b04244273", size = 116853, upload-time = "2025-07-22T19:36:32.403Z" }, ] [[package]] @@ -2002,7 +1785,7 @@ wheels = [ [[package]] name = "openai" -version = "1.97.0" +version = "1.97.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -2014,9 +1797,9 @@ dependencies = [ { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e0/c6/b8d66e4f3b95493a8957065b24533333c927dc23817abe397f13fe589c6e/openai-1.97.0.tar.gz", hash = "sha256:0be349569ccaa4fb54f97bb808423fd29ccaeb1246ee1be762e0c81a47bae0aa", size = 493850, upload-time = "2025-07-16T16:37:35.196Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/57/1c471f6b3efb879d26686d31582997615e969f3bb4458111c9705e56332e/openai-1.97.1.tar.gz", hash = "sha256:a744b27ae624e3d4135225da9b1c89c107a2a7e5bc4c93e5b7b5214772ce7a4e", size = 494267, upload-time = "2025-07-22T13:10:12.607Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/91/1f1cf577f745e956b276a8b1d3d76fa7a6ee0c2b05db3b001b900f2c71db/openai-1.97.0-py3-none-any.whl", hash = "sha256:a1c24d96f4609f3f7f51c9e1c2606d97cc6e334833438659cfd687e9c972c610", size = 764953, upload-time = "2025-07-16T16:37:33.135Z" }, + { url = "https://files.pythonhosted.org/packages/ee/35/412a0e9c3f0d37c94ed764b8ac7adae2d834dbd20e69f6aca582118e0f55/openai-1.97.1-py3-none-any.whl", hash = "sha256:4e96bbdf672ec3d44968c9ea39d2c375891db1acc1794668d8149d5fa6000606", size = 764380, upload-time = "2025-07-22T13:10:10.689Z" }, ] [[package]] @@ -2049,7 +1832,7 @@ wheels = [ [[package]] name = "opentelemetry-instrumentation-openai" -version = "0.42.0" +version = "0.43.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-api", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -2058,9 +1841,9 @@ dependencies = [ { name = "opentelemetry-semantic-conventions-ai", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "tiktoken", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4b/76/27a4f3ad984e626d2d5543ec84e696d7286aba07e15624a9f61f682f0228/opentelemetry_instrumentation_openai-0.42.0.tar.gz", hash = "sha256:d76ed23adbb00a8c35f1cee771afa824485b78f436eb77896db1a8988cdf8e76", size = 23313, upload-time = "2025-07-17T19:46:04.031Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4d/4b/6d327e374c4e9f35f4769515692310d5276cdf40bad268c28d2ae1865183/opentelemetry_instrumentation_openai-0.43.0.tar.gz", hash = "sha256:0329ae6eb8c5ddbf87db2110d872db7faa18f2a8ceaf2c46c9f51fc4c05c2b4f", size = 23438, upload-time = "2025-07-22T08:31:05.408Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/14/5199dd777e5fa83f14008dd1c0535833ac7b20c8f36c1b0a6c2ab729a8eb/opentelemetry_instrumentation_openai-0.42.0-py3-none-any.whl", hash = "sha256:e80e051a781fae981238c10a70b6176be3655ab35aa1cf10128cae44439428c4", size = 33403, upload-time = "2025-07-17T19:45:34.602Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ed/40a8f791df4a6c5c4455edd1ef7d44afb6a47c7d9a5533421ff258a365db/opentelemetry_instrumentation_openai-0.43.0-py3-none-any.whl", hash = "sha256:75be471e66a2d61608a6604ff3674d3320ecfe3bc5c49f955e37b08aafbb921e", size = 33541, upload-time = "2025-07-22T08:30:36.934Z" }, ] [[package]] @@ -2494,19 +2277,6 @@ crypto = [ { name = "cryptography", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -[[package]] -name = "pyproject-api" -version = "1.9.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/19/fd/437901c891f58a7b9096511750247535e891d2d5a5a6eefbc9386a2b41d5/pyproject_api-1.9.1.tar.gz", hash = "sha256:43c9918f49daab37e302038fc1aed54a8c7a91a9fa935d00b9a485f37e0f5335", size = 22710, upload-time = "2025-05-12T14:41:58.025Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/e6/c293c06695d4a3ab0260ef124a74ebadba5f4c511ce3a4259e976902c00b/pyproject_api-1.9.1-py3-none-any.whl", hash = "sha256:7d6238d92f8962773dd75b5f0c4a6a27cce092a14b623b811dba656f3b628948", size = 13158, upload-time = "2025-05-12T14:41:56.217Z" }, -] - [[package]] name = "pyright" version = "1.1.403" @@ -3446,42 +3216,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/55/a7/535c44c7bea4578e48281d83c615219f3ab19e6abc67625ef637c73987be/tornado-6.5.1-cp39-abi3-win_arm64.whl", hash = "sha256:02420a0eb7bf617257b9935e2b754d1b63897525d8a289c9d65690d580b4dcf7", size = 443596, upload-time = "2025-05-22T18:15:37.433Z" }, ] -[[package]] -name = "tox" -version = "4.28.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cachetools", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "chardet", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "colorama", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "filelock", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "platformdirs", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pluggy", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "pyproject-api", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tomli", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, - { name = "virtualenv", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/98/3d/2efc68c86b2879b0abdf0d07839da47026489dca424a11379277a40fc67c/tox-4.28.0.tar.gz", hash = "sha256:442347b1a415733850f097e7e78b8c5f38b5e1719f8b7205aade5d055f08068c", size = 199516, upload-time = "2025-07-20T18:25:51.975Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/be/df/7f962b921f4efa414ad06f2abc665eff379c62ee46b959779381209e2e72/tox-4.28.0-py3-none-any.whl", hash = "sha256:3e2f5c0a00523a58666690108b66820150f6435cb6e4dd95caf21bb52133c1d1", size = 173883, upload-time = "2025-07-20T18:25:49.934Z" }, -] - -[[package]] -name = "tox-uv" -version = "1.26.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "tox", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "uv", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7e/31/2c02a8b4d85d3538d6e9a7aa55dfaf3ea372b2007496b9235047e18c0953/tox_uv-1.26.2.tar.gz", hash = "sha256:5270d5d49e26c1303d902b90d6143a593b43ae148ccc5107251b79bf5bd4fefd", size = 21895, upload-time = "2025-07-21T17:03:39.196Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/73/c9/354b2a28112ce9619616f09a3e8363dae01f9a4c5a2716fa92bcfcf6ccc5/tox_uv-1.26.2-py3-none-any.whl", hash = "sha256:f95c8635b6e046534faf4de88f46c46ac0d644f2dbe0104fc6adac637e0d44b6", size = 16666, upload-time = "2025-07-21T17:03:38.037Z" }, -] - [[package]] name = "tqdm" version = "4.67.1" @@ -3544,27 +3278,27 @@ wheels = [ [[package]] name = "uv" -version = "0.8.0" +version = "0.8.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/6c/0f42f6f59af910ab67ce5acb7f11e6341275cfe9cfa0b8a2ae97303e5775/uv-0.8.0.tar.gz", hash = "sha256:5d4b05056cc923e579007aede5ad1c3cf2c22628a89585f503b724521036748c", size = 3395163, upload-time = "2025-07-17T22:51:40.756Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/44/b53ae1f6b08724ddf3ec7125ddb6a381bd64ccdd696e8d87a1db3502aa10/uv-0.8.2.tar.gz", hash = "sha256:1a2c6d332a4c38f7489f08829aea19cd1e276df7f2c6e51ae64ed92f8574cd68", size = 3412893, upload-time = "2025-07-22T20:36:33.108Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/73/0a/07735385f63229c5a6079044861a7462b1f9ff02dc7c6a891d296ffed9b0/uv-0.8.0-py3-none-linux_armv6l.whl", hash = "sha256:7f1a7f9b10299d9db15acac6cdffc5af23c2b0fd6e56add6d6e5d100a82b5c1f", size = 17839329, upload-time = "2025-07-17T22:50:56.938Z" }, - { url = "https://files.pythonhosted.org/packages/8e/c1/160b81f8c34bf5ea6bddde96f80f3f000d083482f2612a98725a9f714707/uv-0.8.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6aeecfef8955dafcbad24ef5258341f2fcdf969949f74ccaa16a7bf9c3ec44b4", size = 17952798, upload-time = "2025-07-17T22:51:02.635Z" }, - { url = "https://files.pythonhosted.org/packages/9d/98/9a89983caa05cf998eea3dac1e6cff2e0ab8099be0695fd8b9dc6a5038a0/uv-0.8.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2d0ebf05eaee75921b3f23e7401a56bc0732bcdabb7469081ab00769340a93b4", size = 16618272, upload-time = "2025-07-17T22:51:04.941Z" }, - { url = "https://files.pythonhosted.org/packages/6e/8a/ed8c00d04c621b693c53cc9570ecddf766f8ff2078d6182eba55d0c20b10/uv-0.8.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:b784215c688c4eb54df62fb7506ba7c763fb8c9ba8457cd5dd48f0679f5d0328", size = 17199728, upload-time = "2025-07-17T22:51:06.853Z" }, - { url = "https://files.pythonhosted.org/packages/c1/08/fd29a5f93576f81a4d912e60d98fcb78e727c293f57b5a703e121d1875f2/uv-0.8.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:422e6c61b1555478f34300663f0057d5d4fea788c50eae31b332d0cec2a71536", size = 17561205, upload-time = "2025-07-17T22:51:09.528Z" }, - { url = "https://files.pythonhosted.org/packages/f3/28/80a4c04e0c843b16c2406a9a699dea4d2ac0f4863295194a7e202b917afa/uv-0.8.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19bd1fc94de3714c41d9f9f4dbcfdd2feeca00439b2fb2212ece249649b85c72", size = 18337053, upload-time = "2025-07-17T22:51:12.064Z" }, - { url = "https://files.pythonhosted.org/packages/00/43/8c86a21efced9d2617311b456a1e8ad76f4eba2d4809fe5a8d4639719949/uv-0.8.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c039a27387033c84eb07023c941cb6c3f4d71336ada54b83866929af9db75839", size = 19484516, upload-time = "2025-07-17T22:51:14.336Z" }, - { url = "https://files.pythonhosted.org/packages/38/0b/e74a16000ad8e5811ed648bb1801377b311640ed5b7033959fb5c80ab826/uv-0.8.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f5deec88789d0c03eba6af2e615e310eaa4426deb5c690f15e54f09d4a8ad0d", size = 19292816, upload-time = "2025-07-17T22:51:16.757Z" }, - { url = "https://files.pythonhosted.org/packages/91/73/c8ee97f38adee10abfa7040ea5e3f5c37e0be2e67437346ba4dcce211d01/uv-0.8.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d3fcbd19654f168e1cae3054ed75cfc0c80a452d0668f90fc579135de6d7588e", size = 18835921, upload-time = "2025-07-17T22:51:18.948Z" }, - { url = "https://files.pythonhosted.org/packages/bf/94/b8609393606e2f80dec8d6e2a26b79d703857a9d761487cdd05d081d628f/uv-0.8.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb939490ce24d5f88ddebf2ceaf30c613b2bd27f2e67ae62ec0960baa5f8412d", size = 18708625, upload-time = "2025-07-17T22:51:22.37Z" }, - { url = "https://files.pythonhosted.org/packages/2a/44/8754d0a27b4d52d8cce9a5d2e50196dc14a5b7c0739858eabf4abfec1740/uv-0.8.0-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:57af365c459d8e05274363cb10f4781a5e15b7b6f56d1427fd5b04302aa3d244", size = 17464028, upload-time = "2025-07-17T22:51:24.855Z" }, - { url = "https://files.pythonhosted.org/packages/1c/17/ce98535a2f167feeea4d3b5f266239ebfe11ba5ceb1be3aad9772b35e9e0/uv-0.8.0-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:9fb57d550887e9858b8c7c0417e5aa3e9629c2ec851f1567f1cde2ba9bf2ee79", size = 17503466, upload-time = "2025-07-17T22:51:27.253Z" }, - { url = "https://files.pythonhosted.org/packages/ce/37/3990cf8a19012010cd1fafce7934c0aaa8375712c8bc037e0c3ef148df0c/uv-0.8.0-py3-none-musllinux_1_1_i686.whl", hash = "sha256:7bd1ff23f8585e0e80024341aeb896b6b5ce94d43d3a95142be8e4bb3f1354b4", size = 17843023, upload-time = "2025-07-17T22:51:29.44Z" }, - { url = "https://files.pythonhosted.org/packages/e0/91/b88ffc2355fe6c2d1695f42a4605ff0f2773d5bd1a62699757c84ccc6496/uv-0.8.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:29757a08499e4c4462efa4fcba664c8850eb7ab8ec04852582adb901591dcc50", size = 18862516, upload-time = "2025-07-17T22:51:31.887Z" }, - { url = "https://files.pythonhosted.org/packages/37/39/c470b8de6e250fb8f146c3f72c396a9e9f457cfbb04618f430cc52a3a84f/uv-0.8.0-py3-none-win32.whl", hash = "sha256:84b03d7b34e1a8e62b34d13e88f434e3f1773a0841f7ba3603ca23d360529e84", size = 17757431, upload-time = "2025-07-17T22:51:34.24Z" }, - { url = "https://files.pythonhosted.org/packages/fd/4e/4a69b1baa14dfee113f76c823ffa4e79cd6bc6452c24454382a6fa793f2a/uv-0.8.0-py3-none-win_amd64.whl", hash = "sha256:2f47fca8cb0301408ec1ae7f3e0388afb36fc36188d1775dbd8daf336bf5be6f", size = 19493722, upload-time = "2025-07-17T22:51:36.672Z" }, - { url = "https://files.pythonhosted.org/packages/79/95/2803b563c61cd9b26f89a15b248d7e2ee5bbfbac892966ebd09111613f38/uv-0.8.0-py3-none-win_arm64.whl", hash = "sha256:aefc09b9a580f7f41a2358462215538f3806de60c6f20ade4a25ee4d678267e1", size = 18090168, upload-time = "2025-07-17T22:51:38.946Z" }, + { url = "https://files.pythonhosted.org/packages/f3/40/03c5cd3c9fa0fb53dcce1a39a6a9da6d81f29057cf9c4b9bb850dc58e2fb/uv-0.8.2-py3-none-linux_armv6l.whl", hash = "sha256:a89c9a471fbb436063e79afa919b2fb27462900f0f3781f776d8fd0b874acd56", size = 17875572, upload-time = "2025-07-22T20:35:33.672Z" }, + { url = "https://files.pythonhosted.org/packages/22/13/1d97c67fe666112c4327d6eec8bf39c244931c08848d4c95be0a80017f19/uv-0.8.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a3b147064f69455b4558263228b3fdb053c3d550f25d41b049c4d34f1f77d74c", size = 17948871, upload-time = "2025-07-22T20:35:38.742Z" }, + { url = "https://files.pythonhosted.org/packages/72/ec/0dd7b14f92de906afa3adde0f31e05150d081f1aadce9eb77689e3adc4ca/uv-0.8.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ebface4a113c493d953554460429731d44ede2427ba97e606955daadcc6e7ddc", size = 16660631, upload-time = "2025-07-22T20:35:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/fc/bf/4896cde38c29cbca42d1d0f73d80e15e20826968817150323a34c8b23436/uv-0.8.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:6fb07dd58a2cb79640109c0604aeec57d1062fad89114c0fda2f9dbe3de3c0bb", size = 17208209, upload-time = "2025-07-22T20:35:45.355Z" }, + { url = "https://files.pythonhosted.org/packages/cc/91/f03b95ee6bb8c7bc4d6596664235992d1931d6e6b1b018acda6aeab69ea2/uv-0.8.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6af1b0f0f5f1416e94a6b098a595f360303a0024b21cf563d4e6139e6dd72640", size = 17570752, upload-time = "2025-07-22T20:35:48.711Z" }, + { url = "https://files.pythonhosted.org/packages/00/44/3c905c0bce2113a664432c50b7a605eea9f271d126333b2a6c9ec5105ef3/uv-0.8.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bddf1ceceaddbc3f2cf2ebdad3213482d6dab3d1b452ddfecd35468e3b2f0e6", size = 18207389, upload-time = "2025-07-22T20:35:52.415Z" }, + { url = "https://files.pythonhosted.org/packages/67/b9/8a384dc22db96f54642889fa609192f79cd58447755d90b1163a9ba5d812/uv-0.8.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:bffe304fec46d6c264c3b34d58b3358764b7cc17af13bd421e1cd1300b706f93", size = 19633291, upload-time = "2025-07-22T20:35:56.015Z" }, + { url = "https://files.pythonhosted.org/packages/46/c6/fd7855f0aba4a07a5b7a08b95cd6b9d264b534a3bc5095a4acb55aca1d46/uv-0.8.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d53b79f8304e98ee082336fc4c204a7892d15f78799ec2d59ceb09b0b82e45d", size = 19381757, upload-time = "2025-07-22T20:36:00.071Z" }, + { url = "https://files.pythonhosted.org/packages/bd/d7/4752b2f6a9aaad324483f433e659b2fe36996015f348fadf172e5056b94e/uv-0.8.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f618b18b19fef09b087f2e637b2138f570a3c41beb3de4bbbb905a8b994a22a", size = 18671374, upload-time = "2025-07-22T20:36:03.672Z" }, + { url = "https://files.pythonhosted.org/packages/59/65/f979657cc773f17d0c1ec4a1d17dc1b0673ab484d00833aa5514982faf63/uv-0.8.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20f2b1eb4bf8b8197683e057ea9a8f0eb63b682ad20bb232b58529abac73a5ea", size = 18666053, upload-time = "2025-07-22T20:36:07.059Z" }, + { url = "https://files.pythonhosted.org/packages/94/8d/6ff7188911b671e3eedf87ea2ce4f1e39bbbaf27caa74eef92cd9824051d/uv-0.8.2-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:8d3ae329606ba586d317e9a06dca213619afb407bcc584cf6cff2a9b84cf25a2", size = 17462711, upload-time = "2025-07-22T20:36:10.29Z" }, + { url = "https://files.pythonhosted.org/packages/b4/07/4ce00ce186f2c02ca8708a5532102ffa9e0f87a0346521a4db83a04a56b4/uv-0.8.2-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:040ceacad98b85f9ca5ab8c8220270e6a60b2136c4889b334dbfcd13812f895f", size = 17534469, upload-time = "2025-07-22T20:36:13.439Z" }, + { url = "https://files.pythonhosted.org/packages/69/ad/bf37f8bea961278ae5719f23a0998dcae17c431a77d3fa9e0d3a9256a2b2/uv-0.8.2-py3-none-musllinux_1_1_i686.whl", hash = "sha256:9f15bcfd21ca66ec93b77e6ff612798dc75d54260e2ec52f07fe897e91f07367", size = 17787669, upload-time = "2025-07-22T20:36:17.053Z" }, + { url = "https://files.pythonhosted.org/packages/03/49/3b7e1c926bcdf1325aba9647cf1831c55ae84d7d2319a74f2d9ad88535fb/uv-0.8.2-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:9dea45737afec83739189834648b07595ce07f4c201021cc5545ee1759dfe25d", size = 18759496, upload-time = "2025-07-22T20:36:20.371Z" }, + { url = "https://files.pythonhosted.org/packages/d4/74/6b4e52593d1f469250e89ee85964011e9b84b2fc25e15e9353800f36d5ab/uv-0.8.2-py3-none-win32.whl", hash = "sha256:eb37db94c9295bfec77ff65fbc56b9962665d3d5bff0989dcb440c650351ee15", size = 17753486, upload-time = "2025-07-22T20:36:24.074Z" }, + { url = "https://files.pythonhosted.org/packages/79/c8/1d9510c5aeda8c14e6c088f1720e2dd818dc72ed37a0ee40d3d3137aabcf/uv-0.8.2-py3-none-win_amd64.whl", hash = "sha256:0fcaab1172c6fae036a9f16460a71812f7a427b3d3779f99457c2d537a3fc250", size = 19503370, upload-time = "2025-07-22T20:36:27.505Z" }, + { url = "https://files.pythonhosted.org/packages/00/38/8907e8fc94e3c040759180e81d30414734cbee6e575dae7ce9dc9cb1e0fc/uv-0.8.2-py3-none-win_arm64.whl", hash = "sha256:af35c0fe23907fc0518832243b561f623a48a058a75ab552204f87960793321b", size = 18145751, upload-time = "2025-07-22T20:36:30.826Z" }, ] [[package]]