diff --git a/sdk/ai/azure-ai-projects/.env.template b/sdk/ai/azure-ai-projects/.env.template index 76c795cfaf62..71237c4c0e44 100644 --- a/sdk/ai/azure-ai-projects/.env.template +++ b/sdk/ai/azure-ai-projects/.env.template @@ -46,6 +46,17 @@ SHAREPOINT_USER_INPUT= FABRIC_USER_INPUT= BING_CUSTOM_USER_INPUT= A2A_USER_INPUT= +EVALUATOR_NAME= +DATASET_NAME= +DATASET_VERSION= +POLL_INTERVAL_SECONDS= +EVAL_MODEL= +OPTIMIZATION_MODEL= +JOB_ID= +WORK_IQ_PROJECT_CONNECTION_ID= +WORK_IQ_USER_INPUT= +FABRIC_IQ_PROJECT_CONNECTION_ID= +FABRIC_IQ_USER_INPUT= ####################################################################### # diff --git a/sdk/ai/azure-ai-projects/.github/skills/README.md b/sdk/ai/azure-ai-projects/.github/skills/README.md index 7ea120484d10..5fa39f44900e 100644 --- a/sdk/ai/azure-ai-projects/.github/skills/README.md +++ b/sdk/ai/azure-ai-projects/.github/skills/README.md @@ -7,7 +7,7 @@ git clone https://github.com/Azure/azure-sdk-for-python.git ``` * Change to the directory `sdk\ai\azure-ai-projects`. -* Switch to the current feature branch: `git switch feature/azure-ai-projects/2.2.0`. +* Switch to the current feature branch, for example: `git switch feature/azure-ai-projects/2.3.0`. * Make sure you don't have any files edited or added in this branch (clean `git status` state). ## Emit from TypeSpec and create a PR @@ -17,16 +17,26 @@ * Open VSCode in the current folder. * Open the CoPilot chat window ("Toggle Chat"). * Make sure you are in "Agent" mode. -* Start typing `/azure-ai-projects` and press tab to auto complete it to `/azure-ai-projects-emit-from-typespec`, then press Enter. +* Start typing `/` followed by the skill name, like `/azure-ai-projects` and press tab to auto complete it to the designed skill, like `/azure-ai-projects-emit-from-typespec`, then press Enter. * Answer some questions and approve execution to go through the workflow ### Using CoPilot CLI or Agency Copilot CLI * Install [GitHub CoPilot CLI](https://docs.github.com/copilot/how-tos/copilot-cli/set-up-copilot-cli/install-copilot-cli) or [Agency CoPilot CLI](https://aka.ms/agency) (VPN required) if you don't already have it. * Run CoPilot CLI by typing `copilot` -* Start typing `/azure-ai-projects` and press tab to auto complete it to `/azure-ai-projects-emit-from-typespec`, then press Enter. +* Start typing `/` followed by the skill name, like `/azure-ai-projects` and press tab to auto complete it to the desired skill, like `/azure-ai-projects-emit-from-typespec`, then press Enter. * Answer some questions and approve execution to go through the workflow +## Skills + +### azure-ai-projects-emit-from-typespec + +This skill creates a new topic branch, emits SDK from TypeSpec, runs some post-processing and creates a PR. + +### azure-ai-projects-update-changelog + +This skill updates the file CHANGELOG.md, comparing the source in the current branch which the source of the latest public release. It does not create a new topic branch or a PR. + diff --git a/sdk/ai/azure-ai-projects/.github/skills/azure-ai-projects-emit-from-typespec/SKILL.md b/sdk/ai/azure-ai-projects/.github/skills/azure-ai-projects-emit-from-typespec/SKILL.md index 190df28bcbd0..14bd5540f020 100644 --- a/sdk/ai/azure-ai-projects/.github/skills/azure-ai-projects-emit-from-typespec/SKILL.md +++ b/sdk/ai/azure-ai-projects/.github/skills/azure-ai-projects-emit-from-typespec/SKILL.md @@ -4,7 +4,7 @@ license: MIT metadata: version: "1.0.0" distribution: local -description: "Emit the azure-ai-projects Python SDK from TypeSpec, apply post-emitter fixes, update changelog, and create a Pull Request. WHEN: \"emit SDK from TypeSpec\", \"generate azure-ai-projects SDK\", \"update azure-ai-projects from TypeSpec\", \"emit from TypeSpec\", \"regenerate azure-ai-projects\". DO NOT USE FOR: other Azure SDK packages, manual code edits without TypeSpec. INVOKES: azsdk-common-generate-sdk-locally skill, post-emitter-fixes.cmd script, git commands, gh CLI for PR creation." +description: "Emit the azure-ai-projects Python SDK from TypeSpec, apply post-emitter fixes, and create a Pull Request. WHEN: \"emit SDK from TypeSpec\", \"generate azure-ai-projects SDK\", \"update azure-ai-projects from TypeSpec\", \"emit from TypeSpec\", \"regenerate azure-ai-projects\". DO NOT USE FOR: other Azure SDK packages, manual code edits without TypeSpec. INVOKES: PostEmitter.ps1 script, git commands, gh CLI for PR creation." compatibility: requires: "azure-sdk-mcp server, local azure-sdk-for-python clone, git, gh CLI" --- @@ -16,10 +16,6 @@ applying post-emitter fixes, updating the changelog, installing package from sou **Working directory:** `sdk/ai/azure-ai-projects` -**Skills:** This workflow relies on skills defined under `.github/skills/` at the root of the repository. Use those skills for SDK generation, building, changelog updates, and other SDK lifecycle operations instead of running commands directly. In particular: - -- **`azsdk-common-generate-sdk-locally`** – For generating SDK from TypeSpec, building, running checks/tests, updating changelog, metadata, and version. - --- ## Step 1: Gather information from the user @@ -30,11 +26,11 @@ Ask the user the following questions **one at a time**, waiting for each answer Ask the user to choose **one** of the following two options for the target topic branch: -1. **Create a new topic branch (with default branch name)** – Create a new topic branch for the emitted changes. If selected, this default branch name will be used "/", where `github-userid` is the user's GitHub ID and `DD-MM-HHMM` is the current date-time using date, month, hour and minute. For example, if the GitHub ID is "dargilco" and the current date and time is May 1st, 2026 at 8:13am, the default branch name would be `dargilco/emit-from-typespec-01-05-0813`. This should be the default option, and the default branch name should be displayed. If you press enter without typing anything, this option will be selected. +1. **Create a new topic branch (with default branch name)** – Create a new topic branch for the emitted changes. If selected, this default branch name will be used "/", where `github-userid` is the user's personal GitHub ID (not the Microsoft Enterprise Managed User (EMU) account!) and `DD-MM-HHMM` is the current date-time using date, month, hour and minute. For example, if the GitHub ID is "dargilco" and the current date and time is May 1st, 2026 at 8:13am, the default branch name would be `dargilco/emit-from-typespec-01-05-0813`. This should be the default option, and the default branch name should be displayed. If you press enter without typing anything, this option will be selected. -2. **Create a new topic branch (branch name given by user)** - Ask the user for the branch name. Mention that a common format is "/". If the user enters a branch name `feature/azure-ai-projects/2.2.0` then stop and report that they cannot emit directly to the current feature branch. +2. **Create a new topic branch (branch name given by user)** - Ask the user for the branch name. Mention that a common format is "/". If the user enters a branch name `feature/azure-ai-projects/2.3.0` then stop and report that they cannot emit directly to the current feature branch. -3. **Emit to current branch** – Emit directly to the current branch without creating a new topic branch. This is not common, but may be necessary if the user is re-running this workflow because of a previous failure, where the topic branch was already created. If the current branch is named `feature/azure-ai-projects/2.2.0` then stop and report that they cannot emit directly to the current feature branch. +3. **Emit to current branch** – Emit directly to the current branch without creating a new topic branch. This is not common, but may be necessary if the user is re-running this workflow because of a previous failure, where the topic branch was already created. If the current branch is named `feature/azure-ai-projects/2.3.0` then stop and report that they cannot emit directly to the current feature branch. ### 1b. TypeSpec source @@ -42,11 +38,10 @@ Ask the user to choose **one** of the following three options for the TypeSpec s 1. **Latest commit on `feature/foundry-release`** – Automatically find the latest commit to the `feature/foundry-release` branch in [Azure/azure-rest-api-specs](https://github.com/Azure/azure-rest-api-specs) that touched files under `specification/ai-foundry/data-plane/Foundry`, and use that commit hash. This should be the default option. If you press enter without typing anything, this option will be selected. -2. **Local TypeSpec folder** – Emit from a local clone of the [azure-rest-api-specs](https://github.com/Azure/azure-rest-api-specs) repository. If selected, ask for the **full folder path** to the TypeSpec project. This is the folder ending with `\specification\ai-foundry\data-plane\Foundry`. If it does not end with that string, stop and report the error to the user. Do not continue. +2. **Local TypeSpec folder** – Emit from a local clone of the [azure-rest-api-specs](https://github.com/Azure/azure-rest-api-specs) repository. If selected, ask for the **full folder path** to the TypeSpec project. This is the folder ending with `\specification\ai-foundry\data-plane\Foundry\src\sdk-python-js-azure-ai-projects`. If it does not end with that string, stop and report the error to the user. Do not continue. 3. **TypeSpec commit hash** – Emit from a specific commit in the [azure-rest-api-specs](https://github.com/Azure/azure-rest-api-specs) repository. If selected, ask for the **full commit SHA** (40 characters). - --- ## Step 2: Record the current branch @@ -76,27 +71,22 @@ Replace `` with the name provided by the user in Step 1a. ## Step 4: Emit SDK from TypeSpec -Use the **`azsdk-common-generate-sdk-locally`** skill to generate the SDK code. The skill knows how to invoke `azsdk_package_generate_code` and related MCP tools. - -Provide the skill with the TypeSpec source selected by the user. With is either: +If you are emitting from latest commit or a given commit number, edit file `tsp-location.yaml` to update the full hash commit number, then in the folder `sdk/ai/azure-ai-projects` run the command: `tsp-client update --debug` -- **Local folder:** Pass the local spec repo path for local generation. Or, -- **Commit hash:** Update `commit:` in `tsp-location.yaml` to the full SHA first, then invoke the skill for generation. +If you are emitting from a local TypeSpec folder, do not edit the file `tsp-location.yaml`. Run the command: `tsp-client update --debug --local-spec-repo `, where `` is the full path to the local TypeSpec folder ending with `specification\ai-foundry\data-plane\Foundry\src\sdk-python-js-azure-ai-projects`. Note: - You are only allowed to use the `tsp-client update` command. Do not use any of the other `tsp-client` commands. -- If you are generating from local TypeSpec folder, do not edit the file `tsp-location.yaml`. Leave it as is. It should not be used by the emitter. -- If you are generating from local TypeSpec folder, make sure that the local folder path you provide `tsp-client update --local-spec-repo` ends with `specification\ai-foundry\data-plane\Foundry`. - **If the generation fails**, stop and report the error to the user. Do not continue. --- -## Step 5: Revert changes to file pyproject.toml +## Step 5: Revert changes to files pyproject.toml and MANIFEST.in -After the emit, there will be changes to `pyproject.toml` that are not needed. Revert any changes to `pyproject.toml` by running: +After the emit, there will be changes to `pyproject.toml` and `MANIFEST.in` that are not needed. Revert any changes to these files by running: ``` -git restore pyproject.toml +git restore pyproject.toml MANIFEST.in ``` --- @@ -117,13 +107,9 @@ git push -u origin ## Step 7: Run post-emitter fixes -After a successful emit, run the post-emitter fix script located in the `sdk/ai/azure-ai-projects` folder: +After a successful emit, run the PowerShell script named `PostEmitter.ps1` located in the `sdk/ai/azure-ai-projects` folder. -``` -post-emitter-fixes.cmd -``` - -This script applies azure-ai-projects-specific corrections to the emitted code (restores `pyproject.toml`, fixes enum names, patches Sphinx doc-string issues, and runs `black` formatting). +This script applies azure-ai-projects specific corrections to the emitted code (restores `pyproject.toml`, fixes enum names, patches Sphinx doc-string issues, and runs `black` formatting). **If the script fails**, stop and report the error to the user. Do not continue. Do not attempt to analyze the script failures and fix them with Copilot. The script should be fixed by the engineering team if it is not working. @@ -174,14 +160,21 @@ In the folder `sdk\ai\azure-ai-projects`, run `pip install -e .` to install the --- -## Step 12: Update CHANGELOG.md +## Step 12: Run `apiview-stub-generator` to update api.md and api.metadata.yml files + +In the folder `sdk\ai\azure-ai-projects`, run the following command: -Use the **`azsdk-common-generate-sdk-locally`** skill's changelog capability (`azsdk_package_update_changelog_content`) to update `CHANGELOG.md` in the `sdk/ai/azure-ai-projects` folder with a summary of changes from the TypeSpec emit. Some guidelines to follow: -* Start by examining the public SDK API surface of the latest released version of the azure-ai-projects package. The source code for this version can be found in the Main branch of the `azure-sdk-for-python` repository, in the folder `sdk\ai\azure-ai-projects`. -* Then compare it to the public SDK API surface of current version in this topic branch. -* Look at the existing change log from the latest version (if exists) and edit or add to it to capture all the changes you see. If a change log does not exist for the current version at the top of `CHANGELOG.md`, create a new one. -* If a new method was added, there is no need to add the list of all new classes that define the inputs and output of the method. It's enough to mention that the new method was added. -* Show the user the proposed changelog entry and ask for confirmation or edits before saving. +``` +azpysdk apistub . +``` + +This will update the `api.md` and `api.metadata.yml` files under in local folder. + +If it fails, stop and do not continue. If succeeded, do the following cleanup and continue to the next step: + +``` +rmdir /s /q build +``` --- diff --git a/sdk/ai/azure-ai-projects/.github/skills/azure-ai-projects-update-changelog/SKILL.md b/sdk/ai/azure-ai-projects/.github/skills/azure-ai-projects-update-changelog/SKILL.md new file mode 100644 index 000000000000..eeb810776294 --- /dev/null +++ b/sdk/ai/azure-ai-projects/.github/skills/azure-ai-projects-update-changelog/SKILL.md @@ -0,0 +1,342 @@ +--- +name: azure-ai-projects-update-changelog +license: MIT +metadata: + version: "1.0.0" + distribution: local +description: "Update CHANGELOG.md by comparing public APIs between the current branch and the latest released version on PyPI. WHEN: \"update changelog\", \"generate changelog\", \"add changelog entry\", \"what changed in this version\". DO NOT USE FOR: other Azure SDK packages. INVOKES: PyPI API, GitHub API (for tags), file operations." +compatibility: + requires: "local azure-sdk-for-python clone, git, internet access" +--- + +# Update azure-ai-projects Changelog + +This skill guides Copilot through updating the CHANGELOG.md file for the azure-ai-projects package by comparing public APIs between the current branch and the latest released version. + +**Working directory:** `sdk/ai/azure-ai-projects` + +--- + +## Overview + +The skill performs these steps: +1. Read the current version from `azure/ai/projects/_version.py` +2. Fetch the latest released version from PyPI +3. Compare public classes, methods, and properties between current branch and released version +4. Update CHANGELOG.md with a new section or update the existing "(Unreleased)" section + +--- + +## Step 1: Read the current version + +Read the current version from `azure/ai/projects/_version.py`. The file contains a line like: +```python +VERSION = "X.Y.Z" +``` + +Extract this version number and save it as `CURRENT_VERSION`. + +--- + +## Step 2: Fetch the latest released version from PyPI + +Use the PyPI JSON API to get the latest released version: + +``` +https://pypi.org/pypi/azure-ai-projects/json +``` + +From the JSON response: +- Extract `info.version` as `LATEST_PYPI_VERSION` +- This is the version we will compare against + +--- + +## Step 3: Determine if CHANGELOG needs updating + +Check if CHANGELOG.md already has a section for the current version: +- If there's a section `## {CURRENT_VERSION} (Unreleased)` — we will update it +- If there's a section `## {CURRENT_VERSION} (YYYY-MM-DD)` with an actual date — the version is already released, report this to the user and stop +- If there's no section for `CURRENT_VERSION` — we will create a new one + +--- + +## Step 4: Construct the GitHub tag for the released version + +The tag name for a released version follows this pattern: +``` +azure-ai-projects_{VERSION} +``` + +For example, for version `2.2.0`, the tag is `azure-ai-projects_2.2.0`. + +The source code for that release can be found at: +``` +https://github.com/Azure/azure-sdk-for-python/tree/azure-ai-projects_{VERSION}/sdk/ai/azure-ai-projects +``` + +--- + +## Step 5: Compare public APIs + +Compare the public APIs between the current branch and the latest released version. Focus on these locations: + +### 5a. Public classes and enums in `azure/ai/projects/models/__init__.py` + +Compare the `__all__` list and imports in both versions to identify: +- **New classes/enums**: Present in current branch but not in released version +- **Removed classes/enums**: Present in released version but not in current branch +- **Renamed classes/enums**: Check if a removed class has a similar new class (likely a rename) + +### 5b. Public operations in `azure/ai/projects/operations/__init__.py` + +Compare the `__all__` list to identify new or removed operation classes. + +### 5c. Public methods on sub-clients + +For each operations class (like `AgentsOperations`, `BetaOperations`, etc.), compare the public methods: +- Look at files under `azure/ai/projects/operations/` and `azure/ai/projects/aio/operations/` +- Also check `_patch.py` files which may define additional public methods +- Public methods are those that don't start with underscore `_` + +### 5d. Properties on model classes + +For significant model classes, compare public properties (attributes) between versions: +- Properties are defined in `azure/ai/projects/models/_models.py` +- Look for new, removed, or renamed properties +- Pay attention to required vs optional changes + +### 5e. Beta sub-clients on `BetaOperations` + +The `BetaOperations` class exposes beta/preview functionality. Check for: +- New sub-client properties (like `.beta.datasets`, `.beta.models`, `.beta.routines`, etc.) +- Removed sub-client properties +- Check both `azure/ai/projects/operations/_patch.py` and the released version + +### 5f. Sample files in `samples/` folder + +Compare sample files between the current branch and the released version: + +1. **List all `.py` files** recursively under `samples/` in both versions +2. **Identify new samples**: Files present in current branch but not in released version +3. **Identify removed samples**: Files present in released version but not in current branch +4. **Ignore async variants**: If a sample has both sync and async versions (e.g., `sample_foo.py` and `sample_foo_async.py`), only report the sync version +5. **Check existing changelog entries**: If a sample is already mentioned in the current changelog section, leave it as is +6. **Remove stale entries**: If a sample mentioned in the changelog has been removed from the codebase, remove it from the changelog + +For each new sample, provide a one-line description of what it demonstrates. Read the sample file to understand its purpose — typically the docstring at the top or the `if __name__ == "__main__"` block explains what it does. + +--- + +## Step 6: Categorize the changes + +Organize detected changes into these categories: + +### Features Added +- New sub-clients (e.g., "New `.beta.routines` sub-client with routine operations: `create_or_update`, `get`, `enable`, ...") +- New methods on existing sub-clients (e.g., "New methods on `.beta.agents` for optimization jobs: `create_optimization_job`, `get_optimization_job`, ...") +- New model classes that represent significant features (e.g., "Support integration of external Agents. See new `ExternalAgentDefinition` class.") +- New properties on existing classes (e.g., "New optional `force` parameter on `agents.delete` method.") +- New tools (e.g., "New Agent tool in preview `FabricIQPreviewTool`.") + +### Breaking Changes +List breaking changes in beta methods and classes separately: +- Renamed methods (e.g., "Method `.beta.agents.get_session_files` renamed to `.beta.agents.list_session_files`.") +- Renamed arguments (e.g., "Argument `body` in method `.beta.skills.create_from_files()` renamed to `content`.") +- Signature changes (e.g., "Method `.beta.skills.create` signature changed — now takes `name` and keyword `inline_content: SkillInlineContent`; returns `SkillVersion`.") +- Renamed classes (e.g., "Renamed class `AgentEndpoint` to `AgentEndpointConfig`.") +- Property changes (e.g., "Required property `isolation_key_source` removed from class `EntraAuthorizationScheme`.") +- Renamed properties (e.g., "Property `skill_id` renamed to `id` on class `SkillDetails`.") + +**Format for beta changes:** +```markdown +Breaking changes in beta methods: +* ... + +Breaking changes in beta classes: +* ... +``` + +### Bugs Fixed +This section typically contains bug fixes. Leave empty unless you have specific bug fix information to add. + +### Sample updates +List new sample files that were added, with a one-line description of what they demonstrate: +- Compare sample files in the `samples/` folder between current branch and released version +- Only report the sync version — do not list async samples separately (files ending with `_async.py`) +- If a sample is already mentioned in the existing changelog section, preserve that entry +- If a sample mentioned in the changelog has been removed from the codebase, remove it from the changelog +- Group related samples together (e.g., all agent samples, all evaluation samples) +- Use format: `Added \`sample_name.py\` demonstrating [brief description].` + +--- + +## Step 7: Format the changelog entry + +Use this format for the changelog entry: + +```markdown +## {CURRENT_VERSION} (Unreleased) + +### Features Added + +* [List each feature on its own bullet point] + +### Breaking Changes + +Breaking changes in beta methods: +* [List method changes] + +Breaking changes in beta classes: +* [List class changes] + +### Bugs Fixed + +* [List bug fixes, if any] + +### Sample updates + +* [List sample updates, if any] +``` + +**Guidelines for writing entries:** +- For new methods: mention the sub-client and method name, briefly describe what it does. Only report the sync version — do not list both sync and async versions separately. +- For new sub-clients: list all the methods it provides (sync versions only) +- For new tools: just mention the class name +- For property changes: mention the class name and the affected property +- For renames: show "X renamed to Y" format +- Use backticks for code references: `.beta.agents`, `create_version()`, `AgentDetails` + +--- + +## Step 8: Update CHANGELOG.md + +Insert or update the changelog entry in `CHANGELOG.md`: + +1. If updating an existing "(Unreleased)" section: + - Replace the existing section content with the new content + - Preserve any manually-added entries that aren't API-related (like "Sample updates" written by developers) + +2. If creating a new section: + - Insert the new section immediately after the `# Release History` header + - Keep all previous version sections intact + +--- + +## Step 9: Report to user + +After updating the changelog, report: +1. The current version and latest PyPI version compared +2. Summary of changes detected: + - Number of new classes/enums + - Number of new methods + - Number of breaking changes + - Number of removed items +3. Remind the user to: + - Review the generated changelog for accuracy + - Add any bug fixes that were made + - Review sample descriptions for accuracy + - Verify method descriptions are accurate + +--- + +## Tips for API Comparison + +### Using git to compare files + +You can compare files between the current branch and a tag: +```bash +git diff azure-ai-projects_{VERSION} -- azure/ai/projects/models/__init__.py +``` + +### Using GitHub raw URLs + +To fetch files from the released version: +``` +https://raw.githubusercontent.com/Azure/azure-sdk-for-python/azure-ai-projects_{VERSION}/sdk/ai/azure-ai-projects/azure/ai/projects/models/__init__.py +``` + +### Identifying renames vs additions/removals + +If a class was removed and a similar class was added, it's likely a rename. Look for: +- Similar names (e.g., `SkillObject` → `SkillDetails`) +- Similar structure/properties +- Check if there's a corresponding note in the TypeSpec changes + +--- + +## Example Output + +Here's an example of a well-formatted changelog entry: + +```markdown +## 2.3.0 (Unreleased) + +### Features Added + +* Support integration of external Agents (in preview). See new `ExternalAgentDefinition` class. +* New Agent tool in preview `FabricIQPreviewTool`. +* New Agent tool in preview `ToolboxSearchPreviewTool`. +* New methods on `.beta.agents` for + * Code-based hosted agents: `create_version_from_code`, `download_code`. + * Optimization jobs: `create_optimization_job`, `get_optimization_job`, `list_optimization_jobs`, `cancel_optimization_job`, `list_optimization_candidates`. + * Optimization candidate management: `list_optimization_candidates`, `get_optimization_candidate`, `get_optimization_candidate_config`, `get_optimization_candidate_results`, `get_candidate_file`, `promote_candidate`. + * `stop_session` to stop a running agent session. +* New `.beta.datasets` sub-client with data generation job operations: `create_generation_job`, `get_generation_job`, `list_generation_jobs`, `cancel_generation_job`, `delete_generation_job`. +* New `.beta.models` sub-client to handle AI model weights: `create`, `list_versions`, `list`, `get`, `delete`, `update`, `pending_create_version`, `pending_upload`, `get_credentials`. +* New `.beta.routines` sub-client with routine operations: `create_or_update`, `get`, `enable`, `disable`, `list`, `delete`, `list_runs`, `dispatch`. +* New methods on `.beta.evaluators` for evaluator generation jobs: `create_generation_job`, `get_generation_job`, `list_generation_jobs`, `cancel_generation_job`, `delete_generation_job`. +* New methods on `.beta.memory_stores` to handle individual memory items: `create_memory`, `update_memory`, `list_memories`, `get_memory`, `delete_memory`. +* New methods on `.beta.skills` for versioned skill management: `create`, `list_versions`, `get_version`, `download_version`, `delete_version`. +* New optional string properties `description` and `name` added to Agent tools classes which did not have them before. +* New optional `tool_configs` added to Agent tool classes. +* New read-only property `content_hash` on `CodeConfiguration`, returning the SHA-256 hex digest of the uploaded code zip. +* New optional `force` parameter on `agents.delete` and `agents.delete_version` methods. +* New optional `blueprint_reference` parameters on `agents.create_version` method. + + +### Breaking Changes + +Breaking changes in beta methods: +* Argument `isolation_key` in methods `.beta.agents.create_session()` and `.beta.agents.delete_session()` renamed to `user_isolation_key`. +* Argument `body` in methods `.beta.evaluation_taxonomies.create()` and `.beta.evaluation_taxonomies.update()` renamed to `taxonomy`. +* Argument `body` in method `.beta.skills.create_from_files()` renamed to `content`. +* Method `.beta.agents.get_session_files` renamed to `.beta.agents.list_session_files`. +* Method `.beta.skills.create` signature changed — now takes `name` and keyword `inline_content: SkillInlineContent`; returns `SkillVersion`. +* Method `.beta.skills.create_from_package` renamed to `.beta.skills.create_from_files`. +* Method `.beta.skills.create_from_files` signature changed — now takes `name` and `content: CreateSkillVersionFromFilesBody`; returns `SkillVersion`. +* Method `.beta.skills.update` signature changed — now only accepts keyword `default_version`; returns `SkillDetails`. + +Breaking changes in beta classes: +* Required property `isolation_key_source` removed from class `EntraAuthorizationScheme`. +* Renamed class `AgentEndpoint` to `AgentEndpointConfig`. +* Renamed class `DeleteSkillResponse` to `DeleteSkillResult`. +* Renamed class `SessionDirectoryListResponse` to `SessionDirectoryListResult`. +* Renamed class `SessionFileWriteResponse` to `SessionFileWriteResult`. +* Renamed class `SkillObject` to `SkillDetails`. Property `skill_id` renamed to `id`. Properties `has_blob` and `metadata` were removed. +* Renamed class `Target` to `EvaluationTarget`. +* Renamed class `TargetConfig` to `RedTeamTargetConfig`. + +### Bugs Fixed + +* Fixed telemetry instrumentor to correctly call is_recording() as a method on spans, ensuring non-recording spans are properly skipped (e.g., when sampling is configured) ([GitHub issue 46544](https://github.com/Azure/azure-sdk-for-python/issues/46544)). + +### Sample updates + +* Added new Agent tool samples `sample_agent_work_iq.py` and `sample_agent_work_iq_async.py` demonstrating use of `WorkIQPreviewTool`. +* Added new Agent tool samples `sample_agent_fabric_iq.py` and `sample_agent_fabric_iq_async.py` demonstrating use of `FabricIQPreviewTool`. +* Hosted Agents: + * Added Hosted Agent creation samples `sample_create_hosted_agent.py` and `sample_create_hosted_agent_async.py`, demonstrating hosted agent version creation and retrieval with `AIProjectClient`. + * Added Hosted Agent code-upload samples `sample_create_hosted_agent_from_code.py` and `sample_create_hosted_agent_from_code_async.py`, demonstrating uploading a code package (zip) as a new hosted agent version. + * The Hosted Agent creation sample also demonstrates assigning the hosted agent managed identity the Azure AI User RBAC role on the backing Azure AI account. + * Updated the other Hosted Agent samples to reuse an existing Hosted Agent as a prerequisite, instead of creating a new hosted agent version in each sample. +* Added Toolbox tool-search sample `sample_toolboxes_with_search_preview.py` and `sample_toolboxes_with_search_preview_async.py`, demonstrating creating a Toolbox version with `ToolboxSearchPreviewTool` and invoking `MCPTool`. +* Added `.beta.models` samples under `samples/models/`: + * `sample_models_basic.py` — synchronous end-to-end registration via the `create` helper (uses `azcopy`), followed by `get`, `list_versions`, `list`, `get_credentials`, `update`, and `delete`. + * `sample_models_create_and_poll.py` — alternative synchronous registration that hand-rolls the spec's three-step flow (`pending_upload` → upload via `azure-storage-blob` → `pending_create_version` + poll), without taking a dependency on `azcopy`. + * `sample_models_basic_async.py` — asynchronous version of the same three-step flow using `azure.ai.projects.aio.AIProjectClient` and `azure.storage.blob.aio.ContainerClient`. +* Added new evaluation sample `sample_model_evaluation_instant_model.py` demonstrating model evaluation with an instant model. +* Refreshed evaluation samples under `samples/evaluations/` and `samples/evaluations/agentic_evaluators/` (including `sample_agent_evaluation`, `sample_agent_response_evaluation`, `sample_eval_catalog_prompt_based_evaluators`, `sample_evaluations_ai_assisted`, `sample_evaluations_builtin_with_csv`, `sample_evaluations_builtin_with_dataset_id`, `sample_evaluations_builtin_with_inline_data`, `sample_evaluations_builtin_with_inline_data_oai`, `sample_scheduled_evaluations`, `sample_coherence`, `sample_fluency`, `sample_intent_resolution`, `sample_relevance`, `sample_response_completeness`, `sample_tool_call_accuracy`, `sample_tool_call_success`, `sample_tool_input_accuracy`, `sample_tool_output_utilization`, `sample_tool_selection`, and `sample_generic_agentic_evaluator`). +* New sample `sample_dataset_generation_job_simpleqna_with_prompt_source.py` showing an end-to-end flow that generates a QnA dataset via `.beta.datasets.create_generation_job` and runs an OpenAI evaluation. + +``` diff --git a/sdk/ai/azure-ai-projects/CHANGELOG.md b/sdk/ai/azure-ai-projects/CHANGELOG.md index 63ea84bd7254..d1d447932066 100644 --- a/sdk/ai/azure-ai-projects/CHANGELOG.md +++ b/sdk/ai/azure-ai-projects/CHANGELOG.md @@ -1,5 +1,46 @@ # Release History +## 2.3.0 (Unreleased) + +### Features Added + +* Two new methods `enable` and `disable` on the `.agents` subclient. +* New Agent tool type `REMINDER_PREVIEW`. +* Hosted agents are now stable. There is no need to set `allow_preview=True` on the `AIProjectClient` constructor to create a Hosted agent. +* Toolboxes operations are now stable. The have moved from `.beta.toolboxes` subclient to the `.toolboxes` subclient. +* Session and Session files operations are now stable. They have moved from the `.beta.agents` subclient to the `.agents` subclient. +* Agent code operations are now stable. This includes `create_version_from_code` and `download_code`. They have moved from the `.beta.agents` subclient to the `.agents` subclient. + +### Breaking Changes + +* Toolbox operation `create_version` now defines `tools` of type `List[ToolboxTool]` instead of `List[Tool]`. +* Input argument `path` renamed to `remote_path` in methods `.agents.delete_session_file`, `.agents.download_session_file`, `.agents.list_session_files` and `.agents.upload_session_file`. +* Agent Optimization methods `.beta.agents.*optimization*` were re-written. Updated from v1 to v2 preview, focusing on cleanup to better align with Foundry job guidelines and platform standards. The v1 surface accumulated unused candidate sub-resources, internal-detail properties, and custom operation patterns inconsistent with the Foundry platform. The v2 API removes redundant models and operations, adopts shared Foundry job patterns (`JobLike<>`, standard job verbs), and introduces typed discriminated unions for dataset inputs and evaluator references. +* Method `.beta.agents.list_optimization_candidates` now returns `ItemPaged[OptimizationCandidate]` instead of `AgentsPagedResultOptimizationCandidate`. The `after` parameter has been removed (use continuation-token-based paging instead). +* Property `default_ttl_seconds` on class `MemoryStoreDefaultOptions` has changed from type `int` to type `datetime.timedelta`. +* Method ".beta.agents.patch_agent_details` moved out of the beta sub-client and renamed to `.agents.update_details`. + + +### Sample updates + +* Added `sample_routines_crud.py` to demonstrate CRUD operations. +* Added `sample_routines_with_timer_trigger.py` to demonstrate triggering a routine with a timer. +* Added `sample_routines_with_schedule_trigger.py` to demonstrate triggering a routine on a recurring cron schedule via `ScheduleRoutineTrigger`. +* Added `sample_routines_with_dispatch.py` to demonstrate manually firing a routine on demand via `routines.dispatch(...)` using a `CustomRoutineTrigger`. +* Added new Hosted Agent sample `sample_toolbox_with_skill.py` under `samples/hosted_agents/`, demonstrating a code-based Hosted Agent that uses Toolbox MCP skills. +* Updated `sample_dataset_generation_job_traces_for_evaluation.py` and `sample_dataset_generation_job_traces_for_finetuning.py` to create a temporary agent, seed conversations, retry the data generation job over the trace window, and clean up all created resources. +* Updated `sample_memory_crud.py` and `sample_memory_crud_async.py` to demonstrate memory item CRUD (`create_memory`, `get_memory`, `update_memory`, `list_memories`, `delete_memory`) in addition to memory store CRUD. +* Updated the rubric evaluator generation samples (`sample_rubric_evaluator_generation_basic.py`, `sample_rubric_evaluator_generation_iterate.py`, `sample_rubric_evaluator_generation_lifecycle.py`, `sample_rubric_evaluator_generation_all_sources.py`) to use the typed `EvaluatorGenerationJob` / `EvaluatorGenerationInputs` / `*EvaluatorGenerationJobSource` models. The job inputs are now nested under `inputs` per the service contract, and the traces source uses `datetime` values for `start_time` / `end_time`. +* Updated Hosted Agent code-upload samples (`sample_create_hosted_agent_from_code.py`, `sample_create_hosted_agent_from_code_async.py`) to target runtime `python_3_14`, since `python_3_12` is no longer supported. +* Updated Hosted Agent echo-agent assets (`samples/hosted_agents/assets/echo-agent/main.py`, `echo-agent-prebuilt.zip`) to use `@app.response_handler`, resolving a response-handling issue. The remote-build code-upload sample now builds the echo-agent zip from `samples/hosted_agents/assets/echo-agent/` at runtime instead of relying on a checked-in `echo-agent.zip`, so users can update the agent code and rerun the sample with their changes. +* Updated Skills upload/download samples (`sample_skills_upload_and_download.py`, `sample_skills_upload_and_download_async.py`) to build the `team-status-update.zip` package from `samples/skills/assets/team-status-update/` at runtime instead of relying on a checked-in zip archive, so users can update the skill content and rerun the sample with their changes. +* Updated scheduled evaluation samples (`sample_scheduled_evaluations.py`, `sample_scheduled_agent_traces_evaluation_smart_filter.py`) to import `ResourceManagementClient` from `azure.mgmt.resource.resources`. +* Relocated and renamed `sample_skill_in_toolbox.py` (from `samples/hosted_agents/`) to `samples/agents/tools/sample_agent_toolbox_skill.py`. +* Relocated Skills samples from `samples/hosted_agents/` to `samples/skills/`: + * `sample_skills_crud.py`. + * `sample_skills_upload_and_download.py`. +* Relocated Toolbox sample from `samples/hosted_agents/` to `samples/toolboxes/sample_toolboxes_crud.py`. + ## 2.2.0 (2026-05-29) ### Features Added diff --git a/sdk/ai/azure-ai-projects/MANIFEST.in b/sdk/ai/azure-ai-projects/MANIFEST.in index fba50036b227..340d96122c79 100644 --- a/sdk/ai/azure-ai-projects/MANIFEST.in +++ b/sdk/ai/azure-ai-projects/MANIFEST.in @@ -1,7 +1,7 @@ include *.md include LICENSE include azure/ai/projects/py.typed -recursive-include tests *.py -recursive-include samples *.py *.md +recursive-include tests * +recursive-include samples * include azure/__init__.py include azure/ai/__init__.py diff --git a/sdk/ai/azure-ai-projects/PostEmitter.ps1 b/sdk/ai/azure-ai-projects/PostEmitter.ps1 new file mode 100644 index 000000000000..c5ae7d169221 --- /dev/null +++ b/sdk/ai/azure-ai-projects/PostEmitter.ps1 @@ -0,0 +1,166 @@ +# +# To emit from TypeSpec, run this in the current folder: +# +# tsp-client update --debug ==> to use the commit mentioned in the local tsp-location.yaml to generate +# tsp-client update --debug --save-inputs" ==> To save the local folder TempTypeSpecFiles +# tsp-client update --debug --local-spec-repo " ==> to use your local TypeSpec folder. Path is like: +# D:\src\azure-rest-api-specs\specification\ai-foundry\data-plane\Foundry\src\sdk-python-js-azure-ai-projects +# +# Then run this script to "fix" the emitted code: +# powershell -ExecutionPolicy Bypass -File PostEmitter.ps1 +# + +# Revert emitted pyprojects.toml, since it overrides the following changes: +# - We added "Programming Language :: Python :: 3.14". The emitter removes it. +# - The emitter uses lower case "i" in "Ai". I want to keep it upper case in the description field: "Microsoft Corporation Azure AI Projects Client Library for Python". +# - We want a vanity link for the "repository" value, deep linking to the SDK folder (not root of repo): https://aka.ms/azsdk/azure-ai-projects-v2/python/code +# See GitHub issue: https://github.com/microsoft/typespec/issues/10311 +git restore pyproject.toml + +# Revert emitted MANIFEST.in, since it overrides changes I need to get the dist package (*.tar.gz) with required files. +# I would like to keep these two lines, since I have test and sample data files I need: +# recursive-include tests * +# recursive-include samples * +# But the emitter keeps changing it back to only include *.py and *.md files: +# recursive-include tests *.py +# recursive-include samples *.py *.md +git restore MANIFEST.in + +# Force streaming in get_session_log_stream for both sync and async operations. +$files = 'azure\ai\projects\operations\_operations.py', 'azure\ai\projects\aio\operations\_operations.py' +foreach ($f in $files) { + $lines = Get-Content $f + $inFunc = $false + for ($i = 0; $i -lt $lines.Length; $i++) { + if ($lines[$i] -match '^\s*(async\s+)?def\s+get_session_log_stream\(') { + $inFunc = $true + continue + } + if ($inFunc -and $lines[$i] -match '^\s*(async\s+)?def\s+\w+\(') { + $inFunc = $false + } + if ($inFunc -and $lines[$i] -match 'kwargs\.pop\(.+stream.+False\)') { + $indent = ([regex]::Match($lines[$i], '^\s*')).Value + $lines[$i] = $indent + '_stream = True' + } + } + Set-Content $f $lines +} + +# Fix Sphinx docutils warnings in class SessionLogEvent: the generated docstring wraps two long +# ``data:`` JSON lines mid-string inside a ``.. code-block::`` section. The wrapped continuation +# lines have wrong indentation (4 spaces instead of 7), causing "unexpected unindent" warnings. +# Join each broken pair back into one line. +$f = 'azure\ai\projects\models\_models.py' +$c = Get-Content $f -Raw +$c = $c -replace '(Starting server)\r?\n[ \t]+(on port 18080)', '$1 $2' +$c = $c -replace '(Successfully)\r?\n[ \t]+(connected to container\"})\.?', '$1 $2' +Set-Content $f $c -NoNewline +$lines = Get-Content $f +$out = @() +foreach ($line in $lines) { + if ($line -match '^\s*on port 18080' -and $line -notmatch 'data:') { continue } + if ($line -match '^\s*connected to container' -and $line -notmatch 'data:') { continue } + if ($line -match '^\s*data: .*2026-03-10T09:33:17.121Z') { + $out += (' ' + $line.TrimStart()) + continue + } + if ($line -match '^\s*data: .*2026-03-10T09:34:52.714Z') { + $out += (' ' + $line.TrimStart()) + continue + } + $out += $line +} +Set-Content $f $out + +# Fix Sphinx docutils warnings in get_session_log_stream docstrings (sync + async). +# The emitter wraps bullet/code-block lines with insufficient indentation. +$files = 'azure\ai\projects\operations\_operations.py', 'azure\ai\projects\aio\operations\_operations.py' +foreach ($f in $files) { + $c = Get-Content $f -Raw + $c = $c -replace 'schema\r?\n\s+is not contractual and may include additional keys or change format\r?\n\s+over time [^\r\n]*clients should treat it as an opaque string\)', 'schema is not contractual and may include additional keys or change format over time; clients should treat it as an opaque string)' + $c = $c -replace '(message\":\"Starting)\r?\n\s+(FoundryCBAgent server on port 8088\"})', '$1 $2' + $c = $c -replace '(message\":\"INFO: Application)\r?\n\s+(startup complete\.\"})', '$1 $2' + $c = $c -replace '(message\":\"Successfully)\r?\n\s+(connected to container\"})', '$1 $2' + $c = $c -replace '(message\":\"No logs since)\r?\n\s+(last 60 seconds\"})', '$1 $2' + Set-Content $f $c -NoNewline +} + +# A block of code in the implementation of "list_memories", in both sync +# and async _operations.py files, needs to be moved up. It's emitted in the wrong place, +# in the inline function named "prepare_request". Instead it should be moved up into the +# main body of the "list_memories" method, right after the line `error_map.update(kwargs.pop("error_map", {}) or {})`. +# If you don't do this, the PR pipeline will show failures in Pyright (`error: "body" is unbound (reportUnboundVariable)`) +# and some tests will fail. This is the block of code that needs to move up: +# if body is _Unset: +# if scope is _Unset: +# raise TypeError("missing required argument: scope") +# body = {"scope": scope} +# body = {k: v for k, v in body.items() if v is not None} +# The block inside prepare_request has 12-space indentation; after moving to the main function body it needs 8-space indentation. +# Strategy: Find the last list_memories method, then do a targeted string replacement that moves the block right after error_map.update. +$oldPattern = @" + error_map.update(kwargs.pop("error_map", {}) or {}) + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + def prepare_request(_continuation_token=None): + if body is _Unset: + if scope is _Unset: + raise TypeError("missing required argument: scope") + body = {"scope": scope} + body = {k: v for k, v in body.items() if v is not None} + + _request = build_beta_memory_stores_list_memories_request( +"@ +$newPattern = @" + error_map.update(kwargs.pop("error_map", {}) or {}) + if body is _Unset: + if scope is _Unset: + raise TypeError("missing required argument: scope") + body = {"scope": scope} + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + def prepare_request(_continuation_token=None): + _request = build_beta_memory_stores_list_memories_request( +"@ +$files = 'azure\ai\projects\operations\_operations.py', 'azure\ai\projects\aio\operations\_operations.py' +foreach ($f in $files) { + $c = Get-Content $f -Raw + # Find all occurrences of "def list_memories(" and get the index of the last one + $methodMatches = [regex]::Matches($c, 'def list_memories\(') + if ($methodMatches.Count -eq 0) { continue } + $lastMethodStart = $methodMatches[$methodMatches.Count - 1].Index + + # Find the pattern to replace - first occurrence after the last list_memories method + $patternEscaped = [regex]::Escape($oldPattern) + $patternMatches = [regex]::Matches($c, $patternEscaped) + $matchToReplace = $null + foreach ($m in $patternMatches) { + if ($m.Index -gt $lastMethodStart) { + $matchToReplace = $m + break + } + } + if ($matchToReplace -eq $null) { continue } + + # Replace only that specific occurrence + $c = $c.Substring(0, $matchToReplace.Index) + $newPattern + $c.Substring($matchToReplace.Index + $matchToReplace.Length) + + Set-Content $f $c -NoNewline +} + + +# Finishing by running 'black' tool to format code. +pip install black +black --config ../../../eng/black-pyproject.toml . diff --git a/sdk/ai/azure-ai-projects/README.md b/sdk/ai/azure-ai-projects/README.md index 46e2133eea41..c09665e8b58b 100644 --- a/sdk/ai/azure-ai-projects/README.md +++ b/sdk/ai/azure-ai-projects/README.md @@ -169,6 +169,7 @@ The table below lists the operation groups supported by the client library, with | Agents (create, run, stream) | [Agents overview](https://learn.microsoft.com/azure/foundry/agents/overview) | `samples/agents/` | | Hosted agents (preview) | [Hosted agents concepts](https://learn.microsoft.com/azure/foundry/agents/concepts/hosted-agents), [Deploy your first hosted agent](https://learn.microsoft.com/azure/foundry/agents/quickstarts/quickstart-hosted-agent) | `samples/hosted_agents/` | | Agents tools | [Tool catalog](https://learn.microsoft.com/azure/foundry/agents/concepts/tool-catalog) | `samples/agents/tools/` | +| Agents optimization | | `samples/agents/optimization/` | | Connections | [Add a new connection to your project](https://learn.microsoft.com/azure/foundry/how-to/connections-add?tabs=foundry-portal)| `samples/connections/` | | Datasets | | `samples/datasets/` | | Deployments | [Deployment types](https://learn.microsoft.com/azure/foundry/foundry-models/concepts/deployment-types) | `samples/deployments/` | diff --git a/sdk/ai/azure-ai-projects/api.md b/sdk/ai/azure-ai-projects/api.md index 306242f1f143..f258e22fc862 100644 --- a/sdk/ai/azure-ai-projects/api.md +++ b/sdk/ai/azure-ai-projects/api.md @@ -90,53 +90,51 @@ namespace azure.ai.projects.aio.operations ) -> None: ... @overload - async def create_version( + async def create_session( self, agent_name: str, *, - blueprint_reference: Optional[AgentBlueprintReference] = ..., + agent_session_id: Optional[str] = ..., content_type: str = "application/json", - definition: AgentDefinition, - description: Optional[str] = ..., - metadata: Optional[dict[str, str]] = ..., + version_indicator: VersionIndicator, **kwargs: Any - ) -> AgentVersionDetails: ... + ) -> AgentSessionResource: ... @overload - async def create_version( + async def create_session( self, agent_name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> AgentVersionDetails: ... + ) -> AgentSessionResource: ... @overload - async def create_version( + async def create_session( self, agent_name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> AgentVersionDetails: ... + ) -> AgentSessionResource: ... @overload - async def create_version_from_manifest( + async def create_version( self, agent_name: str, *, + blueprint_reference: Optional[AgentBlueprintReference] = ..., content_type: str = "application/json", + definition: AgentDefinition, description: Optional[str] = ..., - manifest_id: str, metadata: Optional[dict[str, str]] = ..., - parameter_values: dict[str, Any], **kwargs: Any ) -> AgentVersionDetails: ... @overload - async def create_version_from_manifest( + async def create_version( self, agent_name: str, body: JSON, @@ -146,7 +144,7 @@ namespace azure.ai.projects.aio.operations ) -> AgentVersionDetails: ... @overload - async def create_version_from_manifest( + async def create_version( self, agent_name: str, body: IO[bytes], @@ -155,178 +153,73 @@ namespace azure.ai.projects.aio.operations **kwargs: Any ) -> AgentVersionDetails: ... - @distributed_trace_async - async def delete( - self, - agent_name: str, - *, - force: Optional[bool] = ..., - **kwargs: Any - ) -> DeleteAgentResponse: ... - - @distributed_trace_async - async def delete_version( + @overload + async def create_version_from_code( self, agent_name: str, - agent_version: str, + content: CreateAgentVersionFromCodeContent, *, - force: Optional[bool] = ..., - **kwargs: Any - ) -> DeleteAgentVersionResponse: ... - - @distributed_trace_async - async def get( - self, - agent_name: str, - **kwargs: Any - ) -> AgentDetails: ... - - @distributed_trace_async - async def get_version( - self, - agent_name: str, - agent_version: str, + code_zip_sha256: str, **kwargs: Any ) -> AgentVersionDetails: ... - @distributed_trace - def list( - self, - *, - before: Optional[str] = ..., - kind: Optional[Union[str, AgentKind]] = ..., - limit: Optional[int] = ..., - order: Optional[Union[str, PageOrder]] = ..., - **kwargs: Any - ) -> AsyncItemPaged[AgentDetails]: ... - - @distributed_trace - def list_versions( - self, - agent_name: str, - *, - before: Optional[str] = ..., - limit: Optional[int] = ..., - order: Optional[Union[str, PageOrder]] = ..., - **kwargs: Any - ) -> AsyncItemPaged[AgentVersionDetails]: ... - - - class azure.ai.projects.aio.operations.BetaAgentsOperations(GeneratedBetaAgentsOperations): - - def __init__( - self, - *args, - **kwargs - ) -> None: ... - - @distributed_trace_async - async def cancel_optimization_job( - self, - job_id: str, - **kwargs: Any - ) -> OptimizationJob: ... - @overload - async def create_optimization_job( - self, - inputs: OptimizationJobInputs, - *, - content_type: str = "application/json", - operation_id: Optional[str] = ..., - **kwargs: Any - ) -> OptimizationJob: ... - - @overload - async def create_optimization_job( - self, - inputs: JSON, - *, - content_type: str = "application/json", - operation_id: Optional[str] = ..., - **kwargs: Any - ) -> OptimizationJob: ... - - @overload - async def create_optimization_job( + async def create_version_from_code( self, - inputs: IO[bytes], + agent_name: str, + content: JSON, *, - content_type: str = "application/json", - operation_id: Optional[str] = ..., + code_zip_sha256: str, **kwargs: Any - ) -> OptimizationJob: ... + ) -> AgentVersionDetails: ... @overload - async def create_session( + async def create_version_from_manifest( self, agent_name: str, *, - agent_session_id: Optional[str] = ..., content_type: str = "application/json", - user_isolation_key: Optional[str] = ..., - version_indicator: VersionIndicator, + description: Optional[str] = ..., + manifest_id: str, + metadata: Optional[dict[str, str]] = ..., + parameter_values: dict[str, Any], **kwargs: Any - ) -> AgentSessionResource: ... + ) -> AgentVersionDetails: ... @overload - async def create_session( + async def create_version_from_manifest( self, agent_name: str, body: JSON, *, content_type: str = "application/json", - user_isolation_key: Optional[str] = ..., **kwargs: Any - ) -> AgentSessionResource: ... + ) -> AgentVersionDetails: ... @overload - async def create_session( + async def create_version_from_manifest( self, agent_name: str, body: IO[bytes], *, content_type: str = "application/json", - user_isolation_key: Optional[str] = ..., - **kwargs: Any - ) -> AgentSessionResource: ... - - @overload - async def create_version_from_code( - self, - agent_name: str, - content: CreateAgentVersionFromCodeContent, - *, - code_zip_sha256: str, - **kwargs: Any - ) -> AgentVersionDetails: ... - - @overload - async def create_version_from_code( - self, - agent_name: str, - content: JSON, - *, - code_zip_sha256: str, **kwargs: Any ) -> AgentVersionDetails: ... @distributed_trace_async - async def delete_optimization_job( + async def delete( self, - job_id: str, + agent_name: str, *, force: Optional[bool] = ..., **kwargs: Any - ) -> None: ... + ) -> DeleteAgentResponse: ... @distributed_trace_async async def delete_session( self, agent_name: str, session_id: str, - *, - user_isolation_key: Optional[str] = ..., **kwargs: Any ) -> None: ... @@ -336,80 +229,89 @@ namespace azure.ai.projects.aio.operations agent_name: str, agent_session_id: str, *, - path: str, recursive: Optional[bool] = ..., - user_isolation_key: Optional[str] = ..., + remote_path: str, **kwargs: Any ) -> None: ... @distributed_trace_async - async def download_code( + async def delete_version( self, agent_name: str, + agent_version: str, *, - agent_version: Optional[str] = ..., + force: Optional[bool] = ..., **kwargs: Any - ) -> AsyncIterator[bytes]: ... + ) -> DeleteAgentVersionResponse: ... @distributed_trace_async - async def download_session_file( + async def disable( + self, + agent_name: str, + **kwargs: Any + ) -> None: ... + + @distributed_trace_async + async def download_code_as_bytes( self, agent_name: str, - agent_session_id: str, *, - path: str, - user_isolation_key: Optional[str] = ..., + agent_version: Optional[str] = ..., **kwargs: Any ) -> AsyncIterator[bytes]: ... @distributed_trace_async - async def get_candidate_file( + async def download_code_to_path( self, - job_id: str, - candidate_id: str, + agent_name: str, *, - path: str, + agent_version: Optional[str] = ..., + file_path: Union[str, PathLike[str]], + overwrite: bool = False, **kwargs: Any - ) -> AsyncIterator[bytes]: ... + ) -> str: ... @distributed_trace_async - async def get_optimization_candidate( + async def download_session_file_as_bytes( self, - job_id: str, - candidate_id: str, + agent_name: str, + agent_session_id: str, + *, + remote_path: str, **kwargs: Any - ) -> CandidateMetadata: ... + ) -> AsyncIterator[bytes]: ... @distributed_trace_async - async def get_optimization_candidate_config( + async def download_session_file_to_path( self, - job_id: str, - candidate_id: str, + agent_name: str, + session_id: str, + *, + file_path: Union[str, PathLike[str]], + overwrite: bool = False, + remote_path: str, **kwargs: Any - ) -> CandidateDeployConfig: ... + ) -> None: ... @distributed_trace_async - async def get_optimization_candidate_results( + async def enable( self, - job_id: str, - candidate_id: str, + agent_name: str, **kwargs: Any - ) -> CandidateResults: ... + ) -> None: ... @distributed_trace_async - async def get_optimization_job( + async def get( self, - job_id: str, + agent_name: str, **kwargs: Any - ) -> OptimizationJob: ... + ) -> AgentDetails: ... @distributed_trace_async async def get_session( self, agent_name: str, session_id: str, - *, - user_isolation_key: Optional[str] = ..., **kwargs: Any ) -> AgentSessionResource: ... @@ -423,28 +325,23 @@ namespace azure.ai.projects.aio.operations ) -> SessionLogEvent: ... @distributed_trace_async - async def list_optimization_candidates( + async def get_version( self, - job_id: str, - *, - after: Optional[str] = ..., - before: Optional[str] = ..., - limit: Optional[int] = ..., - order: Optional[Union[str, PageOrder]] = ..., + agent_name: str, + agent_version: str, **kwargs: Any - ) -> AgentsPagedResultOptimizationCandidate: ... + ) -> AgentVersionDetails: ... @distributed_trace - def list_optimization_jobs( + def list( self, *, - agent_name: Optional[str] = ..., before: Optional[str] = ..., + kind: Optional[Union[str, AgentKind]] = ..., limit: Optional[int] = ..., order: Optional[Union[str, PageOrder]] = ..., - status: Optional[Union[str, JobStatus]] = ..., **kwargs: Any - ) -> AsyncItemPaged[OptimizationJob]: ... + ) -> AsyncItemPaged[AgentDetails]: ... @distributed_trace def list_session_files( @@ -455,8 +352,7 @@ namespace azure.ai.projects.aio.operations before: Optional[str] = ..., limit: Optional[int] = ..., order: Optional[Union[str, PageOrder]] = ..., - path: Optional[str] = ..., - user_isolation_key: Optional[str] = ..., + remote_path: Optional[str] = ..., **kwargs: Any ) -> AsyncItemPaged[SessionDirectoryEntry]: ... @@ -468,12 +364,31 @@ namespace azure.ai.projects.aio.operations before: Optional[str] = ..., limit: Optional[int] = ..., order: Optional[Union[str, PageOrder]] = ..., - user_isolation_key: Optional[str] = ..., **kwargs: Any ) -> AsyncItemPaged[AgentSessionResource]: ... + @distributed_trace + def list_versions( + self, + agent_name: str, + *, + before: Optional[str] = ..., + include_drafts: Optional[bool] = ..., + limit: Optional[int] = ..., + order: Optional[Union[str, PageOrder]] = ..., + **kwargs: Any + ) -> AsyncItemPaged[AgentVersionDetails]: ... + + @distributed_trace_async + async def stop_session( + self, + agent_name: str, + session_id: str, + **kwargs: Any + ) -> None: ... + @overload - async def patch_agent_details( + async def update_details( self, agent_name: str, *, @@ -484,7 +399,7 @@ namespace azure.ai.projects.aio.operations ) -> AgentDetails: ... @overload - async def patch_agent_details( + async def update_details( self, agent_name: str, body: JSON, @@ -494,7 +409,7 @@ namespace azure.ai.projects.aio.operations ) -> AgentDetails: ... @overload - async def patch_agent_details( + async def update_details( self, agent_name: str, body: IO[bytes], @@ -504,56 +419,98 @@ namespace azure.ai.projects.aio.operations ) -> AgentDetails: ... @overload - async def promote_candidate( + async def upload_session_file( + self, + agent_name: str, + session_id: str, + *, + content: bytes, + remote_path: str, + **kwargs: Any + ) -> SessionFileWriteResult: ... + + @overload + async def upload_session_file( + self, + agent_name: str, + session_id: str, + *, + file_path: Union[str, PathLike[str]], + remote_path: str, + **kwargs: Any + ) -> SessionFileWriteResult: ... + + + class azure.ai.projects.aio.operations.BetaAgentsOperations: + + def __init__( + self, + *args, + **kwargs + ) -> None: ... + + @distributed_trace_async + async def cancel_optimization_job( self, job_id: str, - candidate_id: str, - candidate_request: PromoteCandidateRequest, + **kwargs: Any + ) -> OptimizationJob: ... + + @overload + async def create_optimization_job( + self, + job: OptimizationJob, *, content_type: str = "application/json", + operation_id: Optional[str] = ..., **kwargs: Any - ) -> PromoteCandidateResponse: ... + ) -> OptimizationJob: ... @overload - async def promote_candidate( + async def create_optimization_job( self, - job_id: str, - candidate_id: str, - candidate_request: JSON, + job: JSON, *, content_type: str = "application/json", + operation_id: Optional[str] = ..., **kwargs: Any - ) -> PromoteCandidateResponse: ... + ) -> OptimizationJob: ... @overload - async def promote_candidate( + async def create_optimization_job( self, - job_id: str, - candidate_id: str, - candidate_request: IO[bytes], + job: IO[bytes], *, content_type: str = "application/json", + operation_id: Optional[str] = ..., **kwargs: Any - ) -> PromoteCandidateResponse: ... + ) -> OptimizationJob: ... @distributed_trace_async - async def stop_session( + async def delete_optimization_job( self, - agent_name: str, - session_id: str, + job_id: str, **kwargs: Any ) -> None: ... @distributed_trace_async - async def upload_session_file( + async def get_optimization_job( + self, + job_id: str, + **kwargs: Any + ) -> OptimizationJob: ... + + @distributed_trace + def list_optimization_jobs( self, - agent_name: str, - session_id: str, - content_or_file_path: bytes | str, *, - path: str, + agent_name: Optional[str] = ..., + before: Optional[str] = ..., + limit: Optional[int] = ..., + order: Optional[Union[str, PageOrder]] = ..., + status: Optional[Union[str, JobStatus]] = ..., **kwargs: Any - ) -> SessionFileWriteResult: ... + ) -> AsyncItemPaged[OptimizationJobListItem]: ... class azure.ai.projects.aio.operations.BetaDatasetsOperations: @@ -1535,7 +1492,6 @@ namespace azure.ai.projects.aio.operations routines: BetaRoutinesOperations schedules: BetaSchedulesOperations skills: BetaSkillsOperations - toolboxes: BetaToolboxesOperations def __init__( self, @@ -1829,169 +1785,30 @@ namespace azure.ai.projects.aio.operations *, content_type: str = "application/json", **kwargs: Any - ) -> SkillVersion: ... - - @overload - async def create_from_files( - self, - name: str, - content: CreateSkillVersionFromFilesBody, - **kwargs: Any - ) -> SkillVersion: ... - - @overload - async def create_from_files( - self, - name: str, - content: JSON, - **kwargs: Any - ) -> SkillVersion: ... - - @distributed_trace_async - async def delete( - self, - name: str, - **kwargs: Any - ) -> DeleteSkillResult: ... - - @distributed_trace_async - async def delete_version( - self, - name: str, - version: str, - **kwargs: Any - ) -> DeleteSkillVersionResult: ... - - @distributed_trace_async - async def download( - self, - name: str, - **kwargs: Any - ) -> AsyncIterator[bytes]: ... - - @distributed_trace_async - async def download_version( - self, - name: str, - version: str, - **kwargs: Any - ) -> AsyncIterator[bytes]: ... - - @distributed_trace_async - async def get( - self, - name: str, - **kwargs: Any - ) -> SkillDetails: ... - - @distributed_trace_async - async def get_version( - self, - name: str, - version: str, - **kwargs: Any - ) -> SkillVersion: ... - - @distributed_trace - def list( - self, - *, - before: Optional[str] = ..., - limit: Optional[int] = ..., - order: Optional[Union[str, PageOrder]] = ..., - **kwargs: Any - ) -> AsyncItemPaged[SkillDetails]: ... - - @distributed_trace - def list_versions( - self, - name: str, - *, - before: Optional[str] = ..., - limit: Optional[int] = ..., - order: Optional[Union[str, PageOrder]] = ..., - **kwargs: Any - ) -> AsyncItemPaged[SkillVersion]: ... - - @overload - async def update( - self, - name: str, - *, - content_type: str = "application/json", - default_version: str, - **kwargs: Any - ) -> SkillDetails: ... - - @overload - async def update( - self, - name: str, - body: JSON, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> SkillDetails: ... - - @overload - async def update( - self, - name: str, - body: IO[bytes], - *, - content_type: str = "application/json", - **kwargs: Any - ) -> SkillDetails: ... - - - class azure.ai.projects.aio.operations.BetaToolboxesOperations: - - def __init__( - self, - *args, - **kwargs - ) -> None: ... - - @overload - async def create_version( - self, - name: str, - *, - content_type: str = "application/json", - description: Optional[str] = ..., - metadata: Optional[dict[str, str]] = ..., - policies: Optional[ToolboxPolicies] = ..., - skills: Optional[List[ToolboxSkill]] = ..., - tools: List[Tool], - **kwargs: Any - ) -> ToolboxVersionObject: ... + ) -> SkillVersion: ... @overload - async def create_version( + async def create_from_files( self, name: str, - body: JSON, - *, - content_type: str = "application/json", + content: CreateSkillVersionFromFilesBody, **kwargs: Any - ) -> ToolboxVersionObject: ... + ) -> SkillVersion: ... @overload - async def create_version( + async def create_from_files( self, name: str, - body: IO[bytes], - *, - content_type: str = "application/json", + content: JSON, **kwargs: Any - ) -> ToolboxVersionObject: ... + ) -> SkillVersion: ... @distributed_trace_async async def delete( self, name: str, **kwargs: Any - ) -> None: ... + ) -> DeleteSkillResult: ... @distributed_trace_async async def delete_version( @@ -1999,14 +1816,29 @@ namespace azure.ai.projects.aio.operations name: str, version: str, **kwargs: Any - ) -> None: ... + ) -> DeleteSkillVersionResult: ... + + @distributed_trace_async + async def download( + self, + name: str, + **kwargs: Any + ) -> AsyncIterator[bytes]: ... + + @distributed_trace_async + async def download_version( + self, + name: str, + version: str, + **kwargs: Any + ) -> AsyncIterator[bytes]: ... @distributed_trace_async async def get( self, name: str, **kwargs: Any - ) -> ToolboxObject: ... + ) -> SkillDetails: ... @distributed_trace_async async def get_version( @@ -2014,7 +1846,7 @@ namespace azure.ai.projects.aio.operations name: str, version: str, **kwargs: Any - ) -> ToolboxVersionObject: ... + ) -> SkillVersion: ... @distributed_trace def list( @@ -2024,7 +1856,7 @@ namespace azure.ai.projects.aio.operations limit: Optional[int] = ..., order: Optional[Union[str, PageOrder]] = ..., **kwargs: Any - ) -> AsyncItemPaged[ToolboxObject]: ... + ) -> AsyncItemPaged[SkillDetails]: ... @distributed_trace def list_versions( @@ -2035,7 +1867,7 @@ namespace azure.ai.projects.aio.operations limit: Optional[int] = ..., order: Optional[Union[str, PageOrder]] = ..., **kwargs: Any - ) -> AsyncItemPaged[ToolboxVersionObject]: ... + ) -> AsyncItemPaged[SkillVersion]: ... @overload async def update( @@ -2045,7 +1877,7 @@ namespace azure.ai.projects.aio.operations content_type: str = "application/json", default_version: str, **kwargs: Any - ) -> ToolboxObject: ... + ) -> SkillDetails: ... @overload async def update( @@ -2055,7 +1887,7 @@ namespace azure.ai.projects.aio.operations *, content_type: str = "application/json", **kwargs: Any - ) -> ToolboxObject: ... + ) -> SkillDetails: ... @overload async def update( @@ -2065,7 +1897,7 @@ namespace azure.ai.projects.aio.operations *, content_type: str = "application/json", **kwargs: Any - ) -> ToolboxObject: ... + ) -> SkillDetails: ... class azure.ai.projects.aio.operations.ConnectionsOperations(ConnectionsOperationsGenerated): @@ -2401,17 +2233,163 @@ namespace azure.ai.projects.aio.operations async def get_application_insights_connection_string(self) -> str: ... + class azure.ai.projects.aio.operations.ToolboxesOperations: + + def __init__( + self, + *args, + **kwargs + ) -> None: ... + + @overload + async def create_version( + self, + name: str, + *, + content_type: str = "application/json", + description: Optional[str] = ..., + metadata: Optional[dict[str, str]] = ..., + policies: Optional[ToolboxPolicies] = ..., + skills: Optional[List[ToolboxSkill]] = ..., + tools: List[ToolboxTool], + **kwargs: Any + ) -> ToolboxVersionObject: ... + + @overload + async def create_version( + self, + name: str, + body: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> ToolboxVersionObject: ... + + @overload + async def create_version( + self, + name: str, + body: IO[bytes], + *, + content_type: str = "application/json", + **kwargs: Any + ) -> ToolboxVersionObject: ... + + @distributed_trace_async + async def delete( + self, + name: str, + **kwargs: Any + ) -> None: ... + + @distributed_trace_async + async def delete_version( + self, + name: str, + version: str, + **kwargs: Any + ) -> None: ... + + @distributed_trace_async + async def get( + self, + name: str, + **kwargs: Any + ) -> ToolboxObject: ... + + @distributed_trace_async + async def get_version( + self, + name: str, + version: str, + **kwargs: Any + ) -> ToolboxVersionObject: ... + + @distributed_trace + def list( + self, + *, + before: Optional[str] = ..., + limit: Optional[int] = ..., + order: Optional[Union[str, PageOrder]] = ..., + **kwargs: Any + ) -> AsyncItemPaged[ToolboxObject]: ... + + @distributed_trace + def list_versions( + self, + name: str, + *, + before: Optional[str] = ..., + limit: Optional[int] = ..., + order: Optional[Union[str, PageOrder]] = ..., + **kwargs: Any + ) -> AsyncItemPaged[ToolboxVersionObject]: ... + + @overload + async def update( + self, + name: str, + *, + content_type: str = "application/json", + default_version: str, + **kwargs: Any + ) -> ToolboxObject: ... + + @overload + async def update( + self, + name: str, + body: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> ToolboxObject: ... + + @overload + async def update( + self, + name: str, + body: IO[bytes], + *, + content_type: str = "application/json", + **kwargs: Any + ) -> ToolboxObject: ... + + namespace azure.ai.projects.models class azure.ai.projects.models.A2APreviewTool(Tool, discriminator='a2a_preview'): agent_card_path: Optional[str] base_url: Optional[str] - description: Optional[str] - name: Optional[str] project_connection_id: Optional[str] - tool_configs: Optional[dict[str, ToolConfig]] + send_credentials_for_agent_card: Optional[bool] type: Literal[ToolType.A2A_PREVIEW] + @overload + def __init__( + self, + *, + agent_card_path: Optional[str] = ..., + base_url: Optional[str] = ..., + project_connection_id: Optional[str] = ..., + send_credentials_for_agent_card: Optional[bool] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.A2APreviewToolboxTool(ToolboxTool, discriminator='a2a_preview'): + agent_card_path: Optional[str] + base_url: Optional[str] + description: str + name: str + project_connection_id: Optional[str] + send_credentials_for_agent_card: Optional[bool] + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.A2A_PREVIEW] + @overload def __init__( self, @@ -2421,6 +2399,7 @@ namespace azure.ai.projects.models description: Optional[str] = ..., name: Optional[str] = ..., project_connection_id: Optional[str] = ..., + send_credentials_for_agent_card: Optional[bool] = ..., tool_configs: Optional[dict[str, ToolConfig]] = ... ) -> None: ... @@ -2428,6 +2407,9 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.A2AProtocolConfiguration(_Model): + + class azure.ai.projects.models.AISearchIndexResource(_Model): filter: Optional[str] index_asset_id: Optional[str] @@ -2452,6 +2434,20 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.ActivityProtocolConfiguration(_Model): + enable_m365_public_endpoint: Optional[bool] + + @overload + def __init__( + self, + *, + enable_m365_public_endpoint: Optional[bool] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.AgentBlueprintReference(_Model): type: str @@ -2586,6 +2582,7 @@ namespace azure.ai.projects.models instance_identity: Optional[AgentIdentity] name: str object: Literal[AgentObjectType.AGENT] + state: Union[str, AgentState] versions: AgentObjectVersions @overload @@ -2621,12 +2618,13 @@ namespace azure.ai.projects.models class azure.ai.projects.models.AgentEndpointAuthorizationSchemeType(str, Enum, metaclass=CaseInsensitiveEnumMeta): BOT_SERVICE = "BotService" BOT_SERVICE_RBAC = "BotServiceRbac" + BOT_SERVICE_TENANT = "BotServiceTenant" ENTRA = "Entra" class azure.ai.projects.models.AgentEndpointConfig(_Model): authorization_schemes: Optional[list[AgentEndpointAuthorizationScheme]] - protocols: Optional[list[Union[str, AgentEndpointProtocol]]] + protocol_configuration: Optional[ProtocolConfiguration] version_selector: Optional[VersionSelector] @overload @@ -2634,7 +2632,7 @@ namespace azure.ai.projects.models self, *, authorization_schemes: Optional[list[AgentEndpointAuthorizationScheme]] = ..., - protocols: Optional[list[Union[str, AgentEndpointProtocol]]] = ..., + protocol_configuration: Optional[ProtocolConfiguration] = ..., version_selector: Optional[VersionSelector] = ... ) -> None: ... @@ -2670,22 +2668,6 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.AgentIdentifier(_Model): - agent_name: str - agent_version: Optional[str] - - @overload - def __init__( - self, - *, - agent_name: str, - agent_version: Optional[str] = ... - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - class azure.ai.projects.models.AgentIdentity(_Model): client_id: str principal_id: str @@ -2731,14 +2713,6 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.AgentProtocol(str, Enum, metaclass=CaseInsensitiveEnumMeta): - ACTIVITY_PROTOCOL = "activity_protocol" - INVOCATIONS = "invocations" - INVOCATIONS_WS = "invocations_ws" - MCP = "mcp" - RESPONSES = "responses" - - class azure.ai.projects.models.AgentSessionResource(_Model): agent_session_id: str created_at: datetime @@ -2771,6 +2745,11 @@ namespace azure.ai.projects.models UPDATING = "updating" + class azure.ai.projects.models.AgentState(str, Enum, metaclass=CaseInsensitiveEnumMeta): + DISABLED = "disabled" + ENABLED = "enabled" + + class azure.ai.projects.models.AgentTaxonomyInput(EvaluationTaxonomyInput, discriminator='agent'): risk_categories: list[Union[str, RiskCategory]] target: EvaluationTarget @@ -2795,6 +2774,7 @@ namespace azure.ai.projects.models created_at: datetime definition: AgentDefinition description: Optional[str] + draft: Optional[bool] id: str instance_identity: Optional[AgentIdentity] metadata: dict[str, str] @@ -2810,6 +2790,7 @@ namespace azure.ai.projects.models created_at: datetime, definition: AgentDefinition, description: Optional[str] = ..., + draft: Optional[bool] = ..., id: str, metadata: dict[str, str], name: str, @@ -2840,26 +2821,6 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.AgentsPagedResultOptimizationCandidate(_Model): - data: list[OptimizationCandidate] - first_id: Optional[str] - has_more: bool - last_id: Optional[str] - - @overload - def __init__( - self, - *, - data: list[OptimizationCandidate], - first_id: Optional[str] = ..., - has_more: bool, - last_id: Optional[str] = ... - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - class azure.ai.projects.models.ApiError(_Model): additional_info: Optional[dict[str, Any]] code: str @@ -3145,14 +3106,35 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.AzureAISearchToolResource(_Model): - indexes: list[AISearchIndexResource] + class azure.ai.projects.models.AzureAISearchToolResource(_Model): + indexes: list[AISearchIndexResource] + + @overload + def __init__( + self, + *, + indexes: list[AISearchIndexResource] + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.AzureAISearchToolboxTool(ToolboxTool, discriminator='azure_ai_search'): + azure_ai_search: AzureAISearchToolResource + description: str + name: str + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.AZURE_AI_SEARCH] @overload def __init__( self, *, - indexes: list[AISearchIndexResource] + azure_ai_search: AzureAISearchToolResource, + description: Optional[str] = ..., + name: Optional[str] = ..., + tool_configs: Optional[dict[str, ToolConfig]] = ... ) -> None: ... @overload @@ -3298,19 +3280,13 @@ namespace azure.ai.projects.models class azure.ai.projects.models.BingCustomSearchPreviewTool(Tool, discriminator='bing_custom_search_preview'): bing_custom_search_preview: BingCustomSearchToolParameters - description: Optional[str] - name: Optional[str] - tool_configs: Optional[dict[str, ToolConfig]] type: Literal[ToolType.BING_CUSTOM_SEARCH_PREVIEW] @overload def __init__( self, *, - bing_custom_search_preview: BingCustomSearchToolParameters, - description: Optional[str] = ..., - name: Optional[str] = ..., - tool_configs: Optional[dict[str, ToolConfig]] = ... + bing_custom_search_preview: BingCustomSearchToolParameters ) -> None: ... @overload @@ -3437,137 +3413,74 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.BrowserAutomationPreviewTool(Tool, discriminator='browser_automation_preview'): - browser_automation_preview: BrowserAutomationToolParameters - description: Optional[str] - name: Optional[str] - tool_configs: Optional[dict[str, ToolConfig]] - type: Literal[ToolType.BROWSER_AUTOMATION_PREVIEW] - - @overload - def __init__( - self, - *, - browser_automation_preview: BrowserAutomationToolParameters, - description: Optional[str] = ..., - name: Optional[str] = ..., - tool_configs: Optional[dict[str, ToolConfig]] = ... - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - - class azure.ai.projects.models.BrowserAutomationToolConnectionParameters(_Model): - project_connection_id: str - - @overload - def __init__( - self, - *, - project_connection_id: str - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - - class azure.ai.projects.models.BrowserAutomationToolParameters(_Model): - connection: BrowserAutomationToolConnectionParameters + class azure.ai.projects.models.BotServiceTenantAuthorizationScheme(AgentEndpointAuthorizationScheme, discriminator='BotServiceTenant'): + type: Literal[AgentEndpointAuthorizationSchemeType.BOT_SERVICE_TENANT] @overload - def __init__( - self, - *, - connection: BrowserAutomationToolConnectionParameters - ) -> None: ... + def __init__(self) -> None: ... @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.CandidateDeployConfig(_Model): - instructions: Optional[str] - model: Optional[str] - skills: Optional[list[dict[str, Any]]] - temperature: Optional[float] - tools: Optional[list[dict[str, Any]]] + class azure.ai.projects.models.BrowserAutomationPreviewTool(Tool, discriminator='browser_automation_preview'): + browser_automation_preview: BrowserAutomationToolParameters + type: Literal[ToolType.BROWSER_AUTOMATION_PREVIEW] @overload def __init__( self, *, - instructions: Optional[str] = ..., - model: Optional[str] = ..., - skills: Optional[list[dict[str, Any]]] = ..., - temperature: Optional[float] = ..., - tools: Optional[list[dict[str, Any]]] = ... + browser_automation_preview: BrowserAutomationToolParameters ) -> None: ... @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.CandidateFileInfo(_Model): - path: str - size_bytes: int - type: str + class azure.ai.projects.models.BrowserAutomationPreviewToolboxTool(ToolboxTool, discriminator='browser_automation_preview'): + browser_automation_preview: BrowserAutomationToolParameters + description: str + name: str + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.BROWSER_AUTOMATION_PREVIEW] @overload def __init__( self, *, - path: str, - size_bytes: int, - type: str + browser_automation_preview: BrowserAutomationToolParameters, + description: Optional[str] = ..., + name: Optional[str] = ..., + tool_configs: Optional[dict[str, ToolConfig]] = ... ) -> None: ... @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.CandidateMetadata(_Model): - candidate_id: str - candidate_name: str - created_at: datetime - files: list[CandidateFileInfo] - has_results: bool - job_id: str - promotion: Optional[PromotionInfo] - score: Optional[float] - status: str - updated_at: datetime + class azure.ai.projects.models.BrowserAutomationToolConnectionParameters(_Model): + project_connection_id: str @overload def __init__( self, *, - candidate_id: str, - candidate_name: str, - created_at: datetime, - files: list[CandidateFileInfo], - has_results: bool, - job_id: str, - promotion: Optional[PromotionInfo] = ..., - score: Optional[float] = ..., - status: str, - updated_at: datetime + project_connection_id: str ) -> None: ... @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.CandidateResults(_Model): - candidate_id: str - results: list[OptimizationTaskResult] + class azure.ai.projects.models.BrowserAutomationToolParameters(_Model): + connection: BrowserAutomationToolConnectionParameters @overload def __init__( self, *, - candidate_id: str, - results: list[OptimizationTaskResult] + connection: BrowserAutomationToolConnectionParameters ) -> None: ... @overload @@ -3742,9 +3655,30 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.CodeInterpreterToolboxTool(ToolboxTool, discriminator='code_interpreter'): + container: Optional[Union[str, AutoCodeInterpreterToolParam]] + description: str + name: str + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.CODE_INTERPRETER] + + @overload + def __init__( + self, + *, + container: Optional[Union[str, AutoCodeInterpreterToolParam]] = ..., + description: Optional[str] = ..., + name: Optional[str] = ..., + tool_configs: Optional[dict[str, ToolConfig]] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.ComparisonFilter(_Model): key: str - type: Literal["eq", "ne", "gt", "gte", "lt", "lte"] + type: Literal["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"] value: Union[str, float, bool, list[Union[str, float]]] @overload @@ -3752,7 +3686,7 @@ namespace azure.ai.projects.models self, *, key: str, - type: Literal["eq", "ne", "gt", "gte", "lt", "lte"], + type: Literal["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"], value: Union[str, float, bool, list[Union[str, float]]] ) -> None: ... @@ -3784,6 +3718,16 @@ namespace azure.ai.projects.models WINDOWS = "windows" + class azure.ai.projects.models.ComputerTool(Tool, discriminator='computer'): + type: Literal[ToolType.COMPUTER] + + @overload + def __init__(self) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.ComputerUsePreviewTool(Tool, discriminator='computer_use_preview'): display_height: int display_width: int @@ -3954,6 +3898,7 @@ namespace azure.ai.projects.models class azure.ai.projects.models.ContinuousEvaluationRuleAction(EvaluationRuleAction, discriminator='continuousEvaluation'): eval_id: str max_hourly_runs: Optional[int] + sampling_rate: Optional[float] type: Literal[EvaluationRuleActionType.CONTINUOUS_EVALUATION] @overload @@ -3961,7 +3906,8 @@ namespace azure.ai.projects.models self, *, eval_id: str, - max_hourly_runs: Optional[int] = ... + max_hourly_runs: Optional[int] = ..., + sampling_rate: Optional[float] = ... ) -> None: ... @overload @@ -4152,6 +4098,7 @@ namespace azure.ai.projects.models class azure.ai.projects.models.CustomToolParam(Tool, discriminator='custom'): + defer_loading: Optional[bool] description: Optional[str] format: Optional[CustomToolParamFormat] name: str @@ -4161,6 +4108,7 @@ namespace azure.ai.projects.models def __init__( self, *, + defer_loading: Optional[bool] = ..., description: Optional[str] = ..., format: Optional[CustomToolParamFormat] = ..., name: str @@ -4424,42 +4372,6 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.DatasetInfo(_Model): - is_inline: bool - name: Optional[str] - task_count: int - version: Optional[str] - - @overload - def __init__( - self, - *, - is_inline: bool, - name: Optional[str] = ..., - task_count: int, - version: Optional[str] = ... - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - - class azure.ai.projects.models.DatasetRef(_Model): - name: str - version: Optional[str] - - @overload - def __init__( - self, - *, - name: str, - version: Optional[str] = ... - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - class azure.ai.projects.models.DatasetReference(_Model): name: str version: str @@ -4702,23 +4614,32 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.EntraAuthorizationScheme(AgentEndpointAuthorizationScheme, discriminator='Entra'): - isolation_key_source: Optional[IsolationKeySource] - type: Literal[AgentEndpointAuthorizationSchemeType.ENTRA] + class azure.ai.projects.models.EmptyModelParam(_Model): + + + class azure.ai.projects.models.EndpointBasedEvaluatorDefinition(EvaluatorDefinition, discriminator='endpoint'): + connection_name: str + data_schema: dict[str, any] + init_parameters: dict[str, any] + metrics: dict[str, EvaluatorMetric] + type: Literal[EvaluatorDefinitionType.ENDPOINT] @overload def __init__( self, *, - isolation_key_source: Optional[IsolationKeySource] = ... + connection_name: str, + data_schema: Optional[dict[str, Any]] = ..., + init_parameters: Optional[dict[str, Any]] = ..., + metrics: Optional[dict[str, EvaluatorMetric]] = ... ) -> None: ... @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.EntraIDCredentials(BaseCredentials, discriminator='AAD'): - type: Literal[CredentialType.ENTRA_ID] + class azure.ai.projects.models.EntraAuthorizationScheme(AgentEndpointAuthorizationScheme, discriminator='Entra'): + type: Literal[AgentEndpointAuthorizationSchemeType.ENTRA] @overload def __init__(self) -> None: ... @@ -4727,8 +4648,8 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.EntraIsolationKeySource(IsolationKeySource, discriminator='Entra'): - kind: Literal[IsolationKeySourceKind.ENTRA] + class azure.ai.projects.models.EntraIDCredentials(BaseCredentials, discriminator='AAD'): + type: Literal[CredentialType.ENTRA_ID] @overload def __init__(self) -> None: ... @@ -4994,7 +4915,7 @@ namespace azure.ai.projects.models class azure.ai.projects.models.EvaluationScheduleTask(ScheduleTask, discriminator='Evaluation'): configuration: dict[str, str] eval_id: str - eval_run: Any + eval_run: dict[str, Any] type: Literal[ScheduleTaskType.EVALUATION] @overload @@ -5003,7 +4924,7 @@ namespace azure.ai.projects.models *, configuration: Optional[dict[str, str]] = ..., eval_id: str, - eval_run: Any + eval_run: dict[str, Any] ) -> None: ... @overload @@ -5110,6 +5031,7 @@ namespace azure.ai.projects.models class azure.ai.projects.models.EvaluatorDefinitionType(str, Enum, metaclass=CaseInsensitiveEnumMeta): CODE = "code" + ENDPOINT = "endpoint" OPENAI_GRADERS = "openai_graders" PROMPT = "prompt" PROMPT_AND_CODE = "prompt_and_code" @@ -5269,6 +5191,7 @@ namespace azure.ai.projects.models metadata: Optional[dict[str, str]] modified_at: datetime name: str + supported_evaluation_levels: Optional[list[Union[str, EvaluationLevel]]] tags: Optional[dict[str, str]] version: str @@ -5282,6 +5205,7 @@ namespace azure.ai.projects.models display_name: Optional[str] = ..., evaluator_type: Union[str, EvaluatorType], metadata: Optional[dict[str, str]] = ..., + supported_evaluation_levels: Optional[list[Union[str, EvaluationLevel]]] = ..., tags: Optional[dict[str, str]] = ... ) -> None: ... @@ -5321,15 +5245,36 @@ namespace azure.ai.projects.models class azure.ai.projects.models.FabricIQPreviewTool(Tool, discriminator='fabric_iq_preview'): - description: Optional[str] - name: Optional[str] project_connection_id: str require_approval: Optional[Union[MCPToolRequireApproval, str]] server_label: Optional[str] server_url: Optional[str] - tool_configs: Optional[dict[str, ToolConfig]] type: Literal[ToolType.FABRIC_IQ_PREVIEW] + @overload + def __init__( + self, + *, + project_connection_id: str, + require_approval: Optional[Union[MCPToolRequireApproval, str]] = ..., + server_label: Optional[str] = ..., + server_url: Optional[str] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.FabricIQPreviewToolboxTool(ToolboxTool, discriminator='fabric_iq_preview'): + description: str + name: str + project_connection_id: str + require_approval: Optional[Union[MCPToolRequireApproval, str]] + server_label: Optional[str] + server_url: Optional[str] + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.FABRIC_IQ_PREVIEW] + @overload def __init__( self, @@ -5452,6 +5397,33 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.FileSearchToolboxTool(ToolboxTool, discriminator='file_search'): + description: str + filters: Optional[Filters] + max_num_results: Optional[int] + name: str + ranking_options: Optional[RankingOptions] + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.FILE_SEARCH] + vector_store_ids: Optional[list[str]] + + @overload + def __init__( + self, + *, + description: Optional[str] = ..., + filters: Optional[Filters] = ..., + max_num_results: Optional[int] = ..., + name: Optional[str] = ..., + ranking_options: Optional[RankingOptions] = ..., + tool_configs: Optional[dict[str, ToolConfig]] = ..., + vector_store_ids: Optional[list[str]] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.FixedRatioVersionSelectionRule(VersionSelectionRule, discriminator='FixedRatio'): agent_version: str traffic_percentage: int @@ -5612,6 +5584,7 @@ namespace azure.ai.projects.models class azure.ai.projects.models.FunctionTool(Tool, discriminator='function'): + defer_loading: Optional[bool] description: Optional[str] name: str parameters: dict[str, Any] @@ -5622,6 +5595,7 @@ namespace azure.ai.projects.models def __init__( self, *, + defer_loading: Optional[bool] = ..., description: Optional[str] = ..., name: str, parameters: dict[str, Any], @@ -5632,6 +5606,29 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.FunctionToolParam(_Model): + defer_loading: Optional[bool] + description: Optional[str] + name: str + parameters: Optional[EmptyModelParam] + strict: Optional[bool] + type: Literal["function"] + + @overload + def __init__( + self, + *, + defer_loading: Optional[bool] = ..., + description: Optional[str] = ..., + name: str, + parameters: Optional[EmptyModelParam] = ..., + strict: Optional[bool] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.GitHubIssueEvent(str, Enum, metaclass=CaseInsensitiveEnumMeta): CLOSED = "closed" OPENED = "opened" @@ -5663,16 +5660,6 @@ namespace azure.ai.projects.models REGEX = "regex" - class azure.ai.projects.models.HeaderIsolationKeySource(IsolationKeySource, discriminator='Header'): - kind: Literal[IsolationKeySourceKind.HEADER] - - @overload - def __init__(self) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - class azure.ai.projects.models.HeaderTelemetryEndpointAuth(TelemetryEndpointAuth, discriminator='header'): header_name: str secret_id: str @@ -5702,7 +5689,6 @@ namespace azure.ai.projects.models protocol_versions: Optional[list[ProtocolVersionRecord]] rai_config: RaiConfig telemetry_config: Optional[TelemetryConfig] - tools: Optional[list[Tool]] @overload def __init__( @@ -5715,8 +5701,7 @@ namespace azure.ai.projects.models memory: str, protocol_versions: Optional[list[ProtocolVersionRecord]] = ..., rai_config: Optional[RaiConfig] = ..., - telemetry_config: Optional[TelemetryConfig] = ..., - tools: Optional[list[Tool]] = ... + telemetry_config: Optional[TelemetryConfig] = ... ) -> None: ... @overload @@ -5783,7 +5768,7 @@ namespace azure.ai.projects.models output_format: Optional[Literal["png", "webp", "jpeg"]] partial_images: Optional[int] quality: Optional[Literal["low", "medium", "high", "auto"]] - size: Optional[Literal["1024x1024", "1024x1536", "1536x1024", "auto"]] + size: Optional[Union[Literal["1024x1024"], Literal["1024x1536"], Literal["1536x1024"], Literal["auto"], str]] tool_configs: Optional[dict[str, ToolConfig]] type: Literal[ToolType.IMAGE_GENERATION] @@ -5803,7 +5788,7 @@ namespace azure.ai.projects.models output_format: Optional[Literal[png, webp, jpeg]] = ..., partial_images: Optional[int] = ..., quality: Optional[Literal[low, medium, high, auto]] = ..., - size: Optional[Literal[1024x1024, 1024x1536, 1536x1024, auto]] = ..., + size: Optional[Union[Literal[1024x1024], Literal[1024x1536], Literal[1536x1024], Literal[auto], str]] = ..., tool_configs: Optional[dict[str, ToolConfig]] = ... ) -> None: ... @@ -6065,6 +6050,12 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.InvocationsProtocolConfiguration(_Model): + + + class azure.ai.projects.models.InvocationsWsProtocolConfiguration(_Model): + + class azure.ai.projects.models.InvokeAgentInvocationsApiDispatchPayload(RoutineDispatchPayload, discriminator='invoke_agent_invocations_api'): input: Any type: Literal[RoutineDispatchPayloadType.INVOKE_AGENT_INVOCATIONS_API] @@ -6127,35 +6118,16 @@ namespace azure.ai.projects.models def __init__( self, *, - agent_endpoint_id: Optional[str] = ..., - agent_name: Optional[str] = ..., - conversation: Optional[str] = ..., - input: Optional[Any] = ... - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - - class azure.ai.projects.models.IsolationKeySource(_Model): - kind: str - - @overload - def __init__( - self, - *, - kind: str + agent_endpoint_id: Optional[str] = ..., + agent_name: Optional[str] = ..., + conversation: Optional[str] = ..., + input: Optional[Any] = ... ) -> None: ... @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.IsolationKeySourceKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): - ENTRA = "Entra" - HEADER = "Header" - - class azure.ai.projects.models.JobStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta): CANCELLED = "cancelled" FAILED = "failed" @@ -6225,6 +6197,7 @@ namespace azure.ai.projects.models allowed_tools: Optional[Union[list[str], MCPToolFilter]] authorization: Optional[str] connector_id: Optional[Literal["connector_dropbox", "connector_gmail", "connector_googlecalendar", "connector_googledrive", "connector_microsoftteams", "connector_outlookcalendar", "connector_outlookemail", "connector_sharepoint"]] + defer_loading: Optional[bool] headers: Optional[dict[str, str]] project_connection_id: Optional[str] require_approval: Optional[Union[MCPToolRequireApproval, Literal["always"], Literal["never"]]] @@ -6241,6 +6214,7 @@ namespace azure.ai.projects.models allowed_tools: Optional[Union[list[str], MCPToolFilter]] = ..., authorization: Optional[str] = ..., connector_id: Optional[Literal[connector_dropbox, connector_gmail, connector_googlecalendar, connector_googledrive, connector_microsoftteams, connector_outlookcalendar, connector_outlookemail, connector_sharepoint]] = ..., + defer_loading: Optional[bool] = ..., headers: Optional[dict[str, str]] = ..., project_connection_id: Optional[str] = ..., require_approval: Optional[Union[MCPToolRequireApproval, Literal[always], Literal[never]]] = ..., @@ -6286,6 +6260,45 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.MCPToolboxTool(ToolboxTool, discriminator='mcp'): + allowed_tools: Optional[Union[list[str], MCPToolFilter]] + authorization: Optional[str] + connector_id: Optional[Literal["connector_dropbox", "connector_gmail", "connector_googlecalendar", "connector_googledrive", "connector_microsoftteams", "connector_outlookcalendar", "connector_outlookemail", "connector_sharepoint"]] + defer_loading: Optional[bool] + description: str + headers: Optional[dict[str, str]] + name: str + project_connection_id: Optional[str] + require_approval: Optional[Union[MCPToolRequireApproval, Literal["always"], Literal["never"]]] + server_description: Optional[str] + server_label: str + server_url: Optional[str] + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.MCP] + + @overload + def __init__( + self, + *, + allowed_tools: Optional[Union[list[str], MCPToolFilter]] = ..., + authorization: Optional[str] = ..., + connector_id: Optional[Literal[connector_dropbox, connector_gmail, connector_googlecalendar, connector_googledrive, connector_microsoftteams, connector_outlookcalendar, connector_outlookemail, connector_sharepoint]] = ..., + defer_loading: Optional[bool] = ..., + description: Optional[str] = ..., + headers: Optional[dict[str, str]] = ..., + name: Optional[str] = ..., + project_connection_id: Optional[str] = ..., + require_approval: Optional[Union[MCPToolRequireApproval, Literal[always], Literal[never]]] = ..., + server_description: Optional[str] = ..., + server_label: str, + server_url: Optional[str] = ..., + tool_configs: Optional[dict[str, ToolConfig]] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.ManagedAgentIdentityBlueprintReference(AgentBlueprintReference, discriminator='ManagedAgentIdentityBlueprint'): blueprint_id: str type: Literal[AgentBlueprintReferenceType.MANAGED_AGENT_IDENTITY_BLUEPRINT] @@ -6323,6 +6336,9 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.McpProtocolConfiguration(_Model): + + class azure.ai.projects.models.MemoryItem(_Model): content: str kind: str @@ -6402,12 +6418,9 @@ namespace azure.ai.projects.models class azure.ai.projects.models.MemorySearchPreviewTool(Tool, discriminator='memory_search_preview'): - description: Optional[str] memory_store_name: str - name: Optional[str] scope: str search_options: Optional[MemorySearchOptions] - tool_configs: Optional[dict[str, ToolConfig]] type: Literal[ToolType.MEMORY_SEARCH_PREVIEW] update_delay: Optional[int] @@ -6415,12 +6428,9 @@ namespace azure.ai.projects.models def __init__( self, *, - description: Optional[str] = ..., memory_store_name: str, - name: Optional[str] = ..., scope: str, search_options: Optional[MemorySearchOptions] = ..., - tool_configs: Optional[dict[str, ToolConfig]] = ..., update_delay: Optional[int] = ... ) -> None: ... @@ -6449,7 +6459,7 @@ namespace azure.ai.projects.models class azure.ai.projects.models.MemoryStoreDefaultOptions(_Model): chat_summary_enabled: bool - default_ttl_seconds: Optional[int] + default_ttl_seconds: Optional[timedelta] procedural_memory_enabled: Optional[bool] user_profile_details: Optional[str] user_profile_enabled: bool @@ -6459,7 +6469,7 @@ namespace azure.ai.projects.models self, *, chat_summary_enabled: bool, - default_ttl_seconds: Optional[int] = ..., + default_ttl_seconds: Optional[timedelta] = ..., procedural_memory_enabled: Optional[bool] = ..., user_profile_details: Optional[str] = ..., user_profile_enabled: bool @@ -6631,20 +6641,14 @@ namespace azure.ai.projects.models class azure.ai.projects.models.MicrosoftFabricPreviewTool(Tool, discriminator='fabric_dataagent_preview'): - description: Optional[str] fabric_dataagent_preview: FabricDataAgentToolParameters - name: Optional[str] - tool_configs: Optional[dict[str, ToolConfig]] type: Literal[ToolType.FABRIC_DATAAGENT_PREVIEW] @overload def __init__( self, *, - description: Optional[str] = ..., - fabric_dataagent_preview: FabricDataAgentToolParameters, - name: Optional[str] = ..., - tool_configs: Optional[dict[str, ToolConfig]] = ... + fabric_dataagent_preview: FabricDataAgentToolParameters ) -> None: ... @overload @@ -6794,7 +6798,6 @@ namespace azure.ai.projects.models lora_config: Optional[LoraConfig] name: str source: Optional[ModelSourceData] - system_data: Optional[SystemDataV3] tags: Optional[dict[str, str]] version: str warnings: Optional[list[FoundryModelWarning]] @@ -6832,6 +6835,25 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.NamespaceToolParam(Tool, discriminator='namespace'): + description: str + name: str + tools: list[Union[FunctionToolParam, CustomToolParam]] + type: Literal[ToolType.NAMESPACE] + + @overload + def __init__( + self, + *, + description: str, + name: str, + tools: list[Union[FunctionToolParam, CustomToolParam]] + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.NoAuthenticationCredentials(BaseCredentials, discriminator='None'): type: Literal[CredentialType.NONE] @@ -7005,6 +7027,27 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.OpenApiToolboxTool(ToolboxTool, discriminator='openapi'): + description: str + name: str + openapi: OpenApiFunctionDefinition + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.OPENAPI] + + @overload + def __init__( + self, + *, + description: Optional[str] = ..., + name: Optional[str] = ..., + openapi: OpenApiFunctionDefinition, + tool_configs: Optional[dict[str, ToolConfig]] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.OperationState(str, Enum, metaclass=CaseInsensitiveEnumMeta): CANCELED = "Canceled" FAILED = "Failed" @@ -7013,24 +7056,16 @@ namespace azure.ai.projects.models SUCCEEDED = "Succeeded" - class azure.ai.projects.models.OptimizationAgentDefinition(_Model): - agent_name: Optional[str] + class azure.ai.projects.models.OptimizationAgentIdentifier(_Model): + agent_name: str agent_version: Optional[str] - model: Optional[str] - skills: Optional[list[dict[str, Any]]] - system_prompt: Optional[str] - tools: Optional[list[dict[str, Any]]] @overload def __init__( self, *, - agent_name: Optional[str] = ..., - agent_version: Optional[str] = ..., - model: Optional[str] = ..., - skills: Optional[list[dict[str, Any]]] = ..., - system_prompt: Optional[str] = ..., - tools: Optional[list[dict[str, Any]]] = ... + agent_name: str, + agent_version: Optional[str] = ... ) -> None: ... @overload @@ -7041,15 +7076,11 @@ namespace azure.ai.projects.models avg_score: float avg_tokens: float candidate_id: Optional[str] - config: OptimizationAgentDefinition eval_id: Optional[str] eval_run_id: Optional[str] - is_pareto_optimal: bool - mutations: dict[str, Any] + mutations: Optional[dict[str, Any]] name: str - pass_rate: float promotion: Optional[PromotionInfo] - task_scores: list[OptimizationTaskResult] @overload def __init__( @@ -7058,15 +7089,97 @@ namespace azure.ai.projects.models avg_score: float, avg_tokens: float, candidate_id: Optional[str] = ..., - config: OptimizationAgentDefinition, eval_id: Optional[str] = ..., eval_run_id: Optional[str] = ..., - is_pareto_optimal: bool, - mutations: dict[str, Any], + mutations: Optional[dict[str, Any]] = ..., + name: str, + promotion: Optional[PromotionInfo] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.OptimizationDatasetCriterion(_Model): + instruction: str + name: str + + @overload + def __init__( + self, + *, + instruction: str, + name: str + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.OptimizationDatasetInput(_Model): + type: str + + @overload + def __init__( + self, + *, + type: str + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.OptimizationDatasetInputType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + INLINE = "inline" + REFERENCE = "reference" + + + class azure.ai.projects.models.OptimizationDatasetItem(_Model): + criteria: Optional[list[OptimizationDatasetCriterion]] + desired_num_turns: Optional[int] + ground_truth: Optional[str] + query: Optional[str] + + @overload + def __init__( + self, + *, + criteria: Optional[list[OptimizationDatasetCriterion]] = ..., + desired_num_turns: Optional[int] = ..., + ground_truth: Optional[str] = ..., + query: Optional[str] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.OptimizationEvaluatorRef(_Model): + name: str + version: Optional[str] + + @overload + def __init__( + self, + *, name: str, - pass_rate: float, - promotion: Optional[PromotionInfo] = ..., - task_scores: list[OptimizationTaskResult] + version: Optional[str] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.OptimizationInlineDatasetInput(OptimizationDatasetInput, discriminator='inline'): + dataset_items: list[OptimizationDatasetItem] + type: Literal[OptimizationDatasetInputType.INLINE] + + @overload + def __init__( + self, + *, + dataset_items: list[OptimizationDatasetItem] ) -> None: ... @overload @@ -7075,14 +7188,14 @@ namespace azure.ai.projects.models class azure.ai.projects.models.OptimizationJob(_Model): created_at: datetime - dataset: Optional[DatasetInfo] error: Optional[ApiError] id: str inputs: Optional[OptimizationJobInputs] progress: Optional[OptimizationJobProgress] result: Optional[OptimizationJobResult] status: Union[str, JobStatus] - updated_at: Optional[datetime] + updated_at: datetime + warnings: Optional[list[str]] @overload def __init__( @@ -7096,30 +7209,40 @@ namespace azure.ai.projects.models class azure.ai.projects.models.OptimizationJobInputs(_Model): - agent: AgentIdentifier - evaluators: Optional[list[str]] + agent: OptimizationAgentIdentifier + evaluators: list[OptimizationEvaluatorRef] options: Optional[OptimizationOptions] - train_dataset_reference: DatasetRef - validation_dataset_reference: Optional[DatasetRef] + train_dataset: OptimizationDatasetInput + validation_dataset: Optional[OptimizationDatasetInput] @overload def __init__( self, *, - agent: AgentIdentifier, - evaluators: Optional[list[str]] = ..., + agent: OptimizationAgentIdentifier, + evaluators: list[OptimizationEvaluatorRef], options: Optional[OptimizationOptions] = ..., - train_dataset_reference: DatasetRef, - validation_dataset_reference: Optional[DatasetRef] = ... + train_dataset: OptimizationDatasetInput, + validation_dataset: Optional[OptimizationDatasetInput] = ... ) -> None: ... @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.OptimizationJobListItem(_Model): + agent: Optional[OptimizationAgentIdentifier] + created_at: datetime + error: Optional[ApiError] + id: str + progress: Optional[OptimizationJobProgress] + status: Union[str, JobStatus] + updated_at: datetime + + class azure.ai.projects.models.OptimizationJobProgress(_Model): best_score: float - current_iteration: int + candidates_completed: int elapsed_seconds: float @overload @@ -7127,7 +7250,7 @@ namespace azure.ai.projects.models self, *, best_score: float, - current_iteration: int, + candidates_completed: int, elapsed_seconds: float ) -> None: ... @@ -7136,23 +7259,17 @@ namespace azure.ai.projects.models class azure.ai.projects.models.OptimizationJobResult(_Model): - all_target_attributes_failed: Optional[bool] - baseline: Optional[OptimizationCandidate] - best: Optional[OptimizationCandidate] + baseline: Optional[str] + best: Optional[str] candidates: Optional[list[OptimizationCandidate]] - options: Optional[OptimizationOptions] - warnings: Optional[list[str]] @overload def __init__( self, *, - all_target_attributes_failed: Optional[bool] = ..., - baseline: Optional[OptimizationCandidate] = ..., - best: Optional[OptimizationCandidate] = ..., - candidates: Optional[list[OptimizationCandidate]] = ..., - options: Optional[OptimizationOptions] = ..., - warnings: Optional[list[str]] = ... + baseline: Optional[str] = ..., + best: Optional[str] = ..., + candidates: Optional[list[OptimizationCandidate]] = ... ) -> None: ... @overload @@ -7162,7 +7279,7 @@ namespace azure.ai.projects.models class azure.ai.projects.models.OptimizationOptions(_Model): eval_model: Optional[str] evaluation_level: Optional[Union[str, EvaluationLevel]] - max_iterations: Optional[int] + max_candidates: Optional[int] optimization_config: Optional[dict[str, Any]] optimization_model: Optional[str] @@ -7172,7 +7289,7 @@ namespace azure.ai.projects.models *, eval_model: Optional[str] = ..., evaluation_level: Optional[Union[str, EvaluationLevel]] = ..., - max_iterations: Optional[int] = ..., + max_candidates: Optional[int] = ..., optimization_config: Optional[dict[str, Any]] = ..., optimization_model: Optional[str] = ... ) -> None: ... @@ -7181,34 +7298,17 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.OptimizationTaskResult(_Model): - composite_score: float - duration_seconds: float - error_message: Optional[str] - passed: bool - query: Optional[str] - rationales: Optional[dict[str, str]] - response: Optional[str] - run_id: Optional[str] - scores: dict[str, float] - task_name: str - tokens: int + class azure.ai.projects.models.OptimizationReferenceDatasetInput(OptimizationDatasetInput, discriminator='reference'): + name: str + type: Literal[OptimizationDatasetInputType.REFERENCE] + version: Optional[str] @overload def __init__( self, *, - composite_score: float, - duration_seconds: float, - error_message: Optional[str] = ..., - passed: bool, - query: Optional[str] = ..., - rationales: Optional[dict[str, str]] = ..., - response: Optional[str] = ..., - run_id: Optional[str] = ..., - scores: dict[str, float], - task_name: str, - tokens: int + name: str, + version: Optional[str] = ... ) -> None: ... @overload @@ -7306,44 +7406,6 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.PromoteCandidateRequest(_Model): - agent_name: str - agent_version: str - - @overload - def __init__( - self, - *, - agent_name: str, - agent_version: str - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - - class azure.ai.projects.models.PromoteCandidateResponse(_Model): - agent_name: str - agent_version: str - candidate_id: str - promoted_at: datetime - status: str - - @overload - def __init__( - self, - *, - agent_name: str, - agent_version: str, - candidate_id: str, - promoted_at: datetime, - status: str - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - class azure.ai.projects.models.PromotionInfo(_Model): agent_name: str agent_version: str @@ -7464,15 +7526,39 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.ProtocolConfiguration(_Model): + a2a: Optional[A2AProtocolConfiguration] + activity: Optional[ActivityProtocolConfiguration] + invocations: Optional[InvocationsProtocolConfiguration] + invocations_ws: Optional[InvocationsWsProtocolConfiguration] + mcp: Optional[McpProtocolConfiguration] + responses: Optional[ResponsesProtocolConfiguration] + + @overload + def __init__( + self, + *, + a2a: Optional[A2AProtocolConfiguration] = ..., + activity: Optional[ActivityProtocolConfiguration] = ..., + invocations: Optional[InvocationsProtocolConfiguration] = ..., + invocations_ws: Optional[InvocationsWsProtocolConfiguration] = ..., + mcp: Optional[McpProtocolConfiguration] = ..., + responses: Optional[ResponsesProtocolConfiguration] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.ProtocolVersionRecord(_Model): - protocol: Union[str, AgentProtocol] + protocol: Union[str, AgentEndpointProtocol] version: str @overload def __init__( self, *, - protocol: Union[str, AgentProtocol], + protocol: Union[str, AgentEndpointProtocol], version: str ) -> None: ... @@ -7617,14 +7703,50 @@ namespace azure.ai.projects.models key "type": Required[Literal["azure_ai_red_team"]] - class azure.ai.projects.models.RedTeamTargetConfig(_Model): - type: str + class azure.ai.projects.models.RedTeamTargetConfig(_Model): + type: str + + @overload + def __init__( + self, + *, + type: str + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.ReminderPreviewTool(Tool, discriminator='reminder_preview'): + description: Optional[str] + name: Optional[str] + type: Literal[ToolType.REMINDER_PREVIEW] + + @overload + def __init__( + self, + *, + description: Optional[str] = ..., + name: Optional[str] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.ReminderPreviewToolboxTool(ToolboxTool, discriminator='reminder_preview'): + description: str + name: str + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.REMINDER_PREVIEW] @overload def __init__( self, *, - type: str + description: Optional[str] = ..., + name: Optional[str] = ..., + tool_configs: Optional[dict[str, ToolConfig]] = ... ) -> None: ... @overload @@ -7666,6 +7788,9 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.ResponsesProtocolConfiguration(_Model): + + class azure.ai.projects.models.RiskCategory(str, Enum, metaclass=CaseInsensitiveEnumMeta): CODE_VULNERABILITY = "CodeVulnerability" HATE_UNFAIRNESS = "HateUnfairness" @@ -7769,8 +7894,9 @@ namespace azure.ai.projects.models scheduled_fire_at: Optional[datetime] session_id: Optional[str] started_at: Optional[datetime] - status: Optional[str] + status: Optional[RoutineRunStatus] task_id: Optional[str] + trigger_event_payload: Optional[dict[str, Any]] trigger_name: Optional[str] trigger_type: Optional[Union[str, RoutineTriggerType]] triggered_at: Optional[datetime] @@ -7795,8 +7921,9 @@ namespace azure.ai.projects.models scheduled_fire_at: Optional[datetime] = ..., session_id: Optional[str] = ..., started_at: Optional[datetime] = ..., - status: Optional[str] = ..., + status: Optional[RoutineRunStatus] = ..., task_id: Optional[str] = ..., + trigger_event_payload: Optional[dict[str, Any]] = ..., trigger_name: Optional[str] = ..., trigger_type: Optional[Union[str, RoutineTriggerType]] = ..., triggered_at: Optional[datetime] = ... @@ -7967,6 +8094,11 @@ namespace azure.ai.projects.models INSIGHT = "Insight" + class azure.ai.projects.models.SearchContentType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + IMAGE = "image" + TEXT = "text" + + class azure.ai.projects.models.SearchContextSize(str, Enum, metaclass=CaseInsensitiveEnumMeta): HIGH = "high" LOW = "low" @@ -8044,20 +8176,14 @@ namespace azure.ai.projects.models class azure.ai.projects.models.SharepointPreviewTool(Tool, discriminator='sharepoint_grounding_preview'): - description: Optional[str] - name: Optional[str] sharepoint_grounding_preview: SharepointGroundingToolParameters - tool_configs: Optional[dict[str, ToolConfig]] type: Literal[ToolType.SHAREPOINT_GROUNDING_PREVIEW] @overload def __init__( self, *, - description: Optional[str] = ..., - name: Optional[str] = ..., - sharepoint_grounding_preview: SharepointGroundingToolParameters, - tool_configs: Optional[dict[str, ToolConfig]] = ... + sharepoint_grounding_preview: SharepointGroundingToolParameters ) -> None: ... @overload @@ -8239,26 +8365,6 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.SystemDataV3(_Model): - created_at: Optional[datetime] - created_by: Optional[str] - created_by_type: Optional[str] - last_modified_at: Optional[datetime] - - @overload - def __init__( - self, - *, - created_at: Optional[datetime] = ..., - created_by: Optional[str] = ..., - created_by_type: Optional[str] = ..., - last_modified_at: Optional[datetime] = ... - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: ... - - class azure.ai.projects.models.TargetCompletionEvalRunDataSource(TypedDict, total=False): key "input_messages": Required[InputMessagesItemReference] key "source": Required[Union[SourceFileContent, SourceFileID]] @@ -8503,6 +8609,26 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.ToolChoiceComputer(ToolChoiceParam, discriminator='computer'): + type: Literal[ToolChoiceParamType.COMPUTER] + + @overload + def __init__(self) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.ToolChoiceComputerUse(ToolChoiceParam, discriminator='computer_use'): + type: Literal[ToolChoiceParamType.COMPUTER_USE] + + @overload + def __init__(self) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.ToolChoiceComputerUsePreview(ToolChoiceParam, discriminator='computer_use_preview'): type: Literal[ToolChoiceParamType.COMPUTER_USE_PREVIEW] @@ -8598,6 +8724,8 @@ namespace azure.ai.projects.models ALLOWED_TOOLS = "allowed_tools" APPLY_PATCH = "apply_patch" CODE_INTERPRETER = "code_interpreter" + COMPUTER = "computer" + COMPUTER_USE = "computer_use" COMPUTER_USE_PREVIEW = "computer_use_preview" CUSTOM = "custom" FILE_SEARCH = "file_search" @@ -8680,6 +8808,30 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.ToolSearchExecutionType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + CLIENT = "client" + SERVER = "server" + + + class azure.ai.projects.models.ToolSearchToolParam(Tool, discriminator='tool_search'): + description: Optional[str] + execution: Optional[Union[str, ToolSearchExecutionType]] + parameters: Optional[EmptyModelParam] + type: Literal[ToolType.TOOL_SEARCH] + + @overload + def __init__( + self, + *, + description: Optional[str] = ..., + execution: Optional[Union[str, ToolSearchExecutionType]] = ..., + parameters: Optional[EmptyModelParam] = ... + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + class azure.ai.projects.models.ToolType(str, Enum, metaclass=CaseInsensitiveEnumMeta): A2A_PREVIEW = "a2a_preview" APPLY_PATCH = "apply_patch" @@ -8690,6 +8842,7 @@ namespace azure.ai.projects.models BROWSER_AUTOMATION_PREVIEW = "browser_automation_preview" CAPTURE_STRUCTURED_OUTPUTS = "capture_structured_outputs" CODE_INTERPRETER = "code_interpreter" + COMPUTER = "computer" COMPUTER_USE_PREVIEW = "computer_use_preview" CUSTOM = "custom" FABRIC_DATAAGENT_PREVIEW = "fabric_dataagent_preview" @@ -8700,10 +8853,13 @@ namespace azure.ai.projects.models LOCAL_SHELL = "local_shell" MCP = "mcp" MEMORY_SEARCH_PREVIEW = "memory_search_preview" + NAMESPACE = "namespace" OPENAPI = "openapi" + REMINDER_PREVIEW = "reminder_preview" SHAREPOINT_GROUNDING_PREVIEW = "sharepoint_grounding_preview" SHELL = "shell" TOOLBOX_SEARCH_PREVIEW = "toolbox_search_preview" + TOOL_SEARCH = "tool_search" WEB_SEARCH = "web_search" WEB_SEARCH_PREVIEW = "web_search_preview" WORK_IQ_PREVIEW = "work_iq_preview" @@ -8760,11 +8916,11 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.ToolboxSearchPreviewTool(Tool, discriminator='toolbox_search_preview'): - description: Optional[str] - name: Optional[str] - tool_configs: Optional[dict[str, ToolConfig]] - type: Literal[ToolType.TOOLBOX_SEARCH_PREVIEW] + class azure.ai.projects.models.ToolboxSearchPreviewToolboxTool(ToolboxTool, discriminator='toolbox_search_preview'): + description: str + name: str + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.TOOLBOX_SEARCH_PREVIEW] @overload def __init__( @@ -8810,6 +8966,41 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... + class azure.ai.projects.models.ToolboxTool(_Model): + description: Optional[str] + name: Optional[str] + tool_configs: Optional[dict[str, ToolConfig]] + type: str + + @overload + def __init__( + self, + *, + description: Optional[str] = ..., + name: Optional[str] = ..., + tool_configs: Optional[dict[str, ToolConfig]] = ..., + type: str + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + + class azure.ai.projects.models.ToolboxToolType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + A2A_PREVIEW = "a2a_preview" + AZURE_AI_SEARCH = "azure_ai_search" + BROWSER_AUTOMATION_PREVIEW = "browser_automation_preview" + CODE_INTERPRETER = "code_interpreter" + FABRIC_IQ_PREVIEW = "fabric_iq_preview" + FILE_SEARCH = "file_search" + MCP = "mcp" + OPENAPI = "openapi" + REMINDER_PREVIEW = "reminder_preview" + TOOLBOX_SEARCH_PREVIEW = "toolbox_search_preview" + WEB_SEARCH = "web_search" + WORK_IQ_PREVIEW = "work_iq_preview" + + class azure.ai.projects.models.ToolboxVersionObject(_Model): created_at: datetime description: Optional[str] @@ -8818,7 +9009,7 @@ namespace azure.ai.projects.models name: str policies: Optional[ToolboxPolicies] skills: Optional[list[ToolboxSkill]] - tools: list[Tool] + tools: list[ToolboxTool] version: str @overload @@ -8832,7 +9023,7 @@ namespace azure.ai.projects.models name: str, policies: Optional[ToolboxPolicies] = ..., skills: Optional[list[ToolboxSkill]] = ..., - tools: list[Tool], + tools: list[ToolboxTool], version: str ) -> None: ... @@ -9117,6 +9308,7 @@ namespace azure.ai.projects.models class azure.ai.projects.models.WebSearchPreviewTool(Tool, discriminator='web_search_preview'): + search_content_types: Optional[list[Union[str, SearchContentType]]] search_context_size: Optional[Union[str, SearchContextSize]] type: Literal[ToolType.WEB_SEARCH_PREVIEW] user_location: Optional[ApproximateLocation] @@ -9125,6 +9317,7 @@ namespace azure.ai.projects.models def __init__( self, *, + search_content_types: Optional[list[Union[str, SearchContentType]]] = ..., search_context_size: Optional[Union[str, SearchContextSize]] = ..., user_location: Optional[ApproximateLocation] = ... ) -> None: ... @@ -9174,193 +9367,104 @@ namespace azure.ai.projects.models def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.WeeklyRecurrenceSchedule(RecurrenceSchedule, discriminator='Weekly'): - days_of_week: list[Union[str, DayOfWeek]] - type: Literal[RecurrenceType.WEEKLY] + class azure.ai.projects.models.WebSearchToolboxTool(ToolboxTool, discriminator='web_search'): + custom_search_configuration: Optional[WebSearchConfiguration] + description: str + filters: Optional[WebSearchToolFilters] + name: str + search_context_size: Optional[Literal["low", "medium", "high"]] + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.WEB_SEARCH] + user_location: Optional[WebSearchApproximateLocation] @overload def __init__( self, *, - days_of_week: list[Union[str, DayOfWeek]] + custom_search_configuration: Optional[WebSearchConfiguration] = ..., + description: Optional[str] = ..., + filters: Optional[WebSearchToolFilters] = ..., + name: Optional[str] = ..., + search_context_size: Optional[Literal[low, medium, high]] = ..., + tool_configs: Optional[dict[str, ToolConfig]] = ..., + user_location: Optional[WebSearchApproximateLocation] = ... ) -> None: ... @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.WorkIQPreviewTool(Tool, discriminator='work_iq_preview'): - description: Optional[str] - name: Optional[str] - project_connection_id: str - tool_configs: Optional[dict[str, ToolConfig]] - type: Literal[ToolType.WORK_IQ_PREVIEW] + class azure.ai.projects.models.WeeklyRecurrenceSchedule(RecurrenceSchedule, discriminator='Weekly'): + days_of_week: list[Union[str, DayOfWeek]] + type: Literal[RecurrenceType.WEEKLY] @overload def __init__( self, *, - description: Optional[str] = ..., - name: Optional[str] = ..., - project_connection_id: str, - tool_configs: Optional[dict[str, ToolConfig]] = ... + days_of_week: list[Union[str, DayOfWeek]] ) -> None: ... @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... - class azure.ai.projects.models.WorkflowAgentDefinition(AgentDefinition, discriminator='workflow'): - kind: Literal[AgentKind.WORKFLOW] - rai_config: RaiConfig - workflow: Optional[str] + class azure.ai.projects.models.WorkIQPreviewTool(Tool, discriminator='work_iq_preview'): + project_connection_id: str + type: Literal[ToolType.WORK_IQ_PREVIEW] @overload def __init__( self, *, - rai_config: Optional[RaiConfig] = ..., - workflow: Optional[str] = ... + project_connection_id: str ) -> None: ... @overload def __init__(self, mapping: Mapping[str, Any]) -> None: ... -namespace azure.ai.projects.operations - - class azure.ai.projects.operations.AgentsOperations(GeneratedAgentsOperations): - - def __init__( - self, - *args, - **kwargs - ) -> None: ... - - @overload - def create_version( - self, - agent_name: str, - *, - blueprint_reference: Optional[AgentBlueprintReference] = ..., - content_type: str = "application/json", - definition: AgentDefinition, - description: Optional[str] = ..., - metadata: Optional[dict[str, str]] = ..., - **kwargs: Any - ) -> AgentVersionDetails: ... - - @overload - def create_version( - self, - agent_name: str, - body: JSON, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> AgentVersionDetails: ... - - @overload - def create_version( - self, - agent_name: str, - body: IO[bytes], - *, - content_type: str = "application/json", - **kwargs: Any - ) -> AgentVersionDetails: ... + class azure.ai.projects.models.WorkIQPreviewToolboxTool(ToolboxTool, discriminator='work_iq_preview'): + description: str + name: str + project_connection_id: str + tool_configs: dict[str, ToolConfig] + type: Literal[ToolboxToolType.WORK_IQ_PREVIEW] @overload - def create_version_from_manifest( + def __init__( self, - agent_name: str, *, - content_type: str = "application/json", description: Optional[str] = ..., - manifest_id: str, - metadata: Optional[dict[str, str]] = ..., - parameter_values: dict[str, Any], - **kwargs: Any - ) -> AgentVersionDetails: ... - - @overload - def create_version_from_manifest( - self, - agent_name: str, - body: JSON, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> AgentVersionDetails: ... - - @overload - def create_version_from_manifest( - self, - agent_name: str, - body: IO[bytes], - *, - content_type: str = "application/json", - **kwargs: Any - ) -> AgentVersionDetails: ... - - @distributed_trace - def delete( - self, - agent_name: str, - *, - force: Optional[bool] = ..., - **kwargs: Any - ) -> DeleteAgentResponse: ... - - @distributed_trace - def delete_version( - self, - agent_name: str, - agent_version: str, - *, - force: Optional[bool] = ..., - **kwargs: Any - ) -> DeleteAgentVersionResponse: ... - - @distributed_trace - def get( - self, - agent_name: str, - **kwargs: Any - ) -> AgentDetails: ... - - @distributed_trace - def get_version( - self, - agent_name: str, - agent_version: str, - **kwargs: Any - ) -> AgentVersionDetails: ... + name: Optional[str] = ..., + project_connection_id: str, + tool_configs: Optional[dict[str, ToolConfig]] = ... + ) -> None: ... - @distributed_trace - def list( - self, - *, - before: Optional[str] = ..., - kind: Optional[Union[str, AgentKind]] = ..., - limit: Optional[int] = ..., - order: Optional[Union[str, PageOrder]] = ..., - **kwargs: Any - ) -> ItemPaged[AgentDetails]: ... + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... - @distributed_trace - def list_versions( + + class azure.ai.projects.models.WorkflowAgentDefinition(AgentDefinition, discriminator='workflow'): + kind: Literal[AgentKind.WORKFLOW] + rai_config: RaiConfig + workflow: Optional[str] + + @overload + def __init__( self, - agent_name: str, *, - before: Optional[str] = ..., - limit: Optional[int] = ..., - order: Optional[Union[str, PageOrder]] = ..., - **kwargs: Any - ) -> ItemPaged[AgentVersionDetails]: ... + rai_config: Optional[RaiConfig] = ..., + workflow: Optional[str] = ... + ) -> None: ... + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: ... + + +namespace azure.ai.projects.operations - class azure.ai.projects.operations.BetaAgentsOperations(GeneratedBetaAgentsOperations): + class azure.ai.projects.operations.AgentsOperations(GeneratedAgentsOperations): def __init__( self, @@ -9368,76 +9472,69 @@ namespace azure.ai.projects.operations **kwargs ) -> None: ... - @distributed_trace - def cancel_optimization_job( - self, - job_id: str, - **kwargs: Any - ) -> OptimizationJob: ... - @overload - def create_optimization_job( + def create_session( self, - inputs: OptimizationJobInputs, + agent_name: str, *, + agent_session_id: Optional[str] = ..., content_type: str = "application/json", - operation_id: Optional[str] = ..., + version_indicator: VersionIndicator, **kwargs: Any - ) -> OptimizationJob: ... + ) -> AgentSessionResource: ... @overload - def create_optimization_job( + def create_session( self, - inputs: JSON, + agent_name: str, + body: JSON, *, content_type: str = "application/json", - operation_id: Optional[str] = ..., **kwargs: Any - ) -> OptimizationJob: ... + ) -> AgentSessionResource: ... @overload - def create_optimization_job( + def create_session( self, - inputs: IO[bytes], + agent_name: str, + body: IO[bytes], *, content_type: str = "application/json", - operation_id: Optional[str] = ..., **kwargs: Any - ) -> OptimizationJob: ... + ) -> AgentSessionResource: ... @overload - def create_session( + def create_version( self, agent_name: str, *, - agent_session_id: Optional[str] = ..., + blueprint_reference: Optional[AgentBlueprintReference] = ..., content_type: str = "application/json", - user_isolation_key: Optional[str] = ..., - version_indicator: VersionIndicator, + definition: AgentDefinition, + description: Optional[str] = ..., + metadata: Optional[dict[str, str]] = ..., **kwargs: Any - ) -> AgentSessionResource: ... + ) -> AgentVersionDetails: ... @overload - def create_session( + def create_version( self, agent_name: str, body: JSON, *, content_type: str = "application/json", - user_isolation_key: Optional[str] = ..., **kwargs: Any - ) -> AgentSessionResource: ... + ) -> AgentVersionDetails: ... @overload - def create_session( + def create_version( self, agent_name: str, body: IO[bytes], *, content_type: str = "application/json", - user_isolation_key: Optional[str] = ..., **kwargs: Any - ) -> AgentSessionResource: ... + ) -> AgentVersionDetails: ... @overload def create_version_from_code( @@ -9459,22 +9556,53 @@ namespace azure.ai.projects.operations **kwargs: Any ) -> AgentVersionDetails: ... + @overload + def create_version_from_manifest( + self, + agent_name: str, + *, + content_type: str = "application/json", + description: Optional[str] = ..., + manifest_id: str, + metadata: Optional[dict[str, str]] = ..., + parameter_values: dict[str, Any], + **kwargs: Any + ) -> AgentVersionDetails: ... + + @overload + def create_version_from_manifest( + self, + agent_name: str, + body: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> AgentVersionDetails: ... + + @overload + def create_version_from_manifest( + self, + agent_name: str, + body: IO[bytes], + *, + content_type: str = "application/json", + **kwargs: Any + ) -> AgentVersionDetails: ... + @distributed_trace - def delete_optimization_job( + def delete( self, - job_id: str, + agent_name: str, *, force: Optional[bool] = ..., **kwargs: Any - ) -> None: ... + ) -> DeleteAgentResponse: ... @distributed_trace def delete_session( self, agent_name: str, session_id: str, - *, - user_isolation_key: Optional[str] = ..., **kwargs: Any ) -> None: ... @@ -9484,80 +9612,89 @@ namespace azure.ai.projects.operations agent_name: str, agent_session_id: str, *, - path: str, recursive: Optional[bool] = ..., - user_isolation_key: Optional[str] = ..., + remote_path: str, **kwargs: Any ) -> None: ... @distributed_trace - def download_code( + def delete_version( self, agent_name: str, + agent_version: str, *, - agent_version: Optional[str] = ..., + force: Optional[bool] = ..., **kwargs: Any - ) -> Iterator[bytes]: ... + ) -> DeleteAgentVersionResponse: ... @distributed_trace - def download_session_file( + def disable( + self, + agent_name: str, + **kwargs: Any + ) -> None: ... + + @distributed_trace + def download_code_as_bytes( self, agent_name: str, - agent_session_id: str, *, - path: str, - user_isolation_key: Optional[str] = ..., + agent_version: Optional[str] = ..., **kwargs: Any ) -> Iterator[bytes]: ... @distributed_trace - def get_candidate_file( + def download_code_to_path( self, - job_id: str, - candidate_id: str, + agent_name: str, *, - path: str, + agent_version: Optional[str] = ..., + file_path: Union[str, PathLike[str]], + overwrite: bool = False, **kwargs: Any - ) -> Iterator[bytes]: ... + ) -> str: ... @distributed_trace - def get_optimization_candidate( + def download_session_file_as_bytes( self, - job_id: str, - candidate_id: str, + agent_name: str, + agent_session_id: str, + *, + remote_path: str, **kwargs: Any - ) -> CandidateMetadata: ... + ) -> Iterator[bytes]: ... @distributed_trace - def get_optimization_candidate_config( + def download_session_file_to_path( self, - job_id: str, - candidate_id: str, + agent_name: str, + session_id: str, + *, + file_path: Union[str, PathLike[str]], + overwrite: bool = False, + remote_path: str, **kwargs: Any - ) -> CandidateDeployConfig: ... + ) -> None: ... @distributed_trace - def get_optimization_candidate_results( + def enable( self, - job_id: str, - candidate_id: str, + agent_name: str, **kwargs: Any - ) -> CandidateResults: ... + ) -> None: ... @distributed_trace - def get_optimization_job( + def get( self, - job_id: str, + agent_name: str, **kwargs: Any - ) -> OptimizationJob: ... + ) -> AgentDetails: ... @distributed_trace def get_session( self, agent_name: str, session_id: str, - *, - user_isolation_key: Optional[str] = ..., **kwargs: Any ) -> AgentSessionResource: ... @@ -9571,28 +9708,23 @@ namespace azure.ai.projects.operations ) -> SessionLogEvent: ... @distributed_trace - def list_optimization_candidates( + def get_version( self, - job_id: str, - *, - after: Optional[str] = ..., - before: Optional[str] = ..., - limit: Optional[int] = ..., - order: Optional[Union[str, PageOrder]] = ..., + agent_name: str, + agent_version: str, **kwargs: Any - ) -> AgentsPagedResultOptimizationCandidate: ... + ) -> AgentVersionDetails: ... @distributed_trace - def list_optimization_jobs( + def list( self, *, - agent_name: Optional[str] = ..., before: Optional[str] = ..., + kind: Optional[Union[str, AgentKind]] = ..., limit: Optional[int] = ..., order: Optional[Union[str, PageOrder]] = ..., - status: Optional[Union[str, JobStatus]] = ..., **kwargs: Any - ) -> ItemPaged[OptimizationJob]: ... + ) -> ItemPaged[AgentDetails]: ... @distributed_trace def list_session_files( @@ -9603,8 +9735,7 @@ namespace azure.ai.projects.operations before: Optional[str] = ..., limit: Optional[int] = ..., order: Optional[Union[str, PageOrder]] = ..., - path: Optional[str] = ..., - user_isolation_key: Optional[str] = ..., + remote_path: Optional[str] = ..., **kwargs: Any ) -> ItemPaged[SessionDirectoryEntry]: ... @@ -9616,12 +9747,31 @@ namespace azure.ai.projects.operations before: Optional[str] = ..., limit: Optional[int] = ..., order: Optional[Union[str, PageOrder]] = ..., - user_isolation_key: Optional[str] = ..., **kwargs: Any ) -> ItemPaged[AgentSessionResource]: ... + @distributed_trace + def list_versions( + self, + agent_name: str, + *, + before: Optional[str] = ..., + include_drafts: Optional[bool] = ..., + limit: Optional[int] = ..., + order: Optional[Union[str, PageOrder]] = ..., + **kwargs: Any + ) -> ItemPaged[AgentVersionDetails]: ... + + @distributed_trace + def stop_session( + self, + agent_name: str, + session_id: str, + **kwargs: Any + ) -> None: ... + @overload - def patch_agent_details( + def update_details( self, agent_name: str, *, @@ -9632,7 +9782,7 @@ namespace azure.ai.projects.operations ) -> AgentDetails: ... @overload - def patch_agent_details( + def update_details( self, agent_name: str, body: JSON, @@ -9642,7 +9792,7 @@ namespace azure.ai.projects.operations ) -> AgentDetails: ... @overload - def patch_agent_details( + def update_details( self, agent_name: str, body: IO[bytes], @@ -9652,56 +9802,98 @@ namespace azure.ai.projects.operations ) -> AgentDetails: ... @overload - def promote_candidate( + def upload_session_file( + self, + agent_name: str, + session_id: str, + *, + content: bytes, + remote_path: str, + **kwargs: Any + ) -> SessionFileWriteResult: ... + + @overload + def upload_session_file( + self, + agent_name: str, + session_id: str, + *, + file_path: Union[str, PathLike[str]], + remote_path: str, + **kwargs: Any + ) -> SessionFileWriteResult: ... + + + class azure.ai.projects.operations.BetaAgentsOperations: + + def __init__( + self, + *args, + **kwargs + ) -> None: ... + + @distributed_trace + def cancel_optimization_job( self, job_id: str, - candidate_id: str, - candidate_request: PromoteCandidateRequest, + **kwargs: Any + ) -> OptimizationJob: ... + + @overload + def create_optimization_job( + self, + job: OptimizationJob, *, content_type: str = "application/json", + operation_id: Optional[str] = ..., **kwargs: Any - ) -> PromoteCandidateResponse: ... + ) -> OptimizationJob: ... @overload - def promote_candidate( + def create_optimization_job( self, - job_id: str, - candidate_id: str, - candidate_request: JSON, + job: JSON, *, content_type: str = "application/json", + operation_id: Optional[str] = ..., **kwargs: Any - ) -> PromoteCandidateResponse: ... + ) -> OptimizationJob: ... @overload - def promote_candidate( + def create_optimization_job( self, - job_id: str, - candidate_id: str, - candidate_request: IO[bytes], + job: IO[bytes], *, content_type: str = "application/json", + operation_id: Optional[str] = ..., **kwargs: Any - ) -> PromoteCandidateResponse: ... + ) -> OptimizationJob: ... @distributed_trace - def stop_session( + def delete_optimization_job( self, - agent_name: str, - session_id: str, + job_id: str, + **kwargs: Any + ) -> None: ... + + @distributed_trace + def get_optimization_job( + self, + job_id: str, **kwargs: Any - ) -> None: ... + ) -> OptimizationJob: ... @distributed_trace - def upload_session_file( + def list_optimization_jobs( self, - agent_name: str, - session_id: str, - content_or_file_path: bytes | str, *, - path: str, + agent_name: Optional[str] = ..., + before: Optional[str] = ..., + limit: Optional[int] = ..., + order: Optional[Union[str, PageOrder]] = ..., + status: Optional[Union[str, JobStatus]] = ..., **kwargs: Any - ) -> SessionFileWriteResult: ... + ) -> ItemPaged[OptimizationJobListItem]: ... class azure.ai.projects.operations.BetaDatasetsOperations: @@ -10685,7 +10877,6 @@ namespace azure.ai.projects.operations routines: BetaRoutinesOperations schedules: BetaSchedulesOperations skills: BetaSkillsOperations - toolboxes: BetaToolboxesOperations def __init__( self, @@ -11094,130 +11285,6 @@ namespace azure.ai.projects.operations ) -> SkillDetails: ... - class azure.ai.projects.operations.BetaToolboxesOperations: - - def __init__( - self, - *args, - **kwargs - ) -> None: ... - - @overload - def create_version( - self, - name: str, - *, - content_type: str = "application/json", - description: Optional[str] = ..., - metadata: Optional[dict[str, str]] = ..., - policies: Optional[ToolboxPolicies] = ..., - skills: Optional[List[ToolboxSkill]] = ..., - tools: List[Tool], - **kwargs: Any - ) -> ToolboxVersionObject: ... - - @overload - def create_version( - self, - name: str, - body: JSON, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> ToolboxVersionObject: ... - - @overload - def create_version( - self, - name: str, - body: IO[bytes], - *, - content_type: str = "application/json", - **kwargs: Any - ) -> ToolboxVersionObject: ... - - @distributed_trace - def delete( - self, - name: str, - **kwargs: Any - ) -> None: ... - - @distributed_trace - def delete_version( - self, - name: str, - version: str, - **kwargs: Any - ) -> None: ... - - @distributed_trace - def get( - self, - name: str, - **kwargs: Any - ) -> ToolboxObject: ... - - @distributed_trace - def get_version( - self, - name: str, - version: str, - **kwargs: Any - ) -> ToolboxVersionObject: ... - - @distributed_trace - def list( - self, - *, - before: Optional[str] = ..., - limit: Optional[int] = ..., - order: Optional[Union[str, PageOrder]] = ..., - **kwargs: Any - ) -> ItemPaged[ToolboxObject]: ... - - @distributed_trace - def list_versions( - self, - name: str, - *, - before: Optional[str] = ..., - limit: Optional[int] = ..., - order: Optional[Union[str, PageOrder]] = ..., - **kwargs: Any - ) -> ItemPaged[ToolboxVersionObject]: ... - - @overload - def update( - self, - name: str, - *, - content_type: str = "application/json", - default_version: str, - **kwargs: Any - ) -> ToolboxObject: ... - - @overload - def update( - self, - name: str, - body: JSON, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> ToolboxObject: ... - - @overload - def update( - self, - name: str, - body: IO[bytes], - *, - content_type: str = "application/json", - **kwargs: Any - ) -> ToolboxObject: ... - - class azure.ai.projects.operations.ConnectionsOperations(ConnectionsOperationsGenerated): def __init__( @@ -11551,6 +11618,130 @@ namespace azure.ai.projects.operations def get_application_insights_connection_string(self) -> str: ... + class azure.ai.projects.operations.ToolboxesOperations: + + def __init__( + self, + *args, + **kwargs + ) -> None: ... + + @overload + def create_version( + self, + name: str, + *, + content_type: str = "application/json", + description: Optional[str] = ..., + metadata: Optional[dict[str, str]] = ..., + policies: Optional[ToolboxPolicies] = ..., + skills: Optional[List[ToolboxSkill]] = ..., + tools: List[ToolboxTool], + **kwargs: Any + ) -> ToolboxVersionObject: ... + + @overload + def create_version( + self, + name: str, + body: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> ToolboxVersionObject: ... + + @overload + def create_version( + self, + name: str, + body: IO[bytes], + *, + content_type: str = "application/json", + **kwargs: Any + ) -> ToolboxVersionObject: ... + + @distributed_trace + def delete( + self, + name: str, + **kwargs: Any + ) -> None: ... + + @distributed_trace + def delete_version( + self, + name: str, + version: str, + **kwargs: Any + ) -> None: ... + + @distributed_trace + def get( + self, + name: str, + **kwargs: Any + ) -> ToolboxObject: ... + + @distributed_trace + def get_version( + self, + name: str, + version: str, + **kwargs: Any + ) -> ToolboxVersionObject: ... + + @distributed_trace + def list( + self, + *, + before: Optional[str] = ..., + limit: Optional[int] = ..., + order: Optional[Union[str, PageOrder]] = ..., + **kwargs: Any + ) -> ItemPaged[ToolboxObject]: ... + + @distributed_trace + def list_versions( + self, + name: str, + *, + before: Optional[str] = ..., + limit: Optional[int] = ..., + order: Optional[Union[str, PageOrder]] = ..., + **kwargs: Any + ) -> ItemPaged[ToolboxVersionObject]: ... + + @overload + def update( + self, + name: str, + *, + content_type: str = "application/json", + default_version: str, + **kwargs: Any + ) -> ToolboxObject: ... + + @overload + def update( + self, + name: str, + body: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> ToolboxObject: ... + + @overload + def update( + self, + name: str, + body: IO[bytes], + *, + content_type: str = "application/json", + **kwargs: Any + ) -> ToolboxObject: ... + + namespace azure.ai.projects.telemetry def azure.ai.projects.telemetry.trace_function(span_name: Optional[str] = None) -> Callable: ... diff --git a/sdk/ai/azure-ai-projects/api.metadata.yml b/sdk/ai/azure-ai-projects/api.metadata.yml index ccd5facdaa52..416246fd0013 100644 --- a/sdk/ai/azure-ai-projects/api.metadata.yml +++ b/sdk/ai/azure-ai-projects/api.metadata.yml @@ -1,3 +1,3 @@ -apiMdSha256: d6b4f66b877f2a9b50f166f0dc05415b4920cd56eec7506bc4efdaeef81e7b6b +apiMdSha256: 24a9a51dbe82648fdabecd93660698f32ceba6e39f8a7c4353eee2cf097c180f parserVersion: 0.3.28 pythonVersion: 3.14.3 diff --git a/sdk/ai/azure-ai-projects/apiview-properties.json b/sdk/ai/azure-ai-projects/apiview-properties.json index 9aebac269df8..e3402ae3df5d 100644 --- a/sdk/ai/azure-ai-projects/apiview-properties.json +++ b/sdk/ai/azure-ai-projects/apiview-properties.json @@ -3,6 +3,10 @@ "CrossLanguageDefinitionId": { "azure.ai.projects.models.Tool": "OpenAI.Tool", "azure.ai.projects.models.A2APreviewTool": "Azure.AI.Projects.A2APreviewTool", + "azure.ai.projects.models.ToolboxTool": "Azure.AI.Projects.ToolboxTool", + "azure.ai.projects.models.A2APreviewToolboxTool": "Azure.AI.Projects.A2APreviewToolboxTool", + "azure.ai.projects.models.A2AProtocolConfiguration": "Azure.AI.Projects.A2AProtocolConfiguration", + "azure.ai.projects.models.ActivityProtocolConfiguration": "Azure.AI.Projects.ActivityProtocolConfiguration", "azure.ai.projects.models.AgentBlueprintReference": "Azure.AI.Projects.AgentBlueprintReference", "azure.ai.projects.models.AgentCard": "Azure.AI.Projects.AgentCard", "azure.ai.projects.models.AgentCardSkill": "Azure.AI.Projects.AgentCardSkill", @@ -20,11 +24,9 @@ "azure.ai.projects.models.AgentEvaluatorGenerationJobSource": "Azure.AI.Projects.AgentEvaluatorGenerationJobSource", "azure.ai.projects.models.BaseCredentials": "Azure.AI.Projects.BaseCredentials", "azure.ai.projects.models.AgenticIdentityPreviewCredentials": "Azure.AI.Projects.AgenticIdentityPreviewCredentials", - "azure.ai.projects.models.AgentIdentifier": "Azure.AI.Projects.AgentIdentifier", "azure.ai.projects.models.AgentIdentity": "Azure.AI.Projects.AgentIdentity", "azure.ai.projects.models.AgentObjectVersions": "Azure.AI.Projects.AgentObject.versions.anonymous", "azure.ai.projects.models.AgentSessionResource": "Azure.AI.Projects.AgentSessionResource", - "azure.ai.projects.models.AgentsPagedResultOptimizationCandidate": "Azure.AI.Projects.AgentsPagedResult", "azure.ai.projects.models.EvaluationTaxonomyInput": "Azure.AI.Projects.EvaluationTaxonomyInput", "azure.ai.projects.models.AgentTaxonomyInput": "Azure.AI.Projects.AgentTaxonomyInput", "azure.ai.projects.models.AgentVersionDetails": "Azure.AI.Projects.AgentVersionObject", @@ -42,6 +44,7 @@ "azure.ai.projects.models.Index": "Azure.AI.Projects.Index", "azure.ai.projects.models.AzureAISearchIndex": "Azure.AI.Projects.AzureAISearchIndex", "azure.ai.projects.models.AzureAISearchTool": "Azure.AI.Projects.AzureAISearchTool", + "azure.ai.projects.models.AzureAISearchToolboxTool": "Azure.AI.Projects.AzureAISearchToolboxTool", "azure.ai.projects.models.AzureAISearchToolResource": "Azure.AI.Projects.AzureAISearchToolResource", "azure.ai.projects.models.AzureFunctionBinding": "Azure.AI.Projects.AzureFunctionBinding", "azure.ai.projects.models.AzureFunctionDefinition": "Azure.AI.Projects.AzureFunctionDefinition", @@ -60,13 +63,11 @@ "azure.ai.projects.models.BlobReferenceSasCredential": "Azure.AI.Projects.SasCredential", "azure.ai.projects.models.BotServiceAuthorizationScheme": "Azure.AI.Projects.BotServiceAuthorizationScheme", "azure.ai.projects.models.BotServiceRbacAuthorizationScheme": "Azure.AI.Projects.BotServiceRbacAuthorizationScheme", + "azure.ai.projects.models.BotServiceTenantAuthorizationScheme": "Azure.AI.Projects.BotServiceTenantAuthorizationScheme", "azure.ai.projects.models.BrowserAutomationPreviewTool": "Azure.AI.Projects.BrowserAutomationPreviewTool", + "azure.ai.projects.models.BrowserAutomationPreviewToolboxTool": "Azure.AI.Projects.BrowserAutomationPreviewToolboxTool", "azure.ai.projects.models.BrowserAutomationToolConnectionParameters": "Azure.AI.Projects.BrowserAutomationToolConnectionParameters", "azure.ai.projects.models.BrowserAutomationToolParameters": "Azure.AI.Projects.BrowserAutomationToolParameters", - "azure.ai.projects.models.CandidateDeployConfig": "Azure.AI.Projects.CandidateDeployConfig", - "azure.ai.projects.models.CandidateFileInfo": "Azure.AI.Projects.CandidateFileInfo", - "azure.ai.projects.models.CandidateMetadata": "Azure.AI.Projects.CandidateMetadata", - "azure.ai.projects.models.CandidateResults": "Azure.AI.Projects.CandidateResults", "azure.ai.projects.models.CaptureStructuredOutputsTool": "Azure.AI.Projects.CaptureStructuredOutputsTool", "azure.ai.projects.models.ChartCoordinate": "Azure.AI.Projects.ChartCoordinate", "azure.ai.projects.models.MemoryItem": "Azure.AI.Projects.MemoryItem", @@ -77,8 +78,10 @@ "azure.ai.projects.models.CodeBasedEvaluatorDefinition": "Azure.AI.Projects.CodeBasedEvaluatorDefinition", "azure.ai.projects.models.CodeConfiguration": "Azure.AI.Projects.CodeConfiguration", "azure.ai.projects.models.CodeInterpreterTool": "OpenAI.CodeInterpreterTool", + "azure.ai.projects.models.CodeInterpreterToolboxTool": "Azure.AI.Projects.CodeInterpreterToolboxTool", "azure.ai.projects.models.ComparisonFilter": "OpenAI.ComparisonFilter", "azure.ai.projects.models.CompoundFilter": "OpenAI.CompoundFilter", + "azure.ai.projects.models.ComputerTool": "OpenAI.ComputerTool", "azure.ai.projects.models.ComputerUsePreviewTool": "OpenAI.ComputerUsePreviewTool", "azure.ai.projects.models.Connection": "Azure.AI.Projects.Connection", "azure.ai.projects.models.FunctionShellToolParamEnvironment": "OpenAI.FunctionShellToolParamEnvironment", @@ -118,8 +121,6 @@ "azure.ai.projects.models.DatasetCredential": "Azure.AI.Projects.AssetCredentialResponse", "azure.ai.projects.models.DatasetDataGenerationJobOutput": "Azure.AI.Projects.DatasetDataGenerationJobOutput", "azure.ai.projects.models.DatasetEvaluatorGenerationJobSource": "Azure.AI.Projects.DatasetEvaluatorGenerationJobSource", - "azure.ai.projects.models.DatasetInfo": "Azure.AI.Projects.DatasetInfo", - "azure.ai.projects.models.DatasetRef": "Azure.AI.Projects.DatasetRef", "azure.ai.projects.models.DatasetReference": "Azure.AI.Projects.DatasetReference", "azure.ai.projects.models.DatasetVersion": "Azure.AI.Projects.DatasetVersion", "azure.ai.projects.models.DeleteAgentResponse": "Azure.AI.Projects.DeleteAgentResponse", @@ -132,10 +133,10 @@ "azure.ai.projects.models.Dimension": "Azure.AI.Projects.Dimension", "azure.ai.projects.models.DispatchRoutineResult": "Azure.AI.Projects.DispatchRoutineResponse", "azure.ai.projects.models.EmbeddingConfiguration": "Azure.AI.Projects.EmbeddingConfiguration", + "azure.ai.projects.models.EmptyModelParam": "OpenAI.EmptyModelParam", + "azure.ai.projects.models.EndpointBasedEvaluatorDefinition": "Azure.AI.Projects.EndpointBasedEvaluatorDefinition", "azure.ai.projects.models.EntraAuthorizationScheme": "Azure.AI.Projects.EntraAuthorizationScheme", "azure.ai.projects.models.EntraIDCredentials": "Azure.AI.Projects.EntraIDCredentials", - "azure.ai.projects.models.IsolationKeySource": "Azure.AI.Projects.IsolationKeySource", - "azure.ai.projects.models.EntraIsolationKeySource": "Azure.AI.Projects.EntraIsolationKeySource", "azure.ai.projects.models.EvalResult": "Azure.AI.Projects.EvalResult", "azure.ai.projects.models.EvalRunResultCompareItem": "Azure.AI.Projects.EvalRunResultCompareItem", "azure.ai.projects.models.EvalRunResultComparison": "Azure.AI.Projects.EvalRunResultComparison", @@ -161,11 +162,13 @@ "azure.ai.projects.models.ExternalAgentDefinition": "Azure.AI.Projects.ExternalAgentDefinition", "azure.ai.projects.models.FabricDataAgentToolParameters": "Azure.AI.Projects.FabricDataAgentToolParameters", "azure.ai.projects.models.FabricIQPreviewTool": "Azure.AI.Projects.FabricIQPreviewTool", + "azure.ai.projects.models.FabricIQPreviewToolboxTool": "Azure.AI.Projects.FabricIQPreviewToolboxTool", "azure.ai.projects.models.FieldMapping": "Azure.AI.Projects.FieldMapping", "azure.ai.projects.models.FileDataGenerationJobOutput": "Azure.AI.Projects.FileDataGenerationJobOutput", "azure.ai.projects.models.FileDataGenerationJobSource": "Azure.AI.Projects.FileDataGenerationJobSource", "azure.ai.projects.models.FileDatasetVersion": "Azure.AI.Projects.FileDatasetVersion", "azure.ai.projects.models.FileSearchTool": "OpenAI.FileSearchTool", + "azure.ai.projects.models.FileSearchToolboxTool": "Azure.AI.Projects.FileSearchToolboxTool", "azure.ai.projects.models.VersionSelectionRule": "Azure.AI.Projects.VersionSelectionRule", "azure.ai.projects.models.FixedRatioVersionSelectionRule": "Azure.AI.Projects.FixedRatioVersionSelectionRule", "azure.ai.projects.models.FolderDatasetVersion": "Azure.AI.Projects.FolderDatasetVersion", @@ -174,8 +177,8 @@ "azure.ai.projects.models.FunctionShellToolParamEnvironmentContainerReferenceParam": "OpenAI.FunctionShellToolParamEnvironmentContainerReferenceParam", "azure.ai.projects.models.FunctionShellToolParamEnvironmentLocalEnvironmentParam": "OpenAI.FunctionShellToolParamEnvironmentLocalEnvironmentParam", "azure.ai.projects.models.FunctionTool": "OpenAI.FunctionTool", + "azure.ai.projects.models.FunctionToolParam": "OpenAI.FunctionToolParam", "azure.ai.projects.models.GitHubIssueRoutineTrigger": "Azure.AI.Projects.GitHubIssueRoutineTrigger", - "azure.ai.projects.models.HeaderIsolationKeySource": "Azure.AI.Projects.HeaderIsolationKeySource", "azure.ai.projects.models.TelemetryEndpointAuth": "Azure.AI.Projects.TelemetryEndpointAuth", "azure.ai.projects.models.HeaderTelemetryEndpointAuth": "Azure.AI.Projects.HeaderTelemetryEndpointAuth", "azure.ai.projects.models.HostedAgentDefinition": "Azure.AI.Projects.HostedAgentDefinition", @@ -192,6 +195,8 @@ "azure.ai.projects.models.InsightScheduleTask": "Azure.AI.Projects.InsightScheduleTask", "azure.ai.projects.models.InsightsMetadata": "Azure.AI.Projects.InsightsMetadata", "azure.ai.projects.models.InsightSummary": "Azure.AI.Projects.InsightSummary", + "azure.ai.projects.models.InvocationsProtocolConfiguration": "Azure.AI.Projects.InvocationsProtocolConfiguration", + "azure.ai.projects.models.InvocationsWsProtocolConfiguration": "Azure.AI.Projects.InvocationsWsProtocolConfiguration", "azure.ai.projects.models.RoutineDispatchPayload": "Azure.AI.Projects.RoutineDispatchPayload", "azure.ai.projects.models.InvokeAgentInvocationsApiDispatchPayload": "Azure.AI.Projects.InvokeAgentInvocationsApiDispatchPayload", "azure.ai.projects.models.RoutineAction": "Azure.AI.Projects.RoutineAction", @@ -203,7 +208,9 @@ "azure.ai.projects.models.LoraConfig": "Azure.AI.Projects.LoraConfig", "azure.ai.projects.models.ManagedAgentIdentityBlueprintReference": "Azure.AI.Projects.ManagedAgentIdentityBlueprintReference", "azure.ai.projects.models.ManagedAzureAISearchIndex": "Azure.AI.Projects.ManagedAzureAISearchIndex", + "azure.ai.projects.models.McpProtocolConfiguration": "Azure.AI.Projects.McpProtocolConfiguration", "azure.ai.projects.models.MCPTool": "OpenAI.MCPTool", + "azure.ai.projects.models.MCPToolboxTool": "Azure.AI.Projects.MCPToolboxTool", "azure.ai.projects.models.MCPToolFilter": "OpenAI.MCPToolFilter", "azure.ai.projects.models.MCPToolRequireApproval": "OpenAI.MCPToolRequireApproval", "azure.ai.projects.models.MemoryOperation": "Azure.AI.Projects.MemoryOperation", @@ -229,6 +236,7 @@ "azure.ai.projects.models.ModelSourceData": "Azure.AI.Projects.ModelSourceData", "azure.ai.projects.models.ModelVersion": "Azure.AI.Projects.ModelVersion", "azure.ai.projects.models.MonthlyRecurrenceSchedule": "Azure.AI.Projects.MonthlyRecurrenceSchedule", + "azure.ai.projects.models.NamespaceToolParam": "OpenAI.NamespaceToolParam", "azure.ai.projects.models.NoAuthenticationCredentials": "Azure.AI.Projects.NoAuthenticationCredentials", "azure.ai.projects.models.OneTimeTrigger": "Azure.AI.Projects.OneTimeTrigger", "azure.ai.projects.models.OpenApiAuthDetails": "Azure.AI.Projects.OpenApiAuthDetails", @@ -240,33 +248,42 @@ "azure.ai.projects.models.OpenApiProjectConnectionAuthDetails": "Azure.AI.Projects.OpenApiProjectConnectionAuthDetails", "azure.ai.projects.models.OpenApiProjectConnectionSecurityScheme": "Azure.AI.Projects.OpenApiProjectConnectionSecurityScheme", "azure.ai.projects.models.OpenApiTool": "Azure.AI.Projects.OpenApiTool", - "azure.ai.projects.models.OptimizationAgentDefinition": "Azure.AI.Projects.OptimizationAgentDefinition", + "azure.ai.projects.models.OpenApiToolboxTool": "Azure.AI.Projects.OpenApiToolboxTool", + "azure.ai.projects.models.OptimizationAgentIdentifier": "Azure.AI.Projects.OptimizationAgentIdentifier", "azure.ai.projects.models.OptimizationCandidate": "Azure.AI.Projects.OptimizationCandidate", + "azure.ai.projects.models.OptimizationDatasetCriterion": "Azure.AI.Projects.OptimizationDatasetCriterion", + "azure.ai.projects.models.OptimizationDatasetInput": "Azure.AI.Projects.OptimizationDatasetInput", + "azure.ai.projects.models.OptimizationDatasetItem": "Azure.AI.Projects.OptimizationDatasetItem", + "azure.ai.projects.models.OptimizationEvaluatorRef": "Azure.AI.Projects.OptimizationEvaluatorRef", + "azure.ai.projects.models.OptimizationInlineDatasetInput": "Azure.AI.Projects.OptimizationInlineDatasetInput", "azure.ai.projects.models.OptimizationJob": "Azure.AI.Projects.OptimizationJob", "azure.ai.projects.models.OptimizationJobInputs": "Azure.AI.Projects.OptimizationJobInputs", + "azure.ai.projects.models.OptimizationJobListItem": "Azure.AI.Projects.OptimizationJobListItem", "azure.ai.projects.models.OptimizationJobProgress": "Azure.AI.Projects.OptimizationJobProgress", "azure.ai.projects.models.OptimizationJobResult": "Azure.AI.Projects.OptimizationJobResult", "azure.ai.projects.models.OptimizationOptions": "Azure.AI.Projects.OptimizationOptions", - "azure.ai.projects.models.OptimizationTaskResult": "Azure.AI.Projects.OptimizationTaskResult", + "azure.ai.projects.models.OptimizationReferenceDatasetInput": "Azure.AI.Projects.OptimizationReferenceDatasetInput", "azure.ai.projects.models.TelemetryEndpoint": "Azure.AI.Projects.TelemetryEndpoint", "azure.ai.projects.models.OtlpTelemetryEndpoint": "Azure.AI.Projects.OtlpTelemetryEndpoint", "azure.ai.projects.models.PendingUploadRequest": "Azure.AI.Projects.PendingUploadRequest", "azure.ai.projects.models.PendingUploadResponse": "Azure.AI.Projects.PendingUploadResponse", "azure.ai.projects.models.ProceduralMemoryItem": "Azure.AI.Projects.ProceduralMemoryItem", - "azure.ai.projects.models.PromoteCandidateRequest": "Azure.AI.Projects.PromoteCandidateRequest", - "azure.ai.projects.models.PromoteCandidateResponse": "Azure.AI.Projects.PromoteCandidateResponse", "azure.ai.projects.models.PromotionInfo": "Azure.AI.Projects.PromotionInfo", "azure.ai.projects.models.PromptAgentDefinition": "Azure.AI.Projects.PromptAgentDefinition", "azure.ai.projects.models.PromptAgentDefinitionTextOptions": "Azure.AI.Projects.PromptAgentDefinitionTextOptions", "azure.ai.projects.models.PromptBasedEvaluatorDefinition": "Azure.AI.Projects.PromptBasedEvaluatorDefinition", "azure.ai.projects.models.PromptDataGenerationJobSource": "Azure.AI.Projects.PromptDataGenerationJobSource", "azure.ai.projects.models.PromptEvaluatorGenerationJobSource": "Azure.AI.Projects.PromptEvaluatorGenerationJobSource", + "azure.ai.projects.models.ProtocolConfiguration": "Azure.AI.Projects.ProtocolConfiguration", "azure.ai.projects.models.ProtocolVersionRecord": "Azure.AI.Projects.ProtocolVersionRecord", "azure.ai.projects.models.RaiConfig": "Azure.AI.Projects.RaiConfig", "azure.ai.projects.models.RankingOptions": "OpenAI.RankingOptions", "azure.ai.projects.models.Reasoning": "OpenAI.Reasoning", "azure.ai.projects.models.RecurrenceTrigger": "Azure.AI.Projects.RecurrenceTrigger", "azure.ai.projects.models.RedTeam": "Azure.AI.Projects.RedTeam", + "azure.ai.projects.models.ReminderPreviewTool": "Azure.AI.Projects.ReminderPreviewTool", + "azure.ai.projects.models.ReminderPreviewToolboxTool": "Azure.AI.Projects.ReminderPreviewToolboxTool", + "azure.ai.projects.models.ResponsesProtocolConfiguration": "Azure.AI.Projects.ResponsesProtocolConfiguration", "azure.ai.projects.models.ResponseUsageInputTokensDetails": "OpenAI.ResponseUsageInputTokensDetails", "azure.ai.projects.models.ResponseUsageOutputTokensDetails": "OpenAI.ResponseUsageOutputTokensDetails", "azure.ai.projects.models.Routine": "Azure.AI.Projects.Routine", @@ -291,7 +308,6 @@ "azure.ai.projects.models.SpecificFunctionShellParam": "OpenAI.SpecificFunctionShellParam", "azure.ai.projects.models.StructuredInputDefinition": "Azure.AI.Projects.StructuredInputDefinition", "azure.ai.projects.models.StructuredOutputDefinition": "Azure.AI.Projects.StructuredOutputDefinition", - "azure.ai.projects.models.SystemDataV3": "Azure.AI.Projects.SystemDataV3", "azure.ai.projects.models.TaxonomyCategory": "Azure.AI.Projects.TaxonomyCategory", "azure.ai.projects.models.TaxonomySubCategory": "Azure.AI.Projects.TaxonomySubCategory", "azure.ai.projects.models.TelemetryConfig": "Azure.AI.Projects.TelemetryConfig", @@ -302,12 +318,14 @@ "azure.ai.projects.models.TimerRoutineTrigger": "Azure.AI.Projects.TimerRoutineTrigger", "azure.ai.projects.models.ToolboxObject": "Azure.AI.Projects.ToolboxObject", "azure.ai.projects.models.ToolboxPolicies": "Azure.AI.Projects.ToolboxPolicies", - "azure.ai.projects.models.ToolboxSearchPreviewTool": "Azure.AI.Projects.ToolboxSearchPreviewTool", + "azure.ai.projects.models.ToolboxSearchPreviewToolboxTool": "Azure.AI.Projects.ToolboxSearchPreviewToolboxTool", "azure.ai.projects.models.ToolboxSkill": "Azure.AI.Projects.ToolboxSkill", "azure.ai.projects.models.ToolboxSkillReference": "Azure.AI.Projects.ToolboxSkillReference", "azure.ai.projects.models.ToolboxVersionObject": "Azure.AI.Projects.ToolboxVersionObject", "azure.ai.projects.models.ToolChoiceAllowed": "OpenAI.ToolChoiceAllowed", "azure.ai.projects.models.ToolChoiceCodeInterpreter": "OpenAI.ToolChoiceCodeInterpreter", + "azure.ai.projects.models.ToolChoiceComputer": "OpenAI.ToolChoiceComputer", + "azure.ai.projects.models.ToolChoiceComputerUse": "OpenAI.ToolChoiceComputerUse", "azure.ai.projects.models.ToolChoiceComputerUsePreview": "OpenAI.ToolChoiceComputerUsePreview", "azure.ai.projects.models.ToolChoiceCustom": "OpenAI.ToolChoiceCustom", "azure.ai.projects.models.ToolChoiceFileSearch": "OpenAI.ToolChoiceFileSearch", @@ -319,6 +337,7 @@ "azure.ai.projects.models.ToolConfig": "Azure.AI.Projects.ToolConfig", "azure.ai.projects.models.ToolDescription": "Azure.AI.Projects.ToolDescription", "azure.ai.projects.models.ToolProjectConnection": "Azure.AI.Projects.ToolProjectConnection", + "azure.ai.projects.models.ToolSearchToolParam": "OpenAI.ToolSearchToolParam", "azure.ai.projects.models.ToolUseFineTuningDataGenerationJobOptions": "Azure.AI.Projects.ToolUseFineTuningDataGenerationJobOptions", "azure.ai.projects.models.TracesDataGenerationJobOptions": "Azure.AI.Projects.TracesDataGenerationJobOptions", "azure.ai.projects.models.TracesDataGenerationJobSource": "Azure.AI.Projects.TracesDataGenerationJobSource", @@ -333,12 +352,13 @@ "azure.ai.projects.models.WebSearchConfiguration": "Azure.AI.Projects.WebSearchConfiguration", "azure.ai.projects.models.WebSearchPreviewTool": "OpenAI.WebSearchPreviewTool", "azure.ai.projects.models.WebSearchTool": "OpenAI.WebSearchTool", + "azure.ai.projects.models.WebSearchToolboxTool": "Azure.AI.Projects.WebSearchToolboxTool", "azure.ai.projects.models.WebSearchToolFilters": "OpenAI.WebSearchToolFilters", "azure.ai.projects.models.WeeklyRecurrenceSchedule": "Azure.AI.Projects.WeeklyRecurrenceSchedule", "azure.ai.projects.models.WorkflowAgentDefinition": "Azure.AI.Projects.WorkflowAgentDefinition", "azure.ai.projects.models.WorkIQPreviewTool": "Azure.AI.Projects.WorkIQPreviewTool", - "azure.ai.projects.models.AgentObjectType": "Azure.AI.Projects.AgentObjectType", - "azure.ai.projects.models.AgentKind": "Azure.AI.Projects.AgentKind", + "azure.ai.projects.models.WorkIQPreviewToolboxTool": "Azure.AI.Projects.WorkIQPreviewToolboxTool", + "azure.ai.projects.models.EvaluationTaxonomyInputType": "Azure.AI.Projects.EvaluationTaxonomyInputType", "azure.ai.projects.models.ToolType": "OpenAI.ToolType", "azure.ai.projects.models.AzureAISearchQueryType": "Azure.AI.Projects.AzureAISearchQueryType", "azure.ai.projects.models.ContainerMemoryLimit": "OpenAI.ContainerMemoryLimit", @@ -352,36 +372,20 @@ "azure.ai.projects.models.OpenApiAuthType": "Azure.AI.Projects.OpenApiAuthType", "azure.ai.projects.models.FunctionShellToolParamEnvironmentType": "OpenAI.FunctionShellToolParamEnvironmentType", "azure.ai.projects.models.ContainerSkillType": "OpenAI.ContainerSkillType", + "azure.ai.projects.models.ToolSearchExecutionType": "OpenAI.ToolSearchExecutionType", "azure.ai.projects.models.SearchContextSize": "OpenAI.SearchContextSize", - "azure.ai.projects.models.AgentProtocol": "Azure.AI.Projects.AgentProtocol", - "azure.ai.projects.models.CodeDependencyResolution": "Azure.AI.Projects.CodeDependencyResolution", - "azure.ai.projects.models.TelemetryEndpointKind": "Azure.AI.Projects.TelemetryEndpointKind", - "azure.ai.projects.models.TelemetryDataKind": "Azure.AI.Projects.TelemetryDataKind", - "azure.ai.projects.models.TelemetryEndpointAuthType": "Azure.AI.Projects.TelemetryEndpointAuthType", - "azure.ai.projects.models.TelemetryTransportProtocol": "Azure.AI.Projects.TelemetryTransportProtocol", - "azure.ai.projects.models.ToolChoiceParamType": "OpenAI.ToolChoiceParamType", - "azure.ai.projects.models.TextResponseFormatConfigurationType": "OpenAI.TextResponseFormatConfigurationType", - "azure.ai.projects.models.AgentVersionStatus": "Azure.AI.Projects.AgentVersionStatus", - "azure.ai.projects.models.AgentBlueprintReferenceType": "Azure.AI.Projects.AgentBlueprintReferenceType", - "azure.ai.projects.models.VersionSelectorType": "Azure.AI.Projects.VersionSelectorType", - "azure.ai.projects.models.AgentEndpointProtocol": "Azure.AI.Projects.AgentEndpointProtocol", - "azure.ai.projects.models.AgentEndpointAuthorizationSchemeType": "Azure.AI.Projects.AgentEndpointAuthorizationSchemeType", - "azure.ai.projects.models.IsolationKeySourceKind": "Azure.AI.Projects.IsolationKeySourceKind", - "azure.ai.projects.models.VersionIndicatorType": "Azure.AI.Projects.VersionIndicatorType", - "azure.ai.projects.models.AgentSessionStatus": "Azure.AI.Projects.AgentSessionStatus", - "azure.ai.projects.models.PageOrder": "Azure.AI.Projects.PageOrder", - "azure.ai.projects.models.SessionLogEventType": "Azure.AI.Projects.SessionLogEventType", - "azure.ai.projects.models.JobStatus": "Azure.AI.Projects.JobStatus", - "azure.ai.projects.models.EvaluationLevel": "Azure.AI.Projects.EvaluationLevel", - "azure.ai.projects.models.EvaluationTaxonomyInputType": "Azure.AI.Projects.EvaluationTaxonomyInputType", + "azure.ai.projects.models.SearchContentType": "OpenAI.SearchContentType", "azure.ai.projects.models.RiskCategory": "Azure.AI.Projects.RiskCategory", "azure.ai.projects.models.EvaluatorType": "Azure.AI.Projects.EvaluatorType", "azure.ai.projects.models.EvaluatorCategory": "Azure.AI.Projects.EvaluatorCategory", + "azure.ai.projects.models.EvaluationLevel": "Azure.AI.Projects.EvaluationLevel", "azure.ai.projects.models.EvaluatorDefinitionType": "Azure.AI.Projects.EvaluatorDefinitionType", "azure.ai.projects.models.EvaluatorMetricType": "Azure.AI.Projects.EvaluatorMetricType", "azure.ai.projects.models.EvaluatorMetricDirection": "Azure.AI.Projects.EvaluatorMetricDirection", "azure.ai.projects.models.PendingUploadType": "Azure.AI.Projects.PendingUploadType", "azure.ai.projects.models.EvaluatorGenerationJobSourceType": "Azure.AI.Projects.EvaluatorGenerationJobSourceType", + "azure.ai.projects.models.JobStatus": "Azure.AI.Projects.JobStatus", + "azure.ai.projects.models.PageOrder": "Azure.AI.Projects.PageOrder", "azure.ai.projects.models.OperationState": "Azure.Core.Foundations.OperationState", "azure.ai.projects.models.InsightType": "Azure.AI.Projects.InsightType", "azure.ai.projects.models.SampleType": "Azure.AI.Projects.SampleType", @@ -412,6 +416,25 @@ "azure.ai.projects.models.SimpleQnAFineTuningQuestionType": "Azure.AI.Projects.SimpleQnAFineTuningQuestionType", "azure.ai.projects.models.DataGenerationJobScenario": "Azure.AI.Projects.DataGenerationJobScenario", "azure.ai.projects.models.DataGenerationJobOutputType": "Azure.AI.Projects.DataGenerationJobOutputType", + "azure.ai.projects.models.OptimizationDatasetInputType": "Azure.AI.Projects.OptimizationDatasetInputType", + "azure.ai.projects.models.AgentObjectType": "Azure.AI.Projects.AgentObjectType", + "azure.ai.projects.models.AgentState": "Azure.AI.Projects.AgentState", + "azure.ai.projects.models.AgentKind": "Azure.AI.Projects.AgentKind", + "azure.ai.projects.models.AgentEndpointProtocol": "Azure.AI.Projects.AgentEndpointProtocol", + "azure.ai.projects.models.CodeDependencyResolution": "Azure.AI.Projects.CodeDependencyResolution", + "azure.ai.projects.models.TelemetryEndpointKind": "Azure.AI.Projects.TelemetryEndpointKind", + "azure.ai.projects.models.TelemetryDataKind": "Azure.AI.Projects.TelemetryDataKind", + "azure.ai.projects.models.TelemetryEndpointAuthType": "Azure.AI.Projects.TelemetryEndpointAuthType", + "azure.ai.projects.models.TelemetryTransportProtocol": "Azure.AI.Projects.TelemetryTransportProtocol", + "azure.ai.projects.models.ToolChoiceParamType": "OpenAI.ToolChoiceParamType", + "azure.ai.projects.models.TextResponseFormatConfigurationType": "OpenAI.TextResponseFormatConfigurationType", + "azure.ai.projects.models.AgentVersionStatus": "Azure.AI.Projects.AgentVersionStatus", + "azure.ai.projects.models.AgentBlueprintReferenceType": "Azure.AI.Projects.AgentBlueprintReferenceType", + "azure.ai.projects.models.VersionSelectorType": "Azure.AI.Projects.VersionSelectorType", + "azure.ai.projects.models.AgentEndpointAuthorizationSchemeType": "Azure.AI.Projects.AgentEndpointAuthorizationSchemeType", + "azure.ai.projects.models.VersionIndicatorType": "Azure.AI.Projects.VersionIndicatorType", + "azure.ai.projects.models.AgentSessionStatus": "Azure.AI.Projects.AgentSessionStatus", + "azure.ai.projects.models.SessionLogEventType": "Azure.AI.Projects.SessionLogEventType", "azure.ai.projects.models.EvaluationRuleActionType": "Azure.AI.Projects.EvaluationRuleActionType", "azure.ai.projects.models.EvaluationRuleEventType": "Azure.AI.Projects.EvaluationRuleEventType", "azure.ai.projects.models.ConnectionType": "Azure.AI.Projects.ConnectionType", @@ -419,6 +442,7 @@ "azure.ai.projects.models.DatasetType": "Azure.AI.Projects.DatasetType", "azure.ai.projects.models.DeploymentType": "Azure.AI.Projects.DeploymentType", "azure.ai.projects.models.IndexType": "Azure.AI.Projects.IndexType", + "azure.ai.projects.models.ToolboxToolType": "Azure.AI.Projects.ToolboxToolType", "azure.ai.projects.models.MemoryStoreUpdateStatus": "Azure.AI.Projects.MemoryStoreUpdateStatus", "azure.ai.projects.operations.AgentsOperations.get": "Azure.AI.Projects.Agents.getAgent", "azure.ai.projects.aio.operations.AgentsOperations.get": "Azure.AI.Projects.Agents.getAgent", @@ -436,6 +460,34 @@ "azure.ai.projects.aio.operations.AgentsOperations.delete_version": "Azure.AI.Projects.Agents.deleteAgentVersion", "azure.ai.projects.operations.AgentsOperations.list_versions": "Azure.AI.Projects.Agents.listAgentVersions", "azure.ai.projects.aio.operations.AgentsOperations.list_versions": "Azure.AI.Projects.Agents.listAgentVersions", + "azure.ai.projects.operations.AgentsOperations.update_details": "Azure.AI.Projects.Agents.patchAgentObject", + "azure.ai.projects.aio.operations.AgentsOperations.update_details": "Azure.AI.Projects.Agents.patchAgentObject", + "azure.ai.projects.operations.AgentsOperations.create_version_from_code": "Azure.AI.Projects.Agents.createAgentVersionFromCode", + "azure.ai.projects.aio.operations.AgentsOperations.create_version_from_code": "Azure.AI.Projects.Agents.createAgentVersionFromCode", + "azure.ai.projects.operations.AgentsOperations.download_code_as_bytes": "Azure.AI.Projects.Agents.downloadAgentCode", + "azure.ai.projects.aio.operations.AgentsOperations.download_code_as_bytes": "Azure.AI.Projects.Agents.downloadAgentCode", + "azure.ai.projects.operations.AgentsOperations.enable": "Azure.AI.Projects.Agents.enableAgent", + "azure.ai.projects.aio.operations.AgentsOperations.enable": "Azure.AI.Projects.Agents.enableAgent", + "azure.ai.projects.operations.AgentsOperations.disable": "Azure.AI.Projects.Agents.disableAgent", + "azure.ai.projects.aio.operations.AgentsOperations.disable": "Azure.AI.Projects.Agents.disableAgent", + "azure.ai.projects.operations.AgentsOperations.create_session": "Azure.AI.Projects.Agents.createSession", + "azure.ai.projects.aio.operations.AgentsOperations.create_session": "Azure.AI.Projects.Agents.createSession", + "azure.ai.projects.operations.AgentsOperations.get_session": "Azure.AI.Projects.Agents.getSession", + "azure.ai.projects.aio.operations.AgentsOperations.get_session": "Azure.AI.Projects.Agents.getSession", + "azure.ai.projects.operations.AgentsOperations.delete_session": "Azure.AI.Projects.Agents.deleteSession", + "azure.ai.projects.aio.operations.AgentsOperations.delete_session": "Azure.AI.Projects.Agents.deleteSession", + "azure.ai.projects.operations.AgentsOperations.stop_session": "Azure.AI.Projects.Agents.stopSession", + "azure.ai.projects.aio.operations.AgentsOperations.stop_session": "Azure.AI.Projects.Agents.stopSession", + "azure.ai.projects.operations.AgentsOperations.list_sessions": "Azure.AI.Projects.Agents.listSessions", + "azure.ai.projects.aio.operations.AgentsOperations.list_sessions": "Azure.AI.Projects.Agents.listSessions", + "azure.ai.projects.operations.AgentsOperations.get_session_log_stream": "Azure.AI.Projects.Agents.getSessionLogStream", + "azure.ai.projects.aio.operations.AgentsOperations.get_session_log_stream": "Azure.AI.Projects.Agents.getSessionLogStream", + "azure.ai.projects.operations.AgentsOperations.download_session_file_as_bytes": "Azure.AI.Projects.AgentSessionFiles.downloadSessionFile", + "azure.ai.projects.aio.operations.AgentsOperations.download_session_file_as_bytes": "Azure.AI.Projects.AgentSessionFiles.downloadSessionFile", + "azure.ai.projects.operations.AgentsOperations.list_session_files": "Azure.AI.Projects.AgentSessionFiles.listSessionFiles", + "azure.ai.projects.aio.operations.AgentsOperations.list_session_files": "Azure.AI.Projects.AgentSessionFiles.listSessionFiles", + "azure.ai.projects.operations.AgentsOperations.delete_session_file": "Azure.AI.Projects.AgentSessionFiles.deleteSessionFile", + "azure.ai.projects.aio.operations.AgentsOperations.delete_session_file": "Azure.AI.Projects.AgentSessionFiles.deleteSessionFile", "azure.ai.projects.operations.EvaluationRulesOperations.get": "Azure.AI.Projects.EvaluationRules.get", "azure.ai.projects.aio.operations.EvaluationRulesOperations.get": "Azure.AI.Projects.EvaluationRules.get", "azure.ai.projects.operations.EvaluationRulesOperations.delete": "Azure.AI.Projects.EvaluationRules.delete", @@ -473,7 +525,23 @@ "azure.ai.projects.operations.IndexesOperations.delete": "Azure.AI.Projects.Indexes.deleteVersion", "azure.ai.projects.aio.operations.IndexesOperations.delete": "Azure.AI.Projects.Indexes.deleteVersion", "azure.ai.projects.operations.IndexesOperations.create_or_update": "Azure.AI.Projects.Indexes.createOrUpdateVersion", - "azure.ai.projects.aio.operations.IndexesOperations.create_or_update": "Azure.AI.Projects.Indexes.createOrUpdateVersion" + "azure.ai.projects.aio.operations.IndexesOperations.create_or_update": "Azure.AI.Projects.Indexes.createOrUpdateVersion", + "azure.ai.projects.operations.ToolboxesOperations.create_version": "Azure.AI.Projects.Toolboxes.createToolboxVersion", + "azure.ai.projects.aio.operations.ToolboxesOperations.create_version": "Azure.AI.Projects.Toolboxes.createToolboxVersion", + "azure.ai.projects.operations.ToolboxesOperations.get": "Azure.AI.Projects.Toolboxes.getToolbox", + "azure.ai.projects.aio.operations.ToolboxesOperations.get": "Azure.AI.Projects.Toolboxes.getToolbox", + "azure.ai.projects.operations.ToolboxesOperations.list": "Azure.AI.Projects.Toolboxes.listToolboxes", + "azure.ai.projects.aio.operations.ToolboxesOperations.list": "Azure.AI.Projects.Toolboxes.listToolboxes", + "azure.ai.projects.operations.ToolboxesOperations.list_versions": "Azure.AI.Projects.Toolboxes.listToolboxVersions", + "azure.ai.projects.aio.operations.ToolboxesOperations.list_versions": "Azure.AI.Projects.Toolboxes.listToolboxVersions", + "azure.ai.projects.operations.ToolboxesOperations.get_version": "Azure.AI.Projects.Toolboxes.getToolboxVersion", + "azure.ai.projects.aio.operations.ToolboxesOperations.get_version": "Azure.AI.Projects.Toolboxes.getToolboxVersion", + "azure.ai.projects.operations.ToolboxesOperations.update": "Azure.AI.Projects.Toolboxes.updateToolbox", + "azure.ai.projects.aio.operations.ToolboxesOperations.update": "Azure.AI.Projects.Toolboxes.updateToolbox", + "azure.ai.projects.operations.ToolboxesOperations.delete": "Azure.AI.Projects.Toolboxes.deleteToolbox", + "azure.ai.projects.aio.operations.ToolboxesOperations.delete": "Azure.AI.Projects.Toolboxes.deleteToolbox", + "azure.ai.projects.operations.ToolboxesOperations.delete_version": "Azure.AI.Projects.Toolboxes.deleteToolboxVersion", + "azure.ai.projects.aio.operations.ToolboxesOperations.delete_version": "Azure.AI.Projects.Toolboxes.deleteToolboxVersion" }, - "CrossLanguageVersion": "c44eac94eea1" + "CrossLanguageVersion": "8a30c0e05596" } \ No newline at end of file diff --git a/sdk/ai/azure-ai-projects/assets.json b/sdk/ai/azure-ai-projects/assets.json index e52797a1c639..5d024b095e2b 100644 --- a/sdk/ai/azure-ai-projects/assets.json +++ b/sdk/ai/azure-ai-projects/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "python", "TagPrefix": "python/ai/azure-ai-projects", - "Tag": "python/ai/azure-ai-projects_059be0eaf8" + "Tag": "python/ai/azure-ai-projects_9ccd20fb6a" } diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/_client.py b/sdk/ai/azure-ai-projects/azure/ai/projects/_client.py index 5a5f3b9e1d1d..508fbc18d9cd 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/_client.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/_client.py @@ -24,6 +24,7 @@ DeploymentsOperations, EvaluationRulesOperations, IndexesOperations, + ToolboxesOperations, ) if sys.version_info >= (3, 11): @@ -52,6 +53,8 @@ class AIProjectClient: # pylint: disable=too-many-instance-attributes :vartype deployments: azure.ai.projects.operations.DeploymentsOperations :ivar indexes: IndexesOperations operations :vartype indexes: azure.ai.projects.operations.IndexesOperations + :ivar toolboxes: ToolboxesOperations operations + :vartype toolboxes: azure.ai.projects.operations.ToolboxesOperations :param endpoint: Foundry Project endpoint in the form "https://{ai-services-account-name}.services.ai.azure.com/api/projects/{project-name}". If you only have one Project in your Foundry Hub, or to target the default Project in your Hub, use @@ -108,6 +111,7 @@ def __init__( self.datasets = DatasetsOperations(self._client, self._config, self._serialize, self._deserialize) self.deployments = DeploymentsOperations(self._client, self._config, self._serialize, self._deserialize) self.indexes = IndexesOperations(self._client, self._config, self._serialize, self._deserialize) + self.toolboxes = ToolboxesOperations(self._client, self._config, self._serialize, self._deserialize) def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs: Any) -> HttpResponse: """Runs the network request through the client's chained policies. diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/_patch.py b/sdk/ai/azure-ai-projects/azure/ai/projects/_patch.py index 60caaa703731..fe332adb3a45 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/_patch.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/_patch.py @@ -42,18 +42,11 @@ def _resolve_openai_base_url(config: Any, agent_name: Optional[str], kwargs: dic :type kwargs: dict :return: The base URL to use for the (Async)OpenAI client. :rtype: str - :raises ValueError: If ``agent_name`` is provided but ``allow_preview=True`` was not set. """ if "base_url" in kwargs: return kwargs.pop("base_url") if agent_name is not None: - if config.allow_preview: - return config.endpoint.rstrip("/") + f"/agents/{agent_name}/endpoint/protocols/openai" - raise ValueError( - "Calling `get_openai_client` method with an `agent_name` requires you to set `allow_preview=True`" - "\nwhen constructing the AIProjectClient. Note that preview features are under development and " - "\nsubject to change. They should not be used in production environments." - ) + return config.endpoint.rstrip("/") + f"/agents/{agent_name}/endpoint/protocols/openai" return config.endpoint.rstrip("/") + "/openai/v1" diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/_types.py b/sdk/ai/azure-ai-projects/azure/ai/projects/_types.py index 5e23b3911701..abad0c3afee4 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/_types.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/_types.py @@ -11,3 +11,4 @@ if TYPE_CHECKING: from . import models as _models Filters = Union["_models.ComparisonFilter", "_models.CompoundFilter"] +RoutineRunStatus = str diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/model_base.py b/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/model_base.py index bd5b9caf1022..a79d3782e99c 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/model_base.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/model_base.py @@ -109,6 +109,29 @@ def _serialize_bytes(o, format: typing.Optional[str] = None) -> str: return encoded +def _serialize_duration(td: timedelta, format: typing.Optional[str] = None): + """Serialize a timedelta to its wire representation. + + For the ``seconds``/``milliseconds`` encodings the value is converted to a + numeric value, otherwise it falls back to an ISO 8601 duration string. + + :param timedelta td: The timedelta to serialize. + :param str format: The duration encoding format. + :rtype: int or float or str + :return: serialized duration + """ + seconds = td.total_seconds() + if format == "duration-seconds-int": + return int(seconds) + if format == "duration-seconds-float": + return seconds + if format == "duration-milliseconds-int": + return int(seconds * 1000) + if format == "duration-milliseconds-float": + return seconds * 1000 + return _timedelta_as_isostr(td) + + def _serialize_datetime(o, format: typing.Optional[str] = None): if hasattr(o, "year") and hasattr(o, "hour"): if format == "rfc7231": @@ -301,6 +324,12 @@ def _deserialize_duration(attr): return isodate.parse_duration(attr) +def _deserialize_duration_numeric(attr, unit): + if isinstance(attr, timedelta): + return attr + return timedelta(**{unit: float(attr)}) + + def _deserialize_decimal(attr): if isinstance(attr, decimal.Decimal): return attr @@ -330,6 +359,10 @@ def _deserialize_int_as_str(attr): "unix-timestamp": _deserialize_datetime_unix_timestamp, "base64": _deserialize_bytes, "base64url": _deserialize_bytes_base64, + "duration-seconds-int": functools.partial(_deserialize_duration_numeric, unit="seconds"), + "duration-seconds-float": functools.partial(_deserialize_duration_numeric, unit="seconds"), + "duration-milliseconds-int": functools.partial(_deserialize_duration_numeric, unit="milliseconds"), + "duration-milliseconds-float": functools.partial(_deserialize_duration_numeric, unit="milliseconds"), } @@ -564,7 +597,7 @@ def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-m pass # Last, try datetime.timedelta try: - return _timedelta_as_isostr(o) + return _serialize_duration(o, format) except AttributeError: # This will be raised when it hits value.total_seconds in the method above pass diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/serialization.py b/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/serialization.py index a088671e9c51..75906e2eb77f 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/serialization.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/serialization.py @@ -520,6 +520,10 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None: "rfc-1123": Serializer.serialize_rfc, "unix-time": Serializer.serialize_unix, "duration": Serializer.serialize_duration, + "duration-seconds-int": Serializer.serialize_duration_seconds_int, + "duration-seconds-float": Serializer.serialize_duration_seconds_float, + "duration-milliseconds-int": Serializer.serialize_duration_milliseconds_int, + "duration-milliseconds-float": Serializer.serialize_duration_milliseconds_float, "date": Serializer.serialize_date, "time": Serializer.serialize_time, "decimal": Serializer.serialize_decimal, @@ -1109,6 +1113,61 @@ def serialize_duration(attr, **kwargs): # pylint: disable=unused-argument attr = isodate.parse_duration(attr) return isodate.duration_isoformat(attr) + @staticmethod + def _serialize_duration_numeric(attr, scale, as_int): + """Serialize a TimeDelta into a numeric value scaled to the wire unit. + + :param TimeDelta attr: Object to be serialized. + :param int scale: Multiplier applied to total seconds (1 for seconds, 1000 for milliseconds). + :param bool as_int: Whether to truncate the result to an int. + :rtype: int or float + :return: serialized duration + """ + if isinstance(attr, str): + attr = isodate.parse_duration(attr) + value = attr.total_seconds() * scale if isinstance(attr, datetime.timedelta) else attr + return int(value) if as_int else float(value) + + @staticmethod + def serialize_duration_seconds_int(attr, **kwargs): # pylint: disable=unused-argument + """Serialize TimeDelta object into an integer number of seconds. + + :param TimeDelta attr: Object to be serialized. + :rtype: int + :return: serialized duration + """ + return Serializer._serialize_duration_numeric(attr, 1, True) + + @staticmethod + def serialize_duration_seconds_float(attr, **kwargs): # pylint: disable=unused-argument + """Serialize TimeDelta object into a floating point number of seconds. + + :param TimeDelta attr: Object to be serialized. + :rtype: float + :return: serialized duration + """ + return Serializer._serialize_duration_numeric(attr, 1, False) + + @staticmethod + def serialize_duration_milliseconds_int(attr, **kwargs): # pylint: disable=unused-argument + """Serialize TimeDelta object into an integer number of milliseconds. + + :param TimeDelta attr: Object to be serialized. + :rtype: int + :return: serialized duration + """ + return Serializer._serialize_duration_numeric(attr, 1000, True) + + @staticmethod + def serialize_duration_milliseconds_float(attr, **kwargs): # pylint: disable=unused-argument + """Serialize TimeDelta object into a floating point number of milliseconds. + + :param TimeDelta attr: Object to be serialized. + :rtype: float + :return: serialized duration + """ + return Serializer._serialize_duration_numeric(attr, 1000, False) + @staticmethod def serialize_rfc(attr, **kwargs): # pylint: disable=unused-argument """Serialize Datetime object into RFC-1123 formatted string. @@ -1381,6 +1440,10 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None: "rfc-1123": Deserializer.deserialize_rfc, "unix-time": Deserializer.deserialize_unix, "duration": Deserializer.deserialize_duration, + "duration-seconds-int": Deserializer.deserialize_duration_seconds, + "duration-seconds-float": Deserializer.deserialize_duration_seconds, + "duration-milliseconds-int": Deserializer.deserialize_duration_milliseconds, + "duration-milliseconds-float": Deserializer.deserialize_duration_milliseconds, "date": Deserializer.deserialize_date, "time": Deserializer.deserialize_time, "decimal": Deserializer.deserialize_decimal, @@ -1393,6 +1456,10 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None: } self.deserialize_expected_types = { "duration": (isodate.Duration, datetime.timedelta), + "duration-seconds-int": (isodate.Duration, datetime.timedelta), + "duration-seconds-float": (isodate.Duration, datetime.timedelta), + "duration-milliseconds-int": (isodate.Duration, datetime.timedelta), + "duration-milliseconds-float": (isodate.Duration, datetime.timedelta), "iso-8601": (datetime.datetime), } self.dependencies: dict[str, type] = dict(classes) if classes else {} @@ -1954,6 +2021,48 @@ def deserialize_duration(attr): raise DeserializationError(msg) from err return duration + @staticmethod + def _deserialize_duration_numeric(attr, unit): + """Deserialize a numeric duration value into a TimeDelta object. + + :param float attr: response value to be deserialized. + :param str unit: The wire unit, used as the ``timedelta`` keyword + (``"seconds"`` or ``"milliseconds"``). + :return: Deserialized duration + :rtype: TimeDelta + :raises DeserializationError: if value is invalid. + """ + if isinstance(attr, ET.Element): + attr = attr.text + try: + duration = datetime.timedelta(**{unit: float(attr)}) # type: ignore + except (ValueError, OverflowError, TypeError) as err: + msg = "Cannot deserialize duration object." + raise DeserializationError(msg) from err + return duration + + @staticmethod + def deserialize_duration_seconds(attr): + """Deserialize a numeric number of seconds into a TimeDelta object. + + :param float attr: response value to be deserialized. + :return: Deserialized duration + :rtype: TimeDelta + :raises DeserializationError: if value is invalid. + """ + return Deserializer._deserialize_duration_numeric(attr, "seconds") + + @staticmethod + def deserialize_duration_milliseconds(attr): + """Deserialize a numeric number of milliseconds into a TimeDelta object. + + :param float attr: response value to be deserialized. + :return: Deserialized duration + :rtype: TimeDelta + :raises DeserializationError: if value is invalid. + """ + return Deserializer._deserialize_duration_numeric(attr, "milliseconds") + @staticmethod def deserialize_date(attr): """Deserialize ISO-8601 formatted string into Date object. diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/utils.py b/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/utils.py index dcc813297e02..c91d6470e2bf 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/utils.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/_utils/utils.py @@ -31,25 +31,21 @@ def serialize_multipart_data_entry(data_entry: Any) -> Any: def _normalize_multipart_file_entry(field_name: str, entry: Any, index: int) -> Any: - """Ensure each multipart file entry carries a filename so that it is encoded - as a file part (with ``filename=``) rather than a plain form field. - - Servers commonly distinguish multipart file parts from form-data parts by - the presence of ``filename=`` in the part's ``Content-Disposition`` header. - When callers pass bare bytes / str / IO objects (e.g. - ``Path("x.zip").read_bytes()``), the underlying HTTP client emits the part - without a filename, which several Foundry endpoints reject with errors like - "At least one file must be uploaded". This helper synthesizes a filename - from the IO object's ``name`` attribute when available, otherwise falls - back to a stable default. - - :param field_name: The multipart form field name, used as a fallback filename. - :type field_name: str - :param entry: The file entry to normalize. May be a tuple, bytes, str, or IO object. + """Ensure a multipart file entry carries a filename for Content-Disposition. + + Servers distinguish file parts from plain form fields by the presence of + ``filename=`` in the ``Content-Disposition`` header. When callers pass + bare bytes/str/IO the HTTP client omits the filename and the server may + reject the upload. This helper wraps bare values into a (filename, content) + tuple, deriving the name from IO.name when available. + + :param str field_name: The multipart field name used as a filename fallback. + :param entry: The user-provided file entry (tuple, bytes, str, or IO). :type entry: any - :param index: Position of the entry within its field's list, used to disambiguate fallback filenames. - :type index: int - :return: A ``(filename, entry)`` tuple if ``entry`` was not already a tuple, otherwise ``entry`` unchanged. + :param int index: The positional index of the entry within the field, used + to disambiguate fallback filenames when multiple entries are provided. + :return: Either the original tuple entry, or a ``(filename, content)`` tuple + wrapping the bare value. :rtype: any """ if isinstance(entry, tuple): @@ -60,7 +56,14 @@ def _normalize_multipart_file_entry(field_name: str, entry: Any, index: int) -> filename = os.path.basename(name_attr) if not filename: filename = f"{field_name}_{index}" if index else field_name - return (filename, entry) + + # Return a 3-tuple with an explicit "application/octet-stream" content type. + # A 2-tuple (filename, content) would leave the part's Content-Type unset, and + # the sdk core library only defaults to "application/octet-stream" for bare + # (non-tuple) values - a tuple bypasses that default and falls back to the + # HTTP "text/plain" default instead. Setting it explicitly preserves the + # pre-existing behavior for bare bytes/IO across all transports. + return (filename, entry, "application/octet-stream") def prepare_multipart_form_data( @@ -68,11 +71,8 @@ def prepare_multipart_form_data( ) -> list[FileType]: files: list[FileType] = [] - # Append data fields first so they appear before file parts in the encoded - # multipart body. Some streaming server-side parsers (e.g. the Foundry - # hosted-agents `create_agent_version_from_code` endpoint) require small - # JSON metadata parts to precede large binary file parts; otherwise they - # report the metadata part as missing. + # Data fields first so streaming server-side parsers see metadata before + # binary file parts. for data_field in data_fields: data_entry = body.get(data_field) if data_entry: @@ -83,7 +83,7 @@ def prepare_multipart_form_data( if isinstance(multipart_entry, list): for idx, e in enumerate(multipart_entry): files.append((multipart_field, _normalize_multipart_file_entry(multipart_field, e, idx))) - elif multipart_entry: + elif multipart_entry is not None: files.append((multipart_field, _normalize_multipart_file_entry(multipart_field, multipart_entry, 0))) return files diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/_version.py b/sdk/ai/azure-ai-projects/azure/ai/projects/_version.py index 8abefc77cabd..43994a9b16be 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/_version.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/_version.py @@ -6,4 +6,4 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -VERSION = "2.2.0" +VERSION = "2.3.0" diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/_client.py b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/_client.py index 217df480ea3a..c195fb690de2 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/_client.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/_client.py @@ -24,6 +24,7 @@ DeploymentsOperations, EvaluationRulesOperations, IndexesOperations, + ToolboxesOperations, ) if sys.version_info >= (3, 11): @@ -52,6 +53,8 @@ class AIProjectClient: # pylint: disable=too-many-instance-attributes :vartype deployments: azure.ai.projects.aio.operations.DeploymentsOperations :ivar indexes: IndexesOperations operations :vartype indexes: azure.ai.projects.aio.operations.IndexesOperations + :ivar toolboxes: ToolboxesOperations operations + :vartype toolboxes: azure.ai.projects.aio.operations.ToolboxesOperations :param endpoint: Foundry Project endpoint in the form "https://{ai-services-account-name}.services.ai.azure.com/api/projects/{project-name}". If you only have one Project in your Foundry Hub, or to target the default Project in your Hub, use @@ -108,6 +111,7 @@ def __init__( self.datasets = DatasetsOperations(self._client, self._config, self._serialize, self._deserialize) self.deployments = DeploymentsOperations(self._client, self._config, self._serialize, self._deserialize) self.indexes = IndexesOperations(self._client, self._config, self._serialize, self._deserialize) + self.toolboxes = ToolboxesOperations(self._client, self._config, self._serialize, self._deserialize) def send_request( self, request: HttpRequest, *, stream: bool = False, **kwargs: Any diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/__init__.py b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/__init__.py index 1a1c0ffec86c..d6cf67b4d8cf 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/__init__.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/__init__.py @@ -19,6 +19,7 @@ from ._operations import DatasetsOperations # type: ignore from ._operations import DeploymentsOperations # type: ignore from ._operations import IndexesOperations # type: ignore +from ._operations import ToolboxesOperations # type: ignore from ._patch import __all__ as _patch_all from ._patch import * @@ -32,6 +33,7 @@ "DatasetsOperations", "DeploymentsOperations", "IndexesOperations", + "ToolboxesOperations", ] __all__.extend([p for p in _patch_all if p not in __all__]) # pyright: ignore _patch_sdk() diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py index 118e80092cf3..d4d72560dec1 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_operations.py @@ -37,38 +37,34 @@ from ..._utils.serialization import Deserializer, Serializer from ..._utils.utils import prepare_multipart_form_data from ...operations._operations import ( + build_agents_create_session_request, + build_agents_create_version_from_code_request, build_agents_create_version_from_manifest_request, build_agents_create_version_request, build_agents_delete_request, + build_agents_delete_session_file_request, + build_agents_delete_session_request, build_agents_delete_version_request, + build_agents_disable_request, + build_agents_download_code_as_bytes_request, + build_agents_download_session_file_as_bytes_request, + build_agents_enable_request, build_agents_get_request, + build_agents_get_session_log_stream_request, + build_agents_get_session_request, build_agents_get_version_request, build_agents_list_request, + build_agents_list_session_files_request, + build_agents_list_sessions_request, build_agents_list_versions_request, + build_agents_stop_session_request, + build_agents_update_details_request, + build_agents_upload_session_file_request, build_beta_agents_cancel_optimization_job_request, build_beta_agents_create_optimization_job_request, - build_beta_agents_create_session_request, - build_beta_agents_create_version_from_code_request, build_beta_agents_delete_optimization_job_request, - build_beta_agents_delete_session_file_request, - build_beta_agents_delete_session_request, - build_beta_agents_download_code_request, - build_beta_agents_download_session_file_request, - build_beta_agents_get_candidate_file_request, - build_beta_agents_get_optimization_candidate_config_request, - build_beta_agents_get_optimization_candidate_request, - build_beta_agents_get_optimization_candidate_results_request, build_beta_agents_get_optimization_job_request, - build_beta_agents_get_session_log_stream_request, - build_beta_agents_get_session_request, - build_beta_agents_list_optimization_candidates_request, build_beta_agents_list_optimization_jobs_request, - build_beta_agents_list_session_files_request, - build_beta_agents_list_sessions_request, - build_beta_agents_patch_agent_details_request, - build_beta_agents_promote_candidate_request, - build_beta_agents_stop_session_request, - build_beta_agents_upload_session_file_request, build_beta_datasets_cancel_generation_job_request, build_beta_datasets_create_generation_job_request, build_beta_datasets_delete_generation_job_request, @@ -144,14 +140,6 @@ build_beta_skills_list_request, build_beta_skills_list_versions_request, build_beta_skills_update_request, - build_beta_toolboxes_create_version_request, - build_beta_toolboxes_delete_request, - build_beta_toolboxes_delete_version_request, - build_beta_toolboxes_get_request, - build_beta_toolboxes_get_version_request, - build_beta_toolboxes_list_request, - build_beta_toolboxes_list_versions_request, - build_beta_toolboxes_update_request, build_connections_get_request, build_connections_get_with_credentials_request, build_connections_list_request, @@ -173,6 +161,14 @@ build_indexes_get_request, build_indexes_list_request, build_indexes_list_versions_request, + build_toolboxes_create_version_request, + build_toolboxes_delete_request, + build_toolboxes_delete_version_request, + build_toolboxes_get_request, + build_toolboxes_get_version_request, + build_toolboxes_list_request, + build_toolboxes_list_versions_request, + build_toolboxes_update_request, ) from .._configuration import AIProjectClientConfiguration @@ -200,7 +196,6 @@ def __init__(self, *args, **kwargs) -> None: self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") - self.agents = BetaAgentsOperations(self._client, self._config, self._serialize, self._deserialize) self.evaluation_taxonomies = BetaEvaluationTaxonomiesOperations( self._client, self._config, self._serialize, self._deserialize ) @@ -211,12 +206,12 @@ def __init__(self, *args, **kwargs) -> None: self.red_teams = BetaRedTeamsOperations(self._client, self._config, self._serialize, self._deserialize) self.routines = BetaRoutinesOperations(self._client, self._config, self._serialize, self._deserialize) self.schedules = BetaSchedulesOperations(self._client, self._config, self._serialize, self._deserialize) - self.toolboxes = BetaToolboxesOperations(self._client, self._config, self._serialize, self._deserialize) self.skills = BetaSkillsOperations(self._client, self._config, self._serialize, self._deserialize) self.datasets = BetaDatasetsOperations(self._client, self._config, self._serialize, self._deserialize) + self.agents = BetaAgentsOperations(self._client, self._config, self._serialize, self._deserialize) -class AgentsOperations: +class AgentsOperations: # pylint: disable=too-many-public-methods """ .. warning:: **DO NOT** instantiate this class directly. @@ -235,7 +230,9 @@ def __init__(self, *args, **kwargs) -> None: @distributed_trace_async async def get(self, agent_name: str, **kwargs: Any) -> _models.AgentDetails: - """Retrieves the agent. + """Get an agent. + + Retrieves an agent definition by its unique name. :param agent_name: The name of the agent to retrieve. Required. :type agent_name: str @@ -302,7 +299,9 @@ async def get(self, agent_name: str, **kwargs: Any) -> _models.AgentDetails: async def delete( self, agent_name: str, *, force: Optional[bool] = None, **kwargs: Any ) -> _models.DeleteAgentResponse: - """Deletes an agent. For hosted agents, if any version has active sessions, the request is + """Delete an agent. + + Deletes an agent. For hosted agents, if any version has active sessions, the request is rejected with HTTP 409 unless ``force`` is set to true. When force is true, all associated sessions are cascade-deleted along with the agent and its versions. @@ -383,7 +382,9 @@ def list( before: Optional[str] = None, **kwargs: Any ) -> AsyncItemPaged["_models.AgentDetails"]: - """Returns the list of all agents. + """List agents. + + Returns a paged collection of agent resources. :keyword kind: Filter agents by kind. If not provided, all agents are returned. Known values are: "prompt", "hosted", "workflow", and "external". Default value is None. @@ -478,9 +479,12 @@ async def create_version( metadata: Optional[dict[str, str]] = None, description: Optional[str] = None, blueprint_reference: Optional[_models.AgentBlueprintReference] = None, + draft: Optional[bool] = None, **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version. + """Create an agent version. + + Creates a new version for the specified agent and returns the created version resource. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -506,6 +510,11 @@ async def create_version( :paramtype description: str :keyword blueprint_reference: The blueprint reference for the agent. Default value is None. :paramtype blueprint_reference: ~azure.ai.projects.models.AgentBlueprintReference + :keyword draft: (Preview) Whether this agent version is a draft (candidate) rather than a + release. The service defaults to ``false`` if a value is not specified by the caller. Draft + versions are recorded but excluded from default 'latest' resolution and are not auto-promoted. + Default value is None. + :paramtype draft: bool :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping :rtype: ~azure.ai.projects.models.AgentVersionDetails :raises ~azure.core.exceptions.HttpResponseError: @@ -515,7 +524,9 @@ async def create_version( async def create_version( self, agent_name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version. + """Create an agent version. + + Creates a new version for the specified agent and returns the created version resource. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -538,7 +549,9 @@ async def create_version( async def create_version( self, agent_name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version. + """Create an agent version. + + Creates a new version for the specified agent and returns the created version resource. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -567,9 +580,12 @@ async def create_version( metadata: Optional[dict[str, str]] = None, description: Optional[str] = None, blueprint_reference: Optional[_models.AgentBlueprintReference] = None, + draft: Optional[bool] = None, **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version. + """Create an agent version. + + Creates a new version for the specified agent and returns the created version resource. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -594,6 +610,11 @@ async def create_version( :paramtype description: str :keyword blueprint_reference: The blueprint reference for the agent. Default value is None. :paramtype blueprint_reference: ~azure.ai.projects.models.AgentBlueprintReference + :keyword draft: (Preview) Whether this agent version is a draft (candidate) rather than a + release. The service defaults to ``false`` if a value is not specified by the caller. Draft + versions are recorded but excluded from default 'latest' resolution and are not auto-promoted. + Default value is None. + :paramtype draft: bool :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping :rtype: ~azure.ai.projects.models.AgentVersionDetails :raises ~azure.core.exceptions.HttpResponseError: @@ -619,6 +640,7 @@ async def create_version( "blueprint_reference": blueprint_reference, "definition": definition, "description": description, + "draft": draft, "metadata": metadata, } body = {k: v for k, v in body.items() if v is not None} @@ -685,7 +707,9 @@ async def create_version_from_manifest( description: Optional[str] = None, **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version from a manifest. + """Create an agent version from manifest. + + Imports the provided manifest to create a new version for the specified agent. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -720,7 +744,9 @@ async def create_version_from_manifest( async def create_version_from_manifest( self, agent_name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version from a manifest. + """Create an agent version from manifest. + + Imports the provided manifest to create a new version for the specified agent. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -743,7 +769,9 @@ async def create_version_from_manifest( async def create_version_from_manifest( self, agent_name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version from a manifest. + """Create an agent version from manifest. + + Imports the provided manifest to create a new version for the specified agent. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -774,7 +802,9 @@ async def create_version_from_manifest( description: Optional[str] = None, **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version from a manifest. + """Create an agent version from manifest. + + Imports the provided manifest to create a new version for the specified agent. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -882,7 +912,9 @@ async def create_version_from_manifest( @distributed_trace_async async def get_version(self, agent_name: str, agent_version: str, **kwargs: Any) -> _models.AgentVersionDetails: - """Retrieves a specific version of an agent. + """Get an agent version. + + Retrieves the specified version of an agent by its agent name and version identifier. :param agent_name: The name of the agent to retrieve. Required. :type agent_name: str @@ -952,7 +984,9 @@ async def get_version(self, agent_name: str, agent_version: str, **kwargs: Any) async def delete_version( self, agent_name: str, agent_version: str, *, force: Optional[bool] = None, **kwargs: Any ) -> _models.DeleteAgentVersionResponse: - """Deletes a specific version of an agent. For hosted agents, if the version has active sessions, + """Delete an agent version. + + Deletes a specific version of an agent. For hosted agents, if the version has active sessions, the request is rejected with HTTP 409 unless ``force`` is set to true. When force is true, all sessions associated with this version are cascade-deleted. @@ -1035,9 +1069,12 @@ def list_versions( limit: Optional[int] = None, order: Optional[Union[str, _models.PageOrder]] = None, before: Optional[str] = None, + include_drafts: Optional[bool] = None, **kwargs: Any ) -> AsyncItemPaged["_models.AgentVersionDetails"]: - """Returns the list of versions of an agent. + """List agent versions. + + Returns a paged collection of versions for the specified agent. :param agent_name: The name of the agent to retrieve versions for. Required. :type agent_name: str @@ -1055,6 +1092,10 @@ def list_versions( subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str + :keyword include_drafts: (Preview) Whether to include draft versions in the listing. The + service defaults to ``false`` if a value is not specified by the caller (only non-draft + versions are returned). Default value is None. + :paramtype include_drafts: bool :return: An iterator like instance of AgentVersionDetails :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.AgentVersionDetails] :raises ~azure.core.exceptions.HttpResponseError: @@ -1080,6 +1121,7 @@ def prepare_request(_continuation_token=None): order=order, after=_continuation_token, before=before, + include_drafts=include_drafts, api_version=self._config.api_version, headers=_headers, params=_params, @@ -1121,32 +1163,98 @@ async def get_next(_continuation_token=None): return AsyncItemPaged(get_next, extract_data) + @overload + async def update_details( + self, + agent_name: str, + *, + content_type: str = "application/merge-patch+json", + agent_endpoint: Optional[_models.AgentEndpointConfig] = None, + agent_card: Optional[_models.AgentCard] = None, + **kwargs: Any + ) -> _models.AgentDetails: + """Update an agent endpoint. -class EvaluationRulesOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. + Applies a merge-patch update to the specified agent endpoint configuration. - Instead, you should access the following operations through - :class:`~azure.ai.projects.aio.AIProjectClient`'s - :attr:`evaluation_rules` attribute. - """ + :param agent_name: The name of the agent to retrieve. Required. + :type agent_name: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :keyword agent_endpoint: The endpoint configuration for the agent. Default value is None. + :paramtype agent_endpoint: ~azure.ai.projects.models.AgentEndpointConfig + :keyword agent_card: Optional agent card for the agent. Default value is None. + :paramtype agent_card: ~azure.ai.projects.models.AgentCard + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + @overload + async def update_details( + self, agent_name: str, body: JSON, *, content_type: str = "application/merge-patch+json", **kwargs: Any + ) -> _models.AgentDetails: + """Update an agent endpoint. + + Applies a merge-patch update to the specified agent endpoint configuration. + + :param agent_name: The name of the agent to retrieve. Required. + :type agent_name: str + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def update_details( + self, agent_name: str, body: IO[bytes], *, content_type: str = "application/merge-patch+json", **kwargs: Any + ) -> _models.AgentDetails: + """Update an agent endpoint. + + Applies a merge-patch update to the specified agent endpoint configuration. + + :param agent_name: The name of the agent to retrieve. Required. + :type agent_name: str + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace_async - async def get(self, id: str, **kwargs: Any) -> _models.EvaluationRule: - """Get an evaluation rule. + async def update_details( + self, + agent_name: str, + body: Union[JSON, IO[bytes]] = _Unset, + *, + agent_endpoint: Optional[_models.AgentEndpointConfig] = None, + agent_card: Optional[_models.AgentCard] = None, + **kwargs: Any + ) -> _models.AgentDetails: + """Update an agent endpoint. - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.EvaluationRule + Applies a merge-patch update to the specified agent endpoint configuration. + + :param agent_name: The name of the agent to retrieve. Required. + :type agent_name: str + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword agent_endpoint: The endpoint configuration for the agent. Default value is None. + :paramtype agent_endpoint: ~azure.ai.projects.models.AgentEndpointConfig + :keyword agent_card: Optional agent card for the agent. Default value is None. + :paramtype agent_card: ~azure.ai.projects.models.AgentCard + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -1157,14 +1265,27 @@ async def get(self, id: str, **kwargs: Any) -> _models.EvaluationRule: } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.EvaluationRule] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.AgentDetails] = kwargs.pop("cls", None) - _request = build_evaluation_rules_get_request( - id=id, + if body is _Unset: + body = {"agent_card": agent_card, "agent_endpoint": agent_endpoint} + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/merge-patch+json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_agents_update_details_request( + agent_name=agent_name, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -1188,26 +1309,113 @@ async def get(self, id: str, **kwargs: Any) -> _models.EvaluationRule: except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.EvaluationRule, response.json()) + deserialized = _deserialize(_models.AgentDetails, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore + @overload + async def create_version_from_code( + self, + agent_name: str, + content: _models.CreateAgentVersionFromCodeContent, + *, + code_zip_sha256: str, + **kwargs: Any + ) -> _models.AgentVersionDetails: + """Create an agent version from code. + + Creates a new agent version from code. Uploads the code zip and creates a new version for an + existing agent. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param content: Required. + :type content: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_version_from_code( + self, agent_name: str, content: JSON, *, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentVersionDetails: + """Create an agent version from code. + + Creates a new agent version from code. Uploads the code zip and creates a new version for an + existing agent. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param content: Required. + :type content: JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ + @distributed_trace_async - async def delete(self, id: str, **kwargs: Any) -> None: - """Delete an evaluation rule. + async def create_version_from_code( + self, + agent_name: str, + content: Union[_models.CreateAgentVersionFromCodeContent, JSON], + *, + code_zip_sha256: str, + **kwargs: Any + ) -> _models.AgentVersionDetails: + """Create an agent version from code. - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :return: None - :rtype: None + Creates a new agent version from code. Uploads the code zip and creates a new version for an + existing agent. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param content: Is either a CreateAgentVersionFromCodeContent type or a JSON type. Required. + :type content: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent or JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -1221,11 +1429,18 @@ async def delete(self, id: str, **kwargs: Any) -> None: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + cls: ClsType[_models.AgentVersionDetails] = kwargs.pop("cls", None) - _request = build_evaluation_rules_delete_request( - id=id, + _body = content.as_dict() if isinstance(content, _Model) else content + _file_fields: list[str] = ["code"] + _data_fields: list[str] = ["metadata"] + _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + + _request = build_agents_create_version_from_code_request( + agent_name=agent_name, + code_zip_sha256=code_zip_sha256, api_version=self._config.api_version, + files=_files, headers=_headers, params=_params, ) @@ -1234,87 +1449,59 @@ async def delete(self, id: str, **kwargs: Any) -> None: } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.AgentVersionDetails, response.json()) if cls: - return cls(pipeline_response, None, {}) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore - @overload - async def create_or_update( - self, id: str, evaluation_rule: _models.EvaluationRule, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.EvaluationRule: - """Create or update an evaluation rule. - - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :param evaluation_rule: Evaluation rule resource. Required. - :type evaluation_rule: ~azure.ai.projects.models.EvaluationRule - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.EvaluationRule - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def create_or_update( - self, id: str, evaluation_rule: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.EvaluationRule: - """Create or update an evaluation rule. + return deserialized # type: ignore - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :param evaluation_rule: Evaluation rule resource. Required. - :type evaluation_rule: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.EvaluationRule - :raises ~azure.core.exceptions.HttpResponseError: - """ + @distributed_trace_async + async def download_code_as_bytes( + self, agent_name: str, *, agent_version: Optional[str] = None, **kwargs: Any + ) -> AsyncIterator[bytes]: + """Download agent code. - @overload - async def create_or_update( - self, id: str, evaluation_rule: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.EvaluationRule: - """Create or update an evaluation rule. + Downloads the code zip for a code-based hosted agent. + Returns the previously-uploaded zip (``application/zip``). - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :param evaluation_rule: Evaluation rule resource. Required. - :type evaluation_rule: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.EvaluationRule - :raises ~azure.core.exceptions.HttpResponseError: - """ + If ``agent_version`` is supplied, returns that version's code zip; otherwise + returns the latest version's code zip. - @distributed_trace_async - async def create_or_update( - self, id: str, evaluation_rule: Union[_models.EvaluationRule, JSON, IO[bytes]], **kwargs: Any - ) -> _models.EvaluationRule: - """Create or update an evaluation rule. + The SHA-256 digest of the returned bytes matches the ``content_hash`` on the + resolved version's ``code_configuration``. - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :param evaluation_rule: Evaluation rule resource. Is one of the following types: - EvaluationRule, JSON, IO[bytes] Required. - :type evaluation_rule: ~azure.ai.projects.models.EvaluationRule or JSON or IO[bytes] - :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.EvaluationRule + :param agent_name: The name of the agent. Required. + :type agent_name: str + :keyword agent_version: The version of the agent whose code zip should be downloaded. + If omitted, the latest version's code zip is returned. Default value is None. + :paramtype agent_version: str + :return: AsyncIterator[bytes] + :rtype: AsyncIterator[bytes] :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -1325,24 +1512,15 @@ async def create_or_update( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.EvaluationRule] = kwargs.pop("cls", None) - - content_type = content_type or "application/json" - _content = None - if isinstance(evaluation_rule, (IOBase, bytes)): - _content = evaluation_rule - else: - _content = json.dumps(evaluation_rule, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) - _request = build_evaluation_rules_create_or_update_request( - id=id, - content_type=content_type, + _request = build_agents_download_code_as_bytes_request( + agent_name=agent_name, + agent_version=agent_version, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -1352,163 +1530,49 @@ async def create_or_update( _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = kwargs.pop("stream", True) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200, 201]: + if response.status_code not in [200]: if _stream: try: await response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.EvaluationRule, response.json()) - - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore - - return deserialized # type: ignore - - @distributed_trace - def list( - self, - *, - action_type: Optional[Union[str, _models.EvaluationRuleActionType]] = None, - agent_name: Optional[str] = None, - enabled: Optional[bool] = None, - **kwargs: Any - ) -> AsyncItemPaged["_models.EvaluationRule"]: - """List all evaluation rules. - - :keyword action_type: Filter by the type of evaluation rule. Known values are: - "continuousEvaluation" and "humanEvaluationPreview". Default value is None. - :paramtype action_type: str or ~azure.ai.projects.models.EvaluationRuleActionType - :keyword agent_name: Filter by the agent name. Default value is None. - :paramtype agent_name: str - :keyword enabled: Filter by the enabled status. Default value is None. - :paramtype enabled: bool - :return: An iterator like instance of EvaluationRule - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.EvaluationRule] - :raises ~azure.core.exceptions.HttpResponseError: - """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.EvaluationRule]] = kwargs.pop("cls", None) - - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(next_link=None): - if not next_link: - - _request = build_evaluation_rules_list_request( - action_type=action_type, - agent_name=agent_name, - enabled=enabled, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - return _request - - async def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.EvaluationRule], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, AsyncList(list_of_elem) - - async def get_next(next_link=None): - _request = prepare_request(next_link) - - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - return pipeline_response - - return AsyncItemPaged(get_next, extract_data) + raise HttpResponseError(response=response, model=error) + response_headers = {} + response_headers["x-ms-agent-version"] = self._deserialize("str", response.headers.get("x-ms-agent-version")) + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) -class ConnectionsOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. + deserialized = response.iter_bytes() if _decompress else response.iter_raw() - Instead, you should access the following operations through - :class:`~azure.ai.projects.aio.AIProjectClient`'s - :attr:`connections` attribute. - """ + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + return deserialized # type: ignore @distributed_trace_async - async def _get(self, name: str, **kwargs: Any) -> _models.Connection: - """Get a connection by name, without populating connection credentials. + async def enable(self, agent_name: str, **kwargs: Any) -> None: + """Enable an agent. - :param name: The friendly name of the connection, provided by the user. Required. - :type name: str - :return: Connection. The Connection is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Connection + Enables the specified agent, allowing it to accept new sessions and process requests. This + operation is idempotent — enabling an already-enabled agent returns success with no side + effects. + + :param agent_name: The name of the agent to enable. Required. + :type agent_name: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -1522,10 +1586,10 @@ async def _get(self, name: str, **kwargs: Any) -> _models.Connection: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.Connection] = kwargs.pop("cls", None) + cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_connections_get_request( - name=name, + _request = build_agents_enable_request( + agent_name=agent_name, api_version=self._config.api_version, headers=_headers, params=_params, @@ -1535,46 +1599,183 @@ async def _get(self, name: str, **kwargs: Any) -> _models.Connection: } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = False pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass + if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) - response_headers = {} - response_headers["x-ms-client-request-id"] = self._deserialize( - "str", response.headers.get("x-ms-client-request-id") + if cls: + return cls(pipeline_response, None, {}) # type: ignore + + @distributed_trace_async + async def disable(self, agent_name: str, **kwargs: Any) -> None: + """Disable an agent. + + Disables the specified agent, preventing it from accepting new sessions or processing requests. + Existing active sessions are allowed to drain gracefully but no new sessions can be created. + This operation is idempotent — disabling an already-disabled agent returns success with no side + effects. + + :param agent_name: The name of the agent to disable. Required. + :type agent_name: str + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[None] = kwargs.pop("cls", None) + + _request = build_agents_disable_request( + agent_name=agent_name, + api_version=self._config.api_version, + headers=_headers, + params=_params, ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.Connection, response.json()) + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return cls(pipeline_response, None, {}) # type: ignore - return deserialized # type: ignore + @overload + async def create_session( + self, + agent_name: str, + *, + version_indicator: _models.VersionIndicator, + content_type: str = "application/json", + agent_session_id: Optional[str] = None, + **kwargs: Any + ) -> _models.AgentSessionResource: + """Create a session. + + Creates a new session for an agent endpoint. The endpoint resolves the backing agent version + from ``version_indicator`` and enforces session ownership using the provided isolation key for + session-mutating operations. + + :param agent_name: The name of the agent to create a session for. Required. + :type agent_name: str + :keyword version_indicator: Determines which agent version backs the session. Required. + :paramtype version_indicator: ~azure.ai.projects.models.VersionIndicator + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword agent_session_id: Optional caller-provided session ID. If specified, it must be unique + within the agent endpoint. Auto-generated if omitted. Default value is None. + :paramtype agent_session_id: str + :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentSessionResource + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_session( + self, agent_name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AgentSessionResource: + """Create a session. + + Creates a new session for an agent endpoint. The endpoint resolves the backing agent version + from ``version_indicator`` and enforces session ownership using the provided isolation key for + session-mutating operations. + + :param agent_name: The name of the agent to create a session for. Required. + :type agent_name: str + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentSessionResource + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_session( + self, agent_name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AgentSessionResource: + """Create a session. + + Creates a new session for an agent endpoint. The endpoint resolves the backing agent version + from ``version_indicator`` and enforces session ownership using the provided isolation key for + session-mutating operations. + + :param agent_name: The name of the agent to create a session for. Required. + :type agent_name: str + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentSessionResource + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace_async - async def _get_with_credentials(self, name: str, **kwargs: Any) -> _models.Connection: - """Get a connection by name, with its connection credentials. + async def create_session( + self, + agent_name: str, + body: Union[JSON, IO[bytes]] = _Unset, + *, + version_indicator: _models.VersionIndicator = _Unset, + agent_session_id: Optional[str] = None, + **kwargs: Any + ) -> _models.AgentSessionResource: + """Create a session. - :param name: The friendly name of the connection, provided by the user. Required. - :type name: str - :return: Connection. The Connection is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Connection + Creates a new session for an agent endpoint. The endpoint resolves the backing agent version + from ``version_indicator`` and enforces session ownership using the provided isolation key for + session-mutating operations. + + :param agent_name: The name of the agent to create a session for. Required. + :type agent_name: str + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword version_indicator: Determines which agent version backs the session. Required. + :paramtype version_indicator: ~azure.ai.projects.models.VersionIndicator + :keyword agent_session_id: Optional caller-provided session ID. If specified, it must be unique + within the agent endpoint. Auto-generated if omitted. Default value is None. + :paramtype agent_session_id: str + :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentSessionResource :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -1585,14 +1786,29 @@ async def _get_with_credentials(self, name: str, **kwargs: Any) -> _models.Conne } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.Connection] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.AgentSessionResource] = kwargs.pop("cls", None) - _request = build_connections_get_with_credentials_request( - name=name, + if body is _Unset: + if version_indicator is _Unset: + raise TypeError("missing required argument: version_indicator") + body = {"agent_session_id": agent_session_id, "version_indicator": version_indicator} + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_agents_create_session_request( + agent_name=agent_name, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -1609,56 +1825,43 @@ async def _get_with_credentials(self, name: str, **kwargs: Any) -> _models.Conne response = pipeline_response.http_response - if response.status_code not in [200]: + if response.status_code not in [201]: if _stream: try: await response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - response_headers = {} - response_headers["x-ms-client-request-id"] = self._deserialize( - "str", response.headers.get("x-ms-client-request-id") - ) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.Connection, response.json()) + deserialized = _deserialize(_models.AgentSessionResource, response.json()) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - @distributed_trace - def list( - self, - *, - connection_type: Optional[Union[str, _models.ConnectionType]] = None, - default_connection: Optional[bool] = None, - **kwargs: Any - ) -> AsyncItemPaged["_models.Connection"]: - """List all connections in the project, without populating connection credentials. + @distributed_trace_async + async def get_session(self, agent_name: str, session_id: str, **kwargs: Any) -> _models.AgentSessionResource: + """Get a session. - :keyword connection_type: List connections of this specific type. Known values are: - "AzureOpenAI", "AzureBlob", "AzureStorageAccount", "CognitiveSearch", "CosmosDB", "ApiKey", - "AppConfig", "AppInsights", "CustomKeys", and "RemoteTool_Preview". Default value is None. - :paramtype connection_type: str or ~azure.ai.projects.models.ConnectionType - :keyword default_connection: List connections that are default connections. Default value is - None. - :paramtype default_connection: bool - :return: An iterator like instance of Connection - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.Connection] + Retrieves the details of a hosted agent session by agent name and session identifier. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session identifier. Required. + :type session_id: str + :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentSessionResource :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.Connection]] = kwargs.pop("cls", None) - error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -1667,108 +1870,69 @@ def list( } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(next_link=None): - if not next_link: + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - _request = build_connections_list_request( - connection_type=connection_type, - default_connection=default_connection, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + cls: ClsType[_models.AgentSessionResource] = kwargs.pop("cls", None) - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - return _request + _request = build_agents_get_session_request( + agent_name=agent_name, + session_id=session_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - async def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.Connection], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, AsyncList(list_of_elem) + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) - async def get_next(next_link=None): - _request = prepare_request(next_link) + response = pipeline_response.http_response - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - return pipeline_response - - return AsyncItemPaged(get_next, extract_data) + raise HttpResponseError(response=response, model=error) + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.AgentSessionResource, response.json()) -class DatasetsOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore - Instead, you should access the following operations through - :class:`~azure.ai.projects.aio.AIProjectClient`'s - :attr:`datasets` attribute. - """ + return deserialized # type: ignore - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + @distributed_trace_async + async def delete_session(self, agent_name: str, session_id: str, **kwargs: Any) -> None: + """Delete a session. - @distributed_trace - def list_versions(self, name: str, **kwargs: Any) -> AsyncItemPaged["_models.DatasetVersion"]: - """List all versions of the given DatasetVersion. + Deletes a session synchronously. Returns 204 No Content when the session is deleted or does not + exist. - :param name: The name of the resource. Required. - :type name: str - :return: An iterator like instance of DatasetVersion - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.DatasetVersion] + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session identifier. Required. + :type session_id: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.DatasetVersion]] = kwargs.pop("cls", None) - error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -1777,87 +1941,56 @@ def list_versions(self, name: str, **kwargs: Any) -> AsyncItemPaged["_models.Dat } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(next_link=None): - if not next_link: - - _request = build_datasets_list_versions_request( - name=name, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + cls: ClsType[None] = kwargs.pop("cls", None) - return _request + _request = build_agents_delete_session_request( + agent_name=agent_name, + session_id=session_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - async def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.DatasetVersion], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, AsyncList(list_of_elem) + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) - async def get_next(next_link=None): - _request = prepare_request(next_link) + response = pipeline_response.http_response - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + raise HttpResponseError(response=response, model=error) - return pipeline_response + if cls: + return cls(pipeline_response, None, {}) # type: ignore - return AsyncItemPaged(get_next, extract_data) + @distributed_trace_async + async def stop_session(self, agent_name: str, session_id: str, **kwargs: Any) -> None: + """Stop a session. - @distributed_trace - def list(self, **kwargs: Any) -> AsyncItemPaged["_models.DatasetVersion"]: - """List the latest version of each DatasetVersion. + Terminates the specified hosted agent session and returns 204 No Content when the request + succeeds. - :return: An iterator like instance of DatasetVersion - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.DatasetVersion] + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session identifier. Required. + :type session_id: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.DatasetVersion]] = kwargs.pop("cls", None) - error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -1866,58 +1999,118 @@ def list(self, **kwargs: Any) -> AsyncItemPaged["_models.DatasetVersion"]: } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(next_link=None): - if not next_link: - - _request = build_datasets_list_request( - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - return _request + cls: ClsType[None] = kwargs.pop("cls", None) - async def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.DatasetVersion], - deserialized.get("value", []), - ) + _request = build_agents_stop_session_request( + agent_name=agent_name, + session_id=session_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) # type: ignore + + @distributed_trace + def list_sessions( + self, + agent_name: str, + *, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + before: Optional[str] = None, + **kwargs: Any + ) -> AsyncItemPaged["_models.AgentSessionResource"]: + """List sessions for an agent. + + Returns a paged collection of sessions associated with the specified agent endpoint. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the + default is 20. Default value is None. + :paramtype limit: int + :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for + ascending order and``desc`` + for descending order. Known values are: "asc" and "desc". Default value is None. + :paramtype order: str or ~azure.ai.projects.models.PageOrder + :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your + place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + Default value is None. + :paramtype before: str + :return: An iterator like instance of AgentSessionResource + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.AgentSessionResource] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.AgentSessionResource]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(_continuation_token=None): + + _request = build_agents_list_sessions_request( + agent_name=agent_name, + limit=limit, + order=order, + after=_continuation_token, + before=before, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request + + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.AgentSessionResource], + deserialized.get("data", []), + ) if cls: list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, AsyncList(list_of_elem) + return deserialized.get("last_id") or None, AsyncList(list_of_elem) - async def get_next(next_link=None): - _request = prepare_request(next_link) + async def get_next(_continuation_token=None): + _request = prepare_request(_continuation_token) _stream = False pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access @@ -1927,23 +2120,57 @@ async def get_next(next_link=None): if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) return pipeline_response return AsyncItemPaged(get_next, extract_data) @distributed_trace_async - async def get(self, name: str, version: str, **kwargs: Any) -> _models.DatasetVersion: - """Get the specific version of the DatasetVersion. The service returns 404 Not Found error if the - DatasetVersion does not exist. + async def get_session_log_stream( + self, agent_name: str, agent_version: str, session_id: str, **kwargs: Any + ) -> _models.SessionLogEvent: + """Stream console logs for a hosted agent session. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to retrieve. Required. - :type version: str - :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetVersion + Streams console logs (stdout / stderr) for a specific hosted agent session + as a Server-Sent Events (SSE) stream. + + Each SSE frame contains: + + * `event`: always `"log"` + * `data`: a plain-text log line (currently JSON-formatted, but the schema is not contractual and may include additional keys or change format over time; clients should treat it as an opaque string) + + Example SSE frames: + + .. code-block:: + + event: log + data: {"timestamp":"2026-03-10T09:33:17.121Z","stream":"stdout","message":"Starting FoundryCBAgent server on port 8088"} + + event: log + data: {"timestamp":"2026-03-10T09:33:17.130Z","stream":"stderr","message":"INFO: Application startup complete."} + + event: log + data: {"timestamp":"2026-03-10T09:34:52.714Z","stream":"status","message":"Successfully connected to container"} + + event: log + data: {"timestamp":"2026-03-10T09:35:52.714Z","stream":"status","message":"No logs since last 60 seconds"} + + The stream remains open until the client disconnects or the server + terminates the connection. Clients should handle reconnection as needed. + + :param agent_name: The name of the hosted agent. Required. + :type agent_name: str + :param agent_version: The version of the agent. Required. + :type agent_version: str + :param session_id: The session ID (maps to an ADC sandbox). Required. + :type session_id: str + :return: SessionLogEvent. The SessionLogEvent is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SessionLogEvent :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -1957,11 +2184,12 @@ async def get(self, name: str, version: str, **kwargs: Any) -> _models.DatasetVe _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DatasetVersion] = kwargs.pop("cls", None) + cls: ClsType[_models.SessionLogEvent] = kwargs.pop("cls", None) - _request = build_datasets_get_request( - name=name, - version=version, + _request = build_agents_get_session_log_stream_request( + agent_name=agent_name, + agent_version=agent_version, + session_id=session_id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -1972,7 +2200,7 @@ async def get(self, name: str, version: str, **kwargs: Any) -> _models.DatasetVe _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = True pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -1986,29 +2214,45 @@ async def get(self, name: str, version: str, **kwargs: Any) -> _models.DatasetVe except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.DatasetVersion, response.json()) + deserialized = _deserialize(_models.SessionLogEvent, response.text()) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore @distributed_trace_async - async def delete(self, name: str, version: str, **kwargs: Any) -> None: - """Delete the specific version of the DatasetVersion. The service returns 204 No Content if the - DatasetVersion was deleted successfully or if the DatasetVersion does not exist. + async def _upload_session_file( + self, agent_name: str, agent_session_id: str, content: bytes, *, remote_path: str, **kwargs: Any + ) -> _models.SessionFileWriteResult: + """Upload a session file. - :param name: The name of the resource. Required. - :type name: str - :param version: The version of the DatasetVersion to delete. Required. - :type version: str - :return: None - :rtype: None + Uploads binary file content to the specified path in the session sandbox. The service stores + the file relative to the session home directory and rejects payloads larger than 50 MB. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param agent_session_id: The session ID. Required. + :type agent_session_id: str + :param content: Required. + :type content: bytes + :keyword remote_path: The destination file path within the sandbox, relative to the session + home directory. Required. + :paramtype remote_path: str + :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SessionFileWriteResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -2019,15 +2263,21 @@ async def delete(self, name: str, version: str, **kwargs: Any) -> None: } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + content_type: str = kwargs.pop("content_type", _headers.pop("Content-Type", "application/octet-stream")) + cls: ClsType[_models.SessionFileWriteResult] = kwargs.pop("cls", None) - _request = build_datasets_delete_request( - name=name, - version=version, + _content = content + + _request = build_agents_upload_session_file_request( + agent_name=agent_name, + agent_session_id=agent_session_id, + remote_path=remote_path, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -2036,113 +2286,55 @@ async def delete(self, name: str, version: str, **kwargs: Any) -> None: } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [201]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.SessionFileWriteResult, response.json()) if cls: - return cls(pipeline_response, None, {}) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore - @overload - async def create_or_update( - self, - name: str, - version: str, - dataset_version: _models.DatasetVersion, - *, - content_type: str = "application/merge-patch+json", - **kwargs: Any - ) -> _models.DatasetVersion: - """Create a new or update an existing DatasetVersion with the given version id. - - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to create or update. Required. - :type version: str - :param dataset_version: The DatasetVersion to create or update. Required. - :type dataset_version: ~azure.ai.projects.models.DatasetVersion - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def create_or_update( - self, - name: str, - version: str, - dataset_version: JSON, - *, - content_type: str = "application/merge-patch+json", - **kwargs: Any - ) -> _models.DatasetVersion: - """Create a new or update an existing DatasetVersion with the given version id. - - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to create or update. Required. - :type version: str - :param dataset_version: The DatasetVersion to create or update. Required. - :type dataset_version: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def create_or_update( - self, - name: str, - version: str, - dataset_version: IO[bytes], - *, - content_type: str = "application/merge-patch+json", - **kwargs: Any - ) -> _models.DatasetVersion: - """Create a new or update an existing DatasetVersion with the given version id. - - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to create or update. Required. - :type version: str - :param dataset_version: The DatasetVersion to create or update. Required. - :type dataset_version: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ + return deserialized # type: ignore @distributed_trace_async - async def create_or_update( - self, name: str, version: str, dataset_version: Union[_models.DatasetVersion, JSON, IO[bytes]], **kwargs: Any - ) -> _models.DatasetVersion: - """Create a new or update an existing DatasetVersion with the given version id. + async def download_session_file_as_bytes( + self, agent_name: str, agent_session_id: str, *, remote_path: str, **kwargs: Any + ) -> AsyncIterator[bytes]: + """Download a session file. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to create or update. Required. - :type version: str - :param dataset_version: The DatasetVersion to create or update. Is one of the following types: - DatasetVersion, JSON, IO[bytes] Required. - :type dataset_version: ~azure.ai.projects.models.DatasetVersion or JSON or IO[bytes] - :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetVersion + Downloads the file at the specified sandbox path as a binary stream. The path is resolved + relative to the session home directory. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param agent_session_id: The session ID. Required. + :type agent_session_id: str + :keyword remote_path: The file path to download from the sandbox, relative to the session home + directory. Required. + :paramtype remote_path: str + :return: AsyncIterator[bytes] + :rtype: AsyncIterator[bytes] :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -2153,25 +2345,16 @@ async def create_or_update( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.DatasetVersion] = kwargs.pop("cls", None) - - content_type = content_type or "application/merge-patch+json" - _content = None - if isinstance(dataset_version, (IOBase, bytes)): - _content = dataset_version - else: - _content = json.dumps(dataset_version, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) - _request = build_datasets_create_or_update_request( - name=name, - version=version, - content_type=content_type, + _request = build_agents_download_session_file_as_bytes_request( + agent_name=agent_name, + agent_session_id=agent_session_id, + remote_path=remote_path, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -2181,132 +2364,82 @@ async def create_or_update( _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = kwargs.pop("stream", True) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200, 201]: + if response.status_code not in [200]: if _stream: try: await response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.DatasetVersion, response.json()) + deserialized = response.iter_bytes() if _decompress else response.iter_raw() if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - @overload - async def pending_upload( - self, - name: str, - version: str, - pending_upload_request: _models.PendingUploadRequest, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of a dataset for a specific version. - - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to operate on. Required. - :type version: str - :param pending_upload_request: The pending upload request parameters. Required. - :type pending_upload_request: ~azure.ai.projects.models.PendingUploadRequest - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.PendingUploadResponse - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def pending_upload( + @distributed_trace + def list_session_files( self, - name: str, - version: str, - pending_upload_request: JSON, + agent_name: str, + agent_session_id: str, *, - content_type: str = "application/json", + remote_path: Optional[str] = None, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + before: Optional[str] = None, **kwargs: Any - ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of a dataset for a specific version. - - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to operate on. Required. - :type version: str - :param pending_upload_request: The pending upload request parameters. Required. - :type pending_upload_request: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.PendingUploadResponse - :raises ~azure.core.exceptions.HttpResponseError: - """ + ) -> AsyncItemPaged["_models.SessionDirectoryEntry"]: + """List session files. - @overload - async def pending_upload( - self, - name: str, - version: str, - pending_upload_request: IO[bytes], - *, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of a dataset for a specific version. + Returns files and directories at the specified path in the session sandbox. The response + includes only the immediate children of the target directory and defaults to the session home + directory when no path is supplied. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to operate on. Required. - :type version: str - :param pending_upload_request: The pending upload request parameters. Required. - :type pending_upload_request: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.PendingUploadResponse + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param agent_session_id: The session ID. Required. + :type agent_session_id: str + :keyword remote_path: The directory path to list, relative to the session home directory. + Defaults to the home directory if not provided. Default value is None. + :paramtype remote_path: str + :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the + default is 20. Default value is None. + :paramtype limit: int + :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for + ascending order and``desc`` + for descending order. Known values are: "asc" and "desc". Default value is None. + :paramtype order: str or ~azure.ai.projects.models.PageOrder + :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your + place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + Default value is None. + :paramtype before: str + :return: An iterator like instance of SessionDirectoryEntry + :rtype: + ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.SessionDirectoryEntry] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - @distributed_trace_async - async def pending_upload( - self, - name: str, - version: str, - pending_upload_request: Union[_models.PendingUploadRequest, JSON, IO[bytes]], - **kwargs: Any - ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of a dataset for a specific version. + cls: ClsType[List[_models.SessionDirectoryEntry]] = kwargs.pop("cls", None) - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to operate on. Required. - :type version: str - :param pending_upload_request: The pending upload request parameters. Is one of the following - types: PendingUploadRequest, JSON, IO[bytes] Required. - :type pending_upload_request: ~azure.ai.projects.models.PendingUploadRequest or JSON or - IO[bytes] - :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.PendingUploadResponse - :raises ~azure.core.exceptions.HttpResponseError: - """ error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -2315,70 +2448,84 @@ async def pending_upload( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = kwargs.pop("params", {}) or {} - - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.PendingUploadResponse] = kwargs.pop("cls", None) + def prepare_request(_continuation_token=None): - content_type = content_type or "application/json" - _content = None - if isinstance(pending_upload_request, (IOBase, bytes)): - _content = pending_upload_request - else: - _content = json.dumps(pending_upload_request, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + _request = build_agents_list_session_files_request( + agent_name=agent_name, + agent_session_id=agent_session_id, + remote_path=remote_path, + limit=limit, + order=order, + after=_continuation_token, + before=before, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request - _request = build_datasets_pending_upload_request( - name=name, - version=version, - content_type=content_type, - api_version=self._config.api_version, - content=_content, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.SessionDirectoryEntry], + deserialized.get("entries", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("last_id") or None, AsyncList(list_of_elem) - response = pipeline_response.http_response + async def get_next(_continuation_token=None): + _request = prepare_request(_continuation_token) - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.PendingUploadResponse, response.json()) + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return pipeline_response - return deserialized # type: ignore + return AsyncItemPaged(get_next, extract_data) @distributed_trace_async - async def get_credentials(self, name: str, version: str, **kwargs: Any) -> _models.DatasetCredential: - """Get the SAS credential to access the storage account associated with a Dataset version. + async def delete_session_file( + self, + agent_name: str, + agent_session_id: str, + *, + remote_path: str, + recursive: Optional[bool] = None, + **kwargs: Any + ) -> None: + """Delete a session file. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to operate on. Required. - :type version: str - :return: DatasetCredential. The DatasetCredential is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetCredential + Deletes the specified file or directory from the session sandbox. When ``recursive`` is false, + deleting a non-empty directory returns 409 Conflict. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param agent_session_id: The session ID. Required. + :type agent_session_id: str + :keyword remote_path: The file or directory path to delete, relative to the session home + directory. Required. + :paramtype remote_path: str + :keyword recursive: Whether to recursively delete directory contents. The service defaults to + ``false`` if a value is not specified by the caller. Default value is None. + :paramtype recursive: bool + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -2392,11 +2539,13 @@ async def get_credentials(self, name: str, version: str, **kwargs: Any) -> _mode _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DatasetCredential] = kwargs.pop("cls", None) + cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_datasets_get_credentials_request( - name=name, - version=version, + _request = build_agents_delete_session_file_request( + agent_name=agent_name, + agent_session_id=agent_session_id, + remote_path=remote_path, + recursive=recursive, api_version=self._config.api_version, headers=_headers, params=_params, @@ -2406,42 +2555,33 @@ async def get_credentials(self, name: str, version: str, **kwargs: Any) -> _mode } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = False pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass + if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.DatasetCredential, response.json()) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore - - return deserialized # type: ignore + return cls(pipeline_response, None, {}) # type: ignore -class DeploymentsOperations: +class EvaluationRulesOperations: """ .. warning:: **DO NOT** instantiate this class directly. Instead, you should access the following operations through :class:`~azure.ai.projects.aio.AIProjectClient`'s - :attr:`deployments` attribute. + :attr:`evaluation_rules` attribute. """ def __init__(self, *args, **kwargs) -> None: @@ -2452,13 +2592,15 @@ def __init__(self, *args, **kwargs) -> None: self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") @distributed_trace_async - async def get(self, name: str, **kwargs: Any) -> _models.Deployment: - """Get a deployed model. + async def get(self, id: str, **kwargs: Any) -> _models.EvaluationRule: + """Get an evaluation rule. - :param name: Name of the deployment. Required. - :type name: str - :return: Deployment. The Deployment is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Deployment + Retrieves the specified evaluation rule and its configuration. + + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.EvaluationRule :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -2472,10 +2614,10 @@ async def get(self, name: str, **kwargs: Any) -> _models.Deployment: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.Deployment] = kwargs.pop("cls", None) + cls: ClsType[_models.EvaluationRule] = kwargs.pop("cls", None) - _request = build_deployments_get_request( - name=name, + _request = build_evaluation_rules_get_request( + id=id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -2502,49 +2644,28 @@ async def get(self, name: str, **kwargs: Any) -> _models.Deployment: map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) - response_headers = {} - response_headers["x-ms-client-request-id"] = self._deserialize( - "str", response.headers.get("x-ms-client-request-id") - ) - if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.Deployment, response.json()) + deserialized = _deserialize(_models.EvaluationRule, response.json()) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - @distributed_trace - def list( - self, - *, - model_publisher: Optional[str] = None, - model_name: Optional[str] = None, - deployment_type: Optional[Union[str, _models.DeploymentType]] = None, - **kwargs: Any - ) -> AsyncItemPaged["_models.Deployment"]: - """List all deployed models in the project. + @distributed_trace_async + async def delete(self, id: str, **kwargs: Any) -> None: + """Delete an evaluation rule. - :keyword model_publisher: Model publisher to filter models by. Default value is None. - :paramtype model_publisher: str - :keyword model_name: Model name (the publisher specific name) to filter models by. Default - value is None. - :paramtype model_name: str - :keyword deployment_type: Type of deployment to filter list by. "ModelDeployment" Default value - is None. - :paramtype deployment_type: str or ~azure.ai.projects.models.DeploymentType - :return: An iterator like instance of Deployment - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.Deployment] + Removes the specified evaluation rule from the project. + + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.Deployment]] = kwargs.pop("cls", None) - error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -2553,109 +2674,113 @@ def list( } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(next_link=None): - if not next_link: - - _request = build_deployments_list_request( - model_publisher=model_publisher, - model_name=model_name, - deployment_type=deployment_type, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + cls: ClsType[None] = kwargs.pop("cls", None) - return _request + _request = build_evaluation_rules_delete_request( + id=id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - async def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.Deployment], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, AsyncList(list_of_elem) + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) - async def get_next(next_link=None): - _request = prepare_request(next_link) + response = pipeline_response.http_response - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + if cls: + return cls(pipeline_response, None, {}) # type: ignore - return pipeline_response + @overload + async def create_or_update( + self, id: str, evaluation_rule: _models.EvaluationRule, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.EvaluationRule: + """Create or update an evaluation rule. - return AsyncItemPaged(get_next, extract_data) + Creates a new evaluation rule, or replaces the existing rule when the identifier matches. + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :param evaluation_rule: Evaluation rule resource. Required. + :type evaluation_rule: ~azure.ai.projects.models.EvaluationRule + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.EvaluationRule + :raises ~azure.core.exceptions.HttpResponseError: + """ -class IndexesOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. + @overload + async def create_or_update( + self, id: str, evaluation_rule: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.EvaluationRule: + """Create or update an evaluation rule. - Instead, you should access the following operations through - :class:`~azure.ai.projects.aio.AIProjectClient`'s - :attr:`indexes` attribute. - """ + Creates a new evaluation rule, or replaces the existing rule when the identifier matches. - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :param evaluation_rule: Evaluation rule resource. Required. + :type evaluation_rule: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.EvaluationRule + :raises ~azure.core.exceptions.HttpResponseError: + """ - @distributed_trace - def list_versions(self, name: str, **kwargs: Any) -> AsyncItemPaged["_models.Index"]: - """List all versions of the given Index. + @overload + async def create_or_update( + self, id: str, evaluation_rule: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.EvaluationRule: + """Create or update an evaluation rule. - :param name: The name of the resource. Required. - :type name: str - :return: An iterator like instance of Index - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.Index] + Creates a new evaluation rule, or replaces the existing rule when the identifier matches. + + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :param evaluation_rule: Evaluation rule resource. Required. + :type evaluation_rule: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.EvaluationRule :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.Index]] = kwargs.pop("cls", None) + @distributed_trace_async + async def create_or_update( + self, id: str, evaluation_rule: Union[_models.EvaluationRule, JSON, IO[bytes]], **kwargs: Any + ) -> _models.EvaluationRule: + """Create or update an evaluation rule. + Creates a new evaluation rule, or replaces the existing rule when the identifier matches. + + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :param evaluation_rule: Evaluation rule resource. Is one of the following types: + EvaluationRule, JSON, IO[bytes] Required. + :type evaluation_rule: ~azure.ai.projects.models.EvaluationRule or JSON or IO[bytes] + :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.EvaluationRule + :raises ~azure.core.exceptions.HttpResponseError: + """ error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -2664,86 +2789,88 @@ def list_versions(self, name: str, **kwargs: Any) -> AsyncItemPaged["_models.Ind } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(next_link=None): - if not next_link: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} - _request = build_indexes_list_versions_request( - name=name, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.EvaluationRule] = kwargs.pop("cls", None) - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + content_type = content_type or "application/json" + _content = None + if isinstance(evaluation_rule, (IOBase, bytes)): + _content = evaluation_rule + else: + _content = json.dumps(evaluation_rule, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - return _request + _request = build_evaluation_rules_create_or_update_request( + id=id, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - async def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.Index], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, AsyncList(list_of_elem) + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) - async def get_next(next_link=None): - _request = prepare_request(next_link) + response = pipeline_response.http_response - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response + if response.status_code not in [200, 201]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.EvaluationRule, response.json()) - return pipeline_response + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore - return AsyncItemPaged(get_next, extract_data) + return deserialized # type: ignore @distributed_trace - def list(self, **kwargs: Any) -> AsyncItemPaged["_models.Index"]: - """List the latest version of each Index. + def list( + self, + *, + action_type: Optional[Union[str, _models.EvaluationRuleActionType]] = None, + agent_name: Optional[str] = None, + enabled: Optional[bool] = None, + **kwargs: Any + ) -> AsyncItemPaged["_models.EvaluationRule"]: + """List evaluation rules. - :return: An iterator like instance of Index - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.Index] + Returns the evaluation rules configured for the project, optionally filtered by action type, + agent name, or enabled state. + + :keyword action_type: Filter by the type of evaluation rule. Known values are: + "continuousEvaluation" and "humanEvaluationPreview". Default value is None. + :paramtype action_type: str or ~azure.ai.projects.models.EvaluationRuleActionType + :keyword agent_name: Filter by the agent name. Default value is None. + :paramtype agent_name: str + :keyword enabled: Filter by the enabled status. Default value is None. + :paramtype enabled: bool + :return: An iterator like instance of EvaluationRule + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.EvaluationRule] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.Index]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.EvaluationRule]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -2756,7 +2883,10 @@ def list(self, **kwargs: Any) -> AsyncItemPaged["_models.Index"]: def prepare_request(next_link=None): if not next_link: - _request = build_indexes_list_request( + _request = build_evaluation_rules_list_request( + action_type=action_type, + agent_name=agent_name, + enabled=enabled, api_version=self._config.api_version, headers=_headers, params=_params, @@ -2796,7 +2926,7 @@ def prepare_request(next_link=None): async def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.Index], + List[_models.EvaluationRule], deserialized.get("value", []), ) if cls: @@ -2820,17 +2950,35 @@ async def get_next(next_link=None): return AsyncItemPaged(get_next, extract_data) + +class ConnectionsOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. + + Instead, you should access the following operations through + :class:`~azure.ai.projects.aio.AIProjectClient`'s + :attr:`connections` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + @distributed_trace_async - async def get(self, name: str, version: str, **kwargs: Any) -> _models.Index: - """Get the specific version of the Index. The service returns 404 Not Found error if the Index - does not exist. + async def _get(self, name: str, **kwargs: Any) -> _models.Connection: + """Get a connection. - :param name: The name of the resource. Required. + Retrieves the specified connection and its configuration details without including credential + values. + + :param name: The friendly name of the connection, provided by the user. Required. :type name: str - :param version: The specific version id of the Index to retrieve. Required. - :type version: str - :return: Index. The Index is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Index + :return: Connection. The Connection is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Connection :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -2844,11 +2992,10 @@ async def get(self, name: str, version: str, **kwargs: Any) -> _models.Index: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.Index] = kwargs.pop("cls", None) + cls: ClsType[_models.Connection] = kwargs.pop("cls", None) - _request = build_indexes_get_request( + _request = build_connections_get_request( name=name, - version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -2875,27 +3022,31 @@ async def get(self, name: str, version: str, **kwargs: Any) -> _models.Index: map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) + response_headers = {} + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.Index, response.json()) + deserialized = _deserialize(_models.Connection, response.json()) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore @distributed_trace_async - async def delete(self, name: str, version: str, **kwargs: Any) -> None: - """Delete the specific version of the Index. The service returns 204 No Content if the Index was - deleted successfully or if the Index does not exist. + async def _get_with_credentials(self, name: str, **kwargs: Any) -> _models.Connection: + """Get a connection with credentials. - :param name: The name of the resource. Required. + Retrieves the specified connection together with its credential values. + + :param name: The friendly name of the connection, provided by the user. Required. :type name: str - :param version: The version of the Index to delete. Required. - :type version: str - :return: None - :rtype: None + :return: Connection. The Connection is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Connection :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -2909,11 +3060,10 @@ async def delete(self, name: str, version: str, **kwargs: Any) -> None: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + cls: ClsType[_models.Connection] = kwargs.pop("cls", None) - _request = build_indexes_delete_request( + _request = build_connections_get_with_credentials_request( name=name, - version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -2923,109 +3073,67 @@ async def delete(self, name: str, version: str, **kwargs: Any) -> None: } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response) - if cls: - return cls(pipeline_response, None, {}) # type: ignore - - @overload - async def create_or_update( - self, - name: str, - version: str, - index: _models.Index, - *, - content_type: str = "application/merge-patch+json", - **kwargs: Any - ) -> _models.Index: - """Create a new or update an existing Index with the given version id. + response_headers = {} + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the Index to create or update. Required. - :type version: str - :param index: The Index to create or update. Required. - :type index: ~azure.ai.projects.models.Index - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: Index. The Index is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Index - :raises ~azure.core.exceptions.HttpResponseError: - """ + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.Connection, response.json()) - @overload - async def create_or_update( - self, name: str, version: str, index: JSON, *, content_type: str = "application/merge-patch+json", **kwargs: Any - ) -> _models.Index: - """Create a new or update an existing Index with the given version id. + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the Index to create or update. Required. - :type version: str - :param index: The Index to create or update. Required. - :type index: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: Index. The Index is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Index - :raises ~azure.core.exceptions.HttpResponseError: - """ + return deserialized # type: ignore - @overload - async def create_or_update( + @distributed_trace + def list( self, - name: str, - version: str, - index: IO[bytes], *, - content_type: str = "application/merge-patch+json", + connection_type: Optional[Union[str, _models.ConnectionType]] = None, + default_connection: Optional[bool] = None, **kwargs: Any - ) -> _models.Index: - """Create a new or update an existing Index with the given version id. + ) -> AsyncItemPaged["_models.Connection"]: + """List connections. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the Index to create or update. Required. - :type version: str - :param index: The Index to create or update. Required. - :type index: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: Index. The Index is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Index + Returns the connections available in the current project, optionally filtered by type or + default status. + + :keyword connection_type: Lists connections of this specific type. Known values are: + "AzureOpenAI", "AzureBlob", "AzureStorageAccount", "CognitiveSearch", "CosmosDB", "ApiKey", + "AppConfig", "AppInsights", "CustomKeys", and "RemoteTool_Preview". Default value is None. + :paramtype connection_type: str or ~azure.ai.projects.models.ConnectionType + :keyword default_connection: Lists connections that are default connections. Default value is + None. + :paramtype default_connection: bool + :return: An iterator like instance of Connection + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.Connection] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - @distributed_trace_async - async def create_or_update( - self, name: str, version: str, index: Union[_models.Index, JSON, IO[bytes]], **kwargs: Any - ) -> _models.Index: - """Create a new or update an existing Index with the given version id. + cls: ClsType[List[_models.Connection]] = kwargs.pop("cls", None) - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the Index to create or update. Required. - :type version: str - :param index: The Index to create or update. Is one of the following types: Index, JSON, - IO[bytes] Required. - :type index: ~azure.ai.projects.models.Index or JSON or IO[bytes] - :return: Index. The Index is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Index - :raises ~azure.core.exceptions.HttpResponseError: - """ error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -3034,69 +3142,84 @@ async def create_or_update( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = kwargs.pop("params", {}) or {} + def prepare_request(next_link=None): + if not next_link: - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.Index] = kwargs.pop("cls", None) + _request = build_connections_list_request( + connection_type=connection_type, + default_connection=default_connection, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - content_type = content_type or "application/merge-patch+json" - _content = None - if isinstance(index, (IOBase, bytes)): - _content = index - else: - _content = json.dumps(index, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - _request = build_indexes_create_or_update_request( - name=name, - version=version, - content_type=content_type, - api_version=self._config.api_version, - content=_content, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.Connection], + deserialized.get("value", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) - response = pipeline_response.http_response + async def get_next(next_link=None): + _request = prepare_request(next_link) - if response.status_code not in [200, 201]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.Index, response.json()) + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return pipeline_response - return deserialized # type: ignore + return AsyncItemPaged(get_next, extract_data) -class BetaAgentsOperations: # pylint: disable=too-many-public-methods +class DatasetsOperations: """ .. warning:: **DO NOT** instantiate this class directly. Instead, you should access the following operations through :class:`~azure.ai.projects.aio.AIProjectClient`'s - :attr:`agents` attribute. + :attr:`datasets` attribute. """ def __init__(self, *args, **kwargs) -> None: @@ -3106,322 +3229,23 @@ def __init__(self, *args, **kwargs) -> None: self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") - @overload - async def patch_agent_details( - self, - agent_name: str, - *, - content_type: str = "application/merge-patch+json", - agent_endpoint: Optional[_models.AgentEndpointConfig] = None, - agent_card: Optional[_models.AgentCard] = None, - **kwargs: Any - ) -> _models.AgentDetails: - """Updates an agent endpoint. - - :param agent_name: The name of the agent to retrieve. Required. - :type agent_name: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :keyword agent_endpoint: The endpoint configuration for the agent. Default value is None. - :paramtype agent_endpoint: ~azure.ai.projects.models.AgentEndpointConfig - :keyword agent_card: Optional agent card for the agent. Default value is None. - :paramtype agent_card: ~azure.ai.projects.models.AgentCard - :return: AgentDetails. The AgentDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def patch_agent_details( - self, agent_name: str, body: JSON, *, content_type: str = "application/merge-patch+json", **kwargs: Any - ) -> _models.AgentDetails: - """Updates an agent endpoint. - - :param agent_name: The name of the agent to retrieve. Required. - :type agent_name: str - :param body: Required. - :type body: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: AgentDetails. The AgentDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def patch_agent_details( - self, agent_name: str, body: IO[bytes], *, content_type: str = "application/merge-patch+json", **kwargs: Any - ) -> _models.AgentDetails: - """Updates an agent endpoint. - - :param agent_name: The name of the agent to retrieve. Required. - :type agent_name: str - :param body: Required. - :type body: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: AgentDetails. The AgentDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @distributed_trace_async - async def patch_agent_details( - self, - agent_name: str, - body: Union[JSON, IO[bytes]] = _Unset, - *, - agent_endpoint: Optional[_models.AgentEndpointConfig] = None, - agent_card: Optional[_models.AgentCard] = None, - **kwargs: Any - ) -> _models.AgentDetails: - """Updates an agent endpoint. - - :param agent_name: The name of the agent to retrieve. Required. - :type agent_name: str - :param body: Is either a JSON type or a IO[bytes] type. Required. - :type body: JSON or IO[bytes] - :keyword agent_endpoint: The endpoint configuration for the agent. Default value is None. - :paramtype agent_endpoint: ~azure.ai.projects.models.AgentEndpointConfig - :keyword agent_card: Optional agent card for the agent. Default value is None. - :paramtype agent_card: ~azure.ai.projects.models.AgentCard - :return: AgentDetails. The AgentDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = kwargs.pop("params", {}) or {} - - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.AgentDetails] = kwargs.pop("cls", None) - - if body is _Unset: - body = {"agent_card": agent_card, "agent_endpoint": agent_endpoint} - body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/merge-patch+json" - _content = None - if isinstance(body, (IOBase, bytes)): - _content = body - else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - - _request = build_beta_agents_patch_agent_details_request( - agent_name=agent_name, - content_type=content_type, - api_version=self._config.api_version, - content=_content, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - - response = pipeline_response.http_response - - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.AgentDetails, response.json()) - - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore - - return deserialized # type: ignore - - @overload - async def create_version_from_code( - self, - agent_name: str, - content: _models.CreateAgentVersionFromCodeContent, - *, - code_zip_sha256: str, - **kwargs: Any - ) -> _models.AgentVersionDetails: - """create_version_from_code. - - :param agent_name: The unique name that identifies the agent. Name can be used to - retrieve/update/delete the agent. - - * Must start and end with alphanumeric characters, - * Can contain hyphens in the middle - * Must not exceed 63 characters. Required. - :type agent_name: str - :param content: Required. - :type content: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent - :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change - detection (dedup) and integrity verification. Required. - :paramtype code_zip_sha256: str - :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentVersionDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def create_version_from_code( - self, agent_name: str, content: JSON, *, code_zip_sha256: str, **kwargs: Any - ) -> _models.AgentVersionDetails: - """create_version_from_code. - - :param agent_name: The unique name that identifies the agent. Name can be used to - retrieve/update/delete the agent. - - * Must start and end with alphanumeric characters, - * Can contain hyphens in the middle - * Must not exceed 63 characters. Required. - :type agent_name: str - :param content: Required. - :type content: JSON - :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change - detection (dedup) and integrity verification. Required. - :paramtype code_zip_sha256: str - :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentVersionDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @distributed_trace_async - async def create_version_from_code( - self, - agent_name: str, - content: Union[_models.CreateAgentVersionFromCodeContent, JSON], - *, - code_zip_sha256: str, - **kwargs: Any - ) -> _models.AgentVersionDetails: - """create_version_from_code. + @distributed_trace + def list_versions(self, name: str, **kwargs: Any) -> AsyncItemPaged["_models.DatasetVersion"]: + """List versions. - :param agent_name: The unique name that identifies the agent. Name can be used to - retrieve/update/delete the agent. + List all versions of the given DatasetVersion. - * Must start and end with alphanumeric characters, - * Can contain hyphens in the middle - * Must not exceed 63 characters. Required. - :type agent_name: str - :param content: Is either a CreateAgentVersionFromCodeContent type or a JSON type. Required. - :type content: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent or JSON - :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change - detection (dedup) and integrity verification. Required. - :paramtype code_zip_sha256: str - :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentVersionDetails + :param name: The name of the resource. Required. + :type name: str + :return: An iterator like instance of DatasetVersion + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.DatasetVersion] :raises ~azure.core.exceptions.HttpResponseError: """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.AgentVersionDetails] = kwargs.pop("cls", None) - - _body = content.as_dict() if isinstance(content, _Model) else content - _file_fields: list[str] = ["code"] - _data_fields: list[str] = ["metadata"] - _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) - - _request = build_beta_agents_create_version_from_code_request( - agent_name=agent_name, - code_zip_sha256=code_zip_sha256, - api_version=self._config.api_version, - files=_files, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - - response = pipeline_response.http_response - - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.AgentVersionDetails, response.json()) - - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore - - return deserialized # type: ignore - - @distributed_trace_async - async def download_code( - self, agent_name: str, *, agent_version: Optional[str] = None, **kwargs: Any - ) -> AsyncIterator[bytes]: - """Download the code zip for a code-based hosted agent. - Returns the previously-uploaded zip (``application/zip``). - - If ``agent_version`` is supplied, returns that version's code zip; otherwise - returns the latest version's code zip. - - The SHA-256 digest of the returned bytes matches the ``content_hash`` on the - resolved version's ``code_configuration``. + cls: ClsType[List[_models.DatasetVersion]] = kwargs.pop("cls", None) - :param agent_name: The name of the agent. Required. - :type agent_name: str - :keyword agent_version: The version of the agent whose code zip should be downloaded. - If omitted, the latest version's code zip is returned. Default value is None. - :paramtype agent_version: str - :return: AsyncIterator[bytes] - :rtype: AsyncIterator[bytes] - :raises ~azure.core.exceptions.HttpResponseError: - """ error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -3430,177 +3254,89 @@ async def download_code( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) + def prepare_request(next_link=None): + if not next_link: - _request = build_beta_agents_download_code_request( - agent_name=agent_name, - agent_version=agent_version, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + _request = build_datasets_list_versions_request( + name=name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", True) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - response = pipeline_response.http_response + return _request - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.DatasetVersion], + deserialized.get("value", []), ) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers["x-ms-agent-version"] = self._deserialize("str", response.headers.get("x-ms-agent-version")) - response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) - - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - - if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore - - return deserialized # type: ignore - - @overload - async def create_session( - self, - agent_name: str, - *, - version_indicator: _models.VersionIndicator, - user_isolation_key: Optional[str] = None, - content_type: str = "application/json", - agent_session_id: Optional[str] = None, - **kwargs: Any - ) -> _models.AgentSessionResource: - """Creates a new session for an agent endpoint. The endpoint resolves the backing agent version - from ``version_indicator`` and enforces session ownership using the provided isolation key for - session-mutating operations. + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) - :param agent_name: The name of the agent to create a session for. Required. - :type agent_name: str - :keyword version_indicator: Determines which agent version backs the session. Required. - :paramtype version_indicator: ~azure.ai.projects.models.VersionIndicator - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :keyword agent_session_id: Optional caller-provided session ID. If specified, it must be unique - within the agent endpoint. Auto-generated if omitted. Default value is None. - :paramtype agent_session_id: str - :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentSessionResource - :raises ~azure.core.exceptions.HttpResponseError: - """ + async def get_next(next_link=None): + _request = prepare_request(next_link) - @overload - async def create_session( - self, - agent_name: str, - body: JSON, - *, - user_isolation_key: Optional[str] = None, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.AgentSessionResource: - """Creates a new session for an agent endpoint. The endpoint resolves the backing agent version - from ``version_indicator`` and enforces session ownership using the provided isolation key for - session-mutating operations. + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response - :param agent_name: The name of the agent to create a session for. Required. - :type agent_name: str - :param body: Required. - :type body: JSON - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentSessionResource - :raises ~azure.core.exceptions.HttpResponseError: - """ + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - @overload - async def create_session( - self, - agent_name: str, - body: IO[bytes], - *, - user_isolation_key: Optional[str] = None, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.AgentSessionResource: - """Creates a new session for an agent endpoint. The endpoint resolves the backing agent version - from ``version_indicator`` and enforces session ownership using the provided isolation key for - session-mutating operations. + return pipeline_response - :param agent_name: The name of the agent to create a session for. Required. - :type agent_name: str - :param body: Required. - :type body: IO[bytes] - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentSessionResource - :raises ~azure.core.exceptions.HttpResponseError: - """ + return AsyncItemPaged(get_next, extract_data) - @distributed_trace_async - async def create_session( - self, - agent_name: str, - body: Union[JSON, IO[bytes]] = _Unset, - *, - version_indicator: _models.VersionIndicator = _Unset, - user_isolation_key: Optional[str] = None, - agent_session_id: Optional[str] = None, - **kwargs: Any - ) -> _models.AgentSessionResource: - """Creates a new session for an agent endpoint. The endpoint resolves the backing agent version - from ``version_indicator`` and enforces session ownership using the provided isolation key for - session-mutating operations. + @distributed_trace + def list(self, **kwargs: Any) -> AsyncItemPaged["_models.DatasetVersion"]: + """List latest versions. - :param agent_name: The name of the agent to create a session for. Required. - :type agent_name: str - :param body: Is either a JSON type or a IO[bytes] type. Required. - :type body: JSON or IO[bytes] - :keyword version_indicator: Determines which agent version backs the session. Required. - :paramtype version_indicator: ~azure.ai.projects.models.VersionIndicator - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :keyword agent_session_id: Optional caller-provided session ID. If specified, it must be unique - within the agent endpoint. Auto-generated if omitted. Default value is None. - :paramtype agent_session_id: str - :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentSessionResource + List the latest version of each DatasetVersion. + + :return: An iterator like instance of DatasetVersion + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.DatasetVersion] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.DatasetVersion]] = kwargs.pop("cls", None) + error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -3609,84 +3345,86 @@ async def create_session( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = kwargs.pop("params", {}) or {} + def prepare_request(next_link=None): + if not next_link: - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.AgentSessionResource] = kwargs.pop("cls", None) + _request = build_datasets_list_request( + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - if body is _Unset: - if version_indicator is _Unset: - raise TypeError("missing required argument: version_indicator") - body = {"agent_session_id": agent_session_id, "version_indicator": version_indicator} - body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/json" - _content = None - if isinstance(body, (IOBase, bytes)): - _content = body - else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - _request = build_beta_agents_create_session_request( - agent_name=agent_name, - user_isolation_key=user_isolation_key, - content_type=content_type, - api_version=self._config.api_version, - content=_content, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.DatasetVersion], + deserialized.get("value", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) - response = pipeline_response.http_response + async def get_next(next_link=None): + _request = prepare_request(next_link) - if response.status_code not in [201]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs ) - raise HttpResponseError(response=response, model=error) + response = pipeline_response.http_response - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.AgentSessionResource, response.json()) + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return pipeline_response - return deserialized # type: ignore + return AsyncItemPaged(get_next, extract_data) @distributed_trace_async - async def get_session( - self, agent_name: str, session_id: str, *, user_isolation_key: Optional[str] = None, **kwargs: Any - ) -> _models.AgentSessionResource: - """Retrieves a session by ID. + async def get(self, name: str, version: str, **kwargs: Any) -> _models.DatasetVersion: + """Get a version. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param session_id: The session identifier. Required. - :type session_id: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentSessionResource + Get the specific version of the DatasetVersion. The service returns 404 Not Found error if the + DatasetVersion does not exist. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to retrieve. Required. + :type version: str + :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetVersion :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -3700,12 +3438,11 @@ async def get_session( _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.AgentSessionResource] = kwargs.pop("cls", None) + cls: ClsType[_models.DatasetVersion] = kwargs.pop("cls", None) - _request = build_beta_agents_get_session_request( - agent_name=agent_name, - session_id=session_id, - user_isolation_key=user_isolation_key, + _request = build_datasets_get_request( + name=name, + version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -3730,16 +3467,12 @@ async def get_session( except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.AgentSessionResource, response.json()) + deserialized = _deserialize(_models.DatasetVersion, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -3747,19 +3480,16 @@ async def get_session( return deserialized # type: ignore @distributed_trace_async - async def delete_session( - self, agent_name: str, session_id: str, *, user_isolation_key: Optional[str] = None, **kwargs: Any - ) -> None: - """Deletes a session synchronously. Returns 204 No Content when the session is deleted or does not - exist. + async def delete(self, name: str, version: str, **kwargs: Any) -> None: + """Delete a version. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param session_id: The session identifier. Required. - :type session_id: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str + Delete the specific version of the DatasetVersion. The service returns 204 No Content if the + DatasetVersion was deleted successfully or if the DatasetVersion does not exist. + + :param name: The name of the resource. Required. + :type name: str + :param version: The version of the DatasetVersion to delete. Required. + :type version: str :return: None :rtype: None :raises ~azure.core.exceptions.HttpResponseError: @@ -3777,10 +3507,9 @@ async def delete_session( cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_beta_agents_delete_session_request( - agent_name=agent_name, - session_id=session_id, - user_isolation_key=user_isolation_key, + _request = build_datasets_delete_request( + name=name, + version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -3799,25 +3528,112 @@ async def delete_session( if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) if cls: return cls(pipeline_response, None, {}) # type: ignore + @overload + async def create_or_update( + self, + name: str, + version: str, + dataset_version: _models.DatasetVersion, + *, + content_type: str = "application/merge-patch+json", + **kwargs: Any + ) -> _models.DatasetVersion: + """Create or update a version. + + Create a new or update an existing DatasetVersion with the given version id. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to create or update. Required. + :type version: str + :param dataset_version: The DatasetVersion to create or update. Required. + :type dataset_version: ~azure.ai.projects.models.DatasetVersion + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_or_update( + self, + name: str, + version: str, + dataset_version: JSON, + *, + content_type: str = "application/merge-patch+json", + **kwargs: Any + ) -> _models.DatasetVersion: + """Create or update a version. + + Create a new or update an existing DatasetVersion with the given version id. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to create or update. Required. + :type version: str + :param dataset_version: The DatasetVersion to create or update. Required. + :type dataset_version: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_or_update( + self, + name: str, + version: str, + dataset_version: IO[bytes], + *, + content_type: str = "application/merge-patch+json", + **kwargs: Any + ) -> _models.DatasetVersion: + """Create or update a version. + + Create a new or update an existing DatasetVersion with the given version id. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to create or update. Required. + :type version: str + :param dataset_version: The DatasetVersion to create or update. Required. + :type dataset_version: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + @distributed_trace_async - async def stop_session(self, agent_name: str, session_id: str, **kwargs: Any) -> None: - """Stops a session. Returns 204 No Content when the stop succeeds. + async def create_or_update( + self, name: str, version: str, dataset_version: Union[_models.DatasetVersion, JSON, IO[bytes]], **kwargs: Any + ) -> _models.DatasetVersion: + """Create or update a version. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param session_id: The session identifier. Required. - :type session_id: str - :return: None - :rtype: None + Create a new or update an existing DatasetVersion with the given version id. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to create or update. Required. + :type version: str + :param dataset_version: The DatasetVersion to create or update. Is one of the following types: + DatasetVersion, JSON, IO[bytes] Required. + :type dataset_version: ~azure.ai.projects.models.DatasetVersion or JSON or IO[bytes] + :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetVersion :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -3828,15 +3644,25 @@ async def stop_session(self, agent_name: str, session_id: str, **kwargs: Any) -> } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.DatasetVersion] = kwargs.pop("cls", None) - _request = build_beta_agents_stop_session_request( - agent_name=agent_name, - session_id=session_id, + content_type = content_type or "application/merge-patch+json" + _content = None + if isinstance(dataset_version, (IOBase, bytes)): + _content = dataset_version + else: + _content = json.dumps(dataset_version, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_datasets_create_or_update_request( + name=name, + version=version, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -3845,162 +3671,139 @@ async def stop_session(self, agent_name: str, session_id: str, **kwargs: Any) -> } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [200, 201]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.DatasetVersion, response.json()) if cls: - return cls(pipeline_response, None, {}) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore - @distributed_trace - def list_sessions( + return deserialized # type: ignore + + @overload + async def pending_upload( self, - agent_name: str, + name: str, + version: str, + pending_upload_request: _models.PendingUploadRequest, *, - user_isolation_key: Optional[str] = None, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - before: Optional[str] = None, + content_type: str = "application/json", **kwargs: Any - ) -> AsyncItemPaged["_models.AgentSessionResource"]: - """Returns a list of sessions for the specified agent. + ) -> _models.PendingUploadResponse: + """Start a pending upload. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and - 100, and the - default is 20. Default value is None. - :paramtype limit: int - :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for - ascending order and``desc`` - for descending order. Known values are: "asc" and "desc". Default value is None. - :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - Default value is None. - :paramtype before: str - :return: An iterator like instance of AgentSessionResource - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.AgentSessionResource] + Initiates a new pending upload or retrieves an existing one for the specified dataset version. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to operate on. Required. + :type version: str + :param pending_upload_request: The pending upload request parameters. Required. + :type pending_upload_request: ~azure.ai.projects.models.PendingUploadRequest + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.PendingUploadResponse :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.AgentSessionResource]] = kwargs.pop("cls", None) - - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(_continuation_token=None): - - _request = build_beta_agents_list_sessions_request( - agent_name=agent_name, - user_isolation_key=user_isolation_key, - limit=limit, - order=order, - after=_continuation_token, - before=before, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - return _request - async def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.AgentSessionResource], - deserialized.get("data", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("last_id") or None, AsyncList(list_of_elem) + @overload + async def pending_upload( + self, + name: str, + version: str, + pending_upload_request: JSON, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.PendingUploadResponse: + """Start a pending upload. - async def get_next(_continuation_token=None): - _request = prepare_request(_continuation_token) + Initiates a new pending upload or retrieves an existing one for the specified dataset version. - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to operate on. Required. + :type version: str + :param pending_upload_request: The pending upload request parameters. Required. + :type pending_upload_request: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.PendingUploadResponse + :raises ~azure.core.exceptions.HttpResponseError: + """ - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + @overload + async def pending_upload( + self, + name: str, + version: str, + pending_upload_request: IO[bytes], + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.PendingUploadResponse: + """Start a pending upload. - return pipeline_response + Initiates a new pending upload or retrieves an existing one for the specified dataset version. - return AsyncItemPaged(get_next, extract_data) + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to operate on. Required. + :type version: str + :param pending_upload_request: The pending upload request parameters. Required. + :type pending_upload_request: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.PendingUploadResponse + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace_async - async def get_session_log_stream( - self, agent_name: str, agent_version: str, session_id: str, **kwargs: Any - ) -> _models.SessionLogEvent: - """Streams console logs (stdout / stderr) for a specific hosted agent session - as a Server-Sent Events (SSE) stream. - - Each SSE frame contains: - - * `event`: always `"log"` - * `data`: a plain-text log line (currently JSON-formatted, but the schema is not contractual and may include additional keys or change format over time; clients should treat it as an opaque string) - - Example SSE frames: - - .. code-block:: - - event: log - data: {"timestamp":"2026-03-10T09:33:17.121Z","stream":"stdout","message":"Starting FoundryCBAgent server on port 8088"} - - event: log - data: {"timestamp":"2026-03-10T09:33:17.130Z","stream":"stderr","message":"INFO: Application startup complete."} - - event: log - data: {"timestamp":"2026-03-10T09:34:52.714Z","stream":"status","message":"Successfully connected to container"} - - event: log - data: {"timestamp":"2026-03-10T09:35:52.714Z","stream":"status","message":"No logs since last 60 seconds"} + async def pending_upload( + self, + name: str, + version: str, + pending_upload_request: Union[_models.PendingUploadRequest, JSON, IO[bytes]], + **kwargs: Any + ) -> _models.PendingUploadResponse: + """Start a pending upload. - The stream remains open until the client disconnects or the server - terminates the connection. Clients should handle reconnection as needed. + Initiates a new pending upload or retrieves an existing one for the specified dataset version. - :param agent_name: The name of the hosted agent. Required. - :type agent_name: str - :param agent_version: The version of the agent. Required. - :type agent_version: str - :param session_id: The session ID (maps to an ADC sandbox). Required. - :type session_id: str - :return: SessionLogEvent. The SessionLogEvent is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SessionLogEvent + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to operate on. Required. + :type version: str + :param pending_upload_request: The pending upload request parameters. Is one of the following + types: PendingUploadRequest, JSON, IO[bytes] Required. + :type pending_upload_request: ~azure.ai.projects.models.PendingUploadRequest or JSON or + IO[bytes] + :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.PendingUploadResponse :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -4011,16 +3814,25 @@ async def get_session_log_stream( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.SessionLogEvent] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.PendingUploadResponse] = kwargs.pop("cls", None) - _request = build_beta_agents_get_session_log_stream_request( - agent_name=agent_name, - agent_version=agent_version, - session_id=session_id, + content_type = content_type or "application/json" + _content = None + if isinstance(pending_upload_request, (IOBase, bytes)): + _content = pending_upload_request + else: + _content = json.dumps(pending_upload_request, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_datasets_pending_upload_request( + name=name, + version=version, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -4030,7 +3842,7 @@ async def get_session_log_stream( _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = True + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -4044,53 +3856,30 @@ async def get_session_log_stream( except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + raise HttpResponseError(response=response) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SessionLogEvent, response.text()) + deserialized = _deserialize(_models.PendingUploadResponse, response.json()) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore @distributed_trace_async - async def _upload_session_file( - self, - agent_name: str, - agent_session_id: str, - content: bytes, - *, - path: str, - user_isolation_key: Optional[str] = None, - **kwargs: Any - ) -> _models.SessionFileWriteResult: - """Upload a file to the session sandbox via binary stream. Maximum file size is 50 MB. Uploads - exceeding this limit return 413 Payload Too Large. + async def get_credentials(self, name: str, version: str, **kwargs: Any) -> _models.DatasetCredential: + """Get dataset credentials. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param agent_session_id: The session ID. Required. - :type agent_session_id: str - :param content: Required. - :type content: bytes - :keyword path: The destination file path within the sandbox, relative to the session home - directory. Required. - :paramtype path: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SessionFileWriteResult + Gets the SAS credential to access the storage account associated with a Dataset version. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to operate on. Required. + :type version: str + :return: DatasetCredential. The DatasetCredential is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetCredential :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -4101,22 +3890,15 @@ async def _upload_session_file( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: str = kwargs.pop("content_type", _headers.pop("Content-Type", "application/octet-stream")) - cls: ClsType[_models.SessionFileWriteResult] = kwargs.pop("cls", None) - - _content = content + cls: ClsType[_models.DatasetCredential] = kwargs.pop("cls", None) - _request = build_beta_agents_upload_session_file_request( - agent_name=agent_name, - agent_session_id=agent_session_id, - path=path, - user_isolation_key=user_isolation_key, - content_type=content_type, + _request = build_datasets_get_credentials_request( + name=name, + version=version, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -4133,53 +3915,53 @@ async def _upload_session_file( response = pipeline_response.http_response - if response.status_code not in [201]: + if response.status_code not in [200]: if _stream: try: await response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SessionFileWriteResult, response.json()) + deserialized = _deserialize(_models.DatasetCredential, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore + +class DeploymentsOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. + + Instead, you should access the following operations through + :class:`~azure.ai.projects.aio.AIProjectClient`'s + :attr:`deployments` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + @distributed_trace_async - async def download_session_file( - self, - agent_name: str, - agent_session_id: str, - *, - path: str, - user_isolation_key: Optional[str] = None, - **kwargs: Any - ) -> AsyncIterator[bytes]: - """Download a file from the session sandbox as a binary stream. + async def get(self, name: str, **kwargs: Any) -> _models.Deployment: + """Get a deployment. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param agent_session_id: The session ID. Required. - :type agent_session_id: str - :keyword path: The file path to download from the sandbox, relative to the session home - directory. Required. - :paramtype path: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :return: AsyncIterator[bytes] - :rtype: AsyncIterator[bytes] + Gets a deployed model. + + :param name: Name of the deployment. Required. + :type name: str + :return: Deployment. The Deployment is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Deployment :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -4193,13 +3975,10 @@ async def download_session_file( _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) + cls: ClsType[_models.Deployment] = kwargs.pop("cls", None) - _request = build_beta_agents_download_session_file_request( - agent_name=agent_name, - agent_session_id=agent_session_id, - path=path, - user_isolation_key=user_isolation_key, + _request = build_deployments_get_request( + name=name, api_version=self._config.api_version, headers=_headers, params=_params, @@ -4210,7 +3989,7 @@ async def download_session_file( _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -4224,69 +4003,166 @@ async def download_session_file( except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.Deployment, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + def list( + self, + *, + model_publisher: Optional[str] = None, + model_name: Optional[str] = None, + deployment_type: Optional[Union[str, _models.DeploymentType]] = None, + **kwargs: Any + ) -> AsyncItemPaged["_models.Deployment"]: + """List deployments. + + Returns the deployed models available in the current project, optionally filtered by publisher, + model name, or deployment type. + + :keyword model_publisher: Model publisher to filter models by. Default value is None. + :paramtype model_publisher: str + :keyword model_name: Model name (the publisher specific name) to filter models by. Default + value is None. + :paramtype model_name: str + :keyword deployment_type: Type of deployment to filter list by. "ModelDeployment" Default value + is None. + :paramtype deployment_type: str or ~azure.ai.projects.models.DeploymentType + :return: An iterator like instance of Deployment + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.Deployment] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.Deployment]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_deployments_list_request( + model_publisher=model_publisher, + model_name=model_name, + deployment_type=deployment_type, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.Deployment], + deserialized.get("value", []), ) - raise HttpResponseError(response=response, model=error) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) + + async def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - deserialized = response.iter_bytes() if _decompress else response.iter_raw() + return pipeline_response - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return AsyncItemPaged(get_next, extract_data) - return deserialized # type: ignore + +class IndexesOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. + + Instead, you should access the following operations through + :class:`~azure.ai.projects.aio.AIProjectClient`'s + :attr:`indexes` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") @distributed_trace - def list_session_files( - self, - agent_name: str, - agent_session_id: str, - *, - path: Optional[str] = None, - user_isolation_key: Optional[str] = None, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - before: Optional[str] = None, - **kwargs: Any - ) -> AsyncItemPaged["_models.SessionDirectoryEntry"]: - """List files and directories at a given path in the session sandbox. Returns only the immediate - children of the specified directory (non-recursive). If path is not provided, lists the session - home directory. + def list_versions(self, name: str, **kwargs: Any) -> AsyncItemPaged["_models.Index"]: + """List versions. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param agent_session_id: The session ID. Required. - :type agent_session_id: str - :keyword path: The directory path to list, relative to the session home directory. Defaults to - the home directory if not provided. Default value is None. - :paramtype path: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and - 100, and the - default is 20. Default value is None. - :paramtype limit: int - :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for - ascending order and``desc`` - for descending order. Known values are: "asc" and "desc". Default value is None. - :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - Default value is None. - :paramtype before: str - :return: An iterator like instance of SessionDirectoryEntry - :rtype: - ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.SessionDirectoryEntry] + List all versions of the given Index. + + :param name: The name of the resource. Required. + :type name: str + :return: An iterator like instance of Index + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.Index] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.SessionDirectoryEntry]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.Index]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -4296,39 +4172,59 @@ def list_session_files( } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(_continuation_token=None): + def prepare_request(next_link=None): + if not next_link: + + _request = build_indexes_list_versions_request( + name=name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - _request = build_beta_agents_list_session_files_request( - agent_name=agent_name, - agent_session_id=agent_session_id, - path=path, - user_isolation_key=user_isolation_key, - limit=limit, - order=order, - after=_continuation_token, - before=before, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) return _request async def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.SessionDirectoryEntry], - deserialized.get("entries", []), + List[_models.Index], + deserialized.get("value", []), ) if cls: list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("last_id") or None, AsyncList(list_of_elem) + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) - async def get_next(_continuation_token=None): - _request = prepare_request(_continuation_token) + async def get_next(next_link=None): + _request = prepare_request(next_link) _stream = False pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access @@ -4338,47 +4234,27 @@ async def get_next(_continuation_token=None): if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) return pipeline_response return AsyncItemPaged(get_next, extract_data) - @distributed_trace_async - async def delete_session_file( - self, - agent_name: str, - agent_session_id: str, - *, - path: str, - recursive: Optional[bool] = None, - user_isolation_key: Optional[str] = None, - **kwargs: Any - ) -> None: - """Delete a file or directory from the session sandbox. If ``recursive`` is false (default) and - the target is a non-empty directory, the API returns 409 Conflict. + @distributed_trace + def list(self, **kwargs: Any) -> AsyncItemPaged["_models.Index"]: + """List latest versions. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param agent_session_id: The session ID. Required. - :type agent_session_id: str - :keyword path: The file or directory path to delete, relative to the session home directory. - Required. - :paramtype path: str - :keyword recursive: Whether to recursively delete directory contents. The service defaults to - ``false`` if a value is not specified by the caller. Default value is None. - :paramtype recursive: bool - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :return: None - :rtype: None + List the latest version of each Index. + + :return: An iterator like instance of Index + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.Index] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.Index]] = kwargs.pop("cls", None) + error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -4387,141 +4263,86 @@ async def delete_session_file( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[None] = kwargs.pop("cls", None) - - _request = build_beta_agents_delete_session_file_request( - agent_name=agent_name, - agent_session_id=agent_session_id, - path=path, - recursive=recursive, - user_isolation_key=user_isolation_key, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - - response = pipeline_response.http_response - - if response.status_code not in [204]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - if cls: - return cls(pipeline_response, None, {}) # type: ignore + def prepare_request(next_link=None): + if not next_link: - @overload - async def create_optimization_job( - self, - inputs: _models.OptimizationJobInputs, - *, - operation_id: Optional[str] = None, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.OptimizationJob: - """Creates an agent optimization job. + _request = build_indexes_list_request( + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for - idempotent retry. + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - :param inputs: The optimization job inputs. Required. - :type inputs: ~azure.ai.projects.models.OptimizationJobInputs - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ + return _request - @overload - async def create_optimization_job( - self, inputs: JSON, *, operation_id: Optional[str] = None, content_type: str = "application/json", **kwargs: Any - ) -> _models.OptimizationJob: - """Creates an agent optimization job. + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.Index], + deserialized.get("value", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) - Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for - idempotent retry. + async def get_next(next_link=None): + _request = prepare_request(next_link) - :param inputs: The optimization job inputs. Required. - :type inputs: JSON - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response - @overload - async def create_optimization_job( - self, - inputs: IO[bytes], - *, - operation_id: Optional[str] = None, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.OptimizationJob: - """Creates an agent optimization job. + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for - idempotent retry. + return pipeline_response - :param inputs: The optimization job inputs. Required. - :type inputs: IO[bytes] - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ + return AsyncItemPaged(get_next, extract_data) @distributed_trace_async - async def create_optimization_job( - self, - inputs: Union[_models.OptimizationJobInputs, JSON, IO[bytes]], - *, - operation_id: Optional[str] = None, - **kwargs: Any - ) -> _models.OptimizationJob: - """Creates an agent optimization job. + async def get(self, name: str, version: str, **kwargs: Any) -> _models.Index: + """Get a version. - Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for - idempotent retry. + Get the specific version of the Index. The service returns 404 Not Found error if the Index + does not exist. - :param inputs: The optimization job inputs. Is one of the following types: - OptimizationJobInputs, JSON, IO[bytes] Required. - :type inputs: ~azure.ai.projects.models.OptimizationJobInputs or JSON or IO[bytes] - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the Index to retrieve. Required. + :type version: str + :return: Index. The Index is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Index :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -4532,24 +4353,15 @@ async def create_optimization_job( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) - - content_type = content_type or "application/json" - _content = None - if isinstance(inputs, (IOBase, bytes)): - _content = inputs - else: - _content = json.dumps(inputs, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[_models.Index] = kwargs.pop("cls", None) - _request = build_beta_agents_create_optimization_job_request( - operation_id=operation_id, - content_type=content_type, + _request = build_indexes_get_request( + name=name, + version=version, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -4566,43 +4378,38 @@ async def create_optimization_job( response = pipeline_response.http_response - if response.status_code not in [201]: + if response.status_code not in [200]: if _stream: try: await response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers["Operation-Location"] = self._deserialize("str", response.headers.get("Operation-Location")) - response_headers["Location"] = self._deserialize("str", response.headers.get("Location")) + raise HttpResponseError(response=response) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.OptimizationJob, response.json()) + deserialized = _deserialize(_models.Index, response.json()) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore @distributed_trace_async - async def get_optimization_job(self, job_id: str, **kwargs: Any) -> _models.OptimizationJob: - """Get info about an agent optimization job. + async def delete(self, name: str, version: str, **kwargs: Any) -> None: + """Delete a version. - Get an optimization job by id. Returns 202 while in progress, 200 when terminal. + Delete the specific version of the Index. The service returns 204 No Content if the Index was + deleted successfully or if the Index does not exist. - :param job_id: The ID of the job. Required. - :type job_id: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob + :param name: The name of the resource. Required. + :type name: str + :param version: The version of the Index to delete. Required. + :type version: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -4616,10 +4423,11 @@ async def get_optimization_job(self, job_id: str, **kwargs: Any) -> _models.Opti _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) + cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_beta_agents_get_optimization_job_request( - job_id=job_id, + _request = build_indexes_delete_request( + name=name, + version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -4629,151 +4437,115 @@ async def get_optimization_job(self, job_id: str, **kwargs: Any) -> _models.Opti } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = False pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200, 202]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass + if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.OptimizationJob, response.json()) + raise HttpResponseError(response=response) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore - - return deserialized # type: ignore + return cls(pipeline_response, None, {}) # type: ignore - @distributed_trace - def list_optimization_jobs( + @overload + async def create_or_update( self, + name: str, + version: str, + index: _models.Index, *, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - before: Optional[str] = None, - status: Optional[Union[str, _models.JobStatus]] = None, - agent_name: Optional[str] = None, + content_type: str = "application/merge-patch+json", **kwargs: Any - ) -> AsyncItemPaged["_models.OptimizationJob"]: - """Returns a list of agent optimization jobs. + ) -> _models.Index: + """Create or update a version. - List optimization jobs. Supports cursor pagination and optional status / agent_name filters. + Create a new or update an existing Index with the given version id. - :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and - 100, and the - default is 20. Default value is None. - :paramtype limit: int - :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for - ascending order and``desc`` - for descending order. Known values are: "asc" and "desc". Default value is None. - :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - Default value is None. - :paramtype before: str - :keyword status: Filter to jobs in this lifecycle state. Known values are: "queued", - "in_progress", "succeeded", "failed", and "cancelled". Default value is None. - :paramtype status: str or ~azure.ai.projects.models.JobStatus - :keyword agent_name: Filter to jobs targeting this agent name. Default value is None. - :paramtype agent_name: str - :return: An iterator like instance of OptimizationJob - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.OptimizationJob] + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the Index to create or update. Required. + :type version: str + :param index: The Index to create or update. Required. + :type index: ~azure.ai.projects.models.Index + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: Index. The Index is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Index :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.OptimizationJob]] = kwargs.pop("cls", None) - - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(_continuation_token=None): - - _request = build_beta_agents_list_optimization_jobs_request( - limit=limit, - order=order, - after=_continuation_token, - before=before, - status=status, - agent_name=agent_name, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - return _request - async def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.OptimizationJob], - deserialized.get("data", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("last_id") or None, AsyncList(list_of_elem) + @overload + async def create_or_update( + self, name: str, version: str, index: JSON, *, content_type: str = "application/merge-patch+json", **kwargs: Any + ) -> _models.Index: + """Create or update a version. - async def get_next(_continuation_token=None): - _request = prepare_request(_continuation_token) + Create a new or update an existing Index with the given version id. - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the Index to create or update. Required. + :type version: str + :param index: The Index to create or update. Required. + :type index: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: Index. The Index is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Index + :raises ~azure.core.exceptions.HttpResponseError: + """ - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + @overload + async def create_or_update( + self, + name: str, + version: str, + index: IO[bytes], + *, + content_type: str = "application/merge-patch+json", + **kwargs: Any + ) -> _models.Index: + """Create or update a version. - return pipeline_response + Create a new or update an existing Index with the given version id. - return AsyncItemPaged(get_next, extract_data) + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the Index to create or update. Required. + :type version: str + :param index: The Index to create or update. Required. + :type index: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: Index. The Index is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Index + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace_async - async def cancel_optimization_job(self, job_id: str, **kwargs: Any) -> _models.OptimizationJob: - """Cancels an agent optimization job. + async def create_or_update( + self, name: str, version: str, index: Union[_models.Index, JSON, IO[bytes]], **kwargs: Any + ) -> _models.Index: + """Create or update a version. - Request cancellation. Idempotent on terminal states. + Create a new or update an existing Index with the given version id. - :param job_id: The ID of the job to cancel. Required. - :type job_id: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the Index to create or update. Required. + :type version: str + :param index: The Index to create or update. Is one of the following types: Index, JSON, + IO[bytes] Required. + :type index: ~azure.ai.projects.models.Index or JSON or IO[bytes] + :return: Index. The Index is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Index :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -4784,14 +4556,25 @@ async def cancel_optimization_job(self, job_id: str, **kwargs: Any) -> _models.O } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.Index] = kwargs.pop("cls", None) - _request = build_beta_agents_cancel_optimization_job_request( - job_id=job_id, + content_type = content_type or "application/merge-patch+json" + _content = None + if isinstance(index, (IOBase, bytes)): + _content = index + else: + _content = json.dumps(index, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_indexes_create_or_update_request( + name=name, + version=version, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -4808,127 +4591,163 @@ async def cancel_optimization_job(self, job_id: str, **kwargs: Any) -> _models.O response = pipeline_response.http_response - if response.status_code not in [200]: + if response.status_code not in [200, 201]: if _stream: try: await response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.OptimizationJob, response.json()) + deserialized = _deserialize(_models.Index, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - @distributed_trace_async - async def delete_optimization_job(self, job_id: str, *, force: Optional[bool] = None, **kwargs: Any) -> None: - """Deletes an agent optimization job. - Delete the job and its candidate artifacts. Cancels first if non-terminal. +class ToolboxesOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. - :param job_id: The ID of the job to delete. Required. - :type job_id: str - :keyword force: When true, force-delete even if the job is in a non-terminal state. Default - value is None. - :paramtype force: bool - :return: None - :rtype: None + Instead, you should access the following operations through + :class:`~azure.ai.projects.aio.AIProjectClient`'s + :attr:`toolboxes` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + + @overload + async def create_version( + self, + name: str, + *, + tools: List[_models.ToolboxTool], + content_type: str = "application/json", + description: Optional[str] = None, + metadata: Optional[dict[str, str]] = None, + skills: Optional[List[_models.ToolboxSkill]] = None, + policies: Optional[_models.ToolboxPolicies] = None, + **kwargs: Any + ) -> _models.ToolboxVersionObject: + """Create a new version of a toolbox. + + Creates a new toolbox version, provisioning the toolbox itself if it does not already exist. + + :param name: The name of the toolbox. If the toolbox does not exist, it will be created. + Required. + :type name: str + :keyword tools: The list of tools to include in this version. Required. + :paramtype tools: list[~azure.ai.projects.models.ToolboxTool] + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword description: A human-readable description of the toolbox. Default value is None. + :paramtype description: str + :keyword metadata: Arbitrary key-value metadata to associate with the toolbox. Default value is + None. + :paramtype metadata: dict[str, str] + :keyword skills: The list of skill sources to include in this version. A skill reference + specifies a skill name and optionally a version. If version is omitted, the skill's default + version is used. Default value is None. + :paramtype skills: list[~azure.ai.projects.models.ToolboxSkill] + :keyword policies: Policy configuration for this toolbox version. Default value is None. + :paramtype policies: ~azure.ai.projects.models.ToolboxPolicies + :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxVersionObject :raises ~azure.core.exceptions.HttpResponseError: """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + @overload + async def create_version( + self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.ToolboxVersionObject: + """Create a new version of a toolbox. - _request = build_beta_agents_delete_optimization_job_request( - job_id=job_id, - force=force, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + Creates a new toolbox version, provisioning the toolbox itself if it does not already exist. - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + :param name: The name of the toolbox. If the toolbox does not exist, it will be created. + Required. + :type name: str + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxVersionObject + :raises ~azure.core.exceptions.HttpResponseError: + """ - response = pipeline_response.http_response + @overload + async def create_version( + self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.ToolboxVersionObject: + """Create a new version of a toolbox. - if response.status_code not in [204]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + Creates a new toolbox version, provisioning the toolbox itself if it does not already exist. - if cls: - return cls(pipeline_response, None, {}) # type: ignore + :param name: The name of the toolbox. If the toolbox does not exist, it will be created. + Required. + :type name: str + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxVersionObject + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace_async - async def list_optimization_candidates( + async def create_version( self, - job_id: str, + name: str, + body: Union[JSON, IO[bytes]] = _Unset, *, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - after: Optional[str] = None, - before: Optional[str] = None, + tools: List[_models.ToolboxTool] = _Unset, + description: Optional[str] = None, + metadata: Optional[dict[str, str]] = None, + skills: Optional[List[_models.ToolboxSkill]] = None, + policies: Optional[_models.ToolboxPolicies] = None, **kwargs: Any - ) -> _models.AgentsPagedResultOptimizationCandidate: - """Returns a list of candidates for an optimization job. + ) -> _models.ToolboxVersionObject: + """Create a new version of a toolbox. - List candidates produced by a job. + Creates a new toolbox version, provisioning the toolbox itself if it does not already exist. - :param job_id: The optimization job id. Required. - :type job_id: str - :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and - 100, and the - default is 20. Default value is None. - :paramtype limit: int - :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for - ascending order and``desc`` - for descending order. Known values are: "asc" and "desc". Default value is None. - :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword after: A cursor for use in pagination. ``after`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include after=obj_foo in order to fetch the next page of the list. Default - value is None. - :paramtype after: str - :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - Default value is None. - :paramtype before: str - :return: AgentsPagedResultOptimizationCandidate. The AgentsPagedResultOptimizationCandidate is - compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentsPagedResultOptimizationCandidate + :param name: The name of the toolbox. If the toolbox does not exist, it will be created. + Required. + :type name: str + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword tools: The list of tools to include in this version. Required. + :paramtype tools: list[~azure.ai.projects.models.ToolboxTool] + :keyword description: A human-readable description of the toolbox. Default value is None. + :paramtype description: str + :keyword metadata: Arbitrary key-value metadata to associate with the toolbox. Default value is + None. + :paramtype metadata: dict[str, str] + :keyword skills: The list of skill sources to include in this version. A skill reference + specifies a skill name and optionally a version. If version is omitted, the skill's default + version is used. Default value is None. + :paramtype skills: list[~azure.ai.projects.models.ToolboxSkill] + :keyword policies: Policy configuration for this toolbox version. Default value is None. + :paramtype policies: ~azure.ai.projects.models.ToolboxPolicies + :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxVersionObject :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -4939,18 +4758,35 @@ async def list_optimization_candidates( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.AgentsPagedResultOptimizationCandidate] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.ToolboxVersionObject] = kwargs.pop("cls", None) - _request = build_beta_agents_list_optimization_candidates_request( - job_id=job_id, - limit=limit, - order=order, - after=after, - before=before, + if body is _Unset: + if tools is _Unset: + raise TypeError("missing required argument: tools") + body = { + "description": description, + "metadata": metadata, + "policies": policies, + "skills": skills, + "tools": tools, + } + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_toolboxes_create_version_request( + name=name, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -4983,7 +4819,7 @@ async def list_optimization_candidates( if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.AgentsPagedResultOptimizationCandidate, response.json()) + deserialized = _deserialize(_models.ToolboxVersionObject, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -4991,19 +4827,15 @@ async def list_optimization_candidates( return deserialized # type: ignore @distributed_trace_async - async def get_optimization_candidate( - self, job_id: str, candidate_id: str, **kwargs: Any - ) -> _models.CandidateMetadata: - """Get a candidate by id. + async def get(self, name: str, **kwargs: Any) -> _models.ToolboxObject: + """Retrieve a toolbox. - Get a single candidate's metadata, manifest, and promotion info. + Retrieves the specified toolbox and its current configuration. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id. Required. - :type candidate_id: str - :return: CandidateMetadata. The CandidateMetadata is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.CandidateMetadata + :param name: The name of the toolbox to retrieve. Required. + :type name: str + :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxObject :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -5017,11 +4849,10 @@ async def get_optimization_candidate( _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.CandidateMetadata] = kwargs.pop("cls", None) + cls: ClsType[_models.ToolboxObject] = kwargs.pop("cls", None) - _request = build_beta_agents_get_optimization_candidate_request( - job_id=job_id, - candidate_id=candidate_id, + _request = build_toolboxes_get_request( + name=name, api_version=self._config.api_version, headers=_headers, params=_params, @@ -5055,30 +4886,49 @@ async def get_optimization_candidate( if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.CandidateMetadata, response.json()) + deserialized = _deserialize(_models.ToolboxObject, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - @distributed_trace_async - async def get_optimization_candidate_config( - self, job_id: str, candidate_id: str, **kwargs: Any - ) -> _models.CandidateDeployConfig: - """Get candidate deploy config. + @distributed_trace + def list( + self, + *, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + before: Optional[str] = None, + **kwargs: Any + ) -> AsyncItemPaged["_models.ToolboxObject"]: + """List toolboxes. - Get the candidate's deploy config JSON. Used to compose ``agents.create_version(...)`` from a - candidate. + Returns the toolboxes available in the current project. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id. Required. - :type candidate_id: str - :return: CandidateDeployConfig. The CandidateDeployConfig is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.CandidateDeployConfig + :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the + default is 20. Default value is None. + :paramtype limit: int + :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for + ascending order and``desc`` + for descending order. Known values are: "asc" and "desc". Default value is None. + :paramtype order: str or ~azure.ai.projects.models.PageOrder + :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your + place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + Default value is None. + :paramtype before: str + :return: An iterator like instance of ToolboxObject + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.ToolboxObject] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.ToolboxObject]] = kwargs.pop("cls", None) + error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -5087,70 +4937,93 @@ async def get_optimization_candidate_config( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[_models.CandidateDeployConfig] = kwargs.pop("cls", None) + def prepare_request(_continuation_token=None): - _request = build_beta_agents_get_optimization_candidate_config_request( - job_id=job_id, - candidate_id=candidate_id, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + _request = build_toolboxes_list_request( + limit=limit, + order=order, + after=_continuation_token, + before=before, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.ToolboxObject], + deserialized.get("data", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("last_id") or None, AsyncList(list_of_elem) - response = pipeline_response.http_response + async def get_next(_continuation_token=None): + _request = prepare_request(_continuation_token) - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs ) - raise HttpResponseError(response=response, model=error) + response = pipeline_response.http_response - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.CandidateDeployConfig, response.json()) + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return pipeline_response - return deserialized # type: ignore + return AsyncItemPaged(get_next, extract_data) - @distributed_trace_async - async def get_optimization_candidate_results( - self, job_id: str, candidate_id: str, **kwargs: Any - ) -> _models.CandidateResults: - """Get candidate evaluation results. + @distributed_trace + def list_versions( + self, + name: str, + *, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + before: Optional[str] = None, + **kwargs: Any + ) -> AsyncItemPaged["_models.ToolboxVersionObject"]: + """List toolbox versions. - Get full per-task evaluation results for a candidate. + Returns the available versions for the specified toolbox. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id. Required. - :type candidate_id: str - :return: CandidateResults. The CandidateResults is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.CandidateResults + :param name: The name of the toolbox to list versions for. Required. + :type name: str + :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the + default is 20. Default value is None. + :paramtype limit: int + :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for + ascending order and``desc`` + for descending order. Known values are: "asc" and "desc". Default value is None. + :paramtype order: str or ~azure.ai.projects.models.PageOrder + :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your + place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + Default value is None. + :paramtype before: str + :return: An iterator like instance of ToolboxVersionObject + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.ToolboxVersionObject] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.ToolboxVersionObject]] = kwargs.pop("cls", None) + error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -5159,70 +5032,67 @@ async def get_optimization_candidate_results( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[_models.CandidateResults] = kwargs.pop("cls", None) + def prepare_request(_continuation_token=None): - _request = build_beta_agents_get_optimization_candidate_results_request( - job_id=job_id, - candidate_id=candidate_id, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + _request = build_toolboxes_list_versions_request( + name=name, + limit=limit, + order=order, + after=_continuation_token, + before=before, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.ToolboxVersionObject], + deserialized.get("data", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("last_id") or None, AsyncList(list_of_elem) - response = pipeline_response.http_response + async def get_next(_continuation_token=None): + _request = prepare_request(_continuation_token) - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs ) - raise HttpResponseError(response=response, model=error) + response = pipeline_response.http_response - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.CandidateResults, response.json()) + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return pipeline_response - return deserialized # type: ignore + return AsyncItemPaged(get_next, extract_data) @distributed_trace_async - async def get_candidate_file( - self, job_id: str, candidate_id: str, *, path: str, **kwargs: Any - ) -> AsyncIterator[bytes]: - """Get a candidate file. + async def get_version(self, name: str, version: str, **kwargs: Any) -> _models.ToolboxVersionObject: + """Retrieve a specific version of a toolbox. - Stream a specific file from the candidate's blob directory. + Retrieves the specified version of a toolbox by name and version identifier. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id. Required. - :type candidate_id: str - :keyword path: Relative path of the file to download (e.g. 'files/examples.jsonl'). Required. - :paramtype path: str - :return: AsyncIterator[bytes] - :rtype: AsyncIterator[bytes] + :param name: The name of the toolbox. Required. + :type name: str + :param version: The version identifier to retrieve. Required. + :type version: str + :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxVersionObject :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -5236,12 +5106,11 @@ async def get_candidate_file( _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) + cls: ClsType[_models.ToolboxVersionObject] = kwargs.pop("cls", None) - _request = build_beta_agents_get_candidate_file_request( - job_id=job_id, - candidate_id=candidate_id, - path=path, + _request = build_toolboxes_get_version_request( + name=name, + version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -5252,7 +5121,7 @@ async def get_candidate_file( _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -5272,7 +5141,10 @@ async def get_candidate_file( ) raise HttpResponseError(response=response, model=error) - deserialized = response.iter_bytes() if _decompress else response.iter_raw() + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.ToolboxVersionObject, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -5280,114 +5152,83 @@ async def get_candidate_file( return deserialized # type: ignore @overload - async def promote_candidate( - self, - job_id: str, - candidate_id: str, - candidate_request: _models.PromoteCandidateRequest, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.PromoteCandidateResponse: - """Promote a candidate. + async def update( + self, name: str, *, default_version: str, content_type: str = "application/json", **kwargs: Any + ) -> _models.ToolboxObject: + """Update a toolbox to point to a specific version. - Promotes a candidate, recording the deployment timestamp and target agent version. + Updates the toolbox's default version pointer to the specified version. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id to promote. Required. - :type candidate_id: str - :param candidate_request: Promotion details. Required. - :type candidate_request: ~azure.ai.projects.models.PromoteCandidateRequest + :param name: The name of the toolbox to update. Required. + :type name: str + :keyword default_version: The version identifier that the toolbox should point to. When set, + the toolbox's default version will resolve to this version instead of the latest. Required. + :paramtype default_version: str :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str - :return: PromoteCandidateResponse. The PromoteCandidateResponse is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.PromoteCandidateResponse + :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxObject :raises ~azure.core.exceptions.HttpResponseError: """ @overload - async def promote_candidate( - self, - job_id: str, - candidate_id: str, - candidate_request: JSON, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.PromoteCandidateResponse: - """Promote a candidate. + async def update( + self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.ToolboxObject: + """Update a toolbox to point to a specific version. - Promotes a candidate, recording the deployment timestamp and target agent version. + Updates the toolbox's default version pointer to the specified version. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id to promote. Required. - :type candidate_id: str - :param candidate_request: Promotion details. Required. - :type candidate_request: JSON + :param name: The name of the toolbox to update. Required. + :type name: str + :param body: Required. + :type body: JSON :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str - :return: PromoteCandidateResponse. The PromoteCandidateResponse is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.PromoteCandidateResponse + :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxObject :raises ~azure.core.exceptions.HttpResponseError: """ @overload - async def promote_candidate( - self, - job_id: str, - candidate_id: str, - candidate_request: IO[bytes], - *, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.PromoteCandidateResponse: - """Promote a candidate. + async def update( + self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.ToolboxObject: + """Update a toolbox to point to a specific version. - Promotes a candidate, recording the deployment timestamp and target agent version. + Updates the toolbox's default version pointer to the specified version. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id to promote. Required. - :type candidate_id: str - :param candidate_request: Promotion details. Required. - :type candidate_request: IO[bytes] + :param name: The name of the toolbox to update. Required. + :type name: str + :param body: Required. + :type body: IO[bytes] :keyword content_type: Body Parameter content-type. Content type parameter for binary body. Default value is "application/json". :paramtype content_type: str - :return: PromoteCandidateResponse. The PromoteCandidateResponse is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.PromoteCandidateResponse + :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxObject :raises ~azure.core.exceptions.HttpResponseError: """ @distributed_trace_async - async def promote_candidate( - self, - job_id: str, - candidate_id: str, - candidate_request: Union[_models.PromoteCandidateRequest, JSON, IO[bytes]], - **kwargs: Any - ) -> _models.PromoteCandidateResponse: - """Promote a candidate. + async def update( + self, name: str, body: Union[JSON, IO[bytes]] = _Unset, *, default_version: str = _Unset, **kwargs: Any + ) -> _models.ToolboxObject: + """Update a toolbox to point to a specific version. - Promotes a candidate, recording the deployment timestamp and target agent version. + Updates the toolbox's default version pointer to the specified version. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id to promote. Required. - :type candidate_id: str - :param candidate_request: Promotion details. Is one of the following types: - PromoteCandidateRequest, JSON, IO[bytes] Required. - :type candidate_request: ~azure.ai.projects.models.PromoteCandidateRequest or JSON or IO[bytes] - :return: PromoteCandidateResponse. The PromoteCandidateResponse is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.PromoteCandidateResponse + :param name: The name of the toolbox to update. Required. + :type name: str + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword default_version: The version identifier that the toolbox should point to. When set, + the toolbox's default version will resolve to this version instead of the latest. Required. + :paramtype default_version: str + :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxObject :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -5402,18 +5243,22 @@ async def promote_candidate( _params = kwargs.pop("params", {}) or {} content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.PromoteCandidateResponse] = kwargs.pop("cls", None) + cls: ClsType[_models.ToolboxObject] = kwargs.pop("cls", None) + if body is _Unset: + if default_version is _Unset: + raise TypeError("missing required argument: default_version") + body = {"default_version": default_version} + body = {k: v for k, v in body.items() if v is not None} content_type = content_type or "application/json" _content = None - if isinstance(candidate_request, (IOBase, bytes)): - _content = candidate_request + if isinstance(body, (IOBase, bytes)): + _content = body else: - _content = json.dumps(candidate_request, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - _request = build_beta_agents_promote_candidate_request( - job_id=job_id, - candidate_id=candidate_id, + _request = build_toolboxes_update_request( + name=name, content_type=content_type, api_version=self._config.api_version, content=_content, @@ -5449,13 +5294,124 @@ async def promote_candidate( if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.PromoteCandidateResponse, response.json()) + deserialized = _deserialize(_models.ToolboxObject, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore + @distributed_trace_async + async def delete(self, name: str, **kwargs: Any) -> None: + """Delete a toolbox. + + Removes the specified toolbox along with all of its versions. + + :param name: The name of the toolbox to delete. Required. + :type name: str + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[None] = kwargs.pop("cls", None) + + _request = build_toolboxes_delete_request( + name=name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) # type: ignore + + @distributed_trace_async + async def delete_version(self, name: str, version: str, **kwargs: Any) -> None: + """Delete a specific version of a toolbox. + + Removes the specified version of a toolbox. + + :param name: The name of the toolbox. Required. + :type name: str + :param version: The version identifier to delete. Required. + :type version: str + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[None] = kwargs.pop("cls", None) + + _request = build_toolboxes_delete_version_request( + name=name, + version=version, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) # type: ignore + class BetaEvaluationTaxonomiesOperations: """ @@ -5476,7 +5432,9 @@ def __init__(self, *args, **kwargs) -> None: @distributed_trace_async async def get(self, name: str, **kwargs: Any) -> _models.EvaluationTaxonomy: - """Get an evaluation run by name. + """Get an evaluation taxonomy. + + Retrieves the specified evaluation taxonomy. :param name: The name of the resource. Required. :type name: str @@ -5541,6 +5499,9 @@ def list( ) -> AsyncItemPaged["_models.EvaluationTaxonomy"]: """List evaluation taxonomies. + Returns the evaluation taxonomies available in the project, optionally filtered by input name + or input type. + :keyword input_name: Filter by the evaluation input name. Default value is None. :paramtype input_name: str :keyword input_type: Filter by taxonomy input type. Default value is None. @@ -5633,7 +5594,9 @@ async def get_next(next_link=None): @distributed_trace_async async def delete(self, name: str, **kwargs: Any) -> None: - """Delete an evaluation taxonomy by name. + """Delete an evaluation taxonomy. + + Removes the specified evaluation taxonomy from the project. :param name: The name of the resource. Required. :type name: str @@ -5685,6 +5648,8 @@ async def create( ) -> _models.EvaluationTaxonomy: """Create an evaluation taxonomy. + Creates or replaces the specified evaluation taxonomy with the provided definition. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -5703,6 +5668,8 @@ async def create( ) -> _models.EvaluationTaxonomy: """Create an evaluation taxonomy. + Creates or replaces the specified evaluation taxonomy with the provided definition. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -5721,6 +5688,8 @@ async def create( ) -> _models.EvaluationTaxonomy: """Create an evaluation taxonomy. + Creates or replaces the specified evaluation taxonomy with the provided definition. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -5739,6 +5708,8 @@ async def create( ) -> _models.EvaluationTaxonomy: """Create an evaluation taxonomy. + Creates or replaces the specified evaluation taxonomy with the provided definition. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Is one of the following types: EvaluationTaxonomy, @@ -5815,6 +5786,8 @@ async def update( ) -> _models.EvaluationTaxonomy: """Update an evaluation taxonomy. + Update an evaluation taxonomy. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -5833,6 +5806,8 @@ async def update( ) -> _models.EvaluationTaxonomy: """Update an evaluation taxonomy. + Update an evaluation taxonomy. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -5851,6 +5826,8 @@ async def update( ) -> _models.EvaluationTaxonomy: """Update an evaluation taxonomy. + Update an evaluation taxonomy. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -5869,6 +5846,8 @@ async def update( ) -> _models.EvaluationTaxonomy: """Update an evaluation taxonomy. + Update an evaluation taxonomy. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Is one of the following types: EvaluationTaxonomy, @@ -5966,7 +5945,9 @@ def list_versions( limit: Optional[int] = None, **kwargs: Any ) -> AsyncItemPaged["_models.EvaluatorVersion"]: - """List all versions of the given evaluator. + """List evaluator versions. + + Returns the available versions for the specified evaluator. :param name: The name of the resource. Required. :type name: str @@ -6072,7 +6053,9 @@ def list( limit: Optional[int] = None, **kwargs: Any ) -> AsyncItemPaged["_models.EvaluatorVersion"]: - """List the latest version of each evaluator. + """List latest evaluator versions. + + Lists the latest version of each evaluator. :keyword type: Filter evaluators by type. Possible values: 'all', 'custom', 'builtin'. Is one of the following types: Literal["builtin"], Literal["custom"], Literal["all"], str Default @@ -6169,8 +6152,9 @@ async def get_next(next_link=None): @distributed_trace_async async def get_version(self, name: str, version: str, **kwargs: Any) -> _models.EvaluatorVersion: - """Get the specific version of the EvaluatorVersion. The service returns 404 Not Found error if - the EvaluatorVersion does not exist. + """Get an evaluator version. + + Retrieves the specified evaluator version, returning 404 if it does not exist. :param name: The name of the resource. Required. :type name: str @@ -6234,8 +6218,9 @@ async def get_version(self, name: str, version: str, **kwargs: Any) -> _models.E @distributed_trace_async async def delete_version(self, name: str, version: str, **kwargs: Any) -> None: - """Delete the specific version of the EvaluatorVersion. The service returns 204 No Content if the - EvaluatorVersion was deleted successfully or if the EvaluatorVersion does not exist. + """Delete an evaluator version. + + Removes the specified evaluator version. Returns 204 whether the version existed or not. :param name: The name of the resource. Required. :type name: str @@ -6293,7 +6278,9 @@ async def create_version( content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Create a new EvaluatorVersion with auto incremented version id. + """Create an evaluator version. + + Creates a new evaluator version with an auto-incremented version identifier. :param name: The name of the resource. Required. :type name: str @@ -6311,7 +6298,9 @@ async def create_version( async def create_version( self, name: str, evaluator_version: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Create a new EvaluatorVersion with auto incremented version id. + """Create an evaluator version. + + Creates a new evaluator version with an auto-incremented version identifier. :param name: The name of the resource. Required. :type name: str @@ -6329,7 +6318,9 @@ async def create_version( async def create_version( self, name: str, evaluator_version: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Create a new EvaluatorVersion with auto incremented version id. + """Create an evaluator version. + + Creates a new evaluator version with an auto-incremented version identifier. :param name: The name of the resource. Required. :type name: str @@ -6347,7 +6338,9 @@ async def create_version( async def create_version( self, name: str, evaluator_version: Union[_models.EvaluatorVersion, JSON, IO[bytes]], **kwargs: Any ) -> _models.EvaluatorVersion: - """Create a new EvaluatorVersion with auto incremented version id. + """Create an evaluator version. + + Creates a new evaluator version with an auto-incremented version identifier. :param name: The name of the resource. Required. :type name: str @@ -6429,7 +6422,9 @@ async def update_version( content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Update an existing EvaluatorVersion with the given version id. + """Update an evaluator version. + + Updates the specified evaluator version in place. :param name: The name of the resource. Required. :type name: str @@ -6449,7 +6444,9 @@ async def update_version( async def update_version( self, name: str, version: str, evaluator_version: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Update an existing EvaluatorVersion with the given version id. + """Update an evaluator version. + + Updates the specified evaluator version in place. :param name: The name of the resource. Required. :type name: str @@ -6475,7 +6472,9 @@ async def update_version( content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Update an existing EvaluatorVersion with the given version id. + """Update an evaluator version. + + Updates the specified evaluator version in place. :param name: The name of the resource. Required. :type name: str @@ -6499,7 +6498,9 @@ async def update_version( evaluator_version: Union[_models.EvaluatorVersion, JSON, IO[bytes]], **kwargs: Any ) -> _models.EvaluatorVersion: - """Update an existing EvaluatorVersion with the given version id. + """Update an evaluator version. + + Updates the specified evaluator version in place. :param name: The name of the resource. Required. :type name: str @@ -6584,7 +6585,10 @@ async def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of an evaluator for a specific version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified evaluator + version. :param name: Required. :type name: str @@ -6610,7 +6614,10 @@ async def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of an evaluator for a specific version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified evaluator + version. :param name: Required. :type name: str @@ -6636,7 +6643,10 @@ async def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of an evaluator for a specific version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified evaluator + version. :param name: Required. :type name: str @@ -6660,7 +6670,10 @@ async def pending_upload( pending_upload_request: Union[_models.PendingUploadRequest, JSON, IO[bytes]], **kwargs: Any ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of an evaluator for a specific version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified evaluator + version. :param name: Required. :type name: str @@ -6750,7 +6763,10 @@ async def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get the SAS credential to access the storage account associated with an Evaluator version. + """Get evaluator credentials. + + Retrieves SAS credentials for accessing the storage account associated with the specified + evaluator version. :param name: Required. :type name: str @@ -6776,7 +6792,10 @@ async def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get the SAS credential to access the storage account associated with an Evaluator version. + """Get evaluator credentials. + + Retrieves SAS credentials for accessing the storage account associated with the specified + evaluator version. :param name: Required. :type name: str @@ -6802,7 +6821,10 @@ async def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get the SAS credential to access the storage account associated with an Evaluator version. + """Get evaluator credentials. + + Retrieves SAS credentials for accessing the storage account associated with the specified + evaluator version. :param name: Required. :type name: str @@ -6826,7 +6848,10 @@ async def get_credentials( credential_request: Union[_models.EvaluatorCredentialRequest, JSON, IO[bytes]], **kwargs: Any ) -> _models.DatasetCredential: - """Get the SAS credential to access the storage account associated with an Evaluator version. + """Get evaluator credentials. + + Retrieves SAS credentials for accessing the storage account associated with the specified + evaluator version. :param name: Required. :type name: str @@ -6915,7 +6940,7 @@ async def create_generation_job( content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorGenerationJob: - """Creates an evaluator generation job. + """Create an evaluator generation job. Creates an evaluator generation job. The service generates rubric-based evaluator definitions from the provided source materials asynchronously. @@ -6937,7 +6962,7 @@ async def create_generation_job( async def create_generation_job( self, job: JSON, *, operation_id: Optional[str] = None, content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorGenerationJob: - """Creates an evaluator generation job. + """Create an evaluator generation job. Creates an evaluator generation job. The service generates rubric-based evaluator definitions from the provided source materials asynchronously. @@ -6964,7 +6989,7 @@ async def create_generation_job( content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorGenerationJob: - """Creates an evaluator generation job. + """Create an evaluator generation job. Creates an evaluator generation job. The service generates rubric-based evaluator definitions from the provided source materials asynchronously. @@ -6990,7 +7015,7 @@ async def create_generation_job( operation_id: Optional[str] = None, **kwargs: Any ) -> _models.EvaluatorGenerationJob: - """Creates an evaluator generation job. + """Create an evaluator generation job. Creates an evaluator generation job. The service generates rubric-based evaluator definitions from the provided source materials asynchronously. @@ -7076,7 +7101,7 @@ async def create_generation_job( @distributed_trace_async async def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.EvaluatorGenerationJob: - """Get info about an evaluator generation job. + """Get an evaluator generation job. Gets the details of an evaluator generation job by its ID. @@ -7153,9 +7178,11 @@ def list_generation_jobs( before: Optional[str] = None, **kwargs: Any ) -> AsyncItemPaged["_models.EvaluatorGenerationJob"]: - """Returns a list of evaluator generation jobs. + """List evaluator generation jobs. - Returns a list of evaluator generation jobs. + Returns a list of evaluator generation jobs. The List API has up to a few seconds of + propagation delay, so a recently created job may not appear immediately; use the Get evaluator + generation job API with the job ID to retrieve a specific job without delay. :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the @@ -7239,7 +7266,7 @@ async def get_next(_continuation_token=None): @distributed_trace_async async def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.EvaluatorGenerationJob: - """Cancels an evaluator generation job. + """Cancel an evaluator generation job. Cancels an evaluator generation job by its ID. @@ -7306,7 +7333,9 @@ async def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.Eva @distributed_trace_async async def delete_generation_job(self, job_id: str, **kwargs: Any) -> None: - """Deletes an evaluator generation job by its ID. Deletes the job record only; the generated + """Delete an evaluator generation job. + + Deletes an evaluator generation job by its ID. Deletes the job record only; the generated evaluator (if any) is preserved. :param job_id: The ID of the job to delete. Required. @@ -7379,7 +7408,9 @@ def __init__(self, *args, **kwargs) -> None: async def generate( self, insight: _models.Insight, *, content_type: str = "application/json", **kwargs: Any ) -> _models.Insight: - """Generate Insights. + """Generate insights. + + Generates an insights report from the provided evaluation configuration. :param insight: Complete evaluation configuration including data source, evaluators, and result settings. Required. @@ -7396,7 +7427,9 @@ async def generate( async def generate( self, insight: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.Insight: - """Generate Insights. + """Generate insights. + + Generates an insights report from the provided evaluation configuration. :param insight: Complete evaluation configuration including data source, evaluators, and result settings. Required. @@ -7413,7 +7446,9 @@ async def generate( async def generate( self, insight: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.Insight: - """Generate Insights. + """Generate insights. + + Generates an insights report from the provided evaluation configuration. :param insight: Complete evaluation configuration including data source, evaluators, and result settings. Required. @@ -7428,7 +7463,9 @@ async def generate( @distributed_trace_async async def generate(self, insight: Union[_models.Insight, JSON, IO[bytes]], **kwargs: Any) -> _models.Insight: - """Generate Insights. + """Generate insights. + + Generates an insights report from the provided evaluation configuration. :param insight: Complete evaluation configuration including data source, evaluators, and result settings. Is one of the following types: Insight, JSON, IO[bytes] Required. @@ -7505,7 +7542,9 @@ async def generate(self, insight: Union[_models.Insight, JSON, IO[bytes]], **kwa async def get( self, insight_id: str, *, include_coordinates: Optional[bool] = None, **kwargs: Any ) -> _models.Insight: - """Get a specific insight by Id. + """Get an insight. + + Retrieves the specified insight report and its results. :param insight_id: The unique identifier for the insights report. Required. :type insight_id: str @@ -7583,7 +7622,9 @@ def list( include_coordinates: Optional[bool] = None, **kwargs: Any ) -> AsyncItemPaged["_models.Insight"]: - """List all insights in reverse chronological order (newest first). + """List insights. + + Returns insights in reverse chronological order, with the most recent entries first. :keyword type: Filter by the type of analysis. Known values are: "EvaluationRunClusterInsight", "AgentClusterInsight", and "EvaluationComparison". Default value is None. @@ -7721,6 +7762,8 @@ async def create( ) -> _models.MemoryStoreDetails: """Create a memory store. + Creates a memory store resource with the provided configuration. + :keyword name: The name of the memory store. Required. :paramtype name: str :keyword definition: The memory store definition. Required. @@ -7744,6 +7787,8 @@ async def create( ) -> _models.MemoryStoreDetails: """Create a memory store. + Creates a memory store resource with the provided configuration. + :param body: Required. :type body: JSON :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. @@ -7760,6 +7805,8 @@ async def create( ) -> _models.MemoryStoreDetails: """Create a memory store. + Creates a memory store resource with the provided configuration. + :param body: Required. :type body: IO[bytes] :keyword content_type: Body Parameter content-type. Content type parameter for binary body. @@ -7783,6 +7830,8 @@ async def create( ) -> _models.MemoryStoreDetails: """Create a memory store. + Creates a memory store resource with the provided configuration. + :param body: Is either a JSON type or a IO[bytes] type. Required. :type body: JSON or IO[bytes] :keyword name: The name of the memory store. Required. @@ -7881,6 +7930,8 @@ async def update( ) -> _models.MemoryStoreDetails: """Update a memory store. + Updates the specified memory store with the supplied configuration changes. + :param name: The name of the memory store to update. Required. :type name: str :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. @@ -7902,6 +7953,8 @@ async def update( ) -> _models.MemoryStoreDetails: """Update a memory store. + Updates the specified memory store with the supplied configuration changes. + :param name: The name of the memory store to update. Required. :type name: str :param body: Required. @@ -7920,6 +7973,8 @@ async def update( ) -> _models.MemoryStoreDetails: """Update a memory store. + Updates the specified memory store with the supplied configuration changes. + :param name: The name of the memory store to update. Required. :type name: str :param body: Required. @@ -7944,6 +7999,8 @@ async def update( ) -> _models.MemoryStoreDetails: """Update a memory store. + Updates the specified memory store with the supplied configuration changes. + :param name: The name of the memory store to update. Required. :type name: str :param body: Is either a JSON type or a IO[bytes] type. Required. @@ -8027,7 +8084,9 @@ async def update( @distributed_trace_async async def get(self, name: str, **kwargs: Any) -> _models.MemoryStoreDetails: - """Retrieve a memory store. + """Get a memory store. + + Retrieves the specified memory store and its current configuration. :param name: The name of the memory store to retrieve. Required. :type name: str @@ -8099,7 +8158,9 @@ def list( before: Optional[str] = None, **kwargs: Any ) -> AsyncItemPaged["_models.MemoryStoreDetails"]: - """List all memory stores. + """List memory stores. + + Returns the memory stores available to the caller. :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the @@ -8184,6 +8245,8 @@ async def get_next(_continuation_token=None): async def delete(self, name: str, **kwargs: Any) -> _models.DeleteMemoryStoreResult: """Delete a memory store. + Deletes the specified memory store. + :param name: The name of the memory store to delete. Required. :type name: str :return: DeleteMemoryStoreResult. The DeleteMemoryStoreResult is compatible with MutableMapping @@ -8278,7 +8341,9 @@ async def _search_memories( options: Optional[_models.MemorySearchOptions] = None, **kwargs: Any ) -> _models.MemoryStoreSearchResult: - """Search for relevant memories from a memory store based on conversation context. + """Search memories. + + Searches the specified memory store for memories relevant to the provided conversation context. :param name: The name of the memory store to search. Required. :type name: str @@ -8486,7 +8551,10 @@ async def _begin_update_memories( update_delay: Optional[int] = None, **kwargs: Any ) -> AsyncLROPoller[_models.MemoryStoreUpdateCompletedResult]: - """Update memory store with conversation memories. + """Update memories. + + Starts an update that writes conversation memories into the specified memory store. The + operation returns a long-running status location for polling the update result. :param name: The name of the memory store to update. Required. :type name: str @@ -8577,7 +8645,9 @@ def get_long_running_output(pipeline_response): async def delete_scope( self, name: str, *, scope: str, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryStoreDeleteScopeResult: - """Delete all memories associated with a specific scope from a memory store. + """Delete memories by scope. + + Deletes all memories in the specified memory store that are associated with the provided scope. :param name: The name of the memory store. Required. :type name: str @@ -8597,7 +8667,9 @@ async def delete_scope( async def delete_scope( self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryStoreDeleteScopeResult: - """Delete all memories associated with a specific scope from a memory store. + """Delete memories by scope. + + Deletes all memories in the specified memory store that are associated with the provided scope. :param name: The name of the memory store. Required. :type name: str @@ -8616,7 +8688,9 @@ async def delete_scope( async def delete_scope( self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryStoreDeleteScopeResult: - """Delete all memories associated with a specific scope from a memory store. + """Delete memories by scope. + + Deletes all memories in the specified memory store that are associated with the provided scope. :param name: The name of the memory store. Required. :type name: str @@ -8635,7 +8709,9 @@ async def delete_scope( async def delete_scope( self, name: str, body: Union[JSON, IO[bytes]] = _Unset, *, scope: str = _Unset, **kwargs: Any ) -> _models.MemoryStoreDeleteScopeResult: - """Delete all memories associated with a specific scope from a memory store. + """Delete memories by scope. + + Deletes all memories in the specified memory store that are associated with the provided scope. :param name: The name of the memory store. Required. :type name: str @@ -8730,7 +8806,9 @@ async def create_memory( content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Create a memory item in a memory store. + """Create a memory item. + + Creates a memory item in the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -8754,7 +8832,9 @@ async def create_memory( async def create_memory( self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Create a memory item in a memory store. + """Create a memory item. + + Creates a memory item in the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -8772,7 +8852,9 @@ async def create_memory( async def create_memory( self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Create a memory item in a memory store. + """Create a memory item. + + Creates a memory item in the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -8797,7 +8879,9 @@ async def create_memory( kind: Union[str, _models.MemoryItemKind] = _Unset, **kwargs: Any ) -> _models.MemoryItem: - """Create a memory item in a memory store. + """Create a memory item. + + Creates a memory item in the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -8893,7 +8977,9 @@ async def create_memory( async def update_memory( self, name: str, memory_id: str, *, content: str, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Update a memory item in a memory store. + """Update a memory item. + + Updates the specified memory item in the memory store. :param name: The name of the memory store. Required. :type name: str @@ -8913,7 +8999,9 @@ async def update_memory( async def update_memory( self, name: str, memory_id: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Update a memory item in a memory store. + """Update a memory item. + + Updates the specified memory item in the memory store. :param name: The name of the memory store. Required. :type name: str @@ -8933,7 +9021,9 @@ async def update_memory( async def update_memory( self, name: str, memory_id: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Update a memory item in a memory store. + """Update a memory item. + + Updates the specified memory item in the memory store. :param name: The name of the memory store. Required. :type name: str @@ -8953,7 +9043,9 @@ async def update_memory( async def update_memory( self, name: str, memory_id: str, body: Union[JSON, IO[bytes]] = _Unset, *, content: str = _Unset, **kwargs: Any ) -> _models.MemoryItem: - """Update a memory item in a memory store. + """Update a memory item. + + Updates the specified memory item in the memory store. :param name: The name of the memory store. Required. :type name: str @@ -9040,7 +9132,9 @@ async def update_memory( @distributed_trace_async async def get_memory(self, name: str, memory_id: str, **kwargs: Any) -> _models.MemoryItem: - """Retrieve a memory item from a memory store. + """Get a memory item. + + Retrieves the specified memory item from the memory store. :param name: The name of the memory store. Required. :type name: str @@ -9119,7 +9213,9 @@ def list_memories( content_type: str = "application/json", **kwargs: Any ) -> AsyncItemPaged["_models.MemoryItem"]: - """List all memory items in a memory store. + """List memory items. + + Returns memory items from the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -9164,7 +9260,9 @@ def list_memories( content_type: str = "application/json", **kwargs: Any ) -> AsyncItemPaged["_models.MemoryItem"]: - """List all memory items in a memory store. + """List memory items. + + Returns memory items from the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -9208,7 +9306,9 @@ def list_memories( content_type: str = "application/json", **kwargs: Any ) -> AsyncItemPaged["_models.MemoryItem"]: - """List all memory items in a memory store. + """List memory items. + + Returns memory items from the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -9252,7 +9352,9 @@ def list_memories( before: Optional[str] = None, **kwargs: Any ) -> AsyncItemPaged["_models.MemoryItem"]: - """List all memory items in a memory store. + """List memory items. + + Returns memory items from the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -9295,14 +9397,11 @@ def list_memories( 304: ResourceNotModifiedError, } error_map.update(kwargs.pop("error_map", {}) or {}) - - # BUG? These lines were inside the prepare_request() method. Moved here instead. if body is _Unset: if scope is _Unset: raise TypeError("missing required argument: scope") body = {"scope": scope} body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/json" _content = None if isinstance(body, (IOBase, bytes)): @@ -9311,11 +9410,6 @@ def list_memories( _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore def prepare_request(_continuation_token=None): - # if body is _Unset: - # if scope is _Unset: - # raise TypeError("missing required argument: scope") - # body = {"scope": scope} - # body = {k: v for k, v in body.items() if v is not None} _request = build_beta_memory_stores_list_memories_request( name=name, @@ -9369,7 +9463,9 @@ async def get_next(_continuation_token=None): @distributed_trace_async async def delete_memory(self, name: str, memory_id: str, **kwargs: Any) -> _models.DeleteMemoryResult: - """Delete a memory item from a memory store. + """Delete a memory item. + + Deletes the specified memory item from the memory store. :param name: The name of the memory store. Required. :type name: str @@ -9455,7 +9551,9 @@ def __init__(self, *args, **kwargs) -> None: @distributed_trace def list_versions(self, name: str, **kwargs: Any) -> AsyncItemPaged["_models.ModelVersion"]: - """List all versions of the given ModelVersion. + """List versions. + + List all versions of the given ModelVersion. :param name: The name of the resource. Required. :type name: str @@ -9546,7 +9644,9 @@ async def get_next(next_link=None): @distributed_trace def list(self, **kwargs: Any) -> AsyncItemPaged["_models.ModelVersion"]: - """List the latest version of each ModelVersion. + """List latest versions. + + List the latest version of each ModelVersion. :return: An iterator like instance of ModelVersion :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.ModelVersion] @@ -9634,8 +9734,9 @@ async def get_next(next_link=None): @distributed_trace_async async def get(self, name: str, version: str, **kwargs: Any) -> _models.ModelVersion: - """Get the specific version of the ModelVersion. The service returns 404 Not Found error if the - ModelVersion does not exist. + """Get a model version. + + Retrieves the specified model version, returning 404 if it does not exist. :param name: The name of the resource. Required. :type name: str @@ -9699,7 +9800,9 @@ async def get(self, name: str, version: str, **kwargs: Any) -> _models.ModelVers @distributed_trace_async async def delete(self, name: str, version: str, **kwargs: Any) -> None: - """Delete the specific version of the ModelVersion. The service returns 200 OK if the ModelVersion + """Delete a model version. + + Delete the specific version of the ModelVersion. The service returns 200 OK if the ModelVersion was deleted successfully or if the ModelVersion does not exist. :param name: The name of the resource. Required. @@ -9759,7 +9862,9 @@ async def update( content_type: str = "application/merge-patch+json", **kwargs: Any ) -> _models.ModelVersion: - """Update an existing ModelVersion with the given version id. + """Update a model version. + + Update an existing ModelVersion with the given version id. :param name: The name of the resource. Required. :type name: str @@ -9786,7 +9891,9 @@ async def update( content_type: str = "application/merge-patch+json", **kwargs: Any ) -> _models.ModelVersion: - """Update an existing ModelVersion with the given version id. + """Update a model version. + + Update an existing ModelVersion with the given version id. :param name: The name of the resource. Required. :type name: str @@ -9813,7 +9920,9 @@ async def update( content_type: str = "application/merge-patch+json", **kwargs: Any ) -> _models.ModelVersion: - """Update an existing ModelVersion with the given version id. + """Update a model version. + + Update an existing ModelVersion with the given version id. :param name: The name of the resource. Required. :type name: str @@ -9838,7 +9947,9 @@ async def update( model_version_update: Union[_models.UpdateModelVersionRequest, JSON, IO[bytes]], **kwargs: Any ) -> _models.ModelVersion: - """Update an existing ModelVersion with the given version id. + """Update a model version. + + Update an existing ModelVersion with the given version id. :param name: The name of the resource. Required. :type name: str @@ -9925,8 +10036,10 @@ async def pending_create_version( content_type: str = "application/json", **kwargs: Any ) -> _models.CreateAsyncResponse: - """Creates a model version asynchronously with blob content validation. Returns 202 Accepted with - a Location header for polling. + """Create a model version async. + + Creates a model version asynchronously with blob content validation. Returns 202 Accepted with + a location header for polling the operation status. :param name: Name of the model. Required. :type name: str @@ -9946,8 +10059,10 @@ async def pending_create_version( async def pending_create_version( self, name: str, version: str, model_version: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.CreateAsyncResponse: - """Creates a model version asynchronously with blob content validation. Returns 202 Accepted with - a Location header for polling. + """Create a model version async. + + Creates a model version asynchronously with blob content validation. Returns 202 Accepted with + a location header for polling the operation status. :param name: Name of the model. Required. :type name: str @@ -9973,8 +10088,10 @@ async def pending_create_version( content_type: str = "application/json", **kwargs: Any ) -> _models.CreateAsyncResponse: - """Creates a model version asynchronously with blob content validation. Returns 202 Accepted with - a Location header for polling. + """Create a model version async. + + Creates a model version asynchronously with blob content validation. Returns 202 Accepted with + a location header for polling the operation status. :param name: Name of the model. Required. :type name: str @@ -9994,8 +10111,10 @@ async def pending_create_version( async def pending_create_version( self, name: str, version: str, model_version: Union[_models.ModelVersion, JSON, IO[bytes]], **kwargs: Any ) -> _models.CreateAsyncResponse: - """Creates a model version asynchronously with blob content validation. Returns 202 Accepted with - a Location header for polling. + """Create a model version async. + + Creates a model version asynchronously with blob content validation. Returns 202 Accepted with + a location header for polling the operation status. :param name: Name of the model. Required. :type name: str @@ -10083,7 +10202,9 @@ async def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.ModelPendingUploadResponse: - """Start or retrieve a pending upload for a model version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified model version. :param name: Name of the model. Required. :type name: str @@ -10110,7 +10231,9 @@ async def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.ModelPendingUploadResponse: - """Start or retrieve a pending upload for a model version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified model version. :param name: Name of the model. Required. :type name: str @@ -10137,7 +10260,9 @@ async def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.ModelPendingUploadResponse: - """Start or retrieve a pending upload for a model version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified model version. :param name: Name of the model. Required. :type name: str @@ -10162,7 +10287,9 @@ async def pending_upload( pending_upload_request: Union[_models.ModelPendingUploadRequest, JSON, IO[bytes]], **kwargs: Any ) -> _models.ModelPendingUploadResponse: - """Start or retrieve a pending upload for a model version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified model version. :param name: Name of the model. Required. :type name: str @@ -10249,7 +10376,9 @@ async def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get credentials for a model version asset. + """Get model asset credentials. + + Retrieves temporary credentials for accessing the storage backing the specified model version. :param name: Name of the model. Required. :type name: str @@ -10275,7 +10404,9 @@ async def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get credentials for a model version asset. + """Get model asset credentials. + + Retrieves temporary credentials for accessing the storage backing the specified model version. :param name: Name of the model. Required. :type name: str @@ -10301,7 +10432,9 @@ async def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get credentials for a model version asset. + """Get model asset credentials. + + Retrieves temporary credentials for accessing the storage backing the specified model version. :param name: Name of the model. Required. :type name: str @@ -10325,7 +10458,9 @@ async def get_credentials( credential_request: Union[_models.ModelCredentialRequest, JSON, IO[bytes]], **kwargs: Any ) -> _models.DatasetCredential: - """Get credentials for a model version asset. + """Get model asset credentials. + + Retrieves temporary credentials for accessing the storage backing the specified model version. :param name: Name of the model. Required. :type name: str @@ -10420,7 +10555,9 @@ def __init__(self, *args, **kwargs) -> None: @distributed_trace_async async def get(self, name: str, **kwargs: Any) -> _models.RedTeam: - """Get a redteam by name. + """Get a redteam. + + Retrieves the specified redteam and its configuration. :param name: Identifier of the red team run. Required. :type name: str @@ -10481,7 +10618,9 @@ async def get(self, name: str, **kwargs: Any) -> _models.RedTeam: @distributed_trace def list(self, **kwargs: Any) -> AsyncItemPaged["_models.RedTeam"]: - """List a redteam by name. + """List redteams. + + Returns the redteams available in the current project. :return: An iterator like instance of RedTeam :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.RedTeam] @@ -10571,7 +10710,9 @@ async def get_next(next_link=None): async def create( self, red_team: _models.RedTeam, *, content_type: str = "application/json", **kwargs: Any ) -> _models.RedTeam: - """Creates a redteam run. + """Create a redteam run. + + Submits a new redteam run for execution with the provided configuration. :param red_team: Redteam to be run. Required. :type red_team: ~azure.ai.projects.models.RedTeam @@ -10585,7 +10726,9 @@ async def create( @overload async def create(self, red_team: JSON, *, content_type: str = "application/json", **kwargs: Any) -> _models.RedTeam: - """Creates a redteam run. + """Create a redteam run. + + Submits a new redteam run for execution with the provided configuration. :param red_team: Redteam to be run. Required. :type red_team: JSON @@ -10601,7 +10744,9 @@ async def create(self, red_team: JSON, *, content_type: str = "application/json" async def create( self, red_team: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.RedTeam: - """Creates a redteam run. + """Create a redteam run. + + Submits a new redteam run for execution with the provided configuration. :param red_team: Redteam to be run. Required. :type red_team: IO[bytes] @@ -10615,7 +10760,9 @@ async def create( @distributed_trace_async async def create(self, red_team: Union[_models.RedTeam, JSON, IO[bytes]], **kwargs: Any) -> _models.RedTeam: - """Creates a redteam run. + """Create a redteam run. + + Submits a new redteam run for execution with the provided configuration. :param red_team: Redteam to be run. Is one of the following types: RedTeam, JSON, IO[bytes] Required. @@ -10720,6 +10867,8 @@ async def create_or_update( ) -> _models.Routine: """Create or update a routine. + Creates a new routine or replaces an existing routine with the supplied definition. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. @@ -10745,6 +10894,8 @@ async def create_or_update( ) -> _models.Routine: """Create or update a routine. + Creates a new routine or replaces an existing routine with the supplied definition. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Required. @@ -10763,6 +10914,8 @@ async def create_or_update( ) -> _models.Routine: """Create or update a routine. + Creates a new routine or replaces an existing routine with the supplied definition. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Required. @@ -10789,6 +10942,8 @@ async def create_or_update( ) -> _models.Routine: """Create or update a routine. + Creates a new routine or replaces an existing routine with the supplied definition. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Is either a JSON type or a IO[bytes] type. Required. @@ -10876,7 +11031,9 @@ async def create_or_update( @distributed_trace_async async def get(self, routine_name: str, **kwargs: Any) -> _models.Routine: - """Retrieve a routine. + """Get a routine. + + Retrieves the specified routine and its current configuration. :param routine_name: The unique name of the routine. Required. :type routine_name: str @@ -10943,6 +11100,8 @@ async def get(self, routine_name: str, **kwargs: Any) -> _models.Routine: async def enable(self, routine_name: str, **kwargs: Any) -> _models.Routine: """Enable a routine. + Enables the specified routine so it can be dispatched. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :return: Routine. The Routine is compatible with MutableMapping @@ -11008,6 +11167,8 @@ async def enable(self, routine_name: str, **kwargs: Any) -> _models.Routine: async def disable(self, routine_name: str, **kwargs: Any) -> _models.Routine: """Disable a routine. + Disables the specified routine so it no longer runs. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :return: Routine. The Routine is compatible with MutableMapping @@ -11075,6 +11236,8 @@ def list( ) -> AsyncItemPaged["_models.Routine"]: """List routines. + Returns the routines available in the current project. + :keyword limit: The maximum number of routines to return. Default value is None. :paramtype limit: int :keyword before: Unsupported. Reserved for future backward pagination support. Default value is @@ -11152,6 +11315,8 @@ async def get_next(_continuation_token=None): async def delete(self, routine_name: str, **kwargs: Any) -> None: """Delete a routine. + Deletes the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :return: None @@ -11213,6 +11378,8 @@ def list_runs( ) -> AsyncItemPaged["_models.RoutineRun"]: """List prior runs for a routine. + Returns prior runs recorded for the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :keyword filter: An optional MLflow search-runs filter expression applied within the routine's @@ -11304,6 +11471,8 @@ async def dispatch( ) -> _models.DispatchRoutineResult: """Queue an asynchronous routine dispatch. + Queues an asynchronous dispatch for the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. @@ -11323,6 +11492,8 @@ async def dispatch( ) -> _models.DispatchRoutineResult: """Queue an asynchronous routine dispatch. + Queues an asynchronous dispatch for the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Required. @@ -11341,6 +11512,8 @@ async def dispatch( ) -> _models.DispatchRoutineResult: """Queue an asynchronous routine dispatch. + Queues an asynchronous dispatch for the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Required. @@ -11364,6 +11537,8 @@ async def dispatch( ) -> _models.DispatchRoutineResult: """Queue an asynchronous routine dispatch. + Queues an asynchronous dispatch for the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Is either a JSON type or a IO[bytes] type. Required. @@ -11465,6 +11640,8 @@ def __init__(self, *args, **kwargs) -> None: async def delete(self, schedule_id: str, **kwargs: Any) -> None: """Delete a schedule. + Deletes the specified schedule resource. + :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str :return: None @@ -11511,7 +11688,9 @@ async def delete(self, schedule_id: str, **kwargs: Any) -> None: @distributed_trace_async async def get(self, schedule_id: str, **kwargs: Any) -> _models.Schedule: - """Get a schedule by id. + """Get a schedule. + + Retrieves the specified schedule resource. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -11578,7 +11757,9 @@ def list( enabled: Optional[bool] = None, **kwargs: Any ) -> AsyncItemPaged["_models.Schedule"]: - """List all schedules. + """List schedules. + + Returns schedules that match the supplied type and enabled filters. :keyword type: Filter by the type of schedule. Known values are: "Evaluation" and "Insight". Default value is None. @@ -11675,7 +11856,9 @@ async def get_next(next_link=None): async def create_or_update( self, schedule_id: str, schedule: _models.Schedule, *, content_type: str = "application/json", **kwargs: Any ) -> _models.Schedule: - """Create or update operation template. + """Create or update a schedule. + + Creates a new schedule or updates an existing schedule with the supplied definition. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -11693,7 +11876,9 @@ async def create_or_update( async def create_or_update( self, schedule_id: str, schedule: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.Schedule: - """Create or update operation template. + """Create or update a schedule. + + Creates a new schedule or updates an existing schedule with the supplied definition. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -11711,7 +11896,9 @@ async def create_or_update( async def create_or_update( self, schedule_id: str, schedule: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.Schedule: - """Create or update operation template. + """Create or update a schedule. + + Creates a new schedule or updates an existing schedule with the supplied definition. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -11729,7 +11916,9 @@ async def create_or_update( async def create_or_update( self, schedule_id: str, schedule: Union[_models.Schedule, JSON, IO[bytes]], **kwargs: Any ) -> _models.Schedule: - """Create or update operation template. + """Create or update a schedule. + + Creates a new schedule or updates an existing schedule with the supplied definition. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -11803,7 +11992,9 @@ async def create_or_update( @distributed_trace_async async def get_run(self, schedule_id: str, run_id: str, **kwargs: Any) -> _models.ScheduleRun: - """Get a schedule run by id. + """Get a schedule run. + + Retrieves the specified run for a schedule. :param schedule_id: The unique identifier of the schedule. Required. :type schedule_id: str @@ -11878,7 +12069,9 @@ def list_runs( enabled: Optional[bool] = None, **kwargs: Any ) -> AsyncItemPaged["_models.ScheduleRun"]: - """List all schedule runs. + """List schedule runs. + + Returns schedule runs that match the supplied filters. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -11945,251 +12138,63 @@ def prepare_request(next_link=None): } _request.url = self._client.format_url(_request.url, **path_format_arguments) - return _request - - async def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.ScheduleRun], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, AsyncList(list_of_elem) - - async def get_next(next_link=None): - _request = prepare_request(next_link) - - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - return pipeline_response - - return AsyncItemPaged(get_next, extract_data) - - -class BetaToolboxesOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. - - Instead, you should access the following operations through - :class:`~azure.ai.projects.aio.AIProjectClient`'s - :attr:`toolboxes` attribute. - """ - - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") - - @overload - async def create_version( - self, - name: str, - *, - tools: List[_models.Tool], - content_type: str = "application/json", - description: Optional[str] = None, - metadata: Optional[dict[str, str]] = None, - skills: Optional[List[_models.ToolboxSkill]] = None, - policies: Optional[_models.ToolboxPolicies] = None, - **kwargs: Any - ) -> _models.ToolboxVersionObject: - """Create a new version of a toolbox. If the toolbox does not exist, it will be created. - - :param name: The name of the toolbox. If the toolbox does not exist, it will be created. - Required. - :type name: str - :keyword tools: The list of tools to include in this version. Required. - :paramtype tools: list[~azure.ai.projects.models.Tool] - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :keyword description: A human-readable description of the toolbox. Default value is None. - :paramtype description: str - :keyword metadata: Arbitrary key-value metadata to associate with the toolbox. Default value is - None. - :paramtype metadata: dict[str, str] - :keyword skills: The list of skill sources to include in this version. A skill reference - specifies a skill name and optionally a version. If version is omitted, the skill's default - version is used. Default value is None. - :paramtype skills: list[~azure.ai.projects.models.ToolboxSkill] - :keyword policies: Policy configuration for this toolbox version. Default value is None. - :paramtype policies: ~azure.ai.projects.models.ToolboxPolicies - :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxVersionObject - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def create_version( - self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.ToolboxVersionObject: - """Create a new version of a toolbox. If the toolbox does not exist, it will be created. - - :param name: The name of the toolbox. If the toolbox does not exist, it will be created. - Required. - :type name: str - :param body: Required. - :type body: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxVersionObject - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def create_version( - self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.ToolboxVersionObject: - """Create a new version of a toolbox. If the toolbox does not exist, it will be created. - - :param name: The name of the toolbox. If the toolbox does not exist, it will be created. - Required. - :type name: str - :param body: Required. - :type body: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxVersionObject - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @distributed_trace_async - async def create_version( - self, - name: str, - body: Union[JSON, IO[bytes]] = _Unset, - *, - tools: List[_models.Tool] = _Unset, - description: Optional[str] = None, - metadata: Optional[dict[str, str]] = None, - skills: Optional[List[_models.ToolboxSkill]] = None, - policies: Optional[_models.ToolboxPolicies] = None, - **kwargs: Any - ) -> _models.ToolboxVersionObject: - """Create a new version of a toolbox. If the toolbox does not exist, it will be created. - - :param name: The name of the toolbox. If the toolbox does not exist, it will be created. - Required. - :type name: str - :param body: Is either a JSON type or a IO[bytes] type. Required. - :type body: JSON or IO[bytes] - :keyword tools: The list of tools to include in this version. Required. - :paramtype tools: list[~azure.ai.projects.models.Tool] - :keyword description: A human-readable description of the toolbox. Default value is None. - :paramtype description: str - :keyword metadata: Arbitrary key-value metadata to associate with the toolbox. Default value is - None. - :paramtype metadata: dict[str, str] - :keyword skills: The list of skill sources to include in this version. A skill reference - specifies a skill name and optionally a version. If version is omitted, the skill's default - version is used. Default value is None. - :paramtype skills: list[~azure.ai.projects.models.ToolboxSkill] - :keyword policies: Policy configuration for this toolbox version. Default value is None. - :paramtype policies: ~azure.ai.projects.models.ToolboxPolicies - :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxVersionObject - :raises ~azure.core.exceptions.HttpResponseError: - """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = kwargs.pop("params", {}) or {} - - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.ToolboxVersionObject] = kwargs.pop("cls", None) - - if body is _Unset: - if tools is _Unset: - raise TypeError("missing required argument: tools") - body = { - "description": description, - "metadata": metadata, - "policies": policies, - "skills": skills, - "tools": tools, - } - body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/json" - _content = None - if isinstance(body, (IOBase, bytes)): - _content = body - else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - - _request = build_beta_toolboxes_create_version_request( - name=name, - content_type=content_type, - api_version=self._config.api_version, - content=_content, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.ScheduleRun], + deserialized.get("value", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) - response = pipeline_response.http_response + async def get_next(next_link=None): + _request = prepare_request(next_link) - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs ) - raise HttpResponseError(response=response, model=error) + response = pipeline_response.http_response - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.ToolboxVersionObject, response.json()) + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return pipeline_response - return deserialized # type: ignore + return AsyncItemPaged(get_next, extract_data) + + +class BetaSkillsOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. + + Instead, you should access the following operations through + :class:`~azure.ai.projects.aio.AIProjectClient`'s + :attr:`skills` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") @distributed_trace_async - async def get(self, name: str, **kwargs: Any) -> _models.ToolboxObject: - """Retrieve a toolbox. + async def get(self, name: str, **kwargs: Any) -> _models.SkillDetails: + """Retrieve a skill. - :param name: The name of the toolbox to retrieve. Required. + Retrieves the specified skill and its current configuration. + + :param name: The unique name of the skill. Required. :type name: str - :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxObject + :return: SkillDetails. The SkillDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillDetails :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -12203,9 +12208,9 @@ async def get(self, name: str, **kwargs: Any) -> _models.ToolboxObject: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.ToolboxObject] = kwargs.pop("cls", None) + cls: ClsType[_models.SkillDetails] = kwargs.pop("cls", None) - _request = build_beta_toolboxes_get_request( + _request = build_beta_skills_get_request( name=name, api_version=self._config.api_version, headers=_headers, @@ -12240,7 +12245,7 @@ async def get(self, name: str, **kwargs: Any) -> _models.ToolboxObject: if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.ToolboxObject, response.json()) + deserialized = _deserialize(_models.SkillDetails, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -12255,102 +12260,11 @@ def list( order: Optional[Union[str, _models.PageOrder]] = None, before: Optional[str] = None, **kwargs: Any - ) -> AsyncItemPaged["_models.ToolboxObject"]: - """List all toolboxes. - - :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and - 100, and the - default is 20. Default value is None. - :paramtype limit: int - :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for - ascending order and``desc`` - for descending order. Known values are: "asc" and "desc". Default value is None. - :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - Default value is None. - :paramtype before: str - :return: An iterator like instance of ToolboxObject - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.ToolboxObject] - :raises ~azure.core.exceptions.HttpResponseError: - """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.ToolboxObject]] = kwargs.pop("cls", None) - - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(_continuation_token=None): - - _request = build_beta_toolboxes_list_request( - limit=limit, - order=order, - after=_continuation_token, - before=before, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - return _request - - async def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.ToolboxObject], - deserialized.get("data", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("last_id") or None, AsyncList(list_of_elem) - - async def get_next(_continuation_token=None): - _request = prepare_request(_continuation_token) - - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - return pipeline_response - - return AsyncItemPaged(get_next, extract_data) + ) -> AsyncItemPaged["_models.SkillDetails"]: + """List skills. - @distributed_trace - def list_versions( - self, - name: str, - *, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - before: Optional[str] = None, - **kwargs: Any - ) -> AsyncItemPaged["_models.ToolboxVersionObject"]: - """List all versions of a toolbox. + Returns the skills available in the current project. - :param name: The name of the toolbox to list versions for. Required. - :type name: str :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. Default value is None. @@ -12365,14 +12279,14 @@ def list_versions( subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str - :return: An iterator like instance of ToolboxVersionObject - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.ToolboxVersionObject] + :return: An iterator like instance of SkillDetails + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.SkillDetails] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.ToolboxVersionObject]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.SkillDetails]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -12384,8 +12298,7 @@ def list_versions( def prepare_request(_continuation_token=None): - _request = build_beta_toolboxes_list_versions_request( - name=name, + _request = build_beta_skills_list_request( limit=limit, order=order, after=_continuation_token, @@ -12403,172 +12316,112 @@ def prepare_request(_continuation_token=None): async def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.ToolboxVersionObject], + List[_models.SkillDetails], deserialized.get("data", []), ) if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("last_id") or None, AsyncList(list_of_elem) - - async def get_next(_continuation_token=None): - _request = prepare_request(_continuation_token) - - _stream = False - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - return pipeline_response - - return AsyncItemPaged(get_next, extract_data) - - @distributed_trace_async - async def get_version(self, name: str, version: str, **kwargs: Any) -> _models.ToolboxVersionObject: - """Retrieve a specific version of a toolbox. - - :param name: The name of the toolbox. Required. - :type name: str - :param version: The version identifier to retrieve. Required. - :type version: str - :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxVersionObject - :raises ~azure.core.exceptions.HttpResponseError: - """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[_models.ToolboxVersionObject] = kwargs.pop("cls", None) - - _request = build_beta_toolboxes_get_version_request( - name=name, - version=version, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("last_id") or None, AsyncList(list_of_elem) - response = pipeline_response.http_response + async def get_next(_continuation_token=None): + _request = prepare_request(_continuation_token) - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs ) - raise HttpResponseError(response=response, model=error) + response = pipeline_response.http_response - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.ToolboxVersionObject, response.json()) + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return pipeline_response - return deserialized # type: ignore + return AsyncItemPaged(get_next, extract_data) @overload async def update( self, name: str, *, default_version: str, content_type: str = "application/json", **kwargs: Any - ) -> _models.ToolboxObject: - """Update a toolbox to point to a specific version. + ) -> _models.SkillDetails: + """Update a skill. - :param name: The name of the toolbox to update. Required. + Modifies the specified skill's configuration. + + :param name: The name of the skill to update. Required. :type name: str - :keyword default_version: The version identifier that the toolbox should point to. When set, - the toolbox's default version will resolve to this version instead of the latest. Required. + :keyword default_version: The version identifier that the skill should point to. When set, the + skill's default version will resolve to this version instead of the latest. Required. :paramtype default_version: str :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str - :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxObject + :return: SkillDetails. The SkillDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillDetails :raises ~azure.core.exceptions.HttpResponseError: """ @overload async def update( self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.ToolboxObject: - """Update a toolbox to point to a specific version. + ) -> _models.SkillDetails: + """Update a skill. - :param name: The name of the toolbox to update. Required. + Modifies the specified skill's configuration. + + :param name: The name of the skill to update. Required. :type name: str :param body: Required. :type body: JSON :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str - :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxObject + :return: SkillDetails. The SkillDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillDetails :raises ~azure.core.exceptions.HttpResponseError: """ @overload async def update( self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.ToolboxObject: - """Update a toolbox to point to a specific version. + ) -> _models.SkillDetails: + """Update a skill. - :param name: The name of the toolbox to update. Required. + Modifies the specified skill's configuration. + + :param name: The name of the skill to update. Required. :type name: str :param body: Required. :type body: IO[bytes] :keyword content_type: Body Parameter content-type. Content type parameter for binary body. Default value is "application/json". :paramtype content_type: str - :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxObject + :return: SkillDetails. The SkillDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillDetails :raises ~azure.core.exceptions.HttpResponseError: """ @distributed_trace_async async def update( self, name: str, body: Union[JSON, IO[bytes]] = _Unset, *, default_version: str = _Unset, **kwargs: Any - ) -> _models.ToolboxObject: - """Update a toolbox to point to a specific version. + ) -> _models.SkillDetails: + """Update a skill. - :param name: The name of the toolbox to update. Required. + Modifies the specified skill's configuration. + + :param name: The name of the skill to update. Required. :type name: str :param body: Is either a JSON type or a IO[bytes] type. Required. :type body: JSON or IO[bytes] - :keyword default_version: The version identifier that the toolbox should point to. When set, - the toolbox's default version will resolve to this version instead of the latest. Required. + :keyword default_version: The version identifier that the skill should point to. When set, the + skill's default version will resolve to this version instead of the latest. Required. :paramtype default_version: str - :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxObject + :return: SkillDetails. The SkillDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillDetails :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -12583,7 +12436,7 @@ async def update( _params = kwargs.pop("params", {}) or {} content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.ToolboxObject] = kwargs.pop("cls", None) + cls: ClsType[_models.SkillDetails] = kwargs.pop("cls", None) if body is _Unset: if default_version is _Unset: @@ -12597,7 +12450,7 @@ async def update( else: _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - _request = build_beta_toolboxes_update_request( + _request = build_beta_skills_update_request( name=name, content_type=content_type, api_version=self._config.api_version, @@ -12634,7 +12487,7 @@ async def update( if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.ToolboxObject, response.json()) + deserialized = _deserialize(_models.SkillDetails, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -12642,13 +12495,15 @@ async def update( return deserialized # type: ignore @distributed_trace_async - async def delete(self, name: str, **kwargs: Any) -> None: - """Delete a toolbox and all its versions. + async def delete(self, name: str, **kwargs: Any) -> _models.DeleteSkillResult: + """Delete a skill. - :param name: The name of the toolbox to delete. Required. + Removes the specified skill and its associated versions. + + :param name: The unique name of the skill. Required. :type name: str - :return: None - :rtype: None + :return: DeleteSkillResult. The DeleteSkillResult is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DeleteSkillResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -12662,9 +12517,9 @@ async def delete(self, name: str, **kwargs: Any) -> None: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + cls: ClsType[_models.DeleteSkillResult] = kwargs.pop("cls", None) - _request = build_beta_toolboxes_delete_request( + _request = build_beta_skills_delete_request( name=name, api_version=self._config.api_version, headers=_headers, @@ -12675,14 +12530,20 @@ async def delete(self, name: str, **kwargs: Any) -> None: } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) error = _failsafe_deserialize( _models.ApiErrorResponse, @@ -12690,19 +12551,110 @@ async def delete(self, name: str, **kwargs: Any) -> None: ) raise HttpResponseError(response=response, model=error) + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.DeleteSkillResult, response.json()) + if cls: - return cls(pipeline_response, None, {}) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @overload + async def create( + self, + name: str, + *, + content_type: str = "application/json", + inline_content: Optional[_models.SkillInlineContent] = None, + default: Optional[bool] = None, + **kwargs: Any + ) -> _models.SkillVersion: + """Create a new version of a skill. + + Creates a new version of a skill. If the skill does not exist, it will be created. + + :param name: The name of the skill. If the skill does not exist, it will be created. Required. + :type name: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword inline_content: Inline skill content for simple skills without file uploads. + Foundry-specific extension. Default value is None. + :paramtype inline_content: ~azure.ai.projects.models.SkillInlineContent + :keyword default: Whether to set this version as the default. Default value is None. + :paramtype default: bool + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create( + self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.SkillVersion: + """Create a new version of a skill. + + Creates a new version of a skill. If the skill does not exist, it will be created. + + :param name: The name of the skill. If the skill does not exist, it will be created. Required. + :type name: str + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create( + self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.SkillVersion: + """Create a new version of a skill. + + Creates a new version of a skill. If the skill does not exist, it will be created. + + :param name: The name of the skill. If the skill does not exist, it will be created. Required. + :type name: str + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace_async - async def delete_version(self, name: str, version: str, **kwargs: Any) -> None: - """Delete a specific version of a toolbox. + async def create( + self, + name: str, + body: Union[JSON, IO[bytes]] = _Unset, + *, + inline_content: Optional[_models.SkillInlineContent] = None, + default: Optional[bool] = None, + **kwargs: Any + ) -> _models.SkillVersion: + """Create a new version of a skill. - :param name: The name of the toolbox. Required. + Creates a new version of a skill. If the skill does not exist, it will be created. + + :param name: The name of the skill. If the skill does not exist, it will be created. Required. :type name: str - :param version: The version identifier to delete. Required. - :type version: str - :return: None - :rtype: None + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword inline_content: Inline skill content for simple skills without file uploads. + Foundry-specific extension. Default value is None. + :paramtype inline_content: ~azure.ai.projects.models.SkillInlineContent + :keyword default: Whether to set this version as the default. Default value is None. + :paramtype default: bool + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -12713,15 +12665,27 @@ async def delete_version(self, name: str, version: str, **kwargs: Any) -> None: } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) + + if body is _Unset: + body = {"default": default, "inline_content": inline_content} + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - _request = build_beta_toolboxes_delete_version_request( + _request = build_beta_skills_create_request( name=name, - version=version, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -12730,14 +12694,20 @@ async def delete_version(self, name: str, version: str, **kwargs: Any) -> None: } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) error = _failsafe_deserialize( _models.ApiErrorResponse, @@ -12745,35 +12715,62 @@ async def delete_version(self, name: str, version: str, **kwargs: Any) -> None: ) raise HttpResponseError(response=response, model=error) - if cls: - return cls(pipeline_response, None, {}) # type: ignore + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.SkillVersion, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @overload + async def create_from_files( + self, name: str, content: _models.CreateSkillVersionFromFilesBody, **kwargs: Any + ) -> _models.SkillVersion: + """Create a skill version from uploaded files. + + Creates a new version of a skill from uploaded files via multipart form data. + :param name: The name of the skill. Required. + :type name: str + :param content: Required. + :type content: ~azure.ai.projects.models.CreateSkillVersionFromFilesBody + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ -class BetaSkillsOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. + @overload + async def create_from_files(self, name: str, content: JSON, **kwargs: Any) -> _models.SkillVersion: + """Create a skill version from uploaded files. - Instead, you should access the following operations through - :class:`~azure.ai.projects.aio.AIProjectClient`'s - :attr:`skills` attribute. - """ + Creates a new version of a skill from uploaded files via multipart form data. - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + :param name: The name of the skill. Required. + :type name: str + :param content: Required. + :type content: JSON + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace_async - async def get(self, name: str, **kwargs: Any) -> _models.SkillDetails: - """Retrieves a skill. + async def create_from_files( + self, name: str, content: Union[_models.CreateSkillVersionFromFilesBody, JSON], **kwargs: Any + ) -> _models.SkillVersion: + """Create a skill version from uploaded files. - :param name: The unique name of the skill. Required. + Creates a new version of a skill from uploaded files via multipart form data. + + :param name: The name of the skill. Required. :type name: str - :return: SkillDetails. The SkillDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillDetails + :param content: Is either a CreateSkillVersionFromFilesBody type or a JSON type. Required. + :type content: ~azure.ai.projects.models.CreateSkillVersionFromFilesBody or JSON + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -12787,11 +12784,17 @@ async def get(self, name: str, **kwargs: Any) -> _models.SkillDetails: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.SkillDetails] = kwargs.pop("cls", None) + cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) - _request = build_beta_skills_get_request( + _body = content.as_dict() if isinstance(content, _Model) else content + _file_fields: list[str] = ["files"] + _data_fields: list[str] = ["default"] + _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + + _request = build_beta_skills_create_from_files_request( name=name, api_version=self._config.api_version, + files=_files, headers=_headers, params=_params, ) @@ -12824,7 +12827,7 @@ async def get(self, name: str, **kwargs: Any) -> _models.SkillDetails: if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SkillDetails, response.json()) + deserialized = _deserialize(_models.SkillVersion, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -12832,16 +12835,21 @@ async def get(self, name: str, **kwargs: Any) -> _models.SkillDetails: return deserialized # type: ignore @distributed_trace - def list( + def list_versions( self, + name: str, *, limit: Optional[int] = None, order: Optional[Union[str, _models.PageOrder]] = None, before: Optional[str] = None, **kwargs: Any - ) -> AsyncItemPaged["_models.SkillDetails"]: - """Returns the list of all skills. + ) -> AsyncItemPaged["_models.SkillVersion"]: + """List skill versions. + Returns the available versions for the specified skill. + + :param name: The name of the skill to list versions for. Required. + :type name: str :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. Default value is None. @@ -12856,14 +12864,14 @@ def list( subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str - :return: An iterator like instance of SkillDetails - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.SkillDetails] + :return: An iterator like instance of SkillVersion + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.SkillVersion] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.SkillDetails]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.SkillVersion]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -12875,7 +12883,8 @@ def list( def prepare_request(_continuation_token=None): - _request = build_beta_skills_list_request( + _request = build_beta_skills_list_versions_request( + name=name, limit=limit, order=order, after=_continuation_token, @@ -12893,7 +12902,7 @@ def prepare_request(_continuation_token=None): async def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.SkillDetails], + List[_models.SkillVersion], deserialized.get("data", []), ) if cls: @@ -12921,76 +12930,86 @@ async def get_next(_continuation_token=None): return AsyncItemPaged(get_next, extract_data) - @overload - async def update( - self, name: str, *, default_version: str, content_type: str = "application/json", **kwargs: Any - ) -> _models.SkillDetails: - """Update a skill. + @distributed_trace_async + async def get_version(self, name: str, version: str, **kwargs: Any) -> _models.SkillVersion: + """Retrieve a specific version of a skill. - :param name: The name of the skill to update. Required. + Retrieves the specified version of a skill by name and version identifier. + + :param name: The name of the skill. Required. :type name: str - :keyword default_version: The version identifier that the skill should point to. When set, the - skill's default version will resolve to this version instead of the latest. Required. - :paramtype default_version: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: SkillDetails. The SkillDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillDetails + :param version: The version identifier to retrieve. Required. + :type version: str + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion :raises ~azure.core.exceptions.HttpResponseError: """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) - @overload - async def update( - self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.SkillDetails: - """Update a skill. + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - :param name: The name of the skill to update. Required. - :type name: str - :param body: Required. - :type body: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: SkillDetails. The SkillDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ + cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) - @overload - async def update( - self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.SkillDetails: - """Update a skill. + _request = build_beta_skills_get_version_request( + name=name, + version=version, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - :param name: The name of the skill to update. Required. - :type name: str - :param body: Required. - :type body: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: SkillDetails. The SkillDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.SkillVersion, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore @distributed_trace_async - async def update( - self, name: str, body: Union[JSON, IO[bytes]] = _Unset, *, default_version: str = _Unset, **kwargs: Any - ) -> _models.SkillDetails: - """Update a skill. + async def download(self, name: str, **kwargs: Any) -> AsyncIterator[bytes]: + """Download the zip content for the default version of a skill. - :param name: The name of the skill to update. Required. + Downloads the zip content for the default version of a skill. + + :param name: The name of the skill. Required. :type name: str - :param body: Is either a JSON type or a IO[bytes] type. Required. - :type body: JSON or IO[bytes] - :keyword default_version: The version identifier that the skill should point to. When set, the - skill's default version will resolve to this version instead of the latest. Required. - :paramtype default_version: str - :return: SkillDetails. The SkillDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillDetails + :return: AsyncIterator[bytes] + :rtype: AsyncIterator[bytes] :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -13001,29 +13020,14 @@ async def update( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.SkillDetails] = kwargs.pop("cls", None) - - if body is _Unset: - if default_version is _Unset: - raise TypeError("missing required argument: default_version") - body = {"default_version": default_version} - body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/json" - _content = None - if isinstance(body, (IOBase, bytes)): - _content = body - else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) - _request = build_beta_skills_update_request( + _request = build_beta_skills_download_request( name=name, - content_type=content_type, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -13033,7 +13037,7 @@ async def update( _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = kwargs.pop("stream", True) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -13053,24 +13057,28 @@ async def update( ) raise HttpResponseError(response=response, model=error) - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.SkillDetails, response.json()) + response_headers = {} + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore @distributed_trace_async - async def delete(self, name: str, **kwargs: Any) -> _models.DeleteSkillResult: - """Deletes a skill. + async def download_version(self, name: str, version: str, **kwargs: Any) -> AsyncIterator[bytes]: + """Download the zip content for a specific version of a skill. - :param name: The unique name of the skill. Required. + Downloads the zip content for a specific version of a skill. + + :param name: The name of the skill. Required. :type name: str - :return: DeleteSkillResult. The DeleteSkillResult is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DeleteSkillResult + :param version: The version to download content for. Required. + :type version: str + :return: AsyncIterator[bytes] + :rtype: AsyncIterator[bytes] :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -13084,10 +13092,11 @@ async def delete(self, name: str, **kwargs: Any) -> _models.DeleteSkillResult: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DeleteSkillResult] = kwargs.pop("cls", None) + cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) - _request = build_beta_skills_delete_request( + _request = build_beta_skills_download_version_request( name=name, + version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -13098,7 +13107,7 @@ async def delete(self, name: str, **kwargs: Any) -> _models.DeleteSkillResult: _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = kwargs.pop("stream", True) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -13118,102 +13127,29 @@ async def delete(self, name: str, **kwargs: Any) -> _models.DeleteSkillResult: ) raise HttpResponseError(response=response, model=error) - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.DeleteSkillResult, response.json()) + response_headers = {} + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore - @overload - async def create( - self, - name: str, - *, - content_type: str = "application/json", - inline_content: Optional[_models.SkillInlineContent] = None, - default: Optional[bool] = None, - **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill. If the skill does not exist, it will be created. - - :param name: The name of the skill. If the skill does not exist, it will be created. Required. - :type name: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :keyword inline_content: Inline skill content for simple skills without file uploads. - Foundry-specific extension. Default value is None. - :paramtype inline_content: ~azure.ai.projects.models.SkillInlineContent - :keyword default: Whether to set this version as the default. Default value is None. - :paramtype default: bool - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def create( - self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill. If the skill does not exist, it will be created. - - :param name: The name of the skill. If the skill does not exist, it will be created. Required. - :type name: str - :param body: Required. - :type body: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def create( - self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill. If the skill does not exist, it will be created. - - :param name: The name of the skill. If the skill does not exist, it will be created. Required. - :type name: str - :param body: Required. - :type body: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ - @distributed_trace_async - async def create( - self, - name: str, - body: Union[JSON, IO[bytes]] = _Unset, - *, - inline_content: Optional[_models.SkillInlineContent] = None, - default: Optional[bool] = None, - **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill. If the skill does not exist, it will be created. + async def delete_version(self, name: str, version: str, **kwargs: Any) -> _models.DeleteSkillVersionResult: + """Delete a specific version of a skill. - :param name: The name of the skill. If the skill does not exist, it will be created. Required. + Removes the specified version of a skill. + + :param name: The name of the skill. Required. :type name: str - :param body: Is either a JSON type or a IO[bytes] type. Required. - :type body: JSON or IO[bytes] - :keyword inline_content: Inline skill content for simple skills without file uploads. - Foundry-specific extension. Default value is None. - :paramtype inline_content: ~azure.ai.projects.models.SkillInlineContent - :keyword default: Whether to set this version as the default. Default value is None. - :paramtype default: bool - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion + :param version: The version identifier to delete. Required. + :type version: str + :return: DeleteSkillVersionResult. The DeleteSkillVersionResult is compatible with + MutableMapping + :rtype: ~azure.ai.projects.models.DeleteSkillVersionResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -13224,27 +13160,15 @@ async def create( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) - - if body is _Unset: - body = {"default": default, "inline_content": inline_content} - body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/json" - _content = None - if isinstance(body, (IOBase, bytes)): - _content = body - else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[_models.DeleteSkillVersionResult] = kwargs.pop("cls", None) - _request = build_beta_skills_create_request( + _request = build_beta_skills_delete_version_request( name=name, - content_type=content_type, + version=version, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -13277,53 +13201,41 @@ async def create( if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SkillVersion, response.json()) + deserialized = _deserialize(_models.DeleteSkillVersionResult, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - @overload - async def create_from_files( - self, name: str, content: _models.CreateSkillVersionFromFilesBody, **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill from uploaded files via multipart form data. - :param name: The name of the skill. Required. - :type name: str - :param content: Required. - :type content: ~azure.ai.projects.models.CreateSkillVersionFromFilesBody - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ +class BetaDatasetsOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. - @overload - async def create_from_files(self, name: str, content: JSON, **kwargs: Any) -> _models.SkillVersion: - """Creates a new version of a skill from uploaded files via multipart form data. + Instead, you should access the following operations through + :class:`~azure.ai.projects.aio.AIProjectClient`'s + :attr:`datasets` attribute. + """ - :param name: The name of the skill. Required. - :type name: str - :param content: Required. - :type content: JSON - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") @distributed_trace_async - async def create_from_files( - self, name: str, content: Union[_models.CreateSkillVersionFromFilesBody, JSON], **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill from uploaded files via multipart form data. + async def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerationJob: + """Get a data generation job. - :param name: The name of the skill. Required. - :type name: str - :param content: Is either a CreateSkillVersionFromFilesBody type or a JSON type. Required. - :type content: ~azure.ai.projects.models.CreateSkillVersionFromFilesBody or JSON - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion + Retrieves the specified data generation job and its current status. + + :param job_id: The ID of the job. Required. + :type job_id: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -13337,17 +13249,11 @@ async def create_from_files( _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) - - _body = content.as_dict() if isinstance(content, _Model) else content - _file_fields: list[str] = ["files"] - _data_fields: list[str] = ["default"] - _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) - _request = build_beta_skills_create_from_files_request( - name=name, + _request = build_beta_datasets_get_generation_job_request( + job_id=job_id, api_version=self._config.api_version, - files=_files, headers=_headers, params=_params, ) @@ -13377,30 +13283,32 @@ async def create_from_files( ) raise HttpResponseError(response=response, model=error) + response_headers = {} + response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SkillVersion, response.json()) + deserialized = _deserialize(_models.DataGenerationJob, response.json()) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore @distributed_trace - def list_versions( + def list_generation_jobs( self, - name: str, *, limit: Optional[int] = None, order: Optional[Union[str, _models.PageOrder]] = None, before: Optional[str] = None, **kwargs: Any - ) -> AsyncItemPaged["_models.SkillVersion"]: - """List all versions of a skill. + ) -> AsyncItemPaged["_models.DataGenerationJob"]: + """List data generation jobs. + + Returns a list of data generation jobs. - :param name: The name of the skill to list versions for. Required. - :type name: str :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. Default value is None. @@ -13415,14 +13323,14 @@ def list_versions( subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str - :return: An iterator like instance of SkillVersion - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.SkillVersion] + :return: An iterator like instance of DataGenerationJob + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.DataGenerationJob] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.SkillVersion]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.DataGenerationJob]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -13434,8 +13342,7 @@ def list_versions( def prepare_request(_continuation_token=None): - _request = build_beta_skills_list_versions_request( - name=name, + _request = build_beta_datasets_list_generation_jobs_request( limit=limit, order=order, after=_continuation_token, @@ -13453,7 +13360,7 @@ def prepare_request(_continuation_token=None): async def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.SkillVersion], + List[_models.DataGenerationJob], deserialized.get("data", []), ) if cls: @@ -13477,20 +13384,103 @@ async def get_next(_continuation_token=None): ) raise HttpResponseError(response=response, model=error) - return pipeline_response + return pipeline_response + + return AsyncItemPaged(get_next, extract_data) + + @overload + async def create_generation_job( + self, + job: _models.DataGenerationJob, + *, + operation_id: Optional[str] = None, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.DataGenerationJob: + """Create a data generation job. + + Submits a new data generation job for asynchronous execution. + + :param job: The job to create. Required. + :type job: ~azure.ai.projects.models.DataGenerationJob + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_generation_job( + self, job: JSON, *, operation_id: Optional[str] = None, content_type: str = "application/json", **kwargs: Any + ) -> _models.DataGenerationJob: + """Create a data generation job. + + Submits a new data generation job for asynchronous execution. + + :param job: The job to create. Required. + :type job: JSON + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_generation_job( + self, + job: IO[bytes], + *, + operation_id: Optional[str] = None, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.DataGenerationJob: + """Create a data generation job. - return AsyncItemPaged(get_next, extract_data) + Submits a new data generation job for asynchronous execution. + + :param job: The job to create. Required. + :type job: IO[bytes] + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace_async - async def get_version(self, name: str, version: str, **kwargs: Any) -> _models.SkillVersion: - """Retrieve a specific version of a skill. + async def create_generation_job( + self, + job: Union[_models.DataGenerationJob, JSON, IO[bytes]], + *, + operation_id: Optional[str] = None, + **kwargs: Any + ) -> _models.DataGenerationJob: + """Create a data generation job. - :param name: The name of the skill. Required. - :type name: str - :param version: The version identifier to retrieve. Required. - :type version: str - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion + Submits a new data generation job for asynchronous execution. + + :param job: The job to create. Is one of the following types: DataGenerationJob, JSON, + IO[bytes] Required. + :type job: ~azure.ai.projects.models.DataGenerationJob or JSON or IO[bytes] + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -13501,15 +13491,24 @@ async def get_version(self, name: str, version: str, **kwargs: Any) -> _models.S } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) - _request = build_beta_skills_get_version_request( - name=name, - version=version, + content_type = content_type or "application/json" + _content = None + if isinstance(job, (IOBase, bytes)): + _content = job + else: + _content = json.dumps(job, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_beta_datasets_create_generation_job_request( + operation_id=operation_id, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -13526,7 +13525,7 @@ async def get_version(self, name: str, version: str, **kwargs: Any) -> _models.S response = pipeline_response.http_response - if response.status_code not in [200]: + if response.status_code not in [201]: if _stream: try: await response.read() # Load the body in memory and close the socket @@ -13539,24 +13538,30 @@ async def get_version(self, name: str, version: str, **kwargs: Any) -> _models.S ) raise HttpResponseError(response=response, model=error) + response_headers = {} + response_headers["Operation-Location"] = self._deserialize("str", response.headers.get("Operation-Location")) + response_headers["Location"] = self._deserialize("str", response.headers.get("Location")) + if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SkillVersion, response.json()) + deserialized = _deserialize(_models.DataGenerationJob, response.json()) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore @distributed_trace_async - async def download(self, name: str, **kwargs: Any) -> AsyncIterator[bytes]: - """Download the zip content for the default version of a skill. + async def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerationJob: + """Cancel a data generation job. - :param name: The name of the skill. Required. - :type name: str - :return: AsyncIterator[bytes] - :rtype: AsyncIterator[bytes] + Cancels the specified data generation job if it is still in progress. + + :param job_id: The ID of the job to cancel. Required. + :type job_id: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -13570,10 +13575,10 @@ async def download(self, name: str, **kwargs: Any) -> AsyncIterator[bytes]: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) + cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) - _request = build_beta_skills_download_request( - name=name, + _request = build_beta_datasets_cancel_generation_job_request( + job_id=job_id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -13584,7 +13589,7 @@ async def download(self, name: str, **kwargs: Any) -> AsyncIterator[bytes]: _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -13604,26 +13609,26 @@ async def download(self, name: str, **kwargs: Any) -> AsyncIterator[bytes]: ) raise HttpResponseError(response=response, model=error) - response_headers = {} - response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) - - deserialized = response.iter_bytes() if _decompress else response.iter_raw() + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.DataGenerationJob, response.json()) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore @distributed_trace_async - async def download_version(self, name: str, version: str, **kwargs: Any) -> AsyncIterator[bytes]: - """Download the zip content for a specific version of a skill. + async def delete_generation_job(self, job_id: str, **kwargs: Any) -> None: + """Delete a data generation job. - :param name: The name of the skill. Required. - :type name: str - :param version: The version to download content for. Required. - :type version: str - :return: AsyncIterator[bytes] - :rtype: AsyncIterator[bytes] + Removes the specified data generation job and its associated output. + + :param job_id: The ID of the job to delete. Required. + :type job_id: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -13637,11 +13642,10 @@ async def download_version(self, name: str, version: str, **kwargs: Any) -> Asyn _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[AsyncIterator[bytes]] = kwargs.pop("cls", None) + cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_beta_skills_download_version_request( - name=name, - version=version, + _request = build_beta_datasets_delete_generation_job_request( + job_id=job_id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -13651,20 +13655,14 @@ async def download_version(self, name: str, version: str, **kwargs: Any) -> Asyn } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", True) + _stream = False pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass + if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) error = _failsafe_deserialize( _models.ApiErrorResponse, @@ -13672,27 +13670,120 @@ async def download_version(self, name: str, version: str, **kwargs: Any) -> Asyn ) raise HttpResponseError(response=response, model=error) - response_headers = {} - response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + if cls: + return cls(pipeline_response, None, {}) # type: ignore - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore +class BetaAgentsOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. - return deserialized # type: ignore + Instead, you should access the following operations through + :class:`~azure.ai.projects.aio.AIProjectClient`'s + :attr:`agents` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + + @overload + async def create_optimization_job( + self, + job: _models.OptimizationJob, + *, + operation_id: Optional[str] = None, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.OptimizationJob: + """Creates an agent optimization job. + + Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for + idempotent retry. + + :param job: The job to create. Required. + :type job: ~azure.ai.projects.models.OptimizationJob + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_optimization_job( + self, job: JSON, *, operation_id: Optional[str] = None, content_type: str = "application/json", **kwargs: Any + ) -> _models.OptimizationJob: + """Creates an agent optimization job. + + Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for + idempotent retry. + + :param job: The job to create. Required. + :type job: JSON + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_optimization_job( + self, + job: IO[bytes], + *, + operation_id: Optional[str] = None, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.OptimizationJob: + """Creates an agent optimization job. + + Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for + idempotent retry. + + :param job: The job to create. Required. + :type job: IO[bytes] + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace_async - async def delete_version(self, name: str, version: str, **kwargs: Any) -> _models.DeleteSkillVersionResult: - """Delete a specific version of a skill. + async def create_optimization_job( + self, job: Union[_models.OptimizationJob, JSON, IO[bytes]], *, operation_id: Optional[str] = None, **kwargs: Any + ) -> _models.OptimizationJob: + """Creates an agent optimization job. - :param name: The name of the skill. Required. - :type name: str - :param version: The version identifier to delete. Required. - :type version: str - :return: DeleteSkillVersionResult. The DeleteSkillVersionResult is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.DeleteSkillVersionResult + Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for + idempotent retry. + + :param job: The job to create. Is one of the following types: OptimizationJob, JSON, IO[bytes] + Required. + :type job: ~azure.ai.projects.models.OptimizationJob or JSON or IO[bytes] + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -13703,15 +13794,24 @@ async def delete_version(self, name: str, version: str, **kwargs: Any) -> _model } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DeleteSkillVersionResult] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) - _request = build_beta_skills_delete_version_request( - name=name, - version=version, + content_type = content_type or "application/json" + _content = None + if isinstance(job, (IOBase, bytes)): + _content = job + else: + _content = json.dumps(job, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_beta_agents_create_optimization_job_request( + operation_id=operation_id, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -13728,7 +13828,7 @@ async def delete_version(self, name: str, version: str, **kwargs: Any) -> _model response = pipeline_response.http_response - if response.status_code not in [200]: + if response.status_code not in [201]: if _stream: try: await response.read() # Load the body in memory and close the socket @@ -13741,44 +13841,30 @@ async def delete_version(self, name: str, version: str, **kwargs: Any) -> _model ) raise HttpResponseError(response=response, model=error) + response_headers = {} + response_headers["Operation-Location"] = self._deserialize("str", response.headers.get("Operation-Location")) + response_headers["Location"] = self._deserialize("str", response.headers.get("Location")) + if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.DeleteSkillVersionResult, response.json()) + deserialized = _deserialize(_models.OptimizationJob, response.json()) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore - -class BetaDatasetsOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. - - Instead, you should access the following operations through - :class:`~azure.ai.projects.aio.AIProjectClient`'s - :attr:`datasets` attribute. - """ - - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: AsyncPipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") - @distributed_trace_async - async def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerationJob: - """Get info about a data generation job. + async def get_optimization_job(self, job_id: str, **kwargs: Any) -> _models.OptimizationJob: + """Get info about an agent optimization job. - Gets the details of a data generation job by its ID. + Get an optimization job by id. :param job_id: The ID of the job. Required. :type job_id: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -13792,9 +13878,9 @@ async def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGe _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) + cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) - _request = build_beta_datasets_get_generation_job_request( + _request = build_beta_agents_get_optimization_job_request( job_id=job_id, api_version=self._config.api_version, headers=_headers, @@ -13832,7 +13918,7 @@ async def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGe if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.DataGenerationJob, response.json()) + deserialized = _deserialize(_models.OptimizationJob, response.json()) if cls: return cls(pipeline_response, deserialized, response_headers) # type: ignore @@ -13840,17 +13926,19 @@ async def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGe return deserialized # type: ignore @distributed_trace - def list_generation_jobs( + def list_optimization_jobs( self, *, limit: Optional[int] = None, order: Optional[Union[str, _models.PageOrder]] = None, before: Optional[str] = None, + status: Optional[Union[str, _models.JobStatus]] = None, + agent_name: Optional[str] = None, **kwargs: Any - ) -> AsyncItemPaged["_models.DataGenerationJob"]: - """Returns a list of data generation jobs. + ) -> AsyncItemPaged["_models.OptimizationJobListItem"]: + """Returns a list of agent optimization jobs. - Returns a list of data generation jobs. + List optimization jobs. Supports cursor pagination and optional status / agent_name filters. :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the @@ -13866,14 +13954,20 @@ def list_generation_jobs( subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str - :return: An iterator like instance of DataGenerationJob - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.DataGenerationJob] + :keyword status: Filter to jobs in this lifecycle state. Known values are: "queued", + "in_progress", "succeeded", "failed", and "cancelled". Default value is None. + :paramtype status: str or ~azure.ai.projects.models.JobStatus + :keyword agent_name: Filter to jobs targeting this agent name. Default value is None. + :paramtype agent_name: str + :return: An iterator like instance of OptimizationJobListItem + :rtype: + ~azure.core.async_paging.AsyncItemPaged[~azure.ai.projects.models.OptimizationJobListItem] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.DataGenerationJob]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.OptimizationJobListItem]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -13885,11 +13979,13 @@ def list_generation_jobs( def prepare_request(_continuation_token=None): - _request = build_beta_datasets_list_generation_jobs_request( + _request = build_beta_agents_list_optimization_jobs_request( limit=limit, order=order, after=_continuation_token, before=before, + status=status, + agent_name=agent_name, api_version=self._config.api_version, headers=_headers, params=_params, @@ -13903,7 +13999,7 @@ def prepare_request(_continuation_token=None): async def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.DataGenerationJob], + List[_models.OptimizationJobListItem], deserialized.get("data", []), ) if cls: @@ -13931,180 +14027,17 @@ async def get_next(_continuation_token=None): return AsyncItemPaged(get_next, extract_data) - @overload - async def create_generation_job( - self, - job: _models.DataGenerationJob, - *, - operation_id: Optional[str] = None, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.DataGenerationJob: - """Creates a data generation job. - - Creates a data generation job. - - :param job: The job to create. Required. - :type job: ~azure.ai.projects.models.DataGenerationJob - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def create_generation_job( - self, job: JSON, *, operation_id: Optional[str] = None, content_type: str = "application/json", **kwargs: Any - ) -> _models.DataGenerationJob: - """Creates a data generation job. - - Creates a data generation job. - - :param job: The job to create. Required. - :type job: JSON - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - async def create_generation_job( - self, - job: IO[bytes], - *, - operation_id: Optional[str] = None, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.DataGenerationJob: - """Creates a data generation job. - - Creates a data generation job. - - :param job: The job to create. Required. - :type job: IO[bytes] - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @distributed_trace_async - async def create_generation_job( - self, - job: Union[_models.DataGenerationJob, JSON, IO[bytes]], - *, - operation_id: Optional[str] = None, - **kwargs: Any - ) -> _models.DataGenerationJob: - """Creates a data generation job. - - Creates a data generation job. - - :param job: The job to create. Is one of the following types: DataGenerationJob, JSON, - IO[bytes] Required. - :type job: ~azure.ai.projects.models.DataGenerationJob or JSON or IO[bytes] - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = kwargs.pop("params", {}) or {} - - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) - - content_type = content_type or "application/json" - _content = None - if isinstance(job, (IOBase, bytes)): - _content = job - else: - _content = json.dumps(job, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - - _request = build_beta_datasets_create_generation_job_request( - operation_id=operation_id, - content_type=content_type, - api_version=self._config.api_version, - content=_content, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - - response = pipeline_response.http_response - - if response.status_code not in [201]: - if _stream: - try: - await response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers["Operation-Location"] = self._deserialize("str", response.headers.get("Operation-Location")) - response_headers["Location"] = self._deserialize("str", response.headers.get("Location")) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.DataGenerationJob, response.json()) - - if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore - - return deserialized # type: ignore - @distributed_trace_async - async def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerationJob: - """Cancels a data generation job. + async def cancel_optimization_job(self, job_id: str, **kwargs: Any) -> _models.OptimizationJob: + """Cancels an agent optimization job. - Cancels a data generation job by its ID. + Request cancellation of a running or queued job. Returns an error if the job is already in a + terminal state. :param job_id: The ID of the job to cancel. Required. :type job_id: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -14118,9 +14051,9 @@ async def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.Dat _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) + cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) - _request = build_beta_datasets_cancel_generation_job_request( + _request = build_beta_agents_cancel_optimization_job_request( job_id=job_id, api_version=self._config.api_version, headers=_headers, @@ -14155,7 +14088,7 @@ async def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.Dat if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.DataGenerationJob, response.json()) + deserialized = _deserialize(_models.OptimizationJob, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -14163,10 +14096,10 @@ async def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.Dat return deserialized # type: ignore @distributed_trace_async - async def delete_generation_job(self, job_id: str, **kwargs: Any) -> None: - """Deletes a data generation job. + async def delete_optimization_job(self, job_id: str, **kwargs: Any) -> None: + """Deletes an agent optimization job. - Deletes a data generation job by its ID. + Delete the job and its candidate artifacts. Cancels first if non-terminal. :param job_id: The ID of the job to delete. Required. :type job_id: str @@ -14187,7 +14120,7 @@ async def delete_generation_job(self, job_id: str, **kwargs: Any) -> None: cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_beta_datasets_delete_generation_job_request( + _request = build_beta_agents_delete_optimization_job_request( job_id=job_id, api_version=self._config.api_version, headers=_headers, diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch.py b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch.py index 9840dd5a6ac6..5d8893177cae 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch.py @@ -16,9 +16,9 @@ from ._patch_connections_async import ConnectionsOperations from ._patch_memories_async import BetaMemoryStoresOperations from ._patch_models_async import BetaModelsOperations -from ._patch_sessions_async import BetaAgentsOperations from ...operations._patch import _BETA_OPERATION_FEATURE_HEADERS, _OperationMethodHeaderProxy from ._operations import ( + BetaAgentsOperations, BetaDatasetsOperations, BetaEvaluationTaxonomiesOperations, BetaEvaluatorsOperations, @@ -28,7 +28,6 @@ BetaRoutinesOperations, BetaSchedulesOperations, BetaSkillsOperations, - BetaToolboxesOperations, ) @@ -60,8 +59,6 @@ class BetaOperations(GeneratedBetaOperations): """:class:`~azure.ai.projects.aio.operations.BetaRoutinesOperations` operations""" schedules: BetaSchedulesOperations """:class:`~azure.ai.projects.aio.operations.BetaSchedulesOperations` operations""" - toolboxes: BetaToolboxesOperations - """:class:`~azure.ai.projects.aio.operations.BetaToolboxesOperations` operations""" skills: BetaSkillsOperations """:class:`~azure.ai.projects.aio.operations.BetaSkillsOperations` operations""" datasets: BetaDatasetsOperations @@ -100,7 +97,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: "BetaRoutinesOperations", "BetaSchedulesOperations", "BetaSkillsOperations", - "BetaToolboxesOperations", "ConnectionsOperations", "DatasetsOperations", "EvaluationRulesOperations", diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_agents_async.py b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_agents_async.py index 46a4d7a9e456..41d4362d8fda 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_agents_async.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_agents_async.py @@ -8,6 +8,9 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ +import hashlib +import os +from pathlib import Path from typing import Union, Optional, Any, IO, overload from azure.core.exceptions import HttpResponseError from azure.core.tracing.decorator_async import distributed_trace_async @@ -198,3 +201,224 @@ async def create_version( new_exc.model = exc.model raise new_exc from exc raise + + @overload + async def upload_session_file( + self, + agent_name: str, + session_id: str, + *, + content: bytes, + remote_path: str, + **kwargs: Any, + ) -> _models.SessionFileWriteResult: + """Upload binary content to the session sandbox. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session ID. Required. + :type session_id: str + :keyword content: The binary content to upload. Required. + :paramtype content: bytes + :keyword remote_path: The destination file path within the sandbox, relative to the session home + directory. Required. + :paramtype remote_path: str + :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SessionFileWriteResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + ... + + @overload + async def upload_session_file( + self, + agent_name: str, + session_id: str, + *, + file_path: Union[str, "os.PathLike[str]"], + remote_path: str, + **kwargs: Any, + ) -> _models.SessionFileWriteResult: + """Upload a file from disk to the session sandbox. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session ID. Required. + :type session_id: str + :keyword file_path: The full path to a local file whose contents should be uploaded. Required. + :paramtype file_path: str or os.PathLike[str] + :keyword remote_path: The destination file path within the sandbox, relative to the session home + directory. Required. + :paramtype remote_path: str + :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SessionFileWriteResult + :raises ~azure.core.exceptions.HttpResponseError: + :raises FileNotFoundError: If *file_path* does not exist. + """ + ... + + @distributed_trace_async + async def upload_session_file( # type: ignore[override] + self, + agent_name: str, + session_id: str, + *, + content: Optional[bytes] = None, + file_path: Optional[Union[str, "os.PathLike[str]"]] = None, + remote_path: str, + **kwargs: Any, + ) -> _models.SessionFileWriteResult: + """Upload a file to the session sandbox. + + Accepts either binary content directly or a local file path. + When a file path is provided the file is read from disk and its contents + are forwarded to the service. Maximum file size is 50 MB. Uploads + exceeding this limit return 413 Payload Too Large. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session ID. Required. + :type session_id: str + :keyword content: The binary content to upload. Mutually exclusive with *file_path*. + :paramtype content: bytes + :keyword file_path: The full path to a local file whose contents should be uploaded. + Mutually exclusive with *content*. + :paramtype file_path: str or os.PathLike[str] + :keyword remote_path: The destination file path within the sandbox, relative to the session home + directory. Required. + :paramtype remote_path: str + :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SessionFileWriteResult + :raises ~azure.core.exceptions.HttpResponseError: + :raises ValueError: If both *content* and *file_path* are provided, or neither is provided. + :raises FileNotFoundError: If *file_path* is provided and does not exist. + """ + if content is not None and file_path is not None: + raise ValueError("Specify either 'content' or 'file_path', not both.") + if content is None and file_path is None: + raise ValueError("Specify either 'content' or 'file_path'.") + + if file_path is not None: + p = Path(file_path) + if not p.exists(): + raise FileNotFoundError(f"The provided file `{file_path}` does not exist.") + if p.is_dir(): + raise ValueError(f"Provide a valid file path, not a folder path `{file_path}`.") + with open(file_path, "rb") as f: + content = f.read() + + assert content is not None # Guaranteed by validation above + + return await super()._upload_session_file(agent_name, session_id, content, remote_path=remote_path, **kwargs) + + @distributed_trace_async + async def download_session_file_to_path( + self, + agent_name: str, + session_id: str, + *, + file_path: Union[str, "os.PathLike[str]"], + overwrite: bool = False, + remote_path: str, + **kwargs: Any, + ) -> None: + """Download a session file directly to disk. + + Downloads the file at the specified sandbox path and writes it to a local file. + The remote path is resolved relative to the session home directory. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session ID. Required. + :type session_id: str + :keyword file_path: The full path to the local file where the content should be written. Required. + :paramtype file_path: str or os.PathLike[str] + :keyword overwrite: If True, overwrite the local file if it already exists. If False (default), + raise FileExistsError when the file already exists. + :paramtype overwrite: bool + :keyword remote_path: The file path to download from the sandbox, relative to the session home + directory. Required. + :paramtype remote_path: str + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + :raises FileExistsError: If *file_path* already exists and *overwrite* is False. + :raises ValueError: If *file_path* points to a directory. + :raises OSError: If the file cannot be written. + """ + p = Path(file_path) + if p.exists(): + if p.is_dir(): + raise ValueError(f"Provide a valid file path, not a folder path `{file_path}`.") + if not overwrite: + raise FileExistsError(f"The file `{file_path}` already exists. Set overwrite=True to replace it.") + + # Download the file content using the existing method + content_iterator = await self.download_session_file_as_bytes( + agent_name=agent_name, + agent_session_id=session_id, + remote_path=remote_path, + **kwargs, + ) + + # Write the content to disk + with open(file_path, "wb") as f: + async for chunk in content_iterator: + f.write(chunk) + + @distributed_trace_async + async def download_code_to_path( + self, + agent_name: str, + *, + file_path: Union[str, "os.PathLike[str]"], + overwrite: bool = False, + agent_version: Optional[str] = None, + **kwargs: Any, + ) -> str: + """Download agent code directly to disk. + + Downloads the code zip for a code-based hosted agent and writes it to a local file. + + If ``agent_version`` is supplied, downloads that version's code zip; otherwise + downloads the latest version's code zip. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :keyword file_path: The full path to the local file where the code zip should be written. Required. + :paramtype file_path: str or os.PathLike[str] + :keyword overwrite: If True, overwrite the local file if it already exists. If False (default), + raise FileExistsError when the file already exists. + :paramtype overwrite: bool + :keyword agent_version: The version of the agent whose code zip should be downloaded. + If omitted, the latest version's code zip is downloaded. Default value is None. + :paramtype agent_version: str + :return: The SHA-256 hex digest of the downloaded file. + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + :raises FileExistsError: If *file_path* already exists and *overwrite* is False. + :raises ValueError: If *file_path* points to a directory. + :raises OSError: If the file cannot be written. + """ + p = Path(file_path) + if p.exists(): + if p.is_dir(): + raise ValueError(f"Provide a valid file path, not a folder path `{file_path}`.") + if not overwrite: + raise FileExistsError(f"The file `{file_path}` already exists. Set overwrite=True to replace it.") + + # Download the code content using the existing method + content_iterator = await self.download_code_as_bytes( + agent_name=agent_name, + agent_version=agent_version, + **kwargs, + ) + + # Write the content to disk and calculate SHA-256 + sha = hashlib.sha256() + with open(file_path, "wb") as f: + async for chunk in content_iterator: + f.write(chunk) + sha.update(chunk) + + return sha.hexdigest() diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_connections_async.py b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_connections_async.py index f32515aca2fe..792bb1631a82 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_connections_async.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_connections_async.py @@ -30,7 +30,7 @@ class ConnectionsOperations(ConnectionsOperationsGenerated): async def get(self, name: str, *, include_credentials: Optional[bool] = False, **kwargs: Any) -> Connection: """Get a connection by name. - :param name: The name of the resource. Required. + :param name: The name of the connection. Required. :type name: str :keyword include_credentials: Whether to include credentials in the response. Default is False. :paramtype include_credentials: bool @@ -38,18 +38,8 @@ async def get(self, name: str, *, include_credentials: Optional[bool] = False, * :rtype: ~azure.ai.projects.models.Connection :raises ~azure.core.exceptions.HttpResponseError: """ - if include_credentials: - connection = await super()._get_with_credentials(name, **kwargs) - if connection.type == ConnectionType.CUSTOM: - # Why do we do this? See comment in the sync version of this code (file _patch_connections.py). - setattr( - connection.credentials, - "credential_keys", - {k: v for k, v in connection.credentials.as_dict().items() if k != "type"}, - ) - - return connection + return await super()._get_with_credentials(name, **kwargs) return await super()._get(name, **kwargs) diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_sessions_async.py b/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_sessions_async.py deleted file mode 100644 index dd1427541a65..000000000000 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/aio/operations/_patch_sessions_async.py +++ /dev/null @@ -1,74 +0,0 @@ -# pylint: disable=line-too-long,useless-suppression -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -"""Customize generated code here. - -Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize -""" - -from pathlib import Path -from typing import Any -from azure.core.tracing.decorator_async import distributed_trace_async -from ._operations import BetaAgentsOperations as GeneratedBetaAgentsOperations -from ... import models as _models - - -class BetaAgentsOperations(GeneratedBetaAgentsOperations): - """ - .. warning:: - **DO NOT** instantiate this class directly. - - Instead, you should access the following operations through - :class:`~azure.ai.projects.aio.AIProjectClient`'s - :attr:`beta.agents` attribute. - """ - - @distributed_trace_async - async def upload_session_file( # type: ignore[override] - self, - agent_name: str, - session_id: str, - content_or_file_path: "bytes | str", - *, - path: str, - **kwargs: Any, - ) -> _models.SessionFileWriteResult: - """Upload a file to the session sandbox. - - Accepts either a ``bytes`` buffer or a local file path (``str``). - When a file path is provided the file is read from disk and its contents - are forwarded to the service. Maximum file size is 50 MB. Uploads - exceeding this limit return 413 Payload Too Large. - - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param session_id: The session ID. Required. - :type session_id: str - :param content_or_file_path: The binary content to upload, **or** the full path to a local - file whose contents should be uploaded. Required. - :type content_or_file_path: bytes or str - :keyword path: The destination file path within the sandbox, relative to the session home - directory. Required. - :paramtype path: str - :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.SessionFileWriteResult - :raises ~azure.core.exceptions.HttpResponseError: - :raises FileNotFoundError: If *content_or_file_path* is a ``str`` and the file does not exist. - """ - if isinstance(content_or_file_path, str): - - file_path = Path(content_or_file_path) - if not file_path.exists(): - raise ValueError(f"The provided file `{content_or_file_path}` does not exist.") - if file_path.is_dir(): - raise ValueError(f"Provide a valid file path, not a folder path `{content_or_file_path}`.") - - with open(content_or_file_path, "rb") as f: - content: bytes = f.read() - else: - content = content_or_file_path - - return await super()._upload_session_file(agent_name, session_id, content, path=path, **kwargs) diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/models/__init__.py b/sdk/ai/azure-ai-projects/azure/ai/projects/models/__init__.py index 29197fc4bbad..db0b6b2db6f3 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/models/__init__.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/models/__init__.py @@ -15,7 +15,10 @@ from ._models import ( # type: ignore A2APreviewTool, + A2APreviewToolboxTool, + A2AProtocolConfiguration, AISearchIndexResource, + ActivityProtocolConfiguration, AgentBlueprintReference, AgentCard, AgentCardSkill, @@ -27,14 +30,12 @@ AgentEndpointAuthorizationScheme, AgentEndpointConfig, AgentEvaluatorGenerationJobSource, - AgentIdentifier, AgentIdentity, AgentObjectVersions, AgentSessionResource, AgentTaxonomyInput, AgentVersionDetails, AgenticIdentityPreviewCredentials, - AgentsPagedResultOptimizationCandidate, ApiError, ApiErrorResponse, ApiKeyCredentials, @@ -47,6 +48,7 @@ AzureAISearchIndex, AzureAISearchTool, AzureAISearchToolResource, + AzureAISearchToolboxTool, AzureFunctionBinding, AzureFunctionDefinition, AzureFunctionDefinitionFunction, @@ -64,13 +66,11 @@ BlobReferenceSasCredential, BotServiceAuthorizationScheme, BotServiceRbacAuthorizationScheme, + BotServiceTenantAuthorizationScheme, BrowserAutomationPreviewTool, + BrowserAutomationPreviewToolboxTool, BrowserAutomationToolConnectionParameters, BrowserAutomationToolParameters, - CandidateDeployConfig, - CandidateFileInfo, - CandidateMetadata, - CandidateResults, CaptureStructuredOutputsTool, ChartCoordinate, ChatSummaryMemoryItem, @@ -79,8 +79,10 @@ CodeBasedEvaluatorDefinition, CodeConfiguration, CodeInterpreterTool, + CodeInterpreterToolboxTool, ComparisonFilter, CompoundFilter, + ComputerTool, ComputerUsePreviewTool, Connection, ContainerAutoParam, @@ -116,8 +118,6 @@ DatasetCredential, DatasetDataGenerationJobOutput, DatasetEvaluatorGenerationJobSource, - DatasetInfo, - DatasetRef, DatasetReference, DatasetVersion, DeleteAgentResponse, @@ -130,9 +130,10 @@ Dimension, DispatchRoutineResult, EmbeddingConfiguration, + EmptyModelParam, + EndpointBasedEvaluatorDefinition, EntraAuthorizationScheme, EntraIDCredentials, - EntraIsolationKeySource, EvalResult, EvalRunResultCompareItem, EvalRunResultComparison, @@ -161,11 +162,13 @@ ExternalAgentDefinition, FabricDataAgentToolParameters, FabricIQPreviewTool, + FabricIQPreviewToolboxTool, FieldMapping, FileDataGenerationJobOutput, FileDataGenerationJobSource, FileDatasetVersion, FileSearchTool, + FileSearchToolboxTool, FixedRatioVersionSelectionRule, FolderDatasetVersion, FoundryModelWarning, @@ -174,8 +177,8 @@ FunctionShellToolParamEnvironmentContainerReferenceParam, FunctionShellToolParamEnvironmentLocalEnvironmentParam, FunctionTool, + FunctionToolParam, GitHubIssueRoutineTrigger, - HeaderIsolationKeySource, HeaderTelemetryEndpointAuth, HostedAgentDefinition, HourlyRecurrenceSchedule, @@ -195,19 +198,22 @@ InsightScheduleTask, InsightSummary, InsightsMetadata, + InvocationsProtocolConfiguration, + InvocationsWsProtocolConfiguration, InvokeAgentInvocationsApiDispatchPayload, InvokeAgentInvocationsApiRoutineAction, InvokeAgentResponsesApiDispatchPayload, InvokeAgentResponsesApiRoutineAction, - IsolationKeySource, LocalShellToolParam, LocalSkillParam, LoraConfig, MCPTool, MCPToolFilter, MCPToolRequireApproval, + MCPToolboxTool, ManagedAgentIdentityBlueprintReference, ManagedAzureAISearchIndex, + McpProtocolConfiguration, MemoryItem, MemoryOperation, MemorySearchItem, @@ -232,6 +238,7 @@ ModelSourceData, ModelVersion, MonthlyRecurrenceSchedule, + NamespaceToolParam, NoAuthenticationCredentials, OneTimeTrigger, OpenApiAnonymousAuthDetails, @@ -243,26 +250,32 @@ OpenApiProjectConnectionAuthDetails, OpenApiProjectConnectionSecurityScheme, OpenApiTool, - OptimizationAgentDefinition, + OpenApiToolboxTool, + OptimizationAgentIdentifier, OptimizationCandidate, + OptimizationDatasetCriterion, + OptimizationDatasetInput, + OptimizationDatasetItem, + OptimizationEvaluatorRef, + OptimizationInlineDatasetInput, OptimizationJob, OptimizationJobInputs, + OptimizationJobListItem, OptimizationJobProgress, OptimizationJobResult, OptimizationOptions, - OptimizationTaskResult, + OptimizationReferenceDatasetInput, OtlpTelemetryEndpoint, PendingUploadRequest, PendingUploadResponse, ProceduralMemoryItem, - PromoteCandidateRequest, - PromoteCandidateResponse, PromotionInfo, PromptAgentDefinition, PromptAgentDefinitionTextOptions, PromptBasedEvaluatorDefinition, PromptDataGenerationJobSource, PromptEvaluatorGenerationJobSource, + ProtocolConfiguration, ProtocolVersionRecord, RaiConfig, RankingOptions, @@ -271,8 +284,11 @@ RecurrenceTrigger, RedTeam, RedTeamTargetConfig, + ReminderPreviewTool, + ReminderPreviewToolboxTool, ResponseUsageInputTokensDetails, ResponseUsageOutputTokensDetails, + ResponsesProtocolConfiguration, Routine, RoutineAction, RoutineDispatchPayload, @@ -298,7 +314,6 @@ SpecificFunctionShellParam, StructuredInputDefinition, StructuredOutputDefinition, - SystemDataV3, TaxonomyCategory, TaxonomySubCategory, TelemetryConfig, @@ -312,6 +327,8 @@ Tool, ToolChoiceAllowed, ToolChoiceCodeInterpreter, + ToolChoiceComputer, + ToolChoiceComputerUse, ToolChoiceComputerUsePreview, ToolChoiceCustom, ToolChoiceFileSearch, @@ -324,12 +341,14 @@ ToolConfig, ToolDescription, ToolProjectConnection, + ToolSearchToolParam, ToolUseFineTuningDataGenerationJobOptions, ToolboxObject, ToolboxPolicies, - ToolboxSearchPreviewTool, + ToolboxSearchPreviewToolboxTool, ToolboxSkill, ToolboxSkillReference, + ToolboxTool, ToolboxVersionObject, TracesDataGenerationJobOptions, TracesDataGenerationJobSource, @@ -347,8 +366,10 @@ WebSearchPreviewTool, WebSearchTool, WebSearchToolFilters, + WebSearchToolboxTool, WeeklyRecurrenceSchedule, WorkIQPreviewTool, + WorkIQPreviewToolboxTool, WorkflowAgentDefinition, ) @@ -358,8 +379,8 @@ AgentEndpointProtocol, AgentKind, AgentObjectType, - AgentProtocol, AgentSessionStatus, + AgentState, AgentVersionStatus, AttackStrategy, AzureAISearchQueryType, @@ -400,7 +421,6 @@ IndexType, InputFidelity, InsightType, - IsolationKeySourceKind, JobStatus, MemoryItemKind, MemoryOperationKind, @@ -409,6 +429,7 @@ MemoryStoreUpdateStatus, OpenApiAuthType, OperationState, + OptimizationDatasetInputType, PageOrder, PendingUploadType, RankerVersionType, @@ -422,6 +443,7 @@ SampleType, ScheduleProvisioningStatus, ScheduleTaskType, + SearchContentType, SearchContextSize, SessionLogEventType, SimpleQnAFineTuningQuestionType, @@ -431,7 +453,9 @@ TelemetryTransportProtocol, TextResponseFormatConfigurationType, ToolChoiceParamType, + ToolSearchExecutionType, ToolType, + ToolboxToolType, TreatmentEffectType, TriggerType, VersionIndicatorType, @@ -443,7 +467,10 @@ __all__ = [ "A2APreviewTool", + "A2APreviewToolboxTool", + "A2AProtocolConfiguration", "AISearchIndexResource", + "ActivityProtocolConfiguration", "AgentBlueprintReference", "AgentCard", "AgentCardSkill", @@ -455,14 +482,12 @@ "AgentEndpointAuthorizationScheme", "AgentEndpointConfig", "AgentEvaluatorGenerationJobSource", - "AgentIdentifier", "AgentIdentity", "AgentObjectVersions", "AgentSessionResource", "AgentTaxonomyInput", "AgentVersionDetails", "AgenticIdentityPreviewCredentials", - "AgentsPagedResultOptimizationCandidate", "ApiError", "ApiErrorResponse", "ApiKeyCredentials", @@ -475,6 +500,7 @@ "AzureAISearchIndex", "AzureAISearchTool", "AzureAISearchToolResource", + "AzureAISearchToolboxTool", "AzureFunctionBinding", "AzureFunctionDefinition", "AzureFunctionDefinitionFunction", @@ -492,13 +518,11 @@ "BlobReferenceSasCredential", "BotServiceAuthorizationScheme", "BotServiceRbacAuthorizationScheme", + "BotServiceTenantAuthorizationScheme", "BrowserAutomationPreviewTool", + "BrowserAutomationPreviewToolboxTool", "BrowserAutomationToolConnectionParameters", "BrowserAutomationToolParameters", - "CandidateDeployConfig", - "CandidateFileInfo", - "CandidateMetadata", - "CandidateResults", "CaptureStructuredOutputsTool", "ChartCoordinate", "ChatSummaryMemoryItem", @@ -507,8 +531,10 @@ "CodeBasedEvaluatorDefinition", "CodeConfiguration", "CodeInterpreterTool", + "CodeInterpreterToolboxTool", "ComparisonFilter", "CompoundFilter", + "ComputerTool", "ComputerUsePreviewTool", "Connection", "ContainerAutoParam", @@ -544,8 +570,6 @@ "DatasetCredential", "DatasetDataGenerationJobOutput", "DatasetEvaluatorGenerationJobSource", - "DatasetInfo", - "DatasetRef", "DatasetReference", "DatasetVersion", "DeleteAgentResponse", @@ -558,9 +582,10 @@ "Dimension", "DispatchRoutineResult", "EmbeddingConfiguration", + "EmptyModelParam", + "EndpointBasedEvaluatorDefinition", "EntraAuthorizationScheme", "EntraIDCredentials", - "EntraIsolationKeySource", "EvalResult", "EvalRunResultCompareItem", "EvalRunResultComparison", @@ -589,11 +614,13 @@ "ExternalAgentDefinition", "FabricDataAgentToolParameters", "FabricIQPreviewTool", + "FabricIQPreviewToolboxTool", "FieldMapping", "FileDataGenerationJobOutput", "FileDataGenerationJobSource", "FileDatasetVersion", "FileSearchTool", + "FileSearchToolboxTool", "FixedRatioVersionSelectionRule", "FolderDatasetVersion", "FoundryModelWarning", @@ -602,8 +629,8 @@ "FunctionShellToolParamEnvironmentContainerReferenceParam", "FunctionShellToolParamEnvironmentLocalEnvironmentParam", "FunctionTool", + "FunctionToolParam", "GitHubIssueRoutineTrigger", - "HeaderIsolationKeySource", "HeaderTelemetryEndpointAuth", "HostedAgentDefinition", "HourlyRecurrenceSchedule", @@ -623,19 +650,22 @@ "InsightScheduleTask", "InsightSummary", "InsightsMetadata", + "InvocationsProtocolConfiguration", + "InvocationsWsProtocolConfiguration", "InvokeAgentInvocationsApiDispatchPayload", "InvokeAgentInvocationsApiRoutineAction", "InvokeAgentResponsesApiDispatchPayload", "InvokeAgentResponsesApiRoutineAction", - "IsolationKeySource", "LocalShellToolParam", "LocalSkillParam", "LoraConfig", "MCPTool", "MCPToolFilter", "MCPToolRequireApproval", + "MCPToolboxTool", "ManagedAgentIdentityBlueprintReference", "ManagedAzureAISearchIndex", + "McpProtocolConfiguration", "MemoryItem", "MemoryOperation", "MemorySearchItem", @@ -660,6 +690,7 @@ "ModelSourceData", "ModelVersion", "MonthlyRecurrenceSchedule", + "NamespaceToolParam", "NoAuthenticationCredentials", "OneTimeTrigger", "OpenApiAnonymousAuthDetails", @@ -671,26 +702,32 @@ "OpenApiProjectConnectionAuthDetails", "OpenApiProjectConnectionSecurityScheme", "OpenApiTool", - "OptimizationAgentDefinition", + "OpenApiToolboxTool", + "OptimizationAgentIdentifier", "OptimizationCandidate", + "OptimizationDatasetCriterion", + "OptimizationDatasetInput", + "OptimizationDatasetItem", + "OptimizationEvaluatorRef", + "OptimizationInlineDatasetInput", "OptimizationJob", "OptimizationJobInputs", + "OptimizationJobListItem", "OptimizationJobProgress", "OptimizationJobResult", "OptimizationOptions", - "OptimizationTaskResult", + "OptimizationReferenceDatasetInput", "OtlpTelemetryEndpoint", "PendingUploadRequest", "PendingUploadResponse", "ProceduralMemoryItem", - "PromoteCandidateRequest", - "PromoteCandidateResponse", "PromotionInfo", "PromptAgentDefinition", "PromptAgentDefinitionTextOptions", "PromptBasedEvaluatorDefinition", "PromptDataGenerationJobSource", "PromptEvaluatorGenerationJobSource", + "ProtocolConfiguration", "ProtocolVersionRecord", "RaiConfig", "RankingOptions", @@ -699,8 +736,11 @@ "RecurrenceTrigger", "RedTeam", "RedTeamTargetConfig", + "ReminderPreviewTool", + "ReminderPreviewToolboxTool", "ResponseUsageInputTokensDetails", "ResponseUsageOutputTokensDetails", + "ResponsesProtocolConfiguration", "Routine", "RoutineAction", "RoutineDispatchPayload", @@ -726,7 +766,6 @@ "SpecificFunctionShellParam", "StructuredInputDefinition", "StructuredOutputDefinition", - "SystemDataV3", "TaxonomyCategory", "TaxonomySubCategory", "TelemetryConfig", @@ -740,6 +779,8 @@ "Tool", "ToolChoiceAllowed", "ToolChoiceCodeInterpreter", + "ToolChoiceComputer", + "ToolChoiceComputerUse", "ToolChoiceComputerUsePreview", "ToolChoiceCustom", "ToolChoiceFileSearch", @@ -752,12 +793,14 @@ "ToolConfig", "ToolDescription", "ToolProjectConnection", + "ToolSearchToolParam", "ToolUseFineTuningDataGenerationJobOptions", "ToolboxObject", "ToolboxPolicies", - "ToolboxSearchPreviewTool", + "ToolboxSearchPreviewToolboxTool", "ToolboxSkill", "ToolboxSkillReference", + "ToolboxTool", "ToolboxVersionObject", "TracesDataGenerationJobOptions", "TracesDataGenerationJobSource", @@ -775,16 +818,18 @@ "WebSearchPreviewTool", "WebSearchTool", "WebSearchToolFilters", + "WebSearchToolboxTool", "WeeklyRecurrenceSchedule", "WorkIQPreviewTool", + "WorkIQPreviewToolboxTool", "WorkflowAgentDefinition", "AgentBlueprintReferenceType", "AgentEndpointAuthorizationSchemeType", "AgentEndpointProtocol", "AgentKind", "AgentObjectType", - "AgentProtocol", "AgentSessionStatus", + "AgentState", "AgentVersionStatus", "AttackStrategy", "AzureAISearchQueryType", @@ -825,7 +870,6 @@ "IndexType", "InputFidelity", "InsightType", - "IsolationKeySourceKind", "JobStatus", "MemoryItemKind", "MemoryOperationKind", @@ -834,6 +878,7 @@ "MemoryStoreUpdateStatus", "OpenApiAuthType", "OperationState", + "OptimizationDatasetInputType", "PageOrder", "PendingUploadType", "RankerVersionType", @@ -847,6 +892,7 @@ "SampleType", "ScheduleProvisioningStatus", "ScheduleTaskType", + "SearchContentType", "SearchContextSize", "SessionLogEventType", "SimpleQnAFineTuningQuestionType", @@ -856,7 +902,9 @@ "TelemetryTransportProtocol", "TextResponseFormatConfigurationType", "ToolChoiceParamType", + "ToolSearchExecutionType", "ToolType", + "ToolboxToolType", "TreatmentEffectType", "TriggerType", "VersionIndicatorType", diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/models/_enums.py b/sdk/ai/azure-ai-projects/azure/ai/projects/models/_enums.py index fb8d84b06bce..9584e5f77958 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/models/_enums.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/models/_enums.py @@ -14,16 +14,12 @@ class _AgentDefinitionOptInKeys(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Feature opt-in keys for agent definition operations supporting hosted or workflow agents.""" - HOSTED_AGENTS_V1_PREVIEW = "HostedAgents=V1Preview" - """HOSTED_AGENTS_V1_PREVIEW.""" WORKFLOW_AGENTS_V1_PREVIEW = "WorkflowAgents=V1Preview" """WORKFLOW_AGENTS_V1_PREVIEW.""" - AGENT_ENDPOINT_V1_PREVIEW = "AgentEndpoints=V1Preview" - """AGENT_ENDPOINT_V1_PREVIEW.""" - CODE_AGENTS_V1_PREVIEW = "CodeAgents=V1Preview" - """CODE_AGENTS_V1_PREVIEW.""" EXTERNAL_AGENTS_V1_PREVIEW = "ExternalAgents=V1Preview" """EXTERNAL_AGENTS_V1_PREVIEW.""" + DRAFT_AGENTS_V1_PREVIEW = "DraftAgents=V1Preview" + """DRAFT_AGENTS_V1_PREVIEW.""" class _FoundryFeaturesOptInKeys(str, Enum, metaclass=CaseInsensitiveEnumMeta): @@ -41,16 +37,14 @@ class _FoundryFeaturesOptInKeys(str, Enum, metaclass=CaseInsensitiveEnumMeta): """MEMORY_STORES_V1_PREVIEW.""" ROUTINES_V1_PREVIEW = "Routines=V1Preview" """ROUTINES_V1_PREVIEW.""" - TOOLBOXES_V1_PREVIEW = "Toolboxes=V1Preview" - """TOOLBOXES_V1_PREVIEW.""" SKILLS_V1_PREVIEW = "Skills=V1Preview" """SKILLS_V1_PREVIEW.""" DATA_GENERATION_JOBS_V1_PREVIEW = "DataGenerationJobs=V1Preview" """DATA_GENERATION_JOBS_V1_PREVIEW.""" MODELS_V1_PREVIEW = "Models=V1Preview" """MODELS_V1_PREVIEW.""" - AGENTS_OPTIMIZATION_V1_PREVIEW = "AgentsOptimization=V1Preview" - """AGENTS_OPTIMIZATION_V1_PREVIEW.""" + AGENTS_OPTIMIZATION_V2_PREVIEW = "AgentsOptimization=V2Preview" + """AGENTS_OPTIMIZATION_V2_PREVIEW.""" class AgentBlueprintReferenceType(str, Enum, metaclass=CaseInsensitiveEnumMeta): @@ -69,6 +63,8 @@ class AgentEndpointAuthorizationSchemeType(str, Enum, metaclass=CaseInsensitiveE """BOT_SERVICE.""" BOT_SERVICE_RBAC = "BotServiceRbac" """BOT_SERVICE_RBAC.""" + BOT_SERVICE_TENANT = "BotServiceTenant" + """BOT_SERVICE_TENANT.""" class AgentEndpointProtocol(str, Enum, metaclass=CaseInsensitiveEnumMeta): @@ -116,21 +112,6 @@ class AgentObjectType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """AGENT_CONTAINER.""" -class AgentProtocol(str, Enum, metaclass=CaseInsensitiveEnumMeta): - """Type of AgentProtocol.""" - - ACTIVITY_PROTOCOL = "activity_protocol" - """ACTIVITY_PROTOCOL.""" - RESPONSES = "responses" - """RESPONSES.""" - MCP = "mcp" - """MCP.""" - INVOCATIONS = "invocations" - """INVOCATIONS.""" - INVOCATIONS_WS = "invocations_ws" - """WebSocket-based protocol for hosted voice and real-time streaming agents.""" - - class AgentSessionStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The status of an agent session.""" @@ -152,6 +133,15 @@ class AgentSessionStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Session TTL exceeded (30 days from last activity).""" +class AgentState(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """The operational state of an agent.""" + + ENABLED = "enabled" + """Agent endpoint accepts requests. This is the default state on creation.""" + DISABLED = "disabled" + """Agent endpoint rejects all requests.""" + + class AgentVersionStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The provisioning status of an agent version.""" @@ -502,6 +492,9 @@ class EvaluatorDefinitionType(str, Enum, metaclass=CaseInsensitiveEnumMeta): RUBRIC = "rubric" """Rubric-based evaluator definition. Stores dimensions (the scoring blueprint) for both quality and safety evaluators. Can be created via the generate API or manually via createVersion.""" + ENDPOINT = "endpoint" + """Endpoint-based evaluator definition. References a customer-owned HTTP endpoint via a Project + Connection.""" class EvaluatorGenerationJobSourceType(str, Enum, metaclass=CaseInsensitiveEnumMeta): @@ -680,15 +673,6 @@ class InsightType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Evaluation Comparison.""" -class IsolationKeySourceKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): - """Type of IsolationKeySourceKind.""" - - ENTRA = "Entra" - """ENTRA.""" - HEADER = "Header" - """HEADER.""" - - class JobStatus(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Extensible status values shared by Foundry jobs.""" @@ -792,6 +776,15 @@ class OperationState(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The operation has been canceled by the user.""" +class OptimizationDatasetInputType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """Discriminator values for the dataset input union.""" + + INLINE = "inline" + """Inline dataset — items are provided directly in the request body.""" + REFERENCE = "reference" + """Reference to a registered Foundry dataset by name and version.""" + + class PageOrder(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Type of PageOrder.""" @@ -950,6 +943,15 @@ class ScheduleTaskType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Insight task.""" +class SearchContentType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """Type of SearchContentType.""" + + TEXT = "text" + """TEXT.""" + IMAGE = "image" + """IMAGE.""" + + class SearchContextSize(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Type of SearchContextSize.""" @@ -1024,6 +1026,35 @@ class TextResponseFormatConfigurationType(str, Enum, metaclass=CaseInsensitiveEn """JSON_OBJECT.""" +class ToolboxToolType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """Supported tool types for tools stored in a toolbox.""" + + CODE_INTERPRETER = "code_interpreter" + """CODE_INTERPRETER.""" + FILE_SEARCH = "file_search" + """FILE_SEARCH.""" + WEB_SEARCH = "web_search" + """WEB_SEARCH.""" + MCP = "mcp" + """MCP.""" + AZURE_AI_SEARCH = "azure_ai_search" + """AZURE_AI_SEARCH.""" + OPENAPI = "openapi" + """OPENAPI.""" + A2A_PREVIEW = "a2a_preview" + """A2A_PREVIEW.""" + BROWSER_AUTOMATION_PREVIEW = "browser_automation_preview" + """BROWSER_AUTOMATION_PREVIEW.""" + REMINDER_PREVIEW = "reminder_preview" + """REMINDER_PREVIEW.""" + WORK_IQ_PREVIEW = "work_iq_preview" + """WORK_IQ_PREVIEW.""" + FABRIC_IQ_PREVIEW = "fabric_iq_preview" + """FABRIC_IQ_PREVIEW.""" + TOOLBOX_SEARCH_PREVIEW = "toolbox_search_preview" + """TOOLBOX_SEARCH_PREVIEW.""" + + class ToolChoiceParamType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Type of ToolChoiceParamType.""" @@ -1051,6 +1082,19 @@ class ToolChoiceParamType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """IMAGE_GENERATION.""" CODE_INTERPRETER = "code_interpreter" """CODE_INTERPRETER.""" + COMPUTER = "computer" + """COMPUTER.""" + COMPUTER_USE = "computer_use" + """COMPUTER_USE.""" + + +class ToolSearchExecutionType(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """Type of ToolSearchExecutionType.""" + + SERVER = "server" + """SERVER.""" + CLIENT = "client" + """CLIENT.""" class ToolType(str, Enum, metaclass=CaseInsensitiveEnumMeta): @@ -1060,6 +1104,8 @@ class ToolType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """FUNCTION.""" FILE_SEARCH = "file_search" """FILE_SEARCH.""" + COMPUTER = "computer" + """COMPUTER.""" COMPUTER_USE_PREVIEW = "computer_use_preview" """COMPUTER_USE_PREVIEW.""" WEB_SEARCH = "web_search" @@ -1076,6 +1122,10 @@ class ToolType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """SHELL.""" CUSTOM = "custom" """CUSTOM.""" + NAMESPACE = "namespace" + """NAMESPACE.""" + TOOL_SEARCH = "tool_search" + """TOOL_SEARCH.""" WEB_SEARCH_PREVIEW = "web_search_preview" """WEB_SEARCH_PREVIEW.""" APPLY_PATCH = "apply_patch" @@ -1092,6 +1142,8 @@ class ToolType(str, Enum, metaclass=CaseInsensitiveEnumMeta): """SHAREPOINT_GROUNDING_PREVIEW.""" MEMORY_SEARCH_PREVIEW = "memory_search_preview" """MEMORY_SEARCH_PREVIEW.""" + REMINDER_PREVIEW = "reminder_preview" + """REMINDER_PREVIEW.""" WORK_IQ_PREVIEW = "work_iq_preview" """WORK_IQ_PREVIEW.""" FABRIC_IQ_PREVIEW = "fabric_iq_preview" diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/models/_models.py b/sdk/ai/azure-ai-projects/azure/ai/projects/models/_models.py index 308e0e1be187..824a8cad73b9 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/models/_models.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/models/_models.py @@ -34,11 +34,11 @@ FunctionShellToolParamEnvironmentType, IndexType, InsightType, - IsolationKeySourceKind, MemoryItemKind, MemoryStoreKind, MemoryStoreObjectType, OpenApiAuthType, + OptimizationDatasetInputType, PendingUploadType, RecurrenceType, RoutineActionType, @@ -51,6 +51,7 @@ TextResponseFormatConfigurationType, ToolChoiceParamType, ToolType, + ToolboxToolType, TriggerType, VersionIndicatorType, VersionSelectorType, @@ -66,17 +67,18 @@ class Tool(_Model): You probably want to use the sub-classes and not this class directly. Known sub-classes are: A2APreviewTool, ApplyPatchToolParam, AzureAISearchTool, AzureFunctionTool, BingCustomSearchPreviewTool, BingGroundingTool, BrowserAutomationPreviewTool, - CaptureStructuredOutputsTool, CodeInterpreterTool, ComputerUsePreviewTool, CustomToolParam, - MicrosoftFabricPreviewTool, FabricIQPreviewTool, FileSearchTool, FunctionTool, ImageGenTool, - LocalShellToolParam, MCPTool, MemorySearchPreviewTool, OpenApiTool, SharepointPreviewTool, - FunctionShellToolParam, ToolboxSearchPreviewTool, WebSearchTool, WebSearchPreviewTool, - WorkIQPreviewTool - - :ivar type: Required. Known values are: "function", "file_search", "computer_use_preview", - "web_search", "mcp", "code_interpreter", "image_generation", "local_shell", "shell", "custom", - "web_search_preview", "apply_patch", "a2a_preview", "bing_custom_search_preview", - "browser_automation_preview", "fabric_dataagent_preview", "sharepoint_grounding_preview", - "memory_search_preview", "work_iq_preview", "fabric_iq_preview", "toolbox_search_preview", + CaptureStructuredOutputsTool, CodeInterpreterTool, ComputerTool, ComputerUsePreviewTool, + CustomToolParam, MicrosoftFabricPreviewTool, FabricIQPreviewTool, FileSearchTool, FunctionTool, + ImageGenTool, LocalShellToolParam, MCPTool, MemorySearchPreviewTool, NamespaceToolParam, + OpenApiTool, ReminderPreviewTool, SharepointPreviewTool, FunctionShellToolParam, + ToolSearchToolParam, WebSearchTool, WebSearchPreviewTool, WorkIQPreviewTool + + :ivar type: Required. Known values are: "function", "file_search", "computer", + "computer_use_preview", "web_search", "mcp", "code_interpreter", "image_generation", + "local_shell", "shell", "custom", "namespace", "tool_search", "web_search_preview", + "apply_patch", "a2a_preview", "bing_custom_search_preview", "browser_automation_preview", + "fabric_dataagent_preview", "sharepoint_grounding_preview", "memory_search_preview", + "reminder_preview", "work_iq_preview", "fabric_iq_preview", "toolbox_search_preview", "azure_ai_search", "azure_function", "bing_grounding", "capture_structured_outputs", and "openapi". :vartype type: str or ~azure.ai.projects.models.ToolType @@ -84,13 +86,14 @@ class Tool(_Model): __mapping__: dict[str, _Model] = {} type: str = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) - """Required. Known values are: \"function\", \"file_search\", \"computer_use_preview\", - \"web_search\", \"mcp\", \"code_interpreter\", \"image_generation\", \"local_shell\", - \"shell\", \"custom\", \"web_search_preview\", \"apply_patch\", \"a2a_preview\", - \"bing_custom_search_preview\", \"browser_automation_preview\", \"fabric_dataagent_preview\", - \"sharepoint_grounding_preview\", \"memory_search_preview\", \"work_iq_preview\", - \"fabric_iq_preview\", \"toolbox_search_preview\", \"azure_ai_search\", \"azure_function\", - \"bing_grounding\", \"capture_structured_outputs\", and \"openapi\".""" + """Required. Known values are: \"function\", \"file_search\", \"computer\", + \"computer_use_preview\", \"web_search\", \"mcp\", \"code_interpreter\", \"image_generation\", + \"local_shell\", \"shell\", \"custom\", \"namespace\", \"tool_search\", \"web_search_preview\", + \"apply_patch\", \"a2a_preview\", \"bing_custom_search_preview\", + \"browser_automation_preview\", \"fabric_dataagent_preview\", \"sharepoint_grounding_preview\", + \"memory_search_preview\", \"reminder_preview\", \"work_iq_preview\", \"fabric_iq_preview\", + \"toolbox_search_preview\", \"azure_ai_search\", \"azure_function\", \"bing_grounding\", + \"capture_structured_outputs\", and \"openapi\".""" @overload def __init__( @@ -115,14 +118,6 @@ class A2APreviewTool(Tool, discriminator="a2a_preview"): :ivar type: The type of the tool. Always ``"a2a_preview``. Required. A2A_PREVIEW. :vartype type: str or ~azure.ai.projects.models.A2A_PREVIEW - :ivar name: Optional user-defined name for this tool or configuration. - :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. - :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. - :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar base_url: Base URL of the agent. :vartype base_url: str :ivar agent_card_path: The path to the agent card relative to the ``base_url``. If not @@ -132,10 +127,79 @@ class A2APreviewTool(Tool, discriminator="a2a_preview"): connection stores authentication and other connection details needed to connect to the A2A server. :vartype project_connection_id: str + :ivar send_credentials_for_agent_card: When ``true``, Foundry sends its credentials when + fetching the remote agent's Agent Card. The service defaults to ``false`` if a value is not + specified by the caller (anonymous fetch). + :vartype send_credentials_for_agent_card: bool """ type: Literal[ToolType.A2A_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The type of the tool. Always ``\"a2a_preview``. Required. A2A_PREVIEW.""" + base_url: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Base URL of the agent.""" + agent_card_path: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The path to the agent card relative to the ``base_url``. If not provided, defaults to + ``/.well-known/agent-card.json``.""" + project_connection_id: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The connection ID in the project for the A2A server. The connection stores authentication and + other connection details needed to connect to the A2A server.""" + send_credentials_for_agent_card: Optional[bool] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """When ``true``, Foundry sends its credentials when fetching the remote agent's Agent Card. The + service defaults to ``false`` if a value is not specified by the caller (anonymous fetch).""" + + @overload + def __init__( + self, + *, + base_url: Optional[str] = None, + agent_card_path: Optional[str] = None, + project_connection_id: Optional[str] = None, + send_credentials_for_agent_card: Optional[bool] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolType.A2A_PREVIEW # type: ignore + + +class ToolboxTool(_Model): + """An abstract representation of a tool stored in a toolbox. + + You probably want to use the sub-classes and not this class directly. Known sub-classes are: + A2APreviewToolboxTool, AzureAISearchToolboxTool, BrowserAutomationPreviewToolboxTool, + CodeInterpreterToolboxTool, FabricIQPreviewToolboxTool, FileSearchToolboxTool, MCPToolboxTool, + OpenApiToolboxTool, ReminderPreviewToolboxTool, ToolboxSearchPreviewToolboxTool, + WebSearchToolboxTool, WorkIQPreviewToolboxTool + + :ivar type: The type of tool. Required. Known values are: "code_interpreter", "file_search", + "web_search", "mcp", "azure_ai_search", "openapi", "a2a_preview", "browser_automation_preview", + "reminder_preview", "work_iq_preview", "fabric_iq_preview", and "toolbox_search_preview". + :vartype type: str or ~azure.ai.projects.models.ToolboxToolType + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all + default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names + are silently ignored at runtime. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + """ + + __mapping__: dict[str, _Model] = {} + type: str = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) + """The type of tool. Required. Known values are: \"code_interpreter\", \"file_search\", + \"web_search\", \"mcp\", \"azure_ai_search\", \"openapi\", \"a2a_preview\", + \"browser_automation_preview\", \"reminder_preview\", \"work_iq_preview\", + \"fabric_iq_preview\", and \"toolbox_search_preview\".""" name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Optional user-defined name for this tool or configuration.""" description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) @@ -146,6 +210,58 @@ class A2APreviewTool(Tool, discriminator="a2a_preview"): """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at runtime.""" + + @overload + def __init__( + self, + *, + type: str, + name: Optional[str] = None, + description: Optional[str] = None, + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class A2APreviewToolboxTool(ToolboxTool, discriminator="a2a_preview"): + """An A2A tool stored in a toolbox. + + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all + default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names + are silently ignored at runtime. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. A2A_PREVIEW. + :vartype type: str or ~azure.ai.projects.models.A2A_PREVIEW + :ivar base_url: Base URL of the agent. + :vartype base_url: str + :ivar agent_card_path: The path to the agent card relative to the ``base_url``. If not + provided, defaults to ``/.well-known/agent-card.json``. + :vartype agent_card_path: str + :ivar project_connection_id: The connection ID in the project for the A2A server. The + connection stores authentication and other connection details needed to connect to the A2A + server. + :vartype project_connection_id: str + :ivar send_credentials_for_agent_card: When ``true``, Foundry sends its credentials when + fetching the remote agent's Agent Card. The service defaults to ``false`` if a value is not + specified by the caller (anonymous fetch). + :vartype send_credentials_for_agent_card: bool + """ + + type: Literal[ToolboxToolType.A2A_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. A2A_PREVIEW.""" base_url: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Base URL of the agent.""" agent_card_path: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) @@ -154,6 +270,11 @@ class A2APreviewTool(Tool, discriminator="a2a_preview"): project_connection_id: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The connection ID in the project for the A2A server. The connection stores authentication and other connection details needed to connect to the A2A server.""" + send_credentials_for_agent_card: Optional[bool] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """When ``true``, Foundry sends its credentials when fetching the remote agent's Agent Card. The + service defaults to ``false`` if a value is not specified by the caller (anonymous fetch).""" @overload def __init__( @@ -165,6 +286,41 @@ def __init__( base_url: Optional[str] = None, agent_card_path: Optional[str] = None, project_connection_id: Optional[str] = None, + send_credentials_for_agent_card: Optional[bool] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolboxToolType.A2A_PREVIEW # type: ignore + + +class A2AProtocolConfiguration(_Model): + """Configuration specific to the A2A protocol.""" + + +class ActivityProtocolConfiguration(_Model): + """Configuration specific to the activity protocol. + + :ivar enable_m365_public_endpoint: Whether to enable the M365 public endpoint for the activity + protocol. + :vartype enable_m365_public_endpoint: bool + """ + + enable_m365_public_endpoint: Optional[bool] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Whether to enable the M365 public endpoint for the activity protocol.""" + + @overload + def __init__( + self, + *, + enable_m365_public_endpoint: Optional[bool] = None, ) -> None: ... @overload @@ -176,7 +332,6 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.type = ToolType.A2A_PREVIEW # type: ignore class AgentBlueprintReference(_Model): @@ -575,6 +730,9 @@ class AgentDetails(_Model): :vartype id: str :ivar name: The name of the agent. Required. :vartype name: str + :ivar state: The operational state of the agent. Controls whether the agent endpoint accepts or + rejects requests. Required. Known values are: "enabled" and "disabled". + :vartype state: str or ~azure.ai.projects.models.AgentState :ivar versions: The latest version of the agent. Required. :vartype versions: ~azure.ai.projects.models.AgentObjectVersions :ivar agent_endpoint: The endpoint configuration for the agent. @@ -595,6 +753,9 @@ class AgentDetails(_Model): """The unique identifier of the agent. Required.""" name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The name of the agent. Required.""" + state: Union[str, "_models.AgentState"] = rest_field(visibility=["read"]) + """The operational state of the agent. Controls whether the agent endpoint accepts or rejects + requests. Required. Known values are: \"enabled\" and \"disabled\".""" versions: "_models.AgentObjectVersions" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The latest version of the agent. Required.""" agent_endpoint: Optional["_models.AgentEndpointConfig"] = rest_field( @@ -636,15 +797,18 @@ class AgentEndpointAuthorizationScheme(_Model): """AgentEndpointAuthorizationScheme. You probably want to use the sub-classes and not this class directly. Known sub-classes are: - BotServiceAuthorizationScheme, BotServiceRbacAuthorizationScheme, EntraAuthorizationScheme + BotServiceAuthorizationScheme, BotServiceRbacAuthorizationScheme, + BotServiceTenantAuthorizationScheme, EntraAuthorizationScheme - :ivar type: Required. Known values are: "Entra", "BotService", and "BotServiceRbac". + :ivar type: Required. Known values are: "Entra", "BotService", "BotServiceRbac", and + "BotServiceTenant". :vartype type: str or ~azure.ai.projects.models.AgentEndpointAuthorizationSchemeType """ __mapping__: dict[str, _Model] = {} type: str = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) - """Required. Known values are: \"Entra\", \"BotService\", and \"BotServiceRbac\".""" + """Required. Known values are: \"Entra\", \"BotService\", \"BotServiceRbac\", and + \"BotServiceTenant\".""" @overload def __init__( @@ -670,8 +834,8 @@ class AgentEndpointConfig(_Model): :ivar version_selector: The version selector of the agent endpoint determines how traffic is routed to different versions of the agent. :vartype version_selector: ~azure.ai.projects.models.VersionSelector - :ivar protocols: The protocols that the agent supports. - :vartype protocols: list[str or ~azure.ai.projects.models.AgentEndpointProtocol] + :ivar protocol_configuration: Per-protocol configuration for the agent endpoint. + :vartype protocol_configuration: ~azure.ai.projects.models.ProtocolConfiguration :ivar authorization_schemes: The authorization schemes supported by the agent endpoint. :vartype authorization_schemes: list[~azure.ai.projects.models.AgentEndpointAuthorizationScheme] @@ -682,10 +846,10 @@ class AgentEndpointConfig(_Model): ) """The version selector of the agent endpoint determines how traffic is routed to different versions of the agent.""" - protocols: Optional[list[Union[str, "_models.AgentEndpointProtocol"]]] = rest_field( + protocol_configuration: Optional["_models.ProtocolConfiguration"] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """The protocols that the agent supports.""" + """Per-protocol configuration for the agent endpoint.""" authorization_schemes: Optional[list["_models.AgentEndpointAuthorizationScheme"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -696,7 +860,7 @@ def __init__( self, *, version_selector: Optional["_models.VersionSelector"] = None, - protocols: Optional[list[Union[str, "_models.AgentEndpointProtocol"]]] = None, + protocol_configuration: Optional["_models.ProtocolConfiguration"] = None, authorization_schemes: Optional[list["_models.AgentEndpointAuthorizationScheme"]] = None, ) -> None: ... @@ -857,40 +1021,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = CredentialType.AGENTIC_IDENTITY_PREVIEW # type: ignore -class AgentIdentifier(_Model): - """Identifies the registered Foundry agent to optimize (request-only). Skills, tools, and - system_prompt are specified in options.optimization_config. - - :ivar agent_name: Registered Foundry agent name (required). Required. - :vartype agent_name: str - :ivar agent_version: Pinned agent version. Defaults to latest if omitted. - :vartype agent_version: str - """ - - agent_name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Registered Foundry agent name (required). Required.""" - agent_version: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Pinned agent version. Defaults to latest if omitted.""" - - @overload - def __init__( - self, - *, - agent_name: str, - agent_version: Optional[str] = None, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - - class AgentIdentity(_Model): """AgentIdentity. @@ -1013,51 +1143,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class AgentsPagedResultOptimizationCandidate(_Model): - """The response data for a requested list of items. - - :ivar data: The requested list of items. Required. - :vartype data: list[~azure.ai.projects.models.OptimizationCandidate] - :ivar first_id: The first ID represented in this list. - :vartype first_id: str - :ivar last_id: The last ID represented in this list. - :vartype last_id: str - :ivar has_more: A value indicating whether there are additional values available not captured - in this list. Required. - :vartype has_more: bool - """ - - data: list["_models.OptimizationCandidate"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """The requested list of items. Required.""" - first_id: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """The first ID represented in this list.""" - last_id: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """The last ID represented in this list.""" - has_more: bool = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """A value indicating whether there are additional values available not captured in this list. - Required.""" - - @overload - def __init__( - self, - *, - data: list["_models.OptimizationCandidate"], - has_more: bool, - first_id: Optional[str] = None, - last_id: Optional[str] = None, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - - class EvaluationTaxonomyInput(_Model): """Input configuration for the evaluation taxonomy. @@ -1157,6 +1242,10 @@ class AgentVersionDetails(_Model): :vartype created_at: ~datetime.datetime :ivar definition: Required. :vartype definition: ~azure.ai.projects.models.AgentDefinition + :ivar draft: Whether this agent version is a draft (candidate) rather than a release. Draft + versions are recorded but excluded from default 'latest' resolution and are not auto-promoted. + Defaults to false. + :vartype draft: bool :ivar status: The provisioning status of the agent version. Defaults to 'active' for non-hosted agents. For hosted agents, reflects infrastructure readiness. Known values are: "creating", "active", "failed", "deleting", and "deleted". @@ -1197,6 +1286,10 @@ class AgentVersionDetails(_Model): """The Unix timestamp (seconds) when the agent was created. Required.""" definition: "_models.AgentDefinition" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Required.""" + draft: Optional[bool] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Whether this agent version is a draft (candidate) rather than a release. Draft versions are + recorded but excluded from default 'latest' resolution and are not auto-promoted. Defaults to + false.""" status: Optional[Union[str, "_models.AgentVersionStatus"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -1224,6 +1317,7 @@ def __init__( created_at: datetime.datetime, definition: "_models.AgentDefinition", description: Optional[str] = None, + draft: Optional[bool] = None, status: Optional[Union[str, "_models.AgentVersionStatus"]] = None, ) -> None: ... @@ -1812,13 +1906,13 @@ class AzureAISearchTool(Tool, discriminator="azure_ai_search"): :ivar type: The object type, which is always 'azure_ai_search'. Required. AZURE_AI_SEARCH. :vartype type: str or ~azure.ai.projects.models.AZURE_AI_SEARCH - :ivar name: Optional user-defined name for this tool or configuration. + :ivar name: Deprecated. This property is deprecated and will be removed in a future version. :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. + :ivar description: Deprecated. This property is deprecated and will be removed in a future + version. :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar azure_ai_search: The azure ai search index resource. Required. :vartype azure_ai_search: ~azure.ai.projects.models.AzureAISearchToolResource @@ -1827,15 +1921,13 @@ class AzureAISearchTool(Tool, discriminator="azure_ai_search"): type: Literal[ToolType.AZURE_AI_SEARCH] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The object type, which is always 'azure_ai_search'. Required. AZURE_AI_SEARCH.""" name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" azure_ai_search: "_models.AzureAISearchToolResource" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -1863,6 +1955,52 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = ToolType.AZURE_AI_SEARCH # type: ignore +class AzureAISearchToolboxTool(ToolboxTool, discriminator="azure_ai_search"): + """An Azure AI Search tool stored in a toolbox. + + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all + default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names + are silently ignored at runtime. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. AZURE_AI_SEARCH. + :vartype type: str or ~azure.ai.projects.models.AZURE_AI_SEARCH + :ivar azure_ai_search: The azure ai search index resource. Required. + :vartype azure_ai_search: ~azure.ai.projects.models.AzureAISearchToolResource + """ + + type: Literal[ToolboxToolType.AZURE_AI_SEARCH] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. AZURE_AI_SEARCH.""" + azure_ai_search: "_models.AzureAISearchToolResource" = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """The azure ai search index resource. Required.""" + + @overload + def __init__( + self, + *, + azure_ai_search: "_models.AzureAISearchToolResource", + name: Optional[str] = None, + description: Optional[str] = None, + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolboxToolType.AZURE_AI_SEARCH # type: ignore + + class AzureAISearchToolResource(_Model): """A set of index resources used by the ``azure_ai_search`` tool. @@ -2060,26 +2198,23 @@ class AzureFunctionTool(Tool, discriminator="azure_function"): :ivar type: The object type, which is always 'browser_automation'. Required. AZURE_FUNCTION. :vartype type: str or ~azure.ai.projects.models.AZURE_FUNCTION + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar azure_function: The Azure Function Tool definition. Required. :vartype azure_function: ~azure.ai.projects.models.AzureFunctionDefinition - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. - :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] """ type: Literal[ToolType.AZURE_FUNCTION] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The object type, which is always 'browser_automation'. Required. AZURE_FUNCTION.""" - azure_function: "_models.AzureFunctionDefinition" = rest_field( + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """The Azure Function Tool definition. Required.""" - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( + """Deprecated. This property is deprecated and will be removed in a future version.""" + azure_function: "_models.AzureFunctionDefinition" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """The Azure Function Tool definition. Required.""" @overload def __init__( @@ -2233,14 +2368,6 @@ class BingCustomSearchPreviewTool(Tool, discriminator="bing_custom_search_previe :ivar type: The object type, which is always 'bing_custom_search_preview'. Required. BING_CUSTOM_SEARCH_PREVIEW. :vartype type: str or ~azure.ai.projects.models.BING_CUSTOM_SEARCH_PREVIEW - :ivar name: Optional user-defined name for this tool or configuration. - :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. - :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. - :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar bing_custom_search_preview: The bing custom search tool parameters. Required. :vartype bing_custom_search_preview: ~azure.ai.projects.models.BingCustomSearchToolParameters """ @@ -2248,16 +2375,6 @@ class BingCustomSearchPreviewTool(Tool, discriminator="bing_custom_search_previe type: Literal[ToolType.BING_CUSTOM_SEARCH_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The object type, which is always 'bing_custom_search_preview'. Required. BING_CUSTOM_SEARCH_PREVIEW.""" - name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" - description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" bing_custom_search_preview: "_models.BingCustomSearchToolParameters" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -2268,9 +2385,6 @@ def __init__( self, *, bing_custom_search_preview: "_models.BingCustomSearchToolParameters", - name: Optional[str] = None, - description: Optional[str] = None, - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, ) -> None: ... @overload @@ -2406,13 +2520,13 @@ class BingGroundingTool(Tool, discriminator="bing_grounding"): :ivar type: The object type, which is always 'bing_grounding'. Required. BING_GROUNDING. :vartype type: str or ~azure.ai.projects.models.BING_GROUNDING - :ivar name: Optional user-defined name for this tool or configuration. + :ivar name: Deprecated. This property is deprecated and will be removed in a future version. :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. + :ivar description: Deprecated. This property is deprecated and will be removed in a future + version. :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar bing_grounding: The bing grounding search tool parameters. Required. :vartype bing_grounding: ~azure.ai.projects.models.BingGroundingSearchToolParameters @@ -2421,15 +2535,13 @@ class BingGroundingTool(Tool, discriminator="bing_grounding"): type: Literal[ToolType.BING_GROUNDING] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The object type, which is always 'bing_grounding'. Required. BING_GROUNDING.""" name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" bing_grounding: "_models.BingGroundingSearchToolParameters" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -2574,80 +2686,19 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = AgentEndpointAuthorizationSchemeType.BOT_SERVICE_RBAC # type: ignore -class BrowserAutomationPreviewTool(Tool, discriminator="browser_automation_preview"): - """The input definition information for a Browser Automation Tool, as used to configure an Agent. - - :ivar type: The object type, which is always 'browser_automation_preview'. Required. - BROWSER_AUTOMATION_PREVIEW. - :vartype type: str or ~azure.ai.projects.models.BROWSER_AUTOMATION_PREVIEW - :ivar name: Optional user-defined name for this tool or configuration. - :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. - :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. - :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] - :ivar browser_automation_preview: The Browser Automation Tool parameters. Required. - :vartype browser_automation_preview: ~azure.ai.projects.models.BrowserAutomationToolParameters - """ - - type: Literal[ToolType.BROWSER_AUTOMATION_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore - """The object type, which is always 'browser_automation_preview'. Required. - BROWSER_AUTOMATION_PREVIEW.""" - name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" - description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" - browser_automation_preview: "_models.BrowserAutomationToolParameters" = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """The Browser Automation Tool parameters. Required.""" - - @overload - def __init__( - self, - *, - browser_automation_preview: "_models.BrowserAutomationToolParameters", - name: Optional[str] = None, - description: Optional[str] = None, - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ +class BotServiceTenantAuthorizationScheme(AgentEndpointAuthorizationScheme, discriminator="BotServiceTenant"): + """BotServiceTenantAuthorizationScheme. - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - self.type = ToolType.BROWSER_AUTOMATION_PREVIEW # type: ignore - - -class BrowserAutomationToolConnectionParameters(_Model): # pylint: disable=name-too-long - """Definition of input parameters for the connection used by the Browser Automation Tool. - - :ivar project_connection_id: The ID of the project connection to your Azure Playwright - resource. Required. - :vartype project_connection_id: str + :ivar type: Required. BOT_SERVICE_TENANT. + :vartype type: str or ~azure.ai.projects.models.BOT_SERVICE_TENANT """ - project_connection_id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """The ID of the project connection to your Azure Playwright resource. Required.""" + type: Literal[AgentEndpointAuthorizationSchemeType.BOT_SERVICE_TENANT] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. BOT_SERVICE_TENANT.""" @overload def __init__( self, - *, - project_connection_id: str, ) -> None: ... @overload @@ -2659,26 +2710,32 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) + self.type = AgentEndpointAuthorizationSchemeType.BOT_SERVICE_TENANT # type: ignore -class BrowserAutomationToolParameters(_Model): - """Definition of input parameters for the Browser Automation Tool. +class BrowserAutomationPreviewTool(Tool, discriminator="browser_automation_preview"): + """The input definition information for a Browser Automation Tool, as used to configure an Agent. - :ivar connection: The project connection parameters associated with the Browser Automation - Tool. Required. - :vartype connection: ~azure.ai.projects.models.BrowserAutomationToolConnectionParameters + :ivar type: The object type, which is always 'browser_automation_preview'. Required. + BROWSER_AUTOMATION_PREVIEW. + :vartype type: str or ~azure.ai.projects.models.BROWSER_AUTOMATION_PREVIEW + :ivar browser_automation_preview: The Browser Automation Tool parameters. Required. + :vartype browser_automation_preview: ~azure.ai.projects.models.BrowserAutomationToolParameters """ - connection: "_models.BrowserAutomationToolConnectionParameters" = rest_field( + type: Literal[ToolType.BROWSER_AUTOMATION_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """The object type, which is always 'browser_automation_preview'. Required. + BROWSER_AUTOMATION_PREVIEW.""" + browser_automation_preview: "_models.BrowserAutomationToolParameters" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """The project connection parameters associated with the Browser Automation Tool. Required.""" + """The Browser Automation Tool parameters. Required.""" @overload def __init__( self, *, - connection: "_models.BrowserAutomationToolConnectionParameters", + browser_automation_preview: "_models.BrowserAutomationToolParameters", ) -> None: ... @overload @@ -2690,44 +2747,41 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) + self.type = ToolType.BROWSER_AUTOMATION_PREVIEW # type: ignore -class CandidateDeployConfig(_Model): - """Deploy-config blob for a candidate. Suitable for setting OPTIMIZATION_CONFIG on a hosted-agent - version. +class BrowserAutomationPreviewToolboxTool(ToolboxTool, discriminator="browser_automation_preview"): + """A browser automation tool stored in a toolbox. - :ivar instructions: System prompt / instructions. - :vartype instructions: str - :ivar model: Foundry deployment name. - :vartype model: str - :ivar temperature: Optional sampling temperature. - :vartype temperature: float - :ivar skills: Optional skill overrides. - :vartype skills: list[dict[str, any]] - :ivar tools: Optional tool overrides. - :vartype tools: list[dict[str, any]] + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all + default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names + are silently ignored at runtime. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. BROWSER_AUTOMATION_PREVIEW. + :vartype type: str or ~azure.ai.projects.models.BROWSER_AUTOMATION_PREVIEW + :ivar browser_automation_preview: The Browser Automation Tool parameters. Required. + :vartype browser_automation_preview: ~azure.ai.projects.models.BrowserAutomationToolParameters """ - instructions: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """System prompt / instructions.""" - model: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Foundry deployment name.""" - temperature: Optional[float] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional sampling temperature.""" - skills: Optional[list[dict[str, Any]]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional skill overrides.""" - tools: Optional[list[dict[str, Any]]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional tool overrides.""" + type: Literal[ToolboxToolType.BROWSER_AUTOMATION_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. BROWSER_AUTOMATION_PREVIEW.""" + browser_automation_preview: "_models.BrowserAutomationToolParameters" = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """The Browser Automation Tool parameters. Required.""" @overload def __init__( self, *, - instructions: Optional[str] = None, - model: Optional[str] = None, - temperature: Optional[float] = None, - skills: Optional[list[dict[str, Any]]] = None, - tools: Optional[list[dict[str, Any]]] = None, + browser_automation_preview: "_models.BrowserAutomationToolParameters", + name: Optional[str] = None, + description: Optional[str] = None, + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, ) -> None: ... @overload @@ -2739,113 +2793,25 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) + self.type = ToolboxToolType.BROWSER_AUTOMATION_PREVIEW # type: ignore -class CandidateFileInfo(_Model): - """File entry in a candidate's blob directory. +class BrowserAutomationToolConnectionParameters(_Model): # pylint: disable=name-too-long + """Definition of input parameters for the connection used by the Browser Automation Tool. - :ivar path: Relative path of the file. Required. - :vartype path: str - :ivar type: File type category (e.g. 'config', 'results'). Required. - :vartype type: str - :ivar size_bytes: File size in bytes. Required. - :vartype size_bytes: int + :ivar project_connection_id: The ID of the project connection to your Azure Playwright + resource. Required. + :vartype project_connection_id: str """ - path: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Relative path of the file. Required.""" - type: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """File type category (e.g. 'config', 'results'). Required.""" - size_bytes: int = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """File size in bytes. Required.""" - - @overload - def __init__( - self, - *, - path: str, - type: str, - size_bytes: int, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - - -class CandidateMetadata(_Model): - """Candidate metadata returned by GET /candidates/{id}. - - :ivar candidate_id: Server-assigned candidate identifier. Required. - :vartype candidate_id: str - :ivar job_id: Owning optimization job id. Required. - :vartype job_id: str - :ivar candidate_name: Display name of the candidate. Required. - :vartype candidate_name: str - :ivar status: Candidate lifecycle status. Required. - :vartype status: str - :ivar score: Candidate's aggregate score. - :vartype score: float - :ivar has_results: Whether detailed results are available for this candidate. Required. - :vartype has_results: bool - :ivar created_at: Timestamp when the candidate was created, represented in Unix time. Required. - :vartype created_at: ~datetime.datetime - :ivar updated_at: Timestamp when the candidate was last updated, represented in Unix time. - Required. - :vartype updated_at: ~datetime.datetime - :ivar promotion: Promotion metadata. Null if not promoted. - :vartype promotion: ~azure.ai.projects.models.PromotionInfo - :ivar files: Files in the candidate's blob directory. Required. - :vartype files: list[~azure.ai.projects.models.CandidateFileInfo] - """ - - candidate_id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Server-assigned candidate identifier. Required.""" - job_id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Owning optimization job id. Required.""" - candidate_name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Display name of the candidate. Required.""" - status: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Candidate lifecycle status. Required.""" - score: Optional[float] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Candidate's aggregate score.""" - has_results: bool = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Whether detailed results are available for this candidate. Required.""" - created_at: datetime.datetime = rest_field( - visibility=["read", "create", "update", "delete", "query"], format="unix-timestamp" - ) - """Timestamp when the candidate was created, represented in Unix time. Required.""" - updated_at: datetime.datetime = rest_field( - visibility=["read", "create", "update", "delete", "query"], format="unix-timestamp" - ) - """Timestamp when the candidate was last updated, represented in Unix time. Required.""" - promotion: Optional["_models.PromotionInfo"] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Promotion metadata. Null if not promoted.""" - files: list["_models.CandidateFileInfo"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Files in the candidate's blob directory. Required.""" + project_connection_id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The ID of the project connection to your Azure Playwright resource. Required.""" @overload def __init__( self, *, - candidate_id: str, - job_id: str, - candidate_name: str, - status: str, - has_results: bool, - created_at: datetime.datetime, - updated_at: datetime.datetime, - files: list["_models.CandidateFileInfo"], - score: Optional[float] = None, - promotion: Optional["_models.PromotionInfo"] = None, + project_connection_id: str, ) -> None: ... @overload @@ -2859,28 +2825,24 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class CandidateResults(_Model): - """Full per-task evaluation results for a candidate, returned by GET /candidates/{id}/results. +class BrowserAutomationToolParameters(_Model): + """Definition of input parameters for the Browser Automation Tool. - :ivar candidate_id: Owning candidate id. Required. - :vartype candidate_id: str - :ivar results: Per-task evaluation rows. Required. - :vartype results: list[~azure.ai.projects.models.OptimizationTaskResult] + :ivar connection: The project connection parameters associated with the Browser Automation + Tool. Required. + :vartype connection: ~azure.ai.projects.models.BrowserAutomationToolConnectionParameters """ - candidate_id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Owning candidate id. Required.""" - results: list["_models.OptimizationTaskResult"] = rest_field( + connection: "_models.BrowserAutomationToolConnectionParameters" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-task evaluation rows. Required.""" + """The project connection parameters associated with the Browser Automation Tool. Required.""" @overload def __init__( self, *, - candidate_id: str, - results: list["_models.OptimizationTaskResult"], + connection: "_models.BrowserAutomationToolConnectionParameters", ) -> None: ... @overload @@ -2900,13 +2862,13 @@ class CaptureStructuredOutputsTool(Tool, discriminator="capture_structured_outpu :ivar type: The type of the tool. Always ``capture_structured_outputs``. Required. CAPTURE_STRUCTURED_OUTPUTS. :vartype type: str or ~azure.ai.projects.models.CAPTURE_STRUCTURED_OUTPUTS - :ivar name: Optional user-defined name for this tool or configuration. + :ivar name: Deprecated. This property is deprecated and will be removed in a future version. :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. + :ivar description: Deprecated. This property is deprecated and will be removed in a future + version. :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar outputs: The structured outputs to capture from the model. Required. :vartype outputs: ~azure.ai.projects.models.StructuredOutputDefinition @@ -2916,15 +2878,13 @@ class CaptureStructuredOutputsTool(Tool, discriminator="capture_structured_outpu """The type of the tool. Always ``capture_structured_outputs``. Required. CAPTURE_STRUCTURED_OUTPUTS.""" name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" outputs: "_models.StructuredOutputDefinition" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -3213,10 +3173,11 @@ class EvaluatorDefinition(_Model): """Base evaluator configuration with discriminator. You probably want to use the sub-classes and not this class directly. Known sub-classes are: - CodeBasedEvaluatorDefinition, PromptBasedEvaluatorDefinition, RubricBasedEvaluatorDefinition + CodeBasedEvaluatorDefinition, EndpointBasedEvaluatorDefinition, PromptBasedEvaluatorDefinition, + RubricBasedEvaluatorDefinition :ivar type: The type of evaluator definition. Required. Known values are: "prompt", "code", - "prompt_and_code", "service", "openai_graders", and "rubric". + "prompt_and_code", "service", "openai_graders", "rubric", and "endpoint". :vartype type: str or ~azure.ai.projects.models.EvaluatorDefinitionType :ivar init_parameters: The JSON schema (Draft 2020-12) for the evaluator's input parameters. This includes parameters like type, properties, required. @@ -3231,7 +3192,7 @@ class EvaluatorDefinition(_Model): __mapping__: dict[str, _Model] = {} type: str = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) """The type of evaluator definition. Required. Known values are: \"prompt\", \"code\", - \"prompt_and_code\", \"service\", \"openai_graders\", and \"rubric\".""" + \"prompt_and_code\", \"service\", \"openai_graders\", \"rubric\", and \"endpoint\".""" init_parameters: Optional[dict[str, Any]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The JSON schema (Draft 2020-12) for the evaluator's input parameters. This includes parameters like type, properties, required.""" @@ -3388,13 +3349,13 @@ class CodeInterpreterTool(Tool, discriminator="code_interpreter"): :ivar type: The type of the code interpreter tool. Always ``code_interpreter``. Required. CODE_INTERPRETER. :vartype type: str or ~azure.ai.projects.models.CODE_INTERPRETER - :ivar name: Optional user-defined name for this tool or configuration. + :ivar name: Deprecated. This property is deprecated and will be removed in a future version. :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. + :ivar description: Deprecated. This property is deprecated and will be removed in a future + version. :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar container: The code interpreter container. Can be a container ID or an object that specifies uploaded file IDs to make available to your code, along with an optional @@ -3406,15 +3367,13 @@ class CodeInterpreterTool(Tool, discriminator="code_interpreter"): type: Literal[ToolType.CODE_INTERPRETER] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The type of the code interpreter tool. Always ``code_interpreter``. Required. CODE_INTERPRETER.""" name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" container: Optional[Union[str, "_models.AutoCodeInterpreterToolParam"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -3445,6 +3404,58 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = ToolType.CODE_INTERPRETER # type: ignore +class CodeInterpreterToolboxTool(ToolboxTool, discriminator="code_interpreter"): + """A code interpreter tool stored in a toolbox. + + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all + default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names + are silently ignored at runtime. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. CODE_INTERPRETER. + :vartype type: str or ~azure.ai.projects.models.CODE_INTERPRETER + :ivar container: The code interpreter container. Can be a container ID or an object that + specifies uploaded file IDs to make available to your code, along with an optional + ``memory_limit`` setting. If not provided, the service assumes auto. Is either a str type or a + AutoCodeInterpreterToolParam type. + :vartype container: str or ~azure.ai.projects.models.AutoCodeInterpreterToolParam + """ + + type: Literal[ToolboxToolType.CODE_INTERPRETER] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. CODE_INTERPRETER.""" + container: Optional[Union[str, "_models.AutoCodeInterpreterToolParam"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """The code interpreter container. Can be a container ID or an object that specifies uploaded file + IDs to make available to your code, along with an optional ``memory_limit`` setting. If not + provided, the service assumes auto. Is either a str type or a AutoCodeInterpreterToolParam + type.""" + + @overload + def __init__( + self, + *, + name: Optional[str] = None, + description: Optional[str] = None, + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, + container: Optional[Union[str, "_models.AutoCodeInterpreterToolParam"]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolboxToolType.CODE_INTERPRETER # type: ignore + + class ComparisonFilter(_Model): """Comparison Filter. @@ -3459,8 +3470,8 @@ class ComparisonFilter(_Model): * `lte`: less than or equal * `in`: in * `nin`: not in. Required. Is one of the following types: Literal["eq"], Literal["ne"], - Literal["gt"], Literal["gte"], Literal["lt"], Literal["lte"] - :vartype type: str or str or str or str or str or str + Literal["gt"], Literal["gte"], Literal["lt"], Literal["lte"], Literal["in"], Literal["nin"] + :vartype type: str or str or str or str or str or str or str or str :ivar key: The key to compare against the value. Required. :vartype key: str :ivar value: The value to compare against the attribute key; supports string, number, or @@ -3468,7 +3479,7 @@ class ComparisonFilter(_Model): :vartype value: str or float or bool or list[str or float] """ - type: Literal["eq", "ne", "gt", "gte", "lt", "lte"] = rest_field( + type: Literal["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) """Specifies the comparison operator: ``eq``, ``ne``, ``gt``, ``gte``, ``lt``, ``lte``, ``in``, @@ -3482,7 +3493,8 @@ class ComparisonFilter(_Model): * `lte`: less than or equal * `in`: in * `nin`: not in. Required. Is one of the following types: Literal[\"eq\"], - Literal[\"ne\"], Literal[\"gt\"], Literal[\"gte\"], Literal[\"lt\"], Literal[\"lte\"]""" + Literal[\"ne\"], Literal[\"gt\"], Literal[\"gte\"], Literal[\"lt\"], Literal[\"lte\"], + Literal[\"in\"], Literal[\"nin\"]""" key: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The key to compare against the value. Required.""" value: Union[str, float, bool, list[Union[str, float]]] = rest_field( @@ -3495,7 +3507,7 @@ class ComparisonFilter(_Model): def __init__( self, *, - type: Literal["eq", "ne", "gt", "gte", "lt", "lte"], + type: Literal["eq", "ne", "gt", "gte", "lt", "lte", "in", "nin"], key: str, value: Union[str, float, bool, list[Union[str, float]]], ) -> None: ... @@ -3549,6 +3561,33 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) +class ComputerTool(Tool, discriminator="computer"): + """Computer. + + :ivar type: The type of the computer tool. Always ``computer``. Required. COMPUTER. + :vartype type: str or ~azure.ai.projects.models.COMPUTER + """ + + type: Literal[ToolType.COMPUTER] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """The type of the computer tool. Always ``computer``. Required. COMPUTER.""" + + @overload + def __init__( + self, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolType.COMPUTER # type: ignore + + class ComputerUsePreviewTool(Tool, discriminator="computer_use_preview"): """Computer use preview. @@ -3803,7 +3842,7 @@ class ContainerNetworkPolicyAllowlistParam(ContainerNetworkPolicyParam, discrimi allowed_domains: list[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """A list of allowed domains when type is ``allowlist``. Required.""" domain_secrets: Optional[list["_models.ContainerNetworkPolicyDomainSecretParam"]] = rest_field( - visibility=["read", "create", "update", "delete", "query"] + visibility=["create"] ) """Optional domain-scoped secrets for allowlisted domains.""" @@ -3967,6 +4006,10 @@ class ContinuousEvaluationRuleAction(EvaluationRuleAction, discriminator="contin :vartype eval_id: str :ivar max_hourly_runs: Maximum number of evaluation runs allowed per hour. :vartype max_hourly_runs: int + :ivar sampling_rate: Percentage (0-100] chance that a matching event triggers an evaluation. + When omitted, the service-default is to evaluate every event, which is equivalent to setting a + sampling rate of 100. + :vartype sampling_rate: float """ type: Literal[EvaluationRuleActionType.CONTINUOUS_EVALUATION] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore @@ -3977,6 +4020,12 @@ class ContinuousEvaluationRuleAction(EvaluationRuleAction, discriminator="contin name="maxHourlyRuns", visibility=["read", "create", "update", "delete", "query"] ) """Maximum number of evaluation runs allowed per hour.""" + sampling_rate: Optional[float] = rest_field( + name="samplingRate", visibility=["read", "create", "update", "delete", "query"] + ) + """Percentage (0-100] chance that a matching event triggers an evaluation. When omitted, the + service-default is to evaluate every event, which is equivalent to setting a sampling rate of + 100.""" @overload def __init__( @@ -3984,6 +4033,7 @@ def __init__( *, eval_id: str, max_hourly_runs: Optional[int] = None, + sampling_rate: Optional[float] = None, ) -> None: ... @overload @@ -4532,6 +4582,8 @@ class CustomToolParam(Tool, discriminator="custom"): :vartype description: str :ivar format: The input format for the custom tool. Default is unconstrained text. :vartype format: ~azure.ai.projects.models.CustomToolParamFormat + :ivar defer_loading: Whether this tool should be deferred and discovered via tool search. + :vartype defer_loading: bool """ type: Literal[ToolType.CUSTOM] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore @@ -4544,6 +4596,8 @@ class CustomToolParam(Tool, discriminator="custom"): visibility=["read", "create", "update", "delete", "query"] ) """The input format for the custom tool. Default is unconstrained text.""" + defer_loading: Optional[bool] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Whether this tool should be deferred and discovered via tool search.""" @overload def __init__( @@ -4552,6 +4606,7 @@ def __init__( name: str, description: Optional[str] = None, format: Optional["_models.CustomToolParamFormat"] = None, + defer_loading: Optional[bool] = None, ) -> None: ... @overload @@ -5099,83 +5154,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = EvaluatorGenerationJobSourceType.DATASET # type: ignore -class DatasetInfo(_Model): - """Metadata about the dataset used for optimization, surfaced in the response. - - :ivar name: Dataset name when using a registered dataset reference. Null for inline datasets. - :vartype name: str - :ivar version: Dataset version when using a registered dataset reference. Null for inline - datasets. - :vartype version: str - :ivar task_count: Number of tasks/rows in the dataset. Required. - :vartype task_count: int - :ivar is_inline: True when the dataset was provided inline in the request body. Required. - :vartype is_inline: bool - """ - - name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Dataset name when using a registered dataset reference. Null for inline datasets.""" - version: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Dataset version when using a registered dataset reference. Null for inline datasets.""" - task_count: int = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Number of tasks/rows in the dataset. Required.""" - is_inline: bool = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """True when the dataset was provided inline in the request body. Required.""" - - @overload - def __init__( - self, - *, - task_count: int, - is_inline: bool, - name: Optional[str] = None, - version: Optional[str] = None, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - - -class DatasetRef(_Model): - """Reference to a registered dataset in the Foundry Dataset Service. - - :ivar name: Dataset name. Required. - :vartype name: str - :ivar version: Dataset version. If not specified, the latest version is used. - :vartype version: str - """ - - name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Dataset name. Required.""" - version: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Dataset version. If not specified, the latest version is used.""" - - @overload - def __init__( - self, - *, - name: str, - version: Optional[str] = None, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - - class DatasetReference(_Model): """Reference to a versioned Foundry Dataset. @@ -5669,59 +5647,23 @@ class EmbeddingConfiguration(_Model): :ivar model_deployment_name: Deployment name of embedding model. It can point to a model deployment either in the parent AIServices or a connection. Required. - :vartype model_deployment_name: str - :ivar embedding_field: Embedding field. Required. - :vartype embedding_field: str - """ - - model_deployment_name: str = rest_field(name="modelDeploymentName", visibility=["create"]) - """Deployment name of embedding model. It can point to a model deployment either in the parent - AIServices or a connection. Required.""" - embedding_field: str = rest_field(name="embeddingField", visibility=["create"]) - """Embedding field. Required.""" - - @overload - def __init__( - self, - *, - model_deployment_name: str, - embedding_field: str, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - - -class EntraAuthorizationScheme(AgentEndpointAuthorizationScheme, discriminator="Entra"): - """EntraAuthorizationScheme. - - :ivar type: Required. ENTRA. - :vartype type: str or ~azure.ai.projects.models.ENTRA - :ivar isolation_key_source: The source from which the per-user isolation key is derived for - requests authorized via this scheme. Defaults to Entra-based isolation when omitted. - :vartype isolation_key_source: ~azure.ai.projects.models.IsolationKeySource + :vartype model_deployment_name: str + :ivar embedding_field: Embedding field. Required. + :vartype embedding_field: str """ - type: Literal[AgentEndpointAuthorizationSchemeType.ENTRA] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore - """Required. ENTRA.""" - isolation_key_source: Optional["_models.IsolationKeySource"] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """The source from which the per-user isolation key is derived for requests authorized via this - scheme. Defaults to Entra-based isolation when omitted.""" + model_deployment_name: str = rest_field(name="modelDeploymentName", visibility=["create"]) + """Deployment name of embedding model. It can point to a model deployment either in the parent + AIServices or a connection. Required.""" + embedding_field: str = rest_field(name="embeddingField", visibility=["create"]) + """Embedding field. Required.""" @overload def __init__( self, *, - isolation_key_source: Optional["_models.IsolationKeySource"] = None, + model_deployment_name: str, + embedding_field: str, ) -> None: ... @overload @@ -5733,22 +5675,54 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.type = AgentEndpointAuthorizationSchemeType.ENTRA # type: ignore -class EntraIDCredentials(BaseCredentials, discriminator="AAD"): - """Entra ID credential definition. +class EmptyModelParam(_Model): + """EmptyModelParam.""" - :ivar type: The credential type. Required. Entra ID credential (formerly known as AAD). - :vartype type: str or ~azure.ai.projects.models.ENTRA_ID + +class EndpointBasedEvaluatorDefinition(EvaluatorDefinition, discriminator="endpoint"): + """Endpoint-based evaluator definition. The customer owns and hosts an HTTP endpoint that + implements the evaluation contract. The evaluator references a Project Connection by name; the + connection stores the endpoint URL and credentials (API Key or Entra ID). At execution time, + the service resolves the connection to obtain the endpoint URL and authentication details, then + calls the endpoint for each evaluation row. + + :ivar init_parameters: The JSON schema (Draft 2020-12) for the evaluator's input parameters. + This includes parameters like type, properties, required. + :vartype init_parameters: dict[str, any] + :ivar data_schema: The JSON schema (Draft 2020-12) for the evaluator's input data. This + includes parameters like type, properties, required. + :vartype data_schema: dict[str, any] + :ivar metrics: List of output metrics produced by this evaluator. + :vartype metrics: dict[str, ~azure.ai.projects.models.EvaluatorMetric] + :ivar type: Required. Endpoint-based evaluator definition. References a customer-owned HTTP + endpoint via a Project Connection. + :vartype type: str or ~azure.ai.projects.models.ENDPOINT + :ivar connection_name: Name of the Project Connection that stores the endpoint URL and + credentials. The connection must exist on the project and have a non-empty target URL. + Supported auth types: ApiKey (sends ``api-key`` header) and AAD/Entra ID (acquires a bearer + token via the project's Managed Identity). Required. + :vartype connection_name: str """ - type: Literal[CredentialType.ENTRA_ID] = rest_discriminator(name="type", visibility=["read"]) # type: ignore - """The credential type. Required. Entra ID credential (formerly known as AAD).""" + type: Literal[EvaluatorDefinitionType.ENDPOINT] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. Endpoint-based evaluator definition. References a customer-owned HTTP endpoint via a + Project Connection.""" + connection_name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Name of the Project Connection that stores the endpoint URL and credentials. The connection + must exist on the project and have a non-empty target URL. Supported auth types: ApiKey (sends + ``api-key`` header) and AAD/Entra ID (acquires a bearer token via the project's Managed + Identity). Required.""" @overload def __init__( self, + *, + connection_name: str, + init_parameters: Optional[dict[str, Any]] = None, + data_schema: Optional[dict[str, Any]] = None, + metrics: Optional[dict[str, "_models.EvaluatorMetric"]] = None, ) -> None: ... @overload @@ -5760,28 +5734,22 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.type = CredentialType.ENTRA_ID # type: ignore + self.type = EvaluatorDefinitionType.ENDPOINT # type: ignore -class IsolationKeySource(_Model): - """IsolationKeySource. - - You probably want to use the sub-classes and not this class directly. Known sub-classes are: - EntraIsolationKeySource, HeaderIsolationKeySource +class EntraAuthorizationScheme(AgentEndpointAuthorizationScheme, discriminator="Entra"): + """EntraAuthorizationScheme. - :ivar kind: Required. Known values are: "Entra" and "Header". - :vartype kind: str or ~azure.ai.projects.models.IsolationKeySourceKind + :ivar type: Required. ENTRA. + :vartype type: str or ~azure.ai.projects.models.ENTRA """ - __mapping__: dict[str, _Model] = {} - kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) - """Required. Known values are: \"Entra\" and \"Header\".""" + type: Literal[AgentEndpointAuthorizationSchemeType.ENTRA] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. ENTRA.""" @overload def __init__( self, - *, - kind: str, ) -> None: ... @overload @@ -5793,17 +5761,18 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) + self.type = AgentEndpointAuthorizationSchemeType.ENTRA # type: ignore -class EntraIsolationKeySource(IsolationKeySource, discriminator="Entra"): - """EntraIsolationKeySource. +class EntraIDCredentials(BaseCredentials, discriminator="AAD"): + """Entra ID credential definition. - :ivar kind: Required. ENTRA. - :vartype kind: str or ~azure.ai.projects.models.ENTRA + :ivar type: The credential type. Required. Entra ID credential (formerly known as AAD). + :vartype type: str or ~azure.ai.projects.models.ENTRA_ID """ - kind: Literal[IsolationKeySourceKind.ENTRA] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore - """Required. ENTRA.""" + type: Literal[CredentialType.ENTRA_ID] = rest_discriminator(name="type", visibility=["read"]) # type: ignore + """The credential type. Required. Entra ID credential (formerly known as AAD).""" @overload def __init__( @@ -5819,7 +5788,7 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.kind = IsolationKeySourceKind.ENTRA # type: ignore + self.type = CredentialType.ENTRA_ID # type: ignore class EvalResult(_Model): @@ -6422,14 +6391,14 @@ class EvaluationScheduleTask(ScheduleTask, discriminator="Evaluation"): :ivar eval_id: Identifier of the evaluation group. Required. :vartype eval_id: str :ivar eval_run: The evaluation run payload. Required. - :vartype eval_run: any + :vartype eval_run: dict[str, any] """ type: Literal[ScheduleTaskType.EVALUATION] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Required. Evaluation task.""" eval_id: str = rest_field(name="evalId", visibility=["read", "create", "update", "delete", "query"]) """Identifier of the evaluation group. Required.""" - eval_run: Any = rest_field(name="evalRun", visibility=["read", "create", "update", "delete", "query"]) + eval_run: dict[str, Any] = rest_field(name="evalRun", visibility=["read", "create", "update", "delete", "query"]) """The evaluation run payload. Required.""" @overload @@ -6437,7 +6406,7 @@ def __init__( self, *, eval_id: str, - eval_run: Any, + eval_run: dict[str, Any], configuration: Optional[dict[str, str]] = None, ) -> None: ... @@ -6854,6 +6823,12 @@ class EvaluatorVersion(_Model): :vartype evaluator_type: str or ~azure.ai.projects.models.EvaluatorType :ivar categories: The categories of the evaluator. Required. :vartype categories: list[str or ~azure.ai.projects.models.EvaluatorCategory] + :ivar supported_evaluation_levels: Evaluation levels this evaluator supports (e.g., ``turn``, + ``conversation``). When omitted on create, the service defaults to ``["turn"]``. On update, + omitting this field leaves it unchanged; an empty list is rejected. Custom code-based + evaluators support only ``turn``; custom prompt-based evaluators support exactly one level + (``turn`` or ``conversation``). + :vartype supported_evaluation_levels: list[str or ~azure.ai.projects.models.EvaluationLevel] :ivar definition: Definition of the evaluator. Required. :vartype definition: ~azure.ai.projects.models.EvaluatorDefinition :ivar generation_artifacts: Provenance artifacts from the generation pipeline. Read-only; @@ -6889,6 +6864,13 @@ class EvaluatorVersion(_Model): visibility=["read", "create", "update", "delete", "query"] ) """The categories of the evaluator. Required.""" + supported_evaluation_levels: Optional[list[Union[str, "_models.EvaluationLevel"]]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Evaluation levels this evaluator supports (e.g., ``turn``, ``conversation``). When omitted on + create, the service defaults to ``[\"turn\"]``. On update, omitting this field leaves it + unchanged; an empty list is rejected. Custom code-based evaluators support only ``turn``; + custom prompt-based evaluators support exactly one level (``turn`` or ``conversation``).""" definition: "_models.EvaluatorDefinition" = rest_field(visibility=["read", "create"]) """Definition of the evaluator. Required.""" generation_artifacts: Optional["_models.EvaluatorGenerationArtifacts"] = rest_field(visibility=["read"]) @@ -6921,6 +6903,7 @@ def __init__( definition: "_models.EvaluatorDefinition", display_name: Optional[str] = None, metadata: Optional[dict[str, str]] = None, + supported_evaluation_levels: Optional[list[Union[str, "_models.EvaluationLevel"]]] = None, description: Optional[str] = None, tags: Optional[dict[str, str]] = None, ) -> None: ... @@ -7031,6 +7014,48 @@ class FabricIQPreviewTool(Tool, discriminator="fabric_iq_preview"): :ivar require_approval: (Optional) Whether the agent requires approval before executing actions. Default is always. Is either a MCPToolRequireApproval type or a str type. :vartype require_approval: ~azure.ai.projects.models.MCPToolRequireApproval or str + """ + + type: Literal[ToolType.FABRIC_IQ_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """The object type, which is always 'fabric_iq_preview'. Required. FABRIC_IQ_PREVIEW.""" + project_connection_id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The ID of the FabricIQ project connection. Required.""" + server_label: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """(Optional) The label of the FabricIQ MCP server to connect to.""" + server_url: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """(Optional) The URL of the FabricIQ MCP server. If not provided, the URL from the project + connection will be used.""" + require_approval: Optional[Union["_models.MCPToolRequireApproval", str]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """(Optional) Whether the agent requires approval before executing actions. Default is always. Is + either a MCPToolRequireApproval type or a str type.""" + + @overload + def __init__( + self, + *, + project_connection_id: str, + server_label: Optional[str] = None, + server_url: Optional[str] = None, + require_approval: Optional[Union["_models.MCPToolRequireApproval", str]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolType.FABRIC_IQ_PREVIEW # type: ignore + + +class FabricIQPreviewToolboxTool(ToolboxTool, discriminator="fabric_iq_preview"): + """A FabricIQ tool stored in a toolbox. + :ivar name: Optional user-defined name for this tool or configuration. :vartype name: str :ivar description: Optional user-defined description for this tool or configuration. @@ -7039,10 +7064,22 @@ class FabricIQPreviewTool(Tool, discriminator="fabric_iq_preview"): default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at runtime. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. FABRIC_IQ_PREVIEW. + :vartype type: str or ~azure.ai.projects.models.FABRIC_IQ_PREVIEW + :ivar project_connection_id: The ID of the FabricIQ project connection. Required. + :vartype project_connection_id: str + :ivar server_label: (Optional) The label of the FabricIQ MCP server to connect to. + :vartype server_label: str + :ivar server_url: (Optional) The URL of the FabricIQ MCP server. If not provided, the URL from + the project connection will be used. + :vartype server_url: str + :ivar require_approval: (Optional) Whether the agent requires approval before executing + actions. Default is always. Is either a MCPToolRequireApproval type or a str type. + :vartype require_approval: ~azure.ai.projects.models.MCPToolRequireApproval or str """ - type: Literal[ToolType.FABRIC_IQ_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore - """The object type, which is always 'fabric_iq_preview'. Required. FABRIC_IQ_PREVIEW.""" + type: Literal[ToolboxToolType.FABRIC_IQ_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. FABRIC_IQ_PREVIEW.""" project_connection_id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The ID of the FabricIQ project connection. Required.""" server_label: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) @@ -7055,28 +7092,18 @@ class FabricIQPreviewTool(Tool, discriminator="fabric_iq_preview"): ) """(Optional) Whether the agent requires approval before executing actions. Default is always. Is either a MCPToolRequireApproval type or a str type.""" - name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" - description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" @overload def __init__( self, *, project_connection_id: str, - server_label: Optional[str] = None, - server_url: Optional[str] = None, - require_approval: Optional[Union["_models.MCPToolRequireApproval", str]] = None, name: Optional[str] = None, description: Optional[str] = None, tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, + server_label: Optional[str] = None, + server_url: Optional[str] = None, + require_approval: Optional[Union["_models.MCPToolRequireApproval", str]] = None, ) -> None: ... @overload @@ -7088,7 +7115,7 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.type = ToolType.FABRIC_IQ_PREVIEW # type: ignore + self.type = ToolboxToolType.FABRIC_IQ_PREVIEW # type: ignore class FieldMapping(_Model): @@ -7285,13 +7312,13 @@ class FileSearchTool(Tool, discriminator="file_search"): :ivar filters: Is either a ComparisonFilter type or a CompoundFilter type. :vartype filters: ~azure.ai.projects.models.ComparisonFilter or ~azure.ai.projects.models.CompoundFilter - :ivar name: Optional user-defined name for this tool or configuration. + :ivar name: Deprecated. This property is deprecated and will be removed in a future version. :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. + :ivar description: Deprecated. This property is deprecated and will be removed in a future + version. :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] """ @@ -7308,15 +7335,13 @@ class FileSearchTool(Tool, discriminator="file_search"): filters: Optional["_types.Filters"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Is either a ComparisonFilter type or a CompoundFilter type.""" name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" @overload def __init__( @@ -7343,6 +7368,69 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = ToolType.FILE_SEARCH # type: ignore +class FileSearchToolboxTool(ToolboxTool, discriminator="file_search"): + """A file search tool stored in a toolbox. + + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all + default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names + are silently ignored at runtime. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. FILE_SEARCH. + :vartype type: str or ~azure.ai.projects.models.FILE_SEARCH + :ivar max_num_results: The maximum number of results to return. This number should be between 1 + and 50 inclusive. + :vartype max_num_results: int + :ivar ranking_options: Ranking options for search. + :vartype ranking_options: ~azure.ai.projects.models.RankingOptions + :ivar filters: Is either a ComparisonFilter type or a CompoundFilter type. + :vartype filters: ~azure.ai.projects.models.ComparisonFilter or + ~azure.ai.projects.models.CompoundFilter + :ivar vector_store_ids: The IDs of the vector stores to search. + :vartype vector_store_ids: list[str] + """ + + type: Literal[ToolboxToolType.FILE_SEARCH] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. FILE_SEARCH.""" + max_num_results: Optional[int] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The maximum number of results to return. This number should be between 1 and 50 inclusive.""" + ranking_options: Optional["_models.RankingOptions"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Ranking options for search.""" + filters: Optional["_types.Filters"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Is either a ComparisonFilter type or a CompoundFilter type.""" + vector_store_ids: Optional[list[str]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The IDs of the vector stores to search.""" + + @overload + def __init__( + self, + *, + name: Optional[str] = None, + description: Optional[str] = None, + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, + max_num_results: Optional[int] = None, + ranking_options: Optional["_models.RankingOptions"] = None, + filters: Optional["_types.Filters"] = None, + vector_store_ids: Optional[list[str]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolboxToolType.FILE_SEARCH # type: ignore + + class VersionSelectionRule(_Model): """VersionSelectionRule. @@ -7512,13 +7600,13 @@ class FunctionShellToolParam(Tool, discriminator="shell"): :vartype type: str or ~azure.ai.projects.models.SHELL :ivar environment: :vartype environment: ~azure.ai.projects.models.FunctionShellToolParamEnvironment - :ivar name: Optional user-defined name for this tool or configuration. + :ivar name: Deprecated. This property is deprecated and will be removed in a future version. :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. + :ivar description: Deprecated. This property is deprecated and will be removed in a future + version. :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] """ @@ -7528,15 +7616,13 @@ class FunctionShellToolParam(Tool, discriminator="shell"): visibility=["read", "create", "update", "delete", "query"] ) name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" @overload def __init__( @@ -7630,42 +7716,99 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.type = FunctionShellToolParamEnvironmentType.LOCAL # type: ignore + self.type = FunctionShellToolParamEnvironmentType.LOCAL # type: ignore + + +class FunctionTool(Tool, discriminator="function"): + """Function. + + :ivar type: The type of the function tool. Always ``function``. Required. FUNCTION. + :vartype type: str or ~azure.ai.projects.models.FUNCTION + :ivar name: The name of the function to call. Required. + :vartype name: str + :ivar description: + :vartype description: str + :ivar parameters: Required. + :vartype parameters: dict[str, any] + :ivar strict: Required. + :vartype strict: bool + :ivar defer_loading: Whether this function is deferred and loaded via tool search. + :vartype defer_loading: bool + """ + + type: Literal[ToolType.FUNCTION] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """The type of the function tool. Always ``function``. Required. FUNCTION.""" + name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The name of the function to call. Required.""" + description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + parameters: dict[str, Any] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Required.""" + strict: bool = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Required.""" + defer_loading: Optional[bool] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Whether this function is deferred and loaded via tool search.""" + + @overload + def __init__( + self, + *, + name: str, + parameters: dict[str, Any], + strict: bool, + description: Optional[str] = None, + defer_loading: Optional[bool] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolType.FUNCTION # type: ignore -class FunctionTool(Tool, discriminator="function"): - """Function. +class FunctionToolParam(_Model): + """FunctionToolParam. - :ivar type: The type of the function tool. Always ``function``. Required. FUNCTION. - :vartype type: str or ~azure.ai.projects.models.FUNCTION - :ivar name: The name of the function to call. Required. + :ivar name: Required. :vartype name: str :ivar description: :vartype description: str - :ivar parameters: Required. - :vartype parameters: dict[str, any] - :ivar strict: Required. + :ivar parameters: + :vartype parameters: ~azure.ai.projects.models.EmptyModelParam + :ivar strict: :vartype strict: bool + :ivar type: Required. Default value is "function". + :vartype type: str + :ivar defer_loading: Whether this function should be deferred and discovered via tool search. + :vartype defer_loading: bool """ - type: Literal[ToolType.FUNCTION] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore - """The type of the function tool. Always ``function``. Required. FUNCTION.""" name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """The name of the function to call. Required.""" - description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - parameters: dict[str, Any] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Required.""" - strict: bool = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Required.""" + description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + parameters: Optional["_models.EmptyModelParam"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + strict: Optional[bool] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + type: Literal["function"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Required. Default value is \"function\".""" + defer_loading: Optional[bool] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Whether this function should be deferred and discovered via tool search.""" @overload def __init__( self, *, name: str, - parameters: dict[str, Any], - strict: bool, description: Optional[str] = None, + parameters: Optional["_models.EmptyModelParam"] = None, + strict: Optional[bool] = None, + defer_loading: Optional[bool] = None, ) -> None: ... @overload @@ -7677,7 +7820,7 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.type = ToolType.FUNCTION # type: ignore + self.type: Literal["function"] = "function" class GitHubIssueRoutineTrigger(RoutineTrigger, discriminator="github_issue"): @@ -7736,33 +7879,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = RoutineTriggerType.GITHUB_ISSUE # type: ignore -class HeaderIsolationKeySource(IsolationKeySource, discriminator="Header"): - """HeaderIsolationKeySource. - - :ivar kind: Required. HEADER. - :vartype kind: str or ~azure.ai.projects.models.HEADER - """ - - kind: Literal[IsolationKeySourceKind.HEADER] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore - """Required. HEADER.""" - - @overload - def __init__( - self, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - self.kind = IsolationKeySourceKind.HEADER # type: ignore - - class TelemetryEndpointAuth(_Model): """Authentication configuration for a telemetry endpoint. @@ -7848,9 +7964,6 @@ class HostedAgentDefinition(AgentDefinition, discriminator="hosted"): :vartype rai_config: ~azure.ai.projects.models.RaiConfig :ivar kind: Required. HOSTED. :vartype kind: str or ~azure.ai.projects.models.HOSTED - :ivar tools: An array of tools the hosted agent's model may call while generating a response. - You can specify which tool to use by setting the ``tool_choice`` parameter. - :vartype tools: list[~azure.ai.projects.models.Tool] :ivar cpu: The CPU configuration for the hosted agent. Required. :vartype cpu: str :ivar memory: The memory configuration for the hosted agent. Required. @@ -7874,9 +7987,6 @@ class HostedAgentDefinition(AgentDefinition, discriminator="hosted"): kind: Literal[AgentKind.HOSTED] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Required. HOSTED.""" - tools: Optional[list["_models.Tool"]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """An array of tools the hosted agent's model may call while generating a response. You can - specify which tool to use by setting the ``tool_choice`` parameter.""" cpu: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The CPU configuration for the hosted agent. Required.""" memory: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) @@ -7912,7 +8022,6 @@ def __init__( cpu: str, memory: str, rai_config: Optional["_models.RaiConfig"] = None, - tools: Optional[list["_models.Tool"]] = None, environment_variables: Optional[dict[str, str]] = None, container_configuration: Optional["_models.ContainerConfiguration"] = None, protocol_versions: Optional[list["_models.ProtocolVersionRecord"]] = None, @@ -8038,10 +8147,18 @@ class ImageGenTool(Tool, discriminator="image_generation"): ``auto``. Default: ``auto``. Is one of the following types: Literal["low"], Literal["medium"], Literal["high"], Literal["auto"] :vartype quality: str or str or str or str - :ivar size: The size of the generated image. One of ``1024x1024``, ``1024x1536``, - ``1536x1024``, or ``auto``. Default: ``auto``. Is one of the following types: - Literal["1024x1024"], Literal["1024x1536"], Literal["1536x1024"], Literal["auto"] - :vartype size: str or str or str or str + :ivar size: The size of the generated images. For ``gpt-image-2`` and + ``gpt-image-2-2026-04-21``, arbitrary resolutions are supported as ``WIDTHxHEIGHT`` strings, + for example ``1536x864``. Width and height must both be divisible by 16 and the requested + aspect ratio must be between 1:3 and 3:1. Resolutions above ``2560x1440`` are experimental, and + the maximum supported resolution is ``3840x2160``. The requested size must also satisfy the + model's current pixel and edge limits. The standard sizes ``1024x1024``, ``1536x1024``, and + ``1024x1536`` are supported by the GPT image models; ``auto`` is supported for models that + allow automatic sizing. For ``dall-e-2``, use one of ``256x256``, ``512x512``, or + ``1024x1024``. For ``dall-e-3``, use one of ``1024x1024``, ``1792x1024``, or ``1024x1792``. Is + one of the following types: Literal["1024x1024"], Literal["1024x1536"], Literal["1536x1024"], + Literal["auto"], str + :vartype size: str or str or str or str or str :ivar output_format: The output format of the generated image. One of ``png``, ``webp``, or ``jpeg``. Default: ``png``. Is one of the following types: Literal["png"], Literal["webp"], Literal["jpeg"] @@ -8066,13 +8183,13 @@ class ImageGenTool(Tool, discriminator="image_generation"): :ivar action: Whether to generate a new image or edit an existing image. Default: ``auto``. Known values are: "generate", "edit", and "auto". :vartype action: str or ~azure.ai.projects.models.ImageGenAction - :ivar name: Optional user-defined name for this tool or configuration. + :ivar name: Deprecated. This property is deprecated and will be removed in a future version. :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. + :ivar description: Deprecated. This property is deprecated and will be removed in a future + version. :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] """ @@ -8089,12 +8206,19 @@ class ImageGenTool(Tool, discriminator="image_generation"): """The quality of the generated image. One of ``low``, ``medium``, ``high``, or ``auto``. Default: ``auto``. Is one of the following types: Literal[\"low\"], Literal[\"medium\"], Literal[\"high\"], Literal[\"auto\"]""" - size: Optional[Literal["1024x1024", "1024x1536", "1536x1024", "auto"]] = rest_field( - visibility=["read", "create", "update", "delete", "query"] + size: Optional[Union[Literal["1024x1024"], Literal["1024x1536"], Literal["1536x1024"], Literal["auto"], str]] = ( + rest_field(visibility=["read", "create", "update", "delete", "query"]) ) - """The size of the generated image. One of ``1024x1024``, ``1024x1536``, ``1536x1024``, or - ``auto``. Default: ``auto``. Is one of the following types: Literal[\"1024x1024\"], - Literal[\"1024x1536\"], Literal[\"1536x1024\"], Literal[\"auto\"]""" + """The size of the generated images. For ``gpt-image-2`` and ``gpt-image-2-2026-04-21``, arbitrary + resolutions are supported as ``WIDTHxHEIGHT`` strings, for example ``1536x864``. Width and + height must both be divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1. + Resolutions above ``2560x1440`` are experimental, and the maximum supported resolution is + ``3840x2160``. The requested size must also satisfy the model's current pixel and edge limits. + The standard sizes ``1024x1024``, ``1536x1024``, and ``1024x1536`` are supported by the GPT + image models; ``auto`` is supported for models that allow automatic sizing. For ``dall-e-2``, + use one of ``256x256``, ``512x512``, or ``1024x1024``. For ``dall-e-3``, use one of + ``1024x1024``, ``1792x1024``, or ``1024x1792``. Is one of the following types: + Literal[\"1024x1024\"], Literal[\"1024x1536\"], Literal[\"1536x1024\"], Literal[\"auto\"], str""" output_format: Optional[Literal["png", "webp", "jpeg"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -8130,15 +8254,13 @@ class ImageGenTool(Tool, discriminator="image_generation"): """Whether to generate a new image or edit an existing image. Default: ``auto``. Known values are: \"generate\", \"edit\", and \"auto\".""" name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" @overload def __init__( @@ -8148,7 +8270,9 @@ def __init__( Union[Literal["gpt-image-1"], Literal["gpt-image-1-mini"], Literal["gpt-image-1.5"], str] ] = None, quality: Optional[Literal["low", "medium", "high", "auto"]] = None, - size: Optional[Literal["1024x1024", "1024x1536", "1536x1024", "auto"]] = None, + size: Optional[ + Union[Literal["1024x1024"], Literal["1024x1536"], Literal["1536x1024"], Literal["auto"], str] + ] = None, output_format: Optional[Literal["png", "webp", "jpeg"]] = None, output_compression: Optional[int] = None, moderation: Optional[Literal["auto", "low"]] = None, @@ -8569,6 +8693,14 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) +class InvocationsProtocolConfiguration(_Model): + """Configuration specific to the invocations protocol.""" + + +class InvocationsWsProtocolConfiguration(_Model): + """Configuration specific to the WebSocket-based invocations protocol.""" + + class RoutineDispatchPayload(_Model): """Base model for a manual dispatch payload. @@ -8821,28 +8953,26 @@ class LocalShellToolParam(Tool, discriminator="local_shell"): :ivar type: The type of the local shell tool. Always ``local_shell``. Required. LOCAL_SHELL. :vartype type: str or ~azure.ai.projects.models.LOCAL_SHELL - :ivar name: Optional user-defined name for this tool or configuration. + :ivar name: Deprecated. This property is deprecated and will be removed in a future version. :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. + :ivar description: Deprecated. This property is deprecated and will be removed in a future + version. :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] """ type: Literal[ToolType.LOCAL_SHELL] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The type of the local shell tool. Always ``local_shell``. Required. LOCAL_SHELL.""" name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" @overload def __init__( @@ -9029,6 +9159,10 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = IndexType.MANAGED_AZURE_SEARCH # type: ignore +class McpProtocolConfiguration(_Model): + """Configuration specific to the MCP protocol.""" + + class MCPTool(Tool, discriminator="mcp"): """MCP tool. @@ -9069,13 +9203,14 @@ class MCPTool(Tool, discriminator="mcp"): :ivar require_approval: Is one of the following types: MCPToolRequireApproval, Literal["always"], Literal["never"] :vartype require_approval: ~azure.ai.projects.models.MCPToolRequireApproval or str or str + :ivar defer_loading: Whether this MCP tool is deferred and discovered via tool search. + :vartype defer_loading: bool :ivar project_connection_id: The connection ID in the project for the MCP server. The connection stores authentication and other connection details needed to connect to the MCP server. :vartype project_connection_id: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] """ @@ -9128,15 +9263,15 @@ class MCPTool(Tool, discriminator="mcp"): rest_field(visibility=["read", "create", "update", "delete", "query"]) ) """Is one of the following types: MCPToolRequireApproval, Literal[\"always\"], Literal[\"never\"]""" + defer_loading: Optional[bool] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Whether this MCP tool is deferred and discovered via tool search.""" project_connection_id: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The connection ID in the project for the MCP server. The connection stores authentication and other connection details needed to connect to the MCP server.""" tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" @overload def __init__( @@ -9161,6 +9296,7 @@ def __init__( headers: Optional[dict[str, str]] = None, allowed_tools: Optional[Union[list[str], "_models.MCPToolFilter"]] = None, require_approval: Optional[Union["_models.MCPToolRequireApproval", Literal["always"], Literal["never"]]] = None, + defer_loading: Optional[bool] = None, project_connection_id: Optional[str] = None, tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, ) -> None: ... @@ -9177,6 +9313,159 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = ToolType.MCP # type: ignore +class MCPToolboxTool(ToolboxTool, discriminator="mcp"): + """An MCP tool stored in a toolbox. + + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all + default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names + are silently ignored at runtime. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. MCP. + :vartype type: str or ~azure.ai.projects.models.MCP + :ivar server_label: A label for this MCP server, used to identify it in tool calls. Required. + :vartype server_label: str + :ivar server_url: The URL for the MCP server. One of ``server_url`` or ``connector_id`` must be + provided. + :vartype server_url: str + :ivar connector_id: Identifier for service connectors, like those available in ChatGPT. One of + ``server_url`` or ``connector_id`` must be provided. Learn more about service connectors `here + `_. Currently supported ``connector_id`` values are: + + * Dropbox: `connector_dropbox` + * Gmail: `connector_gmail` + * Google Calendar: `connector_googlecalendar` + * Google Drive: `connector_googledrive` + * Microsoft Teams: `connector_microsoftteams` + * Outlook Calendar: `connector_outlookcalendar` + * Outlook Email: `connector_outlookemail` + * SharePoint: `connector_sharepoint`. Is one of the following types: + Literal["connector_dropbox"], Literal["connector_gmail"], Literal["connector_googlecalendar"], + Literal["connector_googledrive"], Literal["connector_microsoftteams"], + Literal["connector_outlookcalendar"], Literal["connector_outlookemail"], + Literal["connector_sharepoint"] + :vartype connector_id: str or str or str or str or str or str or str or str + :ivar authorization: An OAuth access token that can be used with a remote MCP server, either + with a custom MCP server URL or a service connector. Your application must handle the OAuth + authorization flow and provide the token here. + :vartype authorization: str + :ivar server_description: Optional description of the MCP server, used to provide more context. + :vartype server_description: str + :ivar headers: + :vartype headers: dict[str, str] + :ivar allowed_tools: Is either a [str] type or a MCPToolFilter type. + :vartype allowed_tools: list[str] or ~azure.ai.projects.models.MCPToolFilter + :ivar require_approval: Is one of the following types: MCPToolRequireApproval, + Literal["always"], Literal["never"] + :vartype require_approval: ~azure.ai.projects.models.MCPToolRequireApproval or str or str + :ivar defer_loading: Whether this MCP tool is deferred and discovered via tool search. + :vartype defer_loading: bool + :ivar project_connection_id: The connection ID in the project for the MCP server. The + connection stores authentication and other connection details needed to connect to the MCP + server. + :vartype project_connection_id: str + """ + + type: Literal[ToolboxToolType.MCP] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. MCP.""" + server_label: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """A label for this MCP server, used to identify it in tool calls. Required.""" + server_url: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The URL for the MCP server. One of ``server_url`` or ``connector_id`` must be provided.""" + connector_id: Optional[ + Literal[ + "connector_dropbox", + "connector_gmail", + "connector_googlecalendar", + "connector_googledrive", + "connector_microsoftteams", + "connector_outlookcalendar", + "connector_outlookemail", + "connector_sharepoint", + ] + ] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Identifier for service connectors, like those available in ChatGPT. One of ``server_url`` or + ``connector_id`` must be provided. Learn more about service connectors `here + `_. Currently supported ``connector_id`` values are: + + * Dropbox: `connector_dropbox` + * Gmail: `connector_gmail` + * Google Calendar: `connector_googlecalendar` + * Google Drive: `connector_googledrive` + * Microsoft Teams: `connector_microsoftteams` + * Outlook Calendar: `connector_outlookcalendar` + * Outlook Email: `connector_outlookemail` + * SharePoint: `connector_sharepoint`. Is one of the following types: + Literal[\"connector_dropbox\"], Literal[\"connector_gmail\"], + Literal[\"connector_googlecalendar\"], Literal[\"connector_googledrive\"], + Literal[\"connector_microsoftteams\"], Literal[\"connector_outlookcalendar\"], + Literal[\"connector_outlookemail\"], Literal[\"connector_sharepoint\"]""" + authorization: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """An OAuth access token that can be used with a remote MCP server, either with a custom MCP + server URL or a service connector. Your application must handle the OAuth authorization flow + and provide the token here.""" + server_description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Optional description of the MCP server, used to provide more context.""" + headers: Optional[dict[str, str]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + allowed_tools: Optional[Union[list[str], "_models.MCPToolFilter"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Is either a [str] type or a MCPToolFilter type.""" + require_approval: Optional[Union["_models.MCPToolRequireApproval", Literal["always"], Literal["never"]]] = ( + rest_field(visibility=["read", "create", "update", "delete", "query"]) + ) + """Is one of the following types: MCPToolRequireApproval, Literal[\"always\"], Literal[\"never\"]""" + defer_loading: Optional[bool] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Whether this MCP tool is deferred and discovered via tool search.""" + project_connection_id: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The connection ID in the project for the MCP server. The connection stores authentication and + other connection details needed to connect to the MCP server.""" + + @overload + def __init__( + self, + *, + server_label: str, + name: Optional[str] = None, + description: Optional[str] = None, + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, + server_url: Optional[str] = None, + connector_id: Optional[ + Literal[ + "connector_dropbox", + "connector_gmail", + "connector_googlecalendar", + "connector_googledrive", + "connector_microsoftteams", + "connector_outlookcalendar", + "connector_outlookemail", + "connector_sharepoint", + ] + ] = None, + authorization: Optional[str] = None, + server_description: Optional[str] = None, + headers: Optional[dict[str, str]] = None, + allowed_tools: Optional[Union[list[str], "_models.MCPToolFilter"]] = None, + require_approval: Optional[Union["_models.MCPToolRequireApproval", Literal["always"], Literal["never"]]] = None, + defer_loading: Optional[bool] = None, + project_connection_id: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolboxToolType.MCP # type: ignore + + class MCPToolFilter(_Model): """MCP tool filter. @@ -9346,14 +9635,6 @@ class MemorySearchPreviewTool(Tool, discriminator="memory_search_preview"): :ivar type: The type of the tool. Always ``memory_search_preview``. Required. MEMORY_SEARCH_PREVIEW. :vartype type: str or ~azure.ai.projects.models.MEMORY_SEARCH_PREVIEW - :ivar name: Optional user-defined name for this tool or configuration. - :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. - :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. - :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar memory_store_name: The name of the memory store to use. Required. :vartype memory_store_name: str :ivar scope: The namespace used to group and isolate memories, such as a user ID. Limits which @@ -9369,16 +9650,6 @@ class MemorySearchPreviewTool(Tool, discriminator="memory_search_preview"): type: Literal[ToolType.MEMORY_SEARCH_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The type of the tool. Always ``memory_search_preview``. Required. MEMORY_SEARCH_PREVIEW.""" - name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" - description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" memory_store_name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The name of the memory store to use. Required.""" scope: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) @@ -9396,11 +9667,8 @@ class MemorySearchPreviewTool(Tool, discriminator="memory_search_preview"): def __init__( self, *, - memory_store_name: str, - scope: str, - name: Optional[str] = None, - description: Optional[str] = None, - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, + memory_store_name: str, + scope: str, search_options: Optional["_models.MemorySearchOptions"] = None, update_delay: Optional[int] = None, ) -> None: ... @@ -9512,7 +9780,7 @@ class MemoryStoreDefaultOptions(_Model): :vartype procedural_memory_enabled: bool :ivar default_ttl_seconds: The default time-to-live for memories in seconds. A value of ``0`` indicates that memories do not expire. Defaults to ``0``. - :vartype default_ttl_seconds: int + :vartype default_ttl_seconds: ~datetime.timedelta """ user_profile_enabled: bool = rest_field(visibility=["read", "create", "update", "delete", "query"]) @@ -9524,7 +9792,9 @@ class MemoryStoreDefaultOptions(_Model): procedural_memory_enabled: Optional[bool] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Whether to enable procedural memory extraction and storage. The service defaults to ``true`` if a value is not specified by the caller.""" - default_ttl_seconds: Optional[int] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + default_ttl_seconds: Optional[datetime.timedelta] = rest_field( + visibility=["read", "create", "update", "delete", "query"], format="duration-seconds-int" + ) """The default time-to-live for memories in seconds. A value of ``0`` indicates that memories do not expire. Defaults to ``0``.""" @@ -9536,7 +9806,7 @@ def __init__( chat_summary_enabled: bool, user_profile_details: Optional[str] = None, procedural_memory_enabled: Optional[bool] = None, - default_ttl_seconds: Optional[int] = None, + default_ttl_seconds: Optional[datetime.timedelta] = None, ) -> None: ... @overload @@ -9863,14 +10133,6 @@ class MicrosoftFabricPreviewTool(Tool, discriminator="fabric_dataagent_preview") :ivar type: The object type, which is always 'fabric_dataagent_preview'. Required. FABRIC_DATAAGENT_PREVIEW. :vartype type: str or ~azure.ai.projects.models.FABRIC_DATAAGENT_PREVIEW - :ivar name: Optional user-defined name for this tool or configuration. - :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. - :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. - :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar fabric_dataagent_preview: The fabric data agent tool parameters. Required. :vartype fabric_dataagent_preview: ~azure.ai.projects.models.FabricDataAgentToolParameters """ @@ -9878,16 +10140,6 @@ class MicrosoftFabricPreviewTool(Tool, discriminator="fabric_dataagent_preview") type: Literal[ToolType.FABRIC_DATAAGENT_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The object type, which is always 'fabric_dataagent_preview'. Required. FABRIC_DATAAGENT_PREVIEW.""" - name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" - description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" fabric_dataagent_preview: "_models.FabricDataAgentToolParameters" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -9898,9 +10150,6 @@ def __init__( self, *, fabric_dataagent_preview: "_models.FabricDataAgentToolParameters", - name: Optional[str] = None, - description: Optional[str] = None, - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, ) -> None: ... @overload @@ -10226,8 +10475,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ModelVersion(_Model): """Model Version Definition. - :ivar system_data: System related metadata. - :vartype system_data: ~azure.ai.projects.models.SystemDataV3 :ivar blob_uri: URI of the model artifact in blob storage. Required. :vartype blob_uri: str :ivar weight_type: The weight type of the model. Known values are: "FullWeight", "LoRA", and @@ -10257,8 +10504,6 @@ class ModelVersion(_Model): :vartype tags: dict[str, str] """ - system_data: Optional["_models.SystemDataV3"] = rest_field(name="systemData", visibility=["read"]) - """System related metadata.""" blob_uri: str = rest_field(name="blobUri", visibility=["read", "create", "update", "delete", "query"]) """URI of the model artifact in blob storage. Required.""" weight_type: Optional[Union[str, "_models.FoundryModelWeightType"]] = rest_field( @@ -10347,6 +10592,52 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = RecurrenceType.MONTHLY # type: ignore +class NamespaceToolParam(Tool, discriminator="namespace"): + """Namespace. + + :ivar type: The type of the tool. Always ``namespace``. Required. NAMESPACE. + :vartype type: str or ~azure.ai.projects.models.NAMESPACE + :ivar name: The namespace name used in tool calls (for example, ``crm``). Required. + :vartype name: str + :ivar description: A description of the namespace shown to the model. Required. + :vartype description: str + :ivar tools: The function/custom tools available inside this namespace. Required. + :vartype tools: list[~azure.ai.projects.models.FunctionToolParam or + ~azure.ai.projects.models.CustomToolParam] + """ + + type: Literal[ToolType.NAMESPACE] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """The type of the tool. Always ``namespace``. Required. NAMESPACE.""" + name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The namespace name used in tool calls (for example, ``crm``). Required.""" + description: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """A description of the namespace shown to the model. Required.""" + tools: list[Union["_models.FunctionToolParam", "_models.CustomToolParam"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """The function/custom tools available inside this namespace. Required.""" + + @overload + def __init__( + self, + *, + name: str, + description: str, + tools: list[Union["_models.FunctionToolParam", "_models.CustomToolParam"]], + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolType.NAMESPACE # type: ignore + + class NoAuthenticationCredentials(BaseCredentials, discriminator="None"): """Credentials that do not require authentication. @@ -10702,32 +10993,75 @@ class OpenApiTool(Tool, discriminator="openapi"): :ivar type: The object type, which is always 'openapi'. Required. OPENAPI. :vartype type: str or ~azure.ai.projects.models.OPENAPI + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar openapi: The openapi function definition. Required. :vartype openapi: ~azure.ai.projects.models.OpenApiFunctionDefinition - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. - :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] """ type: Literal[ToolType.OPENAPI] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The object type, which is always 'openapi'. Required. OPENAPI.""" + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Deprecated. This property is deprecated and will be removed in a future version.""" openapi: "_models.OpenApiFunctionDefinition" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) """The openapi function definition. Required.""" - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( + + @overload + def __init__( + self, + *, + openapi: "_models.OpenApiFunctionDefinition", + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolType.OPENAPI # type: ignore + + +class OpenApiToolboxTool(ToolboxTool, discriminator="openapi"): + """An OpenAPI tool stored in a toolbox. + + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all + default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names + are silently ignored at runtime. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. OPENAPI. + :vartype type: str or ~azure.ai.projects.models.OPENAPI + :ivar openapi: The openapi function definition. Required. + :vartype openapi: ~azure.ai.projects.models.OpenApiFunctionDefinition + """ + + type: Literal[ToolboxToolType.OPENAPI] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. OPENAPI.""" + openapi: "_models.OpenApiFunctionDefinition" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """The openapi function definition. Required.""" @overload def __init__( self, *, openapi: "_models.OpenApiFunctionDefinition", + name: Optional[str] = None, + description: Optional[str] = None, tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, ) -> None: ... @@ -10740,49 +11074,30 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.type = ToolType.OPENAPI # type: ignore + self.type = ToolboxToolType.OPENAPI # type: ignore -class OptimizationAgentDefinition(_Model): - """Agent definition returned in response payloads (includes resolved config). +class OptimizationAgentIdentifier(_Model): + """Identifies the registered Foundry agent to optimize (request-only). Skills, tools, and + system_prompt are specified in options.optimization_config. - :ivar agent_name: Agent name. + :ivar agent_name: Registered Foundry agent name (required). Required. :vartype agent_name: str - :ivar agent_version: Agent version. + :ivar agent_version: Pinned agent version. Defaults to latest if omitted. :vartype agent_version: str - :ivar model: Model deployment name. - :vartype model: str - :ivar system_prompt: System prompt / instructions. - :vartype system_prompt: str - :ivar skills: Agent skills. - :vartype skills: list[dict[str, any]] - :ivar tools: Agent tools. - :vartype tools: list[dict[str, any]] """ - agent_name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Agent name.""" + agent_name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Registered Foundry agent name (required). Required.""" agent_version: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Agent version.""" - model: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Model deployment name.""" - system_prompt: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """System prompt / instructions.""" - skills: Optional[list[dict[str, Any]]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Agent skills.""" - tools: Optional[list[dict[str, Any]]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Agent tools.""" + """Pinned agent version. Defaults to latest if omitted.""" @overload def __init__( self, *, - agent_name: Optional[str] = None, + agent_name: str, agent_version: Optional[str] = None, - model: Optional[str] = None, - system_prompt: Optional[str] = None, - skills: Optional[list[dict[str, Any]]] = None, - tools: Optional[list[dict[str, Any]]] = None, ) -> None: ... @overload @@ -10804,22 +11119,12 @@ class OptimizationCandidate(_Model): :vartype candidate_id: str :ivar name: Display name of the candidate (e.g., 'baseline', 'instruction-v2'). Required. :vartype name: str - :ivar config: The agent configuration that produced this candidate. Required. - :vartype config: ~azure.ai.projects.models.OptimizationAgentDefinition :ivar mutations: What was mutated from the baseline (e.g., {system_prompt: 'new prompt'}). - Required. :vartype mutations: dict[str, any] :ivar avg_score: Average composite score across all tasks. Required. :vartype avg_score: float :ivar avg_tokens: Average token usage across all tasks. Required. :vartype avg_tokens: float - :ivar pass_rate: Fraction of tasks that met the pass threshold. Required. - :vartype pass_rate: float - :ivar task_scores: Individual task-level scores. Required. - :vartype task_scores: list[~azure.ai.projects.models.OptimizationTaskResult] - :ivar is_pareto_optimal: Whether this candidate is on the Pareto frontier (score vs cost). - Required. - :vartype is_pareto_optimal: bool :ivar eval_id: Foundry evaluation identifier used to score this candidate. :vartype eval_id: str :ivar eval_run_id: Foundry evaluation run identifier for this candidate's scoring run. @@ -10832,24 +11137,12 @@ class OptimizationCandidate(_Model): """Server-assigned candidate identifier. Use with GET /candidates/{id} sub-endpoints.""" name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Display name of the candidate (e.g., 'baseline', 'instruction-v2'). Required.""" - config: "_models.OptimizationAgentDefinition" = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """The agent configuration that produced this candidate. Required.""" - mutations: dict[str, Any] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """What was mutated from the baseline (e.g., {system_prompt: 'new prompt'}). Required.""" + mutations: Optional[dict[str, Any]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """What was mutated from the baseline (e.g., {system_prompt: 'new prompt'}).""" avg_score: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Average composite score across all tasks. Required.""" avg_tokens: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Average token usage across all tasks. Required.""" - pass_rate: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Fraction of tasks that met the pass threshold. Required.""" - task_scores: list["_models.OptimizationTaskResult"] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Individual task-level scores. Required.""" - is_pareto_optimal: bool = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Whether this candidate is on the Pareto frontier (score vs cost). Required.""" eval_id: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Foundry evaluation identifier used to score this candidate.""" eval_run_id: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) @@ -10864,14 +11157,10 @@ def __init__( self, *, name: str, - config: "_models.OptimizationAgentDefinition", - mutations: dict[str, Any], avg_score: float, avg_tokens: float, - pass_rate: float, - task_scores: list["_models.OptimizationTaskResult"], - is_pareto_optimal: bool, candidate_id: Optional[str] = None, + mutations: Optional[dict[str, Any]] = None, eval_id: Optional[str] = None, eval_run_id: Optional[str] = None, promotion: Optional["_models.PromotionInfo"] = None, @@ -10888,6 +11177,187 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) +class OptimizationDatasetCriterion(_Model): + """Evaluation criterion: a name + instruction pair used for per-item scoring. + + :ivar name: Criterion name. Required. + :vartype name: str + :ivar instruction: Criterion instruction / description. Required. + :vartype instruction: str + """ + + name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Criterion name. Required.""" + instruction: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Criterion instruction / description. Required.""" + + @overload + def __init__( + self, + *, + name: str, + instruction: str, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class OptimizationDatasetInput(_Model): + """Base discriminated model for dataset input. Either inline items or a registered reference. + + You probably want to use the sub-classes and not this class directly. Known sub-classes are: + OptimizationInlineDatasetInput, OptimizationReferenceDatasetInput + + :ivar type: Dataset input type discriminator. Required. Known values are: "inline" and + "reference". + :vartype type: str or ~azure.ai.projects.models.OptimizationDatasetInputType + """ + + __mapping__: dict[str, _Model] = {} + type: str = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) + """Dataset input type discriminator. Required. Known values are: \"inline\" and \"reference\".""" + + @overload + def __init__( + self, + *, + type: str, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class OptimizationDatasetItem(_Model): + """A single item in an inline dataset. + + :ivar query: The user query / prompt. + :vartype query: str + :ivar ground_truth: Expected ground truth answer. + :vartype ground_truth: str + :ivar desired_num_turns: Desired number of conversation turns for simulation mode (1-20). + :vartype desired_num_turns: int + :ivar criteria: Per-item evaluation criteria. + :vartype criteria: list[~azure.ai.projects.models.OptimizationDatasetCriterion] + """ + + query: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The user query / prompt.""" + ground_truth: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Expected ground truth answer.""" + desired_num_turns: Optional[int] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Desired number of conversation turns for simulation mode (1-20).""" + criteria: Optional[list["_models.OptimizationDatasetCriterion"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Per-item evaluation criteria.""" + + @overload + def __init__( + self, + *, + query: Optional[str] = None, + ground_truth: Optional[str] = None, + desired_num_turns: Optional[int] = None, + criteria: Optional[list["_models.OptimizationDatasetCriterion"]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class OptimizationEvaluatorRef(_Model): + """Reference to a named evaluator, optionally pinned to a version. + + :ivar name: Evaluator name. Required. + :vartype name: str + :ivar version: Evaluator version. If not specified, the latest version is used. + :vartype version: str + """ + + name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Evaluator name. Required.""" + version: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Evaluator version. If not specified, the latest version is used.""" + + @overload + def __init__( + self, + *, + name: str, + version: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class OptimizationInlineDatasetInput(OptimizationDatasetInput, discriminator="inline"): + """Inline dataset — items supplied directly in the request body. + + :ivar type: Dataset input type discriminator. Required. Inline dataset — items are provided + directly in the request body. + :vartype type: str or ~azure.ai.projects.models.INLINE + :ivar dataset_items: Dataset items. Required. + :vartype dataset_items: list[~azure.ai.projects.models.OptimizationDatasetItem] + """ + + type: Literal[OptimizationDatasetInputType.INLINE] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Dataset input type discriminator. Required. Inline dataset — items are provided directly in the + request body.""" + dataset_items: list["_models.OptimizationDatasetItem"] = rest_field( + name="items", visibility=["read", "create", "update", "delete", "query"] + ) + """Dataset items. Required.""" + + @overload + def __init__( + self, + *, + dataset_items: list["_models.OptimizationDatasetItem"], + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = OptimizationDatasetInputType.INLINE # type: ignore + + class OptimizationJob(_Model): """Agent optimization job resource — a long-running job that optimizes an agent's configuration (instructions, model, skills, tools) to maximize evaluation scores. On success, the result @@ -10895,48 +11365,48 @@ class OptimizationJob(_Model): :ivar id: Server-assigned unique identifier. Required. :vartype id: str + :ivar inputs: Caller-supplied inputs. + :vartype inputs: ~azure.ai.projects.models.OptimizationJobInputs + :ivar result: Result produced on success. + :vartype result: ~azure.ai.projects.models.OptimizationJobResult :ivar status: Current lifecycle status. Required. Known values are: "queued", "in_progress", "succeeded", "failed", and "cancelled". :vartype status: str or ~azure.ai.projects.models.JobStatus :ivar error: Error details — populated only on failure. :vartype error: ~azure.ai.projects.models.ApiError - :ivar result: Result produced on success. - :vartype result: ~azure.ai.projects.models.OptimizationJobResult - :ivar inputs: Caller-supplied inputs. - :vartype inputs: ~azure.ai.projects.models.OptimizationJobInputs :ivar created_at: The timestamp when the job was created, represented in Unix time. Required. :vartype created_at: ~datetime.datetime - :ivar updated_at: The timestamp when the job was last updated (status, progress, or result - change), represented in Unix time. + :ivar updated_at: The timestamp when the job was last updated, represented in Unix time. + Required. :vartype updated_at: ~datetime.datetime - :ivar progress: Progress while in flight. Absent in terminal states. + :ivar progress: Progress snapshot. May be present in terminal states reflecting last-known + progress. :vartype progress: ~azure.ai.projects.models.OptimizationJobProgress - :ivar dataset: Metadata about the dataset used for this optimization job. - :vartype dataset: ~azure.ai.projects.models.DatasetInfo + :ivar warnings: Non-fatal warnings emitted at any point during optimization. + :vartype warnings: list[str] """ id: str = rest_field(visibility=["read"]) """Server-assigned unique identifier. Required.""" + inputs: Optional["_models.OptimizationJobInputs"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Caller-supplied inputs.""" + result: Optional["_models.OptimizationJobResult"] = rest_field(visibility=["read"]) + """Result produced on success.""" status: Union[str, "_models.JobStatus"] = rest_field(visibility=["read"]) """Current lifecycle status. Required. Known values are: \"queued\", \"in_progress\", \"succeeded\", \"failed\", and \"cancelled\".""" error: Optional["_models.ApiError"] = rest_field(visibility=["read"]) """Error details — populated only on failure.""" - result: Optional["_models.OptimizationJobResult"] = rest_field(visibility=["read"]) - """Result produced on success.""" - inputs: Optional["_models.OptimizationJobInputs"] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Caller-supplied inputs.""" created_at: datetime.datetime = rest_field(visibility=["read"], format="unix-timestamp") """The timestamp when the job was created, represented in Unix time. Required.""" - updated_at: Optional[datetime.datetime] = rest_field(visibility=["read"], format="unix-timestamp") - """The timestamp when the job was last updated (status, progress, or result change), represented - in Unix time.""" + updated_at: datetime.datetime = rest_field(visibility=["read"], format="unix-timestamp") + """The timestamp when the job was last updated, represented in Unix time. Required.""" progress: Optional["_models.OptimizationJobProgress"] = rest_field(visibility=["read"]) - """Progress while in flight. Absent in terminal states.""" - dataset: Optional["_models.DatasetInfo"] = rest_field(visibility=["read"]) - """Metadata about the dataset used for this optimization job.""" + """Progress snapshot. May be present in terminal states reflecting last-known progress.""" + warnings: Optional[list[str]] = rest_field(visibility=["read"]) + """Non-fatal warnings emitted at any point during optimization.""" @overload def __init__( @@ -10960,32 +11430,38 @@ class OptimizationJobInputs(_Model): """Caller-supplied inputs for an optimization job. :ivar agent: The agent (and pinned version) being optimized. Required. - :vartype agent: ~azure.ai.projects.models.AgentIdentifier - :ivar train_dataset_reference: Reference to a registered training dataset (required). Required. - :vartype train_dataset_reference: ~azure.ai.projects.models.DatasetRef - :ivar validation_dataset_reference: Optional held-out validation dataset for measuring - generalization of the final candidate. - :vartype validation_dataset_reference: ~azure.ai.projects.models.DatasetRef - :ivar evaluators: Job-level evaluators (referenced by name). Per-task criteria may override. - Default: ['task_adherence']. - :vartype evaluators: list[str] + :vartype agent: ~azure.ai.projects.models.OptimizationAgentIdentifier + :ivar train_dataset: Training dataset — either inline items or a reference to a registered + dataset. Required. Required. + :vartype train_dataset: ~azure.ai.projects.models.OptimizationDatasetInput + :ivar validation_dataset: Optional held-out validation dataset for measuring generalization of + the final candidate. + :vartype validation_dataset: ~azure.ai.projects.models.OptimizationDatasetInput + :ivar evaluators: Job-level evaluators referenced by name and optional version. Required; at + least one must be provided. Required. + :vartype evaluators: list[~azure.ai.projects.models.OptimizationEvaluatorRef] :ivar options: Tuning knobs and run-mode. :vartype options: ~azure.ai.projects.models.OptimizationOptions """ - agent: "_models.AgentIdentifier" = rest_field(visibility=["read", "create", "update", "delete", "query"]) + agent: "_models.OptimizationAgentIdentifier" = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The agent (and pinned version) being optimized. Required.""" - train_dataset_reference: "_models.DatasetRef" = rest_field( + train_dataset: "_models.OptimizationDatasetInput" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Reference to a registered training dataset (required). Required.""" - validation_dataset_reference: Optional["_models.DatasetRef"] = rest_field( + """Training dataset — either inline items or a reference to a registered dataset. Required. + Required.""" + validation_dataset: Optional["_models.OptimizationDatasetInput"] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) """Optional held-out validation dataset for measuring generalization of the final candidate.""" - evaluators: Optional[list[str]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Job-level evaluators (referenced by name). Per-task criteria may override. Default: - ['task_adherence'].""" + evaluators: list["_models.OptimizationEvaluatorRef"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Job-level evaluators referenced by name and optional version. Required; at least one must be + provided. Required.""" options: Optional["_models.OptimizationOptions"] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -10995,10 +11471,10 @@ class OptimizationJobInputs(_Model): def __init__( self, *, - agent: "_models.AgentIdentifier", - train_dataset_reference: "_models.DatasetRef", - validation_dataset_reference: Optional["_models.DatasetRef"] = None, - evaluators: Optional[list[str]] = None, + agent: "_models.OptimizationAgentIdentifier", + train_dataset: "_models.OptimizationDatasetInput", + evaluators: list["_models.OptimizationEvaluatorRef"], + validation_dataset: Optional["_models.OptimizationDatasetInput"] = None, options: Optional["_models.OptimizationOptions"] = None, ) -> None: ... @@ -11013,11 +11489,51 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) +class OptimizationJobListItem(_Model): + """Slim job representation returned by the LIST endpoint. + + :ivar id: Server-assigned unique identifier. Required. + :vartype id: str + :ivar status: Current lifecycle status. Required. Known values are: "queued", "in_progress", + "succeeded", "failed", and "cancelled". + :vartype status: str or ~azure.ai.projects.models.JobStatus + :ivar error: Error details — populated only on failure. + :vartype error: ~azure.ai.projects.models.ApiError + :ivar created_at: The timestamp when the job was created, represented in Unix time. Required. + :vartype created_at: ~datetime.datetime + :ivar updated_at: The timestamp when the job was last updated, represented in Unix time. + Required. + :vartype updated_at: ~datetime.datetime + :ivar progress: Progress snapshot. May be present in terminal states reflecting last-known + progress. + :vartype progress: ~azure.ai.projects.models.OptimizationJobProgress + :ivar agent: The agent targeted by this optimization job. + :vartype agent: ~azure.ai.projects.models.OptimizationAgentIdentifier + """ + + id: str = rest_field(visibility=["read"]) + """Server-assigned unique identifier. Required.""" + status: Union[str, "_models.JobStatus"] = rest_field(visibility=["read"]) + """Current lifecycle status. Required. Known values are: \"queued\", \"in_progress\", + \"succeeded\", \"failed\", and \"cancelled\".""" + error: Optional["_models.ApiError"] = rest_field(visibility=["read"]) + """Error details — populated only on failure.""" + created_at: datetime.datetime = rest_field(visibility=["read"], format="unix-timestamp") + """The timestamp when the job was created, represented in Unix time. Required.""" + updated_at: datetime.datetime = rest_field(visibility=["read"], format="unix-timestamp") + """The timestamp when the job was last updated, represented in Unix time. Required.""" + progress: Optional["_models.OptimizationJobProgress"] = rest_field(visibility=["read"]) + """Progress snapshot. May be present in terminal states reflecting last-known progress.""" + agent: Optional["_models.OptimizationAgentIdentifier"] = rest_field(visibility=["read"]) + """The agent targeted by this optimization job.""" + + class OptimizationJobProgress(_Model): """In-flight progress; only populated while status is queued or in_progress. - :ivar current_iteration: 1-based current iteration index. Required. - :vartype current_iteration: int + :ivar candidates_completed: Number of candidates whose evaluation has completed so far. + Required. + :vartype candidates_completed: int :ivar best_score: Best score observed so far across all candidates. Required. :vartype best_score: float :ivar elapsed_seconds: Wall-clock time elapsed in seconds since the job began executing. @@ -11025,8 +11541,8 @@ class OptimizationJobProgress(_Model): :vartype elapsed_seconds: float """ - current_iteration: int = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """1-based current iteration index. Required.""" + candidates_completed: int = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Number of candidates whose evaluation has completed so far. Required.""" best_score: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Best score observed so far across all candidates. Required.""" elapsed_seconds: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) @@ -11036,7 +11552,7 @@ class OptimizationJobProgress(_Model): def __init__( self, *, - current_iteration: int, + candidates_completed: int, best_score: float, elapsed_seconds: float, ) -> None: ... @@ -11055,56 +11571,30 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class OptimizationJobResult(_Model): """Terminal-state result body. Populated when status is succeeded or failed. - :ivar baseline: Evaluation scores for the original (un-optimized) agent configuration. - :vartype baseline: ~azure.ai.projects.models.OptimizationCandidate - :ivar best: The highest-scoring candidate found during optimization. - :vartype best: ~azure.ai.projects.models.OptimizationCandidate + :ivar baseline: Candidate ID of the original (un-optimized) baseline evaluation. + :vartype baseline: str + :ivar best: Candidate ID of the highest-scoring candidate found during optimization. + :vartype best: str :ivar candidates: All evaluated candidates including baseline. :vartype candidates: list[~azure.ai.projects.models.OptimizationCandidate] - :ivar options: The options used for this optimization run. - :vartype options: ~azure.ai.projects.models.OptimizationOptions - :ivar warnings: Non-fatal warnings from the optimization run (e.g., target attribute failures - that were skipped). - :vartype warnings: list[str] - :ivar all_target_attributes_failed: True when all target attributes failed — only the baseline - was evaluated. - :vartype all_target_attributes_failed: bool """ - baseline: Optional["_models.OptimizationCandidate"] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Evaluation scores for the original (un-optimized) agent configuration.""" - best: Optional["_models.OptimizationCandidate"] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """The highest-scoring candidate found during optimization.""" + baseline: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Candidate ID of the original (un-optimized) baseline evaluation.""" + best: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Candidate ID of the highest-scoring candidate found during optimization.""" candidates: Optional[list["_models.OptimizationCandidate"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) """All evaluated candidates including baseline.""" - options: Optional["_models.OptimizationOptions"] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """The options used for this optimization run.""" - warnings: Optional[list[str]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Non-fatal warnings from the optimization run (e.g., target attribute failures that were - skipped).""" - all_target_attributes_failed: Optional[bool] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """True when all target attributes failed — only the baseline was evaluated.""" @overload def __init__( self, *, - baseline: Optional["_models.OptimizationCandidate"] = None, - best: Optional["_models.OptimizationCandidate"] = None, + baseline: Optional[str] = None, + best: Optional[str] = None, candidates: Optional[list["_models.OptimizationCandidate"]] = None, - options: Optional["_models.OptimizationOptions"] = None, - warnings: Optional[list[str]] = None, - all_target_attributes_failed: Optional[bool] = None, ) -> None: ... @overload @@ -11121,8 +11611,9 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class OptimizationOptions(_Model): """Tuning knobs and run-mode for an optimization job. - :ivar max_iterations: Maximum optimization iterations per strategy. Must be >= 1. Default: 5. - :vartype max_iterations: int + :ivar max_candidates: Maximum number of optimization candidates to generate. Must be >= 1. + Default: 5. + :vartype max_candidates: int :ivar optimization_config: Per-target-attribute configuration overrides. Contains skills, tools, system_prompt for the agent, plus model space for model optimization. :vartype optimization_config: dict[str, any] @@ -11138,8 +11629,8 @@ class OptimizationOptions(_Model): :vartype evaluation_level: str or ~azure.ai.projects.models.EvaluationLevel """ - max_iterations: Optional[int] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Maximum optimization iterations per strategy. Must be >= 1. Default: 5.""" + max_candidates: Optional[int] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Maximum number of optimization candidates to generate. Must be >= 1. Default: 5.""" optimization_config: Optional[dict[str, Any]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -11161,7 +11652,7 @@ class OptimizationOptions(_Model): def __init__( self, *, - max_iterations: Optional[int] = None, + max_candidates: Optional[int] = None, optimization_config: Optional[dict[str, Any]] = None, eval_model: Optional[str] = None, optimization_model: Optional[str] = None, @@ -11179,71 +11670,32 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class OptimizationTaskResult(_Model): - """Per-task evaluation result for a single candidate. +class OptimizationReferenceDatasetInput(OptimizationDatasetInput, discriminator="reference"): + """Reference to a registered Foundry dataset. - :ivar task_name: Task name (from the dataset). Required. - :vartype task_name: str - :ivar query: The user query / input for the task. - :vartype query: str - :ivar scores: Per-evaluator scores keyed by evaluator name. Required. - :vartype scores: dict[str, float] - :ivar composite_score: Composite score combining all evaluator scores. Required. - :vartype composite_score: float - :ivar tokens: Total tokens consumed during the agent run for this task. Required. - :vartype tokens: int - :ivar duration_seconds: Wall-clock seconds for this task's agent execution. Required. - :vartype duration_seconds: float - :ivar passed: Whether the task met the pass threshold. Required. - :vartype passed: bool - :ivar error_message: Error message if the task failed during execution. - :vartype error_message: str - :ivar rationales: Per-evaluator reasoning keyed by evaluator name. - :vartype rationales: dict[str, str] - :ivar response: Raw agent response text. - :vartype response: str - :ivar run_id: Identifier of the agent run that produced this result. - :vartype run_id: str + :ivar type: Dataset input type discriminator. Required. Reference to a registered Foundry + dataset by name and version. + :vartype type: str or ~azure.ai.projects.models.REFERENCE + :ivar name: Registered dataset name. Required. + :vartype name: str + :ivar version: Dataset version. If not specified, the latest version is used. + :vartype version: str """ - task_name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Task name (from the dataset). Required.""" - query: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """The user query / input for the task.""" - scores: dict[str, float] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Per-evaluator scores keyed by evaluator name. Required.""" - composite_score: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Composite score combining all evaluator scores. Required.""" - tokens: int = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Total tokens consumed during the agent run for this task. Required.""" - duration_seconds: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Wall-clock seconds for this task's agent execution. Required.""" - passed: bool = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Whether the task met the pass threshold. Required.""" - error_message: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Error message if the task failed during execution.""" - rationales: Optional[dict[str, str]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Per-evaluator reasoning keyed by evaluator name.""" - response: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Raw agent response text.""" - run_id: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Identifier of the agent run that produced this result.""" + type: Literal[OptimizationDatasetInputType.REFERENCE] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Dataset input type discriminator. Required. Reference to a registered Foundry dataset by name + and version.""" + name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Registered dataset name. Required.""" + version: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Dataset version. If not specified, the latest version is used.""" @overload def __init__( self, *, - task_name: str, - scores: dict[str, float], - composite_score: float, - tokens: int, - duration_seconds: float, - passed: bool, - query: Optional[str] = None, - error_message: Optional[str] = None, - rationales: Optional[dict[str, str]] = None, - response: Optional[str] = None, - run_id: Optional[str] = None, + name: str, + version: Optional[str] = None, ) -> None: ... @overload @@ -11255,6 +11707,7 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) + self.type = OptimizationDatasetInputType.REFERENCE # type: ignore class TelemetryEndpoint(_Model): @@ -11496,89 +11949,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.kind = MemoryItemKind.PROCEDURAL # type: ignore -class PromoteCandidateRequest(_Model): - """Request body for promoting a candidate to a Foundry agent version. - - :ivar agent_name: Name of the Foundry agent to promote to. Required. - :vartype agent_name: str - :ivar agent_version: Version of the Foundry agent to promote to. Required. - :vartype agent_version: str - """ - - agent_name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Name of the Foundry agent to promote to. Required.""" - agent_version: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Version of the Foundry agent to promote to. Required.""" - - @overload - def __init__( - self, - *, - agent_name: str, - agent_version: str, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - - -class PromoteCandidateResponse(_Model): - """Response after successfully promoting a candidate. - - :ivar candidate_id: The promoted candidate id. Required. - :vartype candidate_id: str - :ivar status: Status after promotion. Required. - :vartype status: str - :ivar promoted_at: Timestamp when promotion occurred, represented in Unix time. Required. - :vartype promoted_at: ~datetime.datetime - :ivar agent_name: Name of the Foundry agent promoted to. Required. - :vartype agent_name: str - :ivar agent_version: Version of the Foundry agent promoted to. Required. - :vartype agent_version: str - """ - - candidate_id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """The promoted candidate id. Required.""" - status: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Status after promotion. Required.""" - promoted_at: datetime.datetime = rest_field( - visibility=["read", "create", "update", "delete", "query"], format="unix-timestamp" - ) - """Timestamp when promotion occurred, represented in Unix time. Required.""" - agent_name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Name of the Foundry agent promoted to. Required.""" - agent_version: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Version of the Foundry agent promoted to. Required.""" - - @overload - def __init__( - self, - *, - candidate_id: str, - status: str, - promoted_at: datetime.datetime, - agent_name: str, - agent_version: str, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - - class PromotionInfo(_Model): """Promotion metadata recorded when a candidate is deployed to a Foundry agent. @@ -11880,20 +12250,85 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = EvaluatorGenerationJobSourceType.PROMPT # type: ignore +class ProtocolConfiguration(_Model): + """Per-protocol configuration for the agent endpoint. + + :ivar activity: Configuration for the activity protocol. + :vartype activity: ~azure.ai.projects.models.ActivityProtocolConfiguration + :ivar responses: Configuration for the responses protocol. + :vartype responses: ~azure.ai.projects.models.ResponsesProtocolConfiguration + :ivar a2a: Configuration for the A2A protocol. + :vartype a2a: ~azure.ai.projects.models.A2AProtocolConfiguration + :ivar mcp: Configuration for the MCP protocol. + :vartype mcp: ~azure.ai.projects.models.McpProtocolConfiguration + :ivar invocations: Configuration for the invocations protocol. + :vartype invocations: ~azure.ai.projects.models.InvocationsProtocolConfiguration + :ivar invocations_ws: Configuration for the WebSocket-based invocations protocol. + :vartype invocations_ws: ~azure.ai.projects.models.InvocationsWsProtocolConfiguration + """ + + activity: Optional["_models.ActivityProtocolConfiguration"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Configuration for the activity protocol.""" + responses: Optional["_models.ResponsesProtocolConfiguration"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Configuration for the responses protocol.""" + a2a: Optional["_models.A2AProtocolConfiguration"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Configuration for the A2A protocol.""" + mcp: Optional["_models.McpProtocolConfiguration"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Configuration for the MCP protocol.""" + invocations: Optional["_models.InvocationsProtocolConfiguration"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Configuration for the invocations protocol.""" + invocations_ws: Optional["_models.InvocationsWsProtocolConfiguration"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Configuration for the WebSocket-based invocations protocol.""" + + @overload + def __init__( + self, + *, + activity: Optional["_models.ActivityProtocolConfiguration"] = None, + responses: Optional["_models.ResponsesProtocolConfiguration"] = None, + a2a: Optional["_models.A2AProtocolConfiguration"] = None, + mcp: Optional["_models.McpProtocolConfiguration"] = None, + invocations: Optional["_models.InvocationsProtocolConfiguration"] = None, + invocations_ws: Optional["_models.InvocationsWsProtocolConfiguration"] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + class ProtocolVersionRecord(_Model): """A record mapping for a single protocol and its version. - :ivar protocol: The protocol type. Required. Known values are: "activity_protocol", - "responses", "mcp", "invocations", and "invocations_ws". - :vartype protocol: str or ~azure.ai.projects.models.AgentProtocol + :ivar protocol: The protocol type. Required. Known values are: "activity", "responses", "a2a", + "mcp", "invocations", and "invocations_ws". + :vartype protocol: str or ~azure.ai.projects.models.AgentEndpointProtocol :ivar version: The version string for the protocol, e.g. 'v0.1.1'. Required. :vartype version: str """ - protocol: Union[str, "_models.AgentProtocol"] = rest_field( + protocol: Union[str, "_models.AgentEndpointProtocol"] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """The protocol type. Required. Known values are: \"activity_protocol\", \"responses\", \"mcp\", + """The protocol type. Required. Known values are: \"activity\", \"responses\", \"a2a\", \"mcp\", \"invocations\", and \"invocations_ws\".""" version: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The version string for the protocol, e.g. 'v0.1.1'. Required.""" @@ -11902,7 +12337,7 @@ class ProtocolVersionRecord(_Model): def __init__( self, *, - protocol: Union[str, "_models.AgentProtocol"], + protocol: Union[str, "_models.AgentEndpointProtocol"], version: str, ) -> None: ... @@ -12190,6 +12625,90 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) +class ReminderPreviewTool(Tool, discriminator="reminder_preview"): + """A built-in tool that schedules the agent to re-invoke itself after a delay. The model passes a + single ``minutes`` argument (positive integer) when calling this tool. The service creates a + one-shot timer routine that fires after the specified delay and re-invokes the agent on the + same conversation thread. No pre-created routine is required. + + :ivar type: The type of the tool. Always ``reminder_preview``. Required. REMINDER_PREVIEW. + :vartype type: str or ~azure.ai.projects.models.REMINDER_PREVIEW + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + """ + + type: Literal[ToolType.REMINDER_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """The type of the tool. Always ``reminder_preview``. Required. REMINDER_PREVIEW.""" + name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Optional user-defined name for this tool or configuration.""" + description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Optional user-defined description for this tool or configuration.""" + + @overload + def __init__( + self, + *, + name: Optional[str] = None, + description: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolType.REMINDER_PREVIEW # type: ignore + + +class ReminderPreviewToolboxTool(ToolboxTool, discriminator="reminder_preview"): + """A reminder tool stored in a toolbox. + + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all + default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names + are silently ignored at runtime. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. REMINDER_PREVIEW. + :vartype type: str or ~azure.ai.projects.models.REMINDER_PREVIEW + """ + + type: Literal[ToolboxToolType.REMINDER_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. REMINDER_PREVIEW.""" + + @overload + def __init__( + self, + *, + name: Optional[str] = None, + description: Optional[str] = None, + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolboxToolType.REMINDER_PREVIEW # type: ignore + + +class ResponsesProtocolConfiguration(_Model): + """Configuration specific to the responses protocol.""" + + class ResponseUsageInputTokensDetails(_Model): """ResponseUsageInputTokensDetails. @@ -12315,7 +12834,7 @@ class RoutineRun(_Model): :ivar id: The unique run identifier for the routine attempt. Required. :vartype id: str - :ivar status: The run status. + :ivar status: The run status. Is one of the following types: str :vartype status: str :ivar phase: The AgentExtensions lifecycle phase for the routine attempt. Known values are: "queued", "dispatching", "completed", and "failed". @@ -12325,6 +12844,9 @@ class RoutineRun(_Model): :vartype trigger_type: str or ~azure.ai.projects.models.RoutineTriggerType :ivar trigger_name: The configured trigger name that produced the routine attempt. :vartype trigger_name: str + :ivar trigger_event_payload: The event payload captured from the event that triggered the + routine attempt, when available. + :vartype trigger_event_payload: dict[str, any] :ivar attempt_source: The source path that created the routine attempt. Known values are: "event_fire", "manual_dispatch", "queued_dispatch", "schedule_delivery", and "timer_delivery". :vartype attempt_source: str or ~azure.ai.projects.models.RoutineAttemptSource @@ -12368,8 +12890,8 @@ class RoutineRun(_Model): id: str = rest_field(visibility=["read"]) """The unique run identifier for the routine attempt. Required.""" - status: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """The run status.""" + status: Optional["_types.RoutineRunStatus"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The run status. Is one of the following types: str""" phase: Optional[Union[str, "_models.RoutineRunPhase"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -12382,6 +12904,10 @@ class RoutineRun(_Model): \"github_issue\", \"schedule\", and \"timer\".""" trigger_name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The configured trigger name that produced the routine attempt.""" + trigger_event_payload: Optional[dict[str, Any]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """The event payload captured from the event that triggered the routine attempt, when available.""" attempt_source: Optional[Union[str, "_models.RoutineAttemptSource"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -12435,10 +12961,11 @@ class RoutineRun(_Model): def __init__( self, *, - status: Optional[str] = None, + status: Optional["_types.RoutineRunStatus"] = None, phase: Optional[Union[str, "_models.RoutineRunPhase"]] = None, trigger_type: Optional[Union[str, "_models.RoutineTriggerType"]] = None, trigger_name: Optional[str] = None, + trigger_event_payload: Optional[dict[str, Any]] = None, attempt_source: Optional[Union[str, "_models.RoutineAttemptSource"]] = None, action_type: Optional[Union[str, "_models.RoutineActionType"]] = None, agent_id: Optional[str] = None, @@ -12909,16 +13436,8 @@ class SharepointPreviewTool(Tool, discriminator="sharepoint_grounding_preview"): """The input definition information for a sharepoint tool as used to configure an agent. :ivar type: The object type, which is always 'sharepoint_grounding_preview'. Required. - SHAREPOINT_GROUNDING_PREVIEW. - :vartype type: str or ~azure.ai.projects.models.SHAREPOINT_GROUNDING_PREVIEW - :ivar name: Optional user-defined name for this tool or configuration. - :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. - :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. - :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + SHAREPOINT_GROUNDING_PREVIEW. + :vartype type: str or ~azure.ai.projects.models.SHAREPOINT_GROUNDING_PREVIEW :ivar sharepoint_grounding_preview: The sharepoint grounding tool parameters. Required. :vartype sharepoint_grounding_preview: ~azure.ai.projects.models.SharepointGroundingToolParameters @@ -12927,16 +13446,6 @@ class SharepointPreviewTool(Tool, discriminator="sharepoint_grounding_preview"): type: Literal[ToolType.SHAREPOINT_GROUNDING_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The object type, which is always 'sharepoint_grounding_preview'. Required. SHAREPOINT_GROUNDING_PREVIEW.""" - name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" - description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" sharepoint_grounding_preview: "_models.SharepointGroundingToolParameters" = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -12947,9 +13456,6 @@ def __init__( self, *, sharepoint_grounding_preview: "_models.SharepointGroundingToolParameters", - name: Optional[str] = None, - description: Optional[str] = None, - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, ) -> None: ... @overload @@ -13222,14 +13728,15 @@ class ToolChoiceParam(_Model): ``tools`` parameter to see how to specify which tools the model can call. You probably want to use the sub-classes and not this class directly. Known sub-classes are: - ToolChoiceAllowed, SpecificApplyPatchParam, ToolChoiceCodeInterpreter, - ToolChoiceComputerUsePreview, ToolChoiceCustom, ToolChoiceFileSearch, ToolChoiceFunction, - ToolChoiceImageGeneration, ToolChoiceMCP, SpecificFunctionShellParam, + ToolChoiceAllowed, SpecificApplyPatchParam, ToolChoiceCodeInterpreter, ToolChoiceComputer, + ToolChoiceComputerUse, ToolChoiceComputerUsePreview, ToolChoiceCustom, ToolChoiceFileSearch, + ToolChoiceFunction, ToolChoiceImageGeneration, ToolChoiceMCP, SpecificFunctionShellParam, ToolChoiceWebSearchPreview, ToolChoiceWebSearchPreview20250311 :ivar type: Required. Known values are: "allowed_tools", "function", "mcp", "custom", "apply_patch", "shell", "file_search", "web_search_preview", "computer_use_preview", - "web_search_preview_2025_03_11", "image_generation", and "code_interpreter". + "web_search_preview_2025_03_11", "image_generation", "code_interpreter", "computer", and + "computer_use". :vartype type: str or ~azure.ai.projects.models.ToolChoiceParamType """ @@ -13237,7 +13744,8 @@ class ToolChoiceParam(_Model): type: str = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) """Required. Known values are: \"allowed_tools\", \"function\", \"mcp\", \"custom\", \"apply_patch\", \"shell\", \"file_search\", \"web_search_preview\", \"computer_use_preview\", - \"web_search_preview_2025_03_11\", \"image_generation\", and \"code_interpreter\".""" + \"web_search_preview_2025_03_11\", \"image_generation\", \"code_interpreter\", \"computer\", + and \"computer_use\".""" @overload def __init__( @@ -13402,55 +13910,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class SystemDataV3(_Model): - """System metadata for a resource. - - :ivar created_at: Timestamp of resource creation. - :vartype created_at: ~datetime.datetime - :ivar created_by: Identity that created the resource. - :vartype created_by: str - :ivar created_by_type: Type of identity that created the resource. - :vartype created_by_type: str - :ivar last_modified_at: Timestamp of last resource modification. - :vartype last_modified_at: ~datetime.datetime - """ - - created_at: Optional[datetime.datetime] = rest_field( - name="createdAt", visibility=["read", "create", "update", "delete", "query"], format="unix-timestamp" - ) - """Timestamp of resource creation.""" - created_by: Optional[str] = rest_field(name="createdBy", visibility=["read", "create", "update", "delete", "query"]) - """Identity that created the resource.""" - created_by_type: Optional[str] = rest_field( - name="createdByType", visibility=["read", "create", "update", "delete", "query"] - ) - """Type of identity that created the resource.""" - last_modified_at: Optional[datetime.datetime] = rest_field( - name="lastModifiedAt", visibility=["read", "create", "update", "delete", "query"], format="unix-timestamp" - ) - """Timestamp of last resource modification.""" - - @overload - def __init__( - self, - *, - created_at: Optional[datetime.datetime] = None, - created_by: Optional[str] = None, - created_by_type: Optional[str] = None, - last_modified_at: Optional[datetime.datetime] = None, - ) -> None: ... - - @overload - def __init__(self, mapping: Mapping[str, Any]) -> None: - """ - :param mapping: raw JSON to initialize the model. - :type mapping: Mapping[str, Any] - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) - - class TaxonomyCategory(_Model): """Taxonomy category definition. @@ -13749,7 +14208,7 @@ class TimerRoutineTrigger(RoutineTrigger, discriminator="timer"): type: Literal[RoutineTriggerType.TIMER] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The trigger type. Required. A one-shot timer trigger.""" at: Optional[datetime.datetime] = rest_field( - visibility=["read", "create", "update", "delete", "query"], format="rfc3339" + visibility=["read", "create", "update", "delete", "query"], format="unix-timestamp" ) """The UTC date and time at which the timer fires.""" @@ -13840,13 +14299,9 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class ToolboxSearchPreviewTool(Tool, discriminator="toolbox_search_preview"): - """A tool for searching over the agent's toolbox. When present, deferred tools are hidden from - ``tools/list`` and only discoverable via ``search_tools`` queries at runtime. +class ToolboxSearchPreviewToolboxTool(ToolboxTool, discriminator="toolbox_search_preview"): + """A toolbox search tool stored in a toolbox. - :ivar type: The type of the tool. Always ``toolbox_search_preview``. Required. - TOOLBOX_SEARCH_PREVIEW. - :vartype type: str or ~azure.ai.projects.models.TOOLBOX_SEARCH_PREVIEW :ivar name: Optional user-defined name for this tool or configuration. :vartype name: str :ivar description: Optional user-defined description for this tool or configuration. @@ -13855,20 +14310,13 @@ class ToolboxSearchPreviewTool(Tool, discriminator="toolbox_search_preview"): default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at runtime. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: The type of the tool. Always ``toolbox_search_preview``. Required. + TOOLBOX_SEARCH_PREVIEW. + :vartype type: str or ~azure.ai.projects.models.TOOLBOX_SEARCH_PREVIEW """ - type: Literal[ToolType.TOOLBOX_SEARCH_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + type: Literal[ToolboxToolType.TOOLBOX_SEARCH_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """The type of the tool. Always ``toolbox_search_preview``. Required. TOOLBOX_SEARCH_PREVIEW.""" - name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" - description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" @overload def __init__( @@ -13888,7 +14336,7 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.type = ToolType.TOOLBOX_SEARCH_PREVIEW # type: ignore + self.type = ToolboxToolType.TOOLBOX_SEARCH_PREVIEW # type: ignore class ToolboxSkill(_Model): @@ -13985,7 +14433,7 @@ class ToolboxVersionObject(_Model): :ivar created_at: The Unix timestamp (seconds) when the toolbox version was created. Required. :vartype created_at: ~datetime.datetime :ivar tools: The list of tools contained in this toolbox version. Required. - :vartype tools: list[~azure.ai.projects.models.Tool] + :vartype tools: list[~azure.ai.projects.models.ToolboxTool] :ivar skills: The list of skill sources included in this toolbox version. :vartype skills: list[~azure.ai.projects.models.ToolboxSkill] :ivar policies: Policy configuration for the toolbox version. @@ -14012,7 +14460,7 @@ class ToolboxVersionObject(_Model): visibility=["read", "create", "update", "delete", "query"], format="unix-timestamp" ) """The Unix timestamp (seconds) when the toolbox version was created. Required.""" - tools: list["_models.Tool"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + tools: list["_models.ToolboxTool"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The list of tools contained in this toolbox version. Required.""" skills: Optional[list["_models.ToolboxSkill"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] @@ -14032,7 +14480,7 @@ def __init__( name: str, version: str, created_at: datetime.datetime, - tools: list["_models.Tool"], + tools: list["_models.ToolboxTool"], description: Optional[str] = None, skills: Optional[list["_models.ToolboxSkill"]] = None, policies: Optional["_models.ToolboxPolicies"] = None, @@ -14059,8 +14507,8 @@ class ToolChoiceAllowed(ToolChoiceParam, discriminator="allowed_tools"): the model to call one or more of the allowed tools. Required. Is either a Literal["auto"] type or a Literal["required"] type. :vartype mode: str or str - :ivar tools: A list of tool definitions that the model should be allowed to call. For the - Responses API, the list of tool definitions might look like the following. Required. + :ivar tools: Required. A list of tool definitions that the model should be allowed to call. For + the Responses API, the list of tool definitions might look like: .. code-block:: json @@ -14080,8 +14528,8 @@ class ToolChoiceAllowed(ToolChoiceParam, discriminator="allowed_tools"): call one or more of the allowed tools. Required. Is either a Literal[\"auto\"] type or a Literal[\"required\"] type.""" tools: list[dict[str, Any]] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """A list of tool definitions that the model should be allowed to call. For the Responses API, the - list of tool definitions might look like the following. Required. + """Required. A list of tool definitions that the model should be allowed to call. For the + Responses API, the list of tool definitions might look like: .. code-block:: json @@ -14139,6 +14587,62 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = ToolChoiceParamType.CODE_INTERPRETER # type: ignore +class ToolChoiceComputer(ToolChoiceParam, discriminator="computer"): + """Indicates that the model should use a built-in tool to generate a response. `Learn more about + built-in tools `_. + + :ivar type: Required. COMPUTER. + :vartype type: str or ~azure.ai.projects.models.COMPUTER + """ + + type: Literal[ToolChoiceParamType.COMPUTER] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. COMPUTER.""" + + @overload + def __init__( + self, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolChoiceParamType.COMPUTER # type: ignore + + +class ToolChoiceComputerUse(ToolChoiceParam, discriminator="computer_use"): + """Indicates that the model should use a built-in tool to generate a response. `Learn more about + built-in tools `_. + + :ivar type: Required. COMPUTER_USE. + :vartype type: str or ~azure.ai.projects.models.COMPUTER_USE + """ + + type: Literal[ToolChoiceParamType.COMPUTER_USE] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. COMPUTER_USE.""" + + @overload + def __init__( + self, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolChoiceParamType.COMPUTER_USE # type: ignore + + class ToolChoiceComputerUsePreview(ToolChoiceParam, discriminator="computer_use_preview"): """Indicates that the model should use a built-in tool to generate a response. `Learn more about built-in tools `_. @@ -14483,6 +14987,53 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) +class ToolSearchToolParam(Tool, discriminator="tool_search"): + """Tool search tool. + + :ivar type: The type of the tool. Always ``tool_search``. Required. TOOL_SEARCH. + :vartype type: str or ~azure.ai.projects.models.TOOL_SEARCH + :ivar execution: Whether tool search is executed by the server or by the client. Known values + are: "server" and "client". + :vartype execution: str or ~azure.ai.projects.models.ToolSearchExecutionType + :ivar description: + :vartype description: str + :ivar parameters: + :vartype parameters: ~azure.ai.projects.models.EmptyModelParam + """ + + type: Literal[ToolType.TOOL_SEARCH] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """The type of the tool. Always ``tool_search``. Required. TOOL_SEARCH.""" + execution: Optional[Union[str, "_models.ToolSearchExecutionType"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Whether tool search is executed by the server or by the client. Known values are: \"server\" + and \"client\".""" + description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + parameters: Optional["_models.EmptyModelParam"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + + @overload + def __init__( + self, + *, + execution: Optional[Union[str, "_models.ToolSearchExecutionType"]] = None, + description: Optional[str] = None, + parameters: Optional["_models.EmptyModelParam"] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolType.TOOL_SEARCH # type: ignore + + class ToolUseFineTuningDataGenerationJobOptions( DataGenerationJobOptions, discriminator="tool_use" ): # pylint: disable=name-too-long @@ -15004,6 +15555,8 @@ class WebSearchPreviewTool(Tool, discriminator="web_search_preview"): for the search. One of ``low``, ``medium``, or ``high``. ``medium`` is the default. Known values are: "low", "medium", and "high". :vartype search_context_size: str or ~azure.ai.projects.models.SearchContextSize + :ivar search_content_types: + :vartype search_content_types: list[str or ~azure.ai.projects.models.SearchContentType] """ type: Literal[ToolType.WEB_SEARCH_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore @@ -15018,6 +15571,9 @@ class WebSearchPreviewTool(Tool, discriminator="web_search_preview"): """High level guidance for the amount of context window space to use for the search. One of ``low``, ``medium``, or ``high``. ``medium`` is the default. Known values are: \"low\", \"medium\", and \"high\".""" + search_content_types: Optional[list[Union[str, "_models.SearchContentType"]]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) @overload def __init__( @@ -15025,6 +15581,7 @@ def __init__( *, user_location: Optional["_models.ApproximateLocation"] = None, search_context_size: Optional[Union[str, "_models.SearchContextSize"]] = None, + search_content_types: Optional[list[Union[str, "_models.SearchContentType"]]] = None, ) -> None: ... @overload @@ -15053,13 +15610,13 @@ class WebSearchTool(Tool, discriminator="web_search"): for the search. One of ``low``, ``medium``, or ``high``. ``medium`` is the default. Is one of the following types: Literal["low"], Literal["medium"], Literal["high"] :vartype search_context_size: str or str or str - :ivar name: Optional user-defined name for this tool or configuration. + :ivar name: Deprecated. This property is deprecated and will be removed in a future version. :vartype name: str - :ivar description: Optional user-defined description for this tool or configuration. + :ivar description: Deprecated. This property is deprecated and will be removed in a future + version. :vartype description: str - :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all - default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names - are silently ignored at runtime. + :ivar tool_configs: Deprecated. This property is deprecated and will be removed in a future + version. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] :ivar custom_search_configuration: The project connections attached to this tool. There can be a maximum of 1 connection resource attached to the tool. @@ -15082,15 +15639,13 @@ class WebSearchTool(Tool, discriminator="web_search"): ``low``, ``medium``, or ``high``. ``medium`` is the default. Is one of the following types: Literal[\"low\"], Literal[\"medium\"], Literal[\"high\"]""" name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" + """Deprecated. This property is deprecated and will be removed in a future version.""" custom_search_configuration: Optional["_models.WebSearchConfiguration"] = rest_field( visibility=["read", "create", "update", "delete", "query"] ) @@ -15122,6 +15677,77 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: self.type = ToolType.WEB_SEARCH # type: ignore +class WebSearchToolboxTool(ToolboxTool, discriminator="web_search"): + """A web search tool stored in a toolbox. + + :ivar name: Optional user-defined name for this tool or configuration. + :vartype name: str + :ivar description: Optional user-defined description for this tool or configuration. + :vartype description: str + :ivar tool_configs: Per-tool configuration map. Keys are tool names or ``*`` (catch-all + default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names + are silently ignored at runtime. + :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. WEB_SEARCH. + :vartype type: str or ~azure.ai.projects.models.WEB_SEARCH + :ivar filters: + :vartype filters: ~azure.ai.projects.models.WebSearchToolFilters + :ivar user_location: + :vartype user_location: ~azure.ai.projects.models.WebSearchApproximateLocation + :ivar search_context_size: High level guidance for the amount of context window space to use + for the search. One of ``low``, ``medium``, or ``high``. ``medium`` is the default. Is one of + the following types: Literal["low"], Literal["medium"], Literal["high"] + :vartype search_context_size: str or str or str + :ivar custom_search_configuration: The project connections attached to this tool. There can be + a maximum of 1 connection resource attached to the tool. + :vartype custom_search_configuration: ~azure.ai.projects.models.WebSearchConfiguration + """ + + type: Literal[ToolboxToolType.WEB_SEARCH] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. WEB_SEARCH.""" + filters: Optional["_models.WebSearchToolFilters"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + user_location: Optional["_models.WebSearchApproximateLocation"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + search_context_size: Optional[Literal["low", "medium", "high"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """High level guidance for the amount of context window space to use for the search. One of + ``low``, ``medium``, or ``high``. ``medium`` is the default. Is one of the following types: + Literal[\"low\"], Literal[\"medium\"], Literal[\"high\"]""" + custom_search_configuration: Optional["_models.WebSearchConfiguration"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """The project connections attached to this tool. There can be a maximum of 1 connection resource + attached to the tool.""" + + @overload + def __init__( + self, + *, + name: Optional[str] = None, + description: Optional[str] = None, + tool_configs: Optional[dict[str, "_models.ToolConfig"]] = None, + filters: Optional["_models.WebSearchToolFilters"] = None, + user_location: Optional["_models.WebSearchApproximateLocation"] = None, + search_context_size: Optional[Literal["low", "medium", "high"]] = None, + custom_search_configuration: Optional["_models.WebSearchConfiguration"] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolboxToolType.WEB_SEARCH # type: ignore + + class WebSearchToolFilters(_Model): """WebSearchToolFilters. @@ -15227,6 +15853,35 @@ class WorkIQPreviewTool(Tool, discriminator="work_iq_preview"): :vartype type: str or ~azure.ai.projects.models.WORK_IQ_PREVIEW :ivar project_connection_id: The ID of the WorkIQ project connection. Required. :vartype project_connection_id: str + """ + + type: Literal[ToolType.WORK_IQ_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """The object type, which is always 'work_iq_preview'. Required. WORK_IQ_PREVIEW.""" + project_connection_id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The ID of the WorkIQ project connection. Required.""" + + @overload + def __init__( + self, + *, + project_connection_id: str, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + self.type = ToolType.WORK_IQ_PREVIEW # type: ignore + + +class WorkIQPreviewToolboxTool(ToolboxTool, discriminator="work_iq_preview"): + """A WorkIQ tool stored in a toolbox. + :ivar name: Optional user-defined name for this tool or configuration. :vartype name: str :ivar description: Optional user-defined description for this tool or configuration. @@ -15235,22 +15890,16 @@ class WorkIQPreviewTool(Tool, discriminator="work_iq_preview"): default). Resolution order: exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at runtime. :vartype tool_configs: dict[str, ~azure.ai.projects.models.ToolConfig] + :ivar type: Required. WORK_IQ_PREVIEW. + :vartype type: str or ~azure.ai.projects.models.WORK_IQ_PREVIEW + :ivar project_connection_id: The ID of the WorkIQ project connection. Required. + :vartype project_connection_id: str """ - type: Literal[ToolType.WORK_IQ_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore - """The object type, which is always 'work_iq_preview'. Required. WORK_IQ_PREVIEW.""" + type: Literal[ToolboxToolType.WORK_IQ_PREVIEW] = rest_discriminator(name="type", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Required. WORK_IQ_PREVIEW.""" project_connection_id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The ID of the WorkIQ project connection. Required.""" - name: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined name for this tool or configuration.""" - description: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) - """Optional user-defined description for this tool or configuration.""" - tool_configs: Optional[dict[str, "_models.ToolConfig"]] = rest_field( - visibility=["read", "create", "update", "delete", "query"] - ) - """Per-tool configuration map. Keys are tool names or ``*`` (catch-all default). Resolution order: - exact tool name match takes priority over ``*``. Unknown tool names are silently ignored at - runtime.""" @overload def __init__( @@ -15271,4 +15920,4 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) - self.type = ToolType.WORK_IQ_PREVIEW # type: ignore + self.type = ToolboxToolType.WORK_IQ_PREVIEW # type: ignore diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/models/_patch.py b/sdk/ai/azure-ai-projects/azure/ai/projects/models/_patch.py index a907ab276781..257e53dded78 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/models/_patch.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/models/_patch.py @@ -47,12 +47,10 @@ ) _AGENT_OPERATION_FEATURE_HEADERS: Final[str] = ",".join( [ - _AgentDefinitionOptInKeys.HOSTED_AGENTS_V1_PREVIEW.value, _AgentDefinitionOptInKeys.WORKFLOW_AGENTS_V1_PREVIEW.value, - _AgentDefinitionOptInKeys.AGENT_ENDPOINT_V1_PREVIEW.value, - _AgentDefinitionOptInKeys.CODE_AGENTS_V1_PREVIEW.value, _AgentDefinitionOptInKeys.EXTERNAL_AGENTS_V1_PREVIEW.value, - _FoundryFeaturesOptInKeys.AGENTS_OPTIMIZATION_V1_PREVIEW.value, + _AgentDefinitionOptInKeys.DRAFT_AGENTS_V1_PREVIEW.value, + _FoundryFeaturesOptInKeys.AGENTS_OPTIMIZATION_V2_PREVIEW.value, ] ) @@ -65,7 +63,6 @@ "red_teams": _FoundryFeaturesOptInKeys.RED_TEAMS_V1_PREVIEW.value, "routines": _FoundryFeaturesOptInKeys.ROUTINES_V1_PREVIEW.value, "schedules": _FoundryFeaturesOptInKeys.SCHEDULES_V1_PREVIEW.value, - "toolboxes": _FoundryFeaturesOptInKeys.TOOLBOXES_V1_PREVIEW.value, "skills": _FoundryFeaturesOptInKeys.SKILLS_V1_PREVIEW.value, "datasets": _FoundryFeaturesOptInKeys.DATA_GENERATION_JOBS_V1_PREVIEW.value, "agents": _AGENT_OPERATION_FEATURE_HEADERS, diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/__init__.py b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/__init__.py index 1a1c0ffec86c..d6cf67b4d8cf 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/__init__.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/__init__.py @@ -19,6 +19,7 @@ from ._operations import DatasetsOperations # type: ignore from ._operations import DeploymentsOperations # type: ignore from ._operations import IndexesOperations # type: ignore +from ._operations import ToolboxesOperations # type: ignore from ._patch import __all__ as _patch_all from ._patch import * @@ -32,6 +33,7 @@ "DatasetsOperations", "DeploymentsOperations", "IndexesOperations", + "ToolboxesOperations", ] __all__.extend([p for p in _patch_all if p not in __all__]) # pyright: ignore _patch_sdk() diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py index 2ae3231aea70..7138502ce49b 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_operations.py @@ -253,6 +253,7 @@ def build_agents_list_versions_request( order: Optional[Union[str, _models.PageOrder]] = None, after: Optional[str] = None, before: Optional[str] = None, + include_drafts: Optional[bool] = None, **kwargs: Any ) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) @@ -278,6 +279,8 @@ def build_agents_list_versions_request( _params["after"] = _SERIALIZER.query("after", after, "str") if before is not None: _params["before"] = _SERIALIZER.query("before", before, "str") + if include_drafts is not None: + _params["include_drafts"] = _SERIALIZER.query("include_drafts", include_drafts, "bool") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers @@ -286,17 +289,18 @@ def build_agents_list_versions_request( return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_evaluation_rules_get_request(id: str, **kwargs: Any) -> HttpRequest: +def build_agents_update_details_request(agent_name: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/evaluationrules/{id}" + _url = "/agents/{agent_name}" path_format_arguments = { - "id": _SERIALIZER.url("id", id, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -305,19 +309,26 @@ def build_evaluation_rules_get_request(id: str, **kwargs: Any) -> HttpRequest: _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="PATCH", url=_url, params=_params, headers=_headers, **kwargs) -def build_evaluation_rules_delete_request(id: str, **kwargs: Any) -> HttpRequest: +def build_agents_create_version_from_code_request( # pylint: disable=name-too-long + agent_name: str, *, code_zip_sha256: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") + # Construct URL - _url = "/evaluationrules/{id}" + _url = "/agents/{agent_name}/versions" path_format_arguments = { - "id": _SERIALIZER.url("id", id, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -325,80 +336,67 @@ def build_evaluation_rules_delete_request(id: str, **kwargs: Any) -> HttpRequest # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) + # Construct headers + _headers["x-ms-code-zip-sha256"] = _SERIALIZER.header("code_zip_sha256", code_zip_sha256, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) -def build_evaluation_rules_create_or_update_request( # pylint: disable=name-too-long - id: str, **kwargs: Any + +def build_agents_download_code_as_bytes_request( # pylint: disable=name-too-long + agent_name: str, *, agent_version: Optional[str] = None, **kwargs: Any ) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") + accept = _headers.pop("Accept", "application/zip") # Construct URL - _url = "/evaluationrules/{id}" + _url = "/agents/{agent_name}/code:download" path_format_arguments = { - "id": _SERIALIZER.url("id", id, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters + if agent_version is not None: + _params["agent_version"] = _SERIALIZER.query("agent_version", agent_version, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if content_type is not None: - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="PUT", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_evaluation_rules_list_request( - *, - action_type: Optional[Union[str, _models.EvaluationRuleActionType]] = None, - agent_name: Optional[str] = None, - enabled: Optional[bool] = None, - **kwargs: Any -) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) +def build_agents_enable_request(agent_name: str, **kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - # Construct URL - _url = "/evaluationrules" + _url = "/agents/{agent_name}:enable" + path_format_arguments = { + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - if action_type is not None: - _params["actionType"] = _SERIALIZER.query("action_type", action_type, "str") - if agent_name is not None: - _params["agentName"] = _SERIALIZER.query("agent_name", agent_name, "str") - if enabled is not None: - _params["enabled"] = _SERIALIZER.query("enabled", enabled, "bool") - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="POST", url=_url, params=_params, **kwargs) -def build_connections_get_request(name: str, **kwargs: Any) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) +def build_agents_disable_request(agent_name: str, **kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - # Construct URL - _url = "/connections/{name}" + _url = "/agents/{agent_name}:disable" path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -406,25 +404,21 @@ def build_connections_get_request(name: str, **kwargs: Any) -> HttpRequest: # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="POST", url=_url, params=_params, **kwargs) -def build_connections_get_with_credentials_request( # pylint: disable=name-too-long - name: str, **kwargs: Any -) -> HttpRequest: +def build_agents_create_session_request(agent_name: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/connections/{name}/getConnectionWithCredentials" + _url = "/agents/{agent_name}/endpoint/sessions" path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -433,17 +427,14 @@ def build_connections_get_with_credentials_request( # pylint: disable=name-too- _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) -def build_connections_list_request( - *, - connection_type: Optional[Union[str, _models.ConnectionType]] = None, - default_connection: Optional[bool] = None, - **kwargs: Any -) -> HttpRequest: +def build_agents_get_session_request(agent_name: str, session_id: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -451,14 +442,16 @@ def build_connections_list_request( accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/connections" + _url = "/agents/{agent_name}/endpoint/sessions/{session_id}" + path_format_arguments = { + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "session_id": _SERIALIZER.url("session_id", session_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - if connection_type is not None: - _params["connectionType"] = _SERIALIZER.query("connection_type", connection_type, "str") - if default_connection is not None: - _params["defaultConnection"] = _SERIALIZER.query("default_connection", default_connection, "bool") # Construct headers _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") @@ -466,17 +459,15 @@ def build_connections_list_request( return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_datasets_list_versions_request(name: str, **kwargs: Any) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) +def build_agents_delete_session_request(agent_name: str, session_id: str, **kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - # Construct URL - _url = "/datasets/{name}/versions" + _url = "/agents/{agent_name}/endpoint/sessions/{session_id}" path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "session_id": _SERIALIZER.url("session_id", session_id, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -484,32 +475,37 @@ def build_datasets_list_versions_request(name: str, **kwargs: Any) -> HttpReques # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) -def build_datasets_list_request(**kwargs: Any) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) +def build_agents_stop_session_request(agent_name: str, session_id: str, **kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - # Construct URL - _url = "/datasets" + _url = "/agents/{agent_name}/endpoint/sessions/{session_id}:stop" + path_format_arguments = { + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "session_id": _SERIALIZER.url("session_id", session_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="POST", url=_url, params=_params, **kwargs) -def build_datasets_get_request(name: str, version: str, **kwargs: Any) -> HttpRequest: +def build_agents_list_sessions_request( + agent_name: str, + *, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + after: Optional[str] = None, + before: Optional[str] = None, + **kwargs: Any +) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -517,15 +513,22 @@ def build_datasets_get_request(name: str, version: str, **kwargs: Any) -> HttpRe accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/datasets/{name}/versions/{version}" + _url = "/agents/{agent_name}/endpoint/sessions" path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - "version": _SERIALIZER.url("version", version, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters + if limit is not None: + _params["limit"] = _SERIALIZER.query("limit", limit, "int") + if order is not None: + _params["order"] = _SERIALIZER.query("order", order, "str") + if after is not None: + _params["after"] = _SERIALIZER.query("after", after, "str") + if before is not None: + _params["before"] = _SERIALIZER.query("before", before, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers @@ -534,15 +537,21 @@ def build_datasets_get_request(name: str, version: str, **kwargs: Any) -> HttpRe return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_datasets_delete_request(name: str, version: str, **kwargs: Any) -> HttpRequest: +def build_agents_get_session_log_stream_request( # pylint: disable=name-too-long + agent_name: str, agent_version: str, session_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "text/event-stream") + # Construct URL - _url = "/datasets/{name}/versions/{version}" + _url = "/agents/{agent_name}/versions/{agent_version}/sessions/{session_id}:logstream" path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - "version": _SERIALIZER.url("version", version, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "agent_version": _SERIALIZER.url("agent_version", agent_version, "str"), + "session_id": _SERIALIZER.url("session_id", session_id, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -550,66 +559,81 @@ def build_datasets_delete_request(name: str, version: str, **kwargs: Any) -> Htt # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_datasets_create_or_update_request(name: str, version: str, **kwargs: Any) -> HttpRequest: + +def build_agents_upload_session_file_request( + agent_name: str, agent_session_id: str, *, remote_path: str, **kwargs: Any +) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + content_type: str = kwargs.pop("content_type") api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/datasets/{name}/versions/{version}" + _url = "/agents/{agent_name}/endpoint/sessions/{agent_session_id}/files/content" path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - "version": _SERIALIZER.url("version", version, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "agent_session_id": _SERIALIZER.url("agent_session_id", agent_session_id, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters + _params["path"] = _SERIALIZER.query("remote_path", remote_path, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if content_type is not None: - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="PATCH", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="PUT", url=_url, params=_params, headers=_headers, **kwargs) -def build_datasets_pending_upload_request(name: str, version: str, **kwargs: Any) -> HttpRequest: +def build_agents_download_session_file_as_bytes_request( # pylint: disable=name-too-long + agent_name: str, agent_session_id: str, *, remote_path: str, **kwargs: Any +) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") + accept = _headers.pop("Accept", "application/octet-stream") # Construct URL - _url = "/datasets/{name}/versions/{version}/startPendingUpload" + _url = "/agents/{agent_name}/endpoint/sessions/{agent_session_id}/files/content" path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - "version": _SERIALIZER.url("version", version, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "agent_session_id": _SERIALIZER.url("agent_session_id", agent_session_id, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters + _params["path"] = _SERIALIZER.query("remote_path", remote_path, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if content_type is not None: - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_datasets_get_credentials_request(name: str, version: str, **kwargs: Any) -> HttpRequest: +def build_agents_list_session_files_request( + agent_name: str, + agent_session_id: str, + *, + remote_path: Optional[str] = None, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + after: Optional[str] = None, + before: Optional[str] = None, + **kwargs: Any +) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -617,71 +641,74 @@ def build_datasets_get_credentials_request(name: str, version: str, **kwargs: An accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/datasets/{name}/versions/{version}/credentials" + _url = "/agents/{agent_name}/endpoint/sessions/{agent_session_id}/files" path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - "version": _SERIALIZER.url("version", version, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "agent_session_id": _SERIALIZER.url("agent_session_id", agent_session_id, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters + if remote_path is not None: + _params["path"] = _SERIALIZER.query("remote_path", remote_path, "str") + if limit is not None: + _params["limit"] = _SERIALIZER.query("limit", limit, "int") + if order is not None: + _params["order"] = _SERIALIZER.query("order", order, "str") + if after is not None: + _params["after"] = _SERIALIZER.query("after", after, "str") + if before is not None: + _params["before"] = _SERIALIZER.query("before", before, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_deployments_get_request(name: str, **kwargs: Any) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) +def build_agents_delete_session_file_request( + agent_name: str, agent_session_id: str, *, remote_path: str, recursive: Optional[bool] = None, **kwargs: Any +) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - # Construct URL - _url = "/deployments/{name}" + _url = "/agents/{agent_name}/endpoint/sessions/{agent_session_id}/files" path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), + "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "agent_session_id": _SERIALIZER.url("agent_session_id", agent_session_id, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters + _params["path"] = _SERIALIZER.query("remote_path", remote_path, "str") + if recursive is not None: + _params["recursive"] = _SERIALIZER.query("recursive", recursive, "bool") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) - -def build_deployments_list_request( - *, - model_publisher: Optional[str] = None, - model_name: Optional[str] = None, - deployment_type: Optional[Union[str, _models.DeploymentType]] = None, - **kwargs: Any -) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) +def build_evaluation_rules_get_request(id: str, **kwargs: Any) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/deployments" + _url = "/evaluationrules/{id}" + path_format_arguments = { + "id": _SERIALIZER.url("id", id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - if model_publisher is not None: - _params["modelPublisher"] = _SERIALIZER.query("model_publisher", model_publisher, "str") - if model_name is not None: - _params["modelName"] = _SERIALIZER.query("model_name", model_name, "str") - if deployment_type is not None: - _params["deploymentType"] = _SERIALIZER.query("deployment_type", deployment_type, "str") # Construct headers _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") @@ -689,17 +716,14 @@ def build_deployments_list_request( return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_indexes_list_versions_request(name: str, **kwargs: Any) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) +def build_evaluation_rules_delete_request(id: str, **kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - # Construct URL - _url = "/indexes/{name}/versions" + _url = "/evaluationrules/{id}" path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), + "id": _SERIALIZER.url("id", id, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -707,32 +731,45 @@ def build_indexes_list_versions_request(name: str, **kwargs: Any) -> HttpRequest # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) -def build_indexes_list_request(**kwargs: Any) -> HttpRequest: +def build_evaluation_rules_create_or_update_request( # pylint: disable=name-too-long + id: str, **kwargs: Any +) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/indexes" + _url = "/evaluationrules/{id}" + path_format_arguments = { + "id": _SERIALIZER.url("id", id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="PUT", url=_url, params=_params, headers=_headers, **kwargs) -def build_indexes_get_request(name: str, version: str, **kwargs: Any) -> HttpRequest: +def build_evaluation_rules_list_request( + *, + action_type: Optional[Union[str, _models.EvaluationRuleActionType]] = None, + agent_name: Optional[str] = None, + enabled: Optional[bool] = None, + **kwargs: Any +) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -740,16 +777,16 @@ def build_indexes_get_request(name: str, version: str, **kwargs: Any) -> HttpReq accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/indexes/{name}/versions/{version}" - path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - "version": _SERIALIZER.url("version", version, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore + _url = "/evaluationrules" # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + if action_type is not None: + _params["actionType"] = _SERIALIZER.query("action_type", action_type, "str") + if agent_name is not None: + _params["agentName"] = _SERIALIZER.query("agent_name", agent_name, "str") + if enabled is not None: + _params["enabled"] = _SERIALIZER.query("enabled", enabled, "bool") # Construct headers _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") @@ -757,38 +794,17 @@ def build_indexes_get_request(name: str, version: str, **kwargs: Any) -> HttpReq return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_indexes_delete_request(name: str, version: str, **kwargs: Any) -> HttpRequest: - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - # Construct URL - _url = "/indexes/{name}/versions/{version}" - path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - "version": _SERIALIZER.url("version", version, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore - - # Construct parameters - _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - - return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) - - -def build_indexes_create_or_update_request(name: str, version: str, **kwargs: Any) -> HttpRequest: +def build_connections_get_request(name: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/indexes/{name}/versions/{version}" + _url = "/connections/{name}" path_format_arguments = { "name": _SERIALIZER.url("name", name, "str"), - "version": _SERIALIZER.url("version", version, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -797,27 +813,24 @@ def build_indexes_create_or_update_request(name: str, version: str, **kwargs: An _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if content_type is not None: - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="PATCH", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_patch_agent_details_request( # pylint: disable=name-too-long - agent_name: str, **kwargs: Any +def build_connections_get_with_credentials_request( # pylint: disable=name-too-long + name: str, **kwargs: Any ) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agents/{agent_name}" + _url = "/connections/{name}/getConnectionWithCredentials" path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "name": _SERIALIZER.url("name", name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -826,15 +839,16 @@ def build_beta_agents_patch_agent_details_request( # pylint: disable=name-too-l _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if content_type is not None: - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="PATCH", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_create_version_from_code_request( # pylint: disable=name-too-long - agent_name: str, *, code_zip_sha256: str, **kwargs: Any +def build_connections_list_request( + *, + connection_type: Optional[Union[str, _models.ConnectionType]] = None, + default_connection: Optional[bool] = None, + **kwargs: Any ) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -843,43 +857,37 @@ def build_beta_agents_create_version_from_code_request( # pylint: disable=name- accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agents/{agent_name}/versions" - path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore + _url = "/connections" # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + if connection_type is not None: + _params["connectionType"] = _SERIALIZER.query("connection_type", connection_type, "str") + if default_connection is not None: + _params["defaultConnection"] = _SERIALIZER.query("default_connection", default_connection, "bool") # Construct headers - _headers["x-ms-code-zip-sha256"] = _SERIALIZER.header("code_zip_sha256", code_zip_sha256, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_download_code_request( - agent_name: str, *, agent_version: Optional[str] = None, **kwargs: Any -) -> HttpRequest: +def build_datasets_list_versions_request(name: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/zip") + accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agents/{agent_name}/code:download" + _url = "/datasets/{name}/versions" path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "name": _SERIALIZER.url("name", name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters - if agent_version is not None: - _params["agent_version"] = _SERIALIZER.query("agent_version", agent_version, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers @@ -888,40 +896,26 @@ def build_beta_agents_download_code_request( return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_create_session_request( - agent_name: str, *, user_isolation_key: Optional[str] = None, **kwargs: Any -) -> HttpRequest: +def build_datasets_list_request(**kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agents/{agent_name}/endpoint/sessions" - path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore + _url = "/datasets" # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if user_isolation_key is not None: - _headers["x-ms-user-isolation-key"] = _SERIALIZER.header("user_isolation_key", user_isolation_key, "str") - if content_type is not None: - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_get_session_request( - agent_name: str, session_id: str, *, user_isolation_key: Optional[str] = None, **kwargs: Any -) -> HttpRequest: +def build_datasets_get_request(name: str, version: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -929,10 +923,10 @@ def build_beta_agents_get_session_request( accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agents/{agent_name}/endpoint/sessions/{session_id}" + _url = "/datasets/{name}/versions/{version}" path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), - "session_id": _SERIALIZER.url("session_id", session_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), + "version": _SERIALIZER.url("version", version, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -941,25 +935,20 @@ def build_beta_agents_get_session_request( _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if user_isolation_key is not None: - _headers["x-ms-user-isolation-key"] = _SERIALIZER.header("user_isolation_key", user_isolation_key, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_delete_session_request( - agent_name: str, session_id: str, *, user_isolation_key: Optional[str] = None, **kwargs: Any -) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) +def build_datasets_delete_request(name: str, version: str, **kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) # Construct URL - _url = "/agents/{agent_name}/endpoint/sessions/{session_id}" + _url = "/datasets/{name}/versions/{version}" path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), - "session_id": _SERIALIZER.url("session_id", session_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), + "version": _SERIALIZER.url("version", version, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -967,22 +956,22 @@ def build_beta_agents_delete_session_request( # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - # Construct headers - if user_isolation_key is not None: - _headers["x-ms-user-isolation-key"] = _SERIALIZER.header("user_isolation_key", user_isolation_key, "str") - - return HttpRequest(method="DELETE", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) -def build_beta_agents_stop_session_request(agent_name: str, session_id: str, **kwargs: Any) -> HttpRequest: +def build_datasets_create_or_update_request(name: str, version: str, **kwargs: Any) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") + # Construct URL - _url = "/agents/{agent_name}/endpoint/sessions/{session_id}:stop" + _url = "/datasets/{name}/versions/{version}" path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), - "session_id": _SERIALIZER.url("session_id", session_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), + "version": _SERIALIZER.url("version", version, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -990,67 +979,54 @@ def build_beta_agents_stop_session_request(agent_name: str, session_id: str, **k # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - return HttpRequest(method="POST", url=_url, params=_params, **kwargs) + # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + return HttpRequest(method="PATCH", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_list_sessions_request( - agent_name: str, - *, - user_isolation_key: Optional[str] = None, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - after: Optional[str] = None, - before: Optional[str] = None, - **kwargs: Any -) -> HttpRequest: + +def build_datasets_pending_upload_request(name: str, version: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agents/{agent_name}/endpoint/sessions" + _url = "/datasets/{name}/versions/{version}/startPendingUpload" path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), + "name": _SERIALIZER.url("name", name, "str"), + "version": _SERIALIZER.url("version", version, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters - if limit is not None: - _params["limit"] = _SERIALIZER.query("limit", limit, "int") - if order is not None: - _params["order"] = _SERIALIZER.query("order", order, "str") - if after is not None: - _params["after"] = _SERIALIZER.query("after", after, "str") - if before is not None: - _params["before"] = _SERIALIZER.query("before", before, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if user_isolation_key is not None: - _headers["x-ms-user-isolation-key"] = _SERIALIZER.header("user_isolation_key", user_isolation_key, "str") + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_get_session_log_stream_request( # pylint: disable=name-too-long - agent_name: str, agent_version: str, session_id: str, **kwargs: Any -) -> HttpRequest: +def build_datasets_get_credentials_request(name: str, version: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "text/event-stream") + accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agents/{agent_name}/versions/{agent_version}/sessions/{session_id}:logstream" + _url = "/datasets/{name}/versions/{version}/credentials" path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), - "agent_version": _SERIALIZER.url("agent_version", agent_version, "str"), - "session_id": _SERIALIZER.url("session_id", session_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), + "version": _SERIALIZER.url("version", version, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -1061,83 +1037,65 @@ def build_beta_agents_get_session_log_stream_request( # pylint: disable=name-to # Construct headers _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_upload_session_file_request( # pylint: disable=name-too-long - agent_name: str, agent_session_id: str, *, path: str, user_isolation_key: Optional[str] = None, **kwargs: Any -) -> HttpRequest: +def build_deployments_get_request(name: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: str = kwargs.pop("content_type") api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agents/{agent_name}/endpoint/sessions/{agent_session_id}/files/content" + _url = "/deployments/{name}" path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), - "agent_session_id": _SERIALIZER.url("agent_session_id", agent_session_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters - _params["path"] = _SERIALIZER.query("path", path, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") - if user_isolation_key is not None: - _headers["x-ms-user-isolation-key"] = _SERIALIZER.header("user_isolation_key", user_isolation_key, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="PUT", url=_url, params=_params, headers=_headers, **kwargs) - + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_download_session_file_request( # pylint: disable=name-too-long - agent_name: str, agent_session_id: str, *, path: str, user_isolation_key: Optional[str] = None, **kwargs: Any -) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/octet-stream") +def build_deployments_list_request( + *, + model_publisher: Optional[str] = None, + model_name: Optional[str] = None, + deployment_type: Optional[Union[str, _models.DeploymentType]] = None, + **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - # Construct URL - _url = "/agents/{agent_name}/endpoint/sessions/{agent_session_id}/files/content" - path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), - "agent_session_id": _SERIALIZER.url("agent_session_id", agent_session_id, "str"), - } + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") - _url: str = _url.format(**path_format_arguments) # type: ignore + # Construct URL + _url = "/deployments" # Construct parameters - _params["path"] = _SERIALIZER.query("path", path, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + if model_publisher is not None: + _params["modelPublisher"] = _SERIALIZER.query("model_publisher", model_publisher, "str") + if model_name is not None: + _params["modelName"] = _SERIALIZER.query("model_name", model_name, "str") + if deployment_type is not None: + _params["deploymentType"] = _SERIALIZER.query("deployment_type", deployment_type, "str") # Construct headers - if user_isolation_key is not None: - _headers["x-ms-user-isolation-key"] = _SERIALIZER.header("user_isolation_key", user_isolation_key, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_list_session_files_request( # pylint: disable=name-too-long - agent_name: str, - agent_session_id: str, - *, - path: Optional[str] = None, - user_isolation_key: Optional[str] = None, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - after: Optional[str] = None, - before: Optional[str] = None, - **kwargs: Any -) -> HttpRequest: +def build_indexes_list_versions_request(name: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -1145,109 +1103,75 @@ def build_beta_agents_list_session_files_request( # pylint: disable=name-too-lo accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agents/{agent_name}/endpoint/sessions/{agent_session_id}/files" + _url = "/indexes/{name}/versions" path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), - "agent_session_id": _SERIALIZER.url("agent_session_id", agent_session_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters - if path is not None: - _params["path"] = _SERIALIZER.query("path", path, "str") - if limit is not None: - _params["limit"] = _SERIALIZER.query("limit", limit, "int") - if order is not None: - _params["order"] = _SERIALIZER.query("order", order, "str") - if after is not None: - _params["after"] = _SERIALIZER.query("after", after, "str") - if before is not None: - _params["before"] = _SERIALIZER.query("before", before, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if user_isolation_key is not None: - _headers["x-ms-user-isolation-key"] = _SERIALIZER.header("user_isolation_key", user_isolation_key, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_delete_session_file_request( # pylint: disable=name-too-long - agent_name: str, - agent_session_id: str, - *, - path: str, - recursive: Optional[bool] = None, - user_isolation_key: Optional[str] = None, - **kwargs: Any -) -> HttpRequest: +def build_indexes_list_request(**kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - # Construct URL - _url = "/agents/{agent_name}/endpoint/sessions/{agent_session_id}/files" - path_format_arguments = { - "agent_name": _SERIALIZER.url("agent_name", agent_name, "str"), - "agent_session_id": _SERIALIZER.url("agent_session_id", agent_session_id, "str"), - } + accept = _headers.pop("Accept", "application/json") - _url: str = _url.format(**path_format_arguments) # type: ignore + # Construct URL + _url = "/indexes" # Construct parameters - _params["path"] = _SERIALIZER.query("path", path, "str") - if recursive is not None: - _params["recursive"] = _SERIALIZER.query("recursive", recursive, "bool") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if user_isolation_key is not None: - _headers["x-ms-user-isolation-key"] = _SERIALIZER.header("user_isolation_key", user_isolation_key, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="DELETE", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_create_optimization_job_request( # pylint: disable=name-too-long - *, operation_id: Optional[str] = None, **kwargs: Any -) -> HttpRequest: +def build_indexes_get_request(name: str, version: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agent_optimization_jobs" + _url = "/indexes/{name}/versions/{version}" + path_format_arguments = { + "name": _SERIALIZER.url("name", name, "str"), + "version": _SERIALIZER.url("version", version, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if operation_id is not None: - _headers["Operation-Id"] = _SERIALIZER.header("operation_id", operation_id, "str") - if content_type is not None: - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_get_optimization_job_request( # pylint: disable=name-too-long - job_id: str, **kwargs: Any -) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) +def build_indexes_delete_request(name: str, version: str, **kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - # Construct URL - _url = "/agent_optimization_jobs/{jobId}" + _url = "/indexes/{name}/versions/{version}" path_format_arguments = { - "jobId": _SERIALIZER.url("job_id", job_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), + "version": _SERIALIZER.url("version", version, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -1255,65 +1179,49 @@ def build_beta_agents_get_optimization_job_request( # pylint: disable=name-too- # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) -def build_beta_agents_list_optimization_jobs_request( # pylint: disable=name-too-long - *, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - after: Optional[str] = None, - before: Optional[str] = None, - status: Optional[Union[str, _models.JobStatus]] = None, - agent_name: Optional[str] = None, - **kwargs: Any -) -> HttpRequest: +def build_indexes_create_or_update_request(name: str, version: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agent_optimization_jobs" + _url = "/indexes/{name}/versions/{version}" + path_format_arguments = { + "name": _SERIALIZER.url("name", name, "str"), + "version": _SERIALIZER.url("version", version, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters - if limit is not None: - _params["limit"] = _SERIALIZER.query("limit", limit, "int") - if order is not None: - _params["order"] = _SERIALIZER.query("order", order, "str") - if after is not None: - _params["after"] = _SERIALIZER.query("after", after, "str") - if before is not None: - _params["before"] = _SERIALIZER.query("before", before, "str") - if status is not None: - _params["status"] = _SERIALIZER.query("status", status, "str") - if agent_name is not None: - _params["agent_name"] = _SERIALIZER.query("agent_name", agent_name, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="PATCH", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_cancel_optimization_job_request( # pylint: disable=name-too-long - job_id: str, **kwargs: Any -) -> HttpRequest: +def build_toolboxes_create_version_request(name: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agent_optimization_jobs/{jobId}:cancel" + _url = "/toolboxes/{name}/versions" path_format_arguments = { - "jobId": _SERIALIZER.url("job_id", job_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -1322,35 +1230,38 @@ def build_beta_agents_cancel_optimization_job_request( # pylint: disable=name-t _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_delete_optimization_job_request( # pylint: disable=name-too-long - job_id: str, *, force: Optional[bool] = None, **kwargs: Any -) -> HttpRequest: +def build_toolboxes_get_request(name: str, **kwargs: Any) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") + # Construct URL - _url = "/agent_optimization_jobs/{jobId}" + _url = "/toolboxes/{name}" path_format_arguments = { - "jobId": _SERIALIZER.url("job_id", job_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters - if force is not None: - _params["force"] = _SERIALIZER.query("force", force, "bool") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_list_optimization_candidates_request( # pylint: disable=name-too-long - job_id: str, +def build_toolboxes_list_request( *, limit: Optional[int] = None, order: Optional[Union[str, _models.PageOrder]] = None, @@ -1365,12 +1276,7 @@ def build_beta_agents_list_optimization_candidates_request( # pylint: disable=n accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agent_optimization_jobs/{jobId}/candidates" - path_format_arguments = { - "jobId": _SERIALIZER.url("job_id", job_id, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore + _url = "/toolboxes" # Construct parameters if limit is not None: @@ -1389,8 +1295,14 @@ def build_beta_agents_list_optimization_candidates_request( # pylint: disable=n return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_get_optimization_candidate_request( # pylint: disable=name-too-long - job_id: str, candidate_id: str, **kwargs: Any +def build_toolboxes_list_versions_request( + name: str, + *, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + after: Optional[str] = None, + before: Optional[str] = None, + **kwargs: Any ) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -1399,15 +1311,22 @@ def build_beta_agents_get_optimization_candidate_request( # pylint: disable=nam accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agent_optimization_jobs/{jobId}/candidates/{candidateId}" + _url = "/toolboxes/{name}/versions" path_format_arguments = { - "jobId": _SERIALIZER.url("job_id", job_id, "str"), - "candidateId": _SERIALIZER.url("candidate_id", candidate_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters + if limit is not None: + _params["limit"] = _SERIALIZER.query("limit", limit, "int") + if order is not None: + _params["order"] = _SERIALIZER.query("order", order, "str") + if after is not None: + _params["after"] = _SERIALIZER.query("after", after, "str") + if before is not None: + _params["before"] = _SERIALIZER.query("before", before, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers @@ -1416,9 +1335,7 @@ def build_beta_agents_get_optimization_candidate_request( # pylint: disable=nam return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_get_optimization_candidate_config_request( # pylint: disable=name-too-long - job_id: str, candidate_id: str, **kwargs: Any -) -> HttpRequest: +def build_toolboxes_get_version_request(name: str, version: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -1426,10 +1343,10 @@ def build_beta_agents_get_optimization_candidate_config_request( # pylint: disa accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agent_optimization_jobs/{jobId}/candidates/{candidateId}/config" + _url = "/toolboxes/{name}/versions/{version}" path_format_arguments = { - "jobId": _SERIALIZER.url("job_id", job_id, "str"), - "candidateId": _SERIALIZER.url("candidate_id", candidate_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), + "version": _SERIALIZER.url("version", version, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -1443,20 +1360,18 @@ def build_beta_agents_get_optimization_candidate_config_request( # pylint: disa return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_get_optimization_candidate_results_request( # pylint: disable=name-too-long - job_id: str, candidate_id: str, **kwargs: Any -) -> HttpRequest: +def build_toolboxes_update_request(name: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/agent_optimization_jobs/{jobId}/candidates/{candidateId}/results" + _url = "/toolboxes/{name}" path_format_arguments = { - "jobId": _SERIALIZER.url("job_id", job_id, "str"), - "candidateId": _SERIALIZER.url("candidate_id", candidate_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -1465,54 +1380,40 @@ def build_beta_agents_get_optimization_candidate_results_request( # pylint: dis _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="PATCH", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_agents_get_candidate_file_request( # pylint: disable=name-too-long - job_id: str, candidate_id: str, *, path: str, **kwargs: Any -) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) +def build_toolboxes_delete_request(name: str, **kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/octet-stream") - # Construct URL - _url = "/agent_optimization_jobs/{jobId}/candidates/{candidateId}/files" + _url = "/toolboxes/{name}" path_format_arguments = { - "jobId": _SERIALIZER.url("job_id", job_id, "str"), - "candidateId": _SERIALIZER.url("candidate_id", candidate_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore # Construct parameters - _params["path"] = _SERIALIZER.query("path", path, "str") _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) -def build_beta_agents_promote_candidate_request( # pylint: disable=name-too-long - job_id: str, candidate_id: str, **kwargs: Any -) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) +def build_toolboxes_delete_version_request(name: str, version: str, **kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - # Construct URL - _url = "/agent_optimization_jobs/{jobId}/candidates/{candidateId}:promote" + _url = "/toolboxes/{name}/versions/{version}" path_format_arguments = { - "jobId": _SERIALIZER.url("job_id", job_id, "str"), - "candidateId": _SERIALIZER.url("candidate_id", candidate_id, "str"), + "name": _SERIALIZER.url("name", name, "str"), + "version": _SERIALIZER.url("version", version, "str"), } _url: str = _url.format(**path_format_arguments) # type: ignore @@ -1520,12 +1421,7 @@ def build_beta_agents_promote_candidate_request( # pylint: disable=name-too-lon # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - # Construct headers - if content_type is not None: - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) def build_beta_evaluation_taxonomies_get_request( # pylint: disable=name-too-long @@ -3134,18 +3030,15 @@ def build_beta_schedules_list_runs_request( return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_toolboxes_create_version_request( # pylint: disable=name-too-long - name: str, **kwargs: Any -) -> HttpRequest: +def build_beta_skills_get_request(name: str, **kwargs: Any) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) accept = _headers.pop("Accept", "application/json") # Construct URL - _url = "/toolboxes/{name}/versions" + _url = "/skills/{name}" path_format_arguments = { "name": _SERIALIZER.url("name", name, "str"), } @@ -3156,234 +3049,19 @@ def build_beta_toolboxes_create_version_request( # pylint: disable=name-too-lon _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") # Construct headers - if content_type is not None: - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -def build_beta_toolboxes_get_request(name: str, **kwargs: Any) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - - # Construct URL - _url = "/toolboxes/{name}" - path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore - - # Construct parameters - _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) - - -def build_beta_toolboxes_list_request( - *, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - after: Optional[str] = None, - before: Optional[str] = None, - **kwargs: Any -) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - - # Construct URL - _url = "/toolboxes" - - # Construct parameters - if limit is not None: - _params["limit"] = _SERIALIZER.query("limit", limit, "int") - if order is not None: - _params["order"] = _SERIALIZER.query("order", order, "str") - if after is not None: - _params["after"] = _SERIALIZER.query("after", after, "str") - if before is not None: - _params["before"] = _SERIALIZER.query("before", before, "str") - _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) - - -def build_beta_toolboxes_list_versions_request( # pylint: disable=name-too-long - name: str, - *, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - after: Optional[str] = None, - before: Optional[str] = None, - **kwargs: Any -) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - - # Construct URL - _url = "/toolboxes/{name}/versions" - path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore - - # Construct parameters - if limit is not None: - _params["limit"] = _SERIALIZER.query("limit", limit, "int") - if order is not None: - _params["order"] = _SERIALIZER.query("order", order, "str") - if after is not None: - _params["after"] = _SERIALIZER.query("after", after, "str") - if before is not None: - _params["before"] = _SERIALIZER.query("before", before, "str") - _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) - - -def build_beta_toolboxes_get_version_request(name: str, version: str, **kwargs: Any) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - - # Construct URL - _url = "/toolboxes/{name}/versions/{version}" - path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - "version": _SERIALIZER.url("version", version, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore - - # Construct parameters - _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) - - -def build_beta_toolboxes_update_request(name: str, **kwargs: Any) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - - # Construct URL - _url = "/toolboxes/{name}" - path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore - - # Construct parameters - _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - - # Construct headers - if content_type is not None: - _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="PATCH", url=_url, params=_params, headers=_headers, **kwargs) - - -def build_beta_toolboxes_delete_request(name: str, **kwargs: Any) -> HttpRequest: - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - # Construct URL - _url = "/toolboxes/{name}" - path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore - - # Construct parameters - _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - - return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) - - -def build_beta_toolboxes_delete_version_request( # pylint: disable=name-too-long - name: str, version: str, **kwargs: Any -) -> HttpRequest: - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - # Construct URL - _url = "/toolboxes/{name}/versions/{version}" - path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - "version": _SERIALIZER.url("version", version, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore - - # Construct parameters - _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - - return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) - - -def build_beta_skills_get_request(name: str, **kwargs: Any) -> HttpRequest: - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) - accept = _headers.pop("Accept", "application/json") - - # Construct URL - _url = "/skills/{name}" - path_format_arguments = { - "name": _SERIALIZER.url("name", name, "str"), - } - - _url: str = _url.format(**path_format_arguments) # type: ignore - - # Construct parameters - _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - - # Construct headers - _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - - return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) - - -def build_beta_skills_list_request( - *, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - after: Optional[str] = None, - before: Optional[str] = None, - **kwargs: Any -) -> HttpRequest: +def build_beta_skills_list_request( + *, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + after: Optional[str] = None, + before: Optional[str] = None, + **kwargs: Any +) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) @@ -3787,40 +3465,177 @@ def build_beta_datasets_delete_generation_job_request( # pylint: disable=name-t return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) -class BetaOperations: # pylint: disable=too-many-instance-attributes - """ - .. warning:: - **DO NOT** instantiate this class directly. +def build_beta_agents_create_optimization_job_request( # pylint: disable=name-too-long + *, operation_id: Optional[str] = None, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - Instead, you should access the following operations through - :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`beta` attribute. - """ + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + # Construct URL + _url = "/agent_optimization_jobs" - self.agents = BetaAgentsOperations(self._client, self._config, self._serialize, self._deserialize) - self.evaluation_taxonomies = BetaEvaluationTaxonomiesOperations( - self._client, self._config, self._serialize, self._deserialize - ) - self.evaluators = BetaEvaluatorsOperations(self._client, self._config, self._serialize, self._deserialize) - self.insights = BetaInsightsOperations(self._client, self._config, self._serialize, self._deserialize) - self.memory_stores = BetaMemoryStoresOperations(self._client, self._config, self._serialize, self._deserialize) - self.models = BetaModelsOperations(self._client, self._config, self._serialize, self._deserialize) - self.red_teams = BetaRedTeamsOperations(self._client, self._config, self._serialize, self._deserialize) - self.routines = BetaRoutinesOperations(self._client, self._config, self._serialize, self._deserialize) - self.schedules = BetaSchedulesOperations(self._client, self._config, self._serialize, self._deserialize) - self.toolboxes = BetaToolboxesOperations(self._client, self._config, self._serialize, self._deserialize) - self.skills = BetaSkillsOperations(self._client, self._config, self._serialize, self._deserialize) - self.datasets = BetaDatasetsOperations(self._client, self._config, self._serialize, self._deserialize) + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + # Construct headers + if operation_id is not None: + _headers["Operation-Id"] = _SERIALIZER.header("operation_id", operation_id, "str") + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") -class AgentsOperations: + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_beta_agents_get_optimization_job_request( # pylint: disable=name-too-long + job_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/agent_optimization_jobs/{jobId}" + path_format_arguments = { + "jobId": _SERIALIZER.url("job_id", job_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_beta_agents_list_optimization_jobs_request( # pylint: disable=name-too-long + *, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + after: Optional[str] = None, + before: Optional[str] = None, + status: Optional[Union[str, _models.JobStatus]] = None, + agent_name: Optional[str] = None, + **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/agent_optimization_jobs" + + # Construct parameters + if limit is not None: + _params["limit"] = _SERIALIZER.query("limit", limit, "int") + if order is not None: + _params["order"] = _SERIALIZER.query("order", order, "str") + if after is not None: + _params["after"] = _SERIALIZER.query("after", after, "str") + if before is not None: + _params["before"] = _SERIALIZER.query("before", before, "str") + if status is not None: + _params["status"] = _SERIALIZER.query("status", status, "str") + if agent_name is not None: + _params["agent_name"] = _SERIALIZER.query("agent_name", agent_name, "str") + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_beta_agents_cancel_optimization_job_request( # pylint: disable=name-too-long + job_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/agent_optimization_jobs/{jobId}:cancel" + path_format_arguments = { + "jobId": _SERIALIZER.url("job_id", job_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_beta_agents_delete_optimization_job_request( # pylint: disable=name-too-long + job_id: str, **kwargs: Any +) -> HttpRequest: + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "v1")) + # Construct URL + _url = "/agent_optimization_jobs/{jobId}" + path_format_arguments = { + "jobId": _SERIALIZER.url("job_id", job_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + return HttpRequest(method="DELETE", url=_url, params=_params, **kwargs) + + +class BetaOperations: # pylint: disable=too-many-instance-attributes + """ + .. warning:: + **DO NOT** instantiate this class directly. + + Instead, you should access the following operations through + :class:`~azure.ai.projects.AIProjectClient`'s + :attr:`beta` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + + self.evaluation_taxonomies = BetaEvaluationTaxonomiesOperations( + self._client, self._config, self._serialize, self._deserialize + ) + self.evaluators = BetaEvaluatorsOperations(self._client, self._config, self._serialize, self._deserialize) + self.insights = BetaInsightsOperations(self._client, self._config, self._serialize, self._deserialize) + self.memory_stores = BetaMemoryStoresOperations(self._client, self._config, self._serialize, self._deserialize) + self.models = BetaModelsOperations(self._client, self._config, self._serialize, self._deserialize) + self.red_teams = BetaRedTeamsOperations(self._client, self._config, self._serialize, self._deserialize) + self.routines = BetaRoutinesOperations(self._client, self._config, self._serialize, self._deserialize) + self.schedules = BetaSchedulesOperations(self._client, self._config, self._serialize, self._deserialize) + self.skills = BetaSkillsOperations(self._client, self._config, self._serialize, self._deserialize) + self.datasets = BetaDatasetsOperations(self._client, self._config, self._serialize, self._deserialize) + self.agents = BetaAgentsOperations(self._client, self._config, self._serialize, self._deserialize) + + +class AgentsOperations: # pylint: disable=too-many-public-methods """ .. warning:: **DO NOT** instantiate this class directly. @@ -3839,7 +3654,9 @@ def __init__(self, *args, **kwargs) -> None: @distributed_trace def get(self, agent_name: str, **kwargs: Any) -> _models.AgentDetails: - """Retrieves the agent. + """Get an agent. + + Retrieves an agent definition by its unique name. :param agent_name: The name of the agent to retrieve. Required. :type agent_name: str @@ -3904,7 +3721,9 @@ def get(self, agent_name: str, **kwargs: Any) -> _models.AgentDetails: @distributed_trace def delete(self, agent_name: str, *, force: Optional[bool] = None, **kwargs: Any) -> _models.DeleteAgentResponse: - """Deletes an agent. For hosted agents, if any version has active sessions, the request is + """Delete an agent. + + Deletes an agent. For hosted agents, if any version has active sessions, the request is rejected with HTTP 409 unless ``force`` is set to true. When force is true, all associated sessions are cascade-deleted along with the agent and its versions. @@ -3985,7 +3804,9 @@ def list( before: Optional[str] = None, **kwargs: Any ) -> ItemPaged["_models.AgentDetails"]: - """Returns the list of all agents. + """List agents. + + Returns a paged collection of agent resources. :keyword kind: Filter agents by kind. If not provided, all agents are returned. Known values are: "prompt", "hosted", "workflow", and "external". Default value is None. @@ -4080,9 +3901,12 @@ def create_version( metadata: Optional[dict[str, str]] = None, description: Optional[str] = None, blueprint_reference: Optional[_models.AgentBlueprintReference] = None, + draft: Optional[bool] = None, **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version. + """Create an agent version. + + Creates a new version for the specified agent and returns the created version resource. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -4108,6 +3932,11 @@ def create_version( :paramtype description: str :keyword blueprint_reference: The blueprint reference for the agent. Default value is None. :paramtype blueprint_reference: ~azure.ai.projects.models.AgentBlueprintReference + :keyword draft: (Preview) Whether this agent version is a draft (candidate) rather than a + release. The service defaults to ``false`` if a value is not specified by the caller. Draft + versions are recorded but excluded from default 'latest' resolution and are not auto-promoted. + Default value is None. + :paramtype draft: bool :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping :rtype: ~azure.ai.projects.models.AgentVersionDetails :raises ~azure.core.exceptions.HttpResponseError: @@ -4117,7 +3946,9 @@ def create_version( def create_version( self, agent_name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version. + """Create an agent version. + + Creates a new version for the specified agent and returns the created version resource. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -4140,7 +3971,9 @@ def create_version( def create_version( self, agent_name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version. + """Create an agent version. + + Creates a new version for the specified agent and returns the created version resource. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -4169,9 +4002,12 @@ def create_version( metadata: Optional[dict[str, str]] = None, description: Optional[str] = None, blueprint_reference: Optional[_models.AgentBlueprintReference] = None, + draft: Optional[bool] = None, **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version. + """Create an agent version. + + Creates a new version for the specified agent and returns the created version resource. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -4196,6 +4032,11 @@ def create_version( :paramtype description: str :keyword blueprint_reference: The blueprint reference for the agent. Default value is None. :paramtype blueprint_reference: ~azure.ai.projects.models.AgentBlueprintReference + :keyword draft: (Preview) Whether this agent version is a draft (candidate) rather than a + release. The service defaults to ``false`` if a value is not specified by the caller. Draft + versions are recorded but excluded from default 'latest' resolution and are not auto-promoted. + Default value is None. + :paramtype draft: bool :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping :rtype: ~azure.ai.projects.models.AgentVersionDetails :raises ~azure.core.exceptions.HttpResponseError: @@ -4221,6 +4062,7 @@ def create_version( "blueprint_reference": blueprint_reference, "definition": definition, "description": description, + "draft": draft, "metadata": metadata, } body = {k: v for k, v in body.items() if v is not None} @@ -4287,7 +4129,9 @@ def create_version_from_manifest( description: Optional[str] = None, **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version from a manifest. + """Create an agent version from manifest. + + Imports the provided manifest to create a new version for the specified agent. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -4322,7 +4166,9 @@ def create_version_from_manifest( def create_version_from_manifest( self, agent_name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version from a manifest. + """Create an agent version from manifest. + + Imports the provided manifest to create a new version for the specified agent. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -4345,7 +4191,9 @@ def create_version_from_manifest( def create_version_from_manifest( self, agent_name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version from a manifest. + """Create an agent version from manifest. + + Imports the provided manifest to create a new version for the specified agent. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -4376,7 +4224,9 @@ def create_version_from_manifest( description: Optional[str] = None, **kwargs: Any ) -> _models.AgentVersionDetails: - """Create a new agent version from a manifest. + """Create an agent version from manifest. + + Imports the provided manifest to create a new version for the specified agent. :param agent_name: The unique name that identifies the agent. Name can be used to retrieve/update/delete the agent. @@ -4484,7 +4334,9 @@ def create_version_from_manifest( @distributed_trace def get_version(self, agent_name: str, agent_version: str, **kwargs: Any) -> _models.AgentVersionDetails: - """Retrieves a specific version of an agent. + """Get an agent version. + + Retrieves the specified version of an agent by its agent name and version identifier. :param agent_name: The name of the agent to retrieve. Required. :type agent_name: str @@ -4554,7 +4406,9 @@ def get_version(self, agent_name: str, agent_version: str, **kwargs: Any) -> _mo def delete_version( self, agent_name: str, agent_version: str, *, force: Optional[bool] = None, **kwargs: Any ) -> _models.DeleteAgentVersionResponse: - """Deletes a specific version of an agent. For hosted agents, if the version has active sessions, + """Delete an agent version. + + Deletes a specific version of an agent. For hosted agents, if the version has active sessions, the request is rejected with HTTP 409 unless ``force`` is set to true. When force is true, all sessions associated with this version are cascade-deleted. @@ -4637,9 +4491,12 @@ def list_versions( limit: Optional[int] = None, order: Optional[Union[str, _models.PageOrder]] = None, before: Optional[str] = None, + include_drafts: Optional[bool] = None, **kwargs: Any ) -> ItemPaged["_models.AgentVersionDetails"]: - """Returns the list of versions of an agent. + """List agent versions. + + Returns a paged collection of versions for the specified agent. :param agent_name: The name of the agent to retrieve versions for. Required. :type agent_name: str @@ -4657,6 +4514,10 @@ def list_versions( subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str + :keyword include_drafts: (Preview) Whether to include draft versions in the listing. The + service defaults to ``false`` if a value is not specified by the caller (only non-draft + versions are returned). Default value is None. + :paramtype include_drafts: bool :return: An iterator like instance of AgentVersionDetails :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.AgentVersionDetails] :raises ~azure.core.exceptions.HttpResponseError: @@ -4682,6 +4543,7 @@ def prepare_request(_continuation_token=None): order=order, after=_continuation_token, before=before, + include_drafts=include_drafts, api_version=self._config.api_version, headers=_headers, params=_params, @@ -4723,93 +4585,98 @@ def get_next(_continuation_token=None): return ItemPaged(get_next, extract_data) + @overload + def update_details( + self, + agent_name: str, + *, + content_type: str = "application/merge-patch+json", + agent_endpoint: Optional[_models.AgentEndpointConfig] = None, + agent_card: Optional[_models.AgentCard] = None, + **kwargs: Any + ) -> _models.AgentDetails: + """Update an agent endpoint. -class EvaluationRulesOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. + Applies a merge-patch update to the specified agent endpoint configuration. - Instead, you should access the following operations through - :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`evaluation_rules` attribute. - """ + :param agent_name: The name of the agent to retrieve. Required. + :type agent_name: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :keyword agent_endpoint: The endpoint configuration for the agent. Default value is None. + :paramtype agent_endpoint: ~azure.ai.projects.models.AgentEndpointConfig + :keyword agent_card: Optional agent card for the agent. Default value is None. + :paramtype agent_card: ~azure.ai.projects.models.AgentCard + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + @overload + def update_details( + self, agent_name: str, body: JSON, *, content_type: str = "application/merge-patch+json", **kwargs: Any + ) -> _models.AgentDetails: + """Update an agent endpoint. - @distributed_trace - def get(self, id: str, **kwargs: Any) -> _models.EvaluationRule: - """Get an evaluation rule. + Applies a merge-patch update to the specified agent endpoint configuration. - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.EvaluationRule + :param agent_name: The name of the agent to retrieve. Required. + :type agent_name: str + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails :raises ~azure.core.exceptions.HttpResponseError: """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} + @overload + def update_details( + self, agent_name: str, body: IO[bytes], *, content_type: str = "application/merge-patch+json", **kwargs: Any + ) -> _models.AgentDetails: + """Update an agent endpoint. - cls: ClsType[_models.EvaluationRule] = kwargs.pop("cls", None) + Applies a merge-patch update to the specified agent endpoint configuration. - _request = build_evaluation_rules_get_request( - id=id, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - - response = pipeline_response.http_response - - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.EvaluationRule, response.json()) - - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore - - return deserialized # type: ignore + :param agent_name: The name of the agent to retrieve. Required. + :type agent_name: str + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace - def delete(self, id: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements - """Delete an evaluation rule. + def update_details( + self, + agent_name: str, + body: Union[JSON, IO[bytes]] = _Unset, + *, + agent_endpoint: Optional[_models.AgentEndpointConfig] = None, + agent_card: Optional[_models.AgentCard] = None, + **kwargs: Any + ) -> _models.AgentDetails: + """Update an agent endpoint. - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :return: None - :rtype: None + Applies a merge-patch update to the specified agent endpoint configuration. + + :param agent_name: The name of the agent to retrieve. Required. + :type agent_name: str + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword agent_endpoint: The endpoint configuration for the agent. Default value is None. + :paramtype agent_endpoint: ~azure.ai.projects.models.AgentEndpointConfig + :keyword agent_card: Optional agent card for the agent. Default value is None. + :paramtype agent_card: ~azure.ai.projects.models.AgentCard + :return: AgentDetails. The AgentDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentDetails :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -4820,14 +4687,27 @@ def delete(self, id: str, **kwargs: Any) -> None: # pylint: disable=inconsisten } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.AgentDetails] = kwargs.pop("cls", None) - _request = build_evaluation_rules_delete_request( - id=id, + if body is _Unset: + body = {"agent_card": agent_card, "agent_endpoint": agent_endpoint} + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/merge-patch+json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_agents_update_details_request( + agent_name=agent_name, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -4836,87 +4716,128 @@ def delete(self, id: str, **kwargs: Any) -> None: # pylint: disable=inconsisten } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.AgentDetails, response.json()) if cls: - return cls(pipeline_response, None, {}) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore @overload - def create_or_update( - self, id: str, evaluation_rule: _models.EvaluationRule, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.EvaluationRule: - """Create or update an evaluation rule. + def create_version_from_code( + self, + agent_name: str, + content: _models.CreateAgentVersionFromCodeContent, + *, + code_zip_sha256: str, + **kwargs: Any + ) -> _models.AgentVersionDetails: + """Create an agent version from code. - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :param evaluation_rule: Evaluation rule resource. Required. - :type evaluation_rule: ~azure.ai.projects.models.EvaluationRule - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.EvaluationRule - :raises ~azure.core.exceptions.HttpResponseError: - """ + Creates a new agent version from code. Uploads the code zip and creates a new version for an + existing agent. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. - @overload - def create_or_update( - self, id: str, evaluation_rule: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.EvaluationRule: - """Create or update an evaluation rule. + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :param evaluation_rule: Evaluation rule resource. Required. - :type evaluation_rule: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.EvaluationRule + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param content: Required. + :type content: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails :raises ~azure.core.exceptions.HttpResponseError: """ @overload - def create_or_update( - self, id: str, evaluation_rule: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.EvaluationRule: - """Create or update an evaluation rule. + def create_version_from_code( + self, agent_name: str, content: JSON, *, code_zip_sha256: str, **kwargs: Any + ) -> _models.AgentVersionDetails: + """Create an agent version from code. - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :param evaluation_rule: Evaluation rule resource. Required. - :type evaluation_rule: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.EvaluationRule + Creates a new agent version from code. Uploads the code zip and creates a new version for an + existing agent. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param content: Required. + :type content: JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails :raises ~azure.core.exceptions.HttpResponseError: """ @distributed_trace - def create_or_update( - self, id: str, evaluation_rule: Union[_models.EvaluationRule, JSON, IO[bytes]], **kwargs: Any - ) -> _models.EvaluationRule: - """Create or update an evaluation rule. + def create_version_from_code( + self, + agent_name: str, + content: Union[_models.CreateAgentVersionFromCodeContent, JSON], + *, + code_zip_sha256: str, + **kwargs: Any + ) -> _models.AgentVersionDetails: + """Create an agent version from code. - :param id: Unique identifier for the evaluation rule. Required. - :type id: str - :param evaluation_rule: Evaluation rule resource. Is one of the following types: - EvaluationRule, JSON, IO[bytes] Required. - :type evaluation_rule: ~azure.ai.projects.models.EvaluationRule or JSON or IO[bytes] - :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.EvaluationRule + Creates a new agent version from code. Uploads the code zip and creates a new version for an + existing agent. The SHA-256 hex digest of the zip is provided in the ``x-ms-code-zip-sha256`` + header for integrity and dedup. The request body is multipart/form-data with a JSON metadata + part and a binary code part (part order is irrelevant). Maximum upload size is 250 MB. + + :param agent_name: The unique name that identifies the agent. Name can be used to + retrieve/update/delete the agent. + + * Must start and end with alphanumeric characters, + * Can contain hyphens in the middle + * Must not exceed 63 characters. Required. + :type agent_name: str + :param content: Is either a CreateAgentVersionFromCodeContent type or a JSON type. Required. + :type content: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent or JSON + :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change + detection (dedup) and integrity verification. Required. + :paramtype code_zip_sha256: str + :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentVersionDetails :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -4927,24 +4848,21 @@ def create_or_update( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.EvaluationRule] = kwargs.pop("cls", None) + cls: ClsType[_models.AgentVersionDetails] = kwargs.pop("cls", None) - content_type = content_type or "application/json" - _content = None - if isinstance(evaluation_rule, (IOBase, bytes)): - _content = evaluation_rule - else: - _content = json.dumps(evaluation_rule, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + _body = content.as_dict() if isinstance(content, _Model) else content + _file_fields: list[str] = ["code"] + _data_fields: list[str] = ["metadata"] + _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) - _request = build_evaluation_rules_create_or_update_request( - id=id, - content_type=content_type, + _request = build_agents_create_version_from_code_request( + agent_name=agent_name, + code_zip_sha256=code_zip_sha256, api_version=self._config.api_version, - content=_content, + files=_files, headers=_headers, params=_params, ) @@ -4961,19 +4879,23 @@ def create_or_update( response = pipeline_response.http_response - if response.status_code not in [200, 201]: + if response.status_code not in [200]: if _stream: try: response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.EvaluationRule, response.json()) + deserialized = _deserialize(_models.AgentVersionDetails, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -4981,136 +4903,27 @@ def create_or_update( return deserialized # type: ignore @distributed_trace - def list( - self, - *, - action_type: Optional[Union[str, _models.EvaluationRuleActionType]] = None, - agent_name: Optional[str] = None, - enabled: Optional[bool] = None, - **kwargs: Any - ) -> ItemPaged["_models.EvaluationRule"]: - """List all evaluation rules. + def download_code_as_bytes( + self, agent_name: str, *, agent_version: Optional[str] = None, **kwargs: Any + ) -> Iterator[bytes]: + """Download agent code. - :keyword action_type: Filter by the type of evaluation rule. Known values are: - "continuousEvaluation" and "humanEvaluationPreview". Default value is None. - :paramtype action_type: str or ~azure.ai.projects.models.EvaluationRuleActionType - :keyword agent_name: Filter by the agent name. Default value is None. - :paramtype agent_name: str - :keyword enabled: Filter by the enabled status. Default value is None. - :paramtype enabled: bool - :return: An iterator like instance of EvaluationRule - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.EvaluationRule] - :raises ~azure.core.exceptions.HttpResponseError: - """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.EvaluationRule]] = kwargs.pop("cls", None) - - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(next_link=None): - if not next_link: - - _request = build_evaluation_rules_list_request( - action_type=action_type, - agent_name=agent_name, - enabled=enabled, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - return _request - - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.EvaluationRule], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, iter(list_of_elem) - - def get_next(next_link=None): - _request = prepare_request(next_link) - - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - return pipeline_response - - return ItemPaged(get_next, extract_data) - - -class ConnectionsOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. - - Instead, you should access the following operations through - :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`connections` attribute. - """ + Downloads the code zip for a code-based hosted agent. + Returns the previously-uploaded zip (``application/zip``). - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + If ``agent_version`` is supplied, returns that version's code zip; otherwise + returns the latest version's code zip. - @distributed_trace - def _get(self, name: str, **kwargs: Any) -> _models.Connection: - """Get a connection by name, without populating connection credentials. + The SHA-256 digest of the returned bytes matches the ``content_hash`` on the + resolved version's ``code_configuration``. - :param name: The friendly name of the connection, provided by the user. Required. - :type name: str - :return: Connection. The Connection is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Connection + :param agent_name: The name of the agent. Required. + :type agent_name: str + :keyword agent_version: The version of the agent whose code zip should be downloaded. + If omitted, the latest version's code zip is returned. Default value is None. + :paramtype agent_version: str + :return: Iterator[bytes] + :rtype: Iterator[bytes] :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -5124,10 +4937,11 @@ def _get(self, name: str, **kwargs: Any) -> _models.Connection: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.Connection] = kwargs.pop("cls", None) + cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) - _request = build_connections_get_request( - name=name, + _request = build_agents_download_code_as_bytes_request( + agent_name=agent_name, + agent_version=agent_version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -5138,7 +4952,7 @@ def _get(self, name: str, **kwargs: Any) -> _models.Connection: _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = kwargs.pop("stream", True) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -5152,17 +4966,17 @@ def _get(self, name: str, **kwargs: Any) -> _models.Connection: except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) response_headers = {} - response_headers["x-ms-client-request-id"] = self._deserialize( - "str", response.headers.get("x-ms-client-request-id") - ) + response_headers["x-ms-agent-version"] = self._deserialize("str", response.headers.get("x-ms-agent-version")) + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.Connection, response.json()) + deserialized = response.iter_bytes() if _decompress else response.iter_raw() if cls: return cls(pipeline_response, deserialized, response_headers) # type: ignore @@ -5170,13 +4984,17 @@ def _get(self, name: str, **kwargs: Any) -> _models.Connection: return deserialized # type: ignore @distributed_trace - def _get_with_credentials(self, name: str, **kwargs: Any) -> _models.Connection: - """Get a connection by name, with its connection credentials. + def enable(self, agent_name: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements + """Enable an agent. - :param name: The friendly name of the connection, provided by the user. Required. - :type name: str - :return: Connection. The Connection is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Connection + Enables the specified agent, allowing it to accept new sessions and process requests. This + operation is idempotent — enabling an already-enabled agent returns success with no side + effects. + + :param agent_name: The name of the agent to enable. Required. + :type agent_name: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -5190,10 +5008,10 @@ def _get_with_credentials(self, name: str, **kwargs: Any) -> _models.Connection: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.Connection] = kwargs.pop("cls", None) + cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_connections_get_with_credentials_request( - name=name, + _request = build_agents_enable_request( + agent_name=agent_name, api_version=self._config.api_version, headers=_headers, params=_params, @@ -5203,64 +5021,39 @@ def _get_with_credentials(self, name: str, **kwargs: Any) -> _models.Connection: } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = False pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass + if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - response_headers = {} - response_headers["x-ms-client-request-id"] = self._deserialize( - "str", response.headers.get("x-ms-client-request-id") - ) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.Connection, response.json()) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore - - return deserialized # type: ignore + return cls(pipeline_response, None, {}) # type: ignore @distributed_trace - def list( - self, - *, - connection_type: Optional[Union[str, _models.ConnectionType]] = None, - default_connection: Optional[bool] = None, - **kwargs: Any - ) -> ItemPaged["_models.Connection"]: - """List all connections in the project, without populating connection credentials. + def disable(self, agent_name: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements + """Disable an agent. - :keyword connection_type: List connections of this specific type. Known values are: - "AzureOpenAI", "AzureBlob", "AzureStorageAccount", "CognitiveSearch", "CosmosDB", "ApiKey", - "AppConfig", "AppInsights", "CustomKeys", and "RemoteTool_Preview". Default value is None. - :paramtype connection_type: str or ~azure.ai.projects.models.ConnectionType - :keyword default_connection: List connections that are default connections. Default value is - None. - :paramtype default_connection: bool - :return: An iterator like instance of Connection - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.Connection] + Disables the specified agent, preventing it from accepting new sessions or processing requests. + Existing active sessions are allowed to drain gracefully but no new sessions can be created. + This operation is idempotent — disabling an already-disabled agent returns success with no side + effects. + + :param agent_name: The name of the agent to disable. Required. + :type agent_name: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.Connection]] = kwargs.pop("cls", None) - error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -5269,108 +5062,144 @@ def list( } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(next_link=None): - if not next_link: - - _request = build_connections_list_request( - connection_type=connection_type, - default_connection=default_connection, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - return _request + cls: ClsType[None] = kwargs.pop("cls", None) - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.Connection], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, iter(list_of_elem) + _request = build_agents_disable_request( + agent_name=agent_name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - def get_next(next_link=None): - _request = prepare_request(next_link) + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, ) - response = pipeline_response.http_response + raise HttpResponseError(response=response, model=error) - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + if cls: + return cls(pipeline_response, None, {}) # type: ignore - return pipeline_response + @overload + def create_session( + self, + agent_name: str, + *, + version_indicator: _models.VersionIndicator, + content_type: str = "application/json", + agent_session_id: Optional[str] = None, + **kwargs: Any + ) -> _models.AgentSessionResource: + """Create a session. - return ItemPaged(get_next, extract_data) + Creates a new session for an agent endpoint. The endpoint resolves the backing agent version + from ``version_indicator`` and enforces session ownership using the provided isolation key for + session-mutating operations. + + :param agent_name: The name of the agent to create a session for. Required. + :type agent_name: str + :keyword version_indicator: Determines which agent version backs the session. Required. + :paramtype version_indicator: ~azure.ai.projects.models.VersionIndicator + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword agent_session_id: Optional caller-provided session ID. If specified, it must be unique + within the agent endpoint. Auto-generated if omitted. Default value is None. + :paramtype agent_session_id: str + :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentSessionResource + :raises ~azure.core.exceptions.HttpResponseError: + """ + @overload + def create_session( + self, agent_name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AgentSessionResource: + """Create a session. -class DatasetsOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. + Creates a new session for an agent endpoint. The endpoint resolves the backing agent version + from ``version_indicator`` and enforces session ownership using the provided isolation key for + session-mutating operations. - Instead, you should access the following operations through - :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`datasets` attribute. - """ + :param agent_name: The name of the agent to create a session for. Required. + :type agent_name: str + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentSessionResource + :raises ~azure.core.exceptions.HttpResponseError: + """ - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + @overload + def create_session( + self, agent_name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AgentSessionResource: + """Create a session. - @distributed_trace - def list_versions(self, name: str, **kwargs: Any) -> ItemPaged["_models.DatasetVersion"]: - """List all versions of the given DatasetVersion. + Creates a new session for an agent endpoint. The endpoint resolves the backing agent version + from ``version_indicator`` and enforces session ownership using the provided isolation key for + session-mutating operations. - :param name: The name of the resource. Required. - :type name: str - :return: An iterator like instance of DatasetVersion - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.DatasetVersion] + :param agent_name: The name of the agent to create a session for. Required. + :type agent_name: str + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentSessionResource :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.DatasetVersion]] = kwargs.pop("cls", None) + @distributed_trace + def create_session( + self, + agent_name: str, + body: Union[JSON, IO[bytes]] = _Unset, + *, + version_indicator: _models.VersionIndicator = _Unset, + agent_session_id: Optional[str] = None, + **kwargs: Any + ) -> _models.AgentSessionResource: + """Create a session. + + Creates a new session for an agent endpoint. The endpoint resolves the backing agent version + from ``version_indicator`` and enforces session ownership using the provided isolation key for + session-mutating operations. + :param agent_name: The name of the agent to create a session for. Required. + :type agent_name: str + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword version_indicator: Determines which agent version backs the session. Required. + :paramtype version_indicator: ~azure.ai.projects.models.VersionIndicator + :keyword agent_session_id: Optional caller-provided session ID. If specified, it must be unique + within the agent endpoint. Auto-generated if omitted. Default value is None. + :paramtype agent_session_id: str + :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentSessionResource + :raises ~azure.core.exceptions.HttpResponseError: + """ error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -5379,173 +5208,80 @@ def list_versions(self, name: str, **kwargs: Any) -> ItemPaged["_models.DatasetV } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(next_link=None): - if not next_link: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} - _request = build_datasets_list_versions_request( - name=name, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.AgentSessionResource] = kwargs.pop("cls", None) - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + if body is _Unset: + if version_indicator is _Unset: + raise TypeError("missing required argument: version_indicator") + body = {"agent_session_id": agent_session_id, "version_indicator": version_indicator} + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - return _request + _request = build_agents_create_session_request( + agent_name=agent_name, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.DatasetVersion], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, iter(list_of_elem) + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) - def get_next(next_link=None): - _request = prepare_request(next_link) + response = pipeline_response.http_response - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs + if response.status_code not in [201]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, ) - response = pipeline_response.http_response + raise HttpResponseError(response=response, model=error) - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.AgentSessionResource, response.json()) - return pipeline_response + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore - return ItemPaged(get_next, extract_data) + return deserialized # type: ignore @distributed_trace - def list(self, **kwargs: Any) -> ItemPaged["_models.DatasetVersion"]: - """List the latest version of each DatasetVersion. - - :return: An iterator like instance of DatasetVersion - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.DatasetVersion] - :raises ~azure.core.exceptions.HttpResponseError: - """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.DatasetVersion]] = kwargs.pop("cls", None) - - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(next_link=None): - if not next_link: - - _request = build_datasets_list_request( - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - return _request - - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.DatasetVersion], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, iter(list_of_elem) - - def get_next(next_link=None): - _request = prepare_request(next_link) - - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - return pipeline_response + def get_session(self, agent_name: str, session_id: str, **kwargs: Any) -> _models.AgentSessionResource: + """Get a session. - return ItemPaged(get_next, extract_data) - - @distributed_trace - def get(self, name: str, version: str, **kwargs: Any) -> _models.DatasetVersion: - """Get the specific version of the DatasetVersion. The service returns 404 Not Found error if the - DatasetVersion does not exist. + Retrieves the details of a hosted agent session by agent name and session identifier. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to retrieve. Required. - :type version: str - :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetVersion + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session identifier. Required. + :type session_id: str + :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.AgentSessionResource :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -5559,11 +5295,11 @@ def get(self, name: str, version: str, **kwargs: Any) -> _models.DatasetVersion: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DatasetVersion] = kwargs.pop("cls", None) + cls: ClsType[_models.AgentSessionResource] = kwargs.pop("cls", None) - _request = build_datasets_get_request( - name=name, - version=version, + _request = build_agents_get_session_request( + agent_name=agent_name, + session_id=session_id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -5588,12 +5324,16 @@ def get(self, name: str, version: str, **kwargs: Any) -> _models.DatasetVersion: except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.DatasetVersion, response.json()) + deserialized = _deserialize(_models.AgentSessionResource, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -5601,14 +5341,18 @@ def get(self, name: str, version: str, **kwargs: Any) -> _models.DatasetVersion: return deserialized # type: ignore @distributed_trace - def delete(self, name: str, version: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements - """Delete the specific version of the DatasetVersion. The service returns 204 No Content if the - DatasetVersion was deleted successfully or if the DatasetVersion does not exist. + def delete_session( # pylint: disable=inconsistent-return-statements + self, agent_name: str, session_id: str, **kwargs: Any + ) -> None: + """Delete a session. - :param name: The name of the resource. Required. - :type name: str - :param version: The version of the DatasetVersion to delete. Required. - :type version: str + Deletes a session synchronously. Returns 204 No Content when the session is deleted or does not + exist. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session identifier. Required. + :type session_id: str :return: None :rtype: None :raises ~azure.core.exceptions.HttpResponseError: @@ -5626,9 +5370,9 @@ def delete(self, name: str, version: str, **kwargs: Any) -> None: # pylint: dis cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_datasets_delete_request( - name=name, - version=version, + _request = build_agents_delete_session_request( + agent_name=agent_name, + session_id=session_id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -5647,104 +5391,30 @@ def delete(self, name: str, version: str, **kwargs: Any) -> None: # pylint: dis if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) if cls: return cls(pipeline_response, None, {}) # type: ignore - @overload - def create_or_update( - self, - name: str, - version: str, - dataset_version: _models.DatasetVersion, - *, - content_type: str = "application/merge-patch+json", - **kwargs: Any - ) -> _models.DatasetVersion: - """Create a new or update an existing DatasetVersion with the given version id. - - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to create or update. Required. - :type version: str - :param dataset_version: The DatasetVersion to create or update. Required. - :type dataset_version: ~azure.ai.projects.models.DatasetVersion - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - def create_or_update( - self, - name: str, - version: str, - dataset_version: JSON, - *, - content_type: str = "application/merge-patch+json", - **kwargs: Any - ) -> _models.DatasetVersion: - """Create a new or update an existing DatasetVersion with the given version id. - - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to create or update. Required. - :type version: str - :param dataset_version: The DatasetVersion to create or update. Required. - :type dataset_version: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - def create_or_update( - self, - name: str, - version: str, - dataset_version: IO[bytes], - *, - content_type: str = "application/merge-patch+json", - **kwargs: Any - ) -> _models.DatasetVersion: - """Create a new or update an existing DatasetVersion with the given version id. - - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to create or update. Required. - :type version: str - :param dataset_version: The DatasetVersion to create or update. Required. - :type dataset_version: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ - @distributed_trace - def create_or_update( - self, name: str, version: str, dataset_version: Union[_models.DatasetVersion, JSON, IO[bytes]], **kwargs: Any - ) -> _models.DatasetVersion: - """Create a new or update an existing DatasetVersion with the given version id. + def stop_session( # pylint: disable=inconsistent-return-statements + self, agent_name: str, session_id: str, **kwargs: Any + ) -> None: + """Stop a session. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to create or update. Required. - :type version: str - :param dataset_version: The DatasetVersion to create or update. Is one of the following types: - DatasetVersion, JSON, IO[bytes] Required. - :type dataset_version: ~azure.ai.projects.models.DatasetVersion or JSON or IO[bytes] - :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetVersion + Terminates the specified hosted agent session and returns 204 No Content when the request + succeeds. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session identifier. Required. + :type session_id: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -5755,25 +5425,15 @@ def create_or_update( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.DatasetVersion] = kwargs.pop("cls", None) - - content_type = content_type or "application/merge-patch+json" - _content = None - if isinstance(dataset_version, (IOBase, bytes)): - _content = dataset_version - else: - _content = json.dumps(dataset_version, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_datasets_create_or_update_request( - name=name, - version=version, - content_type=content_type, - api_version=self._config.api_version, - content=_content, + _request = build_agents_stop_session_request( + agent_name=agent_name, + session_id=session_id, + api_version=self._config.api_version, headers=_headers, params=_params, ) @@ -5782,131 +5442,161 @@ def create_or_update( } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = False pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200, 201]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass + if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.DatasetVersion, response.json()) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore - - return deserialized # type: ignore + return cls(pipeline_response, None, {}) # type: ignore - @overload - def pending_upload( + @distributed_trace + def list_sessions( self, - name: str, - version: str, - pending_upload_request: _models.PendingUploadRequest, + agent_name: str, *, - content_type: str = "application/json", + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + before: Optional[str] = None, **kwargs: Any - ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of a dataset for a specific version. + ) -> ItemPaged["_models.AgentSessionResource"]: + """List sessions for an agent. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to operate on. Required. - :type version: str - :param pending_upload_request: The pending upload request parameters. Required. - :type pending_upload_request: ~azure.ai.projects.models.PendingUploadRequest - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.PendingUploadResponse + Returns a paged collection of sessions associated with the specified agent endpoint. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the + default is 20. Default value is None. + :paramtype limit: int + :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for + ascending order and``desc`` + for descending order. Known values are: "asc" and "desc". Default value is None. + :paramtype order: str or ~azure.ai.projects.models.PageOrder + :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your + place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + Default value is None. + :paramtype before: str + :return: An iterator like instance of AgentSessionResource + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.AgentSessionResource] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - @overload - def pending_upload( - self, - name: str, - version: str, - pending_upload_request: JSON, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of a dataset for a specific version. + cls: ClsType[List[_models.AgentSessionResource]] = kwargs.pop("cls", None) - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to operate on. Required. - :type version: str - :param pending_upload_request: The pending upload request parameters. Required. - :type pending_upload_request: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.PendingUploadResponse - :raises ~azure.core.exceptions.HttpResponseError: - """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) - @overload - def pending_upload( - self, - name: str, - version: str, - pending_upload_request: IO[bytes], - *, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of a dataset for a specific version. + def prepare_request(_continuation_token=None): - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to operate on. Required. - :type version: str - :param pending_upload_request: The pending upload request parameters. Required. - :type pending_upload_request: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.PendingUploadResponse - :raises ~azure.core.exceptions.HttpResponseError: - """ + _request = build_agents_list_sessions_request( + agent_name=agent_name, + limit=limit, + order=order, + after=_continuation_token, + before=before, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.AgentSessionResource], + deserialized.get("data", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("last_id") or None, iter(list_of_elem) + + def get_next(_continuation_token=None): + _request = prepare_request(_continuation_token) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + return pipeline_response + + return ItemPaged(get_next, extract_data) @distributed_trace - def pending_upload( - self, - name: str, - version: str, - pending_upload_request: Union[_models.PendingUploadRequest, JSON, IO[bytes]], - **kwargs: Any - ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of a dataset for a specific version. + def get_session_log_stream( + self, agent_name: str, agent_version: str, session_id: str, **kwargs: Any + ) -> _models.SessionLogEvent: + """Stream console logs for a hosted agent session. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to operate on. Required. - :type version: str - :param pending_upload_request: The pending upload request parameters. Is one of the following - types: PendingUploadRequest, JSON, IO[bytes] Required. - :type pending_upload_request: ~azure.ai.projects.models.PendingUploadRequest or JSON or - IO[bytes] - :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.PendingUploadResponse + Streams console logs (stdout / stderr) for a specific hosted agent session + as a Server-Sent Events (SSE) stream. + + Each SSE frame contains: + + * `event`: always `"log"` + * `data`: a plain-text log line (currently JSON-formatted, but the schema is not contractual and may include additional keys or change format over time; clients should treat it as an opaque string) + + Example SSE frames: + + .. code-block:: + + event: log + data: {"timestamp":"2026-03-10T09:33:17.121Z","stream":"stdout","message":"Starting FoundryCBAgent server on port 8088"} + + event: log + data: {"timestamp":"2026-03-10T09:33:17.130Z","stream":"stderr","message":"INFO: Application startup complete."} + + event: log + data: {"timestamp":"2026-03-10T09:34:52.714Z","stream":"status","message":"Successfully connected to container"} + + event: log + data: {"timestamp":"2026-03-10T09:35:52.714Z","stream":"status","message":"No logs since last 60 seconds"} + + The stream remains open until the client disconnects or the server + terminates the connection. Clients should handle reconnection as needed. + + :param agent_name: The name of the hosted agent. Required. + :type agent_name: str + :param agent_version: The version of the agent. Required. + :type agent_version: str + :param session_id: The session ID (maps to an ADC sandbox). Required. + :type session_id: str + :return: SessionLogEvent. The SessionLogEvent is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SessionLogEvent :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -5917,25 +5607,16 @@ def pending_upload( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.PendingUploadResponse] = kwargs.pop("cls", None) - - content_type = content_type or "application/json" - _content = None - if isinstance(pending_upload_request, (IOBase, bytes)): - _content = pending_upload_request - else: - _content = json.dumps(pending_upload_request, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[_models.SessionLogEvent] = kwargs.pop("cls", None) - _request = build_datasets_pending_upload_request( - name=name, - version=version, - content_type=content_type, + _request = build_agents_get_session_log_stream_request( + agent_name=agent_name, + agent_version=agent_version, + session_id=session_id, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -5945,7 +5626,7 @@ def pending_upload( _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = True pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -5959,28 +5640,45 @@ def pending_upload( except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.PendingUploadResponse, response.json()) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.SessionLogEvent, response.text()) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore @distributed_trace - def get_credentials(self, name: str, version: str, **kwargs: Any) -> _models.DatasetCredential: - """Get the SAS credential to access the storage account associated with a Dataset version. + def _upload_session_file( + self, agent_name: str, agent_session_id: str, content: bytes, *, remote_path: str, **kwargs: Any + ) -> _models.SessionFileWriteResult: + """Upload a session file. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the DatasetVersion to operate on. Required. - :type version: str - :return: DatasetCredential. The DatasetCredential is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DatasetCredential + Uploads binary file content to the specified path in the session sandbox. The service stores + the file relative to the session home directory and rejects payloads larger than 50 MB. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param agent_session_id: The session ID. Required. + :type agent_session_id: str + :param content: Required. + :type content: bytes + :keyword remote_path: The destination file path within the sandbox, relative to the session + home directory. Required. + :paramtype remote_path: str + :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SessionFileWriteResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -5991,15 +5689,21 @@ def get_credentials(self, name: str, version: str, **kwargs: Any) -> _models.Dat } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DatasetCredential] = kwargs.pop("cls", None) + content_type: str = kwargs.pop("content_type", _headers.pop("Content-Type", "application/octet-stream")) + cls: ClsType[_models.SessionFileWriteResult] = kwargs.pop("cls", None) - _request = build_datasets_get_credentials_request( - name=name, - version=version, + _content = content + + _request = build_agents_upload_session_file_request( + agent_name=agent_name, + agent_session_id=agent_session_id, + remote_path=remote_path, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -6016,51 +5720,47 @@ def get_credentials(self, name: str, version: str, **kwargs: Any) -> _models.Dat response = pipeline_response.http_response - if response.status_code not in [200]: + if response.status_code not in [201]: if _stream: try: response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.DatasetCredential, response.json()) + deserialized = _deserialize(_models.SessionFileWriteResult, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - -class DeploymentsOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. - - Instead, you should access the following operations through - :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`deployments` attribute. - """ - - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") - @distributed_trace - def get(self, name: str, **kwargs: Any) -> _models.Deployment: - """Get a deployed model. + def download_session_file_as_bytes( + self, agent_name: str, agent_session_id: str, *, remote_path: str, **kwargs: Any + ) -> Iterator[bytes]: + """Download a session file. - :param name: Name of the deployment. Required. - :type name: str - :return: Deployment. The Deployment is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Deployment + Downloads the file at the specified sandbox path as a binary stream. The path is resolved + relative to the session home directory. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param agent_session_id: The session ID. Required. + :type agent_session_id: str + :keyword remote_path: The file path to download from the sandbox, relative to the session home + directory. Required. + :paramtype remote_path: str + :return: Iterator[bytes] + :rtype: Iterator[bytes] :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -6074,10 +5774,12 @@ def get(self, name: str, **kwargs: Any) -> _models.Deployment: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.Deployment] = kwargs.pop("cls", None) + cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) - _request = build_deployments_get_request( - name=name, + _request = build_agents_download_session_file_as_bytes_request( + agent_name=agent_name, + agent_session_id=agent_session_id, + remote_path=remote_path, api_version=self._config.api_version, headers=_headers, params=_params, @@ -6088,7 +5790,7 @@ def get(self, name: str, **kwargs: Any) -> _models.Deployment: _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = kwargs.pop("stream", True) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -6102,50 +5804,66 @@ def get(self, name: str, **kwargs: Any) -> _models.Deployment: except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - response_headers = {} - response_headers["x-ms-client-request-id"] = self._deserialize( - "str", response.headers.get("x-ms-client-request-id") - ) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.Deployment, response.json()) + deserialized = response.iter_bytes() if _decompress else response.iter_raw() if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore @distributed_trace - def list( + def list_session_files( self, + agent_name: str, + agent_session_id: str, *, - model_publisher: Optional[str] = None, - model_name: Optional[str] = None, - deployment_type: Optional[Union[str, _models.DeploymentType]] = None, + remote_path: Optional[str] = None, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + before: Optional[str] = None, **kwargs: Any - ) -> ItemPaged["_models.Deployment"]: - """List all deployed models in the project. + ) -> ItemPaged["_models.SessionDirectoryEntry"]: + """List session files. - :keyword model_publisher: Model publisher to filter models by. Default value is None. - :paramtype model_publisher: str - :keyword model_name: Model name (the publisher specific name) to filter models by. Default - value is None. - :paramtype model_name: str - :keyword deployment_type: Type of deployment to filter list by. "ModelDeployment" Default value - is None. - :paramtype deployment_type: str or ~azure.ai.projects.models.DeploymentType - :return: An iterator like instance of Deployment - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.Deployment] + Returns files and directories at the specified path in the session sandbox. The response + includes only the immediate children of the target directory and defaults to the session home + directory when no path is supplied. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param agent_session_id: The session ID. Required. + :type agent_session_id: str + :keyword remote_path: The directory path to list, relative to the session home directory. + Defaults to the home directory if not provided. Default value is None. + :paramtype remote_path: str + :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the + default is 20. Default value is None. + :paramtype limit: int + :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for + ascending order and``desc`` + for descending order. Known values are: "asc" and "desc". Default value is None. + :paramtype order: str or ~azure.ai.projects.models.PageOrder + :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your + place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + Default value is None. + :paramtype before: str + :return: An iterator like instance of SessionDirectoryEntry + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.SessionDirectoryEntry] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.Deployment]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.SessionDirectoryEntry]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -6155,61 +5873,38 @@ def list( } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(next_link=None): - if not next_link: - - _request = build_deployments_list_request( - model_publisher=model_publisher, - model_name=model_name, - deployment_type=deployment_type, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + def prepare_request(_continuation_token=None): + _request = build_agents_list_session_files_request( + agent_name=agent_name, + agent_session_id=agent_session_id, + remote_path=remote_path, + limit=limit, + order=order, + after=_continuation_token, + before=before, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) return _request def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.Deployment], - deserialized.get("value", []), + List[_models.SessionDirectoryEntry], + deserialized.get("entries", []), ) if cls: list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, iter(list_of_elem) + return deserialized.get("last_id") or None, iter(list_of_elem) - def get_next(next_link=None): - _request = prepare_request(next_link) + def get_next(_continuation_token=None): + _request = prepare_request(_continuation_token) _stream = False pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access @@ -6219,45 +5914,45 @@ def get_next(next_link=None): if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) return pipeline_response return ItemPaged(get_next, extract_data) + @distributed_trace + def delete_session_file( # pylint: disable=inconsistent-return-statements + self, + agent_name: str, + agent_session_id: str, + *, + remote_path: str, + recursive: Optional[bool] = None, + **kwargs: Any + ) -> None: + """Delete a session file. -class IndexesOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. - - Instead, you should access the following operations through - :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`indexes` attribute. - """ + Deletes the specified file or directory from the session sandbox. When ``recursive`` is false, + deleting a non-empty directory returns 409 Conflict. - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") - - @distributed_trace - def list_versions(self, name: str, **kwargs: Any) -> ItemPaged["_models.Index"]: - """List all versions of the given Index. - - :param name: The name of the resource. Required. - :type name: str - :return: An iterator like instance of Index - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.Index] + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param agent_session_id: The session ID. Required. + :type agent_session_id: str + :keyword remote_path: The file or directory path to delete, relative to the session home + directory. Required. + :paramtype remote_path: str + :keyword recursive: Whether to recursively delete directory contents. The service defaults to + ``false`` if a value is not specified by the caller. Default value is None. + :paramtype recursive: bool + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.Index]] = kwargs.pop("cls", None) - error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -6266,173 +5961,71 @@ def list_versions(self, name: str, **kwargs: Any) -> ItemPaged["_models.Index"]: } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(next_link=None): - if not next_link: - - _request = build_indexes_list_versions_request( - name=name, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - return _request - - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.Index], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, iter(list_of_elem) - - def get_next(next_link=None): - _request = prepare_request(next_link) - - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - return pipeline_response - - return ItemPaged(get_next, extract_data) - - @distributed_trace - def list(self, **kwargs: Any) -> ItemPaged["_models.Index"]: - """List the latest version of each Index. - - :return: An iterator like instance of Index - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.Index] - :raises ~azure.core.exceptions.HttpResponseError: - """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.Index]] = kwargs.pop("cls", None) + cls: ClsType[None] = kwargs.pop("cls", None) - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, + _request = build_agents_delete_session_file_request( + agent_name=agent_name, + agent_session_id=agent_session_id, + remote_path=remote_path, + recursive=recursive, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(next_link=None): - if not next_link: - - _request = build_indexes_list_request( - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + _request.url = self._client.format_url(_request.url, **path_format_arguments) - else: - # make call to next link with the client's api-version - _parsed_next_link = urllib.parse.urlparse(next_link) - _next_request_params = case_insensitive_dict( - { - key: [urllib.parse.quote(v) for v in value] - for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() - } - ) - _next_request_params["api-version"] = self._config.api_version - _request = HttpRequest( - "GET", - urllib.parse.urljoin(next_link, _parsed_next_link.path), - headers=_headers, - params=_next_request_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url( - "self._config.endpoint", self._config.endpoint, "str", skip_quote=True - ), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) - return _request + response = pipeline_response.http_response - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.Index], - deserialized.get("value", []), + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, iter(list_of_elem) + raise HttpResponseError(response=response, model=error) - def get_next(next_link=None): - _request = prepare_request(next_link) + if cls: + return cls(pipeline_response, None, {}) # type: ignore - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) +class EvaluationRulesOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. - return pipeline_response + Instead, you should access the following operations through + :class:`~azure.ai.projects.AIProjectClient`'s + :attr:`evaluation_rules` attribute. + """ - return ItemPaged(get_next, extract_data) + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") @distributed_trace - def get(self, name: str, version: str, **kwargs: Any) -> _models.Index: - """Get the specific version of the Index. The service returns 404 Not Found error if the Index - does not exist. + def get(self, id: str, **kwargs: Any) -> _models.EvaluationRule: + """Get an evaluation rule. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the Index to retrieve. Required. - :type version: str - :return: Index. The Index is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Index + Retrieves the specified evaluation rule and its configuration. + + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.EvaluationRule :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -6446,11 +6039,10 @@ def get(self, name: str, version: str, **kwargs: Any) -> _models.Index: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.Index] = kwargs.pop("cls", None) + cls: ClsType[_models.EvaluationRule] = kwargs.pop("cls", None) - _request = build_indexes_get_request( - name=name, - version=version, + _request = build_evaluation_rules_get_request( + id=id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -6480,7 +6072,7 @@ def get(self, name: str, version: str, **kwargs: Any) -> _models.Index: if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.Index, response.json()) + deserialized = _deserialize(_models.EvaluationRule, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -6488,14 +6080,13 @@ def get(self, name: str, version: str, **kwargs: Any) -> _models.Index: return deserialized # type: ignore @distributed_trace - def delete(self, name: str, version: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements - """Delete the specific version of the Index. The service returns 204 No Content if the Index was - deleted successfully or if the Index does not exist. + def delete(self, id: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements + """Delete an evaluation rule. - :param name: The name of the resource. Required. - :type name: str - :param version: The version of the Index to delete. Required. - :type version: str + Removes the specified evaluation rule from the project. + + :param id: Unique identifier for the evaluation rule. Required. + :type id: str :return: None :rtype: None :raises ~azure.core.exceptions.HttpResponseError: @@ -6513,9 +6104,8 @@ def delete(self, name: str, version: str, **kwargs: Any) -> None: # pylint: dis cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_indexes_delete_request( - name=name, - version=version, + _request = build_evaluation_rules_delete_request( + id=id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -6541,91 +6131,79 @@ def delete(self, name: str, version: str, **kwargs: Any) -> None: # pylint: dis @overload def create_or_update( - self, - name: str, - version: str, - index: _models.Index, - *, - content_type: str = "application/merge-patch+json", - **kwargs: Any - ) -> _models.Index: - """Create a new or update an existing Index with the given version id. + self, id: str, evaluation_rule: _models.EvaluationRule, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.EvaluationRule: + """Create or update an evaluation rule. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the Index to create or update. Required. - :type version: str - :param index: The Index to create or update. Required. - :type index: ~azure.ai.projects.models.Index + Creates a new evaluation rule, or replaces the existing rule when the identifier matches. + + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :param evaluation_rule: Evaluation rule resource. Required. + :type evaluation_rule: ~azure.ai.projects.models.EvaluationRule :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". + Default value is "application/json". :paramtype content_type: str - :return: Index. The Index is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Index + :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.EvaluationRule :raises ~azure.core.exceptions.HttpResponseError: """ @overload def create_or_update( - self, name: str, version: str, index: JSON, *, content_type: str = "application/merge-patch+json", **kwargs: Any - ) -> _models.Index: - """Create a new or update an existing Index with the given version id. + self, id: str, evaluation_rule: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.EvaluationRule: + """Create or update an evaluation rule. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the Index to create or update. Required. - :type version: str - :param index: The Index to create or update. Required. - :type index: JSON + Creates a new evaluation rule, or replaces the existing rule when the identifier matches. + + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :param evaluation_rule: Evaluation rule resource. Required. + :type evaluation_rule: JSON :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". + Default value is "application/json". :paramtype content_type: str - :return: Index. The Index is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Index + :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.EvaluationRule :raises ~azure.core.exceptions.HttpResponseError: """ @overload def create_or_update( - self, - name: str, - version: str, - index: IO[bytes], - *, - content_type: str = "application/merge-patch+json", - **kwargs: Any - ) -> _models.Index: - """Create a new or update an existing Index with the given version id. + self, id: str, evaluation_rule: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.EvaluationRule: + """Create or update an evaluation rule. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the Index to create or update. Required. - :type version: str - :param index: The Index to create or update. Required. - :type index: IO[bytes] + Creates a new evaluation rule, or replaces the existing rule when the identifier matches. + + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :param evaluation_rule: Evaluation rule resource. Required. + :type evaluation_rule: IO[bytes] :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/merge-patch+json". + Default value is "application/json". :paramtype content_type: str - :return: Index. The Index is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Index + :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.EvaluationRule :raises ~azure.core.exceptions.HttpResponseError: """ @distributed_trace def create_or_update( - self, name: str, version: str, index: Union[_models.Index, JSON, IO[bytes]], **kwargs: Any - ) -> _models.Index: - """Create a new or update an existing Index with the given version id. + self, id: str, evaluation_rule: Union[_models.EvaluationRule, JSON, IO[bytes]], **kwargs: Any + ) -> _models.EvaluationRule: + """Create or update an evaluation rule. - :param name: The name of the resource. Required. - :type name: str - :param version: The specific version id of the Index to create or update. Required. - :type version: str - :param index: The Index to create or update. Is one of the following types: Index, JSON, - IO[bytes] Required. - :type index: ~azure.ai.projects.models.Index or JSON or IO[bytes] - :return: Index. The Index is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.Index + Creates a new evaluation rule, or replaces the existing rule when the identifier matches. + + :param id: Unique identifier for the evaluation rule. Required. + :type id: str + :param evaluation_rule: Evaluation rule resource. Is one of the following types: + EvaluationRule, JSON, IO[bytes] Required. + :type evaluation_rule: ~azure.ai.projects.models.EvaluationRule or JSON or IO[bytes] + :return: EvaluationRule. The EvaluationRule is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.EvaluationRule :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -6640,18 +6218,17 @@ def create_or_update( _params = kwargs.pop("params", {}) or {} content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.Index] = kwargs.pop("cls", None) + cls: ClsType[_models.EvaluationRule] = kwargs.pop("cls", None) - content_type = content_type or "application/merge-patch+json" + content_type = content_type or "application/json" _content = None - if isinstance(index, (IOBase, bytes)): - _content = index + if isinstance(evaluation_rule, (IOBase, bytes)): + _content = evaluation_rule else: - _content = json.dumps(index, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + _content = json.dumps(evaluation_rule, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - _request = build_indexes_create_or_update_request( - name=name, - version=version, + _request = build_evaluation_rules_create_or_update_request( + id=id, content_type=content_type, api_version=self._config.api_version, content=_content, @@ -6683,22 +6260,130 @@ def create_or_update( if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.Index, response.json()) + deserialized = _deserialize(_models.EvaluationRule, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore + @distributed_trace + def list( + self, + *, + action_type: Optional[Union[str, _models.EvaluationRuleActionType]] = None, + agent_name: Optional[str] = None, + enabled: Optional[bool] = None, + **kwargs: Any + ) -> ItemPaged["_models.EvaluationRule"]: + """List evaluation rules. + + Returns the evaluation rules configured for the project, optionally filtered by action type, + agent name, or enabled state. + + :keyword action_type: Filter by the type of evaluation rule. Known values are: + "continuousEvaluation" and "humanEvaluationPreview". Default value is None. + :paramtype action_type: str or ~azure.ai.projects.models.EvaluationRuleActionType + :keyword agent_name: Filter by the agent name. Default value is None. + :paramtype agent_name: str + :keyword enabled: Filter by the enabled status. Default value is None. + :paramtype enabled: bool + :return: An iterator like instance of EvaluationRule + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.EvaluationRule] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.EvaluationRule]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_evaluation_rules_list_request( + action_type=action_type, + agent_name=agent_name, + enabled=enabled, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.EvaluationRule], + deserialized.get("value", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) + + def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return ItemPaged(get_next, extract_data) + -class BetaAgentsOperations: # pylint: disable=too-many-public-methods +class ConnectionsOperations: """ .. warning:: **DO NOT** instantiate this class directly. Instead, you should access the following operations through :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`agents` attribute. + :attr:`connections` attribute. """ def __init__(self, *args, **kwargs) -> None: @@ -6708,90 +6393,85 @@ def __init__(self, *args, **kwargs) -> None: self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") - @overload - def patch_agent_details( - self, - agent_name: str, - *, - content_type: str = "application/merge-patch+json", - agent_endpoint: Optional[_models.AgentEndpointConfig] = None, - agent_card: Optional[_models.AgentCard] = None, - **kwargs: Any - ) -> _models.AgentDetails: - """Updates an agent endpoint. + @distributed_trace + def _get(self, name: str, **kwargs: Any) -> _models.Connection: + """Get a connection. - :param agent_name: The name of the agent to retrieve. Required. - :type agent_name: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :keyword agent_endpoint: The endpoint configuration for the agent. Default value is None. - :paramtype agent_endpoint: ~azure.ai.projects.models.AgentEndpointConfig - :keyword agent_card: Optional agent card for the agent. Default value is None. - :paramtype agent_card: ~azure.ai.projects.models.AgentCard - :return: AgentDetails. The AgentDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentDetails + Retrieves the specified connection and its configuration details without including credential + values. + + :param name: The friendly name of the connection, provided by the user. Required. + :type name: str + :return: Connection. The Connection is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Connection :raises ~azure.core.exceptions.HttpResponseError: """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) - @overload - def patch_agent_details( - self, agent_name: str, body: JSON, *, content_type: str = "application/merge-patch+json", **kwargs: Any - ) -> _models.AgentDetails: - """Updates an agent endpoint. + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - :param agent_name: The name of the agent to retrieve. Required. - :type agent_name: str - :param body: Required. - :type body: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: AgentDetails. The AgentDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ + cls: ClsType[_models.Connection] = kwargs.pop("cls", None) - @overload - def patch_agent_details( - self, agent_name: str, body: IO[bytes], *, content_type: str = "application/merge-patch+json", **kwargs: Any - ) -> _models.AgentDetails: - """Updates an agent endpoint. + _request = build_connections_get_request( + name=name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - :param agent_name: The name of the agent to retrieve. Required. - :type agent_name: str - :param body: Required. - :type body: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/merge-patch+json". - :paramtype content_type: str - :return: AgentDetails. The AgentDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.Connection, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore @distributed_trace - def patch_agent_details( - self, - agent_name: str, - body: Union[JSON, IO[bytes]] = _Unset, - *, - agent_endpoint: Optional[_models.AgentEndpointConfig] = None, - agent_card: Optional[_models.AgentCard] = None, - **kwargs: Any - ) -> _models.AgentDetails: - """Updates an agent endpoint. + def _get_with_credentials(self, name: str, **kwargs: Any) -> _models.Connection: + """Get a connection with credentials. - :param agent_name: The name of the agent to retrieve. Required. - :type agent_name: str - :param body: Is either a JSON type or a IO[bytes] type. Required. - :type body: JSON or IO[bytes] - :keyword agent_endpoint: The endpoint configuration for the agent. Default value is None. - :paramtype agent_endpoint: ~azure.ai.projects.models.AgentEndpointConfig - :keyword agent_card: Optional agent card for the agent. Default value is None. - :paramtype agent_card: ~azure.ai.projects.models.AgentCard - :return: AgentDetails. The AgentDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentDetails + Retrieves the specified connection together with its credential values. + + :param name: The friendly name of the connection, provided by the user. Required. + :type name: str + :return: Connection. The Connection is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Connection :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -6802,27 +6482,14 @@ def patch_agent_details( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.AgentDetails] = kwargs.pop("cls", None) - - if body is _Unset: - body = {"agent_card": agent_card, "agent_endpoint": agent_endpoint} - body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/merge-patch+json" - _content = None - if isinstance(body, (IOBase, bytes)): - _content = body - else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[_models.Connection] = kwargs.pop("cls", None) - _request = build_beta_agents_patch_agent_details_request( - agent_name=agent_name, - content_type=content_type, + _request = build_connections_get_with_credentials_request( + name=name, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -6846,98 +6513,343 @@ def patch_agent_details( except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.AgentDetails, response.json()) + deserialized = _deserialize(_models.Connection, response.json()) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore - @overload - def create_version_from_code( + @distributed_trace + def list( self, - agent_name: str, - content: _models.CreateAgentVersionFromCodeContent, *, - code_zip_sha256: str, + connection_type: Optional[Union[str, _models.ConnectionType]] = None, + default_connection: Optional[bool] = None, **kwargs: Any - ) -> _models.AgentVersionDetails: - """create_version_from_code. + ) -> ItemPaged["_models.Connection"]: + """List connections. - :param agent_name: The unique name that identifies the agent. Name can be used to - retrieve/update/delete the agent. + Returns the connections available in the current project, optionally filtered by type or + default status. - * Must start and end with alphanumeric characters, - * Can contain hyphens in the middle - * Must not exceed 63 characters. Required. - :type agent_name: str - :param content: Required. - :type content: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent - :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change - detection (dedup) and integrity verification. Required. - :paramtype code_zip_sha256: str - :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentVersionDetails + :keyword connection_type: Lists connections of this specific type. Known values are: + "AzureOpenAI", "AzureBlob", "AzureStorageAccount", "CognitiveSearch", "CosmosDB", "ApiKey", + "AppConfig", "AppInsights", "CustomKeys", and "RemoteTool_Preview". Default value is None. + :paramtype connection_type: str or ~azure.ai.projects.models.ConnectionType + :keyword default_connection: Lists connections that are default connections. Default value is + None. + :paramtype default_connection: bool + :return: An iterator like instance of Connection + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.Connection] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} - @overload - def create_version_from_code( - self, agent_name: str, content: JSON, *, code_zip_sha256: str, **kwargs: Any - ) -> _models.AgentVersionDetails: - """create_version_from_code. + cls: ClsType[List[_models.Connection]] = kwargs.pop("cls", None) - :param agent_name: The unique name that identifies the agent. Name can be used to - retrieve/update/delete the agent. + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) - * Must start and end with alphanumeric characters, - * Can contain hyphens in the middle - * Must not exceed 63 characters. Required. - :type agent_name: str - :param content: Required. - :type content: JSON - :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change - detection (dedup) and integrity verification. Required. - :paramtype code_zip_sha256: str - :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentVersionDetails + def prepare_request(next_link=None): + if not next_link: + + _request = build_connections_list_request( + connection_type=connection_type, + default_connection=default_connection, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.Connection], + deserialized.get("value", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) + + def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return ItemPaged(get_next, extract_data) + + +class DatasetsOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. + + Instead, you should access the following operations through + :class:`~azure.ai.projects.AIProjectClient`'s + :attr:`datasets` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + + @distributed_trace + def list_versions(self, name: str, **kwargs: Any) -> ItemPaged["_models.DatasetVersion"]: + """List versions. + + List all versions of the given DatasetVersion. + + :param name: The name of the resource. Required. + :type name: str + :return: An iterator like instance of DatasetVersion + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.DatasetVersion] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.DatasetVersion]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_datasets_list_versions_request( + name=name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.DatasetVersion], + deserialized.get("value", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) + + def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return ItemPaged(get_next, extract_data) + + @distributed_trace + def list(self, **kwargs: Any) -> ItemPaged["_models.DatasetVersion"]: + """List latest versions. + + List the latest version of each DatasetVersion. + + :return: An iterator like instance of DatasetVersion + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.DatasetVersion] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.DatasetVersion]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_datasets_list_request( + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.DatasetVersion], + deserialized.get("value", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) + + def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return ItemPaged(get_next, extract_data) @distributed_trace - def create_version_from_code( - self, - agent_name: str, - content: Union[_models.CreateAgentVersionFromCodeContent, JSON], - *, - code_zip_sha256: str, - **kwargs: Any - ) -> _models.AgentVersionDetails: - """create_version_from_code. + def get(self, name: str, version: str, **kwargs: Any) -> _models.DatasetVersion: + """Get a version. - :param agent_name: The unique name that identifies the agent. Name can be used to - retrieve/update/delete the agent. + Get the specific version of the DatasetVersion. The service returns 404 Not Found error if the + DatasetVersion does not exist. - * Must start and end with alphanumeric characters, - * Can contain hyphens in the middle - * Must not exceed 63 characters. Required. - :type agent_name: str - :param content: Is either a CreateAgentVersionFromCodeContent type or a JSON type. Required. - :type content: ~azure.ai.projects.models.CreateAgentVersionFromCodeContent or JSON - :keyword code_zip_sha256: SHA-256 hex digest of the uploaded code zip. Used for change - detection (dedup) and integrity verification. Required. - :paramtype code_zip_sha256: str - :return: AgentVersionDetails. The AgentVersionDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentVersionDetails + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to retrieve. Required. + :type version: str + :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetVersion :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -6951,18 +6863,12 @@ def create_version_from_code( _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.AgentVersionDetails] = kwargs.pop("cls", None) - - _body = content.as_dict() if isinstance(content, _Model) else content - _file_fields: list[str] = ["code"] - _data_fields: list[str] = ["metadata"] - _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + cls: ClsType[_models.DatasetVersion] = kwargs.pop("cls", None) - _request = build_beta_agents_create_version_from_code_request( - agent_name=agent_name, - code_zip_sha256=code_zip_sha256, + _request = build_datasets_get_request( + name=name, + version=version, api_version=self._config.api_version, - files=_files, headers=_headers, params=_params, ) @@ -6986,16 +6892,12 @@ def create_version_from_code( except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.AgentVersionDetails, response.json()) + deserialized = _deserialize(_models.DatasetVersion, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -7003,23 +6905,18 @@ def create_version_from_code( return deserialized # type: ignore @distributed_trace - def download_code(self, agent_name: str, *, agent_version: Optional[str] = None, **kwargs: Any) -> Iterator[bytes]: - """Download the code zip for a code-based hosted agent. - Returns the previously-uploaded zip (``application/zip``). - - If ``agent_version`` is supplied, returns that version's code zip; otherwise - returns the latest version's code zip. + def delete(self, name: str, version: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements + """Delete a version. - The SHA-256 digest of the returned bytes matches the ``content_hash`` on the - resolved version's ``code_configuration``. + Delete the specific version of the DatasetVersion. The service returns 204 No Content if the + DatasetVersion was deleted successfully or if the DatasetVersion does not exist. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :keyword agent_version: The version of the agent whose code zip should be downloaded. - If omitted, the latest version's code zip is returned. Default value is None. - :paramtype agent_version: str - :return: Iterator[bytes] - :rtype: Iterator[bytes] + :param name: The name of the resource. Required. + :type name: str + :param version: The version of the DatasetVersion to delete. Required. + :type version: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -7033,12 +6930,164 @@ def download_code(self, agent_name: str, *, agent_version: Optional[str] = None, _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_beta_agents_download_code_request( - agent_name=agent_name, - agent_version=agent_version, + _request = build_datasets_delete_request( + name=name, + version=version, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if cls: + return cls(pipeline_response, None, {}) # type: ignore + + @overload + def create_or_update( + self, + name: str, + version: str, + dataset_version: _models.DatasetVersion, + *, + content_type: str = "application/merge-patch+json", + **kwargs: Any + ) -> _models.DatasetVersion: + """Create or update a version. + + Create a new or update an existing DatasetVersion with the given version id. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to create or update. Required. + :type version: str + :param dataset_version: The DatasetVersion to create or update. Required. + :type dataset_version: ~azure.ai.projects.models.DatasetVersion + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create_or_update( + self, + name: str, + version: str, + dataset_version: JSON, + *, + content_type: str = "application/merge-patch+json", + **kwargs: Any + ) -> _models.DatasetVersion: + """Create or update a version. + + Create a new or update an existing DatasetVersion with the given version id. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to create or update. Required. + :type version: str + :param dataset_version: The DatasetVersion to create or update. Required. + :type dataset_version: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create_or_update( + self, + name: str, + version: str, + dataset_version: IO[bytes], + *, + content_type: str = "application/merge-patch+json", + **kwargs: Any + ) -> _models.DatasetVersion: + """Create or update a version. + + Create a new or update an existing DatasetVersion with the given version id. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to create or update. Required. + :type version: str + :param dataset_version: The DatasetVersion to create or update. Required. + :type dataset_version: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/merge-patch+json". + :paramtype content_type: str + :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + def create_or_update( + self, name: str, version: str, dataset_version: Union[_models.DatasetVersion, JSON, IO[bytes]], **kwargs: Any + ) -> _models.DatasetVersion: + """Create or update a version. + + Create a new or update an existing DatasetVersion with the given version id. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to create or update. Required. + :type version: str + :param dataset_version: The DatasetVersion to create or update. Is one of the following types: + DatasetVersion, JSON, IO[bytes] Required. + :type dataset_version: ~azure.ai.projects.models.DatasetVersion or JSON or IO[bytes] + :return: DatasetVersion. The DatasetVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.DatasetVersion] = kwargs.pop("cls", None) + + content_type = content_type or "application/merge-patch+json" + _content = None + if isinstance(dataset_version, (IOBase, bytes)): + _content = dataset_version + else: + _content = json.dumps(dataset_version, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_datasets_create_or_update_request( + name=name, + version=version, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -7048,157 +7097,138 @@ def download_code(self, agent_name: str, *, agent_version: Optional[str] = None, _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200]: + if response.status_code not in [200, 201]: if _stream: try: response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers["x-ms-agent-version"] = self._deserialize("str", response.headers.get("x-ms-agent-version")) - response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + raise HttpResponseError(response=response) - deserialized = response.iter_bytes() if _decompress else response.iter_raw() + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.DatasetVersion, response.json()) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore @overload - def create_session( + def pending_upload( self, - agent_name: str, + name: str, + version: str, + pending_upload_request: _models.PendingUploadRequest, *, - version_indicator: _models.VersionIndicator, - user_isolation_key: Optional[str] = None, content_type: str = "application/json", - agent_session_id: Optional[str] = None, **kwargs: Any - ) -> _models.AgentSessionResource: - """Creates a new session for an agent endpoint. The endpoint resolves the backing agent version - from ``version_indicator`` and enforces session ownership using the provided isolation key for - session-mutating operations. + ) -> _models.PendingUploadResponse: + """Start a pending upload. - :param agent_name: The name of the agent to create a session for. Required. - :type agent_name: str - :keyword version_indicator: Determines which agent version backs the session. Required. - :paramtype version_indicator: ~azure.ai.projects.models.VersionIndicator - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str + Initiates a new pending upload or retrieves an existing one for the specified dataset version. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to operate on. Required. + :type version: str + :param pending_upload_request: The pending upload request parameters. Required. + :type pending_upload_request: ~azure.ai.projects.models.PendingUploadRequest :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str - :keyword agent_session_id: Optional caller-provided session ID. If specified, it must be unique - within the agent endpoint. Auto-generated if omitted. Default value is None. - :paramtype agent_session_id: str - :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentSessionResource + :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.PendingUploadResponse :raises ~azure.core.exceptions.HttpResponseError: """ @overload - def create_session( + def pending_upload( self, - agent_name: str, - body: JSON, + name: str, + version: str, + pending_upload_request: JSON, *, - user_isolation_key: Optional[str] = None, content_type: str = "application/json", **kwargs: Any - ) -> _models.AgentSessionResource: - """Creates a new session for an agent endpoint. The endpoint resolves the backing agent version - from ``version_indicator`` and enforces session ownership using the provided isolation key for - session-mutating operations. + ) -> _models.PendingUploadResponse: + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified dataset version. - :param agent_name: The name of the agent to create a session for. Required. - :type agent_name: str - :param body: Required. - :type body: JSON - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to operate on. Required. + :type version: str + :param pending_upload_request: The pending upload request parameters. Required. + :type pending_upload_request: JSON :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str - :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentSessionResource + :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.PendingUploadResponse :raises ~azure.core.exceptions.HttpResponseError: """ @overload - def create_session( + def pending_upload( self, - agent_name: str, - body: IO[bytes], + name: str, + version: str, + pending_upload_request: IO[bytes], *, - user_isolation_key: Optional[str] = None, content_type: str = "application/json", **kwargs: Any - ) -> _models.AgentSessionResource: - """Creates a new session for an agent endpoint. The endpoint resolves the backing agent version - from ``version_indicator`` and enforces session ownership using the provided isolation key for - session-mutating operations. + ) -> _models.PendingUploadResponse: + """Start a pending upload. - :param agent_name: The name of the agent to create a session for. Required. - :type agent_name: str - :param body: Required. - :type body: IO[bytes] - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str + Initiates a new pending upload or retrieves an existing one for the specified dataset version. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to operate on. Required. + :type version: str + :param pending_upload_request: The pending upload request parameters. Required. + :type pending_upload_request: IO[bytes] :keyword content_type: Body Parameter content-type. Content type parameter for binary body. Default value is "application/json". :paramtype content_type: str - :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentSessionResource + :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.PendingUploadResponse :raises ~azure.core.exceptions.HttpResponseError: """ @distributed_trace - def create_session( + def pending_upload( self, - agent_name: str, - body: Union[JSON, IO[bytes]] = _Unset, - *, - version_indicator: _models.VersionIndicator = _Unset, - user_isolation_key: Optional[str] = None, - agent_session_id: Optional[str] = None, + name: str, + version: str, + pending_upload_request: Union[_models.PendingUploadRequest, JSON, IO[bytes]], **kwargs: Any - ) -> _models.AgentSessionResource: - """Creates a new session for an agent endpoint. The endpoint resolves the backing agent version - from ``version_indicator`` and enforces session ownership using the provided isolation key for - session-mutating operations. + ) -> _models.PendingUploadResponse: + """Start a pending upload. - :param agent_name: The name of the agent to create a session for. Required. - :type agent_name: str - :param body: Is either a JSON type or a IO[bytes] type. Required. - :type body: JSON or IO[bytes] - :keyword version_indicator: Determines which agent version backs the session. Required. - :paramtype version_indicator: ~azure.ai.projects.models.VersionIndicator - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :keyword agent_session_id: Optional caller-provided session ID. If specified, it must be unique - within the agent endpoint. Auto-generated if omitted. Default value is None. - :paramtype agent_session_id: str - :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentSessionResource + Initiates a new pending upload or retrieves an existing one for the specified dataset version. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to operate on. Required. + :type version: str + :param pending_upload_request: The pending upload request parameters. Is one of the following + types: PendingUploadRequest, JSON, IO[bytes] Required. + :type pending_upload_request: ~azure.ai.projects.models.PendingUploadRequest or JSON or + IO[bytes] + :return: PendingUploadResponse. The PendingUploadResponse is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.PendingUploadResponse :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -7213,23 +7243,18 @@ def create_session( _params = kwargs.pop("params", {}) or {} content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.AgentSessionResource] = kwargs.pop("cls", None) + cls: ClsType[_models.PendingUploadResponse] = kwargs.pop("cls", None) - if body is _Unset: - if version_indicator is _Unset: - raise TypeError("missing required argument: version_indicator") - body = {"agent_session_id": agent_session_id, "version_indicator": version_indicator} - body = {k: v for k, v in body.items() if v is not None} content_type = content_type or "application/json" _content = None - if isinstance(body, (IOBase, bytes)): - _content = body + if isinstance(pending_upload_request, (IOBase, bytes)): + _content = pending_upload_request else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + _content = json.dumps(pending_upload_request, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - _request = build_beta_agents_create_session_request( - agent_name=agent_name, - user_isolation_key=user_isolation_key, + _request = build_datasets_pending_upload_request( + name=name, + version=version, content_type=content_type, api_version=self._config.api_version, content=_content, @@ -7249,23 +7274,19 @@ def create_session( response = pipeline_response.http_response - if response.status_code not in [201]: + if response.status_code not in [200]: if _stream: try: response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.AgentSessionResource, response.json()) + deserialized = _deserialize(_models.PendingUploadResponse, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -7273,20 +7294,17 @@ def create_session( return deserialized # type: ignore @distributed_trace - def get_session( - self, agent_name: str, session_id: str, *, user_isolation_key: Optional[str] = None, **kwargs: Any - ) -> _models.AgentSessionResource: - """Retrieves a session by ID. + def get_credentials(self, name: str, version: str, **kwargs: Any) -> _models.DatasetCredential: + """Get dataset credentials. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param session_id: The session identifier. Required. - :type session_id: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :return: AgentSessionResource. The AgentSessionResource is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentSessionResource + Gets the SAS credential to access the storage account associated with a Dataset version. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the DatasetVersion to operate on. Required. + :type version: str + :return: DatasetCredential. The DatasetCredential is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DatasetCredential :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -7300,12 +7318,11 @@ def get_session( _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.AgentSessionResource] = kwargs.pop("cls", None) + cls: ClsType[_models.DatasetCredential] = kwargs.pop("cls", None) - _request = build_beta_agents_get_session_request( - agent_name=agent_name, - session_id=session_id, - user_isolation_key=user_isolation_key, + _request = build_datasets_get_credentials_request( + name=name, + version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -7330,96 +7347,46 @@ def get_session( except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.AgentSessionResource, response.json()) + deserialized = _deserialize(_models.DatasetCredential, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - @distributed_trace - def delete_session( # pylint: disable=inconsistent-return-statements - self, agent_name: str, session_id: str, *, user_isolation_key: Optional[str] = None, **kwargs: Any - ) -> None: - """Deletes a session synchronously. Returns 204 No Content when the session is deleted or does not - exist. - - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param session_id: The session identifier. Required. - :type session_id: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :return: None - :rtype: None - :raises ~azure.core.exceptions.HttpResponseError: - """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[None] = kwargs.pop("cls", None) - - _request = build_beta_agents_delete_session_request( - agent_name=agent_name, - session_id=session_id, - user_isolation_key=user_isolation_key, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response +class DeploymentsOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. - if response.status_code not in [204]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + Instead, you should access the following operations through + :class:`~azure.ai.projects.AIProjectClient`'s + :attr:`deployments` attribute. + """ - if cls: - return cls(pipeline_response, None, {}) # type: ignore + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") @distributed_trace - def stop_session( # pylint: disable=inconsistent-return-statements - self, agent_name: str, session_id: str, **kwargs: Any - ) -> None: - """Stops a session. Returns 204 No Content when the stop succeeds. + def get(self, name: str, **kwargs: Any) -> _models.Deployment: + """Get a deployment. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param session_id: The session identifier. Required. - :type session_id: str - :return: None - :rtype: None + Gets a deployed model. + + :param name: Name of the deployment. Required. + :type name: str + :return: Deployment. The Deployment is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Deployment :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -7433,11 +7400,10 @@ def stop_session( # pylint: disable=inconsistent-return-statements _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + cls: ClsType[_models.Deployment] = kwargs.pop("cls", None) - _request = build_beta_agents_stop_session_request( - agent_name=agent_name, - session_id=session_id, + _request = build_deployments_get_request( + name=name, api_version=self._config.api_version, headers=_headers, params=_params, @@ -7447,64 +7413,68 @@ def stop_session( # pylint: disable=inconsistent-return-statements } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.Deployment, response.json()) if cls: - return cls(pipeline_response, None, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore @distributed_trace - def list_sessions( + def list( self, - agent_name: str, *, - user_isolation_key: Optional[str] = None, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - before: Optional[str] = None, + model_publisher: Optional[str] = None, + model_name: Optional[str] = None, + deployment_type: Optional[Union[str, _models.DeploymentType]] = None, **kwargs: Any - ) -> ItemPaged["_models.AgentSessionResource"]: - """Returns a list of sessions for the specified agent. + ) -> ItemPaged["_models.Deployment"]: + """List deployments. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and - 100, and the - default is 20. Default value is None. - :paramtype limit: int - :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for - ascending order and``desc`` - for descending order. Known values are: "asc" and "desc". Default value is None. - :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - Default value is None. - :paramtype before: str - :return: An iterator like instance of AgentSessionResource - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.AgentSessionResource] + Returns the deployed models available in the current project, optionally filtered by publisher, + model name, or deployment type. + + :keyword model_publisher: Model publisher to filter models by. Default value is None. + :paramtype model_publisher: str + :keyword model_name: Model name (the publisher specific name) to filter models by. Default + value is None. + :paramtype model_name: str + :keyword deployment_type: Type of deployment to filter list by. "ModelDeployment" Default value + is None. + :paramtype deployment_type: str or ~azure.ai.projects.models.DeploymentType + :return: An iterator like instance of Deployment + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.Deployment] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.AgentSessionResource]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.Deployment]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -7514,37 +7484,61 @@ def list_sessions( } error_map.update(kwargs.pop("error_map", {}) or {}) - def prepare_request(_continuation_token=None): + def prepare_request(next_link=None): + if not next_link: + + _request = build_deployments_list_request( + model_publisher=model_publisher, + model_name=model_name, + deployment_type=deployment_type, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - _request = build_beta_agents_list_sessions_request( - agent_name=agent_name, - user_isolation_key=user_isolation_key, - limit=limit, - order=order, - after=_continuation_token, - before=before, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) return _request def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.AgentSessionResource], - deserialized.get("data", []), + List[_models.Deployment], + deserialized.get("value", []), ) if cls: list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("last_id") or None, iter(list_of_elem) + return deserialized.get("nextLink") or None, iter(list_of_elem) - def get_next(_continuation_token=None): - _request = prepare_request(_continuation_token) + def get_next(next_link=None): + _request = prepare_request(next_link) _stream = False pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access @@ -7554,57 +7548,47 @@ def get_next(_continuation_token=None): if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) return pipeline_response return ItemPaged(get_next, extract_data) - @distributed_trace - def get_session_log_stream( - self, agent_name: str, agent_version: str, session_id: str, **kwargs: Any - ) -> _models.SessionLogEvent: - """Streams console logs (stdout / stderr) for a specific hosted agent session - as a Server-Sent Events (SSE) stream. - - Each SSE frame contains: - - * `event`: always `"log"` - * `data`: a plain-text log line (currently JSON-formatted, but the schema is not contractual and may include additional keys or change format over time; clients should treat it as an opaque string) - - Example SSE frames: - - .. code-block:: - event: log - data: {"timestamp":"2026-03-10T09:33:17.121Z","stream":"stdout","message":"Starting FoundryCBAgent server on port 8088"} +class IndexesOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. - event: log - data: {"timestamp":"2026-03-10T09:33:17.130Z","stream":"stderr","message":"INFO: Application startup complete."} + Instead, you should access the following operations through + :class:`~azure.ai.projects.AIProjectClient`'s + :attr:`indexes` attribute. + """ - event: log - data: {"timestamp":"2026-03-10T09:34:52.714Z","stream":"status","message":"Successfully connected to container"} + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") - event: log - data: {"timestamp":"2026-03-10T09:35:52.714Z","stream":"status","message":"No logs since last 60 seconds"} + @distributed_trace + def list_versions(self, name: str, **kwargs: Any) -> ItemPaged["_models.Index"]: + """List versions. - The stream remains open until the client disconnects or the server - terminates the connection. Clients should handle reconnection as needed. + List all versions of the given Index. - :param agent_name: The name of the hosted agent. Required. - :type agent_name: str - :param agent_version: The version of the agent. Required. - :type agent_version: str - :param session_id: The session ID (maps to an ADC sandbox). Required. - :type session_id: str - :return: SessionLogEvent. The SessionLogEvent is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SessionLogEvent + :param name: The name of the resource. Required. + :type name: str + :return: An iterator like instance of Index + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.Index] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.Index]] = kwargs.pop("cls", None) + error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -7613,88 +7597,89 @@ def get_session_log_stream( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[_models.SessionLogEvent] = kwargs.pop("cls", None) + def prepare_request(next_link=None): + if not next_link: - _request = build_beta_agents_get_session_log_stream_request( - agent_name=agent_name, - agent_version=agent_version, - session_id=session_id, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + _request = build_indexes_list_versions_request( + name=name, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = True - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - response = pipeline_response.http_response + return _request - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.Index], + deserialized.get("value", []), ) - raise HttpResponseError(response=response, model=error) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) - response_headers = {} - response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + def get_next(next_link=None): + _request = prepare_request(next_link) - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.SessionLogEvent, response.text()) + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return pipeline_response - return deserialized # type: ignore + return ItemPaged(get_next, extract_data) @distributed_trace - def _upload_session_file( - self, - agent_name: str, - agent_session_id: str, - content: bytes, - *, - path: str, - user_isolation_key: Optional[str] = None, - **kwargs: Any - ) -> _models.SessionFileWriteResult: - """Upload a file to the session sandbox via binary stream. Maximum file size is 50 MB. Uploads - exceeding this limit return 413 Payload Too Large. + def list(self, **kwargs: Any) -> ItemPaged["_models.Index"]: + """List latest versions. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param agent_session_id: The session ID. Required. - :type agent_session_id: str - :param content: Required. - :type content: bytes - :keyword path: The destination file path within the sandbox, relative to the session home - directory. Required. - :paramtype path: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SessionFileWriteResult + List the latest version of each Index. + + :return: An iterator like instance of Index + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.Index] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.Index]] = kwargs.pop("cls", None) + error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -7703,85 +7688,86 @@ def _upload_session_file( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = kwargs.pop("params", {}) or {} + def prepare_request(next_link=None): + if not next_link: - content_type: str = kwargs.pop("content_type", _headers.pop("Content-Type", "application/octet-stream")) - cls: ClsType[_models.SessionFileWriteResult] = kwargs.pop("cls", None) + _request = build_indexes_list_request( + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - _content = content + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", + urllib.parse.urljoin(next_link, _parsed_next_link.path), + headers=_headers, + params=_next_request_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - _request = build_beta_agents_upload_session_file_request( - agent_name=agent_name, - agent_session_id=agent_session_id, - path=path, - user_isolation_key=user_isolation_key, - content_type=content_type, - api_version=self._config.api_version, - content=_content, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.Index], + deserialized.get("value", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) - response = pipeline_response.http_response + def get_next(next_link=None): + _request = prepare_request(next_link) - if response.status_code not in [201]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs ) - raise HttpResponseError(response=response, model=error) + response = pipeline_response.http_response - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.SessionFileWriteResult, response.json()) + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return pipeline_response - return deserialized # type: ignore + return ItemPaged(get_next, extract_data) @distributed_trace - def download_session_file( - self, - agent_name: str, - agent_session_id: str, - *, - path: str, - user_isolation_key: Optional[str] = None, - **kwargs: Any - ) -> Iterator[bytes]: - """Download a file from the session sandbox as a binary stream. + def get(self, name: str, version: str, **kwargs: Any) -> _models.Index: + """Get a version. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param agent_session_id: The session ID. Required. - :type agent_session_id: str - :keyword path: The file path to download from the sandbox, relative to the session home - directory. Required. - :paramtype path: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :return: Iterator[bytes] - :rtype: Iterator[bytes] + Get the specific version of the Index. The service returns 404 Not Found error if the Index + does not exist. + + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the Index to retrieve. Required. + :type version: str + :return: Index. The Index is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Index :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -7795,13 +7781,11 @@ def download_session_file( _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + cls: ClsType[_models.Index] = kwargs.pop("cls", None) - _request = build_beta_agents_download_session_file_request( - agent_name=agent_name, - agent_session_id=agent_session_id, - path=path, - user_isolation_key=user_isolation_key, + _request = build_indexes_get_request( + name=name, + version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -7812,170 +7796,43 @@ def download_session_file( _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs - ) - - response = pipeline_response.http_response - - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore - - return deserialized # type: ignore - - @distributed_trace - def list_session_files( - self, - agent_name: str, - agent_session_id: str, - *, - path: Optional[str] = None, - user_isolation_key: Optional[str] = None, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - before: Optional[str] = None, - **kwargs: Any - ) -> ItemPaged["_models.SessionDirectoryEntry"]: - """List files and directories at a given path in the session sandbox. Returns only the immediate - children of the specified directory (non-recursive). If path is not provided, lists the session - home directory. - - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param agent_session_id: The session ID. Required. - :type agent_session_id: str - :keyword path: The directory path to list, relative to the session home directory. Defaults to - the home directory if not provided. Default value is None. - :paramtype path: str - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str - :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and - 100, and the - default is 20. Default value is None. - :paramtype limit: int - :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for - ascending order and``desc`` - for descending order. Known values are: "asc" and "desc". Default value is None. - :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - Default value is None. - :paramtype before: str - :return: An iterator like instance of SessionDirectoryEntry - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.SessionDirectoryEntry] - :raises ~azure.core.exceptions.HttpResponseError: - """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.SessionDirectoryEntry]] = kwargs.pop("cls", None) - - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(_continuation_token=None): - - _request = build_beta_agents_list_session_files_request( - agent_name=agent_name, - agent_session_id=agent_session_id, - path=path, - user_isolation_key=user_isolation_key, - limit=limit, - order=order, - after=_continuation_token, - before=before, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - return _request - - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.SessionDirectoryEntry], - deserialized.get("entries", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("last_id") or None, iter(list_of_elem) + ) - def get_next(_continuation_token=None): - _request = prepare_request(_continuation_token) + response = pipeline_response.http_response - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.Index, response.json()) - return pipeline_response + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore - return ItemPaged(get_next, extract_data) + return deserialized # type: ignore @distributed_trace - def delete_session_file( # pylint: disable=inconsistent-return-statements - self, - agent_name: str, - agent_session_id: str, - *, - path: str, - recursive: Optional[bool] = None, - user_isolation_key: Optional[str] = None, - **kwargs: Any - ) -> None: - """Delete a file or directory from the session sandbox. If ``recursive`` is false (default) and - the target is a non-empty directory, the API returns 409 Conflict. + def delete(self, name: str, version: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements + """Delete a version. - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param agent_session_id: The session ID. Required. - :type agent_session_id: str - :keyword path: The file or directory path to delete, relative to the session home directory. - Required. - :paramtype path: str - :keyword recursive: Whether to recursively delete directory contents. The service defaults to - ``false`` if a value is not specified by the caller. Default value is None. - :paramtype recursive: bool - :keyword user_isolation_key: Opaque per-user isolation key used to scope endpoint-scoped data - (responses, conversations, sessions) to a specific end user. Default value is None. - :paramtype user_isolation_key: str + Delete the specific version of the Index. The service returns 204 No Content if the Index was + deleted successfully or if the Index does not exist. + + :param name: The name of the resource. Required. + :type name: str + :param version: The version of the Index to delete. Required. + :type version: str :return: None :rtype: None :raises ~azure.core.exceptions.HttpResponseError: @@ -7993,12 +7850,9 @@ def delete_session_file( # pylint: disable=inconsistent-return-statements cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_beta_agents_delete_session_file_request( - agent_name=agent_name, - agent_session_id=agent_session_id, - path=path, - recursive=recursive, - user_isolation_key=user_isolation_key, + _request = build_indexes_delete_request( + name=name, + version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -8017,112 +7871,106 @@ def delete_session_file( # pylint: disable=inconsistent-return-statements if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + raise HttpResponseError(response=response) if cls: return cls(pipeline_response, None, {}) # type: ignore @overload - def create_optimization_job( + def create_or_update( self, - inputs: _models.OptimizationJobInputs, + name: str, + version: str, + index: _models.Index, *, - operation_id: Optional[str] = None, - content_type: str = "application/json", + content_type: str = "application/merge-patch+json", **kwargs: Any - ) -> _models.OptimizationJob: - """Creates an agent optimization job. + ) -> _models.Index: + """Create or update a version. - Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for - idempotent retry. + Create a new or update an existing Index with the given version id. - :param inputs: The optimization job inputs. Required. - :type inputs: ~azure.ai.projects.models.OptimizationJobInputs - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the Index to create or update. Required. + :type version: str + :param index: The Index to create or update. Required. + :type index: ~azure.ai.projects.models.Index :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". + Default value is "application/merge-patch+json". :paramtype content_type: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob + :return: Index. The Index is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Index :raises ~azure.core.exceptions.HttpResponseError: """ @overload - def create_optimization_job( - self, inputs: JSON, *, operation_id: Optional[str] = None, content_type: str = "application/json", **kwargs: Any - ) -> _models.OptimizationJob: - """Creates an agent optimization job. + def create_or_update( + self, name: str, version: str, index: JSON, *, content_type: str = "application/merge-patch+json", **kwargs: Any + ) -> _models.Index: + """Create or update a version. - Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for - idempotent retry. + Create a new or update an existing Index with the given version id. - :param inputs: The optimization job inputs. Required. - :type inputs: JSON - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the Index to create or update. Required. + :type version: str + :param index: The Index to create or update. Required. + :type index: JSON :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". + Default value is "application/merge-patch+json". :paramtype content_type: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob + :return: Index. The Index is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Index :raises ~azure.core.exceptions.HttpResponseError: """ @overload - def create_optimization_job( + def create_or_update( self, - inputs: IO[bytes], + name: str, + version: str, + index: IO[bytes], *, - operation_id: Optional[str] = None, - content_type: str = "application/json", + content_type: str = "application/merge-patch+json", **kwargs: Any - ) -> _models.OptimizationJob: - """Creates an agent optimization job. + ) -> _models.Index: + """Create or update a version. - Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for - idempotent retry. + Create a new or update an existing Index with the given version id. - :param inputs: The optimization job inputs. Required. - :type inputs: IO[bytes] - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the Index to create or update. Required. + :type version: str + :param index: The Index to create or update. Required. + :type index: IO[bytes] :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". + Default value is "application/merge-patch+json". :paramtype content_type: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob + :return: Index. The Index is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Index :raises ~azure.core.exceptions.HttpResponseError: """ @distributed_trace - def create_optimization_job( - self, - inputs: Union[_models.OptimizationJobInputs, JSON, IO[bytes]], - *, - operation_id: Optional[str] = None, - **kwargs: Any - ) -> _models.OptimizationJob: - """Creates an agent optimization job. + def create_or_update( + self, name: str, version: str, index: Union[_models.Index, JSON, IO[bytes]], **kwargs: Any + ) -> _models.Index: + """Create or update a version. - Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for - idempotent retry. + Create a new or update an existing Index with the given version id. - :param inputs: The optimization job inputs. Is one of the following types: - OptimizationJobInputs, JSON, IO[bytes] Required. - :type inputs: ~azure.ai.projects.models.OptimizationJobInputs or JSON or IO[bytes] - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob + :param name: The name of the resource. Required. + :type name: str + :param version: The specific version id of the Index to create or update. Required. + :type version: str + :param index: The Index to create or update. Is one of the following types: Index, JSON, + IO[bytes] Required. + :type index: ~azure.ai.projects.models.Index or JSON or IO[bytes] + :return: Index. The Index is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.Index :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -8137,91 +7985,21 @@ def create_optimization_job( _params = kwargs.pop("params", {}) or {} content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) + cls: ClsType[_models.Index] = kwargs.pop("cls", None) - content_type = content_type or "application/json" + content_type = content_type or "application/merge-patch+json" _content = None - if isinstance(inputs, (IOBase, bytes)): - _content = inputs + if isinstance(index, (IOBase, bytes)): + _content = index else: - _content = json.dumps(inputs, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + _content = json.dumps(index, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - _request = build_beta_agents_create_optimization_job_request( - operation_id=operation_id, + _request = build_indexes_create_or_update_request( + name=name, + version=version, content_type=content_type, api_version=self._config.api_version, - content=_content, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - - response = pipeline_response.http_response - - if response.status_code not in [201]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers["Operation-Location"] = self._deserialize("str", response.headers.get("Operation-Location")) - response_headers["Location"] = self._deserialize("str", response.headers.get("Location")) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.OptimizationJob, response.json()) - - if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore - - return deserialized # type: ignore - - @distributed_trace - def get_optimization_job(self, job_id: str, **kwargs: Any) -> _models.OptimizationJob: - """Get info about an agent optimization job. - - Get an optimization job by id. Returns 202 while in progress, 200 when terminal. - - :param job_id: The ID of the job. Required. - :type job_id: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) - - _request = build_beta_agents_get_optimization_job_request( - job_id=job_id, - api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -8238,143 +8016,163 @@ def get_optimization_job(self, job_id: str, **kwargs: Any) -> _models.Optimizati response = pipeline_response.http_response - if response.status_code not in [200, 202]: + if response.status_code not in [200, 201]: if _stream: try: response.read() # Load the body in memory and close the socket except (StreamConsumedError, StreamClosedError): pass map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + raise HttpResponseError(response=response) if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.OptimizationJob, response.json()) + deserialized = _deserialize(_models.Index, response.json()) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - @distributed_trace - def list_optimization_jobs( + +class ToolboxesOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. + + Instead, you should access the following operations through + :class:`~azure.ai.projects.AIProjectClient`'s + :attr:`toolboxes` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + + @overload + def create_version( self, + name: str, *, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - before: Optional[str] = None, - status: Optional[Union[str, _models.JobStatus]] = None, - agent_name: Optional[str] = None, + tools: List[_models.ToolboxTool], + content_type: str = "application/json", + description: Optional[str] = None, + metadata: Optional[dict[str, str]] = None, + skills: Optional[List[_models.ToolboxSkill]] = None, + policies: Optional[_models.ToolboxPolicies] = None, **kwargs: Any - ) -> ItemPaged["_models.OptimizationJob"]: - """Returns a list of agent optimization jobs. + ) -> _models.ToolboxVersionObject: + """Create a new version of a toolbox. - List optimization jobs. Supports cursor pagination and optional status / agent_name filters. + Creates a new toolbox version, provisioning the toolbox itself if it does not already exist. - :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and - 100, and the - default is 20. Default value is None. - :paramtype limit: int - :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for - ascending order and``desc`` - for descending order. Known values are: "asc" and "desc". Default value is None. - :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - Default value is None. - :paramtype before: str - :keyword status: Filter to jobs in this lifecycle state. Known values are: "queued", - "in_progress", "succeeded", "failed", and "cancelled". Default value is None. - :paramtype status: str or ~azure.ai.projects.models.JobStatus - :keyword agent_name: Filter to jobs targeting this agent name. Default value is None. - :paramtype agent_name: str - :return: An iterator like instance of OptimizationJob - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.OptimizationJob] + :param name: The name of the toolbox. If the toolbox does not exist, it will be created. + Required. + :type name: str + :keyword tools: The list of tools to include in this version. Required. + :paramtype tools: list[~azure.ai.projects.models.ToolboxTool] + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword description: A human-readable description of the toolbox. Default value is None. + :paramtype description: str + :keyword metadata: Arbitrary key-value metadata to associate with the toolbox. Default value is + None. + :paramtype metadata: dict[str, str] + :keyword skills: The list of skill sources to include in this version. A skill reference + specifies a skill name and optionally a version. If version is omitted, the skill's default + version is used. Default value is None. + :paramtype skills: list[~azure.ai.projects.models.ToolboxSkill] + :keyword policies: Policy configuration for this toolbox version. Default value is None. + :paramtype policies: ~azure.ai.projects.models.ToolboxPolicies + :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxVersionObject :raises ~azure.core.exceptions.HttpResponseError: """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.OptimizationJob]] = kwargs.pop("cls", None) - - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(_continuation_token=None): - - _request = build_beta_agents_list_optimization_jobs_request( - limit=limit, - order=order, - after=_continuation_token, - before=before, - status=status, - agent_name=agent_name, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - return _request - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.OptimizationJob], - deserialized.get("data", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("last_id") or None, iter(list_of_elem) + @overload + def create_version( + self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.ToolboxVersionObject: + """Create a new version of a toolbox. - def get_next(_continuation_token=None): - _request = prepare_request(_continuation_token) + Creates a new toolbox version, provisioning the toolbox itself if it does not already exist. - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response + :param name: The name of the toolbox. If the toolbox does not exist, it will be created. + Required. + :type name: str + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxVersionObject + :raises ~azure.core.exceptions.HttpResponseError: + """ - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + @overload + def create_version( + self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.ToolboxVersionObject: + """Create a new version of a toolbox. - return pipeline_response + Creates a new toolbox version, provisioning the toolbox itself if it does not already exist. - return ItemPaged(get_next, extract_data) + :param name: The name of the toolbox. If the toolbox does not exist, it will be created. + Required. + :type name: str + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxVersionObject + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace - def cancel_optimization_job(self, job_id: str, **kwargs: Any) -> _models.OptimizationJob: - """Cancels an agent optimization job. + def create_version( + self, + name: str, + body: Union[JSON, IO[bytes]] = _Unset, + *, + tools: List[_models.ToolboxTool] = _Unset, + description: Optional[str] = None, + metadata: Optional[dict[str, str]] = None, + skills: Optional[List[_models.ToolboxSkill]] = None, + policies: Optional[_models.ToolboxPolicies] = None, + **kwargs: Any + ) -> _models.ToolboxVersionObject: + """Create a new version of a toolbox. - Request cancellation. Idempotent on terminal states. + Creates a new toolbox version, provisioning the toolbox itself if it does not already exist. - :param job_id: The ID of the job to cancel. Required. - :type job_id: str - :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.OptimizationJob + :param name: The name of the toolbox. If the toolbox does not exist, it will be created. + Required. + :type name: str + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword tools: The list of tools to include in this version. Required. + :paramtype tools: list[~azure.ai.projects.models.ToolboxTool] + :keyword description: A human-readable description of the toolbox. Default value is None. + :paramtype description: str + :keyword metadata: Arbitrary key-value metadata to associate with the toolbox. Default value is + None. + :paramtype metadata: dict[str, str] + :keyword skills: The list of skill sources to include in this version. A skill reference + specifies a skill name and optionally a version. If version is omitted, the skill's default + version is used. Default value is None. + :paramtype skills: list[~azure.ai.projects.models.ToolboxSkill] + :keyword policies: Policy configuration for this toolbox version. Default value is None. + :paramtype policies: ~azure.ai.projects.models.ToolboxPolicies + :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxVersionObject :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -8385,14 +8183,35 @@ def cancel_optimization_job(self, job_id: str, **kwargs: Any) -> _models.Optimiz } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.ToolboxVersionObject] = kwargs.pop("cls", None) - _request = build_beta_agents_cancel_optimization_job_request( - job_id=job_id, + if body is _Unset: + if tools is _Unset: + raise TypeError("missing required argument: tools") + body = { + "description": description, + "metadata": metadata, + "policies": policies, + "skills": skills, + "tools": tools, + } + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_toolboxes_create_version_request( + name=name, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -8425,7 +8244,7 @@ def cancel_optimization_job(self, job_id: str, **kwargs: Any) -> _models.Optimiz if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.OptimizationJob, response.json()) + deserialized = _deserialize(_models.ToolboxVersionObject, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -8433,20 +8252,15 @@ def cancel_optimization_job(self, job_id: str, **kwargs: Any) -> _models.Optimiz return deserialized # type: ignore @distributed_trace - def delete_optimization_job( # pylint: disable=inconsistent-return-statements - self, job_id: str, *, force: Optional[bool] = None, **kwargs: Any - ) -> None: - """Deletes an agent optimization job. + def get(self, name: str, **kwargs: Any) -> _models.ToolboxObject: + """Retrieve a toolbox. - Delete the job and its candidate artifacts. Cancels first if non-terminal. + Retrieves the specified toolbox and its current configuration. - :param job_id: The ID of the job to delete. Required. - :type job_id: str - :keyword force: When true, force-delete even if the job is in a non-terminal state. Default - value is None. - :paramtype force: bool - :return: None - :rtype: None + :param name: The name of the toolbox to retrieve. Required. + :type name: str + :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxObject :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -8460,11 +8274,10 @@ def delete_optimization_job( # pylint: disable=inconsistent-return-statements _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + cls: ClsType[_models.ToolboxObject] = kwargs.pop("cls", None) - _request = build_beta_agents_delete_optimization_job_request( - job_id=job_id, - force=force, + _request = build_toolboxes_get_request( + name=name, api_version=self._config.api_version, headers=_headers, params=_params, @@ -8474,14 +8287,20 @@ def delete_optimization_job( # pylint: disable=inconsistent-return-statements } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) error = _failsafe_deserialize( _models.ApiErrorResponse, @@ -8489,26 +8308,29 @@ def delete_optimization_job( # pylint: disable=inconsistent-return-statements ) raise HttpResponseError(response=response, model=error) + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.ToolboxObject, response.json()) + if cls: - return cls(pipeline_response, None, {}) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore @distributed_trace - def list_optimization_candidates( + def list( self, - job_id: str, *, limit: Optional[int] = None, order: Optional[Union[str, _models.PageOrder]] = None, - after: Optional[str] = None, before: Optional[str] = None, **kwargs: Any - ) -> _models.AgentsPagedResultOptimizationCandidate: - """Returns a list of candidates for an optimization job. + ) -> ItemPaged["_models.ToolboxObject"]: + """List toolboxes. - List candidates produced by a job. + Returns the toolboxes available in the current project. - :param job_id: The optimization job id. Required. - :type job_id: str :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. Default value is None. @@ -8517,23 +8339,21 @@ def list_optimization_candidates( ascending order and``desc`` for descending order. Known values are: "asc" and "desc". Default value is None. :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword after: A cursor for use in pagination. ``after`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include after=obj_foo in order to fetch the next page of the list. Default - value is None. - :paramtype after: str :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str - :return: AgentsPagedResultOptimizationCandidate. The AgentsPagedResultOptimizationCandidate is - compatible with MutableMapping - :rtype: ~azure.ai.projects.models.AgentsPagedResultOptimizationCandidate + :return: An iterator like instance of ToolboxObject + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.ToolboxObject] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.ToolboxObject]] = kwargs.pop("cls", None) + error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -8542,69 +8362,162 @@ def list_optimization_candidates( } error_map.update(kwargs.pop("error_map", {}) or {}) + def prepare_request(_continuation_token=None): + + _request = build_toolboxes_list_request( + limit=limit, + order=order, + after=_continuation_token, + before=before, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.ToolboxObject], + deserialized.get("data", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("last_id") or None, iter(list_of_elem) + + def get_next(_continuation_token=None): + _request = prepare_request(_continuation_token) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + return pipeline_response + + return ItemPaged(get_next, extract_data) + + @distributed_trace + def list_versions( + self, + name: str, + *, + limit: Optional[int] = None, + order: Optional[Union[str, _models.PageOrder]] = None, + before: Optional[str] = None, + **kwargs: Any + ) -> ItemPaged["_models.ToolboxVersionObject"]: + """List toolbox versions. + + Returns the available versions for the specified toolbox. + + :param name: The name of the toolbox to list versions for. Required. + :type name: str + :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and + 100, and the + default is 20. Default value is None. + :paramtype limit: int + :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for + ascending order and``desc`` + for descending order. Known values are: "asc" and "desc". Default value is None. + :paramtype order: str or ~azure.ai.projects.models.PageOrder + :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your + place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + Default value is None. + :paramtype before: str + :return: An iterator like instance of ToolboxVersionObject + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.ToolboxVersionObject] + :raises ~azure.core.exceptions.HttpResponseError: + """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.AgentsPagedResultOptimizationCandidate] = kwargs.pop("cls", None) + cls: ClsType[List[_models.ToolboxVersionObject]] = kwargs.pop("cls", None) - _request = build_beta_agents_list_optimization_candidates_request( - job_id=job_id, - limit=limit, - order=order, - after=after, - before=before, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + error_map.update(kwargs.pop("error_map", {}) or {}) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + def prepare_request(_continuation_token=None): - response = pipeline_response.http_response + _request = build_toolboxes_list_versions_request( + name=name, + limit=limit, + order=order, + after=_continuation_token, + before=before, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.ToolboxVersionObject], + deserialized.get("data", []), ) - raise HttpResponseError(response=response, model=error) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("last_id") or None, iter(list_of_elem) - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.AgentsPagedResultOptimizationCandidate, response.json()) + def get_next(_continuation_token=None): + _request = prepare_request(_continuation_token) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response - return deserialized # type: ignore + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) + + return pipeline_response + + return ItemPaged(get_next, extract_data) @distributed_trace - def get_optimization_candidate(self, job_id: str, candidate_id: str, **kwargs: Any) -> _models.CandidateMetadata: - """Get a candidate by id. + def get_version(self, name: str, version: str, **kwargs: Any) -> _models.ToolboxVersionObject: + """Retrieve a specific version of a toolbox. - Get a single candidate's metadata, manifest, and promotion info. + Retrieves the specified version of a toolbox by name and version identifier. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id. Required. - :type candidate_id: str - :return: CandidateMetadata. The CandidateMetadata is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.CandidateMetadata + :param name: The name of the toolbox. Required. + :type name: str + :param version: The version identifier to retrieve. Required. + :type version: str + :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxVersionObject :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -8618,11 +8531,11 @@ def get_optimization_candidate(self, job_id: str, candidate_id: str, **kwargs: A _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.CandidateMetadata] = kwargs.pop("cls", None) + cls: ClsType[_models.ToolboxVersionObject] = kwargs.pop("cls", None) - _request = build_beta_agents_get_optimization_candidate_request( - job_id=job_id, - candidate_id=candidate_id, + _request = build_toolboxes_get_version_request( + name=name, + version=version, api_version=self._config.api_version, headers=_headers, params=_params, @@ -8656,100 +8569,91 @@ def get_optimization_candidate(self, job_id: str, candidate_id: str, **kwargs: A if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.CandidateMetadata, response.json()) + deserialized = _deserialize(_models.ToolboxVersionObject, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - @distributed_trace - def get_optimization_candidate_config( - self, job_id: str, candidate_id: str, **kwargs: Any - ) -> _models.CandidateDeployConfig: - """Get candidate deploy config. - - Get the candidate's deploy config JSON. Used to compose ``agents.create_version(...)`` from a - candidate. - - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id. Required. - :type candidate_id: str - :return: CandidateDeployConfig. The CandidateDeployConfig is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.CandidateDeployConfig - :raises ~azure.core.exceptions.HttpResponseError: - """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[_models.CandidateDeployConfig] = kwargs.pop("cls", None) + @overload + def update( + self, name: str, *, default_version: str, content_type: str = "application/json", **kwargs: Any + ) -> _models.ToolboxObject: + """Update a toolbox to point to a specific version. - _request = build_beta_agents_get_optimization_candidate_config_request( - job_id=job_id, - candidate_id=candidate_id, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + Updates the toolbox's default version pointer to the specified version. - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + :param name: The name of the toolbox to update. Required. + :type name: str + :keyword default_version: The version identifier that the toolbox should point to. When set, + the toolbox's default version will resolve to this version instead of the latest. Required. + :paramtype default_version: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxObject + :raises ~azure.core.exceptions.HttpResponseError: + """ - response = pipeline_response.http_response + @overload + def update( + self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.ToolboxObject: + """Update a toolbox to point to a specific version. - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) + Updates the toolbox's default version pointer to the specified version. - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.CandidateDeployConfig, response.json()) + :param name: The name of the toolbox to update. Required. + :type name: str + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxObject + :raises ~azure.core.exceptions.HttpResponseError: + """ - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + @overload + def update( + self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.ToolboxObject: + """Update a toolbox to point to a specific version. - return deserialized # type: ignore + Updates the toolbox's default version pointer to the specified version. + + :param name: The name of the toolbox to update. Required. + :type name: str + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxObject + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace - def get_optimization_candidate_results( - self, job_id: str, candidate_id: str, **kwargs: Any - ) -> _models.CandidateResults: - """Get candidate evaluation results. + def update( + self, name: str, body: Union[JSON, IO[bytes]] = _Unset, *, default_version: str = _Unset, **kwargs: Any + ) -> _models.ToolboxObject: + """Update a toolbox to point to a specific version. - Get full per-task evaluation results for a candidate. + Updates the toolbox's default version pointer to the specified version. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id. Required. - :type candidate_id: str - :return: CandidateResults. The CandidateResults is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.CandidateResults + :param name: The name of the toolbox to update. Required. + :type name: str + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword default_version: The version identifier that the toolbox should point to. When set, + the toolbox's default version will resolve to this version instead of the latest. Required. + :paramtype default_version: str + :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.ToolboxObject :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -8760,15 +8664,29 @@ def get_optimization_candidate_results( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.CandidateResults] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.ToolboxObject] = kwargs.pop("cls", None) - _request = build_beta_agents_get_optimization_candidate_results_request( - job_id=job_id, - candidate_id=candidate_id, + if body is _Unset: + if default_version is _Unset: + raise TypeError("missing required argument: default_version") + body = {"default_version": default_version} + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_toolboxes_update_request( + name=name, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -8801,7 +8719,7 @@ def get_optimization_candidate_results( if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.CandidateResults, response.json()) + deserialized = _deserialize(_models.ToolboxObject, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -8809,19 +8727,15 @@ def get_optimization_candidate_results( return deserialized # type: ignore @distributed_trace - def get_candidate_file(self, job_id: str, candidate_id: str, *, path: str, **kwargs: Any) -> Iterator[bytes]: - """Get a candidate file. + def delete(self, name: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements + """Delete a toolbox. - Stream a specific file from the candidate's blob directory. + Removes the specified toolbox along with all of its versions. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id. Required. - :type candidate_id: str - :keyword path: Relative path of the file to download (e.g. 'files/examples.jsonl'). Required. - :paramtype path: str - :return: Iterator[bytes] - :rtype: Iterator[bytes] + :param name: The name of the toolbox to delete. Required. + :type name: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -8835,12 +8749,10 @@ def get_candidate_file(self, job_id: str, candidate_id: str, *, path: str, **kwa _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_beta_agents_get_candidate_file_request( - job_id=job_id, - candidate_id=candidate_id, - path=path, + _request = build_toolboxes_delete_request( + name=name, api_version=self._config.api_version, headers=_headers, params=_params, @@ -8850,20 +8762,14 @@ def get_candidate_file(self, job_id: str, candidate_id: str, *, path: str, **kwa } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", True) + _stream = False pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass + if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) error = _failsafe_deserialize( _models.ApiErrorResponse, @@ -8871,122 +8777,23 @@ def get_candidate_file(self, job_id: str, candidate_id: str, *, path: str, **kwa ) raise HttpResponseError(response=response, model=error) - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore - - return deserialized # type: ignore - - @overload - def promote_candidate( - self, - job_id: str, - candidate_id: str, - candidate_request: _models.PromoteCandidateRequest, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.PromoteCandidateResponse: - """Promote a candidate. - - Promotes a candidate, recording the deployment timestamp and target agent version. - - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id to promote. Required. - :type candidate_id: str - :param candidate_request: Promotion details. Required. - :type candidate_request: ~azure.ai.projects.models.PromoteCandidateRequest - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: PromoteCandidateResponse. The PromoteCandidateResponse is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.PromoteCandidateResponse - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - def promote_candidate( - self, - job_id: str, - candidate_id: str, - candidate_request: JSON, - *, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.PromoteCandidateResponse: - """Promote a candidate. - - Promotes a candidate, recording the deployment timestamp and target agent version. - - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id to promote. Required. - :type candidate_id: str - :param candidate_request: Promotion details. Required. - :type candidate_request: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: PromoteCandidateResponse. The PromoteCandidateResponse is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.PromoteCandidateResponse - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - def promote_candidate( - self, - job_id: str, - candidate_id: str, - candidate_request: IO[bytes], - *, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.PromoteCandidateResponse: - """Promote a candidate. - - Promotes a candidate, recording the deployment timestamp and target agent version. - - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id to promote. Required. - :type candidate_id: str - :param candidate_request: Promotion details. Required. - :type candidate_request: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: PromoteCandidateResponse. The PromoteCandidateResponse is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.PromoteCandidateResponse - :raises ~azure.core.exceptions.HttpResponseError: - """ + return cls(pipeline_response, None, {}) # type: ignore @distributed_trace - def promote_candidate( - self, - job_id: str, - candidate_id: str, - candidate_request: Union[_models.PromoteCandidateRequest, JSON, IO[bytes]], - **kwargs: Any - ) -> _models.PromoteCandidateResponse: - """Promote a candidate. + def delete_version( # pylint: disable=inconsistent-return-statements + self, name: str, version: str, **kwargs: Any + ) -> None: + """Delete a specific version of a toolbox. - Promotes a candidate, recording the deployment timestamp and target agent version. + Removes the specified version of a toolbox. - :param job_id: The optimization job id. Required. - :type job_id: str - :param candidate_id: The candidate id to promote. Required. - :type candidate_id: str - :param candidate_request: Promotion details. Is one of the following types: - PromoteCandidateRequest, JSON, IO[bytes] Required. - :type candidate_request: ~azure.ai.projects.models.PromoteCandidateRequest or JSON or IO[bytes] - :return: PromoteCandidateResponse. The PromoteCandidateResponse is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.PromoteCandidateResponse + :param name: The name of the toolbox. Required. + :type name: str + :param version: The version identifier to delete. Required. + :type version: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -8997,25 +8804,15 @@ def promote_candidate( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.PromoteCandidateResponse] = kwargs.pop("cls", None) - - content_type = content_type or "application/json" - _content = None - if isinstance(candidate_request, (IOBase, bytes)): - _content = candidate_request - else: - _content = json.dumps(candidate_request, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_beta_agents_promote_candidate_request( - job_id=job_id, - candidate_id=candidate_id, - content_type=content_type, + _request = build_toolboxes_delete_version_request( + name=name, + version=version, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -9024,20 +8821,14 @@ def promote_candidate( } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = False pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass + if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) error = _failsafe_deserialize( _models.ApiErrorResponse, @@ -9045,15 +8836,8 @@ def promote_candidate( ) raise HttpResponseError(response=response, model=error) - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.PromoteCandidateResponse, response.json()) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore - - return deserialized # type: ignore + return cls(pipeline_response, None, {}) # type: ignore class BetaEvaluationTaxonomiesOperations: @@ -9075,7 +8859,9 @@ def __init__(self, *args, **kwargs) -> None: @distributed_trace def get(self, name: str, **kwargs: Any) -> _models.EvaluationTaxonomy: - """Get an evaluation run by name. + """Get an evaluation taxonomy. + + Retrieves the specified evaluation taxonomy. :param name: The name of the resource. Required. :type name: str @@ -9140,6 +8926,9 @@ def list( ) -> ItemPaged["_models.EvaluationTaxonomy"]: """List evaluation taxonomies. + Returns the evaluation taxonomies available in the project, optionally filtered by input name + or input type. + :keyword input_name: Filter by the evaluation input name. Default value is None. :paramtype input_name: str :keyword input_type: Filter by taxonomy input type. Default value is None. @@ -9232,7 +9021,9 @@ def get_next(next_link=None): @distributed_trace def delete(self, name: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements - """Delete an evaluation taxonomy by name. + """Delete an evaluation taxonomy. + + Removes the specified evaluation taxonomy from the project. :param name: The name of the resource. Required. :type name: str @@ -9284,6 +9075,8 @@ def create( ) -> _models.EvaluationTaxonomy: """Create an evaluation taxonomy. + Creates or replaces the specified evaluation taxonomy with the provided definition. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -9302,6 +9095,8 @@ def create( ) -> _models.EvaluationTaxonomy: """Create an evaluation taxonomy. + Creates or replaces the specified evaluation taxonomy with the provided definition. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -9320,6 +9115,8 @@ def create( ) -> _models.EvaluationTaxonomy: """Create an evaluation taxonomy. + Creates or replaces the specified evaluation taxonomy with the provided definition. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -9338,6 +9135,8 @@ def create( ) -> _models.EvaluationTaxonomy: """Create an evaluation taxonomy. + Creates or replaces the specified evaluation taxonomy with the provided definition. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Is one of the following types: EvaluationTaxonomy, @@ -9414,6 +9213,8 @@ def update( ) -> _models.EvaluationTaxonomy: """Update an evaluation taxonomy. + Update an evaluation taxonomy. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -9432,6 +9233,8 @@ def update( ) -> _models.EvaluationTaxonomy: """Update an evaluation taxonomy. + Update an evaluation taxonomy. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -9450,6 +9253,8 @@ def update( ) -> _models.EvaluationTaxonomy: """Update an evaluation taxonomy. + Update an evaluation taxonomy. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Required. @@ -9468,6 +9273,8 @@ def update( ) -> _models.EvaluationTaxonomy: """Update an evaluation taxonomy. + Update an evaluation taxonomy. + :param name: The name of the evaluation taxonomy. Required. :type name: str :param taxonomy: The evaluation taxonomy. Is one of the following types: EvaluationTaxonomy, @@ -9565,7 +9372,9 @@ def list_versions( limit: Optional[int] = None, **kwargs: Any ) -> ItemPaged["_models.EvaluatorVersion"]: - """List all versions of the given evaluator. + """List evaluator versions. + + Returns the available versions for the specified evaluator. :param name: The name of the resource. Required. :type name: str @@ -9671,7 +9480,9 @@ def list( limit: Optional[int] = None, **kwargs: Any ) -> ItemPaged["_models.EvaluatorVersion"]: - """List the latest version of each evaluator. + """List latest evaluator versions. + + Lists the latest version of each evaluator. :keyword type: Filter evaluators by type. Possible values: 'all', 'custom', 'builtin'. Is one of the following types: Literal["builtin"], Literal["custom"], Literal["all"], str Default @@ -9768,8 +9579,9 @@ def get_next(next_link=None): @distributed_trace def get_version(self, name: str, version: str, **kwargs: Any) -> _models.EvaluatorVersion: - """Get the specific version of the EvaluatorVersion. The service returns 404 Not Found error if - the EvaluatorVersion does not exist. + """Get an evaluator version. + + Retrieves the specified evaluator version, returning 404 if it does not exist. :param name: The name of the resource. Required. :type name: str @@ -9835,8 +9647,9 @@ def get_version(self, name: str, version: str, **kwargs: Any) -> _models.Evaluat def delete_version( # pylint: disable=inconsistent-return-statements self, name: str, version: str, **kwargs: Any ) -> None: - """Delete the specific version of the EvaluatorVersion. The service returns 204 No Content if the - EvaluatorVersion was deleted successfully or if the EvaluatorVersion does not exist. + """Delete an evaluator version. + + Removes the specified evaluator version. Returns 204 whether the version existed or not. :param name: The name of the resource. Required. :type name: str @@ -9894,7 +9707,9 @@ def create_version( content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Create a new EvaluatorVersion with auto incremented version id. + """Create an evaluator version. + + Creates a new evaluator version with an auto-incremented version identifier. :param name: The name of the resource. Required. :type name: str @@ -9912,7 +9727,9 @@ def create_version( def create_version( self, name: str, evaluator_version: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Create a new EvaluatorVersion with auto incremented version id. + """Create an evaluator version. + + Creates a new evaluator version with an auto-incremented version identifier. :param name: The name of the resource. Required. :type name: str @@ -9930,7 +9747,9 @@ def create_version( def create_version( self, name: str, evaluator_version: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Create a new EvaluatorVersion with auto incremented version id. + """Create an evaluator version. + + Creates a new evaluator version with an auto-incremented version identifier. :param name: The name of the resource. Required. :type name: str @@ -9948,7 +9767,9 @@ def create_version( def create_version( self, name: str, evaluator_version: Union[_models.EvaluatorVersion, JSON, IO[bytes]], **kwargs: Any ) -> _models.EvaluatorVersion: - """Create a new EvaluatorVersion with auto incremented version id. + """Create an evaluator version. + + Creates a new evaluator version with an auto-incremented version identifier. :param name: The name of the resource. Required. :type name: str @@ -10030,7 +9851,9 @@ def update_version( content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Update an existing EvaluatorVersion with the given version id. + """Update an evaluator version. + + Updates the specified evaluator version in place. :param name: The name of the resource. Required. :type name: str @@ -10050,7 +9873,9 @@ def update_version( def update_version( self, name: str, version: str, evaluator_version: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Update an existing EvaluatorVersion with the given version id. + """Update an evaluator version. + + Updates the specified evaluator version in place. :param name: The name of the resource. Required. :type name: str @@ -10076,7 +9901,9 @@ def update_version( content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorVersion: - """Update an existing EvaluatorVersion with the given version id. + """Update an evaluator version. + + Updates the specified evaluator version in place. :param name: The name of the resource. Required. :type name: str @@ -10100,7 +9927,9 @@ def update_version( evaluator_version: Union[_models.EvaluatorVersion, JSON, IO[bytes]], **kwargs: Any ) -> _models.EvaluatorVersion: - """Update an existing EvaluatorVersion with the given version id. + """Update an evaluator version. + + Updates the specified evaluator version in place. :param name: The name of the resource. Required. :type name: str @@ -10185,7 +10014,10 @@ def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of an evaluator for a specific version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified evaluator + version. :param name: Required. :type name: str @@ -10211,7 +10043,10 @@ def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of an evaluator for a specific version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified evaluator + version. :param name: Required. :type name: str @@ -10237,7 +10072,10 @@ def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of an evaluator for a specific version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified evaluator + version. :param name: Required. :type name: str @@ -10261,7 +10099,10 @@ def pending_upload( pending_upload_request: Union[_models.PendingUploadRequest, JSON, IO[bytes]], **kwargs: Any ) -> _models.PendingUploadResponse: - """Start a new or get an existing pending upload of an evaluator for a specific version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified evaluator + version. :param name: Required. :type name: str @@ -10351,7 +10192,10 @@ def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get the SAS credential to access the storage account associated with an Evaluator version. + """Get evaluator credentials. + + Retrieves SAS credentials for accessing the storage account associated with the specified + evaluator version. :param name: Required. :type name: str @@ -10377,7 +10221,10 @@ def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get the SAS credential to access the storage account associated with an Evaluator version. + """Get evaluator credentials. + + Retrieves SAS credentials for accessing the storage account associated with the specified + evaluator version. :param name: Required. :type name: str @@ -10403,7 +10250,10 @@ def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get the SAS credential to access the storage account associated with an Evaluator version. + """Get evaluator credentials. + + Retrieves SAS credentials for accessing the storage account associated with the specified + evaluator version. :param name: Required. :type name: str @@ -10427,7 +10277,10 @@ def get_credentials( credential_request: Union[_models.EvaluatorCredentialRequest, JSON, IO[bytes]], **kwargs: Any ) -> _models.DatasetCredential: - """Get the SAS credential to access the storage account associated with an Evaluator version. + """Get evaluator credentials. + + Retrieves SAS credentials for accessing the storage account associated with the specified + evaluator version. :param name: Required. :type name: str @@ -10516,7 +10369,7 @@ def create_generation_job( content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorGenerationJob: - """Creates an evaluator generation job. + """Create an evaluator generation job. Creates an evaluator generation job. The service generates rubric-based evaluator definitions from the provided source materials asynchronously. @@ -10538,7 +10391,7 @@ def create_generation_job( def create_generation_job( self, job: JSON, *, operation_id: Optional[str] = None, content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorGenerationJob: - """Creates an evaluator generation job. + """Create an evaluator generation job. Creates an evaluator generation job. The service generates rubric-based evaluator definitions from the provided source materials asynchronously. @@ -10565,7 +10418,7 @@ def create_generation_job( content_type: str = "application/json", **kwargs: Any ) -> _models.EvaluatorGenerationJob: - """Creates an evaluator generation job. + """Create an evaluator generation job. Creates an evaluator generation job. The service generates rubric-based evaluator definitions from the provided source materials asynchronously. @@ -10591,7 +10444,7 @@ def create_generation_job( operation_id: Optional[str] = None, **kwargs: Any ) -> _models.EvaluatorGenerationJob: - """Creates an evaluator generation job. + """Create an evaluator generation job. Creates an evaluator generation job. The service generates rubric-based evaluator definitions from the provided source materials asynchronously. @@ -10677,7 +10530,7 @@ def create_generation_job( @distributed_trace def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.EvaluatorGenerationJob: - """Get info about an evaluator generation job. + """Get an evaluator generation job. Gets the details of an evaluator generation job by its ID. @@ -10754,9 +10607,11 @@ def list_generation_jobs( before: Optional[str] = None, **kwargs: Any ) -> ItemPaged["_models.EvaluatorGenerationJob"]: - """Returns a list of evaluator generation jobs. + """List evaluator generation jobs. - Returns a list of evaluator generation jobs. + Returns a list of evaluator generation jobs. The List API has up to a few seconds of + propagation delay, so a recently created job may not appear immediately; use the Get evaluator + generation job API with the job ID to retrieve a specific job without delay. :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the @@ -10839,7 +10694,7 @@ def get_next(_continuation_token=None): @distributed_trace def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.EvaluatorGenerationJob: - """Cancels an evaluator generation job. + """Cancel an evaluator generation job. Cancels an evaluator generation job by its ID. @@ -10908,7 +10763,9 @@ def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.Evaluator def delete_generation_job( # pylint: disable=inconsistent-return-statements self, job_id: str, **kwargs: Any ) -> None: - """Deletes an evaluator generation job by its ID. Deletes the job record only; the generated + """Delete an evaluator generation job. + + Deletes an evaluator generation job by its ID. Deletes the job record only; the generated evaluator (if any) is preserved. :param job_id: The ID of the job to delete. Required. @@ -10981,7 +10838,9 @@ def __init__(self, *args, **kwargs) -> None: def generate( self, insight: _models.Insight, *, content_type: str = "application/json", **kwargs: Any ) -> _models.Insight: - """Generate Insights. + """Generate insights. + + Generates an insights report from the provided evaluation configuration. :param insight: Complete evaluation configuration including data source, evaluators, and result settings. Required. @@ -10996,7 +10855,9 @@ def generate( @overload def generate(self, insight: JSON, *, content_type: str = "application/json", **kwargs: Any) -> _models.Insight: - """Generate Insights. + """Generate insights. + + Generates an insights report from the provided evaluation configuration. :param insight: Complete evaluation configuration including data source, evaluators, and result settings. Required. @@ -11011,7 +10872,9 @@ def generate(self, insight: JSON, *, content_type: str = "application/json", **k @overload def generate(self, insight: IO[bytes], *, content_type: str = "application/json", **kwargs: Any) -> _models.Insight: - """Generate Insights. + """Generate insights. + + Generates an insights report from the provided evaluation configuration. :param insight: Complete evaluation configuration including data source, evaluators, and result settings. Required. @@ -11026,7 +10889,9 @@ def generate(self, insight: IO[bytes], *, content_type: str = "application/json" @distributed_trace def generate(self, insight: Union[_models.Insight, JSON, IO[bytes]], **kwargs: Any) -> _models.Insight: - """Generate Insights. + """Generate insights. + + Generates an insights report from the provided evaluation configuration. :param insight: Complete evaluation configuration including data source, evaluators, and result settings. Is one of the following types: Insight, JSON, IO[bytes] Required. @@ -11101,7 +10966,9 @@ def generate(self, insight: Union[_models.Insight, JSON, IO[bytes]], **kwargs: A @distributed_trace def get(self, insight_id: str, *, include_coordinates: Optional[bool] = None, **kwargs: Any) -> _models.Insight: - """Get a specific insight by Id. + """Get an insight. + + Retrieves the specified insight report and its results. :param insight_id: The unique identifier for the insights report. Required. :type insight_id: str @@ -11179,7 +11046,9 @@ def list( include_coordinates: Optional[bool] = None, **kwargs: Any ) -> ItemPaged["_models.Insight"]: - """List all insights in reverse chronological order (newest first). + """List insights. + + Returns insights in reverse chronological order, with the most recent entries first. :keyword type: Filter by the type of analysis. Known values are: "EvaluationRunClusterInsight", "AgentClusterInsight", and "EvaluationComparison". Default value is None. @@ -11317,6 +11186,8 @@ def create( ) -> _models.MemoryStoreDetails: """Create a memory store. + Creates a memory store resource with the provided configuration. + :keyword name: The name of the memory store. Required. :paramtype name: str :keyword definition: The memory store definition. Required. @@ -11340,6 +11211,8 @@ def create( ) -> _models.MemoryStoreDetails: """Create a memory store. + Creates a memory store resource with the provided configuration. + :param body: Required. :type body: JSON :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. @@ -11356,6 +11229,8 @@ def create( ) -> _models.MemoryStoreDetails: """Create a memory store. + Creates a memory store resource with the provided configuration. + :param body: Required. :type body: IO[bytes] :keyword content_type: Body Parameter content-type. Content type parameter for binary body. @@ -11379,6 +11254,8 @@ def create( ) -> _models.MemoryStoreDetails: """Create a memory store. + Creates a memory store resource with the provided configuration. + :param body: Is either a JSON type or a IO[bytes] type. Required. :type body: JSON or IO[bytes] :keyword name: The name of the memory store. Required. @@ -11477,6 +11354,8 @@ def update( ) -> _models.MemoryStoreDetails: """Update a memory store. + Updates the specified memory store with the supplied configuration changes. + :param name: The name of the memory store to update. Required. :type name: str :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. @@ -11498,6 +11377,8 @@ def update( ) -> _models.MemoryStoreDetails: """Update a memory store. + Updates the specified memory store with the supplied configuration changes. + :param name: The name of the memory store to update. Required. :type name: str :param body: Required. @@ -11516,6 +11397,8 @@ def update( ) -> _models.MemoryStoreDetails: """Update a memory store. + Updates the specified memory store with the supplied configuration changes. + :param name: The name of the memory store to update. Required. :type name: str :param body: Required. @@ -11540,6 +11423,8 @@ def update( ) -> _models.MemoryStoreDetails: """Update a memory store. + Updates the specified memory store with the supplied configuration changes. + :param name: The name of the memory store to update. Required. :type name: str :param body: Is either a JSON type or a IO[bytes] type. Required. @@ -11623,7 +11508,9 @@ def update( @distributed_trace def get(self, name: str, **kwargs: Any) -> _models.MemoryStoreDetails: - """Retrieve a memory store. + """Get a memory store. + + Retrieves the specified memory store and its current configuration. :param name: The name of the memory store to retrieve. Required. :type name: str @@ -11695,7 +11582,9 @@ def list( before: Optional[str] = None, **kwargs: Any ) -> ItemPaged["_models.MemoryStoreDetails"]: - """List all memory stores. + """List memory stores. + + Returns the memory stores available to the caller. :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the @@ -11780,6 +11669,8 @@ def get_next(_continuation_token=None): def delete(self, name: str, **kwargs: Any) -> _models.DeleteMemoryStoreResult: """Delete a memory store. + Deletes the specified memory store. + :param name: The name of the memory store to delete. Required. :type name: str :return: DeleteMemoryStoreResult. The DeleteMemoryStoreResult is compatible with MutableMapping @@ -11874,7 +11765,9 @@ def _search_memories( options: Optional[_models.MemorySearchOptions] = None, **kwargs: Any ) -> _models.MemoryStoreSearchResult: - """Search for relevant memories from a memory store based on conversation context. + """Search memories. + + Searches the specified memory store for memories relevant to the provided conversation context. :param name: The name of the memory store to search. Required. :type name: str @@ -12082,7 +11975,10 @@ def _begin_update_memories( update_delay: Optional[int] = None, **kwargs: Any ) -> LROPoller[_models.MemoryStoreUpdateCompletedResult]: - """Update memory store with conversation memories. + """Update memories. + + Starts an update that writes conversation memories into the specified memory store. The + operation returns a long-running status location for polling the update result. :param name: The name of the memory store to update. Required. :type name: str @@ -12172,7 +12068,9 @@ def get_long_running_output(pipeline_response): def delete_scope( self, name: str, *, scope: str, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryStoreDeleteScopeResult: - """Delete all memories associated with a specific scope from a memory store. + """Delete memories by scope. + + Deletes all memories in the specified memory store that are associated with the provided scope. :param name: The name of the memory store. Required. :type name: str @@ -12192,7 +12090,9 @@ def delete_scope( def delete_scope( self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryStoreDeleteScopeResult: - """Delete all memories associated with a specific scope from a memory store. + """Delete memories by scope. + + Deletes all memories in the specified memory store that are associated with the provided scope. :param name: The name of the memory store. Required. :type name: str @@ -12211,7 +12111,9 @@ def delete_scope( def delete_scope( self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryStoreDeleteScopeResult: - """Delete all memories associated with a specific scope from a memory store. + """Delete memories by scope. + + Deletes all memories in the specified memory store that are associated with the provided scope. :param name: The name of the memory store. Required. :type name: str @@ -12230,7 +12132,9 @@ def delete_scope( def delete_scope( self, name: str, body: Union[JSON, IO[bytes]] = _Unset, *, scope: str = _Unset, **kwargs: Any ) -> _models.MemoryStoreDeleteScopeResult: - """Delete all memories associated with a specific scope from a memory store. + """Delete memories by scope. + + Deletes all memories in the specified memory store that are associated with the provided scope. :param name: The name of the memory store. Required. :type name: str @@ -12325,7 +12229,9 @@ def create_memory( content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Create a memory item in a memory store. + """Create a memory item. + + Creates a memory item in the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -12349,7 +12255,9 @@ def create_memory( def create_memory( self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Create a memory item in a memory store. + """Create a memory item. + + Creates a memory item in the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -12367,7 +12275,9 @@ def create_memory( def create_memory( self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Create a memory item in a memory store. + """Create a memory item. + + Creates a memory item in the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -12392,7 +12302,9 @@ def create_memory( kind: Union[str, _models.MemoryItemKind] = _Unset, **kwargs: Any ) -> _models.MemoryItem: - """Create a memory item in a memory store. + """Create a memory item. + + Creates a memory item in the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -12488,7 +12400,9 @@ def create_memory( def update_memory( self, name: str, memory_id: str, *, content: str, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Update a memory item in a memory store. + """Update a memory item. + + Updates the specified memory item in the memory store. :param name: The name of the memory store. Required. :type name: str @@ -12508,7 +12422,9 @@ def update_memory( def update_memory( self, name: str, memory_id: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Update a memory item in a memory store. + """Update a memory item. + + Updates the specified memory item in the memory store. :param name: The name of the memory store. Required. :type name: str @@ -12528,7 +12444,9 @@ def update_memory( def update_memory( self, name: str, memory_id: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.MemoryItem: - """Update a memory item in a memory store. + """Update a memory item. + + Updates the specified memory item in the memory store. :param name: The name of the memory store. Required. :type name: str @@ -12548,7 +12466,9 @@ def update_memory( def update_memory( self, name: str, memory_id: str, body: Union[JSON, IO[bytes]] = _Unset, *, content: str = _Unset, **kwargs: Any ) -> _models.MemoryItem: - """Update a memory item in a memory store. + """Update a memory item. + + Updates the specified memory item in the memory store. :param name: The name of the memory store. Required. :type name: str @@ -12635,7 +12555,9 @@ def update_memory( @distributed_trace def get_memory(self, name: str, memory_id: str, **kwargs: Any) -> _models.MemoryItem: - """Retrieve a memory item from a memory store. + """Get a memory item. + + Retrieves the specified memory item from the memory store. :param name: The name of the memory store. Required. :type name: str @@ -12714,7 +12636,9 @@ def list_memories( content_type: str = "application/json", **kwargs: Any ) -> ItemPaged["_models.MemoryItem"]: - """List all memory items in a memory store. + """List memory items. + + Returns memory items from the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -12759,7 +12683,9 @@ def list_memories( content_type: str = "application/json", **kwargs: Any ) -> ItemPaged["_models.MemoryItem"]: - """List all memory items in a memory store. + """List memory items. + + Returns memory items from the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -12803,7 +12729,9 @@ def list_memories( content_type: str = "application/json", **kwargs: Any ) -> ItemPaged["_models.MemoryItem"]: - """List all memory items in a memory store. + """List memory items. + + Returns memory items from the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -12847,7 +12775,9 @@ def list_memories( before: Optional[str] = None, **kwargs: Any ) -> ItemPaged["_models.MemoryItem"]: - """List all memory items in a memory store. + """List memory items. + + Returns memory items from the specified memory store. :param name: The name of the memory store. Required. :type name: str @@ -12890,14 +12820,11 @@ def list_memories( 304: ResourceNotModifiedError, } error_map.update(kwargs.pop("error_map", {}) or {}) - - # BUG? These lines were inside the prepare_request() method. Moved here instead. if body is _Unset: if scope is _Unset: raise TypeError("missing required argument: scope") body = {"scope": scope} body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/json" _content = None if isinstance(body, (IOBase, bytes)): @@ -12906,11 +12833,6 @@ def list_memories( _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore def prepare_request(_continuation_token=None): - # if body is _Unset: - # if scope is _Unset: - # raise TypeError("missing required argument: scope") - # body = {"scope": scope} - # body = {k: v for k, v in body.items() if v is not None} _request = build_beta_memory_stores_list_memories_request( name=name, @@ -12964,7 +12886,9 @@ def get_next(_continuation_token=None): @distributed_trace def delete_memory(self, name: str, memory_id: str, **kwargs: Any) -> _models.DeleteMemoryResult: - """Delete a memory item from a memory store. + """Delete a memory item. + + Deletes the specified memory item from the memory store. :param name: The name of the memory store. Required. :type name: str @@ -13050,7 +12974,9 @@ def __init__(self, *args, **kwargs) -> None: @distributed_trace def list_versions(self, name: str, **kwargs: Any) -> ItemPaged["_models.ModelVersion"]: - """List all versions of the given ModelVersion. + """List versions. + + List all versions of the given ModelVersion. :param name: The name of the resource. Required. :type name: str @@ -13141,7 +13067,9 @@ def get_next(next_link=None): @distributed_trace def list(self, **kwargs: Any) -> ItemPaged["_models.ModelVersion"]: - """List the latest version of each ModelVersion. + """List latest versions. + + List the latest version of each ModelVersion. :return: An iterator like instance of ModelVersion :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.ModelVersion] @@ -13229,8 +13157,9 @@ def get_next(next_link=None): @distributed_trace def get(self, name: str, version: str, **kwargs: Any) -> _models.ModelVersion: - """Get the specific version of the ModelVersion. The service returns 404 Not Found error if the - ModelVersion does not exist. + """Get a model version. + + Retrieves the specified model version, returning 404 if it does not exist. :param name: The name of the resource. Required. :type name: str @@ -13294,7 +13223,9 @@ def get(self, name: str, version: str, **kwargs: Any) -> _models.ModelVersion: @distributed_trace def delete(self, name: str, version: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements - """Delete the specific version of the ModelVersion. The service returns 200 OK if the ModelVersion + """Delete a model version. + + Delete the specific version of the ModelVersion. The service returns 200 OK if the ModelVersion was deleted successfully or if the ModelVersion does not exist. :param name: The name of the resource. Required. @@ -13354,7 +13285,9 @@ def update( content_type: str = "application/merge-patch+json", **kwargs: Any ) -> _models.ModelVersion: - """Update an existing ModelVersion with the given version id. + """Update a model version. + + Update an existing ModelVersion with the given version id. :param name: The name of the resource. Required. :type name: str @@ -13381,7 +13314,9 @@ def update( content_type: str = "application/merge-patch+json", **kwargs: Any ) -> _models.ModelVersion: - """Update an existing ModelVersion with the given version id. + """Update a model version. + + Update an existing ModelVersion with the given version id. :param name: The name of the resource. Required. :type name: str @@ -13408,7 +13343,9 @@ def update( content_type: str = "application/merge-patch+json", **kwargs: Any ) -> _models.ModelVersion: - """Update an existing ModelVersion with the given version id. + """Update a model version. + + Update an existing ModelVersion with the given version id. :param name: The name of the resource. Required. :type name: str @@ -13433,7 +13370,9 @@ def update( model_version_update: Union[_models.UpdateModelVersionRequest, JSON, IO[bytes]], **kwargs: Any ) -> _models.ModelVersion: - """Update an existing ModelVersion with the given version id. + """Update a model version. + + Update an existing ModelVersion with the given version id. :param name: The name of the resource. Required. :type name: str @@ -13520,8 +13459,10 @@ def pending_create_version( content_type: str = "application/json", **kwargs: Any ) -> _models.CreateAsyncResponse: - """Creates a model version asynchronously with blob content validation. Returns 202 Accepted with - a Location header for polling. + """Create a model version async. + + Creates a model version asynchronously with blob content validation. Returns 202 Accepted with + a location header for polling the operation status. :param name: Name of the model. Required. :type name: str @@ -13541,8 +13482,10 @@ def pending_create_version( def pending_create_version( self, name: str, version: str, model_version: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.CreateAsyncResponse: - """Creates a model version asynchronously with blob content validation. Returns 202 Accepted with - a Location header for polling. + """Create a model version async. + + Creates a model version asynchronously with blob content validation. Returns 202 Accepted with + a location header for polling the operation status. :param name: Name of the model. Required. :type name: str @@ -13568,8 +13511,10 @@ def pending_create_version( content_type: str = "application/json", **kwargs: Any ) -> _models.CreateAsyncResponse: - """Creates a model version asynchronously with blob content validation. Returns 202 Accepted with - a Location header for polling. + """Create a model version async. + + Creates a model version asynchronously with blob content validation. Returns 202 Accepted with + a location header for polling the operation status. :param name: Name of the model. Required. :type name: str @@ -13589,8 +13534,10 @@ def pending_create_version( def pending_create_version( self, name: str, version: str, model_version: Union[_models.ModelVersion, JSON, IO[bytes]], **kwargs: Any ) -> _models.CreateAsyncResponse: - """Creates a model version asynchronously with blob content validation. Returns 202 Accepted with - a Location header for polling. + """Create a model version async. + + Creates a model version asynchronously with blob content validation. Returns 202 Accepted with + a location header for polling the operation status. :param name: Name of the model. Required. :type name: str @@ -13678,7 +13625,9 @@ def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.ModelPendingUploadResponse: - """Start or retrieve a pending upload for a model version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified model version. :param name: Name of the model. Required. :type name: str @@ -13705,7 +13654,9 @@ def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.ModelPendingUploadResponse: - """Start or retrieve a pending upload for a model version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified model version. :param name: Name of the model. Required. :type name: str @@ -13732,7 +13683,9 @@ def pending_upload( content_type: str = "application/json", **kwargs: Any ) -> _models.ModelPendingUploadResponse: - """Start or retrieve a pending upload for a model version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified model version. :param name: Name of the model. Required. :type name: str @@ -13757,7 +13710,9 @@ def pending_upload( pending_upload_request: Union[_models.ModelPendingUploadRequest, JSON, IO[bytes]], **kwargs: Any ) -> _models.ModelPendingUploadResponse: - """Start or retrieve a pending upload for a model version. + """Start a pending upload. + + Initiates a new pending upload or retrieves an existing one for the specified model version. :param name: Name of the model. Required. :type name: str @@ -13844,7 +13799,9 @@ def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get credentials for a model version asset. + """Get model asset credentials. + + Retrieves temporary credentials for accessing the storage backing the specified model version. :param name: Name of the model. Required. :type name: str @@ -13870,7 +13827,9 @@ def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get credentials for a model version asset. + """Get model asset credentials. + + Retrieves temporary credentials for accessing the storage backing the specified model version. :param name: Name of the model. Required. :type name: str @@ -13896,7 +13855,9 @@ def get_credentials( content_type: str = "application/json", **kwargs: Any ) -> _models.DatasetCredential: - """Get credentials for a model version asset. + """Get model asset credentials. + + Retrieves temporary credentials for accessing the storage backing the specified model version. :param name: Name of the model. Required. :type name: str @@ -13920,7 +13881,9 @@ def get_credentials( credential_request: Union[_models.ModelCredentialRequest, JSON, IO[bytes]], **kwargs: Any ) -> _models.DatasetCredential: - """Get credentials for a model version asset. + """Get model asset credentials. + + Retrieves temporary credentials for accessing the storage backing the specified model version. :param name: Name of the model. Required. :type name: str @@ -14015,7 +13978,9 @@ def __init__(self, *args, **kwargs) -> None: @distributed_trace def get(self, name: str, **kwargs: Any) -> _models.RedTeam: - """Get a redteam by name. + """Get a redteam. + + Retrieves the specified redteam and its configuration. :param name: Identifier of the red team run. Required. :type name: str @@ -14076,7 +14041,9 @@ def get(self, name: str, **kwargs: Any) -> _models.RedTeam: @distributed_trace def list(self, **kwargs: Any) -> ItemPaged["_models.RedTeam"]: - """List a redteam by name. + """List redteams. + + Returns the redteams available in the current project. :return: An iterator like instance of RedTeam :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.RedTeam] @@ -14166,7 +14133,9 @@ def get_next(next_link=None): def create( self, red_team: _models.RedTeam, *, content_type: str = "application/json", **kwargs: Any ) -> _models.RedTeam: - """Creates a redteam run. + """Create a redteam run. + + Submits a new redteam run for execution with the provided configuration. :param red_team: Redteam to be run. Required. :type red_team: ~azure.ai.projects.models.RedTeam @@ -14180,7 +14149,9 @@ def create( @overload def create(self, red_team: JSON, *, content_type: str = "application/json", **kwargs: Any) -> _models.RedTeam: - """Creates a redteam run. + """Create a redteam run. + + Submits a new redteam run for execution with the provided configuration. :param red_team: Redteam to be run. Required. :type red_team: JSON @@ -14194,7 +14165,9 @@ def create(self, red_team: JSON, *, content_type: str = "application/json", **kw @overload def create(self, red_team: IO[bytes], *, content_type: str = "application/json", **kwargs: Any) -> _models.RedTeam: - """Creates a redteam run. + """Create a redteam run. + + Submits a new redteam run for execution with the provided configuration. :param red_team: Redteam to be run. Required. :type red_team: IO[bytes] @@ -14208,7 +14181,9 @@ def create(self, red_team: IO[bytes], *, content_type: str = "application/json", @distributed_trace def create(self, red_team: Union[_models.RedTeam, JSON, IO[bytes]], **kwargs: Any) -> _models.RedTeam: - """Creates a redteam run. + """Create a redteam run. + + Submits a new redteam run for execution with the provided configuration. :param red_team: Redteam to be run. Is one of the following types: RedTeam, JSON, IO[bytes] Required. @@ -14313,6 +14288,8 @@ def create_or_update( ) -> _models.Routine: """Create or update a routine. + Creates a new routine or replaces an existing routine with the supplied definition. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. @@ -14338,6 +14315,8 @@ def create_or_update( ) -> _models.Routine: """Create or update a routine. + Creates a new routine or replaces an existing routine with the supplied definition. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Required. @@ -14356,6 +14335,8 @@ def create_or_update( ) -> _models.Routine: """Create or update a routine. + Creates a new routine or replaces an existing routine with the supplied definition. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Required. @@ -14382,6 +14363,8 @@ def create_or_update( ) -> _models.Routine: """Create or update a routine. + Creates a new routine or replaces an existing routine with the supplied definition. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Is either a JSON type or a IO[bytes] type. Required. @@ -14469,7 +14452,9 @@ def create_or_update( @distributed_trace def get(self, routine_name: str, **kwargs: Any) -> _models.Routine: - """Retrieve a routine. + """Get a routine. + + Retrieves the specified routine and its current configuration. :param routine_name: The unique name of the routine. Required. :type routine_name: str @@ -14536,6 +14521,8 @@ def get(self, routine_name: str, **kwargs: Any) -> _models.Routine: def enable(self, routine_name: str, **kwargs: Any) -> _models.Routine: """Enable a routine. + Enables the specified routine so it can be dispatched. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :return: Routine. The Routine is compatible with MutableMapping @@ -14601,6 +14588,8 @@ def enable(self, routine_name: str, **kwargs: Any) -> _models.Routine: def disable(self, routine_name: str, **kwargs: Any) -> _models.Routine: """Disable a routine. + Disables the specified routine so it no longer runs. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :return: Routine. The Routine is compatible with MutableMapping @@ -14668,6 +14657,8 @@ def list( ) -> ItemPaged["_models.Routine"]: """List routines. + Returns the routines available in the current project. + :keyword limit: The maximum number of routines to return. Default value is None. :paramtype limit: int :keyword before: Unsupported. Reserved for future backward pagination support. Default value is @@ -14745,6 +14736,8 @@ def get_next(_continuation_token=None): def delete(self, routine_name: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements """Delete a routine. + Deletes the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :return: None @@ -14806,6 +14799,8 @@ def list_runs( ) -> ItemPaged["_models.RoutineRun"]: """List prior runs for a routine. + Returns prior runs recorded for the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :keyword filter: An optional MLflow search-runs filter expression applied within the routine's @@ -14897,6 +14892,8 @@ def dispatch( ) -> _models.DispatchRoutineResult: """Queue an asynchronous routine dispatch. + Queues an asynchronous dispatch for the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. @@ -14916,6 +14913,8 @@ def dispatch( ) -> _models.DispatchRoutineResult: """Queue an asynchronous routine dispatch. + Queues an asynchronous dispatch for the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Required. @@ -14934,6 +14933,8 @@ def dispatch( ) -> _models.DispatchRoutineResult: """Queue an asynchronous routine dispatch. + Queues an asynchronous dispatch for the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Required. @@ -14957,6 +14958,8 @@ def dispatch( ) -> _models.DispatchRoutineResult: """Queue an asynchronous routine dispatch. + Queues an asynchronous dispatch for the specified routine. + :param routine_name: The unique name of the routine. Required. :type routine_name: str :param body: Is either a JSON type or a IO[bytes] type. Required. @@ -15058,6 +15061,8 @@ def __init__(self, *args, **kwargs) -> None: def delete(self, schedule_id: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements """Delete a schedule. + Deletes the specified schedule resource. + :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str :return: None @@ -15104,7 +15109,9 @@ def delete(self, schedule_id: str, **kwargs: Any) -> None: # pylint: disable=in @distributed_trace def get(self, schedule_id: str, **kwargs: Any) -> _models.Schedule: - """Get a schedule by id. + """Get a schedule. + + Retrieves the specified schedule resource. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -15171,7 +15178,9 @@ def list( enabled: Optional[bool] = None, **kwargs: Any ) -> ItemPaged["_models.Schedule"]: - """List all schedules. + """List schedules. + + Returns schedules that match the supplied type and enabled filters. :keyword type: Filter by the type of schedule. Known values are: "Evaluation" and "Insight". Default value is None. @@ -15268,7 +15277,9 @@ def get_next(next_link=None): def create_or_update( self, schedule_id: str, schedule: _models.Schedule, *, content_type: str = "application/json", **kwargs: Any ) -> _models.Schedule: - """Create or update operation template. + """Create or update a schedule. + + Creates a new schedule or updates an existing schedule with the supplied definition. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -15286,7 +15297,9 @@ def create_or_update( def create_or_update( self, schedule_id: str, schedule: JSON, *, content_type: str = "application/json", **kwargs: Any ) -> _models.Schedule: - """Create or update operation template. + """Create or update a schedule. + + Creates a new schedule or updates an existing schedule with the supplied definition. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -15304,7 +15317,9 @@ def create_or_update( def create_or_update( self, schedule_id: str, schedule: IO[bytes], *, content_type: str = "application/json", **kwargs: Any ) -> _models.Schedule: - """Create or update operation template. + """Create or update a schedule. + + Creates a new schedule or updates an existing schedule with the supplied definition. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -15322,7 +15337,9 @@ def create_or_update( def create_or_update( self, schedule_id: str, schedule: Union[_models.Schedule, JSON, IO[bytes]], **kwargs: Any ) -> _models.Schedule: - """Create or update operation template. + """Create or update a schedule. + + Creates a new schedule or updates an existing schedule with the supplied definition. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -15396,7 +15413,9 @@ def create_or_update( @distributed_trace def get_run(self, schedule_id: str, run_id: str, **kwargs: Any) -> _models.ScheduleRun: - """Get a schedule run by id. + """Get a schedule run. + + Retrieves the specified run for a schedule. :param schedule_id: The unique identifier of the schedule. Required. :type schedule_id: str @@ -15471,7 +15490,9 @@ def list_runs( enabled: Optional[bool] = None, **kwargs: Any ) -> ItemPaged["_models.ScheduleRun"]: - """List all schedule runs. + """List schedule runs. + + Returns schedule runs that match the supplied filters. :param schedule_id: Identifier of the schedule. Required. :type schedule_id: str @@ -15538,251 +15559,63 @@ def prepare_request(next_link=None): } _request.url = self._client.format_url(_request.url, **path_format_arguments) - return _request - - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.ScheduleRun], - deserialized.get("value", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("nextLink") or None, iter(list_of_elem) - - def get_next(next_link=None): - _request = prepare_request(next_link) - - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) - - return pipeline_response - - return ItemPaged(get_next, extract_data) - - -class BetaToolboxesOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. - - Instead, you should access the following operations through - :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`toolboxes` attribute. - """ - - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") - - @overload - def create_version( - self, - name: str, - *, - tools: List[_models.Tool], - content_type: str = "application/json", - description: Optional[str] = None, - metadata: Optional[dict[str, str]] = None, - skills: Optional[List[_models.ToolboxSkill]] = None, - policies: Optional[_models.ToolboxPolicies] = None, - **kwargs: Any - ) -> _models.ToolboxVersionObject: - """Create a new version of a toolbox. If the toolbox does not exist, it will be created. - - :param name: The name of the toolbox. If the toolbox does not exist, it will be created. - Required. - :type name: str - :keyword tools: The list of tools to include in this version. Required. - :paramtype tools: list[~azure.ai.projects.models.Tool] - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :keyword description: A human-readable description of the toolbox. Default value is None. - :paramtype description: str - :keyword metadata: Arbitrary key-value metadata to associate with the toolbox. Default value is - None. - :paramtype metadata: dict[str, str] - :keyword skills: The list of skill sources to include in this version. A skill reference - specifies a skill name and optionally a version. If version is omitted, the skill's default - version is used. Default value is None. - :paramtype skills: list[~azure.ai.projects.models.ToolboxSkill] - :keyword policies: Policy configuration for this toolbox version. Default value is None. - :paramtype policies: ~azure.ai.projects.models.ToolboxPolicies - :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxVersionObject - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - def create_version( - self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.ToolboxVersionObject: - """Create a new version of a toolbox. If the toolbox does not exist, it will be created. - - :param name: The name of the toolbox. If the toolbox does not exist, it will be created. - Required. - :type name: str - :param body: Required. - :type body: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxVersionObject - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - def create_version( - self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.ToolboxVersionObject: - """Create a new version of a toolbox. If the toolbox does not exist, it will be created. - - :param name: The name of the toolbox. If the toolbox does not exist, it will be created. - Required. - :type name: str - :param body: Required. - :type body: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxVersionObject - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @distributed_trace - def create_version( - self, - name: str, - body: Union[JSON, IO[bytes]] = _Unset, - *, - tools: List[_models.Tool] = _Unset, - description: Optional[str] = None, - metadata: Optional[dict[str, str]] = None, - skills: Optional[List[_models.ToolboxSkill]] = None, - policies: Optional[_models.ToolboxPolicies] = None, - **kwargs: Any - ) -> _models.ToolboxVersionObject: - """Create a new version of a toolbox. If the toolbox does not exist, it will be created. - - :param name: The name of the toolbox. If the toolbox does not exist, it will be created. - Required. - :type name: str - :param body: Is either a JSON type or a IO[bytes] type. Required. - :type body: JSON or IO[bytes] - :keyword tools: The list of tools to include in this version. Required. - :paramtype tools: list[~azure.ai.projects.models.Tool] - :keyword description: A human-readable description of the toolbox. Default value is None. - :paramtype description: str - :keyword metadata: Arbitrary key-value metadata to associate with the toolbox. Default value is - None. - :paramtype metadata: dict[str, str] - :keyword skills: The list of skill sources to include in this version. A skill reference - specifies a skill name and optionally a version. If version is omitted, the skill's default - version is used. Default value is None. - :paramtype skills: list[~azure.ai.projects.models.ToolboxSkill] - :keyword policies: Policy configuration for this toolbox version. Default value is None. - :paramtype policies: ~azure.ai.projects.models.ToolboxPolicies - :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxVersionObject - :raises ~azure.core.exceptions.HttpResponseError: - """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = kwargs.pop("params", {}) or {} - - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.ToolboxVersionObject] = kwargs.pop("cls", None) - - if body is _Unset: - if tools is _Unset: - raise TypeError("missing required argument: tools") - body = { - "description": description, - "metadata": metadata, - "policies": policies, - "skills": skills, - "tools": tools, - } - body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/json" - _content = None - if isinstance(body, (IOBase, bytes)): - _content = body - else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - - _request = build_beta_toolboxes_create_version_request( - name=name, - content_type=content_type, - api_version=self._config.api_version, - content=_content, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + return _request - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize( + List[_models.ScheduleRun], + deserialized.get("value", []), + ) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) - response = pipeline_response.http_response + def get_next(next_link=None): + _request = prepare_request(next_link) - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs ) - raise HttpResponseError(response=response, model=error) + response = pipeline_response.http_response - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.ToolboxVersionObject, response.json()) + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return pipeline_response - return deserialized # type: ignore + return ItemPaged(get_next, extract_data) + + +class BetaSkillsOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. + + Instead, you should access the following operations through + :class:`~azure.ai.projects.AIProjectClient`'s + :attr:`skills` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") @distributed_trace - def get(self, name: str, **kwargs: Any) -> _models.ToolboxObject: - """Retrieve a toolbox. + def get(self, name: str, **kwargs: Any) -> _models.SkillDetails: + """Retrieve a skill. - :param name: The name of the toolbox to retrieve. Required. + Retrieves the specified skill and its current configuration. + + :param name: The unique name of the skill. Required. :type name: str - :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxObject + :return: SkillDetails. The SkillDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillDetails :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -15796,9 +15629,9 @@ def get(self, name: str, **kwargs: Any) -> _models.ToolboxObject: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.ToolboxObject] = kwargs.pop("cls", None) + cls: ClsType[_models.SkillDetails] = kwargs.pop("cls", None) - _request = build_beta_toolboxes_get_request( + _request = build_beta_skills_get_request( name=name, api_version=self._config.api_version, headers=_headers, @@ -15833,7 +15666,7 @@ def get(self, name: str, **kwargs: Any) -> _models.ToolboxObject: if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.ToolboxObject, response.json()) + deserialized = _deserialize(_models.SkillDetails, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -15848,102 +15681,11 @@ def list( order: Optional[Union[str, _models.PageOrder]] = None, before: Optional[str] = None, **kwargs: Any - ) -> ItemPaged["_models.ToolboxObject"]: - """List all toolboxes. - - :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and - 100, and the - default is 20. Default value is None. - :paramtype limit: int - :keyword order: Sort order by the ``created_at`` timestamp of the objects. ``asc`` for - ascending order and``desc`` - for descending order. Known values are: "asc" and "desc". Default value is None. - :paramtype order: str or ~azure.ai.projects.models.PageOrder - :keyword before: A cursor for use in pagination. ``before`` is an object ID that defines your - place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - Default value is None. - :paramtype before: str - :return: An iterator like instance of ToolboxObject - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.ToolboxObject] - :raises ~azure.core.exceptions.HttpResponseError: - """ - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[List[_models.ToolboxObject]] = kwargs.pop("cls", None) - - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - def prepare_request(_continuation_token=None): - - _request = build_beta_toolboxes_list_request( - limit=limit, - order=order, - after=_continuation_token, - before=before, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - return _request - - def extract_data(pipeline_response): - deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize( - List[_models.ToolboxObject], - deserialized.get("data", []), - ) - if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("last_id") or None, iter(list_of_elem) - - def get_next(_continuation_token=None): - _request = prepare_request(_continuation_token) - - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - return pipeline_response - - return ItemPaged(get_next, extract_data) + ) -> ItemPaged["_models.SkillDetails"]: + """List skills. - @distributed_trace - def list_versions( - self, - name: str, - *, - limit: Optional[int] = None, - order: Optional[Union[str, _models.PageOrder]] = None, - before: Optional[str] = None, - **kwargs: Any - ) -> ItemPaged["_models.ToolboxVersionObject"]: - """List all versions of a toolbox. + Returns the skills available in the current project. - :param name: The name of the toolbox to list versions for. Required. - :type name: str :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. Default value is None. @@ -15958,14 +15700,14 @@ def list_versions( subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str - :return: An iterator like instance of ToolboxVersionObject - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.ToolboxVersionObject] + :return: An iterator like instance of SkillDetails + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.SkillDetails] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.ToolboxVersionObject]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.SkillDetails]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -15977,8 +15719,7 @@ def list_versions( def prepare_request(_continuation_token=None): - _request = build_beta_toolboxes_list_versions_request( - name=name, + _request = build_beta_skills_list_request( limit=limit, order=order, after=_continuation_token, @@ -15996,172 +15737,112 @@ def prepare_request(_continuation_token=None): def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.ToolboxVersionObject], + List[_models.SkillDetails], deserialized.get("data", []), ) if cls: - list_of_elem = cls(list_of_elem) # type: ignore - return deserialized.get("last_id") or None, iter(list_of_elem) - - def get_next(_continuation_token=None): - _request = prepare_request(_continuation_token) - - _stream = False - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - return pipeline_response - - return ItemPaged(get_next, extract_data) - - @distributed_trace - def get_version(self, name: str, version: str, **kwargs: Any) -> _models.ToolboxVersionObject: - """Retrieve a specific version of a toolbox. - - :param name: The name of the toolbox. Required. - :type name: str - :param version: The version identifier to retrieve. Required. - :type version: str - :return: ToolboxVersionObject. The ToolboxVersionObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxVersionObject - :raises ~azure.core.exceptions.HttpResponseError: - """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[_models.ToolboxVersionObject] = kwargs.pop("cls", None) - - _request = build_beta_toolboxes_get_version_request( - name=name, - version=version, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("last_id") or None, iter(list_of_elem) - response = pipeline_response.http_response + def get_next(_continuation_token=None): + _request = prepare_request(_continuation_token) - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs ) - raise HttpResponseError(response=response, model=error) + response = pipeline_response.http_response - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.ToolboxVersionObject, response.json()) + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) - if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return pipeline_response - return deserialized # type: ignore + return ItemPaged(get_next, extract_data) @overload def update( self, name: str, *, default_version: str, content_type: str = "application/json", **kwargs: Any - ) -> _models.ToolboxObject: - """Update a toolbox to point to a specific version. + ) -> _models.SkillDetails: + """Update a skill. - :param name: The name of the toolbox to update. Required. + Modifies the specified skill's configuration. + + :param name: The name of the skill to update. Required. :type name: str - :keyword default_version: The version identifier that the toolbox should point to. When set, - the toolbox's default version will resolve to this version instead of the latest. Required. + :keyword default_version: The version identifier that the skill should point to. When set, the + skill's default version will resolve to this version instead of the latest. Required. :paramtype default_version: str :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str - :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxObject + :return: SkillDetails. The SkillDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillDetails :raises ~azure.core.exceptions.HttpResponseError: """ @overload def update( self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.ToolboxObject: - """Update a toolbox to point to a specific version. + ) -> _models.SkillDetails: + """Update a skill. - :param name: The name of the toolbox to update. Required. + Modifies the specified skill's configuration. + + :param name: The name of the skill to update. Required. :type name: str :param body: Required. :type body: JSON :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. Default value is "application/json". :paramtype content_type: str - :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxObject + :return: SkillDetails. The SkillDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillDetails :raises ~azure.core.exceptions.HttpResponseError: """ @overload def update( self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.ToolboxObject: - """Update a toolbox to point to a specific version. + ) -> _models.SkillDetails: + """Update a skill. - :param name: The name of the toolbox to update. Required. + Modifies the specified skill's configuration. + + :param name: The name of the skill to update. Required. :type name: str :param body: Required. :type body: IO[bytes] :keyword content_type: Body Parameter content-type. Content type parameter for binary body. Default value is "application/json". :paramtype content_type: str - :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxObject + :return: SkillDetails. The SkillDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillDetails :raises ~azure.core.exceptions.HttpResponseError: """ @distributed_trace def update( self, name: str, body: Union[JSON, IO[bytes]] = _Unset, *, default_version: str = _Unset, **kwargs: Any - ) -> _models.ToolboxObject: - """Update a toolbox to point to a specific version. + ) -> _models.SkillDetails: + """Update a skill. - :param name: The name of the toolbox to update. Required. + Modifies the specified skill's configuration. + + :param name: The name of the skill to update. Required. :type name: str :param body: Is either a JSON type or a IO[bytes] type. Required. :type body: JSON or IO[bytes] - :keyword default_version: The version identifier that the toolbox should point to. When set, - the toolbox's default version will resolve to this version instead of the latest. Required. + :keyword default_version: The version identifier that the skill should point to. When set, the + skill's default version will resolve to this version instead of the latest. Required. :paramtype default_version: str - :return: ToolboxObject. The ToolboxObject is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.ToolboxObject + :return: SkillDetails. The SkillDetails is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillDetails :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -16176,7 +15857,7 @@ def update( _params = kwargs.pop("params", {}) or {} content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.ToolboxObject] = kwargs.pop("cls", None) + cls: ClsType[_models.SkillDetails] = kwargs.pop("cls", None) if body is _Unset: if default_version is _Unset: @@ -16190,7 +15871,7 @@ def update( else: _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - _request = build_beta_toolboxes_update_request( + _request = build_beta_skills_update_request( name=name, content_type=content_type, api_version=self._config.api_version, @@ -16227,7 +15908,7 @@ def update( if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.ToolboxObject, response.json()) + deserialized = _deserialize(_models.SkillDetails, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -16235,13 +15916,15 @@ def update( return deserialized # type: ignore @distributed_trace - def delete(self, name: str, **kwargs: Any) -> None: # pylint: disable=inconsistent-return-statements - """Delete a toolbox and all its versions. + def delete(self, name: str, **kwargs: Any) -> _models.DeleteSkillResult: + """Delete a skill. - :param name: The name of the toolbox to delete. Required. + Removes the specified skill and its associated versions. + + :param name: The unique name of the skill. Required. :type name: str - :return: None - :rtype: None + :return: DeleteSkillResult. The DeleteSkillResult is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DeleteSkillResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -16255,9 +15938,9 @@ def delete(self, name: str, **kwargs: Any) -> None: # pylint: disable=inconsist _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + cls: ClsType[_models.DeleteSkillResult] = kwargs.pop("cls", None) - _request = build_beta_toolboxes_delete_request( + _request = build_beta_skills_delete_request( name=name, api_version=self._config.api_version, headers=_headers, @@ -16268,14 +15951,20 @@ def delete(self, name: str, **kwargs: Any) -> None: # pylint: disable=inconsist } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) error = _failsafe_deserialize( _models.ApiErrorResponse, @@ -16283,21 +15972,110 @@ def delete(self, name: str, **kwargs: Any) -> None: # pylint: disable=inconsist ) raise HttpResponseError(response=response, model=error) + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.DeleteSkillResult, response.json()) + if cls: - return cls(pipeline_response, None, {}) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @overload + def create( + self, + name: str, + *, + content_type: str = "application/json", + inline_content: Optional[_models.SkillInlineContent] = None, + default: Optional[bool] = None, + **kwargs: Any + ) -> _models.SkillVersion: + """Create a new version of a skill. + + Creates a new version of a skill. If the skill does not exist, it will be created. + + :param name: The name of the skill. If the skill does not exist, it will be created. Required. + :type name: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword inline_content: Inline skill content for simple skills without file uploads. + Foundry-specific extension. Default value is None. + :paramtype inline_content: ~azure.ai.projects.models.SkillInlineContent + :keyword default: Whether to set this version as the default. Default value is None. + :paramtype default: bool + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create( + self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.SkillVersion: + """Create a new version of a skill. + + Creates a new version of a skill. If the skill does not exist, it will be created. + + :param name: The name of the skill. If the skill does not exist, it will be created. Required. + :type name: str + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create( + self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.SkillVersion: + """Create a new version of a skill. + + Creates a new version of a skill. If the skill does not exist, it will be created. + + :param name: The name of the skill. If the skill does not exist, it will be created. Required. + :type name: str + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace - def delete_version( # pylint: disable=inconsistent-return-statements - self, name: str, version: str, **kwargs: Any - ) -> None: - """Delete a specific version of a toolbox. + def create( + self, + name: str, + body: Union[JSON, IO[bytes]] = _Unset, + *, + inline_content: Optional[_models.SkillInlineContent] = None, + default: Optional[bool] = None, + **kwargs: Any + ) -> _models.SkillVersion: + """Create a new version of a skill. - :param name: The name of the toolbox. Required. + Creates a new version of a skill. If the skill does not exist, it will be created. + + :param name: The name of the skill. If the skill does not exist, it will be created. Required. :type name: str - :param version: The version identifier to delete. Required. - :type version: str - :return: None - :rtype: None + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword inline_content: Inline skill content for simple skills without file uploads. + Foundry-specific extension. Default value is None. + :paramtype inline_content: ~azure.ai.projects.models.SkillInlineContent + :keyword default: Whether to set this version as the default. Default value is None. + :paramtype default: bool + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -16308,15 +16086,27 @@ def delete_version( # pylint: disable=inconsistent-return-statements } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[None] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) + + if body is _Unset: + body = {"default": default, "inline_content": inline_content} + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - _request = build_beta_toolboxes_delete_version_request( + _request = build_beta_skills_create_request( name=name, - version=version, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -16325,14 +16115,20 @@ def delete_version( # pylint: disable=inconsistent-return-statements } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _stream = False + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [204]: + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass map_error(status_code=response.status_code, response=response, error_map=error_map) error = _failsafe_deserialize( _models.ApiErrorResponse, @@ -16340,35 +16136,62 @@ def delete_version( # pylint: disable=inconsistent-return-statements ) raise HttpResponseError(response=response, model=error) - if cls: - return cls(pipeline_response, None, {}) # type: ignore + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.SkillVersion, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @overload + def create_from_files( + self, name: str, content: _models.CreateSkillVersionFromFilesBody, **kwargs: Any + ) -> _models.SkillVersion: + """Create a skill version from uploaded files. + + Creates a new version of a skill from uploaded files via multipart form data. + :param name: The name of the skill. Required. + :type name: str + :param content: Required. + :type content: ~azure.ai.projects.models.CreateSkillVersionFromFilesBody + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ -class BetaSkillsOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. + @overload + def create_from_files(self, name: str, content: JSON, **kwargs: Any) -> _models.SkillVersion: + """Create a skill version from uploaded files. - Instead, you should access the following operations through - :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`skills` attribute. - """ + Creates a new version of a skill from uploaded files via multipart form data. - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + :param name: The name of the skill. Required. + :type name: str + :param content: Required. + :type content: JSON + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace - def get(self, name: str, **kwargs: Any) -> _models.SkillDetails: - """Retrieves a skill. + def create_from_files( + self, name: str, content: Union[_models.CreateSkillVersionFromFilesBody, JSON], **kwargs: Any + ) -> _models.SkillVersion: + """Create a skill version from uploaded files. - :param name: The unique name of the skill. Required. + Creates a new version of a skill from uploaded files via multipart form data. + + :param name: The name of the skill. Required. :type name: str - :return: SkillDetails. The SkillDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillDetails + :param content: Is either a CreateSkillVersionFromFilesBody type or a JSON type. Required. + :type content: ~azure.ai.projects.models.CreateSkillVersionFromFilesBody or JSON + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -16382,11 +16205,17 @@ def get(self, name: str, **kwargs: Any) -> _models.SkillDetails: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.SkillDetails] = kwargs.pop("cls", None) + cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) - _request = build_beta_skills_get_request( + _body = content.as_dict() if isinstance(content, _Model) else content + _file_fields: list[str] = ["files"] + _data_fields: list[str] = ["default"] + _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + + _request = build_beta_skills_create_from_files_request( name=name, api_version=self._config.api_version, + files=_files, headers=_headers, params=_params, ) @@ -16419,7 +16248,7 @@ def get(self, name: str, **kwargs: Any) -> _models.SkillDetails: if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SkillDetails, response.json()) + deserialized = _deserialize(_models.SkillVersion, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -16427,16 +16256,21 @@ def get(self, name: str, **kwargs: Any) -> _models.SkillDetails: return deserialized # type: ignore @distributed_trace - def list( + def list_versions( self, + name: str, *, limit: Optional[int] = None, order: Optional[Union[str, _models.PageOrder]] = None, before: Optional[str] = None, **kwargs: Any - ) -> ItemPaged["_models.SkillDetails"]: - """Returns the list of all skills. + ) -> ItemPaged["_models.SkillVersion"]: + """List skill versions. + Returns the available versions for the specified skill. + + :param name: The name of the skill to list versions for. Required. + :type name: str :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. Default value is None. @@ -16451,14 +16285,14 @@ def list( subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str - :return: An iterator like instance of SkillDetails - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.SkillDetails] + :return: An iterator like instance of SkillVersion + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.SkillVersion] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.SkillDetails]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.SkillVersion]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -16470,7 +16304,8 @@ def list( def prepare_request(_continuation_token=None): - _request = build_beta_skills_list_request( + _request = build_beta_skills_list_versions_request( + name=name, limit=limit, order=order, after=_continuation_token, @@ -16488,7 +16323,7 @@ def prepare_request(_continuation_token=None): def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.SkillDetails], + List[_models.SkillVersion], deserialized.get("data", []), ) if cls: @@ -16516,76 +16351,18 @@ def get_next(_continuation_token=None): return ItemPaged(get_next, extract_data) - @overload - def update( - self, name: str, *, default_version: str, content_type: str = "application/json", **kwargs: Any - ) -> _models.SkillDetails: - """Update a skill. - - :param name: The name of the skill to update. Required. - :type name: str - :keyword default_version: The version identifier that the skill should point to. When set, the - skill's default version will resolve to this version instead of the latest. Required. - :paramtype default_version: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: SkillDetails. The SkillDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - def update( - self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.SkillDetails: - """Update a skill. - - :param name: The name of the skill to update. Required. - :type name: str - :param body: Required. - :type body: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: SkillDetails. The SkillDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - def update( - self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.SkillDetails: - """Update a skill. - - :param name: The name of the skill to update. Required. - :type name: str - :param body: Required. - :type body: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: SkillDetails. The SkillDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillDetails - :raises ~azure.core.exceptions.HttpResponseError: - """ - @distributed_trace - def update( - self, name: str, body: Union[JSON, IO[bytes]] = _Unset, *, default_version: str = _Unset, **kwargs: Any - ) -> _models.SkillDetails: - """Update a skill. + def get_version(self, name: str, version: str, **kwargs: Any) -> _models.SkillVersion: + """Retrieve a specific version of a skill. - :param name: The name of the skill to update. Required. + Retrieves the specified version of a skill by name and version identifier. + + :param name: The name of the skill. Required. :type name: str - :param body: Is either a JSON type or a IO[bytes] type. Required. - :type body: JSON or IO[bytes] - :keyword default_version: The version identifier that the skill should point to. When set, the - skill's default version will resolve to this version instead of the latest. Required. - :paramtype default_version: str - :return: SkillDetails. The SkillDetails is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillDetails + :param version: The version identifier to retrieve. Required. + :type version: str + :return: SkillVersion. The SkillVersion is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SkillVersion :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -16596,29 +16373,15 @@ def update( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.SkillDetails] = kwargs.pop("cls", None) - - if body is _Unset: - if default_version is _Unset: - raise TypeError("missing required argument: default_version") - body = {"default_version": default_version} - body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/json" - _content = None - if isinstance(body, (IOBase, bytes)): - _content = body - else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) - _request = build_beta_skills_update_request( + _request = build_beta_skills_get_version_request( name=name, - content_type=content_type, + version=version, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -16651,7 +16414,7 @@ def update( if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SkillDetails, response.json()) + deserialized = _deserialize(_models.SkillVersion, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -16659,13 +16422,15 @@ def update( return deserialized # type: ignore @distributed_trace - def delete(self, name: str, **kwargs: Any) -> _models.DeleteSkillResult: - """Deletes a skill. + def download(self, name: str, **kwargs: Any) -> Iterator[bytes]: + """Download the zip content for the default version of a skill. - :param name: The unique name of the skill. Required. + Downloads the zip content for the default version of a skill. + + :param name: The name of the skill. Required. :type name: str - :return: DeleteSkillResult. The DeleteSkillResult is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DeleteSkillResult + :return: Iterator[bytes] + :rtype: Iterator[bytes] :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -16679,9 +16444,9 @@ def delete(self, name: str, **kwargs: Any) -> _models.DeleteSkillResult: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DeleteSkillResult] = kwargs.pop("cls", None) + cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) - _request = build_beta_skills_delete_request( + _request = build_beta_skills_download_request( name=name, api_version=self._config.api_version, headers=_headers, @@ -16693,7 +16458,7 @@ def delete(self, name: str, **kwargs: Any) -> _models.DeleteSkillResult: _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) + _stream = kwargs.pop("stream", True) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -16713,102 +16478,99 @@ def delete(self, name: str, **kwargs: Any) -> _models.DeleteSkillResult: ) raise HttpResponseError(response=response, model=error) - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.DeleteSkillResult, response.json()) + response_headers = {} + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + + deserialized = response.iter_bytes() if _decompress else response.iter_raw() if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore - @overload - def create( - self, - name: str, - *, - content_type: str = "application/json", - inline_content: Optional[_models.SkillInlineContent] = None, - default: Optional[bool] = None, - **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill. If the skill does not exist, it will be created. + @distributed_trace + def download_version(self, name: str, version: str, **kwargs: Any) -> Iterator[bytes]: + """Download the zip content for a specific version of a skill. + + Downloads the zip content for a specific version of a skill. + + :param name: The name of the skill. Required. + :type name: str + :param version: The version to download content for. Required. + :type version: str + :return: Iterator[bytes] + :rtype: Iterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + + _request = build_beta_skills_download_version_request( + name=name, + version=version, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _decompress = kwargs.pop("decompress", True) + _stream = kwargs.pop("stream", True) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) - :param name: The name of the skill. If the skill does not exist, it will be created. Required. - :type name: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :keyword inline_content: Inline skill content for simple skills without file uploads. - Foundry-specific extension. Default value is None. - :paramtype inline_content: ~azure.ai.projects.models.SkillInlineContent - :keyword default: Whether to set this version as the default. Default value is None. - :paramtype default: bool - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ + response = pipeline_response.http_response - @overload - def create( - self, name: str, body: JSON, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill. If the skill does not exist, it will be created. + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = _failsafe_deserialize( + _models.ApiErrorResponse, + response, + ) + raise HttpResponseError(response=response, model=error) - :param name: The name of the skill. If the skill does not exist, it will be created. Required. - :type name: str - :param body: Required. - :type body: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ + response_headers = {} + response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) - @overload - def create( - self, name: str, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill. If the skill does not exist, it will be created. + deserialized = response.iter_bytes() if _decompress else response.iter_raw() - :param name: The name of the skill. If the skill does not exist, it will be created. Required. - :type name: str - :param body: Required. - :type body: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore @distributed_trace - def create( - self, - name: str, - body: Union[JSON, IO[bytes]] = _Unset, - *, - inline_content: Optional[_models.SkillInlineContent] = None, - default: Optional[bool] = None, - **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill. If the skill does not exist, it will be created. + def delete_version(self, name: str, version: str, **kwargs: Any) -> _models.DeleteSkillVersionResult: + """Delete a specific version of a skill. - :param name: The name of the skill. If the skill does not exist, it will be created. Required. + Removes the specified version of a skill. + + :param name: The name of the skill. Required. :type name: str - :param body: Is either a JSON type or a IO[bytes] type. Required. - :type body: JSON or IO[bytes] - :keyword inline_content: Inline skill content for simple skills without file uploads. - Foundry-specific extension. Default value is None. - :paramtype inline_content: ~azure.ai.projects.models.SkillInlineContent - :keyword default: Whether to set this version as the default. Default value is None. - :paramtype default: bool - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion + :param version: The version identifier to delete. Required. + :type version: str + :return: DeleteSkillVersionResult. The DeleteSkillVersionResult is compatible with + MutableMapping + :rtype: ~azure.ai.projects.models.DeleteSkillVersionResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -16819,27 +16581,15 @@ def create( } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) - - if body is _Unset: - body = {"default": default, "inline_content": inline_content} - body = {k: v for k, v in body.items() if v is not None} - content_type = content_type or "application/json" - _content = None - if isinstance(body, (IOBase, bytes)): - _content = body - else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + cls: ClsType[_models.DeleteSkillVersionResult] = kwargs.pop("cls", None) - _request = build_beta_skills_create_request( + _request = build_beta_skills_delete_version_request( name=name, - content_type=content_type, + version=version, api_version=self._config.api_version, - content=_content, headers=_headers, params=_params, ) @@ -16872,53 +16622,41 @@ def create( if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SkillVersion, response.json()) + deserialized = _deserialize(_models.DeleteSkillVersionResult, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore - @overload - def create_from_files( - self, name: str, content: _models.CreateSkillVersionFromFilesBody, **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill from uploaded files via multipart form data. - :param name: The name of the skill. Required. - :type name: str - :param content: Required. - :type content: ~azure.ai.projects.models.CreateSkillVersionFromFilesBody - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ +class BetaDatasetsOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. - @overload - def create_from_files(self, name: str, content: JSON, **kwargs: Any) -> _models.SkillVersion: - """Creates a new version of a skill from uploaded files via multipart form data. + Instead, you should access the following operations through + :class:`~azure.ai.projects.AIProjectClient`'s + :attr:`datasets` attribute. + """ - :param name: The name of the skill. Required. - :type name: str - :param content: Required. - :type content: JSON - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion - :raises ~azure.core.exceptions.HttpResponseError: - """ + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") @distributed_trace - def create_from_files( - self, name: str, content: Union[_models.CreateSkillVersionFromFilesBody, JSON], **kwargs: Any - ) -> _models.SkillVersion: - """Creates a new version of a skill from uploaded files via multipart form data. + def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerationJob: + """Get a data generation job. - :param name: The name of the skill. Required. - :type name: str - :param content: Is either a CreateSkillVersionFromFilesBody type or a JSON type. Required. - :type content: ~azure.ai.projects.models.CreateSkillVersionFromFilesBody or JSON - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion + Retrieves the specified data generation job and its current status. + + :param job_id: The ID of the job. Required. + :type job_id: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -16932,17 +16670,11 @@ def create_from_files( _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) - - _body = content.as_dict() if isinstance(content, _Model) else content - _file_fields: list[str] = ["files"] - _data_fields: list[str] = ["default"] - _files = prepare_multipart_form_data(_body, _file_fields, _data_fields) + cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) - _request = build_beta_skills_create_from_files_request( - name=name, + _request = build_beta_datasets_get_generation_job_request( + job_id=job_id, api_version=self._config.api_version, - files=_files, headers=_headers, params=_params, ) @@ -16972,30 +16704,32 @@ def create_from_files( ) raise HttpResponseError(response=response, model=error) + response_headers = {} + response_headers["Retry-After"] = self._deserialize("int", response.headers.get("Retry-After")) + if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SkillVersion, response.json()) + deserialized = _deserialize(_models.DataGenerationJob, response.json()) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore @distributed_trace - def list_versions( + def list_generation_jobs( self, - name: str, *, limit: Optional[int] = None, order: Optional[Union[str, _models.PageOrder]] = None, before: Optional[str] = None, **kwargs: Any - ) -> ItemPaged["_models.SkillVersion"]: - """List all versions of a skill. + ) -> ItemPaged["_models.DataGenerationJob"]: + """List data generation jobs. + + Returns a list of data generation jobs. - :param name: The name of the skill to list versions for. Required. - :type name: str :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. Default value is None. @@ -17010,14 +16744,14 @@ def list_versions( subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str - :return: An iterator like instance of SkillVersion - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.SkillVersion] + :return: An iterator like instance of DataGenerationJob + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.DataGenerationJob] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.SkillVersion]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.DataGenerationJob]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -17029,8 +16763,7 @@ def list_versions( def prepare_request(_continuation_token=None): - _request = build_beta_skills_list_versions_request( - name=name, + _request = build_beta_datasets_list_generation_jobs_request( limit=limit, order=order, after=_continuation_token, @@ -17048,7 +16781,7 @@ def prepare_request(_continuation_token=None): def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.SkillVersion], + List[_models.DataGenerationJob], deserialized.get("data", []), ) if cls: @@ -17072,20 +16805,103 @@ def get_next(_continuation_token=None): ) raise HttpResponseError(response=response, model=error) - return pipeline_response + return pipeline_response + + return ItemPaged(get_next, extract_data) + + @overload + def create_generation_job( + self, + job: _models.DataGenerationJob, + *, + operation_id: Optional[str] = None, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.DataGenerationJob: + """Create a data generation job. + + Submits a new data generation job for asynchronous execution. + + :param job: The job to create. Required. + :type job: ~azure.ai.projects.models.DataGenerationJob + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create_generation_job( + self, job: JSON, *, operation_id: Optional[str] = None, content_type: str = "application/json", **kwargs: Any + ) -> _models.DataGenerationJob: + """Create a data generation job. + + Submits a new data generation job for asynchronous execution. + + :param job: The job to create. Required. + :type job: JSON + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create_generation_job( + self, + job: IO[bytes], + *, + operation_id: Optional[str] = None, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.DataGenerationJob: + """Create a data generation job. + + Submits a new data generation job for asynchronous execution. - return ItemPaged(get_next, extract_data) + :param job: The job to create. Required. + :type job: IO[bytes] + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace - def get_version(self, name: str, version: str, **kwargs: Any) -> _models.SkillVersion: - """Retrieve a specific version of a skill. + def create_generation_job( + self, + job: Union[_models.DataGenerationJob, JSON, IO[bytes]], + *, + operation_id: Optional[str] = None, + **kwargs: Any + ) -> _models.DataGenerationJob: + """Create a data generation job. - :param name: The name of the skill. Required. - :type name: str - :param version: The version identifier to retrieve. Required. - :type version: str - :return: SkillVersion. The SkillVersion is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.SkillVersion + Submits a new data generation job for asynchronous execution. + + :param job: The job to create. Is one of the following types: DataGenerationJob, JSON, + IO[bytes] Required. + :type job: ~azure.ai.projects.models.DataGenerationJob or JSON or IO[bytes] + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -17096,15 +16912,24 @@ def get_version(self, name: str, version: str, **kwargs: Any) -> _models.SkillVe } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.SkillVersion] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) - _request = build_beta_skills_get_version_request( - name=name, - version=version, + content_type = content_type or "application/json" + _content = None + if isinstance(job, (IOBase, bytes)): + _content = job + else: + _content = json.dumps(job, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_beta_datasets_create_generation_job_request( + operation_id=operation_id, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -17121,7 +16946,7 @@ def get_version(self, name: str, version: str, **kwargs: Any) -> _models.SkillVe response = pipeline_response.http_response - if response.status_code not in [200]: + if response.status_code not in [201]: if _stream: try: response.read() # Load the body in memory and close the socket @@ -17134,24 +16959,30 @@ def get_version(self, name: str, version: str, **kwargs: Any) -> _models.SkillVe ) raise HttpResponseError(response=response, model=error) + response_headers = {} + response_headers["Operation-Location"] = self._deserialize("str", response.headers.get("Operation-Location")) + response_headers["Location"] = self._deserialize("str", response.headers.get("Location")) + if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.SkillVersion, response.json()) + deserialized = _deserialize(_models.DataGenerationJob, response.json()) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore @distributed_trace - def download(self, name: str, **kwargs: Any) -> Iterator[bytes]: - """Download the zip content for the default version of a skill. + def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerationJob: + """Cancel a data generation job. - :param name: The name of the skill. Required. - :type name: str - :return: Iterator[bytes] - :rtype: Iterator[bytes] + Cancels the specified data generation job if it is still in progress. + + :param job_id: The ID of the job to cancel. Required. + :type job_id: str + :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.DataGenerationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -17165,10 +16996,10 @@ def download(self, name: str, **kwargs: Any) -> Iterator[bytes]: _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) - _request = build_beta_skills_download_request( - name=name, + _request = build_beta_datasets_cancel_generation_job_request( + job_id=job_id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -17179,7 +17010,7 @@ def download(self, name: str, **kwargs: Any) -> Iterator[bytes]: _request.url = self._client.format_url(_request.url, **path_format_arguments) _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", True) + _stream = kwargs.pop("stream", False) pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) @@ -17199,26 +17030,28 @@ def download(self, name: str, **kwargs: Any) -> Iterator[bytes]: ) raise HttpResponseError(response=response, model=error) - response_headers = {} - response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) - - deserialized = response.iter_bytes() if _decompress else response.iter_raw() + if _stream: + deserialized = response.iter_bytes() if _decompress else response.iter_raw() + else: + deserialized = _deserialize(_models.DataGenerationJob, response.json()) if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + return cls(pipeline_response, deserialized, {}) # type: ignore return deserialized # type: ignore @distributed_trace - def download_version(self, name: str, version: str, **kwargs: Any) -> Iterator[bytes]: - """Download the zip content for a specific version of a skill. + def delete_generation_job( # pylint: disable=inconsistent-return-statements + self, job_id: str, **kwargs: Any + ) -> None: + """Delete a data generation job. - :param name: The name of the skill. Required. - :type name: str - :param version: The version to download content for. Required. - :type version: str - :return: Iterator[bytes] - :rtype: Iterator[bytes] + Removes the specified data generation job and its associated output. + + :param job_id: The ID of the job to delete. Required. + :type job_id: str + :return: None + :rtype: None :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -17232,11 +17065,10 @@ def download_version(self, name: str, version: str, **kwargs: Any) -> Iterator[b _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_beta_skills_download_version_request( - name=name, - version=version, + _request = build_beta_datasets_delete_generation_job_request( + job_id=job_id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -17246,20 +17078,14 @@ def download_version(self, name: str, version: str, **kwargs: Any) -> Iterator[b } _request.url = self._client.format_url(_request.url, **path_format_arguments) - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", True) + _stream = False pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access _request, stream=_stream, **kwargs ) response = pipeline_response.http_response - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass + if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) error = _failsafe_deserialize( _models.ApiErrorResponse, @@ -17267,27 +17093,120 @@ def download_version(self, name: str, version: str, **kwargs: Any) -> Iterator[b ) raise HttpResponseError(response=response, model=error) - response_headers = {} - response_headers["Content-Type"] = self._deserialize("str", response.headers.get("Content-Type")) + if cls: + return cls(pipeline_response, None, {}) # type: ignore - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore +class BetaAgentsOperations: + """ + .. warning:: + **DO NOT** instantiate this class directly. - return deserialized # type: ignore + Instead, you should access the following operations through + :class:`~azure.ai.projects.AIProjectClient`'s + :attr:`agents` attribute. + """ + + def __init__(self, *args, **kwargs) -> None: + input_args = list(args) + self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") + self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") + self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") + self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") + + @overload + def create_optimization_job( + self, + job: _models.OptimizationJob, + *, + operation_id: Optional[str] = None, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.OptimizationJob: + """Creates an agent optimization job. + + Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for + idempotent retry. + + :param job: The job to create. Required. + :type job: ~azure.ai.projects.models.OptimizationJob + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create_optimization_job( + self, job: JSON, *, operation_id: Optional[str] = None, content_type: str = "application/json", **kwargs: Any + ) -> _models.OptimizationJob: + """Creates an agent optimization job. + + Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for + idempotent retry. + + :param job: The job to create. Required. + :type job: JSON + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create_optimization_job( + self, + job: IO[bytes], + *, + operation_id: Optional[str] = None, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.OptimizationJob: + """Creates an agent optimization job. + + Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for + idempotent retry. + + :param job: The job to create. Required. + :type job: IO[bytes] + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob + :raises ~azure.core.exceptions.HttpResponseError: + """ @distributed_trace - def delete_version(self, name: str, version: str, **kwargs: Any) -> _models.DeleteSkillVersionResult: - """Delete a specific version of a skill. + def create_optimization_job( + self, job: Union[_models.OptimizationJob, JSON, IO[bytes]], *, operation_id: Optional[str] = None, **kwargs: Any + ) -> _models.OptimizationJob: + """Creates an agent optimization job. - :param name: The name of the skill. Required. - :type name: str - :param version: The version identifier to delete. Required. - :type version: str - :return: DeleteSkillVersionResult. The DeleteSkillVersionResult is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.DeleteSkillVersionResult + Create an optimization job. Returns 201 with the queued job. Honours ``Operation-Id`` for + idempotent retry. + + :param job: The job to create. Is one of the following types: OptimizationJob, JSON, IO[bytes] + Required. + :type job: ~azure.ai.projects.models.OptimizationJob or JSON or IO[bytes] + :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the + server creates the job unconditionally. Default value is None. + :paramtype operation_id: str + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -17298,15 +17217,24 @@ def delete_version(self, name: str, version: str, **kwargs: Any) -> _models.Dele } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DeleteSkillVersionResult] = kwargs.pop("cls", None) + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) - _request = build_beta_skills_delete_version_request( - name=name, - version=version, + content_type = content_type or "application/json" + _content = None + if isinstance(job, (IOBase, bytes)): + _content = job + else: + _content = json.dumps(job, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_beta_agents_create_optimization_job_request( + operation_id=operation_id, + content_type=content_type, api_version=self._config.api_version, + content=_content, headers=_headers, params=_params, ) @@ -17323,7 +17251,7 @@ def delete_version(self, name: str, version: str, **kwargs: Any) -> _models.Dele response = pipeline_response.http_response - if response.status_code not in [200]: + if response.status_code not in [201]: if _stream: try: response.read() # Load the body in memory and close the socket @@ -17336,44 +17264,30 @@ def delete_version(self, name: str, version: str, **kwargs: Any) -> _models.Dele ) raise HttpResponseError(response=response, model=error) + response_headers = {} + response_headers["Operation-Location"] = self._deserialize("str", response.headers.get("Operation-Location")) + response_headers["Location"] = self._deserialize("str", response.headers.get("Location")) + if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.DeleteSkillVersionResult, response.json()) + deserialized = _deserialize(_models.OptimizationJob, response.json()) if cls: - return cls(pipeline_response, deserialized, {}) # type: ignore + return cls(pipeline_response, deserialized, response_headers) # type: ignore return deserialized # type: ignore - -class BetaDatasetsOperations: - """ - .. warning:: - **DO NOT** instantiate this class directly. - - Instead, you should access the following operations through - :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`datasets` attribute. - """ - - def __init__(self, *args, **kwargs) -> None: - input_args = list(args) - self._client: PipelineClient = input_args.pop(0) if input_args else kwargs.pop("client") - self._config: AIProjectClientConfiguration = input_args.pop(0) if input_args else kwargs.pop("config") - self._serialize: Serializer = input_args.pop(0) if input_args else kwargs.pop("serializer") - self._deserialize: Deserializer = input_args.pop(0) if input_args else kwargs.pop("deserializer") - @distributed_trace - def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerationJob: - """Get info about a data generation job. + def get_optimization_job(self, job_id: str, **kwargs: Any) -> _models.OptimizationJob: + """Get info about an agent optimization job. - Gets the details of a data generation job by its ID. + Get an optimization job by id. :param job_id: The ID of the job. Required. :type job_id: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -17387,9 +17301,9 @@ def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerati _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) + cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) - _request = build_beta_datasets_get_generation_job_request( + _request = build_beta_agents_get_optimization_job_request( job_id=job_id, api_version=self._config.api_version, headers=_headers, @@ -17427,7 +17341,7 @@ def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerati if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.DataGenerationJob, response.json()) + deserialized = _deserialize(_models.OptimizationJob, response.json()) if cls: return cls(pipeline_response, deserialized, response_headers) # type: ignore @@ -17435,17 +17349,19 @@ def get_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerati return deserialized # type: ignore @distributed_trace - def list_generation_jobs( + def list_optimization_jobs( self, *, limit: Optional[int] = None, order: Optional[Union[str, _models.PageOrder]] = None, before: Optional[str] = None, + status: Optional[Union[str, _models.JobStatus]] = None, + agent_name: Optional[str] = None, **kwargs: Any - ) -> ItemPaged["_models.DataGenerationJob"]: - """Returns a list of data generation jobs. + ) -> ItemPaged["_models.OptimizationJobListItem"]: + """Returns a list of agent optimization jobs. - Returns a list of data generation jobs. + List optimization jobs. Supports cursor pagination and optional status / agent_name filters. :keyword limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the @@ -17461,14 +17377,19 @@ def list_generation_jobs( subsequent call can include before=obj_foo in order to fetch the previous page of the list. Default value is None. :paramtype before: str - :return: An iterator like instance of DataGenerationJob - :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.DataGenerationJob] + :keyword status: Filter to jobs in this lifecycle state. Known values are: "queued", + "in_progress", "succeeded", "failed", and "cancelled". Default value is None. + :paramtype status: str or ~azure.ai.projects.models.JobStatus + :keyword agent_name: Filter to jobs targeting this agent name. Default value is None. + :paramtype agent_name: str + :return: An iterator like instance of OptimizationJobListItem + :rtype: ~azure.core.paging.ItemPaged[~azure.ai.projects.models.OptimizationJobListItem] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[List[_models.DataGenerationJob]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.OptimizationJobListItem]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -17480,11 +17401,13 @@ def list_generation_jobs( def prepare_request(_continuation_token=None): - _request = build_beta_datasets_list_generation_jobs_request( + _request = build_beta_agents_list_optimization_jobs_request( limit=limit, order=order, after=_continuation_token, before=before, + status=status, + agent_name=agent_name, api_version=self._config.api_version, headers=_headers, params=_params, @@ -17498,7 +17421,7 @@ def prepare_request(_continuation_token=None): def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() list_of_elem = _deserialize( - List[_models.DataGenerationJob], + List[_models.OptimizationJobListItem], deserialized.get("data", []), ) if cls: @@ -17526,180 +17449,17 @@ def get_next(_continuation_token=None): return ItemPaged(get_next, extract_data) - @overload - def create_generation_job( - self, - job: _models.DataGenerationJob, - *, - operation_id: Optional[str] = None, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.DataGenerationJob: - """Creates a data generation job. - - Creates a data generation job. - - :param job: The job to create. Required. - :type job: ~azure.ai.projects.models.DataGenerationJob - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - def create_generation_job( - self, job: JSON, *, operation_id: Optional[str] = None, content_type: str = "application/json", **kwargs: Any - ) -> _models.DataGenerationJob: - """Creates a data generation job. - - Creates a data generation job. - - :param job: The job to create. Required. - :type job: JSON - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @overload - def create_generation_job( - self, - job: IO[bytes], - *, - operation_id: Optional[str] = None, - content_type: str = "application/json", - **kwargs: Any - ) -> _models.DataGenerationJob: - """Creates a data generation job. - - Creates a data generation job. - - :param job: The job to create. Required. - :type job: IO[bytes] - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ - - @distributed_trace - def create_generation_job( - self, - job: Union[_models.DataGenerationJob, JSON, IO[bytes]], - *, - operation_id: Optional[str] = None, - **kwargs: Any - ) -> _models.DataGenerationJob: - """Creates a data generation job. - - Creates a data generation job. - - :param job: The job to create. Is one of the following types: DataGenerationJob, JSON, - IO[bytes] Required. - :type job: ~azure.ai.projects.models.DataGenerationJob or JSON or IO[bytes] - :keyword operation_id: Client-generated unique ID for idempotent retries. When absent, the - server creates the job unconditionally. Default value is None. - :paramtype operation_id: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob - :raises ~azure.core.exceptions.HttpResponseError: - """ - error_map: MutableMapping = { - 401: ClientAuthenticationError, - 404: ResourceNotFoundError, - 409: ResourceExistsError, - 304: ResourceNotModifiedError, - } - error_map.update(kwargs.pop("error_map", {}) or {}) - - _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) - _params = kwargs.pop("params", {}) or {} - - content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) - - content_type = content_type or "application/json" - _content = None - if isinstance(job, (IOBase, bytes)): - _content = job - else: - _content = json.dumps(job, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - - _request = build_beta_datasets_create_generation_job_request( - operation_id=operation_id, - content_type=content_type, - api_version=self._config.api_version, - content=_content, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) - - _decompress = kwargs.pop("decompress", True) - _stream = kwargs.pop("stream", False) - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) - - response = pipeline_response.http_response - - if response.status_code not in [201]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = _failsafe_deserialize( - _models.ApiErrorResponse, - response, - ) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers["Operation-Location"] = self._deserialize("str", response.headers.get("Operation-Location")) - response_headers["Location"] = self._deserialize("str", response.headers.get("Location")) - - if _stream: - deserialized = response.iter_bytes() if _decompress else response.iter_raw() - else: - deserialized = _deserialize(_models.DataGenerationJob, response.json()) - - if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore - - return deserialized # type: ignore - @distributed_trace - def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGenerationJob: - """Cancels a data generation job. + def cancel_optimization_job(self, job_id: str, **kwargs: Any) -> _models.OptimizationJob: + """Cancels an agent optimization job. - Cancels a data generation job by its ID. + Request cancellation of a running or queued job. Returns an error if the job is already in a + terminal state. :param job_id: The ID of the job to cancel. Required. :type job_id: str - :return: DataGenerationJob. The DataGenerationJob is compatible with MutableMapping - :rtype: ~azure.ai.projects.models.DataGenerationJob + :return: OptimizationJob. The OptimizationJob is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.OptimizationJob :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -17713,9 +17473,9 @@ def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGener _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - cls: ClsType[_models.DataGenerationJob] = kwargs.pop("cls", None) + cls: ClsType[_models.OptimizationJob] = kwargs.pop("cls", None) - _request = build_beta_datasets_cancel_generation_job_request( + _request = build_beta_agents_cancel_optimization_job_request( job_id=job_id, api_version=self._config.api_version, headers=_headers, @@ -17750,7 +17510,7 @@ def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGener if _stream: deserialized = response.iter_bytes() if _decompress else response.iter_raw() else: - deserialized = _deserialize(_models.DataGenerationJob, response.json()) + deserialized = _deserialize(_models.OptimizationJob, response.json()) if cls: return cls(pipeline_response, deserialized, {}) # type: ignore @@ -17758,12 +17518,12 @@ def cancel_generation_job(self, job_id: str, **kwargs: Any) -> _models.DataGener return deserialized # type: ignore @distributed_trace - def delete_generation_job( # pylint: disable=inconsistent-return-statements + def delete_optimization_job( # pylint: disable=inconsistent-return-statements self, job_id: str, **kwargs: Any ) -> None: - """Deletes a data generation job. + """Deletes an agent optimization job. - Deletes a data generation job by its ID. + Delete the job and its candidate artifacts. Cancels first if non-terminal. :param job_id: The ID of the job to delete. Required. :type job_id: str @@ -17784,7 +17544,7 @@ def delete_generation_job( # pylint: disable=inconsistent-return-statements cls: ClsType[None] = kwargs.pop("cls", None) - _request = build_beta_datasets_delete_generation_job_request( + _request = build_beta_agents_delete_optimization_job_request( job_id=job_id, api_version=self._config.api_version, headers=_headers, diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch.py b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch.py index 29adf947b535..283443056bf4 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch.py @@ -19,8 +19,8 @@ from ._patch_connections import ConnectionsOperations from ._patch_memories import BetaMemoryStoresOperations from ._patch_models import BetaModelsOperations -from ._patch_sessions import BetaAgentsOperations from ._operations import ( + BetaAgentsOperations, BetaDatasetsOperations, BetaEvaluationTaxonomiesOperations, BetaEvaluatorsOperations, @@ -30,7 +30,6 @@ BetaRoutinesOperations, BetaSchedulesOperations, BetaSkillsOperations, - BetaToolboxesOperations, ) @@ -115,8 +114,6 @@ class BetaOperations(GeneratedBetaOperations): """:class:`~azure.ai.projects.operations.BetaRoutinesOperations` operations""" schedules: BetaSchedulesOperations """:class:`~azure.ai.projects.operations.BetaSchedulesOperations` operations""" - toolboxes: BetaToolboxesOperations - """:class:`~azure.ai.projects.operations.BetaToolboxesOperations` operations""" skills: BetaSkillsOperations """:class:`~azure.ai.projects.operations.BetaSkillsOperations` operations""" datasets: BetaDatasetsOperations @@ -155,7 +152,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: "BetaRoutinesOperations", "BetaSchedulesOperations", "BetaSkillsOperations", - "BetaToolboxesOperations", "ConnectionsOperations", "DatasetsOperations", "EvaluationRulesOperations", diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch_agents.py b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch_agents.py index a2f129f1dae1..ac1c9f658c28 100644 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch_agents.py +++ b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch_agents.py @@ -8,6 +8,9 @@ Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ +import hashlib +import os +from pathlib import Path from typing import Union, Optional, Any, IO, overload from azure.core.exceptions import HttpResponseError from azure.core.tracing.decorator import distributed_trace @@ -214,3 +217,224 @@ def create_version( new_exc.model = exc.model raise new_exc from exc raise + + @overload + def upload_session_file( + self, + agent_name: str, + session_id: str, + *, + content: bytes, + remote_path: str, + **kwargs: Any, + ) -> _models.SessionFileWriteResult: + """Upload binary content to the session sandbox. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session ID. Required. + :type session_id: str + :keyword content: The binary content to upload. Required. + :paramtype content: bytes + :keyword remote_path: The destination file path within the sandbox, relative to the session home + directory. Required. + :paramtype remote_path: str + :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SessionFileWriteResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + ... + + @overload + def upload_session_file( + self, + agent_name: str, + session_id: str, + *, + file_path: Union[str, "os.PathLike[str]"], + remote_path: str, + **kwargs: Any, + ) -> _models.SessionFileWriteResult: + """Upload a file from disk to the session sandbox. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session ID. Required. + :type session_id: str + :keyword file_path: The full path to a local file whose contents should be uploaded. Required. + :paramtype file_path: str or os.PathLike[str] + :keyword remote_path: The destination file path within the sandbox, relative to the session home + directory. Required. + :paramtype remote_path: str + :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SessionFileWriteResult + :raises ~azure.core.exceptions.HttpResponseError: + :raises FileNotFoundError: If *file_path* does not exist. + """ + ... + + @distributed_trace + def upload_session_file( # type: ignore[override] + self, + agent_name: str, + session_id: str, + *, + content: Optional[bytes] = None, + file_path: Optional[Union[str, "os.PathLike[str]"]] = None, + remote_path: str, + **kwargs: Any, + ) -> _models.SessionFileWriteResult: + """Upload a file to the session sandbox. + + Accepts either binary content directly or a local file path. + When a file path is provided the file is read from disk and its contents + are forwarded to the service. Maximum file size is 50 MB. Uploads + exceeding this limit return 413 Payload Too Large. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session ID. Required. + :type session_id: str + :keyword content: The binary content to upload. Mutually exclusive with *file_path*. + :paramtype content: bytes + :keyword file_path: The full path to a local file whose contents should be uploaded. + Mutually exclusive with *content*. + :paramtype file_path: str or os.PathLike[str] + :keyword remote_path: The destination file path within the sandbox, relative to the session home + directory. Required. + :paramtype remote_path: str + :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with MutableMapping + :rtype: ~azure.ai.projects.models.SessionFileWriteResult + :raises ~azure.core.exceptions.HttpResponseError: + :raises ValueError: If both *content* and *file_path* are provided, or neither is provided. + :raises FileNotFoundError: If *file_path* is provided and does not exist. + """ + if content is not None and file_path is not None: + raise ValueError("Specify either 'content' or 'file_path', not both.") + if content is None and file_path is None: + raise ValueError("Specify either 'content' or 'file_path'.") + + if file_path is not None: + p = Path(file_path) + if not p.exists(): + raise FileNotFoundError(f"The provided file `{file_path}` does not exist.") + if p.is_dir(): + raise ValueError(f"Provide a valid file path, not a folder path `{file_path}`.") + with open(file_path, "rb") as f: + content = f.read() + + assert content is not None # Guaranteed by validation above + + return super()._upload_session_file(agent_name, session_id, content, remote_path=remote_path, **kwargs) + + @distributed_trace + def download_session_file_to_path( + self, + agent_name: str, + session_id: str, + *, + file_path: Union[str, "os.PathLike[str]"], + overwrite: bool = False, + remote_path: str, + **kwargs: Any, + ) -> None: + """Download a session file directly to disk. + + Downloads the file at the specified sandbox path and writes it to a local file. + The remote path is resolved relative to the session home directory. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :param session_id: The session ID. Required. + :type session_id: str + :keyword file_path: The full path to the local file where the content should be written. Required. + :paramtype file_path: str or os.PathLike[str] + :keyword overwrite: If True, overwrite the local file if it already exists. If False (default), + raise FileExistsError when the file already exists. + :paramtype overwrite: bool + :keyword remote_path: The file path to download from the sandbox, relative to the session home + directory. Required. + :paramtype remote_path: str + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + :raises FileExistsError: If *file_path* already exists and *overwrite* is False. + :raises ValueError: If *file_path* points to a directory. + :raises OSError: If the file cannot be written. + """ + p = Path(file_path) + if p.exists(): + if p.is_dir(): + raise ValueError(f"Provide a valid file path, not a folder path `{file_path}`.") + if not overwrite: + raise FileExistsError(f"The file `{file_path}` already exists. Set overwrite=True to replace it.") + + # Download the file content using the existing method + content_iterator = self.download_session_file_as_bytes( + agent_name=agent_name, + agent_session_id=session_id, + remote_path=remote_path, + **kwargs, + ) + + # Write the content to disk + with open(file_path, "wb") as f: + for chunk in content_iterator: + f.write(chunk) + + @distributed_trace + def download_code_to_path( + self, + agent_name: str, + *, + file_path: Union[str, "os.PathLike[str]"], + overwrite: bool = False, + agent_version: Optional[str] = None, + **kwargs: Any, + ) -> str: + """Download agent code directly to disk. + + Downloads the code zip for a code-based hosted agent and writes it to a local file. + + If ``agent_version`` is supplied, downloads that version's code zip; otherwise + downloads the latest version's code zip. + + :param agent_name: The name of the agent. Required. + :type agent_name: str + :keyword file_path: The full path to the local file where the code zip should be written. Required. + :paramtype file_path: str or os.PathLike[str] + :keyword overwrite: If True, overwrite the local file if it already exists. If False (default), + raise FileExistsError when the file already exists. + :paramtype overwrite: bool + :keyword agent_version: The version of the agent whose code zip should be downloaded. + If omitted, the latest version's code zip is downloaded. Default value is None. + :paramtype agent_version: str + :return: The SHA-256 hex digest of the downloaded file. + :rtype: str + :raises ~azure.core.exceptions.HttpResponseError: + :raises FileExistsError: If *file_path* already exists and *overwrite* is False. + :raises ValueError: If *file_path* points to a directory. + :raises OSError: If the file cannot be written. + """ + p = Path(file_path) + if p.exists(): + if p.is_dir(): + raise ValueError(f"Provide a valid file path, not a folder path `{file_path}`.") + if not overwrite: + raise FileExistsError(f"The file `{file_path}` already exists. Set overwrite=True to replace it.") + + # Download the code content using the existing method + content_iterator = self.download_code_as_bytes( + agent_name=agent_name, + agent_version=agent_version, + **kwargs, + ) + + # Write the content to disk and calculate SHA-256 + sha = hashlib.sha256() + with open(file_path, "wb") as f: + for chunk in content_iterator: + f.write(chunk) + sha.update(chunk) + + return sha.hexdigest() diff --git a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch_sessions.py b/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch_sessions.py deleted file mode 100644 index 8d417620e725..000000000000 --- a/sdk/ai/azure-ai-projects/azure/ai/projects/operations/_patch_sessions.py +++ /dev/null @@ -1,74 +0,0 @@ -# pylint: disable=line-too-long,useless-suppression -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -"""Customize generated code here. - -Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize -""" - -from pathlib import Path -from typing import Any -from azure.core.tracing.decorator import distributed_trace -from ._operations import BetaAgentsOperations as GeneratedBetaAgentsOperations -from .. import models as _models - - -class BetaAgentsOperations(GeneratedBetaAgentsOperations): - """ - .. warning:: - **DO NOT** instantiate this class directly. - - Instead, you should access the following operations through - :class:`~azure.ai.projects.AIProjectClient`'s - :attr:`beta.agents` attribute. - """ - - @distributed_trace - def upload_session_file( # type: ignore[override] - self, - agent_name: str, - session_id: str, - content_or_file_path: "bytes | str", - *, - path: str, - **kwargs: Any, - ) -> _models.SessionFileWriteResult: - """Upload a file to the session sandbox. - - Accepts either a ``bytes`` buffer or a local file path (``str``). - When a file path is provided the file is read from disk and its contents - are forwarded to the service. Maximum file size is 50 MB. Uploads - exceeding this limit return 413 Payload Too Large. - - :param agent_name: The name of the agent. Required. - :type agent_name: str - :param session_id: The session ID. Required. - :type session_id: str - :param content_or_file_path: The binary content to upload, **or** the full path to a local - file whose contents should be uploaded. Required. - :type content_or_file_path: bytes or str - :keyword path: The destination file path within the sandbox, relative to the session home - directory. Required. - :paramtype path: str - :return: SessionFileWriteResult. The SessionFileWriteResult is compatible with - MutableMapping - :rtype: ~azure.ai.projects.models.SessionFileWriteResult - :raises ~azure.core.exceptions.HttpResponseError: - :raises FileNotFoundError: If *content_or_file_path* is a ``str`` and the file does not exist. - """ - if isinstance(content_or_file_path, str): - - file_path = Path(content_or_file_path) - if not file_path.exists(): - raise ValueError(f"The provided file `{content_or_file_path}` does not exist.") - if file_path.is_dir(): - raise ValueError(f"Provide a valid file path, not a folder path `{content_or_file_path}`.") - - with open(content_or_file_path, "rb") as f: - content: bytes = f.read() - else: - content = content_or_file_path - - return super()._upload_session_file(agent_name, session_id, content, path=path, **kwargs) diff --git a/sdk/ai/azure-ai-projects/evaluation-typespec-issues.md b/sdk/ai/azure-ai-projects/docs/evaluation-typespec-issues.md similarity index 100% rename from sdk/ai/azure-ai-projects/evaluation-typespec-issues.md rename to sdk/ai/azure-ai-projects/docs/evaluation-typespec-issues.md diff --git a/sdk/ai/azure-ai-projects/docs/subclients.md b/sdk/ai/azure-ai-projects/docs/public-methods.md similarity index 64% rename from sdk/ai/azure-ai-projects/docs/subclients.md rename to sdk/ai/azure-ai-projects/docs/public-methods.md index e6b40e3e6e1b..edcca485b7e6 100644 --- a/sdk/ai/azure-ai-projects/docs/subclients.md +++ b/sdk/ai/azure-ai-projects/docs/public-methods.md @@ -1,57 +1,89 @@ -# AIProjectClient Subclients +# Public AIProjectClient methods -This document lists all sub-clients available on `AIProjectClient` and their public method counts. Overload methods are not counted. Only synchronous methods are counted (but each one has an equivalent asynchronous method). +This document lists all public methods available on `AIProjectClient` and its sub-clients. Overload methods are not counted. Only synchronous methods are counted (but each one has an equivalent asynchronous method). ## Summary -There are a total of 139 unique public methods across all sub-clients. +There are a total of 143 unique public methods: +- 5 stable methods on the client +- 57 stable methods on top-level sub-clients +- 81 beta methods on nested beta sub-clients -### Top-level Sub-clients (stable operations) +### Top-level sub-clients (stable operations) | Subclient | Class Name | Methods Count | |-----------|------------|----------------| -| `agents` | AgentsOperations | 8 | -| `evaluation_rules` | EvaluationRulesOperations | 4 | +| `agents` | AgentsOperations | 25 | | `connections` | ConnectionsOperations | 3 | | `datasets` | DatasetsOperations | 9 | | `deployments` | DeploymentsOperations | 2 | +| `evaluation_rules` | EvaluationRulesOperations | 4 | | `indexes` | IndexesOperations | 5 | | `telemetry` | TelemetryOperations | 1 | +| `toolboxes` | ToolboxesOperations | 8 | -### Nested Sub-clients (beta operations) +### Nested sub-clients (beta operations) | Subclient | Class Name | Methods Count | |-----------|------------|----------------| -| `beta.agents` | BetaAgentsOperations | 24 | +| `beta.agents` | BetaAgentsOperations | 5 | | `beta.datasets` | BetaDatasetsOperations | 5 | | `beta.evaluation_taxonomies` | BetaEvaluationTaxonomiesOperations | 5 | | `beta.evaluators` | BetaEvaluatorsOperations | 13 | | `beta.insights` | BetaInsightsOperations | 3 | | `beta.memory_stores` | BetaMemoryStoresOperations | 13 | -| `beta.models` | BetaModelsOperations | 8 | +| `beta.models` | BetaModelsOperations | 9 | | `beta.red_teams` | BetaRedTeamsOperations | 3 | | `beta.routines` | BetaRoutinesOperations | 8 | | `beta.schedules` | BetaSchedulesOperations | 6 | | `beta.skills` | BetaSkillsOperations | 11 | -| `beta.toolboxes` | BetaToolboxesOperations | 8 | -## Method list table +## Stable methods on the client + +Alphabetically sorted. An asterisk at the end of the method name means is a hand-written method. + +``` +.__enter__ +.__exit__ +.close +.get_openai_client* +.send_request +``` -Alphabetically sorted, with ".beta" sub-client at the end. +## Stable methods on top-level sub clients + +Alphabetically sorted. An asterisk at the end of the method name means is a hand-written method. ``` +.agents.create_session .agents.create_version +.agents.create_version_from_code .agents.create_version_from_manifest .agents.delete +.agents.delete_session +.agents.delete_session_file .agents.delete_version +.agents.disable +.agents.download_code_as_bytes +.agents.download_code_to_path* +.agents.download_session_file_as_bytes +.agents.download_session_file_to_path* +.agents.enable .agents.get +.agents.get_session +.agents.get_session_log_stream .agents.get_version .agents.list +.agents.list_session_files +.agents.list_sessions .agents.list_versions +.agents.stop_session +.agents.update_details +.agents.upload_session_file* -.connections.get -.connections.get_default +.connections.get* +.connections.get_default* .connections.list .datasets.create_or_update @@ -61,8 +93,8 @@ Alphabetically sorted, with ".beta" sub-client at the end. .datasets.list .datasets.list_versions .datasets.pending_upload -.datasets.upload_file -.datasets.upload_folder +.datasets.upload_file* +.datasets.upload_folder* .deployments.get .deployments.list @@ -78,32 +110,28 @@ Alphabetically sorted, with ".beta" sub-client at the end. .indexes.list .indexes.list_versions -.telemetry.get_application_insights_connection_string +.telemetry.get_application_insights_connection_string* +.toolboxes.create_version +.toolboxes.delete +.toolboxes.delete_version +.toolboxes.get +.toolboxes.get_version +.toolboxes.list +.toolboxes.list_versions +.toolboxes.update +``` + +## Beta methods on nested sub-clients + +Alphabetically sorted. An asterisk at the end of the method name means is a hand-written method. + +``` .beta.agents.cancel_optimization_job .beta.agents.create_optimization_job -.beta.agents.create_session -.beta.agents.create_version_from_code .beta.agents.delete_optimization_job -.beta.agents.delete_session -.beta.agents.delete_session_file -.beta.agents.download_code -.beta.agents.download_session_file -.beta.agents.get_candidate_file -.beta.agents.get_optimization_candidate -.beta.agents.get_optimization_candidate_config -.beta.agents.get_optimization_candidate_results .beta.agents.get_optimization_job -.beta.agents.get_session -.beta.agents.get_session_log_stream -.beta.agents.list_optimization_candidates .beta.agents.list_optimization_jobs -.beta.agents.list_session_files -.beta.agents.list_sessions -.beta.agents.patch_agent_details -.beta.agents.promote_candidate -.beta.agents.stop_session -.beta.agents.upload_session_file .beta.datasets.cancel_generation_job .beta.datasets.create_generation_job @@ -135,7 +163,7 @@ Alphabetically sorted, with ".beta" sub-client at the end. .beta.insights.get .beta.insights.list -.beta.memory_stores.begin_update_memories +.beta.memory_stores.begin_update_memories* .beta.memory_stores.create .beta.memory_stores.create_memory .beta.memory_stores.delete @@ -145,16 +173,17 @@ Alphabetically sorted, with ".beta" sub-client at the end. .beta.memory_stores.get_memory .beta.memory_stores.list .beta.memory_stores.list_memories -.beta.memory_stores.search_memories +.beta.memory_stores.search_memories* .beta.memory_stores.update .beta.memory_stores.update_memory -.beta.models.pending_create_version +.beta.models.create* .beta.models.delete .beta.models.get .beta.models.get_credentials .beta.models.list .beta.models.list_versions +.beta.models.pending_create_version .beta.models.pending_upload .beta.models.update @@ -189,13 +218,4 @@ Alphabetically sorted, with ".beta" sub-client at the end. .beta.skills.list .beta.skills.list_versions .beta.skills.update - -.beta.toolboxes.create_version -.beta.toolboxes.delete -.beta.toolboxes.delete_version -.beta.toolboxes.get -.beta.toolboxes.get_version -.beta.toolboxes.list -.beta.toolboxes.list_versions -.beta.toolboxes.update ``` diff --git a/sdk/ai/azure-ai-projects/docs/tool-classes-removed-properties.md b/sdk/ai/azure-ai-projects/docs/tool-classes-removed-properties.md new file mode 100644 index 000000000000..7a0f4e3ebd2d --- /dev/null +++ b/sdk/ai/azure-ai-projects/docs/tool-classes-removed-properties.md @@ -0,0 +1,43 @@ +# Tool Classes: Removed Properties (v2.2.0 → v2.3.0) + +The following Tool-derived classes had properties **removed** in v2.3.0 compared to v2.2.0. These properties (`name`, `description`, `tool_configs`) now only exist on the corresponding `ToolboxTool` subclasses. + +## General Availability Tools + +| Class Name | Removed Properties | +|------------|-------------------| +| `AzureAISearchTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `AzureFunctionTool` | `tool_configs: Optional[dict[str, ToolConfig]]` | +| `BingGroundingTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `CaptureStructuredOutputsTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `CodeInterpreterTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `FileSearchTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `FunctionShellToolParam` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `FunctionTool` | *(no changes)* | +| `ImageGenTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `LocalShellToolParam` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `MCPTool` | `tool_configs: Optional[dict[str, ToolConfig]]` | +| `OpenApiTool` | `tool_configs: Optional[dict[str, ToolConfig]]` | +| `WebSearchTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +v +## Preview Tools + +| Class Name | Removed Properties | +|------------|-------------------| +| `A2APreviewTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `BingCustomSearchPreviewTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `BrowserAutomationPreviewTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `ComputerUsePreviewTool` | *(no changes)* | +| `FabricIQPreviewTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `MemorySearchPreviewTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `MicrosoftFabricPreviewTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `SharepointPreviewTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `ToolboxSearchPreviewTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | +| `WebSearchPreviewTool` | *(no changes)* | +| `WorkIQPreviewTool` | `name: Optional[str]`, `description: Optional[str]`, `tool_configs: Optional[dict[str, ToolConfig]]` | + +## Summary + +- **Total Tool classes analyzed:** 24 +- **Classes with removed properties:** 19 +- **Common pattern:** `name`, `description`, and `tool_configs` were moved exclusively to `ToolboxTool` subclasses diff --git a/sdk/ai/azure-ai-projects/post-emitter-fixes.cmd b/sdk/ai/azure-ai-projects/post-emitter-fixes.cmd deleted file mode 100644 index 029f54360f28..000000000000 --- a/sdk/ai/azure-ai-projects/post-emitter-fixes.cmd +++ /dev/null @@ -1,93 +0,0 @@ -REM -REM To emit from TypeSpec, run this in the current folder: -REM -REM tsp-client update --debug --local-spec-repo e:\src\azure-rest-api-specs\specification\ai-foundry\data-plane\Foundry -REM -REM (replace `e:\src\...` with the local folder containing up to date TypeSpec) -REM -REM Then run this script to "fix" the emitted code. -REM - -REM Revert emitted pyprojects.toml, since it overrides the following changes: -REM - We added "Programming Language :: Python :: 3.14". The emitter removes it. -REM - The emitter uses lower case "i" in "Ai". I want to keep it upper case in the description field: "Microsoft Corporation Azure AI Projects Client Library for Python". -REM - We want a vanity link for the "repository" value, deep linking to the SDK folder (not root of repo): https://aka.ms/azsdk/azure-ai-projects-v2/python/code -git restore pyproject.toml - -REM Rename `"items_property": items`, to `"items": items` in search_memories and begin_update_memories methods. "items" is specified in TypeSpec, but Python emitter does not allow it. -powershell -Command "(Get-Content azure\ai\projects\aio\operations\_operations.py) -replace '\"items_property\": items', '\"items\": items' | Set-Content azure\ai\projects\aio\operations\_operations.py" -powershell -Command "(Get-Content azure\ai\projects\operations\_operations.py) -replace '\"items_property\": items', '\"items\": items' | Set-Content azure\ai\projects\operations\_operations.py" - -REM Rename WEB_SEARCH_PREVIEW2025_03_11 enum member to WEB_SEARCH_PREVIEW_2025_03_11, to match actual string value -powershell -Command "(Get-Content azure\ai\projects\models\_enums.py) -replace 'WEB_SEARCH_PREVIEW2025_03_11', 'WEB_SEARCH_PREVIEW_2025_03_11' | Set-Content azure\ai\projects\models\_enums.py" -powershell -Command "(Get-Content azure\ai\projects\models\_models.py) -replace 'WEB_SEARCH_PREVIEW2025_03_11', 'WEB_SEARCH_PREVIEW_2025_03_11' | Set-Content azure\ai\projects\models\_models.py" - -REM Rename DEFAULT2024_11_15 to DEFAULT_2024_11_15 -powershell -Command "(Get-Content azure\ai\projects\models\_enums.py) -replace 'DEFAULT2024_11_15', 'DEFAULT_2024_11_15' | Set-Content azure\ai\projects\models\_enums.py" - -REM Rename `A2_A` to `A2A` in enum class AgentEndpointProtocol and ToolType -powershell -Command "(Get-Content azure\ai\projects\models\_enums.py) -replace 'A2_A', 'A2A' | Set-Content azure\ai\projects\models\_enums.py" -powershell -Command "(Get-Content azure\ai\projects\models\_models.py) -replace 'A2_A', 'A2A' | Set-Content azure\ai\projects\models\_models.py" - -REM Rename MEMORY1_GB/MEMORY4_GB/MEMORY16_GB/MEMORY64_GB to MEMORY_1GB/MEMORY_4GB/MEMORY_16GB/MEMORY_64GB in enum class ContainerMemoryLimit -REM For some reason these TypeSpec decorators stopped working. Need to understand why: @@clientName(OpenAI.ContainerMemoryLimit.`1g`, "MEMORY_1GB", "python"); -powershell -Command "(Get-Content azure\ai\projects\models\_enums.py) -replace 'MEMORY1_GB', 'MEMORY_1GB' | Set-Content azure\ai\projects\models\_enums.py" -powershell -Command "(Get-Content azure\ai\projects\models\_enums.py) -replace 'MEMORY4_GB', 'MEMORY_4GB' | Set-Content azure\ai\projects\models\_enums.py" -powershell -Command "(Get-Content azure\ai\projects\models\_enums.py) -replace 'MEMORY16_GB', 'MEMORY_16GB' | Set-Content azure\ai\projects\models\_enums.py" -powershell -Command "(Get-Content azure\ai\projects\models\_enums.py) -replace 'MEMORY64_GB', 'MEMORY_64GB' | Set-Content azure\ai\projects\models\_enums.py" - -REM Edit both _operations.py files to fix missing Foundry-Features HTTP request header in continued list paging calls. Add: -REM headers=_headers -REM to the end of each of these lines in the BetaXxxOperations classes (do not do this in GA operations classes!) -REM "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params -REM In emitted code, these first 7 of those lines are associated with GA operations, so start the replacement -REM from the 8th occurrence onward. -powershell -Command "$gaCount=7; $old=[char]34+'GET'+[char]34+', urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params'; $new=$old+', headers=_headers'; foreach ($f in 'azure\ai\projects\aio\operations\_operations.py','azure\ai\projects\operations\_operations.py') { $c=Get-Content $f -Raw; $parts=$c -split [regex]::Escape($old); $r=$parts[0]; for ($i=1; $i -lt $parts.Length; $i++) { if ($i -le $gaCount) { $r+=$old+$parts[$i] } else { $r+=$new+$parts[$i] } }; Set-Content $f $r -NoNewline }" - -REM Force streaming in get_session_log_stream for both sync and async operations. -powershell -Command "$files='azure\ai\projects\operations\_operations.py','azure\ai\projects\aio\operations\_operations.py'; foreach ($f in $files) { $lines=Get-Content $f; $inFunc=$false; for ($i=0; $i -lt $lines.Length; $i++) { if ($lines[$i] -match '^\s*(async\s+)?def\s+get_session_log_stream\(') { $inFunc=$true; continue }; if ($inFunc -and $lines[$i] -match '^\s*(async\s+)?def\s+\w+\(') { $inFunc=$false }; if ($inFunc -and $lines[$i] -match 'kwargs\.pop\(.+stream.+False\)') { $indent=([regex]::Match($lines[$i], '^\s*')).Value; $lines[$i]=$indent + '_stream = True' } }; Set-Content $f $lines }" - -REM Fix Sphinx issue in class ToolChoiceAllowed, in "tools" property doc string. The "Required" cannot come at the end of the code-block. -REM move it to the end of the text before the code block, and make sure there are no periods after "]". -REM .. code-block:: json -REM -REM [ -REM { "type": "function", "name": "get_weather" }, -REM { "type": "mcp", "server_label": "deepwiki" }, -REM { "type": "image_generation" } -REM ]. Required. -powershell -Command "(Get-Content azure\ai\projects\models\_models.py) -replace 'Responses API, the list of tool definitions might look like:', 'Responses API, the list of tool definitions might look like the following. Required.' | Set-Content azure\ai\projects\models\_models.py" -powershell -Command "(Get-Content azure\ai\projects\models\_models.py) -replace 'list of tool definitions might look like:', 'list of tool definitions might look like the following. Required.' | Set-Content azure\ai\projects\models\_models.py" -powershell -Command "(Get-Content azure\ai\projects\models\_models.py) -replace ' \]\. Required\.', ' ]' | Set-Content azure\ai\projects\models\_models.py" - -REM Fix Sphinx docutils warnings in class SessionLogEvent: the generated docstring wraps two long -REM ``data:`` JSON lines mid-string inside a ``.. code-block::`` section. The wrapped continuation -REM lines have wrong indentation (4 spaces instead of 7), causing "unexpected unindent" warnings. -REM Join each broken pair back into one line. -powershell -Command "$f='azure\ai\projects\models\_models.py'; $c=Get-Content $f -Raw; $c=$c -replace '(Starting server)\r?\n[ \t]+(on port 18080)', '$1 $2'; $c=$c -replace '(Successfully)\r?\n[ \t]+(connected to container\"})\.?', '$1 $2'; Set-Content $f $c -NoNewline; $lines=Get-Content $f; $out=@(); foreach ($line in $lines) { if ($line -match '^\s*on port 18080' -and $line -notmatch 'data:') { continue }; if ($line -match '^\s*connected to container' -and $line -notmatch 'data:') { continue }; if ($line -match '^\s*data: .*2026-03-10T09:33:17.121Z') { $out += (' ' + $line.TrimStart()); continue }; if ($line -match '^\s*data: .*2026-03-10T09:34:52.714Z') { $out += (' ' + $line.TrimStart()); continue }; $out += $line }; Set-Content $f $out" - -REM Fix Sphinx docutils warnings in get_session_log_stream docstrings (sync + async). -REM The emitter wraps bullet/code-block lines with insufficient indentation. -powershell -Command "$files='azure\ai\projects\operations\_operations.py','azure\ai\projects\aio\operations\_operations.py'; foreach ($f in $files) { $c=Get-Content $f -Raw; $c=$c -replace 'schema\r?\n\s+is not contractual and may include additional keys or change format\r?\n\s+over time [^\r\n]*clients should treat it as an opaque string\)', 'schema is not contractual and may include additional keys or change format over time; clients should treat it as an opaque string)'; $c=$c -replace '(message\":\"Starting)\r?\n\s+(FoundryCBAgent server on port 8088\"})', '$1 $2'; $c=$c -replace '(message\":\"INFO: Application)\r?\n\s+(startup complete\.\"})', '$1 $2'; $c=$c -replace '(message\":\"Successfully)\r?\n\s+(connected to container\"})', '$1 $2'; $c=$c -replace '(message\":\"No logs since)\r?\n\s+(last 60 seconds\"})', '$1 $2'; Set-Content $f $c -NoNewline }" - -REM Reorder loops in `prepare_multipart_form_data` and synthesize filenames for -REM bare bytes/str/IO file entries (azure\ai\projects\_utils\utils.py). -REM 1) The emitter generates the multipart-file loop before the data-field loop, -REM so JSON metadata parts end up after large binary file parts in the encoded -REM body. Some streaming server-side parsers (e.g. the Foundry hosted-agents -REM `create_agent_version_from_code` endpoint) require the small JSON metadata -REM parts to precede the binary file parts; otherwise they report the metadata -REM part as missing. -REM 2) When callers pass bare bytes (e.g. `Path("x.zip").read_bytes()`) for a -REM multipart file field, the part is emitted without a `filename=` in its -REM Content-Disposition, and servers (e.g. Foundry `create_from_files` for -REM skills) reject it with "At least one file must be uploaded". This rewrite -REM synthesizes a filename for bare bytes/str/IO entries (from `.name` when -REM available, otherwise a stable default) so the part is encoded as a file. -powershell -Command "$f='azure\ai\projects\_utils\utils.py'; $c=Get-Content $f -Raw; if ($c -notmatch '(?m)^import os\r?$') { $c=$c -replace '(?m)^import json\r?$', \"import json`r`nimport os\" }; if ($c -notmatch ':param field_name: The multipart form field name') { $c=$c -replace '(?s)def _normalize_multipart_file_entry\(.*?return \(filename, entry\)\r?\n\r?\n\r?\n', ''; $helper=(@('def _normalize_multipart_file_entry(field_name: str, entry: Any, index: int) -> Any:',' \"\"\"Ensure each multipart file entry carries a filename so that it is encoded',' as a file part (with ``filename=``) rather than a plain form field.','',' Servers commonly distinguish multipart file parts from form-data parts by',' the presence of ``filename=`` in the part''s ``Content-Disposition`` header.',' When callers pass bare bytes / str / IO objects (e.g.',' ``Path(\"x.zip\").read_bytes()``), the underlying HTTP client emits the part',' without a filename, which several Foundry endpoints reject with errors like',' \"At least one file must be uploaded\". This helper synthesizes a filename',' from the IO object''s ``name`` attribute when available, otherwise falls',' back to a stable default.','',' :param field_name: The multipart form field name, used as a fallback filename.',' :type field_name: str',' :param entry: The file entry to normalize. May be a tuple, bytes, str, or IO object.',' :type entry: any',' :param index: Position of the entry within its field''s list, used to disambiguate fallback filenames.',' :type index: int',' :return: A ``(filename, entry)`` tuple if ``entry`` was not already a tuple, otherwise ``entry`` unchanged.',' :rtype: any',' \"\"\"',' if isinstance(entry, tuple):',' return entry',' filename: Optional[str] = None',' name_attr = getattr(entry, \"name\", None)',' if isinstance(name_attr, str) and name_attr:',' filename = os.path.basename(name_attr)',' if not filename:',' filename = f\"{field_name}_{index}\" if index else field_name',' return (filename, entry)','','') -join [Environment]::NewLine); $c=$c -replace '(?m)^def prepare_multipart_form_data\(', ($helper + 'def prepare_multipart_form_data('); $pattern='(?s) files: list\[FileType\] = \[\]\r?\n.*? return files'; $new=(@(' files: list[FileType] = []','',' # Append data fields first so they appear before file parts in the encoded',' # multipart body. Some streaming server-side parsers (e.g. the Foundry',' # hosted-agents `create_agent_version_from_code` endpoint) require small',' # JSON metadata parts to precede large binary file parts; otherwise they',' # report the metadata part as missing.',' for data_field in data_fields:',' data_entry = body.get(data_field)',' if data_entry:',' files.append((data_field, str(serialize_multipart_data_entry(data_entry))))','',' for multipart_field in multipart_fields:',' multipart_entry = body.get(multipart_field)',' if isinstance(multipart_entry, list):',' for idx, e in enumerate(multipart_entry):',' files.append((multipart_field, _normalize_multipart_file_entry(multipart_field, e, idx)))',' elif multipart_entry:',' files.append((multipart_field, _normalize_multipart_file_entry(multipart_field, multipart_entry, 0)))','',' return files') -join [Environment]::NewLine); $c=[regex]::Replace($c, $pattern, $new) }; Set-Content $f $c -NoNewline" - -REM Finishing by running 'black' tool to format code. -pip install black -black --config ../../../eng/black-pyproject.toml . || echo black not found, skipping formatting. - - diff --git a/sdk/ai/azure-ai-projects/pyproject.toml b/sdk/ai/azure-ai-projects/pyproject.toml index 26eac48e1123..3cc1de11d7af 100644 --- a/sdk/ai/azure-ai-projects/pyproject.toml +++ b/sdk/ai/azure-ai-projects/pyproject.toml @@ -67,6 +67,9 @@ pytyped = ["py.typed"] [tool.azure-sdk-build] verifytypes = false +[tool.mypy] +exclude = '.*samples[\\/]hosted_agents[\\/]assets[\\/].*main\.py$' + [tool.azure-sdk-conda] in_bundle = false diff --git a/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py b/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py new file mode 100644 index 000000000000..575a7ca885f3 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py @@ -0,0 +1,127 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +DESCRIPTION: + Given an AIProjectClient, this sample demonstrates how to create an agent + optimization job, poll it to completion, and read the results. + + Agent optimization automatically improves an agent's system prompt, model + choice, or tool definitions by running candidate variants against your + training dataset and scoring them with the evaluators you specify. + +USAGE: + python sample_optimization_job_basic.py + + Before running the sample: + + pip install "azure-ai-projects>=2.3.0" azure-identity python-dotenv + + Set these environment variables with your own values: + 1) FOUNDRY_PROJECT_ENDPOINT - Required. The Azure AI Project endpoint, as found + in the overview page of your Microsoft Foundry portal. + 2) FOUNDRY_AGENT_NAME - Required. The name of the agent to optimize. + 3) DATASET_NAME - Required. The name of the registered training dataset. + 4) EVALUATOR_NAME - Required. The name of a registered project evaluator. + 5) DATASET_VERSION - Optional. Version of the training dataset. Defaults to "1". + 6) POLL_INTERVAL_SECONDS - Optional. Seconds between status polls. Defaults to 10. + 7) EVAL_MODEL - Optional. The model used for evaluation. Defaults to "gpt-4o". + 8) OPTIMIZATION_MODEL - Optional. The model used for optimization. Defaults to "gpt-5.1". +""" + +import os +import time + +from dotenv import load_dotenv + +from azure.identity import DefaultAzureCredential +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import ( + OptimizationAgentIdentifier as AgentIdentifier, + OptimizationEvaluatorRef as EvaluatorRef, + JobStatus, + OptimizationJob, + OptimizationJobInputs, + OptimizationOptions, + OptimizationReferenceDatasetInput as ReferenceDatasetInput, +) + +load_dotenv() + +endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] +agent_name = os.environ["FOUNDRY_AGENT_NAME"] +dataset_name = os.environ["DATASET_NAME"] +evaluator_name = os.environ["EVALUATOR_NAME"] +dataset_version = os.environ.get("DATASET_VERSION", "1") +poll_interval = int(os.environ.get("POLL_INTERVAL_SECONDS", "10")) +eval_model = os.environ.get("EVAL_MODEL", "gpt-4o") +optimization_model = os.environ.get("OPTIMIZATION_MODEL", "gpt-5.1") + +TERMINAL_STATUSES = {JobStatus.SUCCEEDED, JobStatus.FAILED, JobStatus.CANCELLED} + +with ( + DefaultAzureCredential() as credential, + AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client, +): + + # ------------------------------------------------------------------ + # 1. Create an optimization job. + # ------------------------------------------------------------------ + print("Creating optimization job...") + job = project_client.beta.agents.create_optimization_job( + job=OptimizationJob( + inputs=OptimizationJobInputs( + agent=AgentIdentifier(agent_name=agent_name), + train_dataset=ReferenceDatasetInput( + name=dataset_name, + version=dataset_version, + ), + evaluators=[EvaluatorRef(name=evaluator_name)], + options=OptimizationOptions( + max_candidates=3, + eval_model=eval_model, + optimization_model=optimization_model, + ), + ) + ) + ) + print(f"Created job: id={job.id}, status={job.status}") + + # ------------------------------------------------------------------ + # 2. Poll until the job reaches a terminal state. + # ------------------------------------------------------------------ + print(f"Polling job `{job.id}` to completion...", end="", flush=True) + while job.status not in TERMINAL_STATUSES: + time.sleep(poll_interval) + job = project_client.beta.agents.get_optimization_job(job_id=job.id) + print(".", end="", flush=True) + print() + print(f"Final status: {job.status}") + + if job.warnings: + for warning in job.warnings: + print(f"[WARNING] {warning}") + + if job.status == JobStatus.FAILED: + message = job.error.message if job.error else "" + raise RuntimeError(f"Optimization job `{job.id}` failed: {message}") + + # ------------------------------------------------------------------ + # 3. Inspect the results. + # ------------------------------------------------------------------ + if job.status == JobStatus.SUCCEEDED and job.result: + result = job.result + print(f"\nBaseline candidate: {result.baseline}") + print(f"Best candidate: {result.best}") + print(f"Candidates ({len(result.candidates or [])}):") + for candidate in result.candidates or []: + print( + f" - {candidate.name}" + f" | avg_score={candidate.avg_score:.4f}" + f" | avg_tokens={candidate.avg_tokens:.0f}" + ) + if candidate.eval_id: + print(f" eval_id={candidate.eval_id}") diff --git a/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py b/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py new file mode 100644 index 000000000000..6a636a03c5a0 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py @@ -0,0 +1,130 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +DESCRIPTION: + Async version of sample_optimization_job_basic.py. Demonstrates how to + create an agent optimization job, poll it to completion, and read the + results using the async AIProjectClient. + +USAGE: + python sample_optimization_job_basic_async.py + + Before running the sample: + + pip install "azure-ai-projects>=2.3.0" azure-identity python-dotenv + + Set these environment variables with your own values: + 1) FOUNDRY_PROJECT_ENDPOINT - Required. The Azure AI Project endpoint, as found + in the overview page of your Microsoft Foundry portal. + 2) FOUNDRY_AGENT_NAME - Required. The name of the agent to optimize. + 3) DATASET_NAME - Required. The name of the registered training dataset. + 4) EVALUATOR_NAME - Required. The name of a registered project evaluator. + 5) DATASET_VERSION - Optional. Version of the training dataset. Defaults to "1". + 6) POLL_INTERVAL_SECONDS - Optional. Seconds between status polls. Defaults to 10. + 7) EVAL_MODEL - Optional. The model used for evaluation. Defaults to "gpt-4o". + 8) OPTIMIZATION_MODEL - Optional. The model used for optimization. Defaults to "gpt-5.1". +""" + +import asyncio +import os + +from dotenv import load_dotenv + +from azure.identity.aio import DefaultAzureCredential +from azure.ai.projects.aio import AIProjectClient +from azure.ai.projects.models import ( + OptimizationAgentIdentifier as AgentIdentifier, + OptimizationEvaluatorRef as EvaluatorRef, + JobStatus, + OptimizationJob, + OptimizationJobInputs, + OptimizationOptions, + OptimizationReferenceDatasetInput as ReferenceDatasetInput, +) + +load_dotenv() + +endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] +agent_name = os.environ["FOUNDRY_AGENT_NAME"] +dataset_name = os.environ["DATASET_NAME"] +evaluator_name = os.environ["EVALUATOR_NAME"] +dataset_version = os.environ.get("DATASET_VERSION", "1") +eval_model = os.environ.get("EVAL_MODEL", "gpt-4o") +optimization_model = os.environ.get("OPTIMIZATION_MODEL", "gpt-5.1") +poll_interval = int(os.environ.get("POLL_INTERVAL_SECONDS", "10")) + +TERMINAL_STATUSES = {JobStatus.SUCCEEDED, JobStatus.FAILED, JobStatus.CANCELLED} + + +async def main() -> None: + async with ( + DefaultAzureCredential() as credential, + AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client, + ): + + # ------------------------------------------------------------------ + # 1. Create an optimization job. + # ------------------------------------------------------------------ + print("Creating optimization job...") + job = await project_client.beta.agents.create_optimization_job( + job=OptimizationJob( + inputs=OptimizationJobInputs( + agent=AgentIdentifier(agent_name=agent_name), + train_dataset=ReferenceDatasetInput( + name=dataset_name, + version=dataset_version, + ), + evaluators=[EvaluatorRef(name=evaluator_name)], + options=OptimizationOptions( + max_candidates=3, + eval_model=eval_model, + optimization_model=optimization_model, + ), + ) + ) + ) + print(f"Created job: id={job.id}, status={job.status}") + + # ------------------------------------------------------------------ + # 2. Poll until terminal state. + # ------------------------------------------------------------------ + print(f"Polling job `{job.id}` to completion...", end="", flush=True) + while job.status not in TERMINAL_STATUSES: + await asyncio.sleep(poll_interval) + job = await project_client.beta.agents.get_optimization_job(job_id=job.id) + print(".", end="", flush=True) + print() + print(f"Final status: {job.status}") + + if job.warnings: + for warning in job.warnings: + print(f"[WARNING] {warning}") + + if job.status == JobStatus.FAILED: + message = job.error.message if job.error else "" + raise RuntimeError(f"Optimization job `{job.id}` failed: {message}") + + # ------------------------------------------------------------------ + # 3. Inspect the results. + # ------------------------------------------------------------------ + if job.status == JobStatus.SUCCEEDED and job.result: + result = job.result + print(f"\nBaseline candidate: {result.baseline}") + print(f"Best candidate: {result.best}") + print(f"Candidates ({len(result.candidates or [])}):") + for candidate in result.candidates or []: + print( + f" - {candidate.name}" + f" | avg_score={candidate.avg_score:.4f}" + f" | avg_tokens={candidate.avg_tokens:.0f}" + ) + if candidate.eval_id: + print(f" eval_id={candidate.eval_id}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_cancel.py b/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_cancel.py new file mode 100644 index 000000000000..9dd011a14394 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_cancel.py @@ -0,0 +1,90 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +DESCRIPTION: + Given an AIProjectClient, this sample demonstrates how to create an agent + optimization job and immediately cancel it. + +USAGE: + python sample_optimization_job_cancel.py + + Before running the sample: + + pip install "azure-ai-projects>=2.3.0" azure-identity python-dotenv + + Set these environment variables with your own values: + 1) FOUNDRY_PROJECT_ENDPOINT - Required. The Azure AI Project endpoint, as found + in the overview page of your Microsoft Foundry portal. + 2) FOUNDRY_AGENT_NAME - Required. The name of the agent to optimize. + 3) DATASET_NAME - Required. The name of the registered training dataset. + 4) EVALUATOR_NAME - Required. The name of a registered project evaluator. + 5) DATASET_VERSION - Optional. Version of the training dataset. Defaults to "1". + 6) EVAL_MODEL - Optional. The model used for evaluation. Defaults to "gpt-4o". + 7) OPTIMIZATION_MODEL - Optional. The model used for optimization. Defaults to "gpt-5.1". + +""" + +import os + +from dotenv import load_dotenv + +from azure.identity import DefaultAzureCredential +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import ( + OptimizationAgentIdentifier as AgentIdentifier, + OptimizationEvaluatorRef as EvaluatorRef, + OptimizationJob, + OptimizationJobInputs, + OptimizationOptions, + OptimizationReferenceDatasetInput as ReferenceDatasetInput, +) + +load_dotenv() + +endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] +agent_name = os.environ["FOUNDRY_AGENT_NAME"] +dataset_name = os.environ["DATASET_NAME"] +evaluator_name = os.environ["EVALUATOR_NAME"] +dataset_version = os.environ.get("DATASET_VERSION", "1") +eval_model = os.environ.get("EVAL_MODEL", "gpt-4o") +optimization_model = os.environ.get("OPTIMIZATION_MODEL", "gpt-5.1") + + +with ( + DefaultAzureCredential() as credential, + AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client, +): + + # ------------------------------------------------------------------ + # 1. Create a job. + # ------------------------------------------------------------------ + print("Creating optimization job...") + job = project_client.beta.agents.create_optimization_job( + job=OptimizationJob( + inputs=OptimizationJobInputs( + agent=AgentIdentifier(agent_name=agent_name), + train_dataset=ReferenceDatasetInput( + name=dataset_name, + version=dataset_version, + ), + evaluators=[EvaluatorRef(name=evaluator_name)], + options=OptimizationOptions( + max_candidates=3, + eval_model=eval_model, + optimization_model=optimization_model, + ), + ) + ) + ) + print(f"Created job: id={job.id}, status={job.status}") + + # ------------------------------------------------------------------ + # 2. Cancel it immediately. + # ------------------------------------------------------------------ + print(f"Cancelling job {job.id}...") + cancelled = project_client.beta.agents.cancel_optimization_job(job_id=job.id) + print(f"Job {cancelled.id} status: {cancelled.status}") diff --git a/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_list_get_delete.py b/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_list_get_delete.py new file mode 100644 index 000000000000..f2d87a84b668 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_list_get_delete.py @@ -0,0 +1,98 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +DESCRIPTION: + Given an AIProjectClient, this sample demonstrates how to list optimization + jobs (with optional filters), get a specific job by ID, and delete a job. + +USAGE: + python sample_optimization_job_list_get_delete.py + + Before running the sample: + + pip install "azure-ai-projects>=2.3.0" azure-identity python-dotenv + + Set these environment variables with your own values: + 1) FOUNDRY_PROJECT_ENDPOINT - Required. The Azure AI Project endpoint, as found + in the overview page of your Microsoft Foundry portal. + 2) FOUNDRY_AGENT_NAME - Required. Filter the list to jobs for this agent. + 3) JOB_ID - Required. If set, fetches and deletes this specific job. +""" + +import os + +from dotenv import load_dotenv + +from azure.identity import DefaultAzureCredential +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import JobStatus + +load_dotenv() + +endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] +agent_name = os.environ["FOUNDRY_AGENT_NAME"] +job_id = os.environ["JOB_ID"] + +with ( + DefaultAzureCredential() as credential, + AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client, +): + + # ------------------------------------------------------------------ + # 1. List the most recent 10 optimization jobs (unfiltered). + # ------------------------------------------------------------------ + print("Listing optimization jobs (limit=10):") + count = 0 + for job_list_item in project_client.beta.agents.list_optimization_jobs(limit=10): + agent_str = job_list_item.agent.agent_name if job_list_item.agent else "?" + print(f" {job_list_item.id} | status={job_list_item.status} | agent={agent_str}") + count += 1 + print(f" ({count} jobs listed)\n") + + # ------------------------------------------------------------------ + # 2. List jobs filtered by agent name (if provided). + # ------------------------------------------------------------------ + if agent_name: + print(f"Listing jobs for agent '{agent_name}' (limit=10):") + count = 0 + for job_list_item in project_client.beta.agents.list_optimization_jobs(agent_name=agent_name, limit=10): + print(f" {job_list_item.id} | status={job_list_item.status}") + count += 1 + print(f" ({count} jobs)\n") + + # ------------------------------------------------------------------ + # 3. List jobs filtered by status. + # ------------------------------------------------------------------ + print(f"Listing succeeded jobs (limit=5):") + count = 0 + for job_list_item in project_client.beta.agents.list_optimization_jobs(status=JobStatus.SUCCEEDED, limit=5): + print(f" {job_list_item.id}") + count += 1 + print(f" ({count} succeeded jobs)\n") + + # ------------------------------------------------------------------ + # 4. Get a specific job by ID (if provided). + # ------------------------------------------------------------------ + if job_id: + print(f"Getting job {job_id}...") + job = project_client.beta.agents.get_optimization_job(job_id=job_id) + print(f" status={job.status}") + if job.inputs: + print(f" agent={job.inputs.agent.agent_name if job.inputs.agent else '?'}") + if job.result: + print(f" baseline={job.result.baseline}, best={job.result.best}") + print(f" candidates: {len(job.result.candidates or [])}") + if job.warnings: + for w in job.warnings: + print(f" [WARNING] {w}") + + # ------------------------------------------------------------------ + # 5. Delete the job. + # ------------------------------------------------------------------ + print(f"\nDeleting job {job_id}...") + project_client.beta.agents.delete_optimization_job(job_id=job_id) + print(" Deleted.") diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skill_in_toolbox.py b/sdk/ai/azure-ai-projects/samples/agents/tools/sample_agent_toolbox_skill.py similarity index 90% rename from sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skill_in_toolbox.py rename to sdk/ai/azure-ai-projects/samples/agents/tools/sample_agent_toolbox_skill.py index af07a47bae37..25c4a2a96d1d 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skill_in_toolbox.py +++ b/sdk/ai/azure-ai-projects/samples/agents/tools/sample_agent_toolbox_skill.py @@ -17,16 +17,15 @@ context, so when asked a shipping-cost question the agent answers directly using the skill's formula. - Skills and Toolboxes are currently preview features. In the Python SDK, - you access these operations via `project_client.beta.skills` and - `project_client.beta.toolboxes`. + Skills are currently a preview features. In the Python SDK, + you access these operations via `project_client.beta.skills`. USAGE: - python sample_skill_in_toolbox.py + python sample_agent_toolbox_skill.py Before running the sample: - pip install "azure-ai-projects>=2.2.0" python-dotenv openai + pip install "azure-ai-projects>=2.3.0" python-dotenv openai Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the @@ -40,6 +39,7 @@ from dotenv import load_dotenv +from azure.ai.projects.models._models import ToolboxSearchPreviewToolboxTool from azure.core.exceptions import ResourceNotFoundError from azure.identity import DefaultAzureCredential @@ -48,7 +48,7 @@ MCPTool, PromptAgentDefinition, SkillInlineContent, - ToolboxSearchPreviewTool, + ToolboxSearchPreviewToolboxTool, ToolboxSkillReference, ) @@ -68,7 +68,7 @@ ): try: - project_client.beta.toolboxes.delete(TOOLBOX_NAME) + project_client.toolboxes.delete(TOOLBOX_NAME) except ResourceNotFoundError: pass @@ -92,10 +92,10 @@ ) print(f"Created skill: {skill_version.name} version={skill_version.version}") - toolbox_version = project_client.beta.toolboxes.create_version( + toolbox_version = project_client.toolboxes.create_version( name=TOOLBOX_NAME, description="Toolbox exposing a shipping-cost skill.", - tools=[ToolboxSearchPreviewTool()], + tools=[ToolboxSearchPreviewToolboxTool()], skills=[ToolboxSkillReference(name=skill_version.name, version=skill_version.version)], ) print(f"Created toolbox: {toolbox_version.name} version={toolbox_version.version}") @@ -107,7 +107,6 @@ server_label="skill-toolbox", server_url=toolbox_mcp_url, authorization=token, - headers={"Foundry-Features": "Toolboxes=V1Preview"}, require_approval="never", ) @@ -149,7 +148,7 @@ print(f"Response: {response.output_text}") - project_client.beta.toolboxes.delete(TOOLBOX_NAME) + project_client.toolboxes.delete(TOOLBOX_NAME) print("Toolbox deleted") project_client.beta.skills.delete(SKILL_NAME) print("Skill deleted") diff --git a/sdk/ai/azure-ai-projects/samples/agents/tools/sample_toolboxes_with_search_preview.py b/sdk/ai/azure-ai-projects/samples/agents/tools/sample_toolboxes_with_search_preview.py index 63bdc57e0ee8..ff4e7faa33f6 100644 --- a/sdk/ai/azure-ai-projects/samples/agents/tools/sample_toolboxes_with_search_preview.py +++ b/sdk/ai/azure-ai-projects/samples/agents/tools/sample_toolboxes_with_search_preview.py @@ -17,14 +17,14 @@ those inner tools. Toolboxes and tool search are preview features. CRUD goes through - 'project_client.beta.toolboxes'. + 'project_client.toolboxes'. USAGE: python sample_toolboxes_with_search_preview.py Before running the sample: - pip install "azure-ai-projects>=2.2.0" python-dotenv openai + pip install "azure-ai-projects>=2.3.0" python-dotenv openai Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -36,17 +36,14 @@ """ import os - from dotenv import load_dotenv - -from azure.core.exceptions import ResourceNotFoundError from azure.identity import DefaultAzureCredential - from azure.ai.projects import AIProjectClient from azure.ai.projects.models import ( MCPTool, + MCPToolboxTool, + ToolboxSearchPreviewToolboxTool, PromptAgentDefinition, - ToolboxSearchPreviewTool, ) load_dotenv() @@ -65,17 +62,17 @@ project_client.get_openai_client() as openai_client, ): - inner_mcp_tool = MCPTool( + inner_mcp_tool = MCPToolboxTool( server_label=INNER_MCP_LABEL, server_url=INNER_MCP_URL, require_approval="never", project_connection_id=os.environ["MCP_PROJECT_CONNECTION_ID"], ) - toolbox_version = project_client.beta.toolboxes.create_version( + toolbox_version = project_client.toolboxes.create_version( name=TOOLBOX_NAME, description=f"Toolbox with `{INNER_MCP_LABEL}` MCP server and tool search enabled.", - tools=[inner_mcp_tool, ToolboxSearchPreviewTool()], + tools=[inner_mcp_tool, ToolboxSearchPreviewToolboxTool()], ) print(f"Created toolbox `{TOOLBOX_NAME}` (version {toolbox_version.version}).") @@ -86,7 +83,6 @@ server_label=TOOLBOX_MCP_LABEL, server_url=toolbox_mcp_url, authorization=token, - headers={"Foundry-Features": "Toolboxes=V1Preview"}, require_approval="never", ) diff --git a/sdk/ai/azure-ai-projects/samples/agents/tools/sample_toolboxes_with_search_preview_async.py b/sdk/ai/azure-ai-projects/samples/agents/tools/sample_toolboxes_with_search_preview_async.py index bfd43071c2f3..1a44ab930311 100644 --- a/sdk/ai/azure-ai-projects/samples/agents/tools/sample_toolboxes_with_search_preview_async.py +++ b/sdk/ai/azure-ai-projects/samples/agents/tools/sample_toolboxes_with_search_preview_async.py @@ -17,14 +17,14 @@ those inner tools. Toolboxes and tool search are preview features. CRUD goes through - 'project_client.beta.toolboxes'. + 'project_client.toolboxes'. USAGE: python sample_toolboxes_with_search_preview_async.py Before running the sample: - pip install "azure-ai-projects>=2.2.0" python-dotenv openai aiohttp + pip install "azure-ai-projects>=2.3.0" python-dotenv openai aiohttp Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -37,16 +37,14 @@ import asyncio import os - from dotenv import load_dotenv - from azure.identity.aio import DefaultAzureCredential - from azure.ai.projects.aio import AIProjectClient from azure.ai.projects.models import ( MCPTool, + MCPToolboxTool, + ToolboxSearchPreviewToolboxTool, PromptAgentDefinition, - ToolboxSearchPreviewTool, ) load_dotenv() @@ -66,17 +64,17 @@ async def main() -> None: project_client.get_openai_client() as openai_client, ): - inner_mcp_tool = MCPTool( + inner_mcp_tool = MCPToolboxTool( server_label=INNER_MCP_LABEL, server_url=INNER_MCP_URL, require_approval="never", project_connection_id=os.environ["MCP_PROJECT_CONNECTION_ID"], ) - toolbox_version = await project_client.beta.toolboxes.create_version( + toolbox_version = await project_client.toolboxes.create_version( name=TOOLBOX_NAME, description=f"Toolbox with `{INNER_MCP_LABEL}` MCP server and tool search enabled.", - tools=[inner_mcp_tool, ToolboxSearchPreviewTool()], + tools=[inner_mcp_tool, ToolboxSearchPreviewToolboxTool()], ) print(f"Created toolbox `{TOOLBOX_NAME}` (version {toolbox_version.version}).") @@ -87,7 +85,6 @@ async def main() -> None: server_label=TOOLBOX_MCP_LABEL, server_url=toolbox_mcp_url, authorization=token, - headers={"Foundry-Features": "Toolboxes=V1Preview"}, require_approval="never", ) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/canvas-design.zip b/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/canvas-design.zip deleted file mode 100644 index 65eab1246042..000000000000 Binary files a/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/canvas-design.zip and /dev/null differ diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent-prebuilt.zip b/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent-prebuilt.zip index 99c68e9b0b6b..497bb015a682 100644 Binary files a/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent-prebuilt.zip and b/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent-prebuilt.zip differ diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent.zip b/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent.zip deleted file mode 100644 index 133f1995d33a..000000000000 Binary files a/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent.zip and /dev/null differ diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent/main.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent/main.py index 9a5d0f694e20..5820f00bc4a8 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent/main.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/echo-agent/main.py @@ -1,41 +1,40 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. -# import asyncio -# import logging +import asyncio +import logging -# from azure.ai.agentserver.responses import ( -# CreateResponse, -# ResponseContext, -# ResponsesAgentServerHost, -# TextResponse, -# ) +from azure.ai.agentserver.responses import ( + CreateResponse, + ResponseContext, + ResponsesAgentServerHost, + TextResponse, +) -# # Configure logging -# logging.basicConfig( -# level=logging.INFO, -# format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' -# ) -# logger = logging.getLogger(__name__) +# Configure logging +logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s") +logger = logging.getLogger(__name__) -# app = ResponsesAgentServerHost() +app = ResponsesAgentServerHost() -# @app.create_handler -# async def handler(request: CreateResponse, context: ResponseContext, cancellation_signal: asyncio.Event): -# """Echo the user's input back as a single message.""" -# input_text = await context.get_input_text() -# logger.info(f"Received input: {input_text}") +@app.response_handler +async def handler( + request: CreateResponse, context: ResponseContext, cancellation_signal: asyncio.Event +) -> TextResponse: + """Echo the user's input back as a single message.""" + input_text = await context.get_input_text() + logger.info(f"Received input: {input_text}") -# output_text = f"Echo: {input_text}" -# logger.info(f"Sending output: {output_text}") + output_text = f"Echo: {input_text}" + logger.info(f"Sending output: {output_text}") -# return TextResponse(context, request, text=output_text) + return TextResponse(context, request, text=output_text) -# def main() -> None: -# app.run() +def main() -> None: + app.run() -# if __name__ == "__main__": -# main() +if __name__ == "__main__": + main() diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/toolbox-agent/main.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/toolbox-agent/main.py new file mode 100644 index 000000000000..3a1829d1fd21 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/toolbox-agent/main.py @@ -0,0 +1,80 @@ +# Copyright (c) Microsoft. All rights reserved. + +import asyncio +import os +from collections.abc import Callable, Generator + +import httpx +from typing import Any, cast +from agent_framework import Agent, SkillsProvider +from agent_framework.foundry import FoundryChatClient +from agent_framework_foundry_hosting import ResponsesHostServer # type: ignore[import-untyped] +from azure.identity import DefaultAzureCredential, get_bearer_token_provider +from dotenv import load_dotenv +from mcp.client.session import ClientSession +from mcp.client.streamable_http import streamable_http_client + +MCPSkillsSource = cast(Any, __import__("agent_framework", fromlist=["MCPSkillsSource"]).MCPSkillsSource) + +load_dotenv() + + +class ToolboxAuth(httpx.Auth): + """Attach a fresh Foundry bearer token to every request.""" + + requires_response_body = True + + def __init__(self, token_provider: Callable[[], str]) -> None: + self._token_provider = token_provider + + def auth_flow(self, request: httpx.Request) -> Generator[httpx.Request, httpx.Response, None]: + request.headers["Authorization"] = f"Bearer {self._token_provider()}" + yield request + + +async def main() -> None: + project_endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] + deployment = os.environ["FOUNDRY_MODEL_NAME"] + toolbox_mcp_url = os.environ["MCP_SERVER_URL"] + store_responses = os.environ.get("AGENT_STORE_RESPONSES", "false").lower() == "true" + + credential = DefaultAzureCredential() + token_provider = get_bearer_token_provider(credential, "https://ai.azure.com/.default") + + async with ( + httpx.AsyncClient( + auth=ToolboxAuth(token_provider), + headers={"Foundry-Features": "Routines=V1Preview"}, + timeout=httpx.Timeout(30.0, read=300.0), + follow_redirects=True, + ) as http_client, + streamable_http_client( + url=toolbox_mcp_url, + http_client=http_client, + ) as (read, write, _), + ClientSession(read, write) as session, + ): + await session.initialize() + + skills_provider = SkillsProvider(MCPSkillsSource(client=session)) + + agent = Agent( + client=FoundryChatClient( + project_endpoint=project_endpoint, + model=deployment, + credential=credential, + ), + name=os.environ.get("AGENT_NAME", "TOOLBOX_AGENT"), + instructions=os.environ.get( + "AGENT_INSTRUCTIONS", + ), + context_providers=[skills_provider], + default_options={"store": store_responses}, + ) + + server = ResponsesHostServer(agent) + await server.run_async() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/toolbox-agent/requirements.txt b/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/toolbox-agent/requirements.txt new file mode 100644 index 000000000000..6cf68528e791 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/assets/toolbox-agent/requirements.txt @@ -0,0 +1,10 @@ +agent-framework-foundry==1.8.2 +agent-framework-foundry-hosting==1.0.0a260618 +azure-ai-agentserver-core +azure-ai-agentserver-invocations +azure-ai-agentserver-responses +azure-ai-projects +azure-identity +httpx +mcp +python-dotenv diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/hosted_agents_util.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/hosted_agents_util.py index ede784f3db33..4ff8bd7952f4 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/hosted_agents_util.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/hosted_agents_util.py @@ -1,9 +1,16 @@ import asyncio import hashlib +import sys import time from pathlib import Path from typing import Tuple +_SAMPLES_DIR = Path(__file__).resolve().parents[1] +if str(_SAMPLES_DIR) not in sys.path: + sys.path.insert(0, str(_SAMPLES_DIR)) + +from util import zip as zip_directory + from azure.ai.projects import AIProjectClient from azure.ai.projects.aio import AIProjectClient as AsyncAIProjectClient from azure.ai.projects.models import ( @@ -19,25 +26,32 @@ def select_echo_agent_code_zip( ) -> Tuple[CodeDependencyResolution, str, bytes, str]: """Pick the dependency-resolution mode and matching echo-agent zip, and load it. - When ``use_remote_build`` is ``True``, returns REMOTE_BUILD with - ``assets/echo-agent.zip``; otherwise BUNDLED with - ``assets/echo-agent-prebuilt.zip``. + When ``use_remote_build`` is ``True``, returns REMOTE_BUILD with a zip + built from ``assets/echo-agent/``; otherwise BUNDLED with + the checked-in ``assets/echo-agent-prebuilt.zip``. - Reads the zip bytes, computes its SHA-256, and prints a one-line summary. + Computes the zip SHA-256 and prints a one-line summary. Returns ``(dependency_resolution, zip_filename, zip_bytes, zip_sha256)``. """ dependency_resolution = ( CodeDependencyResolution.REMOTE_BUILD if use_remote_build else CodeDependencyResolution.BUNDLED ) - zip_filename = "echo-agent.zip" if use_remote_build else "echo-agent-prebuilt.zip" - zip_path = _ASSETS_DIR / zip_filename - zip_bytes = zip_path.read_bytes() - zip_sha256 = hashlib.sha256(zip_bytes).hexdigest() - print( - f"Loaded code zip from {zip_path} (dependency_resolution={dependency_resolution.value}): " - f"{len(zip_bytes)} bytes, sha256={zip_sha256}" - ) + + if use_remote_build: + zip_filename = "echo-agent.zip" + zip_bytes, zip_sha256, zip_path = zip_directory(_ASSETS_DIR / "echo-agent", zip_filename) + zip_filename = zip_path.name + else: + zip_filename = "echo-agent-prebuilt.zip" + zip_path = _ASSETS_DIR / zip_filename + zip_bytes = zip_path.read_bytes() + zip_sha256 = hashlib.sha256(zip_bytes).hexdigest() + print( + f"Loaded code zip from {zip_path} (dependency_resolution={dependency_resolution.value}): " + f"{len(zip_bytes)} bytes, sha256={zip_sha256}" + ) + return dependency_resolution, zip_filename, zip_bytes, zip_sha256 diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/rbac_util.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/rbac_util.py index 3d87562790f2..61570cdd9f93 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/rbac_util.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/rbac_util.py @@ -1,3 +1,4 @@ +import os import uuid from typing import Any, cast from urllib.parse import urlparse @@ -5,10 +6,6 @@ from azure.core.credentials import TokenCredential from azure.core.credentials_async import AsyncTokenCredential from azure.core.exceptions import ResourceNotFoundError -from azure.mgmt.authorization import AuthorizationManagementClient, models as authorization_models -from azure.mgmt.authorization.aio import AuthorizationManagementClient as AsyncAuthorizationManagementClient -from azure.mgmt.resource.resources import ResourceManagementClient -from azure.mgmt.resource.resources.aio import ResourceManagementClient as AsyncResourceManagementClient from azure.ai.projects.models import AgentVersionDetails AZURE_AI_USER_ROLE_DEFINITION_GUID = "53ca6127-db72-4b80-b1b0-d745d6d5456d" @@ -28,6 +25,8 @@ def _resolve_ai_account_resource_id( project_name: str, subscription_id: str, ) -> str: + from azure.mgmt.resource.resources import ResourceManagementClient + resource_client = ResourceManagementClient(credential, subscription_id) project_resources = resource_client.resources.list( filter="resourceType eq 'Microsoft.CognitiveServices/accounts/projects'" @@ -59,6 +58,8 @@ def _resolve_ai_account_resource_id( def _ensure_agent_identity_rbac_with_role_id( credential: TokenCredential, principal_id: str, scope_resource_id: str, subscription_id: str, role_id: str ) -> tuple[bool, str]: + from azure.mgmt.authorization import AuthorizationManagementClient, models as authorization_models + authorization_client = AuthorizationManagementClient(credential, subscription_id) role_definition_id = f"/subscriptions/{subscription_id}/providers/Microsoft.Authorization/roleDefinitions/{role_id}" role_assignment_name = str( @@ -117,6 +118,9 @@ def ensure_agent_identity_rbac( :raises ~azure.core.exceptions.HttpResponseError: If role assignment creation fails for reasons other than an existing assignment. """ + if os.environ.get("SKIP_RBAC"): + print("Skipping RBAC setup.") + return if not agent.instance_identity or not agent.instance_identity.principal_id: raise RuntimeError("Agent instance_identity or principal_id is not available.") principal_id = agent.instance_identity.principal_id @@ -140,6 +144,8 @@ async def _resolve_ai_account_resource_id_async( project_name: str, subscription_id: str, ) -> str: + from azure.mgmt.resource.resources.aio import ResourceManagementClient as AsyncResourceManagementClient + async with AsyncResourceManagementClient(credential, subscription_id) as resource_client: project_id_segment = f"/accounts/{account_name}/projects/{project_name}".lower() matching_projects = [] @@ -178,6 +184,9 @@ async def _ensure_agent_identity_rbac_with_role_id_async( subscription_id: str, role_id: str, ) -> tuple[bool, str]: + from azure.mgmt.authorization import models as authorization_models + from azure.mgmt.authorization.aio import AuthorizationManagementClient as AsyncAuthorizationManagementClient + async with AsyncAuthorizationManagementClient(credential, subscription_id) as authorization_client: role_definition_id = ( f"/subscriptions/{subscription_id}/providers/Microsoft.Authorization/roleDefinitions/{role_id}" @@ -233,6 +242,9 @@ async def ensure_agent_identity_rbac_async( :raises ~azure.core.exceptions.HttpResponseError: If role assignment creation fails for reasons other than an existing assignment. """ + if os.environ.get("SKIP_RBAC"): + print("Skipping RBAC setup.") + return if not agent.instance_identity or not agent.instance_identity.principal_id: raise RuntimeError("Agent instance_identity or principal_id is not available.") principal_id = agent.instance_identity.principal_id diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_agent_endpoint.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_agent_endpoint.py index 82be3e7df1ce..4180322ed289 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_agent_endpoint.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_agent_endpoint.py @@ -13,16 +13,12 @@ Sessions only work with Hosted Agents. - Session and Agent endpoint operations are currently preview features. - In the Python SDK, you access these operations via - `project_client.beta.agents`. - USAGE: python sample_agent_endpoint.py Before running the sample: - pip install "azure-ai-projects>=2.1.0" python-dotenv + pip install "azure-ai-projects>=2.3.0" python-dotenv Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -42,8 +38,9 @@ from azure.ai.projects import AIProjectClient from azure.ai.projects.models import ( AgentEndpointConfig, - AgentEndpointProtocol, FixedRatioVersionSelectionRule, + ProtocolConfiguration, + ResponsesProtocolConfiguration, VersionSelector, ) from azure.ai.projects.models import VersionRefIndicator @@ -59,13 +56,12 @@ AIProjectClient( endpoint=endpoint, credential=credential, - allow_preview=True, ) as project_client, ): agent = get_latest_active_agent_version(project_client, agent_name) - session = project_client.beta.agents.create_session( + session = project_client.agents.create_session( agent_name=agent_name, version_indicator=VersionRefIndicator(agent_version=agent.version), ) @@ -79,10 +75,10 @@ FixedRatioVersionSelectionRule(agent_version=agent.version, traffic_percentage=100), ] ), - protocols=[AgentEndpointProtocol.RESPONSES], + protocol_configuration=ProtocolConfiguration(responses=ResponsesProtocolConfiguration()), ) - patched_agent = project_client.beta.agents.patch_agent_details( + patched_agent = project_client.agents.update_details( agent_name=agent_name, agent_endpoint=endpoint_config, ) @@ -100,7 +96,7 @@ ) print(f"Response output: {response.output_text}") finally: - project_client.beta.agents.delete_session( + project_client.agents.delete_session( agent_name=agent_name, session_id=session.agent_session_id, ) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_agent_endpoint_async.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_agent_endpoint_async.py index 94649b7ad73a..b9b227197d9d 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_agent_endpoint_async.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_agent_endpoint_async.py @@ -13,16 +13,12 @@ Sessions only work with Hosted Agents. - Session and Agent endpoint operations are currently preview features. - In the Python SDK, you access these operations via - `project_client.beta.agents`. - USAGE: python sample_agent_endpoint_async.py Before running the sample: - pip install "azure-ai-projects>=2.1.0" python-dotenv aiohttp + pip install "azure-ai-projects>=2.3.0" python-dotenv aiohttp Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -43,8 +39,9 @@ from azure.ai.projects.aio import AIProjectClient from azure.ai.projects.models import ( AgentEndpointConfig, - AgentEndpointProtocol, FixedRatioVersionSelectionRule, + ProtocolConfiguration, + ResponsesProtocolConfiguration, VersionSelector, ) from azure.ai.projects.models import VersionRefIndicator @@ -62,13 +59,12 @@ async def main(): AIProjectClient( endpoint=endpoint, credential=credential, - allow_preview=True, ) as project_client, ): agent = await get_latest_active_agent_version_async(project_client, agent_name) - session = await project_client.beta.agents.create_session( + session = await project_client.agents.create_session( agent_name=agent_name, version_indicator=VersionRefIndicator(agent_version=agent.version), ) @@ -82,10 +78,10 @@ async def main(): FixedRatioVersionSelectionRule(agent_version=agent.version, traffic_percentage=100), ] ), - protocols=[AgentEndpointProtocol.RESPONSES], + protocol_configuration=ProtocolConfiguration(responses=ResponsesProtocolConfiguration()), ) - patched_agent = await project_client.beta.agents.patch_agent_details( + patched_agent = await project_client.agents.update_details( agent_name=agent_name, agent_endpoint=endpoint_config, ) @@ -103,7 +99,7 @@ async def main(): ) print(f"Response output: {response.output_text}") finally: - await project_client.beta.agents.delete_session( + await project_client.agents.delete_session( agent_name=agent_name, session_id=session.agent_session_id, ) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent.py index 6498ad618799..e22ec9036b4e 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent.py @@ -7,7 +7,8 @@ """ DESCRIPTION: This sample demonstrates CRUD operations for Hosted Agent versions - using the synchronous AIProjectClient. + using the synchronous AIProjectClient. It also invokes the hosted + agent via `responses.create`. This is the only hosted_agents sample that sets up agent identity RBAC via `ensure_agent_identity_rbac`. @@ -84,3 +85,11 @@ fetched = project_client.agents.get_version(agent_name=agent_name, agent_version=created.version) print(f"Fetched hosted agent version: {fetched.version}, status: {fetched.status}") + + user_input = "Good morning!" + with project_client.get_openai_client(agent_name=agent_name) as openai_client: + response = openai_client.responses.create( + input=user_input, + ) + print(f"Sent: {user_input}") + print(f"Response output: {response.output_text}") diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_async.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_async.py index ff92d553a2cd..2fb2faf3493a 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_async.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_async.py @@ -8,6 +8,7 @@ DESCRIPTION: Async variant of `sample_create_hosted_agent.py`. Demonstrates CRUD operations for Hosted Agent versions using the asynchronous AIProjectClient. + It also invokes the hosted agent via `responses.create`. This is the only hosted_agents async sample that sets up agent identity RBAC via `ensure_agent_identity_rbac_async`. @@ -87,6 +88,14 @@ async def main() -> None: fetched = await project_client.agents.get_version(agent_name=agent_name, agent_version=created.version) print(f"Fetched hosted agent version: {fetched.version}, status: {fetched.status}") + user_input = "Good morning!" + async with project_client.get_openai_client(agent_name=agent_name) as openai_client: + response = await openai_client.responses.create( + input=user_input, + ) + print(f"Sent: {user_input}") + print(f"Response output: {response.output_text}") + if __name__ == "__main__": asyncio.run(main()) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_from_code.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_from_code.py index cdd4a3396125..a1bed07219ff 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_from_code.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_from_code.py @@ -10,14 +10,14 @@ poll for provisioning, and download it back to verify the round-trip. The dependency resolution mode is selected via the - `FOUNDRY_HOSTED_AGENT_REMOTE_BUILD` environment variable (default: `false`): + `FOUNDRY_HOSTED_AGENT_REMOTE_BUILD` environment variable (default: `true`): * `false` (BUNDLED) — uploads `assets/echo-agent-prebuilt.zip`, which bundles the agent source plus a `packages/` folder with Linux-built dependencies, so the service skips pip entirely. - * `true` (REMOTE_BUILD) — uploads `assets/echo-agent.zip`, which contains - only the agent source plus `requirements.txt`; the service resolves - dependencies remotely from the public package index. + * `true` (REMOTE_BUILD) — zips and uploads `assets/echo-agent/`, which + contains only the agent source plus `requirements.txt`; the service + resolves dependencies remotely from the public package index. The agent must already exist; create it with `samples/hosted_agents/sample_create_hosted_agent.py`. @@ -35,19 +35,15 @@ 2) FOUNDRY_HOSTED_AGENT_NAME - The Hosted Agent name. Must already exist. 3) AZURE_SUBSCRIPTION_ID - Azure subscription ID where the Azure AI account and project are deployed. - 4) FOUNDRY_HOSTED_AGENT_REMOTE_BUILD - Optional. Set to `true` to use - REMOTE_BUILD; defaults to `false` (BUNDLED). + 4) FOUNDRY_HOSTED_AGENT_REMOTE_BUILD - Optional. Set to `false` to use + BUNDLED; defaults to `true` (REMOTE_BUILD). """ -import hashlib import os import tempfile from pathlib import Path - from dotenv import load_dotenv - from azure.identity import DefaultAzureCredential - from azure.ai.projects import AIProjectClient from azure.ai.projects.models import ( CodeConfiguration, @@ -65,14 +61,30 @@ endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] agent_name = os.environ["FOUNDRY_HOSTED_AGENT_NAME"] subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"] -use_remote_build = os.environ.get("FOUNDRY_HOSTED_AGENT_REMOTE_BUILD", "false").strip().lower() == "true" +use_remote_build = os.environ.get("FOUNDRY_HOSTED_AGENT_REMOTE_BUILD", "true").strip().lower() == "true" dependency_resolution, zip_filename, code_zip_bytes, code_zip_sha256 = select_echo_agent_code_zip(use_remote_build) with ( DefaultAzureCredential() as credential, - AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client, + AIProjectClient(endpoint=endpoint, credential=credential) as project_client, ): + # The ``code`` field accepts any variant of the SDK's ``FileType`` union. + # The 3-tuple form used here pins both the filename and the content type. + # + # # 1) bare IO[bytes] - filename derived from the file handle's `.name` + # code=code_zip_path.open("rb") + # + # # 2) (filename, bytes) + # code=(zip_filename, code_zip_bytes) + # + # # 3) (filename, IO[bytes]) + # code=(zip_filename, code_zip_path.open("rb")) + # + # # 4) (filename, bytes, content_type) + # code=(zip_filename, code_zip_bytes, "application/zip") + code = (zip_filename, code_zip_bytes, "application/zip") + content = CreateAgentVersionFromCodeContent( metadata=CreateAgentVersionFromCodeMetadata( description=f"Code-based hosted agent uploaded with dependency_resolution={dependency_resolution.value}.", @@ -80,17 +92,17 @@ cpu="0.5", memory="1Gi", code_configuration=CodeConfiguration( - runtime="python_3_12", + runtime="python_3_14", entry_point=["python", "main.py"], dependency_resolution=dependency_resolution, ), protocol_versions=[ProtocolVersionRecord(protocol="responses", version="1.0.0")], ), ), - code=(zip_filename, code_zip_bytes, "application/zip"), + code=code, ) - created = project_client.beta.agents.create_version_from_code( + created = project_client.agents.create_version_from_code( agent_name=agent_name, content=content, code_zip_sha256=code_zip_sha256, @@ -112,15 +124,14 @@ # Download the zip for the version we just created, streaming to a temp file. version_zip_path = Path(tempfile.gettempdir()) / f"{agent_name}-{created.version}.zip" - sha = hashlib.sha256() - with open(version_zip_path, "wb") as f: - for chunk in project_client.beta.agents.download_code( - agent_name=agent_name, - agent_version=created.version, - ): - f.write(chunk) - sha.update(chunk) - downloaded_version_sha256 = sha.hexdigest() + + downloaded_version_sha256 = project_client.agents.download_code_to_path( + agent_name=agent_name, + agent_version=created.version, + file_path=version_zip_path, + overwrite=True, + ) + print( f"Downloaded version code zip to {version_zip_path}: {version_zip_path.stat().st_size} bytes, " f"sha256={downloaded_version_sha256} (matches uploaded: {downloaded_version_sha256 == code_zip_sha256})" diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_from_code_async.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_from_code_async.py index cd05ad4b472e..d70ac2b3935a 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_from_code_async.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_create_hosted_agent_from_code_async.py @@ -11,14 +11,14 @@ and downloads it back to verify the round-trip. The dependency resolution mode is selected via the - `FOUNDRY_HOSTED_AGENT_REMOTE_BUILD` environment variable (default: `false`): + `FOUNDRY_HOSTED_AGENT_REMOTE_BUILD` environment variable (default: `true`): * `false` (BUNDLED) — uploads `assets/echo-agent-prebuilt.zip`, which bundles the agent source plus a `packages/` folder with Linux-built dependencies, so the service skips pip entirely. - * `true` (REMOTE_BUILD) — uploads `assets/echo-agent.zip`, which contains - only the agent source plus `requirements.txt`; the service resolves - dependencies remotely from the public package index. + * `true` (REMOTE_BUILD) — zips and uploads `assets/echo-agent/`, which + contains only the agent source plus `requirements.txt`; the service + resolves dependencies remotely from the public package index. The agent must already exist; create it with `samples/hosted_agents/sample_create_hosted_agent_async.py`. @@ -36,20 +36,16 @@ 2) FOUNDRY_HOSTED_AGENT_NAME - The Hosted Agent name. Must already exist. 3) AZURE_SUBSCRIPTION_ID - Azure subscription ID where the Azure AI account and project are deployed. - 4) FOUNDRY_HOSTED_AGENT_REMOTE_BUILD - Optional. Set to `true` to use - REMOTE_BUILD; defaults to `false` (BUNDLED). + 4) FOUNDRY_HOSTED_AGENT_REMOTE_BUILD - Optional. Set to `false` to use + BUNDLED; defaults to `true` (REMOTE_BUILD). """ import asyncio -import hashlib import os import tempfile from pathlib import Path - from dotenv import load_dotenv - from azure.identity.aio import DefaultAzureCredential - from azure.ai.projects.aio import AIProjectClient from azure.ai.projects.models import ( CodeConfiguration, @@ -69,14 +65,30 @@ async def main() -> None: endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] agent_name = os.environ["FOUNDRY_HOSTED_AGENT_NAME"] subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"] - use_remote_build = os.environ.get("FOUNDRY_HOSTED_AGENT_REMOTE_BUILD", "false").strip().lower() == "true" + use_remote_build = os.environ.get("FOUNDRY_HOSTED_AGENT_REMOTE_BUILD", "true").strip().lower() == "true" dependency_resolution, zip_filename, code_zip_bytes, code_zip_sha256 = select_echo_agent_code_zip(use_remote_build) async with ( DefaultAzureCredential() as credential, - AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client, + AIProjectClient(endpoint=endpoint, credential=credential) as project_client, ): + # The ``code`` field accepts any variant of the SDK's ``FileType`` union. + # The 3-tuple form used here pins both the filename and the content type. + # + # # 1) bare IO[bytes] - filename derived from the file handle's `.name` + # code=code_zip_path.open("rb") + # + # # 2) (filename, bytes) + # code=(zip_filename, code_zip_bytes) + # + # # 3) (filename, IO[bytes]) + # code=(zip_filename, code_zip_path.open("rb")) + # + # # 4) (filename, bytes, content_type) + # code=(zip_filename, code_zip_bytes, "application/zip") + code = (zip_filename, code_zip_bytes, "application/zip") + content = CreateAgentVersionFromCodeContent( metadata=CreateAgentVersionFromCodeMetadata( description=f"Code-based hosted agent uploaded with dependency_resolution={dependency_resolution.value}.", @@ -84,17 +96,17 @@ async def main() -> None: cpu="0.5", memory="1Gi", code_configuration=CodeConfiguration( - runtime="python_3_12", + runtime="python_3_14", entry_point=["python", "main.py"], dependency_resolution=dependency_resolution, ), protocol_versions=[ProtocolVersionRecord(protocol="responses", version="1.0.0")], ), ), - code=(zip_filename, code_zip_bytes, "application/zip"), + code=code, ) - created = await project_client.beta.agents.create_version_from_code( + created = await project_client.agents.create_version_from_code( agent_name=agent_name, content=content, code_zip_sha256=code_zip_sha256, @@ -118,16 +130,14 @@ async def main() -> None: # Download the zip for the version we just created, streaming to a temp file. version_zip_path = Path(tempfile.gettempdir()) / f"{agent_name}-{created.version}.zip" - sha = hashlib.sha256() - version_stream = await project_client.beta.agents.download_code( + + downloaded_version_sha256 = await project_client.agents.download_code_to_path( agent_name=agent_name, agent_version=created.version, + file_path=version_zip_path, + overwrite=True, ) - with open(version_zip_path, "wb") as f: - async for chunk in version_stream: - f.write(chunk) - sha.update(chunk) - downloaded_version_sha256 = sha.hexdigest() + print( f"Downloaded version code zip to {version_zip_path}: {version_zip_path.stat().st_size} bytes, " f"sha256={downloaded_version_sha256} (matches uploaded: {downloaded_version_sha256 == code_zip_sha256})" diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_session_log_stream.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_session_log_stream.py index 8957839ec8f9..45d1726e65a4 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_session_log_stream.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_session_log_stream.py @@ -7,21 +7,17 @@ """ DESCRIPTION: This sample demonstrates how to stream hosted agent session logs - using `project_client.beta.agents.get_session_log_stream` with the + using `project_client.agents.get_session_log_stream` with the synchronous AIProjectClient. Sessions only work with Hosted Agents. - Session and log stream operations are currently preview features. - In the Python SDK, you access these operations via - `project_client.beta.agents`. - USAGE: python sample_session_log_stream.py Before running the sample: - pip install "azure-ai-projects>=2.1.0" python-dotenv + pip install "azure-ai-projects>=2.3.0" python-dotenv Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -37,16 +33,14 @@ """ import os - from dotenv import load_dotenv - from azure.identity import DefaultAzureCredential - from azure.ai.projects import AIProjectClient from azure.ai.projects.models import ( AgentEndpointConfig, - AgentEndpointProtocol, FixedRatioVersionSelectionRule, + ProtocolConfiguration, + ResponsesProtocolConfiguration, VersionSelector, ) from azure.ai.projects.models import VersionRefIndicator @@ -92,12 +86,11 @@ def _iter_sse_frames(stream, max_log_events: int): AIProjectClient( endpoint=endpoint, credential=credential, - allow_preview=True, ) as project_client, project_client.get_openai_client(agent_name=agent_name) as openai_client, ): agent = get_latest_active_agent_version(project_client, agent_name) - session = project_client.beta.agents.create_session( + session = project_client.agents.create_session( agent_name=agent_name, version_indicator=VersionRefIndicator(agent_version=agent.version), ) @@ -109,10 +102,10 @@ def _iter_sse_frames(stream, max_log_events: int): FixedRatioVersionSelectionRule(agent_version=agent.version, traffic_percentage=100), ] ), - protocols=[AgentEndpointProtocol.RESPONSES], + protocol_configuration=ProtocolConfiguration(responses=ResponsesProtocolConfiguration()), ) - project_client.beta.agents.patch_agent_details( + project_client.agents.update_details( agent_name=agent_name, agent_endpoint=endpoint_config, ) @@ -129,7 +122,7 @@ def _iter_sse_frames(stream, max_log_events: int): print(f"Response output: {response.output_text}") print("Streaming session logs...") - raw_stream = project_client.beta.agents.get_session_log_stream( + raw_stream = project_client.agents.get_session_log_stream( agent_name=agent_name, agent_version=agent.version, session_id=session.agent_session_id, @@ -138,7 +131,7 @@ def _iter_sse_frames(stream, max_log_events: int): print(f"SSE event: {frame.get('event')}") print(f"SSE data: {frame.get('data')}\n") finally: - project_client.beta.agents.delete_session( + project_client.agents.delete_session( agent_name=agent_name, session_id=session.agent_session_id, ) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_session_log_stream_async.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_session_log_stream_async.py index 3c2fe3bfa3d9..e8ae915d80fb 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_session_log_stream_async.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_session_log_stream_async.py @@ -7,21 +7,17 @@ """ DESCRIPTION: This sample demonstrates how to stream hosted agent session logs - using `project_client.beta.agents.get_session_log_stream` with the + using `project_client.agents.get_session_log_stream` with the asynchronous AIProjectClient. Sessions only work with Hosted Agents. - Session and log stream operations are currently preview features. - In the Python SDK, you access these operations via - `project_client.beta.agents`. - USAGE: python sample_session_log_stream_async.py Before running the sample: - pip install "azure-ai-projects>=2.1.0" python-dotenv aiohttp + pip install "azure-ai-projects>=2.3.0" python-dotenv aiohttp Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -38,16 +34,14 @@ import asyncio import os - from dotenv import load_dotenv - from azure.identity.aio import DefaultAzureCredential - from azure.ai.projects.aio import AIProjectClient from azure.ai.projects.models import ( AgentEndpointConfig, - AgentEndpointProtocol, FixedRatioVersionSelectionRule, + ProtocolConfiguration, + ResponsesProtocolConfiguration, VersionSelector, ) from azure.ai.projects.models import VersionRefIndicator @@ -123,11 +117,10 @@ async def main(): AIProjectClient( endpoint=endpoint, credential=credential, - allow_preview=True, ) as project_client, ): agent = await get_latest_active_agent_version_async(project_client, agent_name) - session = await project_client.beta.agents.create_session( + session = await project_client.agents.create_session( agent_name=agent_name, version_indicator=VersionRefIndicator(agent_version=agent.version), ) @@ -139,10 +132,10 @@ async def main(): FixedRatioVersionSelectionRule(agent_version=agent.version, traffic_percentage=100), ] ), - protocols=[AgentEndpointProtocol.RESPONSES], + protocol_configuration=ProtocolConfiguration(responses=ResponsesProtocolConfiguration()), ) - await project_client.beta.agents.patch_agent_details( + await project_client.agents.update_details( agent_name=agent_name, agent_endpoint=endpoint_config, ) @@ -160,7 +153,7 @@ async def main(): print(f"Response output: {response.output_text}") print("Streaming session logs...") - raw_stream = await project_client.beta.agents.get_session_log_stream( + raw_stream = await project_client.agents.get_session_log_stream( agent_name=agent_name, agent_version=agent.version, session_id=session.agent_session_id, @@ -169,7 +162,7 @@ async def main(): print(f"SSE event: {frame.get('event')}") print(f"SSE data: {frame.get('data')}\n") finally: - await project_client.beta.agents.delete_session( + await project_client.agents.delete_session( agent_name=agent_name, session_id=session.agent_session_id, ) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_crud.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_crud.py index 5ef49160a3fb..f1a7ccbb547a 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_crud.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_crud.py @@ -11,15 +11,12 @@ Sessions only work with Hosted Agents. - Sessions are currently a preview feature. In the Python SDK, you access - these operations via `project_client.beta.agents`. - USAGE: python sample_sessions_crud.py Before running the sample: - pip install "azure-ai-projects>=2.1.0" python-dotenv + pip install "azure-ai-projects>=2.3.0" python-dotenv Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -31,10 +28,10 @@ SDK FUNCTIONS: - project_client.agents.list_versions: resolves the active version for the existing hosted agent. - - project_client.beta.agents.create_session: creates a session for the agent. - - project_client.beta.agents.get_session: retrieves a session by ID. - - project_client.beta.agents.list_sessions: lists sessions for an agent. - - project_client.beta.agents.delete_session: deletes a session by ID. + - project_client.agents.create_session: creates a session for the agent. + - project_client.agents.get_session: retrieves a session by ID. + - project_client.agents.list_sessions: lists sessions for an agent. + - project_client.agents.delete_session: deletes a session by ID. """ import os @@ -57,18 +54,17 @@ AIProjectClient( endpoint=endpoint, credential=credential, - allow_preview=True, ) as project_client, ): agent = get_latest_active_agent_version(project_client, agent_name) - session = project_client.beta.agents.create_session( + session = project_client.agents.create_session( agent_name=agent_name, version_indicator=VersionRefIndicator(agent_version=agent.version), ) print(f"Created session (id: {session.agent_session_id}, status: {session.status})") # Retrieve the session by its ID - fetched = project_client.beta.agents.get_session( + fetched = project_client.agents.get_session( agent_name=agent_name, session_id=session.agent_session_id, ) @@ -76,12 +72,12 @@ # List sessions for the agent print("Listing sessions for the agent...") - sessions = project_client.beta.agents.list_sessions(agent_name=agent_name) + sessions = project_client.agents.list_sessions(agent_name=agent_name) print("Sessions:") for item in sessions: print(f" - {item.agent_session_id} (status: {item.status})") - project_client.beta.agents.delete_session( + project_client.agents.delete_session( agent_name=agent_name, session_id=session.agent_session_id, ) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_crud_async.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_crud_async.py index 82362b933488..d9b70765e184 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_crud_async.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_crud_async.py @@ -11,15 +11,12 @@ Sessions only work with Hosted Agents. - Sessions are currently a preview feature. In the Python SDK, you access - these operations via `project_client.beta.agents`. - USAGE: python sample_sessions_crud_async.py Before running the sample: - pip install "azure-ai-projects>=2.1.0" python-dotenv aiohttp + pip install "azure-ai-projects>=2.3.0" python-dotenv aiohttp Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -31,10 +28,10 @@ SDK FUNCTIONS: - project_client.agents.list_versions: resolves the active version for the existing hosted agent. - - project_client.beta.agents.create_session: creates a session for the agent. - - project_client.beta.agents.get_session: retrieves a session by ID. - - project_client.beta.agents.list_sessions: lists sessions for an agent. - - project_client.beta.agents.delete_session: deletes a session by ID. + - project_client.agents.create_session: creates a session for the agent. + - project_client.agents.get_session: retrieves a session by ID. + - project_client.agents.list_sessions: lists sessions for an agent. + - project_client.agents.delete_session: deletes a session by ID. """ import asyncio @@ -60,18 +57,17 @@ async def main(): AIProjectClient( endpoint=endpoint, credential=credential, - allow_preview=True, ) as project_client, ): agent = await get_latest_active_agent_version_async(project_client, agent_name) - session = await project_client.beta.agents.create_session( + session = await project_client.agents.create_session( agent_name=agent_name, version_indicator=VersionRefIndicator(agent_version=agent.version), ) print(f"Created session (id: {session.agent_session_id}, status: {session.status})") # Retrieve the session by its ID - fetched = await project_client.beta.agents.get_session( + fetched = await project_client.agents.get_session( agent_name=agent_name, session_id=session.agent_session_id, ) @@ -79,12 +75,12 @@ async def main(): # List sessions for the agent print("Listing sessions for the agent...") - sessions = project_client.beta.agents.list_sessions(agent_name=agent_name) + sessions = project_client.agents.list_sessions(agent_name=agent_name) print("Sessions:") async for item in sessions: print(f" - {item.agent_session_id} (status: {item.status})") - await project_client.beta.agents.delete_session( + await project_client.agents.delete_session( agent_name=agent_name, session_id=session.agent_session_id, ) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_files_upload_download.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_files_upload_download.py index 848c91609e38..d4ed7e998b48 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_files_upload_download.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_files_upload_download.py @@ -11,15 +11,12 @@ Sessions only work with Hosted Agents. - Sessions are currently a preview feature. In the Python SDK, you access - these operations via `project_client.beta.agents`. - USAGE: python sample_sessions_files_upload_download.py Before running the sample: - pip install "azure-ai-projects>=2.1.0" python-dotenv + pip install "azure-ai-projects>=2.3.0" python-dotenv Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -59,67 +56,66 @@ AIProjectClient( endpoint=endpoint, credential=credential, - allow_preview=True, ) as project_client, ): agent = get_latest_active_agent_version(project_client, agent_name) - session = project_client.beta.agents.create_session( + session = project_client.agents.create_session( agent_name=agent_name, version_indicator=VersionRefIndicator(agent_version=agent.version), ) print(f"Session created (id: {session.agent_session_id}, status: {session.status})") try: - # Upload and list session files - project_client.beta.agents.upload_session_file( + print(f"Uploading session file: {data_file1} -> {remote_file_path1}") + project_client.agents.upload_session_file( agent_name=agent_name, session_id=session.agent_session_id, - content_or_file_path=data_file1, - path=remote_file_path1, + file_path=data_file1, + remote_path=remote_file_path1, ) print(f"Uploading session file: {data_file2} -> {remote_file_path2}") - project_client.beta.agents.upload_session_file( + project_client.agents.upload_session_file( agent_name=agent_name, session_id=session.agent_session_id, - content_or_file_path=data_file2, - path=remote_file_path2, + file_path=data_file2, + remote_path=remote_file_path2, ) print("Listing session files for the session at path '.'...") - files = project_client.beta.agents.list_session_files( + files = project_client.agents.list_session_files( agent_name=agent_name, agent_session_id=session.agent_session_id, - path="/remote", + remote_path="/remote", ) for entry in files: print(f" - name={entry.name}, size={entry.size}, is_directory={entry.is_directory}") print(f"Downloading and printing content from '{remote_file_path1}'") content_bytes = b"".join( - project_client.beta.agents.download_session_file( + project_client.agents.download_session_file_as_bytes( agent_name=agent_name, agent_session_id=session.agent_session_id, - path=remote_file_path1, + remote_path=remote_file_path1, ) ) file_content = content_bytes.decode("utf-8", errors="replace") print(f"Session file content ({remote_file_path1}):\n{file_content}") print(f"Deleting session file at path: {remote_file_path1}...") - project_client.beta.agents.delete_session_file( + project_client.agents.delete_session_file( agent_name=agent_name, agent_session_id=session.agent_session_id, - path=remote_file_path1, + remote_path=remote_file_path1, ) print(f"Deleting session file at path: {remote_file_path2}...") - project_client.beta.agents.delete_session_file( + project_client.agents.delete_session_file( agent_name=agent_name, agent_session_id=session.agent_session_id, - path=remote_file_path2, + remote_path=remote_file_path2, ) finally: - project_client.beta.agents.delete_session( + project_client.agents.delete_session( agent_name=agent_name, session_id=session.agent_session_id, ) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_files_upload_download_async.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_files_upload_download_async.py index 4fecd929aa47..9bc61c5273c5 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_files_upload_download_async.py +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_sessions_files_upload_download_async.py @@ -11,15 +11,12 @@ Sessions only work with Hosted Agents. - Sessions are currently a preview feature. In the Python SDK, you access - these operations via `project_client.beta.agents`. - USAGE: python sample_sessions_files_upload_download_async.py Before running the sample: - pip install "azure-ai-projects>=2.1.0" python-dotenv aiohttp + pip install "azure-ai-projects>=2.3.0" python-dotenv aiohttp Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -61,67 +58,66 @@ async def main(): AIProjectClient( endpoint=endpoint, credential=credential, - allow_preview=True, ) as project_client, ): agent = await get_latest_active_agent_version_async(project_client, agent_name) - session = await project_client.beta.agents.create_session( + session = await project_client.agents.create_session( agent_name=agent_name, version_indicator=VersionRefIndicator(agent_version=agent.version), ) print(f"Session created (id: {session.agent_session_id}, status: {session.status})") try: - # Upload and list session files - await project_client.beta.agents.upload_session_file( + print(f"Uploading session file: {data_file1} -> {remote_file_path1}") + await project_client.agents.upload_session_file( agent_name=agent_name, session_id=session.agent_session_id, - content_or_file_path=data_file1, - path=remote_file_path1, + file_path=data_file1, + remote_path=remote_file_path1, ) print(f"Uploading session file: {data_file2} -> {remote_file_path2}") - await project_client.beta.agents.upload_session_file( + await project_client.agents.upload_session_file( agent_name=agent_name, session_id=session.agent_session_id, - content_or_file_path=data_file2, - path=remote_file_path2, + file_path=data_file2, + remote_path=remote_file_path2, ) print("Listing session files for the session at path '.'...") - files = project_client.beta.agents.list_session_files( + files = project_client.agents.list_session_files( agent_name=agent_name, agent_session_id=session.agent_session_id, - path="/remote", + remote_path="/remote", ) async for entry in files: print(f" - name={entry.name}, size={entry.size}, is_directory={entry.is_directory}") print(f"Downloading and printing content from '{remote_file_path1}'") content_bytes = b"" - async for chunk in await project_client.beta.agents.download_session_file( + async for chunk in await project_client.agents.download_session_file_as_bytes( agent_name=agent_name, agent_session_id=session.agent_session_id, - path=remote_file_path1, + remote_path=remote_file_path1, ): content_bytes += chunk file_content = content_bytes.decode("utf-8", errors="replace") print(f"Session file content ({remote_file_path1}):\n{file_content}") print(f"Deleting session file at path: {remote_file_path1}...") - await project_client.beta.agents.delete_session_file( + await project_client.agents.delete_session_file( agent_name=agent_name, agent_session_id=session.agent_session_id, - path=remote_file_path1, + remote_path=remote_file_path1, ) print(f"Deleting session file at path: {remote_file_path2}...") - await project_client.beta.agents.delete_session_file( + await project_client.agents.delete_session_file( agent_name=agent_name, agent_session_id=session.agent_session_id, - path=remote_file_path2, + remote_path=remote_file_path2, ) finally: - await project_client.beta.agents.delete_session( + await project_client.agents.delete_session( agent_name=agent_name, session_id=session.agent_session_id, ) diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_toolbox_with_skill.py b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_toolbox_with_skill.py new file mode 100644 index 000000000000..3062b7bebccd --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_toolbox_with_skill.py @@ -0,0 +1,209 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +DESCRIPTION: + Demonstrates deploying a code-based Hosted Agent that discovers and uses + skills from a Foundry Toolbox MCP endpoint via Agent Framework + ``SkillsProvider(MCPSkillsSource(...))``. + + The sample: + 1. Creates a shipping-cost skill. + 2. Creates a toolbox version that references the skill. + 3. Packages ``assets/toolbox-agent/`` source as a zip at runtime + (REMOTE_BUILD - the service resolves dependencies from requirements.txt). + 4. Deploys a new Hosted Agent version, forwarding the project endpoint, + model name, and toolbox MCP URL to the hosted code. + 5. Waits for the version to become active. + 6. Sends a query to the agent via the Responses API. + 7. Cleans up created resources (agent version, toolbox, and skill). + + The hosted agent must already exist; create it first with: + samples/hosted_agents/sample_create_hosted_agent.py + +USAGE: + python sample_toolbox_with_skill.py + + Before running the sample: + + pip install "azure-ai-projects>=2.3.0" python-dotenv + + Set these environment variables with your own values: + 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the + Overview page of your Microsoft Foundry portal. + 2) FOUNDRY_MODEL_NAME - The deployment name of the AI model, as found under + the "Name" column in the "Models + endpoints" tab in your Foundry project. + 3) FOUNDRY_HOSTED_AGENT_NAME - The Hosted Agent name. Must already exist. + 4) AZURE_SUBSCRIPTION_ID - Azure subscription ID where the Azure AI account + and project are deployed. +""" + +import os +import sys +from pathlib import Path + +_SAMPLES_DIR = Path(__file__).resolve().parents[1] +if str(_SAMPLES_DIR) not in sys.path: + sys.path.insert(0, str(_SAMPLES_DIR)) + +from dotenv import load_dotenv + +from azure.identity import DefaultAzureCredential +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import ( + CodeConfiguration, + CodeDependencyResolution, + CreateAgentVersionFromCodeContent, + CreateAgentVersionFromCodeMetadata, + HostedAgentDefinition, + ProtocolVersionRecord, +) + +from hosted_agents_util import wait_for_agent_version_active +from rbac_util import ensure_agent_identity_rbac +from util import zip + +from azure.core.exceptions import ResourceNotFoundError +from azure.ai.projects.models import ( + SkillInlineContent, + ToolboxSearchPreviewToolboxTool, + ToolboxSkillReference, +) + +load_dotenv() + +endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] +model_name = os.environ["FOUNDRY_MODEL_NAME"] +agent_name = os.environ["FOUNDRY_HOSTED_AGENT_NAME"] +subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"] + +_HOSTED_AGENT_SOURCE_DIR = Path(__file__).parent / "assets" / "toolbox-agent" + +SKILL_NAME = "shipping-cost-skill" +TOOLBOX_NAME = "toolbox_with_skill" + + +def main() -> None: + with ( + DefaultAzureCredential() as credential, + AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client, + project_client.get_openai_client(agent_name=agent_name) as hosted_openai_client, + ): + + try: + project_client.toolboxes.delete(TOOLBOX_NAME) + except ResourceNotFoundError: + pass + + try: + project_client.beta.skills.delete(SKILL_NAME) + except ResourceNotFoundError: + pass + + skill_version = project_client.beta.skills.create( + name=SKILL_NAME, + inline_content=SkillInlineContent( + description="Compute shipping cost for a package given weight and destination.", + instructions=( + "You are a shipping cost calculator. When asked to compute " + "shipping cost, use this formula: cost (USD) = 5 + 2 * weight_kg " + "for domestic destinations, and cost (USD) = 15 + 4 * weight_kg " + "for international destinations. Always state the formula you used." + ), + metadata={"revision": "1"}, + ), + ) + print(f"Created skill: {skill_version.name} version={skill_version.version}") + + toolbox_version = project_client.toolboxes.create_version( + name=TOOLBOX_NAME, + description="Toolbox exposing a shipping-cost skill.", + tools=[ToolboxSearchPreviewToolboxTool()], + skills=[ToolboxSkillReference(name=skill_version.name, version=skill_version.version)], + ) + print(f"Created toolbox: {toolbox_version.name} version={toolbox_version.version}") + + toolbox_mcp_url = f"{endpoint}/toolboxes/{TOOLBOX_NAME}/versions/{toolbox_version.version}/mcp?api-version=v1" + + zip_filename = "hosted-toolbox-agent.zip" + zip_bytes, zip_sha256, _ = zip(_HOSTED_AGENT_SOURCE_DIR, zip_filename) + + # The ``code`` field accepts any variant of the SDK's ``FileType`` union. + # The 3-tuple form used here pins both the filename and the content type. + # + # # 1) bare IO[bytes] - filename derived from the file handle's `.name` + # code=zip_path.open("rb") + # + # # 2) (filename, bytes) + # code=(zip_filename, zip_bytes) + # + # # 3) (filename, IO[bytes]) + # code=(zip_filename, zip_path.open("rb")) + # + # # 4) (filename, bytes, content_type) + # code=(zip_filename, zip_bytes, "application/zip") + code = (zip_filename, zip_bytes, "application/zip") + + content = CreateAgentVersionFromCodeContent( + metadata=CreateAgentVersionFromCodeMetadata( + description="Hosted agent code for toolbox MCP skills with shipping-cost skill.", + definition=HostedAgentDefinition( + cpu="0.5", + memory="1Gi", + code_configuration=CodeConfiguration( + runtime="python_3_14", + entry_point=["python", "main.py"], + dependency_resolution=CodeDependencyResolution.REMOTE_BUILD, + ), + environment_variables={ + "FOUNDRY_PROJECT_ENDPOINT": endpoint, + "FOUNDRY_MODEL_NAME": model_name, + "MCP_SERVER_URL": toolbox_mcp_url, + }, + protocol_versions=[ProtocolVersionRecord(protocol="responses", version="1.0.0")], + ), + ), + code=code, + ) + + created = project_client.agents.create_version_from_code( + agent_name=agent_name, + content=content, + code_zip_sha256=zip_sha256, + ) + print(f"Created hosted agent version: {created.version}") + + wait_for_agent_version_active( + project_client=project_client, + agent_name=agent_name, + agent_version=created.version, + ) + + ensure_agent_identity_rbac( + agent=created, + credential=credential, + subscription_id=subscription_id, + foundry_project_endpoint=endpoint, + ) + + user_input = "Compute the shipping cost for a 3 kg package shipped domestically." + print(f"User: {user_input}") + response = hosted_openai_client.responses.create(input=user_input) + + response_text = response.output_text or "" + print("Response:") + print(response_text.encode("utf-8", errors="replace").decode("utf-8")) + + project_client.agents.delete_version(agent_name=agent_name, agent_version=created.version, force=True) + print(f"Agent version {created.version} deleted") + project_client.toolboxes.delete(TOOLBOX_NAME) + print("Toolbox deleted") + project_client.beta.skills.delete(SKILL_NAME) + print("Skill deleted") + + +if __name__ == "__main__": + main() diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_crud.py b/sdk/ai/azure-ai-projects/samples/routines/sample_routines_crud.py similarity index 97% rename from sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_crud.py rename to sdk/ai/azure-ai-projects/samples/routines/sample_routines_crud.py index f71a74b33b48..45aadc1f8b26 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_crud.py +++ b/sdk/ai/azure-ai-projects/samples/routines/sample_routines_crud.py @@ -58,7 +58,7 @@ def print_routine_state(routine: Routine) -> None: with ( DefaultAzureCredential() as credential, - AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client, + AIProjectClient(endpoint=endpoint, credential=credential) as project_client, ): routine_name = "sample-routine" diff --git a/sdk/ai/azure-ai-projects/samples/routines/sample_routines_with_dispatch.py b/sdk/ai/azure-ai-projects/samples/routines/sample_routines_with_dispatch.py new file mode 100644 index 000000000000..1c5164cf00c8 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/routines/sample_routines_with_dispatch.py @@ -0,0 +1,130 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +""" +DESCRIPTION: + This sample demonstrates how to create a Routine with a manual (custom) + trigger and fire it on demand via `dispatch(...)`, then record the + resulting run by polling `list_runs(...)` using the synchronous + AIProjectClient. + + The routine is bound to an existing hosted agent. Because the trigger is + a `CustomRoutineTrigger`, the routine never fires on its own; the sample + explicitly invokes it with `project_client.beta.routines.dispatch(...)` + passing an `InvokeAgentResponsesApiDispatchPayload` carrying the input + sent to the agent. The sample then polls the run history until a + terminal phase is reached (or a deadline elapses), printing each + observed transition. The routine is deleted at the end of the sample. + + Routines are currently a preview feature. In the Python SDK, you access + these operations via `project_client.beta.routines`. + +USAGE: + python sample_routines_with_dispatch.py + + Before running the sample: + + pip install "azure-ai-projects>=2.2.0" python-dotenv + + Set these environment variables with your own values: + 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview + page of your Microsoft Foundry portal. + 2) FOUNDRY_HOSTED_AGENT_NAME - The name of an existing Hosted Agent to invoke + when the routine is dispatched. +""" + +import json +import os +import time + +from dotenv import load_dotenv + +from azure.core.exceptions import ResourceNotFoundError +from azure.identity import DefaultAzureCredential + +from azure.ai.projects import AIProjectClient +from azure.ai.projects.models import ( + CustomRoutineTrigger, + InvokeAgentResponsesApiDispatchPayload, + InvokeAgentResponsesApiRoutineAction, + RoutineRun, + RoutineRunPhase, +) + +load_dotenv() + +endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] +agent_name = os.environ["FOUNDRY_HOSTED_AGENT_NAME"] + + +with ( + DefaultAzureCredential() as credential, + AIProjectClient(endpoint=endpoint, credential=credential) as project_client, +): + + routine_name = "sample-routine-dispatch" + + try: + project_client.beta.routines.delete(routine_name) + print(f"Routine `{routine_name}` deleted") + except ResourceNotFoundError: + pass + + created = project_client.beta.routines.create_or_update( + routine_name, + description="Routine used by the dispatch sample.", + enabled=True, + triggers={ + "manual": CustomRoutineTrigger( + provider="sample-provider", + event_name="sample-event", + parameters={}, + ), + }, + action=InvokeAgentResponsesApiRoutineAction(agent_name=agent_name), + ) + print(f"Created routine: {created.name} enabled={created.enabled}") + + dispatch_result = project_client.beta.routines.dispatch( + routine_name, + payload=InvokeAgentResponsesApiDispatchPayload( + input="Say hello from a manually dispatched routine.", + ), + ) + print(f"Dispatched routine: dispatch_id={dispatch_result.dispatch_id} task_id={dispatch_result.task_id}") + + seen_phases: dict[str, RoutineRunPhase] = {} + final_run: RoutineRun | None = None + + deadline = time.monotonic() + 180 + while time.monotonic() < deadline: + runs = list(project_client.beta.routines.list_runs(routine_name, limit=20, order="desc")) + for run in runs: + if seen_phases.get(run.id) == run.phase: + continue + seen_phases[run.id] = run.phase # type: ignore[assignment] + print( + f" - run_id={run.id} phase={run.phase} status={run.status} " + f"trigger_type={run.trigger_type} triggered_at={run.triggered_at} ended_at={run.ended_at}" + ) + if str(run.status).lower() == "finished": + final_run = run + + if final_run is not None: + break + time.sleep(5) + + if final_run: + print("Final run:") + print(json.dumps(final_run.as_dict(), indent=2, default=str)) + # Note: retrieving the response body produced by a routine-dispatched + # run via `openai_client.responses.retrieve(final_run.response_id)` is + # not yet supported by the service for this scenario. + else: + print("Dispatch did not produce a terminal run within the deadline.") + + project_client.beta.routines.delete(routine_name) + print("Routine deleted") diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_with_schedule_trigger.py b/sdk/ai/azure-ai-projects/samples/routines/sample_routines_with_schedule_trigger.py similarity index 99% rename from sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_with_schedule_trigger.py rename to sdk/ai/azure-ai-projects/samples/routines/sample_routines_with_schedule_trigger.py index 7bd7c0780661..7f3b6404d644 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_with_schedule_trigger.py +++ b/sdk/ai/azure-ai-projects/samples/routines/sample_routines_with_schedule_trigger.py @@ -62,7 +62,7 @@ def main() -> None: with ( DefaultAzureCredential() as credential, - AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client, + AIProjectClient(endpoint=endpoint, credential=credential) as project_client, ): routine_name = "sample-routine-schedule" diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_with_timer_trigger.py b/sdk/ai/azure-ai-projects/samples/routines/sample_routines_with_timer_trigger.py similarity index 98% rename from sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_with_timer_trigger.py rename to sdk/ai/azure-ai-projects/samples/routines/sample_routines_with_timer_trigger.py index 96ed2f533e81..1ef31fb4a108 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_routines_with_timer_trigger.py +++ b/sdk/ai/azure-ai-projects/samples/routines/sample_routines_with_timer_trigger.py @@ -74,7 +74,7 @@ with ( DefaultAzureCredential() as credential, - AIProjectClient(endpoint=endpoint, credential=credential, allow_preview=True) as project_client, + AIProjectClient(endpoint=endpoint, credential=credential) as project_client, ): # Azure Monitor exporter: same spans also sent to the Application Insights # resource attached to the Foundry project, viewable in the "Tracing" tab diff --git a/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/LICENSE.txt b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/LICENSE.txt new file mode 100644 index 000000000000..7a4a3ea2424c --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/SKILL.md b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/SKILL.md new file mode 100644 index 000000000000..9f63fee82de8 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/SKILL.md @@ -0,0 +1,130 @@ +--- +name: canvas-design +description: Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations. +license: Complete terms in LICENSE.txt +--- + +These are instructions for creating design philosophies - aesthetic movements that are then EXPRESSED VISUALLY. Output only .md files, .pdf files, and .png files. + +Complete this in two steps: +1. Design Philosophy Creation (.md file) +2. Express by creating it on a canvas (.pdf file or .png file) + +First, undertake this task: + +## DESIGN PHILOSOPHY CREATION + +To begin, create a VISUAL PHILOSOPHY (not layouts or templates) that will be interpreted through: +- Form, space, color, composition +- Images, graphics, shapes, patterns +- Minimal text as visual accent + +### THE CRITICAL UNDERSTANDING +- What is received: Some subtle input or instructions by the user that should be taken into account, but used as a foundation; it should not constrain creative freedom. +- What is created: A design philosophy/aesthetic movement. +- What happens next: Then, the same version receives the philosophy and EXPRESSES IT VISUALLY - creating artifacts that are 90% visual design, 10% essential text. + +Consider this approach: +- Write a manifesto for an art movement +- The next phase involves making the artwork + +The philosophy must emphasize: Visual expression. Spatial communication. Artistic interpretation. Minimal words. + +### HOW TO GENERATE A VISUAL PHILOSOPHY + +**Name the movement** (1-2 words): "Brutalist Joy" / "Chromatic Silence" / "Metabolist Dreams" + +**Articulate the philosophy** (4-6 paragraphs - concise but complete): + +To capture the VISUAL essence, express how the philosophy manifests through: +- Space and form +- Color and material +- Scale and rhythm +- Composition and balance +- Visual hierarchy + +**CRITICAL GUIDELINES:** +- **Avoid redundancy**: Each design aspect should be mentioned once. Avoid repeating points about color theory, spatial relationships, or typographic principles unless adding new depth. +- **Emphasize craftsmanship REPEATEDLY**: The philosophy MUST stress multiple times that the final work should appear as though it took countless hours to create, was labored over with care, and comes from someone at the absolute top of their field. This framing is essential - repeat phrases like "meticulously crafted," "the product of deep expertise," "painstaking attention," "master-level execution." +- **Leave creative space**: Remain specific about the aesthetic direction, but concise enough that the next Claude has room to make interpretive choices also at a extremely high level of craftmanship. + +The philosophy must guide the next version to express ideas VISUALLY, not through text. Information lives in design, not paragraphs. + +### PHILOSOPHY EXAMPLES + +**"Concrete Poetry"** +Philosophy: Communication through monumental form and bold geometry. +Visual expression: Massive color blocks, sculptural typography (huge single words, tiny labels), Brutalist spatial divisions, Polish poster energy meets Le Corbusier. Ideas expressed through visual weight and spatial tension, not explanation. Text as rare, powerful gesture - never paragraphs, only essential words integrated into the visual architecture. Every element placed with the precision of a master craftsman. + +**"Chromatic Language"** +Philosophy: Color as the primary information system. +Visual expression: Geometric precision where color zones create meaning. Typography minimal - small sans-serif labels letting chromatic fields communicate. Think Josef Albers' interaction meets data visualization. Information encoded spatially and chromatically. Words only to anchor what color already shows. The result of painstaking chromatic calibration. + +**"Analog Meditation"** +Philosophy: Quiet visual contemplation through texture and breathing room. +Visual expression: Paper grain, ink bleeds, vast negative space. Photography and illustration dominate. Typography whispered (small, restrained, serving the visual). Japanese photobook aesthetic. Images breathe across pages. Text appears sparingly - short phrases, never explanatory blocks. Each composition balanced with the care of a meditation practice. + +**"Organic Systems"** +Philosophy: Natural clustering and modular growth patterns. +Visual expression: Rounded forms, organic arrangements, color from nature through architecture. Information shown through visual diagrams, spatial relationships, iconography. Text only for key labels floating in space. The composition tells the story through expert spatial orchestration. + +**"Geometric Silence"** +Philosophy: Pure order and restraint. +Visual expression: Grid-based precision, bold photography or stark graphics, dramatic negative space. Typography precise but minimal - small essential text, large quiet zones. Swiss formalism meets Brutalist material honesty. Structure communicates, not words. Every alignment the work of countless refinements. + +*These are condensed examples. The actual design philosophy should be 4-6 substantial paragraphs.* + +### ESSENTIAL PRINCIPLES +- **VISUAL PHILOSOPHY**: Create an aesthetic worldview to be expressed through design +- **MINIMAL TEXT**: Always emphasize that text is sparse, essential-only, integrated as visual element - never lengthy +- **SPATIAL EXPRESSION**: Ideas communicate through space, form, color, composition - not paragraphs +- **ARTISTIC FREEDOM**: The next Claude interprets the philosophy visually - provide creative room +- **PURE DESIGN**: This is about making ART OBJECTS, not documents with decoration +- **EXPERT CRAFTSMANSHIP**: Repeatedly emphasize the final work must look meticulously crafted, labored over with care, the product of countless hours by someone at the top of their field + +**The design philosophy should be 4-6 paragraphs long.** Fill it with poetic design philosophy that brings together the core vision. Avoid repeating the same points. Keep the design philosophy generic without mentioning the intention of the art, as if it can be used wherever. Output the design philosophy as a .md file. + +--- + +## DEDUCING THE SUBTLE REFERENCE + +**CRITICAL STEP**: Before creating the canvas, identify the subtle conceptual thread from the original request. + +**THE ESSENTIAL PRINCIPLE**: +The topic is a **subtle, niche reference embedded within the art itself** - not always literal, always sophisticated. Someone familiar with the subject should feel it intuitively, while others simply experience a masterful abstract composition. The design philosophy provides the aesthetic language. The deduced topic provides the soul - the quiet conceptual DNA woven invisibly into form, color, and composition. + +This is **VERY IMPORTANT**: The reference must be refined so it enhances the work's depth without announcing itself. Think like a jazz musician quoting another song - only those who know will catch it, but everyone appreciates the music. + +--- + +## CANVAS CREATION + +With both the philosophy and the conceptual framework established, express it on a canvas. Take a moment to gather thoughts and clear the mind. Use the design philosophy created and the instructions below to craft a masterpiece, embodying all aspects of the philosophy with expert craftsmanship. + +**IMPORTANT**: For any type of content, even if the user requests something for a movie/game/book, the approach should still be sophisticated. Never lose sight of the idea that this should be art, not something that's cartoony or amateur. + +To create museum or magazine quality work, use the design philosophy as the foundation. Create one single page, highly visual, design-forward PDF or PNG output (unless asked for more pages). Generally use repeating patterns and perfect shapes. Treat the abstract philosophical design as if it were a scientific bible, borrowing the visual language of systematic observation—dense accumulation of marks, repeated elements, or layered patterns that build meaning through patient repetition and reward sustained viewing. Add sparse, clinical typography and systematic reference markers that suggest this could be a diagram from an imaginary discipline, treating the invisible subject with the same reverence typically reserved for documenting observable phenomena. Anchor the piece with simple phrase(s) or details positioned subtly, using a limited color palette that feels intentional and cohesive. Embrace the paradox of using analytical visual language to express ideas about human experience: the result should feel like an artifact that proves something ephemeral can be studied, mapped, and understood through careful attention. This is true art. + +**Text as a contextual element**: Text is always minimal and visual-first, but let context guide whether that means whisper-quiet labels or bold typographic gestures. A punk venue poster might have larger, more aggressive type than a minimalist ceramics studio identity. Most of the time, font should be thin. All use of fonts must be design-forward and prioritize visual communication. Regardless of text scale, nothing falls off the page and nothing overlaps. Every element must be contained within the canvas boundaries with proper margins. Check carefully that all text, graphics, and visual elements have breathing room and clear separation. This is non-negotiable for professional execution. **IMPORTANT: Use different fonts if writing text. Search the `./canvas-fonts` directory. Regardless of approach, sophistication is non-negotiable.** + +Download and use whatever fonts are needed to make this a reality. Get creative by making the typography actually part of the art itself -- if the art is abstract, bring the font onto the canvas, not typeset digitally. + +To push boundaries, follow design instinct/intuition while using the philosophy as a guiding principle. Embrace ultimate design freedom and choice. Push aesthetics and design to the frontier. + +**CRITICAL**: To achieve human-crafted quality (not AI-generated), create work that looks like it took countless hours. Make it appear as though someone at the absolute top of their field labored over every detail with painstaking care. Ensure the composition, spacing, color choices, typography - everything screams expert-level craftsmanship. Double-check that nothing overlaps, formatting is flawless, every detail perfect. Create something that could be shown to people to prove expertise and rank as undeniably impressive. + +Output the final result as a single, downloadable .pdf or .png file, alongside the design philosophy used as a .md file. + +--- + +## FINAL STEP + +**IMPORTANT**: The user ALREADY said "It isn't perfect enough. It must be pristine, a masterpiece if craftsmanship, as if it were about to be displayed in a museum." + +**CRITICAL**: To refine the work, avoid adding more graphics; instead refine what has been created and make it extremely crisp, respecting the design philosophy and the principles of minimalism entirely. Rather than adding a fun filter or refactoring a font, consider how to make the existing composition more cohesive with the art. If the instinct is to call a new function or draw a new shape, STOP and instead ask: "How can I make what's already here more of a piece of art?" + +Take a second pass. Go back to the code and refine/polish further to make this a philosophically designed masterpiece. + +## MULTI-PAGE OPTION + +To create additional pages when requested, create more creative pages along the same lines as the design philosophy but distinctly different as well. Bundle those pages in the same .pdf or many .pngs. Treat the first page as just a single page in a whole coffee table book waiting to be filled. Make the next pages unique twists and memories of the original. Have them almost tell a story in a very tasteful way. Exercise full creative freedom. \ No newline at end of file diff --git a/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/DMMono-OFL.txt b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/DMMono-OFL.txt new file mode 100644 index 000000000000..5b17f0c628c0 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/DMMono-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The DM Mono Project Authors (https://www.github.com/googlefonts/dm-mono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/DMMono-Regular.ttf b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/DMMono-Regular.ttf new file mode 100644 index 000000000000..7efe813da72c Binary files /dev/null and b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/DMMono-Regular.ttf differ diff --git a/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/InstrumentSans-OFL.txt b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/InstrumentSans-OFL.txt new file mode 100644 index 000000000000..4bb99142f612 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/InstrumentSans-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2022 The Instrument Sans Project Authors (https://github.com/Instrument/instrument-sans) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf new file mode 100644 index 000000000000..14c6113cdd3a Binary files /dev/null and b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf differ diff --git a/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf new file mode 100644 index 000000000000..976303184a52 Binary files /dev/null and b/sdk/ai/azure-ai-projects/samples/skills/assets/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf differ diff --git a/sdk/ai/azure-ai-projects/samples/skills/assets/team-status-update/SKILL.md b/sdk/ai/azure-ai-projects/samples/skills/assets/team-status-update/SKILL.md new file mode 100644 index 000000000000..cb64f127084e --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/skills/assets/team-status-update/SKILL.md @@ -0,0 +1,30 @@ +--- +name: team-status-update +description: Drafts concise team status updates with progress, plans, and blockers. +--- + +# Team Status Update + +Use this skill to draft a short team status update that summarizes completed work, +upcoming work, and blockers. + +## Guidelines + +- Keep the update short enough to read in under a minute. +- Use one to three bullets in each section. +- Put completed work under Completed work. +- Put upcoming work under Next steps. +- Put risks, blockers, or needed help under Blockers. +- Include owners, dates, or metrics when they make the update clearer. + +## Ask For + +- Team name. +- Time period. +- Completed work. +- Next steps. +- Blockers or risks. + +## Output + +Use the structure in `status-update-template.md`. \ No newline at end of file diff --git a/sdk/ai/azure-ai-projects/samples/skills/assets/team-status-update/status-update-template.md b/sdk/ai/azure-ai-projects/samples/skills/assets/team-status-update/status-update-template.md new file mode 100644 index 000000000000..6e243f9e8875 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/skills/assets/team-status-update/status-update-template.md @@ -0,0 +1,15 @@ +# Team Status Update Template + +## Completed work + +- Finished the onboarding guide draft. +- Grouped the top support questions into three themes. + +## Next steps + +- Publish the guide on Friday. +- Add support FAQ links next week. + +## Blockers + +- Need an owner for quarterly refreshes. \ No newline at end of file diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skills_crud.py b/sdk/ai/azure-ai-projects/samples/skills/sample_skills_crud.py similarity index 100% rename from sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skills_crud.py rename to sdk/ai/azure-ai-projects/samples/skills/sample_skills_crud.py diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skills_crud_async.py b/sdk/ai/azure-ai-projects/samples/skills/sample_skills_crud_async.py similarity index 100% rename from sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skills_crud_async.py rename to sdk/ai/azure-ai-projects/samples/skills/sample_skills_crud_async.py diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skills_upload_and_download.py b/sdk/ai/azure-ai-projects/samples/skills/sample_skills_upload_and_download.py similarity index 73% rename from sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skills_upload_and_download.py rename to sdk/ai/azure-ai-projects/samples/skills/sample_skills_upload_and_download.py index 5000e1b8a26a..ce39661f87cc 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skills_upload_and_download.py +++ b/sdk/ai/azure-ai-projects/samples/skills/sample_skills_upload_and_download.py @@ -29,14 +29,19 @@ 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview page of your Microsoft Foundry portal. - This sample uploads `samples/hosted_agents/assets/canvas-design.zip`. + This sample builds and uploads `samples/skills/assets/team-status-update/`. """ import os +import sys import tempfile from datetime import datetime from pathlib import Path +_SAMPLES_DIR = Path(__file__).resolve().parents[1] +if str(_SAMPLES_DIR) not in sys.path: + sys.path.insert(0, str(_SAMPLES_DIR)) + from dotenv import load_dotenv from azure.core.exceptions import ResourceNotFoundError @@ -45,12 +50,15 @@ from azure.ai.projects import AIProjectClient from azure.ai.projects.models import CreateSkillVersionFromFilesBody +from util import zip + load_dotenv() endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] download_folder = Path(tempfile.gettempdir()).resolve() -skill_name = "canvas-design" -skill_file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/canvas-design.zip")) +skill_name = "team-status-update" +skill_zip_filename = "team-status-update.zip" +skill_source_dir = Path(__file__).parent / "assets/team-status-update" with ( DefaultAzureCredential() as credential, @@ -63,26 +71,27 @@ except ResourceNotFoundError: pass - skill_path = Path(skill_file_path) + skill_zip_bytes, _, skill_zip_path = zip(skill_source_dir, skill_zip_filename) + skill_zip_filename = skill_zip_path.name # The ``files`` field accepts any variant of the SDK's ``FileType`` union. - # All four forms below produce an equivalent multipart request body; pick - # whichever fits your call site. The 3-tuple form (used here) is the most - # explicit — it pins both the filename and the content type. + # The 2-tuple form used here pins the filename while letting the transport + # choose the multipart part headers. # - # # 1) bare IO[bytes] — filename derived from the file handle's `.name` - # files=[skill_path.open("rb")] + # # 1) bare IO[bytes] - filename derived from the file handle's `.name` + # files=[skill_zip_path.open("rb")] # # # 2) (filename, bytes) - # files=[(skill_path.name, skill_path.read_bytes())] + # files=[(skill_zip_filename, skill_zip_bytes)] # # # 3) (filename, IO[bytes]) - # files=[(skill_path.name, skill_path.open("rb"))] + # files=[(skill_zip_filename, skill_zip_path.open("rb"))] # # # 4) (filename, bytes, content_type) - # files=[(skill_path.name, skill_path.read_bytes(), "application/zip")] + # files=[(skill_zip_filename, skill_zip_bytes, "application/zip")] + # imported = project_client.beta.skills.create_from_files( skill_name, - content=CreateSkillVersionFromFilesBody(files=[(skill_path.name, skill_path.read_bytes(), "application/zip")]), + content=CreateSkillVersionFromFilesBody(files=[(skill_zip_filename, skill_zip_bytes)]), ) imported_skill_name = imported.name print(f"Imported skill from package: {imported.name} ({imported.skill_id}) version={imported.version}") diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skills_upload_and_download_async.py b/sdk/ai/azure-ai-projects/samples/skills/sample_skills_upload_and_download_async.py similarity index 74% rename from sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skills_upload_and_download_async.py rename to sdk/ai/azure-ai-projects/samples/skills/sample_skills_upload_and_download_async.py index 1ddaabeea304..a9044c056a74 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_skills_upload_and_download_async.py +++ b/sdk/ai/azure-ai-projects/samples/skills/sample_skills_upload_and_download_async.py @@ -29,15 +29,20 @@ 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview page of your Microsoft Foundry portal. - This sample uploads `samples/hosted_agents/assets/canvas-design.zip`. + This sample builds and uploads `samples/skills/assets/team-status-update/`. """ import asyncio import os +import sys import tempfile from datetime import datetime from pathlib import Path +_SAMPLES_DIR = Path(__file__).resolve().parents[1] +if str(_SAMPLES_DIR) not in sys.path: + sys.path.insert(0, str(_SAMPLES_DIR)) + from dotenv import load_dotenv from azure.core.exceptions import ResourceNotFoundError @@ -46,12 +51,15 @@ from azure.ai.projects.aio import AIProjectClient from azure.ai.projects.models import CreateSkillVersionFromFilesBody +from util import zip + load_dotenv() endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] download_folder = Path(tempfile.gettempdir()).resolve() -skill_name = "canvas-design" -skill_file_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/canvas-design.zip")) +skill_name = "team-status-update" +skill_zip_filename = "team-status-update.zip" +skill_source_dir = Path(__file__).parent / "assets/team-status-update" async def main() -> None: @@ -66,28 +74,27 @@ async def main() -> None: except ResourceNotFoundError: pass - skill_path = Path(skill_file_path) + skill_zip_bytes, _, skill_zip_path = zip(skill_source_dir, skill_zip_filename) + uploaded_skill_zip_filename = skill_zip_path.name # The ``files`` field accepts any variant of the SDK's ``FileType`` union. - # All four forms below produce an equivalent multipart request body; pick - # whichever fits your call site. The 3-tuple form (used here) is the most - # explicit — it pins both the filename and the content type. + # The 2-tuple form used here pins the filename while letting the transport + # choose the multipart part headers. # - # # 1) bare IO[bytes] — filename derived from the file handle's `.name` - # files=[skill_path.open("rb")] + # # 1) bare IO[bytes] - filename derived from the file handle's `.name` + # files=[skill_zip_path.open("rb")] # # # 2) (filename, bytes) - # files=[(skill_path.name, skill_path.read_bytes())] + # files=[(skill_zip_filename, skill_zip_bytes)] # # # 3) (filename, IO[bytes]) - # files=[(skill_path.name, skill_path.open("rb"))] + # files=[(skill_zip_filename, skill_zip_path.open("rb"))] # # # 4) (filename, bytes, content_type) - # files=[(skill_path.name, skill_path.read_bytes(), "application/zip")] + # files=[(skill_zip_filename, skill_zip_bytes, "application/zip")] + # imported = await project_client.beta.skills.create_from_files( skill_name, - content=CreateSkillVersionFromFilesBody( - files=[(skill_path.name, skill_path.read_bytes(), "application/zip")] - ), + content=CreateSkillVersionFromFilesBody(files=[(uploaded_skill_zip_filename, skill_zip_bytes)]), ) imported_skill_name = imported.name print(f"Imported skill from package: {imported.name} ({imported.skill_id}) version={imported.version}") diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_toolboxes_crud.py b/sdk/ai/azure-ai-projects/samples/toolboxes/sample_toolboxes_crud.py similarity index 72% rename from sdk/ai/azure-ai-projects/samples/hosted_agents/sample_toolboxes_crud.py rename to sdk/ai/azure-ai-projects/samples/toolboxes/sample_toolboxes_crud.py index 60ca6d1b969a..6fd505e17fd3 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_toolboxes_crud.py +++ b/sdk/ai/azure-ai-projects/samples/toolboxes/sample_toolboxes_crud.py @@ -13,15 +13,12 @@ `require_approval` values, switches the default version, and prints the MCP `require_approval` setting from the fetched default version. - Toolboxes are currently a preview feature. In the Python SDK, you access - these operations via `project_client.beta.toolboxes`. - USAGE: python sample_toolboxes_crud.py Before running the sample: - pip install "azure-ai-projects>=2.1.0" python-dotenv + pip install "azure-ai-projects>=2.3.0" python-dotenv Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -38,94 +35,94 @@ from azure.identity import DefaultAzureCredential from azure.ai.projects import AIProjectClient -from azure.ai.projects.models import MCPTool, Tool +from azure.ai.projects.models import MCPToolboxTool, ToolboxTool load_dotenv() endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] -def print_mcp_require_approval(tools: list[Tool]) -> None: +def print_mcp_require_approval(tools: list[ToolboxTool]) -> None: for tool in tools: - if isinstance(tool, MCPTool): + if isinstance(tool, MCPToolboxTool): print(f" - MCP `{tool.server_label}` require_approval: {tool.require_approval}") with ( DefaultAzureCredential() as credential, - AIProjectClient(endpoint=endpoint, credential=credential, logging_enable=True) as project_client, + AIProjectClient(endpoint=endpoint, credential=credential) as project_client, ): toolbox_name = "toolbox_with_mcp_tool" try: - project_client.beta.toolboxes.delete(toolbox_name) + project_client.toolboxes.delete(toolbox_name) print(f"Toolbox `{toolbox_name}` deleted") except ResourceNotFoundError: pass - tools_with_mcp_approval_required: list[Tool] = [ - MCPTool( + tools_with_mcp_approval_required: list[ToolboxTool] = [ + MCPToolboxTool( server_label="api_specs", server_url="https://gitmcp.io/Azure/azure-rest-api-specs", require_approval="never", ) ] - tools_with_mcp_approval_always: list[Tool] = [ - MCPTool( + tools_with_mcp_approval_always: list[ToolboxTool] = [ + MCPToolboxTool( server_label="api_specs", server_url="https://gitmcp.io/Azure/azure-rest-api-specs", require_approval="always", ) ] - created = project_client.beta.toolboxes.create_version( + created = project_client.toolboxes.create_version( name=toolbox_name, description="Toolbox version with MCP require_approval set to 'never'.", tools=tools_with_mcp_approval_required, ) print(f"Created toolbox: {created.name} with MCP tools requiring approval 'never' in version {created.version}") - created = project_client.beta.toolboxes.create_version( + created = project_client.toolboxes.create_version( name=toolbox_name, description="Toolbox version with MCP require_approval set to 'always'.", tools=tools_with_mcp_approval_always, ) print(f"Created toolbox: {created.name} with MCP tools requiring approval 'always' in version {created.version}") - updated = project_client.beta.toolboxes.update( + updated = project_client.toolboxes.update( toolbox_name, default_version="2", ) print(f"Updated toolbox: {updated.name} default version is now {updated.default_version}") - fetched = project_client.beta.toolboxes.get(name=toolbox_name) + fetched = project_client.toolboxes.get(name=toolbox_name) print(f"Retrieved toolbox with default version: {fetched.default_version}") - fetched_version = project_client.beta.toolboxes.get_version( + fetched_version = project_client.toolboxes.get_version( name=toolbox_name, version=fetched.default_version, ) print_mcp_require_approval(fetched_version.tools) - updated = project_client.beta.toolboxes.update( + updated = project_client.toolboxes.update( toolbox_name, default_version="1", ) print(f"Updated toolbox: {updated.name} default version is now {updated.default_version}") - fetched = project_client.beta.toolboxes.get(name=toolbox_name) + fetched = project_client.toolboxes.get(name=toolbox_name) print(f"Retrieved toolbox with default version: {fetched.default_version}") - fetched_version = project_client.beta.toolboxes.get_version( + fetched_version = project_client.toolboxes.get_version( name=toolbox_name, version=fetched.default_version, ) print_mcp_require_approval(fetched_version.tools) - toolboxes = list(project_client.beta.toolboxes.list()) + toolboxes = list(project_client.toolboxes.list()) print(f"Found {len(toolboxes)} toolboxes") for item in toolboxes: print(f" - {item.name} ({item.id})") - project_client.beta.toolboxes.delete(name=toolbox_name) + project_client.toolboxes.delete(name=toolbox_name) print("Toolbox deleted") diff --git a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_toolboxes_crud_async.py b/sdk/ai/azure-ai-projects/samples/toolboxes/sample_toolboxes_crud_async.py similarity index 74% rename from sdk/ai/azure-ai-projects/samples/hosted_agents/sample_toolboxes_crud_async.py rename to sdk/ai/azure-ai-projects/samples/toolboxes/sample_toolboxes_crud_async.py index 1721a5e6fdb0..c5cee41a4638 100644 --- a/sdk/ai/azure-ai-projects/samples/hosted_agents/sample_toolboxes_crud_async.py +++ b/sdk/ai/azure-ai-projects/samples/toolboxes/sample_toolboxes_crud_async.py @@ -13,15 +13,12 @@ `require_approval` values, switches the default version, and prints the MCP `require_approval` setting from the fetched default version. - Toolboxes are currently a preview feature. In the Python SDK, you access - these operations via `project_client.beta.toolboxes`. - USAGE: python sample_toolboxes_crud_async.py Before running the sample: - pip install "azure-ai-projects>=2.1.0" python-dotenv aiohttp + pip install "azure-ai-projects>=2.3.0" python-dotenv aiohttp Set these environment variables with your own values: 1) FOUNDRY_PROJECT_ENDPOINT - The Azure AI Project endpoint, as found in the Overview @@ -37,16 +34,16 @@ from azure.identity.aio import DefaultAzureCredential from azure.ai.projects.aio import AIProjectClient -from azure.ai.projects.models import MCPTool, Tool +from azure.ai.projects.models import MCPToolboxTool, ToolboxTool load_dotenv() endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"] -def print_mcp_require_approval(tools: list[Tool]) -> None: +def print_mcp_require_approval(tools: list[ToolboxTool]) -> None: for tool in tools: - if isinstance(tool, MCPTool): + if isinstance(tool, MCPToolboxTool): print(f" - MCP `{tool.server_label}` require_approval: {tool.require_approval}") @@ -60,35 +57,35 @@ async def main() -> None: toolbox_name = "toolbox_with_mcp_tool" try: - await project_client.beta.toolboxes.delete(toolbox_name) + await project_client.toolboxes.delete(toolbox_name) print(f"Toolbox `{toolbox_name}` deleted") except ResourceNotFoundError: pass - tools_with_mcp_approval_never: list[Tool] = [ - MCPTool( + tools_with_mcp_approval_never: list[ToolboxTool] = [ + MCPToolboxTool( server_label="api_specs", server_url="https://gitmcp.io/Azure/azure-rest-api-specs", require_approval="never", ) ] - tools_with_mcp_approval_always: list[Tool] = [ - MCPTool( + tools_with_mcp_approval_always: list[ToolboxTool] = [ + MCPToolboxTool( server_label="api_specs", server_url="https://gitmcp.io/Azure/azure-rest-api-specs", require_approval="always", ) ] - created = await project_client.beta.toolboxes.create_version( + created = await project_client.toolboxes.create_version( name=toolbox_name, description="Toolbox version with MCP require_approval set to 'never'.", tools=tools_with_mcp_approval_never, ) print(f"Created toolbox: {created.name} with MCP tools requiring approval 'never' in version {created.version}") - created = await project_client.beta.toolboxes.create_version( + created = await project_client.toolboxes.create_version( name=toolbox_name, description="Toolbox version with MCP require_approval set to 'always'.", tools=tools_with_mcp_approval_always, @@ -97,42 +94,42 @@ async def main() -> None: f"Created toolbox: {created.name} with MCP tools requiring approval 'always' in version {created.version}" ) - updated = await project_client.beta.toolboxes.update( + updated = await project_client.toolboxes.update( name=toolbox_name, default_version="2", ) print(f"Updated toolbox: {updated.name} default version is now {updated.default_version}") - fetched = await project_client.beta.toolboxes.get(name=toolbox_name) + fetched = await project_client.toolboxes.get(name=toolbox_name) print(f"Retrieved toolbox with default version: {fetched.default_version}") - fetched_version = await project_client.beta.toolboxes.get_version( + fetched_version = await project_client.toolboxes.get_version( name=toolbox_name, version=fetched.default_version, ) print_mcp_require_approval(fetched_version.tools) - updated = await project_client.beta.toolboxes.update( + updated = await project_client.toolboxes.update( toolbox_name, default_version="1", ) print(f"Updated toolbox: {updated.name} default version is now {updated.default_version}") - fetched = await project_client.beta.toolboxes.get(name=toolbox_name) + fetched = await project_client.toolboxes.get(name=toolbox_name) print(f"Retrieved toolbox with default version: {fetched.default_version}") - fetched_version = await project_client.beta.toolboxes.get_version( + fetched_version = await project_client.toolboxes.get_version( name=toolbox_name, version=fetched.default_version, ) print_mcp_require_approval(fetched_version.tools) toolboxes = [] - async for item in project_client.beta.toolboxes.list(): + async for item in project_client.toolboxes.list(): toolboxes.append(item) print(f"Found {len(toolboxes)} toolboxes") for item in toolboxes: print(f" - {item.name} ({item.id})") - await project_client.beta.toolboxes.delete(name=toolbox_name) + await project_client.toolboxes.delete(name=toolbox_name) print("Toolbox deleted") diff --git a/sdk/ai/azure-ai-projects/samples/util.py b/sdk/ai/azure-ai-projects/samples/util.py new file mode 100644 index 000000000000..111e08294bd1 --- /dev/null +++ b/sdk/ai/azure-ai-projects/samples/util.py @@ -0,0 +1,56 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +import hashlib +import os +import tempfile +import zipfile +from pathlib import Path +from typing import Optional, Tuple + + +def _resolve_zip_file(zip_file: str) -> Path: + zip_path = Path(zip_file) + if zip_path.is_absolute(): + return zip_path + + for base_path in (Path.cwd(), Path(__file__).resolve().parent, Path(__file__).resolve().parents[1]): + candidate = base_path / zip_path + if candidate.exists(): + return candidate.resolve() + + return (Path.cwd() / zip_path).resolve() + + +def zip( + source_dir: Path, zip_filename: Optional[str] = None, *, env_var: str = "ZIP_FILE_PATH" +) -> Tuple[bytes, str, Path]: + """Return zip bytes, SHA-256, and path for a source directory. + + Direct sample runs create a normal zip from ``source_dir`` in the temp folder. + Callers can set ``env_var`` to load an existing zip file instead of creating + a new archive. + """ + configured_zip_file = os.environ.get(env_var) + if configured_zip_file: + zip_path = _resolve_zip_file(configured_zip_file) + zip_bytes = zip_path.read_bytes() + zip_sha256 = hashlib.sha256(zip_bytes).hexdigest() + print(f"Loaded zip from {zip_path}: {len(zip_bytes)} bytes, sha256={zip_sha256}") + return zip_bytes, zip_sha256, zip_path + + zip_path = Path(tempfile.gettempdir()).resolve() / (zip_filename or f"{source_dir.name}.zip") + with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zf: + for file_path in sorted(source_dir.rglob("*")): + if not file_path.is_file(): + continue + if "__pycache__" in file_path.parts or file_path.suffix == ".pyc" or file_path.name == "README.md": + continue + zf.write(file_path, file_path.relative_to(source_dir).as_posix()) + + zip_bytes = zip_path.read_bytes() + zip_sha256 = hashlib.sha256(zip_bytes).hexdigest() + print(f"Built zip from {source_dir}: {len(zip_bytes)} bytes, sha256={zip_sha256}, path={zip_path}") + return zip_bytes, zip_sha256, zip_path diff --git a/sdk/ai/azure-ai-projects/tests/agents/test_agents_crud.py b/sdk/ai/azure-ai-projects/tests/agents/test_agents_crud.py index 702d7786fbdb..51040ba9f8e2 100644 --- a/sdk/ai/azure-ai-projects/tests/agents/test_agents_crud.py +++ b/sdk/ai/azure-ai-projects/tests/agents/test_agents_crud.py @@ -6,9 +6,19 @@ # cSpell:disable import json import io +import openai from test_base import TestBase, servicePreparer -from devtools_testutils import recorded_by_proxy -from azure.ai.projects.models import PromptAgentDefinition, AgentDetails, AgentVersionDetails +from devtools_testutils import recorded_by_proxy, RecordedTransport +from azure.ai.projects.models import ( + AgentDetails, + AgentEndpointConfig, + AgentVersionDetails, + FixedRatioVersionSelectionRule, + PromptAgentDefinition, + ProtocolConfiguration, + ResponsesProtocolConfiguration, + VersionSelector, +) class TestAgentCrud(TestBase): @@ -39,6 +49,7 @@ def test_agents_crud(self, **kwargs): """ print("\n") model = kwargs.get("foundry_model_name") + assert model is not None project_client = self.create_client(operation_group="agents", **kwargs) first_agent_name = "MyAgent1" second_agent_name = "MyAgent2" @@ -111,3 +122,174 @@ def test_agents_crud(self, **kwargs): agent_name=second_agent_name, agent_version=agent2_version1.version ) assert result.deleted + + # To run this test: + # pytest tests\agents\test_agents_crud.py::TestAgentCrud::test_agent_disable_enable -s + @servicePreparer() + @recorded_by_proxy(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) + def test_agent_disable_enable(self, **kwargs): + """ + Test disable and enable operations for Agents. + + This test creates an agent, verifies it can respond to requests, + disables it and verifies requests fail, then enables it and + verifies requests work again. + + Routes used in this test: + + Action REST API Route Client Method + ------+---------------------------------------------+----------------------------------- + POST /agents/{agent_name}/versions project_client.agents.create_version() + POST /openai/responses openai_client.responses.create() + POST /agents/{agent_name}:disable project_client.agents.disable() + POST /agents/{agent_name}:enable project_client.agents.enable() + DELETE /agents/{agent_name}/versions/{agent_version} project_client.agents.delete_version() + """ + print("\n") + model: str = kwargs["foundry_model_name"] + agent_name = "DisableEnableTestAgent" + + # Setup + project_client = self.create_client(operation_group="agents", **kwargs) + # Intentionally use Agent Endpoint here for Responses calls (by giving `agent_name`). Async tests will use Project + # endpoint instead, so we cover both endpoint. + openai_client = project_client.get_openai_client(agent_name=agent_name) + + # Delete any existing agent from previous test runs (ignore failures) + try: + project_client.agents.delete(agent_name=agent_name) + except Exception: + pass + + # Create an Agent + agent = project_client.agents.create_version( + agent_name=agent_name, + definition=PromptAgentDefinition( + model=model, + instructions="You are a helpful assistant that answers general questions", + ), + ) + print(f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})") + self._validate_agent_version(agent) + + # Verify the agent can respond to requests + response = openai_client.responses.create( + input="How many feet in a mile?", + extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}}, + ) + print(f"Response id: {response.id}, output text: {response.output_text}") + assert "5280" in response.output_text or "5,280" in response.output_text + + # Disable the agent + project_client.agents.disable(agent_name=agent_name) + print(f"Agent disabled") + + # Verify requests fail when agent is disabled + error_raised = False + try: + _ = openai_client.responses.create( + input="How many feet in a mile?", + extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}}, + ) + except openai.PermissionDeniedError as e: + error_raised = True + print(f"Expected error when calling disabled agent: {e}") + assert error_raised, "Expected an error when calling a disabled agent" + + # Enable the agent + project_client.agents.enable(agent_name=agent_name) + print(f"Agent enabled") + + # Verify the agent can respond to requests again + response = openai_client.responses.create( + input="How many meters in a mile?", + extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}}, + ) + print(f"Response id: {response.id}, output text: {response.output_text}") + assert "1609" in response.output_text or "1,609" in response.output_text + + # Cleanup - delete the agent + result = project_client.agents.delete_version(agent_name=agent_name, agent_version=agent.version) + assert result.deleted + print(f"Agent deleted") + + # To run this test: + # pytest tests\agents\test_agents_crud.py::TestAgentCrud::test_prompt_agent_endpoint_responses -s + @servicePreparer() + @recorded_by_proxy(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) + def test_prompt_agent_endpoint_responses(self, **kwargs): + """ + Test prompt-agent endpoint routing for the Responses protocol. + + This test: + 1. Creates a prompt agent version + 2. Configures the agent endpoint to route 100% of traffic to that version + 3. Invokes the agent endpoint through the OpenAI-compatible responses client + 4. Verifies the response + 5. Cleans up by deleting the agent version + + Routes used in this test: + + Action REST API Route Client Method + ------+---------------------------------------------+----------------------------------- + POST /agents/{agent_name}/versions project_client.agents.create_version() + PATCH /agents/{agent_name} project_client.agents.update_details() + POST /agents/{agent_name}/endpoint/protocols/openai/conversations openai_client.conversations.create() + POST /agents/{agent_name}/endpoint/protocols/openai/responses openai_client.responses.create() + DELETE /agents/{agent_name}/versions/{agent_version} project_client.agents.delete_version() + """ + print("\n") + model = kwargs.get("foundry_model_name") + assert model is not None + agent_name = "PromptAgentEndpointTestAgent" + + project_client = self.create_client(operation_group="agents", allow_preview=True, **kwargs) + agent = project_client.agents.create_version( + agent_name=agent_name, + definition=PromptAgentDefinition( + model=model, + instructions="You are a helpful assistant that answers general knowledge questions.", + ), + ) + self._validate_agent_version(agent) + print(f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})") + + try: + endpoint_config = AgentEndpointConfig( + version_selector=VersionSelector( + version_selection_rules=[ + FixedRatioVersionSelectionRule(agent_version=agent.version, traffic_percentage=100), + ] + ), + protocol_configuration=ProtocolConfiguration(responses=ResponsesProtocolConfiguration()), + ) + + patched_agent = project_client.agents.update_details( + agent_name=agent_name, + agent_endpoint=endpoint_config, + ) + assert patched_agent.agent_endpoint is not None + print(f"Agent endpoint configured for agent: {patched_agent.name}") + + with project_client.get_openai_client(agent_name=agent_name) as openai_client: + conversation = openai_client.conversations.create( + items=[ + { + "type": "message", + "role": "user", + "content": "What is 2 + 2? Answer with just the number.", + } + ] + ) + response = openai_client.responses.create( + conversation=conversation.id, + input="and then add 2 again", + ) + + print(f"Response id: {response.id}, output text: {response.output_text}") + assert response.output_text + assert "6" in response.output_text.strip() + finally: + result = project_client.agents.delete_version(agent_name=agent_name, agent_version=agent.version) + assert result.deleted + print("Agent deleted") diff --git a/sdk/ai/azure-ai-projects/tests/agents/test_agents_crud_async.py b/sdk/ai/azure-ai-projects/tests/agents/test_agents_crud_async.py index 7dae5621f724..17f4d7f01113 100644 --- a/sdk/ai/azure-ai-projects/tests/agents/test_agents_crud_async.py +++ b/sdk/ai/azure-ai-projects/tests/agents/test_agents_crud_async.py @@ -6,9 +6,20 @@ # cSpell:disable import json import io +import openai from test_base import TestBase, servicePreparer from devtools_testutils.aio import recorded_by_proxy_async -from azure.ai.projects.models import PromptAgentDefinition, AgentDetails, AgentVersionDetails +from devtools_testutils import RecordedTransport +from azure.ai.projects.models import ( + AgentDetails, + AgentEndpointConfig, + AgentVersionDetails, + FixedRatioVersionSelectionRule, + PromptAgentDefinition, + ProtocolConfiguration, + ResponsesProtocolConfiguration, + VersionSelector, +) class TestAgentCrudAsync(TestBase): @@ -24,6 +35,7 @@ async def test_agents_crud_async(self, **kwargs): It uses different ways of creating agents: strongly typed, dictionary, and IO[bytes]. """ model = kwargs.get("foundry_model_name") + assert model is not None project_client = self.create_async_client(operation_group="agents", **kwargs) first_agent_name = "MyAgent1" second_agent_name = "MyAgent2" @@ -100,3 +112,178 @@ async def test_agents_crud_async(self, **kwargs): agent_name=second_agent_name, agent_version=agent2_version1.version ) assert result.deleted + + # To run this test: + # pytest tests\agents\test_agents_crud_async.py::TestAgentCrudAsync::test_agent_disable_enable_async -s + @servicePreparer() + @recorded_by_proxy_async(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) + async def test_agent_disable_enable_async(self, **kwargs): + """ + Test disable and enable operations for Agents. + + This test creates an agent, verifies it can respond to requests, + disables it and verifies requests fail, then enables it and + verifies requests work again. + + Routes used in this test: + + Action REST API Route Client Method + ------+---------------------------------------------+----------------------------------- + POST /agents/{agent_name}/versions project_client.agents.create_version() + POST /openai/responses openai_client.responses.create() + POST /agents/{agent_name}:disable project_client.agents.disable() + POST /agents/{agent_name}:enable project_client.agents.enable() + DELETE /agents/{agent_name}/versions/{agent_version} project_client.agents.delete_version() + """ + print("\n") + model: str = kwargs["foundry_model_name"] + agent_name = "DisableEnableTestAgent" + + # Setup + project_client = self.create_async_client(operation_group="agents", **kwargs) + # Intentionally use Project Endpoint here for Responses calls (by not giving `agent_name`). Sync tests will use Agent + # endpoint instead, so we cover both endpoint. + openai_client = project_client.get_openai_client() + + async with project_client: + + # Delete any existing agent from previous test runs (ignore failures) + try: + await project_client.agents.delete(agent_name=agent_name) + except Exception: + pass + + # Create an Agent + agent = await project_client.agents.create_version( + agent_name=agent_name, + definition=PromptAgentDefinition( + model=model, + instructions="You are a helpful assistant that answers general questions", + ), + ) + print(f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})") + self._validate_agent_version(agent) + + # Verify the agent can respond to requests + response = await openai_client.responses.create( + input="How many feet in a mile?", + extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}}, + ) + print(f"Response id: {response.id}, output text: {response.output_text}") + assert "5280" in response.output_text or "5,280" in response.output_text + + # Disable the agent + await project_client.agents.disable(agent_name=agent_name) + print("Agent disabled") + + # Verify requests fail when agent is disabled + error_raised = False + try: + _ = await openai_client.responses.create( + input="How many feet in a mile?", + extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}}, + ) + except openai.PermissionDeniedError as e: + error_raised = True + print(f"Expected error when calling disabled agent: {e}") + assert error_raised, "Expected an error when calling a disabled agent" + + # Enable the agent + await project_client.agents.enable(agent_name=agent_name) + print("Agent enabled") + + # Verify the agent can respond to requests again + response = await openai_client.responses.create( + input="How many meters in a mile?", + extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}}, + ) + print(f"Response id: {response.id}, output text: {response.output_text}") + assert "1609" in response.output_text or "1,609" in response.output_text + + # Cleanup - delete the agent + result = await project_client.agents.delete_version(agent_name=agent_name, agent_version=agent.version) + assert result.deleted + print("Agent deleted") + + # To run this test: + # pytest tests\agents\test_agents_crud_async.py::TestAgentCrudAsync::test_prompt_agent_endpoint_responses_async -s + @servicePreparer() + @recorded_by_proxy_async(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) + async def test_prompt_agent_endpoint_responses_async(self, **kwargs): + """ + Test prompt-agent endpoint routing for the Responses protocol. + + This test: + 1. Creates a prompt agent version + 2. Configures the agent endpoint to route 100% of traffic to that version + 3. Invokes the agent endpoint through the OpenAI-compatible responses client + 4. Verifies the response + 5. Cleans up by deleting the agent version + + Routes used in this test: + + Action REST API Route Client Method + ------+---------------------------------------------+----------------------------------- + POST /agents/{agent_name}/versions project_client.agents.create_version() + PATCH /agents/{agent_name} project_client.agents.update_details() + POST /agents/{agent_name}/endpoint/protocols/openai/conversations openai_client.conversations.create() + POST /agents/{agent_name}/endpoint/protocols/openai/responses openai_client.responses.create() + DELETE /agents/{agent_name}/versions/{agent_version} project_client.agents.delete_version() + """ + print("\n") + model = kwargs.get("foundry_model_name") + assert model is not None + agent_name = "PromptAgentEndpointTestAgent" + + project_client = self.create_async_client(operation_group="agents", allow_preview=True, **kwargs) + + async with project_client: + agent = await project_client.agents.create_version( + agent_name=agent_name, + definition=PromptAgentDefinition( + model=model, + instructions="You are a helpful assistant that answers general knowledge questions.", + ), + ) + self._validate_agent_version(agent) + print(f"Agent created (id: {agent.id}, name: {agent.name}, version: {agent.version})") + + try: + endpoint_config = AgentEndpointConfig( + version_selector=VersionSelector( + version_selection_rules=[ + FixedRatioVersionSelectionRule(agent_version=agent.version, traffic_percentage=100), + ] + ), + protocol_configuration=ProtocolConfiguration(responses=ResponsesProtocolConfiguration()), + ) + + patched_agent = await project_client.agents.update_details( + agent_name=agent_name, + agent_endpoint=endpoint_config, + ) + assert patched_agent.agent_endpoint is not None + print(f"Agent endpoint configured for agent: {patched_agent.name}") + + openai_client = project_client.get_openai_client(agent_name=agent_name) + conversation = await openai_client.conversations.create( + items=[ + { + "type": "message", + "role": "user", + "content": "What is 2 + 2? Answer with just the number.", + } + ] + ) + response = await openai_client.responses.create( + conversation=conversation.id, + input="and then add 2 again", + ) + + print(f"Response id: {response.id}, output text: {response.output_text}") + assert response.output_text + assert "6" in response.output_text.strip() + finally: + result = await project_client.agents.delete_version(agent_name=agent_name, agent_version=agent.version) + assert result.deleted + print("Agent deleted") diff --git a/sdk/ai/azure-ai-projects/tests/conftest.py b/sdk/ai/azure-ai-projects/tests/conftest.py index d875289e8c8d..4ea07947a42e 100644 --- a/sdk/ai/azure-ai-projects/tests/conftest.py +++ b/sdk/ai/azure-ai-projects/tests/conftest.py @@ -54,6 +54,7 @@ class SanitizedValues: COMPONENT_NAME = "sanitized-component-name" AGENTS_API_VERSION = "sanitized-api-version" API_KEY = "sanitized-api-key" + MODEL_DEPLOYMENT_NAME = "sanitized-model-deployment-name" @pytest.fixture(scope="session") @@ -66,6 +67,7 @@ def sanitized_values(): "component_name": f"{SanitizedValues.COMPONENT_NAME}", "agents_api_version": f"{SanitizedValues.AGENTS_API_VERSION}", "api_key": f"{SanitizedValues.API_KEY}", + "model_deployment_name": f"{SanitizedValues.MODEL_DEPLOYMENT_NAME}", } @@ -236,6 +238,36 @@ def sanitize_url_paths(): ) add_body_string_sanitizer(target=image_generation_model, value="sanitized-gpt-image") + model_deployment_names = { + value + for value in ( + os.environ.get("FOUNDRY_MODEL_NAME"), + os.environ.get("foundry_model_name"), + os.environ.get("MODEL_DEPLOYMENT_NAME"), + os.environ.get("model_deployment_name"), + os.environ.get("MEMORY_STORE_CHAT_MODEL_DEPLOYMENT_NAME"), + os.environ.get("memory_store_chat_model_deployment_name"), + ) + if value and value != sanitized_values["model_deployment_name"] + } + for model_deployment_name in model_deployment_names: + add_general_regex_sanitizer( + regex=re.escape(model_deployment_name), + value=sanitized_values["model_deployment_name"], + ) + add_body_string_sanitizer( + target=model_deployment_name, + value=sanitized_values["model_deployment_name"], + ) + + # Deterministic fallback sanitization for model deployment names returned by + # OpenAI-compatible endpoints. These can appear in response bodies and headers + # even when the live value was not supplied through a known environment variable. + add_general_regex_sanitizer( + regex=r"(? str: The sample path may be absolute or relative and may use either '\\' or '/'. Matching is done against the path segment under the `samples/` directory. - Falls back to resource_management_instructions when no folder match is found. + Raises ValueError when no explicit folder mapping is found. """ normalized = str(sample_path).replace("\\", "/") @@ -272,4 +275,8 @@ def get_instructions_for_sample_path(sample_path: str) -> str: if folder == key or folder.startswith(f"{key}/"): return INSTRUCTIONS_BY_FOLDER[key] - return resource_management_instructions + known = ", ".join(sorted(INSTRUCTIONS_BY_FOLDER.keys())) + raise ValueError( + f"No LLM instruction mapping found for sample folder '{folder}' from path '{sample_path}'. " + f"Add an entry to INSTRUCTIONS_BY_FOLDER. Known folders: {known}" + ) diff --git a/sdk/ai/azure-ai-projects/tests/samples/sample_executor.py b/sdk/ai/azure-ai-projects/tests/samples/sample_executor.py index 9fc9adfa3698..340b490c8eba 100644 --- a/sdk/ai/azure-ai-projects/tests/samples/sample_executor.py +++ b/sdk/ai/azure-ai-projects/tests/samples/sample_executor.py @@ -1276,14 +1276,14 @@ def _inject_env_vars(*, sample_path: str, kwargs: dict) -> None: @functools.wraps(fn) async def _wrapper_async(test_class, sample_path: str, *args, **kwargs): _inject_env_vars(sample_path=sample_path, kwargs=kwargs) - return await fn(test_class, sample_path, *args, **kwargs) + return await fn(test_class, *args, sample_path=sample_path, **kwargs) return _wrapper_async @functools.wraps(fn) def _wrapper_sync(test_class, sample_path: str, *args, **kwargs): _inject_env_vars(sample_path=sample_path, kwargs=kwargs) - return fn(test_class, sample_path, *args, **kwargs) + return fn(test_class, *args, sample_path=sample_path, **kwargs) return _wrapper_sync diff --git a/sdk/ai/azure-ai-projects/tests/samples/test_samples.py b/sdk/ai/azure-ai-projects/tests/samples/test_samples.py index c3fa6905f7df..a963cf08f611 100644 --- a/sdk/ai/azure-ai-projects/tests/samples/test_samples.py +++ b/sdk/ai/azure-ai-projects/tests/samples/test_samples.py @@ -233,18 +233,36 @@ def test_chat_completions_samples(self, sample_path: str, **kwargs) -> None: @servicePreparer() @additionalSampleTests( [ + AdditionalSampleTestDetail( + test_id="sample_create_hosted_agent", + sample_filename="sample_create_hosted_agent.py", + env_vars={ + "SKIP_RBAC": "true", + }, + ), AdditionalSampleTestDetail( test_id="sample_create_hosted_agent_from_remote_build", sample_filename="sample_create_hosted_agent_from_code.py", env_vars={ "FOUNDRY_HOSTED_AGENT_REMOTE_BUILD": "true", + "ZIP_FILE_PATH": "tests/samples/assets/echo-agent.zip", + "SKIP_RBAC": "true", + }, + ), + AdditionalSampleTestDetail( + test_id="sample_create_hosted_agent_from_code", + sample_filename="sample_create_hosted_agent_from_code.py", + env_vars={ + "FOUNDRY_HOSTED_AGENT_REMOTE_BUILD": "false", + "SKIP_RBAC": "true", }, ), AdditionalSampleTestDetail( - test_id="sample_routines_with_schedule_trigger", - sample_filename="sample_routines_with_schedule_trigger.py", + test_id="sample_toolbox_with_skill", + sample_filename="sample_toolbox_with_skill.py", env_vars={ - "POLL_INTERVAL_SECONDS": "300", + "ZIP_FILE_PATH": "tests/samples/assets/toolbox-agent.zip", + "SKIP_RBAC": "true", }, ), ] @@ -253,18 +271,94 @@ def test_chat_completions_samples(self, sample_path: str, **kwargs) -> None: "sample_path", get_sample_paths( "hosted_agents", + samples_to_skip=[ + "sample_create_hosted_agent.py", # Specified through AdditionalSampleTestDetail + "sample_toolbox_with_skill.py", # Specified through AdditionalSampleTestDetail + "sample_create_hosted_agent_from_code.py", # Specified through AdditionalSampleTestDetail + ], + ), + ) + @SamplePathPasser() + # To run a single sample: pytest tests\samples\test_samples.py::TestSamples::test_hosted_agents_samples[sample_agent_endpoint] -s + @recorded_by_proxy(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) + def test_hosted_agents_samples(self, sample_path: str, **kwargs) -> None: + env_vars = get_sample_env_vars(kwargs) + executor = SyncSampleExecutor(self, sample_path, env_vars=env_vars, **kwargs) + executor.execute() + executor.validate_print_calls_by_llm() + + @additionalSampleTests( + [ + AdditionalSampleTestDetail( + test_id="sample_skills_upload_and_download", + sample_filename="sample_skills_upload_and_download.py", + env_vars={ + "ZIP_FILE_PATH": "tests/samples/assets/team-status-update.zip", + }, + ), + ] + ) + @pytest.mark.parametrize( + "sample_path", + get_sample_paths( + "skills", + samples_to_skip=[ + "sample_skills_upload_and_download.py", # Specified through AdditionalSampleTestDetail + ], + ), + ) + @servicePreparer() + @SamplePathPasser() + @recorded_by_proxy(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) + def test_skills_samples(self, sample_path: str, **kwargs) -> None: + env_vars = get_sample_env_vars(kwargs) + executor = SyncSampleExecutor(self, sample_path, env_vars=env_vars, **kwargs) + executor.execute() + executor.validate_print_calls_by_llm() + + @pytest.mark.parametrize( + "sample_path", + get_sample_paths( + "toolboxes", + samples_to_skip=[], + ), + ) + @servicePreparer() + @SamplePathPasser() + @recorded_by_proxy(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) + def test_toolboxes_samples(self, sample_path: str, **kwargs) -> None: + env_vars = get_sample_env_vars(kwargs) + executor = SyncSampleExecutor(self, sample_path, env_vars=env_vars, **kwargs) + executor.execute() + executor.validate_print_calls_by_llm() + + @servicePreparer() + # @additionalSampleTests( + # [ + # AdditionalSampleTestDetail( + # test_id="sample_routines_with_schedule_trigger", + # sample_filename="sample_routines_with_schedule_trigger.py", + # env_vars={ + # "POLL_INTERVAL_SECONDS": "300", + # }, + # ), + # ] + # ) + @pytest.mark.parametrize( + "sample_path", + get_sample_paths( + "routines", samples_to_skip=[ "sample_routines_with_schedule_trigger.py", # Specify through AdditionalSampleTestDetail "sample_routines_crud.py", # Skipped due to service serialization issues "sample_routines_with_timer_trigger.py", # Skipped due to service serialization issues + "sample_routines_with_dispatch.py", # 403: test identity lacks routines/dispatch data-action ], ), ) @SamplePathPasser() @recorded_by_proxy(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) - def test_hosted_agents_samples(self, sample_path: str, **kwargs) -> None: - if os.path.basename(sample_path).startswith("sample_create_hosted_agent") and not self.is_live: - pytest.skip("sample_create_hosted_agent.py is skipped in replay mode due to RBAC complications.") + def test_routines_samples(self, sample_path: str, **kwargs) -> None: env_vars = get_sample_env_vars(kwargs) executor = SyncSampleExecutor(self, sample_path, env_vars=env_vars, **kwargs) executor.execute() diff --git a/sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py b/sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py index db877e4900bd..f5ed3508de95 100644 --- a/sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py +++ b/sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py @@ -201,11 +201,28 @@ async def test_chat_completions_samples(self, sample_path: str, **kwargs) -> Non @servicePreparer() @additionalSampleTests( [ + AdditionalSampleTestDetail( + test_id="sample_create_hosted_agent_async", + sample_filename="sample_create_hosted_agent_async.py", + env_vars={ + "SKIP_RBAC": "true", + }, + ), AdditionalSampleTestDetail( test_id="sample_create_hosted_agent_from_remote_build_async", sample_filename="sample_create_hosted_agent_from_code_async.py", env_vars={ "FOUNDRY_HOSTED_AGENT_REMOTE_BUILD": "true", + "ZIP_FILE_PATH": "tests/samples/assets/echo-agent.zip", + "SKIP_RBAC": "true", + }, + ), + AdditionalSampleTestDetail( + test_id="sample_create_hosted_agent_from_code_async", + sample_filename="sample_create_hosted_agent_from_code_async.py", + env_vars={ + "FOUNDRY_HOSTED_AGENT_REMOTE_BUILD": "false", + "SKIP_RBAC": "true", }, ), ] @@ -214,14 +231,60 @@ async def test_chat_completions_samples(self, sample_path: str, **kwargs) -> Non "sample_path", get_async_sample_paths( "hosted_agents", - samples_to_skip=[], + samples_to_skip=[ + "sample_create_hosted_agent_async.py", # Specified through AdditionalSampleTestDetail + "sample_create_hosted_agent_from_code_async.py", # Specified through AdditionalSampleTestDetail + ], ), ) @SamplePathPasser() @recorded_by_proxy_async(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) async def test_hosted_agents_samples(self, sample_path: str, **kwargs) -> None: - if os.path.basename(sample_path).startswith("sample_create_hosted_agent") and not self.is_live: - pytest.skip("sample_create_hosted_agent.py is skipped in replay mode due to RBAC complications.") + env_vars = get_sample_env_vars(kwargs) + executor = AsyncSampleExecutor(self, sample_path, env_vars=env_vars, **kwargs) + await executor.execute_async() + await executor.validate_print_calls_by_llm_async() + + @additionalSampleTests( + [ + AdditionalSampleTestDetail( + test_id="sample_skills_upload_and_download_async", + sample_filename="sample_skills_upload_and_download_async.py", + env_vars={ + "ZIP_FILE_PATH": "tests/samples/assets/team-status-update.zip", + }, + ), + ] + ) + @pytest.mark.parametrize( + "sample_path", + get_async_sample_paths( + "skills", + samples_to_skip=[ + "sample_skills_upload_and_download_async.py", # Specified through AdditionalSampleTestDetail + ], + ), + ) + @servicePreparer() + @SamplePathPasser() + @recorded_by_proxy_async(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) + async def test_skills_samples(self, sample_path: str, **kwargs) -> None: + env_vars = get_sample_env_vars(kwargs) + executor = AsyncSampleExecutor(self, sample_path, env_vars=env_vars, **kwargs) + await executor.execute_async() + await executor.validate_print_calls_by_llm_async() + + @pytest.mark.parametrize( + "sample_path", + get_async_sample_paths( + "toolboxes", + samples_to_skip=[], + ), + ) + @servicePreparer() + @SamplePathPasser() + @recorded_by_proxy_async(RecordedTransport.AZURE_CORE, RecordedTransport.HTTPX) + async def test_toolboxes_samples(self, sample_path: str, **kwargs) -> None: env_vars = get_sample_env_vars(kwargs) executor = AsyncSampleExecutor(self, sample_path, env_vars=env_vars, **kwargs) await executor.execute_async() diff --git a/sdk/ai/azure-ai-projects/tests/samples/test_util.py b/sdk/ai/azure-ai-projects/tests/samples/test_util.py new file mode 100644 index 000000000000..b27042ad860d --- /dev/null +++ b/sdk/ai/azure-ai-projects/tests/samples/test_util.py @@ -0,0 +1,77 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +import hashlib +import io +import sys +import zipfile +from pathlib import Path + +SAMPLES_DIR = Path(__file__).resolve().parents[2] / "samples" +sys.path.insert(0, str(SAMPLES_DIR.resolve())) + +import util +from util import zip as zip_directory + + +def test_zip_writes_zip_to_temp_folder(tmp_path, monkeypatch): + source_dir = tmp_path / "source" + nested_dir = source_dir / "nested" + nested_dir.mkdir(parents=True) + (source_dir / "b.txt").write_bytes(b"bravo") + (nested_dir / "a.txt").write_bytes(b"alpha") + (source_dir / "README.md").write_bytes(b"skip") + pycache_dir = source_dir / "__pycache__" + pycache_dir.mkdir() + (pycache_dir / "module.pyc").write_bytes(b"skip") + + temp_dir = tmp_path / "temp" + temp_dir.mkdir() + monkeypatch.setattr(util.tempfile, "gettempdir", lambda: str(temp_dir)) + + zip_bytes, zip_sha256, zip_path = zip_directory(source_dir, "source.zip") + + assert zip_path == temp_dir.resolve() / "source.zip" + assert zip_path.read_bytes() == zip_bytes + assert zip_sha256 == hashlib.sha256(zip_bytes).hexdigest() + + with zipfile.ZipFile(io.BytesIO(zip_bytes), "r") as zf: + assert zf.namelist() == ["b.txt", "nested/a.txt"] + assert zf.read("b.txt") == b"bravo" + assert zf.read("nested/a.txt") == b"alpha" + + +def test_zip_loads_zip_file_from_env_var(tmp_path, monkeypatch): + source_dir = tmp_path / "source" + source_dir.mkdir() + (source_dir / "ignored.txt").write_text("ignored", encoding="utf-8") + + prebuilt_zip = tmp_path / "prebuilt.zip" + with zipfile.ZipFile(prebuilt_zip, "w", compression=zipfile.ZIP_DEFLATED) as zf: + zf.writestr("asset.txt", b"from prebuilt") + + monkeypatch.setenv("ZIP_FILE_PATH", str(prebuilt_zip)) + + zip_bytes, zip_sha256, zip_path = zip_directory(source_dir, "runtime.zip") + + assert zip_path == prebuilt_zip + assert zip_bytes == prebuilt_zip.read_bytes() + assert zip_sha256 == hashlib.sha256(zip_bytes).hexdigest() + + +def test_zip_uses_source_dir_name_for_default_zip_filename(tmp_path, monkeypatch): + source_dir = tmp_path / "canvas-design" + source_dir.mkdir() + (source_dir / "SKILL.md").write_text("# Canvas Design\n", encoding="utf-8") + + temp_dir = tmp_path / "temp" + temp_dir.mkdir() + monkeypatch.setattr(util.tempfile, "gettempdir", lambda: str(temp_dir)) + + _zip_bytes, _zip_sha256, zip_path = zip_directory(source_dir) + + assert zip_path == temp_dir.resolve() / "canvas-design.zip" + assert zip_path.exists() diff --git a/sdk/ai/azure-ai-projects/tests/sessions/test_agent_session_files_crud.py b/sdk/ai/azure-ai-projects/tests/sessions/test_agent_session_files_crud.py new file mode 100644 index 000000000000..075158fc51a2 --- /dev/null +++ b/sdk/ai/azure-ai-projects/tests/sessions/test_agent_session_files_crud.py @@ -0,0 +1,462 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +# cSpell:disable +import os +import tempfile +from pathlib import Path +from test_base import TestBase, servicePreparer +from devtools_testutils import recorded_by_proxy +from azure.ai.projects.models import VersionRefIndicator + + +class TestAgentSessionFilesCrud(TestBase): + """ + Test CRUD operations for Agent Session Files. + + These tests require a Hosted Agent to be deployed and available. + Sessions only work with Hosted Agents. + + Prerequisites: + - A Hosted Agent must be deployed and active. + - Environment variable FOUNDRY_HOSTED_AGENT_NAME must be set. + """ + + def _get_latest_active_agent_version(self, project_client, agent_name): + """Get the latest active agent version for a hosted agent.""" + for version in project_client.agents.list_versions(agent_name=agent_name, order="desc"): + if version.status == "active": + return version + raise RuntimeError( + f"No active version found for hosted agent '{agent_name}'. " + "Create or activate a version before running this test." + ) + + # To run this test: + # pytest tests\sessions\test_agent_session_files_crud.py::TestAgentSessionFilesCrud::test_agent_session_files_crud -s + @servicePreparer() + @recorded_by_proxy() + def test_agent_session_files_crud(self, **kwargs): + """ + Test CRUD operations for Agent Session Files. + + This test: + 1. Creates a session for a hosted agent + 2. Uploads two files to the session + 3. Lists files in the session and verifies the uploaded files are present + 4. Downloads a file and verifies its content + 5. Deletes both files + 6. Cleans up by deleting the session + + Routes used in this test: + + Action REST API Route Client Method + ------+---------------------------------------------------------------------------+------------------------------------------- + POST /agents/{agent_name}/sessions project_client.agents.create_session() + POST /agents/{agent_name}/sessions/{session_id}/files:upload project_client.agents.upload_session_file() + GET /agents/{agent_name}/sessions/{session_id}/files project_client.agents.list_session_files() + GET /agents/{agent_name}/sessions/{session_id}/files:download project_client.agents.download_session_file_as_bytes() + DELETE /agents/{agent_name}/sessions/{session_id}/files project_client.agents.delete_session_file() + DELETE /agents/{agent_name}/sessions/{session_id} project_client.agents.delete_session() + """ + print("\n") + + agent_name = kwargs["foundry_hosted_agent_name"] + project_client = self.create_client(**kwargs) + + # Construct paths to test data files + test_dir = os.path.dirname(os.path.abspath(__file__)) + test_data_folder = os.path.join(test_dir, "..", "test_data", "sessions") + data_file1 = os.path.join(test_data_folder, "data_file1.txt") + data_file2 = os.path.join(test_data_folder, "data_file2.txt") + data_file3 = os.path.join(test_data_folder, "data_file3.txt") + remote_file_path1 = "/remote/data_file1.txt" + remote_file_path2 = "/remote/data_file2.txt" + remote_file_path3 = "/remote/data_file3.txt" + + # Verify test data files exist + assert os.path.exists(data_file1), f"Test data file not found: {data_file1}" + assert os.path.exists(data_file2), f"Test data file not found: {data_file2}" + assert os.path.exists(data_file3), f"Test data file not found: {data_file3}" + + # Get the latest active agent version + agent = self._get_latest_active_agent_version(project_client, agent_name) + assert agent is not None, "Failed to get agent version" + assert agent.version is not None, "Agent version should not be None" + print(f"Using agent: {agent_name}, version: {agent.version}") + + # Create a session + session = project_client.agents.create_session( + agent_name=agent_name, + version_indicator=VersionRefIndicator(agent_version=agent.version), + ) + assert session is not None, "Session creation returned None" + assert session.agent_session_id is not None, "Session ID should not be None" + assert session.status is not None, "Session status should not be None" + print(f"Session created (id: {session.agent_session_id}, status: {session.status})") + + try: + # Upload first file using file_path (str) + print(f"Uploading session file: {data_file1} -> {remote_file_path1}") + project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session.agent_session_id, + file_path=data_file1, + remote_path=remote_file_path1, + ) + print(f"Successfully uploaded file to {remote_file_path1}") + + # Upload second file using file_path (PathLike[str]) + print(f"Uploading session file using PathLike: {data_file2} -> {remote_file_path2}") + project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session.agent_session_id, + file_path=Path(data_file2), + remote_path=remote_file_path2, + ) + print(f"Successfully uploaded file to {remote_file_path2}") + + # Upload third file using content (bytes) + print(f"Uploading session file using content: {data_file3} -> {remote_file_path3}") + with open(data_file3, "rb") as f: + file3_content = f.read() + project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session.agent_session_id, + content=file3_content, + remote_path=remote_file_path3, + ) + print(f"Successfully uploaded file to {remote_file_path3}") + + # List session files and verify uploaded files are present + print("Listing session files at path '/remote'...") + files = project_client.agents.list_session_files( + agent_name=agent_name, + agent_session_id=session.agent_session_id, + remote_path="/remote", + ) + + # Convert to list for verification + files_list = list(files) + assert len(files_list) >= 3, f"Expected at least 3 files, got {len(files_list)}" + + # Verify file entries + file_names = [entry.name for entry in files_list] + print(f"Files found: {file_names}") + assert "data_file1.txt" in file_names, "data_file1.txt not found in listed files" + assert "data_file2.txt" in file_names, "data_file2.txt not found in listed files" + assert "data_file3.txt" in file_names, "data_file3.txt not found in listed files" + + # Verify file properties + for entry in files_list: + print(f" - name={entry.name}, size={entry.size}, is_directory={entry.is_directory}") + assert entry.name is not None, "File name should not be None" + assert entry.size is not None, "File size should not be None" + assert entry.is_directory is not None, "is_directory should not be None" + + # -------------------------------------------------------------------------------------------------- + + # Download and verify content of first file + print(f"Downloading and verifying content from '{remote_file_path1}'") + content_bytes = b"".join( + project_client.agents.download_session_file_as_bytes( + agent_name=agent_name, + agent_session_id=session.agent_session_id, + remote_path=remote_file_path1, + ) + ) + assert content_bytes is not None, "Downloaded content should not be None" + assert len(content_bytes) > 0, "Downloaded content should not be empty" + + file_content = content_bytes.decode("utf-8", errors="replace") + print(f"Downloaded content: {file_content.strip()}") + + # Verify content matches expected + expected_content = "This is sample file 1" + assert ( + expected_content in file_content + ), f"Expected content '{expected_content}' not found in downloaded file" + print("Content verification passed!") + + # Download second file to disk using download_session_file_to_path with str file_path + temp_dir = tempfile.gettempdir() + download_path = os.path.join(temp_dir, "downloaded_data_file2_sync_test.txt") + print(f"Downloading session file to disk: {remote_file_path2} -> {download_path}") + + project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session.agent_session_id, + file_path=download_path, # str type + remote_path=remote_file_path2, + overwrite=True, + ) + print(f"Successfully downloaded file to {download_path}") + + # Verify the downloaded file exists and has expected content + assert os.path.exists(download_path), f"Downloaded file not found: {download_path}" + with open(download_path, "r", encoding="utf-8") as f: + downloaded_content = f.read() + + print(f"Downloaded content from disk: {downloaded_content.strip()}") + expected_content2 = "This is sample file 2" + assert ( + expected_content2 in downloaded_content + ), f"Expected content '{expected_content2}' not found in downloaded file" + print("download_session_file_to_path content verification passed!") + + # Clean up local temp file + if os.path.exists(download_path): + os.remove(download_path) + print(f"Cleaned up temp file: {download_path}") + + # -------------------------------------------------------------------------------------------------- + + # Download third file to disk using download_session_file_to_path with PathLike file_path + download_path3 = Path(tempfile.gettempdir()) / "downloaded_data_file3_sync_test.txt" + print(f"Downloading session file to disk using PathLike: {remote_file_path3} -> {download_path3}") + + project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session.agent_session_id, + file_path=download_path3, # PathLike[str] type + remote_path=remote_file_path3, + overwrite=True, + ) + print(f"Successfully downloaded file to {download_path3}") + + # Verify the downloaded file exists and has expected content + assert download_path3.exists(), f"Downloaded file not found: {download_path3}" + with open(download_path3, "r", encoding="utf-8") as f: + downloaded_content3 = f.read() + + print(f"Downloaded content from disk: {downloaded_content3.strip()}") + expected_content3 = "This is sample file 3" + assert ( + expected_content3 in downloaded_content3 + ), f"Expected content '{expected_content3}' not found in downloaded file" + print("download_session_file_to_path with PathLike content verification passed!") + + # Clean up local temp file + if download_path3.exists(): + download_path3.unlink() + print(f"Cleaned up temp file: {download_path3}") + + # Delete first file + print(f"Deleting session file at path: {remote_file_path1}...") + project_client.agents.delete_session_file( + agent_name=agent_name, + agent_session_id=session.agent_session_id, + remote_path=remote_file_path1, + ) + print(f"Successfully deleted {remote_file_path1}") + + # Delete second file + print(f"Deleting session file at path: {remote_file_path2}...") + project_client.agents.delete_session_file( + agent_name=agent_name, + agent_session_id=session.agent_session_id, + remote_path=remote_file_path2, + ) + print(f"Successfully deleted {remote_file_path2}") + + # Delete third file + print(f"Deleting session file at path: {remote_file_path3}...") + project_client.agents.delete_session_file( + agent_name=agent_name, + agent_session_id=session.agent_session_id, + remote_path=remote_file_path3, + ) + print(f"Successfully deleted {remote_file_path3}") + + print("All session file CRUD operations completed successfully!") + + finally: + # Clean up: delete the session + project_client.agents.delete_session( + agent_name=agent_name, + session_id=session.agent_session_id, + ) + print(f"Session deleted (id: {session.agent_session_id})") + + # To run this test: + # pytest tests\sessions\test_agent_session_files_crud.py::TestAgentSessionFilesCrud::test_agent_session_files_invalid_input -s + # These are unit-tests that do not make network calls. + @servicePreparer() + def test_agent_session_files_invalid_input(self, **kwargs): + """ + Test that upload_session_file and download_session_file_to_path raise appropriate + errors when given invalid input (non-existing files, folder paths). + + These are client-side validations that occur before any API call is made. + """ + print("\n") + + foundry_project_endpoint = "https://fake-endpoint" + agent_name = "fake-agent-name" + session_id = "fake-session-id" + + project_client = self.create_client(agent_name=agent_name, foundry_project_endpoint=foundry_project_endpoint) + + try: + # -------------------------------------------------------------------------------------------------- + # Test upload_session_file with invalid inputs + # -------------------------------------------------------------------------------------------------- + + # Test that upload_session_file raises FileNotFoundError when file_path is a non-existing file (str type) + non_existing_file_str = os.path.join(tempfile.gettempdir(), "non_existing_file_12345.txt") + print(f"Testing upload_session_file with non-existing file (str): {non_existing_file_str}") + try: + project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session_id, + file_path=non_existing_file_str, # str type pointing to non-existing file + remote_path="/remote/non_existing.txt", + ) + assert False, "Expected FileNotFoundError when file_path is a non-existing file (str type)" + except FileNotFoundError as e: + print(f"Got expected FileNotFoundError for non-existing file (str): {e}") + assert "does not exist" in str(e).lower(), f"Error message should mention 'does not exist': {e}" + + # Test that upload_session_file raises FileNotFoundError when file_path is a non-existing file (PathLike type) + non_existing_file_pathlike = Path(tempfile.gettempdir()) / "non_existing_file_12345.txt" + print(f"Testing upload_session_file with non-existing file (PathLike): {non_existing_file_pathlike}") + try: + project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session_id, + file_path=non_existing_file_pathlike, # PathLike[str] type pointing to non-existing file + remote_path="/remote/non_existing.txt", + ) + assert False, "Expected FileNotFoundError when file_path is a non-existing file (PathLike type)" + except FileNotFoundError as e: + print(f"Got expected FileNotFoundError for non-existing file (PathLike): {e}") + assert "does not exist" in str(e).lower(), f"Error message should mention 'does not exist': {e}" + + # Test that upload_session_file raises ValueError when file_path is a folder (str type) + upload_folder_path_str = tempfile.gettempdir() # This is a folder, not a file + print(f"Testing upload_session_file with folder path (str): {upload_folder_path_str}") + try: + project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session_id, + file_path=upload_folder_path_str, # str type pointing to a folder + remote_path="/remote/folder_upload.txt", + ) + assert False, "Expected ValueError when file_path is a folder (str type)" + except ValueError as e: + print(f"Got expected ValueError for folder path (str): {e}") + assert "folder" in str(e).lower(), f"Error message should mention 'folder': {e}" + + # Test that upload_session_file raises ValueError when file_path is a folder (PathLike type) + upload_folder_path_pathlike = Path(tempfile.gettempdir()) # This is a folder, not a file + print(f"Testing upload_session_file with folder path (PathLike): {upload_folder_path_pathlike}") + try: + project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session_id, + file_path=upload_folder_path_pathlike, # PathLike[str] type pointing to a folder + remote_path="/remote/folder_upload.txt", + ) + assert False, "Expected ValueError when file_path is a folder (PathLike type)" + except ValueError as e: + print(f"Got expected ValueError for folder path (PathLike): {e}") + assert "folder" in str(e).lower(), f"Error message should mention 'folder': {e}" + + print("upload_session_file error handling tests passed!") + + # -------------------------------------------------------------------------------------------------- + # Test download_session_file_to_path with invalid inputs + # -------------------------------------------------------------------------------------------------- + + # Test that download_session_file_to_path raises ValueError when file_path is a folder (str type) + folder_path_str = tempfile.gettempdir() # This is a folder, not a file + print(f"Testing download_session_file_to_path with folder path (str): {folder_path_str}") + try: + project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session_id, + file_path=folder_path_str, # str type pointing to a folder + remote_path="/remote/some_file.txt", + ) + assert False, "Expected ValueError when file_path is a folder (str type)" + except ValueError as e: + print(f"Got expected ValueError for folder path (str): {e}") + assert "folder" in str(e).lower(), f"Error message should mention 'folder': {e}" + + # Test that download_session_file_to_path raises ValueError when file_path is a folder (PathLike type) + folder_path_pathlike = Path(tempfile.gettempdir()) # This is a folder, not a file + print(f"Testing download_session_file_to_path with folder path (PathLike): {folder_path_pathlike}") + try: + project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session_id, + file_path=folder_path_pathlike, # PathLike[str] type pointing to a folder + remote_path="/remote/some_file.txt", + ) + assert False, "Expected ValueError when file_path is a folder (PathLike type)" + except ValueError as e: + print(f"Got expected ValueError for folder path (PathLike): {e}") + assert "folder" in str(e).lower(), f"Error message should mention 'folder': {e}" + + print("download_session_file_to_path folder path validation tests passed!") + + # -------------------------------------------------------------------------------------------------- + # Test download_session_file_to_path with existing file (overwrite behavior) + # -------------------------------------------------------------------------------------------------- + + # Create a temporary file that already exists + existing_file_path = os.path.join(tempfile.gettempdir(), "existing_file_for_overwrite_sync_test.txt") + with open(existing_file_path, "w", encoding="utf-8") as f: + f.write("This file already exists") + + try: + # Test that download_session_file_to_path raises FileExistsError when file exists (default overwrite=False) + print( + f"Testing download_session_file_to_path with existing file (default overwrite): {existing_file_path}" + ) + try: + project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session_id, + file_path=existing_file_path, + remote_path="/remote/some_file.txt", + ) + assert False, "Expected FileExistsError when file already exists (default overwrite=False)" + except FileExistsError as e: + print(f"Got expected FileExistsError (default overwrite): {e}") + assert "already exists" in str(e).lower(), f"Error message should mention 'already exists': {e}" + assert "overwrite=True" in str(e), f"Error message should mention 'overwrite=True': {e}" + + # Test that download_session_file_to_path raises FileExistsError when file exists with explicit overwrite=False + print( + f"Testing download_session_file_to_path with existing file (explicit overwrite=False): {existing_file_path}" + ) + try: + project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session_id, + file_path=existing_file_path, + overwrite=False, + remote_path="/remote/some_file.txt", + ) + assert False, "Expected FileExistsError when file already exists (explicit overwrite=False)" + except FileExistsError as e: + print(f"Got expected FileExistsError (explicit overwrite=False): {e}") + assert "already exists" in str(e).lower(), f"Error message should mention 'already exists': {e}" + assert "overwrite=True" in str(e), f"Error message should mention 'overwrite=True': {e}" + + print("download_session_file_to_path overwrite validation tests passed!") + + finally: + # Clean up the temporary file + if os.path.exists(existing_file_path): + os.remove(existing_file_path) + print(f"Cleaned up temp file: {existing_file_path}") + + print("All invalid input tests passed!") + + finally: + # Add any cleanup here + ... diff --git a/sdk/ai/azure-ai-projects/tests/sessions/test_agent_session_files_crud_async.py b/sdk/ai/azure-ai-projects/tests/sessions/test_agent_session_files_crud_async.py new file mode 100644 index 000000000000..9e352b53eec5 --- /dev/null +++ b/sdk/ai/azure-ai-projects/tests/sessions/test_agent_session_files_crud_async.py @@ -0,0 +1,468 @@ +# pylint: disable=line-too-long,useless-suppression +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +# cSpell:disable +import os +import tempfile +from pathlib import Path +from test_base import TestBase, servicePreparer +from devtools_testutils.aio import recorded_by_proxy_async +from azure.ai.projects.models import VersionRefIndicator + + +class TestAgentSessionFilesCrudAsync(TestBase): + """ + Test CRUD operations for Agent Session Files (Async). + + These tests require a Hosted Agent to be deployed and available. + Sessions only work with Hosted Agents. + + Prerequisites: + - A Hosted Agent must be deployed and active. + - Environment variable FOUNDRY_HOSTED_AGENT_NAME must be set. + """ + + async def _get_latest_active_agent_version_async(self, project_client, agent_name): + """Get the latest active agent version for a hosted agent (async).""" + async for version in project_client.agents.list_versions(agent_name=agent_name, order="desc"): + if version.status == "active": + return version + raise RuntimeError( + f"No active version found for hosted agent '{agent_name}'. " + "Create or activate a version before running this test." + ) + + # To run this test: + # pytest tests\sessions\test_agent_session_files_crud_async.py::TestAgentSessionFilesCrudAsync::test_agent_session_files_crud_async -s + @servicePreparer() + @recorded_by_proxy_async() + async def test_agent_session_files_crud_async(self, **kwargs): + """ + Test CRUD operations for Agent Session Files (Async). + + This test: + 1. Creates a session for a hosted agent + 2. Uploads two files to the session + 3. Lists files in the session and verifies the uploaded files are present + 4. Downloads a file and verifies its content + 5. Deletes both files + 6. Cleans up by deleting the session + + Routes used in this test: + + Action REST API Route Client Method + ------+---------------------------------------------------------------------------+------------------------------------------- + POST /agents/{agent_name}/sessions project_client.agents.create_session() + POST /agents/{agent_name}/sessions/{session_id}/files:upload project_client.agents.upload_session_file() + GET /agents/{agent_name}/sessions/{session_id}/files project_client.agents.list_session_files() + GET /agents/{agent_name}/sessions/{session_id}/files:download project_client.agents.download_session_file_as_bytes() + DELETE /agents/{agent_name}/sessions/{session_id}/files project_client.agents.delete_session_file() + DELETE /agents/{agent_name}/sessions/{session_id} project_client.agents.delete_session() + """ + print("\n") + + agent_name = kwargs["foundry_hosted_agent_name"] + project_client = self.create_async_client(**kwargs) + + # Construct paths to test data files + test_dir = os.path.dirname(os.path.abspath(__file__)) + test_data_folder = os.path.join(test_dir, "..", "test_data", "sessions") + data_file1 = os.path.join(test_data_folder, "data_file1.txt") + data_file2 = os.path.join(test_data_folder, "data_file2.txt") + data_file3 = os.path.join(test_data_folder, "data_file3.txt") + remote_file_path1 = "/remote/data_file1.txt" + remote_file_path2 = "/remote/data_file2.txt" + remote_file_path3 = "/remote/data_file3.txt" + + # Verify test data files exist + assert os.path.exists(data_file1), f"Test data file not found: {data_file1}" + assert os.path.exists(data_file2), f"Test data file not found: {data_file2}" + assert os.path.exists(data_file3), f"Test data file not found: {data_file3}" + + async with project_client: + # Get the latest active agent version + agent = await self._get_latest_active_agent_version_async(project_client, agent_name) + assert agent is not None, "Failed to get agent version" + assert agent.version is not None, "Agent version should not be None" + print(f"Using agent: {agent_name}, version: {agent.version}") + + # Create a session + session = await project_client.agents.create_session( + agent_name=agent_name, + version_indicator=VersionRefIndicator(agent_version=agent.version), + ) + assert session is not None, "Session creation returned None" + assert session.agent_session_id is not None, "Session ID should not be None" + assert session.status is not None, "Session status should not be None" + print(f"Session created (id: {session.agent_session_id}, status: {session.status})") + + try: + # Upload first file using file_path (str) + print(f"Uploading session file: {data_file1} -> {remote_file_path1}") + await project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session.agent_session_id, + file_path=data_file1, + remote_path=remote_file_path1, + ) + print(f"Successfully uploaded file to {remote_file_path1}") + + # Upload second file using file_path (PathLike[str]) + print(f"Uploading session file using PathLike: {data_file2} -> {remote_file_path2}") + await project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session.agent_session_id, + file_path=Path(data_file2), + remote_path=remote_file_path2, + ) + print(f"Successfully uploaded file to {remote_file_path2}") + + # Upload third file using content (bytes) + print(f"Uploading session file using content: {data_file3} -> {remote_file_path3}") + with open(data_file3, "rb") as f: + file3_content = f.read() + await project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session.agent_session_id, + content=file3_content, + remote_path=remote_file_path3, + ) + print(f"Successfully uploaded file to {remote_file_path3}") + + # List session files and verify uploaded files are present + print("Listing session files at path '/remote'...") + files_list = [] + async for entry in project_client.agents.list_session_files( + agent_name=agent_name, + agent_session_id=session.agent_session_id, + remote_path="/remote", + ): + files_list.append(entry) + + assert len(files_list) >= 3, f"Expected at least 3 files, got {len(files_list)}" + + # Verify file entries + file_names = [entry.name for entry in files_list] + print(f"Files found: {file_names}") + assert "data_file1.txt" in file_names, "data_file1.txt not found in listed files" + assert "data_file2.txt" in file_names, "data_file2.txt not found in listed files" + assert "data_file3.txt" in file_names, "data_file3.txt not found in listed files" + + # Verify file properties + for entry in files_list: + print(f" - name={entry.name}, size={entry.size}, is_directory={entry.is_directory}") + assert entry.name is not None, "File name should not be None" + assert entry.size is not None, "File size should not be None" + assert entry.is_directory is not None, "is_directory should not be None" + + # Download and verify content of first file + print(f"Downloading and verifying content from '{remote_file_path1}'") + content_chunks = [] + download_iterator = await project_client.agents.download_session_file_as_bytes( + agent_name=agent_name, + agent_session_id=session.agent_session_id, + remote_path=remote_file_path1, + ) + async for chunk in download_iterator: + content_chunks.append(chunk) + content_bytes = b"".join(content_chunks) + + assert content_bytes is not None, "Downloaded content should not be None" + assert len(content_bytes) > 0, "Downloaded content should not be empty" + + file_content = content_bytes.decode("utf-8", errors="replace") + print(f"Downloaded content: {file_content.strip()}") + + # Verify content matches expected + expected_content = "This is sample file 1" + assert ( + expected_content in file_content + ), f"Expected content '{expected_content}' not found in downloaded file" + print("Content verification passed!") + + # Download second file to disk using download_session_file_to_path with str file_path + temp_dir = tempfile.gettempdir() + download_path = os.path.join(temp_dir, "downloaded_data_file2_async_test.txt") + print(f"Downloading session file to disk: {remote_file_path2} -> {download_path}") + + await project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session.agent_session_id, + file_path=download_path, # str type + remote_path=remote_file_path2, + overwrite=True, + ) + print(f"Successfully downloaded file to {download_path}") + + # Verify the downloaded file exists and has expected content + assert os.path.exists(download_path), f"Downloaded file not found: {download_path}" + with open(download_path, "r", encoding="utf-8") as f: + downloaded_content = f.read() + + print(f"Downloaded content from disk: {downloaded_content.strip()}") + expected_content2 = "This is sample file 2" + assert ( + expected_content2 in downloaded_content + ), f"Expected content '{expected_content2}' not found in downloaded file" + print("download_session_file_to_path content verification passed!") + + # Clean up local temp file + if os.path.exists(download_path): + os.remove(download_path) + print(f"Cleaned up temp file: {download_path}") + + # -------------------------------------------------------------------------------------------------- + + # Download third file to disk using download_session_file_to_path with PathLike file_path + download_path3 = Path(tempfile.gettempdir()) / "downloaded_data_file3_async_test.txt" + print(f"Downloading session file to disk using PathLike: {remote_file_path3} -> {download_path3}") + + await project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session.agent_session_id, + file_path=download_path3, # PathLike[str] type + remote_path=remote_file_path3, + overwrite=True, + ) + print(f"Successfully downloaded file to {download_path3}") + + # Verify the downloaded file exists and has expected content + assert download_path3.exists(), f"Downloaded file not found: {download_path3}" + with open(download_path3, "r", encoding="utf-8") as f: + downloaded_content3 = f.read() + + print(f"Downloaded content from disk: {downloaded_content3.strip()}") + expected_content3 = "This is sample file 3" + assert ( + expected_content3 in downloaded_content3 + ), f"Expected content '{expected_content3}' not found in downloaded file" + print("download_session_file_to_path with PathLike content verification passed!") + + # Clean up local temp file + if download_path3.exists(): + download_path3.unlink() + print(f"Cleaned up temp file: {download_path3}") + + # Delete first file + print(f"Deleting session file at path: {remote_file_path1}...") + await project_client.agents.delete_session_file( + agent_name=agent_name, + agent_session_id=session.agent_session_id, + remote_path=remote_file_path1, + ) + print(f"Successfully deleted {remote_file_path1}") + + # Delete second file + print(f"Deleting session file at path: {remote_file_path2}...") + await project_client.agents.delete_session_file( + agent_name=agent_name, + agent_session_id=session.agent_session_id, + remote_path=remote_file_path2, + ) + print(f"Successfully deleted {remote_file_path2}") + + # Delete third file + print(f"Deleting session file at path: {remote_file_path3}...") + await project_client.agents.delete_session_file( + agent_name=agent_name, + agent_session_id=session.agent_session_id, + remote_path=remote_file_path3, + ) + print(f"Successfully deleted {remote_file_path3}") + + print("All session file CRUD operations completed successfully!") + + finally: + # Clean up: delete the session + await project_client.agents.delete_session( + agent_name=agent_name, + session_id=session.agent_session_id, + ) + print(f"Session deleted (id: {session.agent_session_id})") + + # To run this test: + # pytest tests\sessions\test_agent_session_files_crud_async.py::TestAgentSessionFilesCrudAsync::test_agent_session_files_invalid_input_async -s + # These are unit-tests that do not make network calls. + @servicePreparer() + async def test_agent_session_files_invalid_input_async(self, **kwargs): + """ + Test that upload_session_file and download_session_file_to_path raise appropriate + errors when given invalid input (non-existing files, folder paths). + + These are client-side validations that occur before any API call is made. + """ + print("\n") + + foundry_project_endpoint = "https://fake-endpoint" + agent_name = "fake-agent-name" + session_id = "fake-session-id" + + project_client = self.create_async_client( + agent_name=agent_name, foundry_project_endpoint=foundry_project_endpoint + ) + + async with project_client: + + try: + # -------------------------------------------------------------------------------------------------- + # Test upload_session_file with invalid inputs + # -------------------------------------------------------------------------------------------------- + + # Test that upload_session_file raises FileNotFoundError when file_path is a non-existing file (str type) + non_existing_file_str = os.path.join(tempfile.gettempdir(), "non_existing_file_12345.txt") + print(f"Testing upload_session_file with non-existing file (str): {non_existing_file_str}") + try: + await project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session_id, + file_path=non_existing_file_str, # str type pointing to non-existing file + remote_path="/remote/non_existing.txt", + ) + assert False, "Expected FileNotFoundError when file_path is a non-existing file (str type)" + except FileNotFoundError as e: + print(f"Got expected FileNotFoundError for non-existing file (str): {e}") + assert "does not exist" in str(e).lower(), f"Error message should mention 'does not exist': {e}" + + # Test that upload_session_file raises FileNotFoundError when file_path is a non-existing file (PathLike type) + non_existing_file_pathlike = Path(tempfile.gettempdir()) / "non_existing_file_12345.txt" + print(f"Testing upload_session_file with non-existing file (PathLike): {non_existing_file_pathlike}") + try: + await project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session_id, + file_path=non_existing_file_pathlike, # PathLike[str] type pointing to non-existing file + remote_path="/remote/non_existing.txt", + ) + assert False, "Expected FileNotFoundError when file_path is a non-existing file (PathLike type)" + except FileNotFoundError as e: + print(f"Got expected FileNotFoundError for non-existing file (PathLike): {e}") + assert "does not exist" in str(e).lower(), f"Error message should mention 'does not exist': {e}" + + # Test that upload_session_file raises ValueError when file_path is a folder (str type) + upload_folder_path_str = tempfile.gettempdir() # This is a folder, not a file + print(f"Testing upload_session_file with folder path (str): {upload_folder_path_str}") + try: + await project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session_id, + file_path=upload_folder_path_str, # str type pointing to a folder + remote_path="/remote/folder_upload.txt", + ) + assert False, "Expected ValueError when file_path is a folder (str type)" + except ValueError as e: + print(f"Got expected ValueError for folder path (str): {e}") + assert "folder" in str(e).lower(), f"Error message should mention 'folder': {e}" + + # Test that upload_session_file raises ValueError when file_path is a folder (PathLike type) + upload_folder_path_pathlike = Path(tempfile.gettempdir()) # This is a folder, not a file + print(f"Testing upload_session_file with folder path (PathLike): {upload_folder_path_pathlike}") + try: + await project_client.agents.upload_session_file( + agent_name=agent_name, + session_id=session_id, + file_path=upload_folder_path_pathlike, # PathLike[str] type pointing to a folder + remote_path="/remote/folder_upload.txt", + ) + assert False, "Expected ValueError when file_path is a folder (PathLike type)" + except ValueError as e: + print(f"Got expected ValueError for folder path (PathLike): {e}") + assert "folder" in str(e).lower(), f"Error message should mention 'folder': {e}" + + print("upload_session_file error handling tests passed!") + + # -------------------------------------------------------------------------------------------------- + # Test download_session_file_to_path with invalid inputs + # -------------------------------------------------------------------------------------------------- + + # Test that download_session_file_to_path raises ValueError when file_path is a folder (str type) + folder_path_str = tempfile.gettempdir() # This is a folder, not a file + print(f"Testing download_session_file_to_path with folder path (str): {folder_path_str}") + try: + await project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session_id, + file_path=folder_path_str, # str type pointing to a folder + remote_path="/remote/some_file.txt", + ) + assert False, "Expected ValueError when file_path is a folder (str type)" + except ValueError as e: + print(f"Got expected ValueError for folder path (str): {e}") + assert "folder" in str(e).lower(), f"Error message should mention 'folder': {e}" + + # Test that download_session_file_to_path raises ValueError when file_path is a folder (PathLike type) + folder_path_pathlike = Path(tempfile.gettempdir()) # This is a folder, not a file + print(f"Testing download_session_file_to_path with folder path (PathLike): {folder_path_pathlike}") + try: + await project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session_id, + file_path=folder_path_pathlike, # PathLike[str] type pointing to a folder + remote_path="/remote/some_file.txt", + ) + assert False, "Expected ValueError when file_path is a folder (PathLike type)" + except ValueError as e: + print(f"Got expected ValueError for folder path (PathLike): {e}") + assert "folder" in str(e).lower(), f"Error message should mention 'folder': {e}" + + print("download_session_file_to_path folder path validation tests passed!") + + # -------------------------------------------------------------------------------------------------- + # Test download_session_file_to_path with existing file (overwrite behavior) + # -------------------------------------------------------------------------------------------------- + + # Create a temporary file that already exists + existing_file_path = os.path.join(tempfile.gettempdir(), "existing_file_for_overwrite_async_test.txt") + with open(existing_file_path, "w", encoding="utf-8") as f: + f.write("This file already exists") + + try: + # Test that download_session_file_to_path raises FileExistsError when file exists (default overwrite=False) + print( + f"Testing download_session_file_to_path with existing file (default overwrite): {existing_file_path}" + ) + try: + await project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session_id, + file_path=existing_file_path, + remote_path="/remote/some_file.txt", + ) + assert False, "Expected FileExistsError when file already exists (default overwrite=False)" + except FileExistsError as e: + print(f"Got expected FileExistsError (default overwrite): {e}") + assert "already exists" in str(e).lower(), f"Error message should mention 'already exists': {e}" + assert "overwrite=True" in str(e), f"Error message should mention 'overwrite=True': {e}" + + # Test that download_session_file_to_path raises FileExistsError when file exists with explicit overwrite=False + print( + f"Testing download_session_file_to_path with existing file (explicit overwrite=False): {existing_file_path}" + ) + try: + await project_client.agents.download_session_file_to_path( + agent_name=agent_name, + session_id=session_id, + file_path=existing_file_path, + overwrite=False, + remote_path="/remote/some_file.txt", + ) + assert False, "Expected FileExistsError when file already exists (explicit overwrite=False)" + except FileExistsError as e: + print(f"Got expected FileExistsError (explicit overwrite=False): {e}") + assert "already exists" in str(e).lower(), f"Error message should mention 'already exists': {e}" + assert "overwrite=True" in str(e), f"Error message should mention 'overwrite=True': {e}" + + print("download_session_file_to_path overwrite validation tests passed!") + + finally: + # Clean up the temporary file + if os.path.exists(existing_file_path): + os.remove(existing_file_path) + print(f"Cleaned up temp file: {existing_file_path}") + + print("All invalid input tests passed!") + + finally: + # Add any cleanup here + ... diff --git a/sdk/ai/azure-ai-projects/tests/test_data/sessions/.gitattributes b/sdk/ai/azure-ai-projects/tests/test_data/sessions/.gitattributes new file mode 100644 index 000000000000..29227928d2b0 --- /dev/null +++ b/sdk/ai/azure-ai-projects/tests/test_data/sessions/.gitattributes @@ -0,0 +1,8 @@ +# Force LF line endings for session file test text files to ensure consistent binary representation +# across Windows and Linux platforms. +# +# These files are uploaded as binary request payloads in session file tests. +# Without consistent line endings, payload bytes differ between platforms, +# causing test-proxy playback body mismatches. + +*.txt text eol=lf diff --git a/sdk/ai/azure-ai-projects/tests/test_data/sessions/data_file1.txt b/sdk/ai/azure-ai-projects/tests/test_data/sessions/data_file1.txt new file mode 100644 index 000000000000..e129759a15ff --- /dev/null +++ b/sdk/ai/azure-ai-projects/tests/test_data/sessions/data_file1.txt @@ -0,0 +1 @@ +This is sample file 1 diff --git a/sdk/ai/azure-ai-projects/tests/test_data/sessions/data_file2.txt b/sdk/ai/azure-ai-projects/tests/test_data/sessions/data_file2.txt new file mode 100644 index 000000000000..3dd74cdfc9eb --- /dev/null +++ b/sdk/ai/azure-ai-projects/tests/test_data/sessions/data_file2.txt @@ -0,0 +1 @@ +This is sample file 2 diff --git a/sdk/ai/azure-ai-projects/tests/test_data/sessions/data_file3.txt b/sdk/ai/azure-ai-projects/tests/test_data/sessions/data_file3.txt new file mode 100644 index 000000000000..dde35c02f5a4 --- /dev/null +++ b/sdk/ai/azure-ai-projects/tests/test_data/sessions/data_file3.txt @@ -0,0 +1 @@ +This is sample file 3 diff --git a/sdk/ai/azure-ai-projects/tsp-location.yaml b/sdk/ai/azure-ai-projects/tsp-location.yaml new file mode 100644 index 000000000000..1bc32f47c8a5 --- /dev/null +++ b/sdk/ai/azure-ai-projects/tsp-location.yaml @@ -0,0 +1,29 @@ +directory: specification/ai-foundry/data-plane/Foundry/src/sdk-python-js-azure-ai-projects +commit: 4f887f370f1bef899f5db67a18df7ba9cbfac7de +repo: Azure/azure-rest-api-specs +additionalDirectories: + - specification/ai-foundry/data-plane/Foundry/src/agents + - specification/ai-foundry/data-plane/Foundry/src/agents-optimization + - specification/ai-foundry/data-plane/Foundry/src/agents-session-files + - specification/ai-foundry/data-plane/Foundry/src/common + - specification/ai-foundry/data-plane/Foundry/src/connections + - specification/ai-foundry/data-plane/Foundry/src/data_generation_jobs + - specification/ai-foundry/data-plane/Foundry/src/datasets + - specification/ai-foundry/data-plane/Foundry/src/deployments + - specification/ai-foundry/data-plane/Foundry/src/evaluation-rules + - specification/ai-foundry/data-plane/Foundry/src/evaluation-taxonomies + - specification/ai-foundry/data-plane/Foundry/src/evaluators + - specification/ai-foundry/data-plane/Foundry/src/indexes + - specification/ai-foundry/data-plane/Foundry/src/insights + - specification/ai-foundry/data-plane/Foundry/src/memory-stores + - specification/ai-foundry/data-plane/Foundry/src/models + - specification/ai-foundry/data-plane/Foundry/src/openai-conversations + - specification/ai-foundry/data-plane/Foundry/src/openai-evaluations + - specification/ai-foundry/data-plane/Foundry/src/openai-responses + - specification/ai-foundry/data-plane/Foundry/src/red-teams + - specification/ai-foundry/data-plane/Foundry/src/routines + - specification/ai-foundry/data-plane/Foundry/src/schedules + - specification/ai-foundry/data-plane/Foundry/src/sdk-common + - specification/ai-foundry/data-plane/Foundry/src/skills + - specification/ai-foundry/data-plane/Foundry/src/toolboxes + - specification/ai-foundry/data-plane/Foundry/src/tools diff --git a/sdk/ai/azure-ai-projects/tsp-location.yaml.saved b/sdk/ai/azure-ai-projects/tsp-location.yaml.saved deleted file mode 100644 index ce66d3088118..000000000000 --- a/sdk/ai/azure-ai-projects/tsp-location.yaml.saved +++ /dev/null @@ -1,4 +0,0 @@ -directory: specification/ai-foundry/data-plane/Foundry -commit: e041b5a178996b62fe86a267dc468df5c1677c54 -repo: Azure/azure-rest-api-specs -additionalDirectories: