diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e19e00ae..6f232a132 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1469,5 +1469,3 @@ * @idelsink made their first contribution * @dependabot[bot] made their first contribution * @ari-nz made their first contribution - - diff --git a/Makefile b/Makefile index c90107fe5..39d38ae63 100644 --- a/Makefile +++ b/Makefile @@ -177,7 +177,7 @@ codegen: # fix resource patch # in codegen/out/public_api.py replace all occurrences of resource_path='/v1 with resource_path='/api/v1 # Use portable sed syntax: -i'' works on both macOS and Linux - sed -i"" "s|resource_path='/v1|resource_path='/api/v1|g" codegen/out/aignx/codegen/api/public_api.py + sed -i "" "s|resource_path='/v1|resource_path='/api/v1|g" codegen/out/aignx/codegen/api/public_api.py # Special rule to catch any arguments (like patch, minor, major, pdf, Python versions, or x.y.z) # This prevents "No rule to make target" errors when passing arguments to make commands diff --git a/codegen/in/archive/openapi_1.4.0.json b/codegen/in/archive/openapi_1.4.0.json new file mode 100644 index 000000000..cae9e0200 --- /dev/null +++ b/codegen/in/archive/openapi_1.4.0.json @@ -0,0 +1,2970 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Aignostics Platform API", + "description": "\nThe Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. \n\nTo begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. \n\nMore information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com).\n\n**How to authorize and test API endpoints:**\n\n1. Click the \"Authorize\" button in the right corner below\n3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials\n4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint\n\n**Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized.\n\n", + "version": "1.4.0" + }, + "servers": [ + { + "url": "/api" + } + ], + "paths": { + "/v1/applications": { + "get": { + "tags": [ + "Public" + ], + "summary": "List available applications", + "description": "Returns the list of the applications, available to the caller.\n\nThe application is available if any of the versions of the application is assigned to the caller's organization.\nThe response is paginated and sorted according to the provided parameters.", + "operationId": "list_applications_v1_applications_get", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "default": 1, + "title": "Page" + } + }, + { + "name": "page-size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 5, + "default": 50, + "title": "Page-Size" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Sort the results by one or more fields. Use `+` for ascending and `-` for descending order.\n\n**Available fields:**\n- `application_id`\n- `name`\n- `description`\n- `regulatory_classes`\n\n**Examples:**\n- `?sort=application_id` - Sort by application_id ascending\n- `?sort=-name` - Sort by name descending\n- `?sort=+description&sort=name` - Sort by description ascending, then name descending", + "title": "Sort" + }, + "description": "Sort the results by one or more fields. Use `+` for ascending and `-` for descending order.\n\n**Available fields:**\n- `application_id`\n- `name`\n- `description`\n- `regulatory_classes`\n\n**Examples:**\n- `?sort=application_id` - Sort by application_id ascending\n- `?sort=-name` - Sort by name descending\n- `?sort=+description&sort=name` - Sort by description ascending, then name descending" + } + ], + "responses": { + "200": { + "description": "A list of applications available to the caller", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApplicationReadShortResponse" + }, + "title": "Response List Applications V1 Applications Get" + }, + "example": [ + { + "application_id": "he-tme", + "name": "Atlas H&E-TME", + "regulatory_classes": [ + "RUO" + ], + "description": "The Atlas H&E TME is an AI application designed to examine FFPE (formalin-fixed, paraffin-embedded) tissues stained with H&E (hematoxylin and eosin), delivering comprehensive insights into the tumor microenvironment.", + "latest_version": { + "number": "1.0.0", + "released_at": "2025-09-01T19:01:05.401Z" + } + }, + { + "application_id": "test-app", + "name": "Test Application", + "regulatory_classes": [ + "RUO" + ], + "description": "This is the test application with two algorithms: TissueQc and Tissue Segmentation", + "latest_version": { + "number": "2.0.0", + "released_at": "2025-09-02T19:01:05.401Z" + } + } + ] + } + } + }, + "401": { + "description": "Unauthorized - Invalid or missing authentication" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/applications/{application_id}": { + "get": { + "tags": [ + "Public" + ], + "summary": "Read Application By Id", + "description": "Retrieve details of a specific application by its ID.", + "operationId": "read_application_by_id_v1_applications__application_id__get", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "application_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Application Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApplicationReadResponse" + } + } + } + }, + "403": { + "description": "Forbidden - You don't have permission to see this application" + }, + "404": { + "description": "Not Found - Application with the given ID does not exist" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/applications/{application_id}/versions/{version}": { + "get": { + "tags": [ + "Public" + ], + "summary": "Application Version Details", + "description": "Get the application version details.\n\nAllows caller to retrieve information about application version based on provided application version ID.", + "operationId": "application_version_details_v1_applications__application_id__versions__version__get", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "application_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Application Id" + } + }, + { + "name": "version", + "in": "path", + "required": true, + "schema": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", + "title": "Version" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionReadResponse" + }, + "example": { + "version_number": "0.4.4", + "changelog": "New deployment", + "input_artifacts": [ + { + "name": "whole_slide_image", + "mime_type": "image/tiff", + "metadata_schema": { + "type": "object", + "$defs": { + "LungCancerMetadata": { + "type": "object", + "title": "LungCancerMetadata", + "required": [ + "type", + "tissue" + ], + "properties": { + "type": { + "enum": [ + "lung" + ], + "type": "string", + "const": "lung", + "title": "Type" + }, + "tissue": { + "enum": [ + "lung", + "lymph node", + "liver", + "adrenal gland", + "bone", + "brain" + ], + "type": "string", + "title": "Tissue" + } + }, + "additionalProperties": false + } + }, + "title": "ExternalImageMetadata", + "$schema": "http://json-schema.org/draft-07/schema#", + "required": [ + "checksum_crc32c", + "base_mpp", + "width", + "height", + "cancer" + ], + "properties": { + "stain": { + "enum": [ + "H&E" + ], + "type": "string", + "const": "H&E", + "title": "Stain", + "default": "H&E" + }, + "width": { + "type": "integer", + "title": "Width", + "maximum": 150000, + "minimum": 1 + }, + "cancer": { + "anyOf": [ + { + "$ref": "#/$defs/LungCancerMetadata" + } + ], + "title": "Cancer" + }, + "height": { + "type": "integer", + "title": "Height", + "maximum": 150000, + "minimum": 1 + }, + "base_mpp": { + "type": "number", + "title": "Base Mpp", + "maximum": 0.5, + "minimum": 0.125 + }, + "mime_type": { + "enum": [ + "application/dicom", + "image/tiff" + ], + "type": "string", + "title": "Mime Type", + "default": "image/tiff" + }, + "checksum_crc32c": { + "type": "string", + "title": "Checksum Crc32C" + } + }, + "description": "Metadata corresponding to an external image.", + "additionalProperties": false + } + } + ], + "output_artifacts": [ + { + "name": "tissue_qc:tiff_heatmap", + "mime_type": "image/tiff", + "metadata_schema": { + "type": "object", + "title": "HeatmapMetadata", + "$schema": "http://json-schema.org/draft-07/schema#", + "required": [ + "checksum_crc32c", + "width", + "height", + "class_colors" + ], + "properties": { + "width": { + "type": "integer", + "title": "Width" + }, + "height": { + "type": "integer", + "title": "Height" + }, + "base_mpp": { + "type": "number", + "title": "Base Mpp", + "maximum": 0.5, + "minimum": 0.125 + }, + "mime_type": { + "enum": [ + "image/tiff" + ], + "type": "string", + "const": "image/tiff", + "title": "Mime Type", + "default": "image/tiff" + }, + "class_colors": { + "type": "object", + "title": "Class Colors", + "additionalProperties": { + "type": "array", + "maxItems": 3, + "minItems": 3, + "prefixItems": [ + { + "type": "integer", + "maximum": 255, + "minimum": 0 + }, + { + "type": "integer", + "maximum": 255, + "minimum": 0 + }, + { + "type": "integer", + "maximum": 255, + "minimum": 0 + } + ] + } + }, + "checksum_crc32c": { + "type": "string", + "title": "Checksum Crc32C" + } + }, + "description": "Metadata corresponding to a segmentation heatmap file.", + "additionalProperties": false + }, + "scope": "ITEM", + "visibility": "EXTERNAL" + } + ], + "released_at": "2025-04-16T08:45:20.655972Z" + } + } + } + }, + "403": { + "description": "Forbidden - You don't have permission to see this version" + }, + "404": { + "description": "Not Found - Application version with given ID is not available to you or does not exist" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/runs": { + "get": { + "tags": [ + "Public" + ], + "summary": "List Runs", + "description": "List runs with filtering, sorting, and pagination capabilities.\n\nReturns paginated runs that were submitted by the user.", + "operationId": "list_runs_v1_runs_get", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "application_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional application ID filter", + "examples": [ + "tissue-segmentation", + "heta" + ], + "title": "Application Id" + }, + "description": "Optional application ID filter" + }, + { + "name": "application_version", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optional Version Name", + "examples": [ + "1.0.2", + "1.0.1-beta2" + ], + "title": "Application Version" + }, + "description": "Optional Version Name" + }, + { + "name": "external_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Optionally filter runs by items with this external ID", + "examples": [ + "slide_001", + "patient_12345_sample_A" + ], + "title": "External Id" + }, + "description": "Optionally filter runs by items with this external ID" + }, + { + "name": "custom_metadata", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "maxLength": 1000 + }, + { + "type": "null" + } + ], + "description": "Use PostgreSQL JSONPath expressions to filter runs by their custom_metadata.\n#### URL Encoding Required\n**Important**: JSONPath expressions contain special characters that must be URL-encoded when used in query parameters. Most HTTP clients handle this automatically, but when constructing URLs manually, please ensure proper encoding.\n\n#### Examples (Clear Format):\n- **Field existence**: `$.study` - Runs that have a study field defined\n- **Exact value match**: `$.study ? (@ == \"high\")` - Runs with specific study value\n- **Numeric comparison**: `$.confidence_score ? (@ > 0.75)` - Runs with confidence score greater than 0.75\n- **Array operations**: `$.tags[*] ? (@ == \"draft\")` - Runs with tags array containing \"draft\"\n- **Complex conditions**: `$.resources ? (@.gpu_count > 2 && @.memory_gb >= 16)` - Runs with high resource requirements\n\n#### Examples (URL-Encoded Format):\n- **Field existence**: `%24.study`\n- **Exact value match**: `%24.study%20%3F%20(%40%20%3D%3D%20%22high%22)`\n- **Numeric comparison**: `%24.confidence_score%20%3F%20(%40%20%3E%200.75)`\n- **Array operations**: `%24.tags%5B*%5D%20%3F%20(%40%20%3D%3D%20%22draft%22)`\n- **Complex conditions**: `%24.resources%20%3F%20(%40.gpu_count%20%3E%202%20%26%26%20%40.memory_gb%20%3E%3D%2016)`\n\n#### Notes\n- JSONPath expressions are evaluated using PostgreSQL's `@?` operator\n- The `$.` prefix is automatically added to root-level field references if missing\n- String values in conditions must be enclosed in double quotes\n- Use `&&` for AND operations and `||` for OR operations\n- Regular expressions use `like_regex` with standard regex syntax\n- **Please remember to URL-encode the entire JSONPath expression when making HTTP requests**\n\n ", + "title": "Custom Metadata" + }, + "description": "Use PostgreSQL JSONPath expressions to filter runs by their custom_metadata.\n#### URL Encoding Required\n**Important**: JSONPath expressions contain special characters that must be URL-encoded when used in query parameters. Most HTTP clients handle this automatically, but when constructing URLs manually, please ensure proper encoding.\n\n#### Examples (Clear Format):\n- **Field existence**: `$.study` - Runs that have a study field defined\n- **Exact value match**: `$.study ? (@ == \"high\")` - Runs with specific study value\n- **Numeric comparison**: `$.confidence_score ? (@ > 0.75)` - Runs with confidence score greater than 0.75\n- **Array operations**: `$.tags[*] ? (@ == \"draft\")` - Runs with tags array containing \"draft\"\n- **Complex conditions**: `$.resources ? (@.gpu_count > 2 && @.memory_gb >= 16)` - Runs with high resource requirements\n\n#### Examples (URL-Encoded Format):\n- **Field existence**: `%24.study`\n- **Exact value match**: `%24.study%20%3F%20(%40%20%3D%3D%20%22high%22)`\n- **Numeric comparison**: `%24.confidence_score%20%3F%20(%40%20%3E%200.75)`\n- **Array operations**: `%24.tags%5B*%5D%20%3F%20(%40%20%3D%3D%20%22draft%22)`\n- **Complex conditions**: `%24.resources%20%3F%20(%40.gpu_count%20%3E%202%20%26%26%20%40.memory_gb%20%3E%3D%2016)`\n\n#### Notes\n- JSONPath expressions are evaluated using PostgreSQL's `@?` operator\n- The `$.` prefix is automatically added to root-level field references if missing\n- String values in conditions must be enclosed in double quotes\n- Use `&&` for AND operations and `||` for OR operations\n- Regular expressions use `like_regex` with standard regex syntax\n- **Please remember to URL-encode the entire JSONPath expression when making HTTP requests**\n\n ", + "examples": { + "no_filter": { + "summary": "No filter (returns all)", + "description": "Returns all items without filtering by custom metadata", + "value": "$" + }, + "field_exists": { + "summary": "Check if field exists", + "description": "Find applications that have a project field defined", + "value": "$.study" + }, + "field_has_value": { + "summary": "Check if field has a certain value", + "description": "Compare a field value against a certain value", + "value": "$.study ? (@ == \"abc-1\")" + }, + "numeric_comparisons": { + "summary": "Compare to a numeric value of a field", + "description": "Compare a field value against a numeric value of a field", + "value": "$.confidence_score ? (@ > 0.75)" + }, + "array_operations": { + "summary": "Check if an array contains a certain value", + "description": "Check if an array contains a certain value", + "value": "$.tags[*] ? (@ == \"draft\")" + }, + "complex_filters": { + "summary": "Combine multiple checks", + "description": "Combine multiple checks", + "value": "$.resources ? (@.gpu_count > 2 && @.memory_gb >= 16)" + } + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "default": 1, + "title": "Page" + } + }, + { + "name": "page_size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 5, + "default": 50, + "title": "Page Size" + } + }, + { + "name": "for_organization", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs.", + "title": "For Organization" + }, + "description": "Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs." + }, + { + "name": "sort", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Sort the results by one or more fields. Use `+` for ascending and `-` for descending order.\n\n**Available fields:**\n- `run_id`\n- `application_id`\n- `version_number`\n- `custom_metadata`\n- `submitted_at`\n- `submitted_by`\n- `terminated_at`\n- `termination_reason`\n\n**Examples:**\n- `?sort=submitted_at` - Sort by creation time (ascending)\n- `?sort=-submitted_at` - Sort by creation time (descending)\n- `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending)\n", + "title": "Sort" + }, + "description": "Sort the results by one or more fields. Use `+` for ascending and `-` for descending order.\n\n**Available fields:**\n- `run_id`\n- `application_id`\n- `version_number`\n- `custom_metadata`\n- `submitted_at`\n- `submitted_by`\n- `terminated_at`\n- `termination_reason`\n\n**Examples:**\n- `?sort=submitted_at` - Sort by creation time (ascending)\n- `?sort=-submitted_at` - Sort by creation time (descending)\n- `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending)\n" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RunReadResponse" + }, + "title": "Response List Runs V1 Runs Get" + } + } + } + }, + "404": { + "description": "Run not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "post": { + "tags": [ + "Public" + ], + "summary": "Initiate Run", + "description": "This endpoint initiates a processing run for a selected application and version, and returns a `run_id` for tracking purposes.\n\nSlide processing occurs asynchronously, allowing you to retrieve results for individual slides as soon as they\ncomplete processing. The system typically processes slides in batches.\nBelow is an example of the required payload for initiating an Atlas H&E TME processing run.\n\n\n### Payload\n\nThe payload includes `application_id`, optional `version_number`, and `items` base fields.\n\n`application_id` is the unique identifier for the application.\n`version_number` is the semantic version to use. If not provided, the latest available version will be used.\n\n`items` includes the list of the items to process (slides, in case of HETA application).\nEvery item has a set of standard fields defined by the API, plus the custom_metadata, specific to the\nchosen application.\n\nExample payload structure with the comments:\n```\n{\n application_id: \"he-tme\",\n version_number: \"1.0.0-beta\",\n items: [{\n \"external_id\": \"slide_1\",\n \"custom_metadata\": {\"project\": \"sample-study\"},\n \"input_artifacts\": [{\n \"name\": \"user_slide\",\n \"download_url\": \"https://...\",\n \"metadata\": {\n \"specimen\": {\n \"disease\": \"LUNG_CANCER\",\n \"tissue\": \"LUNG\"\n },\n \"staining_method\": \"H&E\",\n \"width_px\": 136223,\n \"height_px\": 87761,\n \"resolution_mpp\": 0.2628238,\n \"media-type\":\"image/tiff\",\n \"checksum_base64_crc32c\": \"64RKKA==\"\n }\n }]\n }]\n}\n```\n\n| Parameter | Description |\n| :---- | :---- |\n| `application_id` required | Unique ID for the application |\n| `version_number` optional | Semantic version of the application. If not provided, the latest available version will be used |\n| `items` required | List of submitted items i.e. whole slide images (WSIs) with parameters described below. |\n| `external_id` required | Unique WSI name or ID for easy reference to items, provided by the caller. The `external_id` should be unique across all items of the run. |\n| `input_artifacts` required | List of provided artifacts for a WSI; at the moment Atlas H&E-TME receives only 1 artifact per slide (the slide itself), but for some other applications this can be a slide and a segmentation map |\n| `name` required | Type of artifact; Atlas H&E-TME supports only `\"input_slide\"` |\n| `download_url` required | Signed URL to the input file in the S3 or GCS; Should be valid for at least 6 days |\n| `specimen: disease` required | Supported cancer types for Atlas H&E-TME (see full list in Atlas H&E-TME manual) |\n| `specimen: tissue` required | Supported tissue types for Atlas H&E-TME (see full list in Atlas H&E-TME manual) |\n| `staining_method` required | WSI stain bio-marker; Atlas H&E-TME supports only `\"H&E\"` |\n| `width_px` required | Integer value. Number of pixels of the WSI in the X dimension. |\n| `height_px` required | Integer value. Number of pixels of the WSI in the Y dimension. |\n| `resolution_mpp` required | Resolution of WSI in micrometers per pixel; check allowed range in Atlas H&E-TME manual |\n| `media-type` required | Supported media formats; available values are: image/tiff (for .tiff or .tif WSI), application/dicom (for DICOM ), application/zip (for zipped DICOM), and application/octet-stream (for .svs WSI) |\n| `checksum_base64_crc32c` required | Base64-encoded big-endian CRC32C checksum of the WSI image |\n\n\n\n### Response\n\nThe endpoint returns the run UUID. After that, the job is scheduled for the execution in the background.\n\nTo check the status of the run, call `GET v1/runs/{run_id}` endpoint with the returned run UUID.\n\n### Rejection\n\nApart from the authentication, authorization, and malformed input error, the request can be\nrejected when specific quota limit is exceeded. More details on quotas is described in the\ndocumentation", + "operationId": "create_run_v1_runs_post", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RunCreationRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RunCreationResponse" + } + } + } + }, + "404": { + "description": "Application version not found" + }, + "403": { + "description": "Forbidden - You don't have permission to create this run" + }, + "400": { + "description": "Bad Request - Input validation failed" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/runs/{run_id}": { + "get": { + "tags": [ + "Public" + ], + "summary": "Get run details", + "description": "This endpoint allows the caller to retrieve the current status of a run along with other relevant run details.\n A run becomes available immediately after it is created through the `POST /v1/runs/` endpoint.\n\n To download the output results, use `GET /v1/runs/{run_id}/` items to get outputs for all slides.\nAccess to a run is restricted to the user who created it.", + "operationId": "get_run_v1_runs__run_id__get", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "run_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "Run id, returned by `POST /v1/runs/` endpoint", + "title": "Run Id" + }, + "description": "Run id, returned by `POST /v1/runs/` endpoint" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RunReadResponse" + } + } + } + }, + "404": { + "description": "Run not found because it was deleted." + }, + "403": { + "description": "Forbidden - You don't have permission to see this run" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/runs/{run_id}/cancel": { + "post": { + "tags": [ + "Public" + ], + "summary": "Cancel Run", + "description": "The run can be canceled by the user who created the run.\n\nThe execution can be canceled any time while the run is not in the terminated state. The\npending items of a canceled run will not be processed and will not add to the cost.\n\nWhen the run is canceled, the already completed items remain available for download.", + "operationId": "cancel_run_v1_runs__run_id__cancel_post", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "run_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "Run id, returned by `POST /runs/` endpoint", + "title": "Run Id" + }, + "description": "Run id, returned by `POST /runs/` endpoint" + } + ], + "responses": { + "202": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Run not found" + }, + "403": { + "description": "Forbidden - You don't have permission to cancel this run" + }, + "409": { + "description": "Conflict - The Run is already cancelled" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/runs/{run_id}/items": { + "get": { + "tags": [ + "Public" + ], + "summary": "List Run Items", + "description": "List items in a run with filtering, sorting, and pagination capabilities.\n\nReturns paginated items within a specific run. Results can be filtered\nby `item_id`, `external_ids`, `custom_metadata`, `terminated_at`, and `termination_reason` using JSONPath expressions.\n\n## JSONPath Metadata Filtering\nUse PostgreSQL JSONPath expressions to filter items using their custom_metadata.\n\n### Examples:\n- **Field existence**: `$.case_id` - Results that have a case_id field defined\n- **Exact value match**: `$.priority ? (@ == \"high\")` - Results with high priority\n- **Numeric comparison**: `$.confidence_score ? (@ > 0.95)` - Results with high confidence\n- **Array operations**: `$.flags[*] ? (@ == \"reviewed\")` - Results flagged as reviewed\n- **Complex conditions**: `$.metrics ? (@.accuracy > 0.9 && @.recall > 0.8)` - Results meeting performance thresholds\n\n## Notes\n- JSONPath expressions are evaluated using PostgreSQL's `@?` operator\n- The `$.` prefix is automatically added to root-level field references if missing\n- String values in conditions must be enclosed in double quotes\n- Use `&&` for AND operations and `||` for OR operations", + "operationId": "list_run_items_v1_runs__run_id__items_get", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "run_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "Run id, returned by `POST /v1/runs/` endpoint", + "title": "Run Id" + }, + "description": "Run id, returned by `POST /v1/runs/` endpoint" + }, + { + "name": "item_id__in", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + } + }, + { + "type": "null" + } + ], + "description": "Filter for item ids", + "title": "Item Id In" + }, + "description": "Filter for item ids" + }, + { + "name": "external_id__in", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Filter for items by their external_id from the input payload", + "title": "External Id In" + }, + "description": "Filter for items by their external_id from the input payload" + }, + { + "name": "state", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/ItemState" + }, + { + "type": "null" + } + ], + "description": "Filter items by their state", + "title": "State" + }, + "description": "Filter items by their state" + }, + { + "name": "termination_reason", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/ItemTerminationReason" + }, + { + "type": "null" + } + ], + "description": "Filter items by their termination reason. Only applies to TERMINATED items.", + "title": "Termination Reason" + }, + "description": "Filter items by their termination reason. Only applies to TERMINATED items." + }, + { + "name": "custom_metadata", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "maxLength": 1000 + }, + { + "type": "null" + } + ], + "description": "JSONPath expression to filter items by their custom_metadata", + "title": "Custom Metadata" + }, + "description": "JSONPath expression to filter items by their custom_metadata", + "examples": { + "no_filter": { + "summary": "No filter (returns all)", + "description": "Returns all items without filtering by custom metadata", + "value": "$" + }, + "field_exists": { + "summary": "Check if field exists", + "description": "Find items that have a project field defined", + "value": "$.project" + }, + "field_has_value": { + "summary": "Check if field has a certain value", + "description": "Compare a field value against a certain value", + "value": "$.project ? (@ == \"cancer-research\")" + }, + "numeric_comparisons": { + "summary": "Compare to a numeric value of a field", + "description": "Compare a field value against a numeric value of a field", + "value": "$.duration_hours ? (@ < 2)" + }, + "array_operations": { + "summary": "Check if an array contains a certain value", + "description": "Check if an array contains a certain value", + "value": "$.tags[*] ? (@ == \"production\")" + }, + "complex_filters": { + "summary": "Combine multiple checks", + "description": "Combine multiple checks", + "value": "$.resources ? (@.gpu_count > 2 && @.memory_gb >= 16)" + } + } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "default": 1, + "title": "Page" + } + }, + { + "name": "page_size", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 5, + "default": 50, + "title": "Page Size" + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Sort the items by one or more fields. Use `+` for ascending and `-` for descending order.\n **Available fields:**\n- `item_id`\n- `external_id`\n- `custom_metadata`\n- `terminated_at`\n- `termination_reason`\n\n**Examples:**\n- `?sort=item_id` - Sort by id of the item (ascending)\n- `?sort=-external_id` - Sort by external ID (descending)\n- `?sort=custom_metadata&sort=-external_id` - Sort by metadata, then by external ID (descending)", + "title": "Sort" + }, + "description": "Sort the items by one or more fields. Use `+` for ascending and `-` for descending order.\n **Available fields:**\n- `item_id`\n- `external_id`\n- `custom_metadata`\n- `terminated_at`\n- `termination_reason`\n\n**Examples:**\n- `?sort=item_id` - Sort by id of the item (ascending)\n- `?sort=-external_id` - Sort by external ID (descending)\n- `?sort=custom_metadata&sort=-external_id` - Sort by metadata, then by external ID (descending)" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ItemResultReadResponse" + }, + "title": "Response List Run Items V1 Runs Run Id Items Get" + } + } + } + }, + "404": { + "description": "Run not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/runs/{run_id}/items/{external_id}": { + "get": { + "tags": [ + "Public" + ], + "summary": "Get Item By Run", + "description": "Retrieve details of a specific item (slide) by its external ID and the run ID.", + "operationId": "get_item_by_run_v1_runs__run_id__items__external_id__get", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "run_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "The run id, returned by `POST /runs/` endpoint", + "title": "Run Id" + }, + "description": "The run id, returned by `POST /runs/` endpoint" + }, + { + "name": "external_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "description": "The `external_id` that was defined for the item by the customer that triggered the run.", + "title": "External Id" + }, + "description": "The `external_id` that was defined for the item by the customer that triggered the run." + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ItemResultReadResponse" + } + } + } + }, + "404": { + "description": "Not Found - Item with given ID does not exist" + }, + "403": { + "description": "Forbidden - You don't have permission to see this item" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/runs/{run_id}/artifacts/{artifact_id}/file": { + "get": { + "tags": [ + "Public" + ], + "summary": "Get Artifact Url", + "description": "Download the artifact file with the specified artifact_id, belonging to the specified run.\nThe artifact_is is returned by the `GET /v1/runs/{run_id}/items` endpoint as part of the item results, and can also\nbe retrieved via `GET /v1/runs/{run_id}/items/{external_id}`.\n\nThe endpoint may return a redirect response with a presigned URL to download the artifact file from the storage\nbucket. The presigned URL is valid for a limited time, so it should be used immediately after receiving the response.", + "operationId": "get_artifact_url_v1_runs__run_id__artifacts__artifact_id__file_get", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "run_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "Run id, returned by `POST /runs/` endpoint", + "title": "Run Id" + }, + "description": "Run id, returned by `POST /runs/` endpoint" + }, + { + "name": "artifact_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "The artifact id to download", + "title": "Artifact Id" + }, + "description": "The artifact id to download" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Not Found - Artifact not found for the specified run" + }, + "307": { + "description": "Temporary Redirect - Redirect to the artifact file URL" + }, + "403": { + "description": "Forbidden - You don't have permission to download this artifact" + }, + "410": { + "description": "Gone - Artifact has been deleted" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/runs/{run_id}/artifacts": { + "delete": { + "tags": [ + "Public" + ], + "summary": "Delete Run Items", + "description": "This endpoint allows the caller to explicitly delete artifacts generated by a run.\nIt can only be invoked when the run has reached a final state, i.e.\n`PROCESSED`, `CANCELED_SYSTEM`, or `CANCELED_USER`.\nNote that by default, all artifacts are automatically deleted 30 days after the run finishes,\nregardless of whether the caller explicitly requests such deletion.", + "operationId": "delete_run_items_v1_runs__run_id__artifacts_delete", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "run_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "Run id, returned by `POST /runs/` endpoint", + "title": "Run Id" + }, + "description": "Run id, returned by `POST /runs/` endpoint" + } + ], + "responses": { + "200": { + "description": "Run artifacts deleted", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Run not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/runs/{run_id}/custom-metadata": { + "put": { + "tags": [ + "Public" + ], + "summary": "Put Run Custom Metadata", + "description": "Update the custom metadata of a run with the specified `run_id`.\n\nOptionally, a checksum may be provided along the custom metadata JSON.\nIt can be used to verify if the custom metadata was updated since the last time it was accessed.\nIf the checksum is provided, it must match the existing custom metadata in the system, ensuring that the current\ncustom metadata value to be overwritten is acknowledged by the user.\nIf no checksum is provided, submitted metadata directly overwrites the existing metadata, without any checks.\n\nThe latest custom metadata and checksum can be retrieved for the run via the `GET /v1/runs/{run_id}` endpoint.\n\n**Note on deadlines:** Run deadlines must be set during run creation and cannot be modified afterward.\nAny deadline changes in custom metadata will be ignored by the system.", + "operationId": "put_run_custom_metadata_v1_runs__run_id__custom_metadata_put", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "run_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "Run id, returned by `POST /runs/` endpoint", + "title": "Run Id" + }, + "description": "Run id, returned by `POST /runs/` endpoint" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomMetadataUpdateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Custom metadata successfully updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomMetadataUpdateResponse" + } + } + } + }, + "404": { + "description": "Run not found" + }, + "403": { + "description": "Forbidden - You don't have permission to update this run" + }, + "412": { + "description": "Precondition Failed - Checksum mismatch, resource has been modified" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/runs/{run_id}/items/{external_id}/custom-metadata": { + "put": { + "tags": [ + "Public" + ], + "summary": "Put Item Custom Metadata By Run", + "description": "Update the custom metadata of the item with the specified `external_id`, belonging to the specified run.\n\nOptionally, a checksum may be provided along the custom metadata JSON.\nIt can be used to verify if the custom metadata was updated since the last time it was accessed.\nIf the checksum is provided, it must match the existing custom metadata in the system, ensuring that the current\ncustom metadata value to be overwritten is acknowledged by the user.\nIf no checksum is provided, submitted metadata directly overwrites the existing metadata, without any checks.\n\nThe latest custom metadata and checksum can be retrieved\n for individual items via `GET /v1/runs/{run_id}/items/{external_id}`,\n and for all items of a run via `GET /v1/runs/{run_id}/items`.", + "operationId": "put_item_custom_metadata_by_run_v1_runs__run_id__items__external_id__custom_metadata_put", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "run_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "The run id, returned by `POST /runs/` endpoint", + "title": "Run Id" + }, + "description": "The run id, returned by `POST /runs/` endpoint" + }, + { + "name": "external_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "description": "The `external_id` that was defined for the item by the customer that triggered the run.", + "title": "External Id" + }, + "description": "The `external_id` that was defined for the item by the customer that triggered the run." + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomMetadataUpdateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Custom metadata successfully updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomMetadataUpdateResponse" + } + } + } + }, + "403": { + "description": "Forbidden - You don't have permission to update this item" + }, + "404": { + "description": "Item not found" + }, + "412": { + "description": "Precondition Failed - Checksum mismatch" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/v1/me": { + "get": { + "tags": [ + "Public" + ], + "summary": "Get current user", + "description": "Retrieves your identity details, including name, email, and organization.\nThis is useful for verifying that the request is being made under the correct user profile\nand organization context, as well as confirming that the expected environment variables are correctly set\n(in case you are using Python SDK)", + "operationId": "get_me_v1_me_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MeReadResponse" + } + } + } + } + }, + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ] + } + } + }, + "components": { + "schemas": { + "ApplicationReadResponse": { + "properties": { + "application_id": { + "type": "string", + "title": "Application Id", + "description": "Application ID", + "examples": [ + "he-tme" + ] + }, + "name": { + "type": "string", + "title": "Name", + "description": "Application display name", + "examples": [ + "Atlas H&E-TME" + ] + }, + "regulatory_classes": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Regulatory Classes", + "description": "Regulatory classes, to which the applications comply with. Possible values include: RUO, IVDR, FDA.", + "examples": [ + [ + "RUO" + ] + ] + }, + "description": { + "type": "string", + "title": "Description", + "description": "Describing what the application can do ", + "examples": [ + "The Atlas H&E TME is an AI application designed to examine FFPE (formalin-fixed, paraffin-embedded) tissues stained with H&E (hematoxylin and eosin), delivering comprehensive insights into the tumor microenvironment." + ] + }, + "versions": { + "items": { + "$ref": "#/components/schemas/ApplicationVersion" + }, + "type": "array", + "title": "Versions", + "description": "All version numbers available to the user" + } + }, + "type": "object", + "required": [ + "application_id", + "name", + "regulatory_classes", + "description", + "versions" + ], + "title": "ApplicationReadResponse", + "description": "Response schema for `List available applications` and `Read Application by Id` endpoints" + }, + "ApplicationReadShortResponse": { + "properties": { + "application_id": { + "type": "string", + "title": "Application Id", + "description": "Application ID", + "examples": [ + "he-tme" + ] + }, + "name": { + "type": "string", + "title": "Name", + "description": "Application display name", + "examples": [ + "Atlas H&E-TME" + ] + }, + "regulatory_classes": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Regulatory Classes", + "description": "Regulatory classes, to which the applications comply with. Possible values include: RUO, IVDR, FDA.", + "examples": [ + [ + "RUO" + ] + ] + }, + "description": { + "type": "string", + "title": "Description", + "description": "Describing what the application can do ", + "examples": [ + "The Atlas H&E TME is an AI application designed to examine FFPE (formalin-fixed, paraffin-embedded) tissues stained with H&E (hematoxylin and eosin), delivering comprehensive insights into the tumor microenvironment." + ] + }, + "latest_version": { + "anyOf": [ + { + "$ref": "#/components/schemas/ApplicationVersion" + }, + { + "type": "null" + } + ], + "description": "The version with highest version number available to the user" + } + }, + "type": "object", + "required": [ + "application_id", + "name", + "regulatory_classes", + "description" + ], + "title": "ApplicationReadShortResponse", + "description": "Response schema for `List available applications` and `Read Application by Id` endpoints" + }, + "ApplicationVersion": { + "properties": { + "number": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", + "title": "Number", + "description": "The number of the latest version", + "examples": [ + "1.0.0" + ] + }, + "released_at": { + "type": "string", + "format": "date-time", + "title": "Released At", + "description": "The timestamp for when the application version was made available in the Platform", + "examples": [ + "2025-09-15T10:30:45.123Z" + ] + } + }, + "type": "object", + "required": [ + "number", + "released_at" + ], + "title": "ApplicationVersion" + }, + "ArtifactOutput": { + "type": "string", + "enum": [ + "NONE", + "AVAILABLE", + "DELETED_BY_USER", + "DELETED_BY_SYSTEM" + ], + "title": "ArtifactOutput" + }, + "ArtifactState": { + "type": "string", + "enum": [ + "PENDING", + "PROCESSING", + "TERMINATED" + ], + "title": "ArtifactState" + }, + "ArtifactTerminationReason": { + "type": "string", + "enum": [ + "SUCCEEDED", + "USER_ERROR", + "SYSTEM_ERROR", + "SKIPPED" + ], + "title": "ArtifactTerminationReason" + }, + "CustomMetadataUpdateRequest": { + "properties": { + "custom_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Custom Metadata", + "description": "JSON metadata that should be set for the run", + "examples": [ + { + "department": "D1", + "study": "abc-1" + } + ] + }, + "custom_metadata_checksum": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Custom Metadata Checksum", + "description": "Optional field to verify that the latest custom metadata was known. If set to the checksum retrieved via the /runs endpoint, it must match the checksum of the current value in the database.", + "examples": [ + "f54fe109" + ] + } + }, + "type": "object", + "title": "CustomMetadataUpdateRequest" + }, + "CustomMetadataUpdateResponse": { + "properties": { + "custom_metadata_checksum": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Custom Metadata Checksum", + "description": "The checksum of the updated custom metadata. If the `custom_metadata` is None,\nthe checksum also None.", + "readOnly": true + } + }, + "type": "object", + "required": [ + "custom_metadata_checksum" + ], + "title": "CustomMetadataUpdateResponse" + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail" + } + }, + "type": "object", + "title": "HTTPValidationError" + }, + "InputArtifact": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "mime_type": { + "type": "string", + "pattern": "^\\w+\\/\\w+[-+.|\\w+]+\\w+$", + "title": "Mime Type", + "examples": [ + "image/tiff" + ] + }, + "metadata_schema": { + "additionalProperties": true, + "type": "object", + "title": "Metadata Schema" + } + }, + "type": "object", + "required": [ + "name", + "mime_type", + "metadata_schema" + ], + "title": "InputArtifact" + }, + "InputArtifactCreationRequest": { + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "Type of artifact. For Atlas H&E-TME, use \"input_slide\"", + "examples": [ + "input_slide" + ] + }, + "download_url": { + "type": "string", + "maxLength": 2083, + "minLength": 1, + "format": "uri", + "title": "Download Url", + "description": "[Signed URL](https://cloud.google.com/cdn/docs/using-signed-urls) to the input artifact file. The URL should be valid for at least 6 days from the payload submission time.", + "examples": [ + "https://example.com/case-no-1-slide.tiff" + ] + }, + "metadata": { + "additionalProperties": true, + "type": "object", + "title": "Metadata", + "description": "The metadata of the artifact, required by the application version. The JSON schema of the metadata can be requested by `/v1/versions/{application_version_id}`. The schema is located in `input_artifacts.[].metadata_schema`", + "examples": [ + { + "checksum_base64_crc32c": "752f9554", + "height": 2000, + "height_mpp": 0.5, + "width": 10000, + "width_mpp": 0.5 + } + ] + } + }, + "type": "object", + "required": [ + "name", + "download_url", + "metadata" + ], + "title": "InputArtifactCreationRequest", + "description": "Input artifact containing the slide image and associated metadata." + }, + "ItemCreationRequest": { + "properties": { + "external_id": { + "type": "string", + "maxLength": 255, + "title": "External Id", + "description": "Unique identifier for this item within the run. Used for referencing items. Must be unique across all items in the same run", + "examples": [ + "slide_1", + "patient_001_slide_A", + "sample_12345" + ] + }, + "custom_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Custom Metadata", + "description": "Optional JSON custom_metadata to store additional information alongside an item.", + "examples": [ + { + "case": "abc" + } + ] + }, + "input_artifacts": { + "items": { + "$ref": "#/components/schemas/InputArtifactCreationRequest" + }, + "type": "array", + "title": "Input Artifacts", + "description": "List of input artifacts for this item. For Atlas H&E-TME, typically contains one artifact (the slide image)", + "examples": [ + [ + { + "download_url": "https://example-bucket.s3.amazonaws.com/slide1.tiff", + "metadata": { + "checksum_base64_crc32c": "64RKKA==", + "height_px": 87761, + "media-type": "image/tiff", + "resolution_mpp": 0.2628238, + "specimen": { + "disease": "LUNG_CANCER", + "tissue": "LUNG" + }, + "staining_method": "H&E", + "width_px": 136223 + }, + "name": "input_slide" + } + ] + ] + } + }, + "type": "object", + "required": [ + "external_id", + "input_artifacts" + ], + "title": "ItemCreationRequest", + "description": "Individual item (slide) to be processed in a run." + }, + "ItemOutput": { + "type": "string", + "enum": [ + "NONE", + "FULL" + ], + "title": "ItemOutput" + }, + "ItemResultReadResponse": { + "properties": { + "item_id": { + "type": "string", + "format": "uuid", + "title": "Item Id", + "description": "Item UUID generated by the Platform" + }, + "external_id": { + "type": "string", + "title": "External Id", + "description": "The external_id of the item from the user payload", + "examples": [ + "slide_1" + ] + }, + "custom_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Custom Metadata", + "description": "The custom_metadata of the item that has been provided by the user on run creation." + }, + "custom_metadata_checksum": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Custom Metadata Checksum", + "description": "The checksum of the `custom_metadata` field.\nCan be used in the `PUT /runs/{run-id}/items/{external_id}/custom_metadata`\nrequest to avoid unwanted override of the values in concurrent requests.", + "examples": [ + "f54fe109" + ] + }, + "queue_position_org": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Queue Position Org", + "description": "The position of the item in the organization's queue." + }, + "queue_position_platform": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Queue Position Platform", + "description": "The position of the item in the platform's queue." + }, + "state": { + "$ref": "#/components/schemas/ItemState", + "description": "\nThe item moves from `PENDING` to `PROCESSING` to `TERMINATED` state.\nWhen terminated, consult the `termination_reason` property to see whether it was successful.\n " + }, + "output": { + "$ref": "#/components/schemas/ItemOutput", + "description": "The output status of the item (NONE, FULL)" + }, + "termination_reason": { + "anyOf": [ + { + "$ref": "#/components/schemas/ItemTerminationReason" + }, + { + "type": "null" + } + ], + "description": "\nWhen the `state` is `TERMINATED` this will explain why\n`SUCCEEDED` -> Successful processing.\n`USER_ERROR` -> Failed because the provided input was invalid.\n`SYSTEM_ERROR` -> There was an error in the model or platform.\n`SKIPPED` -> Was cancelled\n" + }, + "error_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Code" + }, + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Message", + "description": "\n The error message in case the `termination_reason` is in `USER_ERROR` or `SYSTEM_ERROR`\n ", + "examples": [ + "This item was not processed because the threshold of 3 items finishing in error state (user or system error) was reached before the item was processed.", + "The item was not processed because the run was cancelled by the user before the item was processed.", + "User error raised by Application because the input data provided by the user cannot be processed:\nThe image width is 123000 px, but the maximum width is 100000 px", + "A system error occurred during the item execution:\n System went out of memory in cell classification", + "An unknown system error occurred during the item execution" + ] + }, + "terminated_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Terminated At", + "description": "Timestamp showing when the item reached a terminal state.", + "examples": [ + "2024-01-15T10:30:45.123Z" + ] + }, + "output_artifacts": { + "items": { + "$ref": "#/components/schemas/OutputArtifactResultReadResponse" + }, + "type": "array", + "title": "Output Artifacts", + "description": "\nThe list of the results generated by the application algorithm. The number of files and their\ntypes depend on the particular application version, call `/v1/versions/{version_id}` to get\nthe details.\n " + } + }, + "type": "object", + "required": [ + "item_id", + "external_id", + "custom_metadata", + "state", + "output", + "output_artifacts" + ], + "title": "ItemResultReadResponse", + "description": "Response schema for items in `List Run Items` endpoint" + }, + "ItemState": { + "type": "string", + "enum": [ + "PENDING", + "PROCESSING", + "TERMINATED" + ], + "title": "ItemState" + }, + "ItemTerminationReason": { + "type": "string", + "enum": [ + "SUCCEEDED", + "USER_ERROR", + "SYSTEM_ERROR", + "SKIPPED" + ], + "title": "ItemTerminationReason" + }, + "MeReadResponse": { + "properties": { + "user": { + "$ref": "#/components/schemas/UserReadResponse" + }, + "organization": { + "$ref": "#/components/schemas/OrganizationReadResponse" + } + }, + "type": "object", + "required": [ + "user", + "organization" + ], + "title": "MeReadResponse", + "description": "Response schema for `Get current user` endpoint" + }, + "OrganizationReadResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Unique organization identifier", + "examples": [ + "org_123456" + ] + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name", + "description": "Organization name (E.g. “aignx”)", + "examples": [ + "aignx" + ] + }, + "display_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Display Name", + "description": "Public organization name (E.g. “Aignostics GmbH”)", + "examples": [ + "Aignostics GmbH" + ] + }, + "aignostics_bucket_hmac_access_key_id": { + "type": "string", + "title": "Aignostics Bucket Hmac Access Key Id", + "description": "HMAC access key ID for the Aignostics-provided storage bucket. Used to authenticate requests for uploading files and generating signed URLs", + "examples": [ + "YOUR_HMAC_ACCESS_KEY_ID" + ] + }, + "aignostics_bucket_hmac_secret_access_key": { + "type": "string", + "title": "Aignostics Bucket Hmac Secret Access Key", + "description": "HMAC secret access key paired with the access key ID. Keep this credential secure.", + "examples": [ + "YOUR/HMAC/SECRET_ACCESS_KEY" + ] + }, + "aignostics_bucket_name": { + "type": "string", + "title": "Aignostics Bucket Name", + "description": "Name of the bucket provided by Aignostics for storing input artifacts (slide images)", + "examples": [ + "aignostics-platform-bucket" + ] + }, + "aignostics_bucket_protocol": { + "type": "string", + "title": "Aignostics Bucket Protocol", + "description": "Protocol to use for bucket access. Defines the URL scheme for connecting to the storage service", + "examples": [ + "gs" + ] + }, + "aignostics_logfire_token": { + "type": "string", + "title": "Aignostics Logfire Token", + "description": "Authentication token for Logfire observability service. Enables sending application logs and performance metrics to Aignostics for monitoring and support", + "examples": [ + "your-logfire-token" + ] + }, + "aignostics_sentry_dsn": { + "type": "string", + "title": "Aignostics Sentry Dsn", + "description": "Data Source Name (DSN) for Sentry error tracking service. Allows automatic reporting of errors and exceptions to Aignostics support team", + "examples": [ + "https://2354s3#ewsha@o44.ingest.us.sentry.io/34345123432" + ] + } + }, + "type": "object", + "required": [ + "id", + "aignostics_bucket_hmac_access_key_id", + "aignostics_bucket_hmac_secret_access_key", + "aignostics_bucket_name", + "aignostics_bucket_protocol", + "aignostics_logfire_token", + "aignostics_sentry_dsn" + ], + "title": "OrganizationReadResponse", + "description": "Part of response schema for Organization object in `Get current user` endpoint.\nThis model corresponds to the response schema returned from\nAuth0 GET /v2/organizations/{id} endpoint, flattens out the metadata out\nand doesn't return branding or token_quota objects.\nFor details, see:\nhttps://auth0.com/docs/api/management/v2/organizations/get-organizations-by-id\n\n#### Configuration for integrating with Aignostics Platform services.\n\nThe Aignostics Platform API requires signed URLs for input artifacts (slide images). To simplify this process,\nAignostics provides a dedicated storage bucket. The HMAC credentials below grant read and write\naccess to this bucket, allowing you to upload files and generate the signed URLs needed for API calls.\n\nAdditionally, logging and error reporting tokens enable Aignostics to provide better support and monitor\nsystem performance for your integration." + }, + "OutputArtifact": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "mime_type": { + "type": "string", + "pattern": "^\\w+\\/\\w+[-+.|\\w+]+\\w+$", + "title": "Mime Type", + "examples": [ + "application/vnd.apache.parquet" + ] + }, + "metadata_schema": { + "additionalProperties": true, + "type": "object", + "title": "Metadata Schema" + }, + "scope": { + "$ref": "#/components/schemas/OutputArtifactScope" + }, + "visibility": { + "$ref": "#/components/schemas/OutputArtifactVisibility" + } + }, + "type": "object", + "required": [ + "name", + "mime_type", + "metadata_schema", + "scope", + "visibility" + ], + "title": "OutputArtifact" + }, + "OutputArtifactResultReadResponse": { + "properties": { + "output_artifact_id": { + "type": "string", + "format": "uuid", + "title": "Output Artifact Id", + "description": "The Id of the artifact. Used internally" + }, + "name": { + "type": "string", + "title": "Name", + "description": "\nName of the output from the output schema from the `/v1/versions/{version_id}` endpoint.\n ", + "examples": [ + "tissue_qc:tiff_heatmap" + ] + }, + "metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Metadata", + "description": "The metadata of the output artifact, provided by the application. Can only be None if the artifact itself was deleted." + }, + "state": { + "$ref": "#/components/schemas/ArtifactState", + "description": "The current state of the artifact (PENDING, PROCESSING, TERMINATED)" + }, + "termination_reason": { + "anyOf": [ + { + "$ref": "#/components/schemas/ArtifactTerminationReason" + }, + { + "type": "null" + } + ], + "description": "The reason for termination when state is TERMINATED" + }, + "output": { + "$ref": "#/components/schemas/ArtifactOutput", + "description": "The output status of the artifact (NONE, FULL)" + }, + "error_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Code" + }, + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Message" + }, + "download_url": { + "anyOf": [ + { + "type": "string", + "maxLength": 2083, + "minLength": 1, + "format": "uri" + }, + { + "type": "null" + } + ], + "title": "Download Url", + "description": "\nThe download URL to the output file. The URL is valid for 1 hour after the endpoint is called.\nA new URL is generated every time the endpoint is called.\n ", + "deprecated": true + } + }, + "type": "object", + "required": [ + "output_artifact_id", + "name", + "state", + "output" + ], + "title": "OutputArtifactResultReadResponse" + }, + "OutputArtifactScope": { + "type": "string", + "enum": [ + "ITEM", + "GLOBAL" + ], + "title": "OutputArtifactScope" + }, + "OutputArtifactVisibility": { + "type": "string", + "enum": [ + "INTERNAL", + "EXTERNAL" + ], + "title": "OutputArtifactVisibility" + }, + "RunCreationRequest": { + "properties": { + "application_id": { + "type": "string", + "title": "Application Id", + "description": "Unique ID for the application to use for processing", + "examples": [ + "he-tme" + ] + }, + "version_number": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Version Number", + "description": "Semantic version of the application to use for processing. If not provided, the latest available version will be used", + "examples": [ + "1.0.0-beta1" + ] + }, + "custom_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Custom Metadata", + "description": "Optional JSON metadata to store additional information alongside the run", + "examples": [ + { + "department": "D1", + "study": "abc-1" + } + ] + }, + "scheduling": { + "anyOf": [ + { + "$ref": "#/components/schemas/SchedulingRequest" + }, + { + "type": "null" + } + ], + "description": "Optional scheduling constraints for this run.", + "examples": [ + { + "deadline": "2026-03-05T23:59:59Z", + "due_date": "2026-03-04T23:59:59Z" + } + ] + }, + "items": { + "items": { + "$ref": "#/components/schemas/ItemCreationRequest" + }, + "type": "array", + "minItems": 1, + "title": "Items", + "description": "List of items (slides) to process. Each item represents a whole slide image (WSI) with its associated metadata and artifacts", + "examples": [ + [ + { + "external_id": "slide_1", + "input_artifacts": [ + { + "download_url": "https://example-bucket.s3.amazonaws.com/slide1.tiff?signature=...", + "metadata": { + "checksum_base64_crc32c": "64RKKA==", + "height_px": 87761, + "media-type": "image/tiff", + "resolution_mpp": 0.2628238, + "specimen": { + "disease": "LUNG_CANCER", + "tissue": "LUNG" + }, + "staining_method": "H&E", + "width_px": 136223 + }, + "name": "input_slide" + } + ] + } + ] + ] + } + }, + "type": "object", + "required": [ + "application_id", + "items" + ], + "title": "RunCreationRequest", + "description": "Request schema for `Initiate Run` endpoint.\nIt describes which application version is chosen, and which user data should be processed." + }, + "RunCreationResponse": { + "properties": { + "run_id": { + "type": "string", + "format": "uuid", + "title": "Run Id", + "examples": [ + "3fa85f64-5717-4562-b3fc-2c963f66afa6" + ] + } + }, + "type": "object", + "required": [ + "run_id" + ], + "title": "RunCreationResponse" + }, + "RunItemStatistics": { + "properties": { + "item_count": { + "type": "integer", + "title": "Item Count", + "description": "Total number of the items in the run" + }, + "item_pending_count": { + "type": "integer", + "title": "Item Pending Count", + "description": "The number of items in `PENDING` state" + }, + "item_processing_count": { + "type": "integer", + "title": "Item Processing Count", + "description": "The number of items in `PROCESSING` state" + }, + "item_user_error_count": { + "type": "integer", + "title": "Item User Error Count", + "description": "The number of items in `TERMINATED` state, and the item termination reason is `USER_ERROR`" + }, + "item_system_error_count": { + "type": "integer", + "title": "Item System Error Count", + "description": "The number of items in `TERMINATED` state, and the item termination reason is `SYSTEM_ERROR`" + }, + "item_skipped_count": { + "type": "integer", + "title": "Item Skipped Count", + "description": "The number of items in `TERMINATED` state, and the item termination reason is `SKIPPED`" + }, + "item_succeeded_count": { + "type": "integer", + "title": "Item Succeeded Count", + "description": "The number of items in `TERMINATED` state, and the item termination reason is `SUCCEEDED`" + } + }, + "type": "object", + "required": [ + "item_count", + "item_pending_count", + "item_processing_count", + "item_user_error_count", + "item_system_error_count", + "item_skipped_count", + "item_succeeded_count" + ], + "title": "RunItemStatistics" + }, + "RunOutput": { + "type": "string", + "enum": [ + "NONE", + "PARTIAL", + "FULL" + ], + "title": "RunOutput" + }, + "RunReadResponse": { + "properties": { + "run_id": { + "type": "string", + "format": "uuid", + "title": "Run Id", + "description": "UUID of the application" + }, + "application_id": { + "type": "string", + "title": "Application Id", + "description": "Application id", + "examples": [ + "he-tme" + ] + }, + "version_number": { + "type": "string", + "title": "Version Number", + "description": "Application version number", + "examples": [ + "0.4.4" + ] + }, + "state": { + "$ref": "#/components/schemas/RunState", + "description": "When the run request is received by the Platform, the `state` of it is set to\n`PENDING`. The state changes to `PROCESSING` when at least one item is being processed. After `PROCESSING`, the\nstate of the run can switch back to `PENDING` if there are no processing items, or to `TERMINATED` when the run\nfinished processing." + }, + "output": { + "$ref": "#/components/schemas/RunOutput", + "description": "The status of the output of the run. When 0 items are successfully processed the output is\n`NONE`, after one item is successfully processed, the value is set to `PARTIAL`. When all items of the run are\nsuccessfully processed, the output is set to `FULL`." + }, + "termination_reason": { + "anyOf": [ + { + "$ref": "#/components/schemas/RunTerminationReason" + }, + { + "type": "null" + } + ], + "description": "The termination reason of the run. When the run is not in `TERMINATED` state, the\n termination_reason is `null`. If all items of of the run are processed (successfully or with an error), then\n termination_reason is set to `ALL_ITEMS_PROCESSED`. If the run is cancelled by the user, the value is set to\n `CANCELED_BY_USER`. If the run reaches the threshold of number of failed items, the Platform cancels the run\n and sets the termination_reason to `CANCELED_BY_SYSTEM`.\n " + }, + "error_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Code", + "description": "When the termination_reason is set to CANCELED_BY_SYSTEM, the error_code is set to define the\n structured description of the error.", + "examples": [ + "SCHEDULER.ITEMS_WITH_ERROR_THRESHOLD_REACHED" + ] + }, + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Message", + "description": "When the termination_reason is set to CANCELED_BY_SYSTEM, the error_message is set to provide\n more insights to the error cause.", + "examples": [ + "Run canceled given errors on more than 10 items." + ] + }, + "statistics": { + "$ref": "#/components/schemas/RunItemStatistics", + "description": "Aggregated statistics of the run execution" + }, + "custom_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Custom Metadata", + "description": "Optional JSON metadata that was stored in alongside the run by the user", + "examples": [ + { + "department": "D1", + "study": "abc-1" + } + ] + }, + "custom_metadata_checksum": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Custom Metadata Checksum", + "description": "The checksum of the `custom_metadata` field. Can be used in the `PUT /runs/{run-id}/custom_metadata`\nrequest to avoid unwanted override of the values in concurrent requests.", + "examples": [ + "f54fe109" + ] + }, + "submitted_at": { + "type": "string", + "format": "date-time", + "title": "Submitted At", + "description": "Timestamp showing when the run was triggered" + }, + "submitted_by": { + "type": "string", + "title": "Submitted By", + "description": "Id of the user who triggered the run", + "examples": [ + "auth0|123456" + ] + }, + "terminated_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Terminated At", + "description": "Timestamp showing when the run reached a terminal state.", + "examples": [ + "2024-01-15T10:30:45.123Z" + ] + }, + "num_preceding_items_org": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Num Preceding Items Org", + "description": "How many Items from other Runs in the same Organization are due to begin processing before this Run's next Item does." + }, + "num_preceding_items_platform": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Num Preceding Items Platform", + "description": "How many Items from other Runs are due to begin processing before this Run's next Item does." + }, + "scheduling": { + "anyOf": [ + { + "$ref": "#/components/schemas/SchedulingResponse" + }, + { + "type": "null" + } + ], + "description": "Scheduling constraints set for this run." + } + }, + "type": "object", + "required": [ + "run_id", + "application_id", + "version_number", + "state", + "output", + "termination_reason", + "error_code", + "error_message", + "statistics", + "submitted_at", + "submitted_by" + ], + "title": "RunReadResponse", + "description": "Response schema for `Get run details` endpoint" + }, + "RunState": { + "type": "string", + "enum": [ + "PENDING", + "PROCESSING", + "TERMINATED" + ], + "title": "RunState" + }, + "RunTerminationReason": { + "type": "string", + "enum": [ + "ALL_ITEMS_PROCESSED", + "CANCELED_BY_SYSTEM", + "CANCELED_BY_USER" + ], + "title": "RunTerminationReason" + }, + "SchedulingRequest": { + "properties": { + "due_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Due Date", + "description": "Requested completion time. Items are prioritized to meet this target.", + "examples": [ + "2026-03-04T23:59:59Z" + ] + }, + "deadline": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Deadline", + "description": "Hard deadline. The run will be cancelled if not completed by this time.", + "examples": [ + "2026-03-05T23:59:59Z" + ] + } + }, + "type": "object", + "title": "SchedulingRequest", + "description": "Scheduling constraints for a run." + }, + "SchedulingResponse": { + "properties": { + "due_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "deadline": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Deadline" + } + }, + "type": "object", + "title": "SchedulingResponse", + "description": "Scheduling fields returned in run responses." + }, + "UserReadResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "Unique user identifier", + "examples": [ + "auth0|123456" + ] + }, + "email": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Email", + "description": "User email", + "examples": [ + "user@domain.com" + ] + }, + "email_verified": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Email Verified", + "examples": [ + true + ] + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Name", + "description": "First and last name of the user", + "examples": [ + "Jane Doe" + ] + }, + "given_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Given Name", + "examples": [ + "Jane" + ] + }, + "family_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Family Name", + "examples": [ + "Doe" + ] + }, + "nickname": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Nickname", + "examples": [ + "jdoe" + ] + }, + "picture": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Picture", + "examples": [ + "https://example.com/jdoe.jpg" + ] + }, + "updated_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Updated At", + "examples": [ + "2023-10-05T14:48:00.000Z" + ] + } + }, + "type": "object", + "required": [ + "id" + ], + "title": "UserReadResponse", + "description": "Part of response schema for User object in `Get current user` endpoint.\nThis model corresponds to the response schema returned from\nAuth0 GET /v2/users/{id} endpoint.\nFor details, see:\nhttps://auth0.com/docs/api/management/v2/users/get-users-by-id" + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "type": "array", + "title": "Location" + }, + "msg": { + "type": "string", + "title": "Message" + }, + "type": { + "type": "string", + "title": "Error Type" + }, + "input": { + "title": "Input" + }, + "ctx": { + "type": "object", + "title": "Context" + } + }, + "type": "object", + "required": [ + "loc", + "msg", + "type" + ], + "title": "ValidationError" + }, + "VersionReadResponse": { + "properties": { + "version_number": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", + "title": "Version Number", + "description": "Semantic version of the application" + }, + "changelog": { + "type": "string", + "title": "Changelog", + "description": "Description of the changes relative to the previous version" + }, + "input_artifacts": { + "items": { + "$ref": "#/components/schemas/InputArtifact" + }, + "type": "array", + "title": "Input Artifacts", + "description": "List of the input fields, provided by the User" + }, + "output_artifacts": { + "items": { + "$ref": "#/components/schemas/OutputArtifact" + }, + "type": "array", + "title": "Output Artifacts", + "description": "List of the output fields, generated by the application" + }, + "released_at": { + "type": "string", + "format": "date-time", + "title": "Released At", + "description": "The timestamp when the application version was registered" + } + }, + "type": "object", + "required": [ + "version_number", + "changelog", + "input_artifacts", + "output_artifacts", + "released_at" + ], + "title": "VersionReadResponse", + "description": "Base Response schema for the `Application Version Details` endpoint" + } + }, + "securitySchemes": { + "OAuth2AuthorizationCodeBearer": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "scopes": {}, + "authorizationUrl": "https://aignostics-platform-staging.eu.auth0.com/authorize", + "tokenUrl": "https://aignostics-platform-staging.eu.auth0.com/oauth/token" + } + } + } + } + } +} diff --git a/codegen/in/openapi.json b/codegen/in/openapi.json index e3ee044a4..cae9e0200 100644 --- a/codegen/in/openapi.json +++ b/codegen/in/openapi.json @@ -3,7 +3,7 @@ "info": { "title": "Aignostics Platform API", "description": "\nThe Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. \n\nTo begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. \n\nMore information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com).\n\n**How to authorize and test API endpoints:**\n\n1. Click the \"Authorize\" button in the right corner below\n3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials\n4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint\n\n**Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized.\n\n", - "version": "1.0.0-ga" + "version": "1.4.0" }, "servers": [ { @@ -17,7 +17,7 @@ "Public" ], "summary": "List available applications", - "description": "Returns the list of the applications, available to the caller.\n\nThe application is available if any of the versions of the application is assigned to the caller’s organization.\nThe response is paginated and sorted according to the provided parameters.", + "description": "Returns the list of the applications, available to the caller.\n\nThe application is available if any of the versions of the application is assigned to the caller's organization.\nThe response is paginated and sorted according to the provided parameters.", "operationId": "list_applications_v1_applications_get", "security": [ { @@ -210,6 +210,7 @@ "required": true, "schema": { "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", "title": "Version" } } @@ -582,6 +583,24 @@ "title": "Page Size" } }, + { + "name": "for_organization", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs.", + "title": "For Organization" + }, + "description": "Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs." + }, { "name": "sort", "in": "query", @@ -598,10 +617,10 @@ "type": "null" } ], - "description": "Sort the results by one or more fields. Use `+` for ascending and `-` for descending order.\n\n**Available fields:**\n- `run_id`\n- `application_id`\n- `version_number`\n- `custom_metadata`\n- `statistics`\n- `submitted_at`\n- `submitted_by`\n- `terminated_at`\n- `termination_reason`\n\n**Examples:**\n- `?sort=submitted_at` - Sort by creation time (ascending)\n- `?sort=-submitted_at` - Sort by creation time (descending)\n- `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending)\n", + "description": "Sort the results by one or more fields. Use `+` for ascending and `-` for descending order.\n\n**Available fields:**\n- `run_id`\n- `application_id`\n- `version_number`\n- `custom_metadata`\n- `submitted_at`\n- `submitted_by`\n- `terminated_at`\n- `termination_reason`\n\n**Examples:**\n- `?sort=submitted_at` - Sort by creation time (ascending)\n- `?sort=-submitted_at` - Sort by creation time (descending)\n- `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending)\n", "title": "Sort" }, - "description": "Sort the results by one or more fields. Use `+` for ascending and `-` for descending order.\n\n**Available fields:**\n- `run_id`\n- `application_id`\n- `version_number`\n- `custom_metadata`\n- `statistics`\n- `submitted_at`\n- `submitted_by`\n- `terminated_at`\n- `termination_reason`\n\n**Examples:**\n- `?sort=submitted_at` - Sort by creation time (ascending)\n- `?sort=-submitted_at` - Sort by creation time (descending)\n- `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending)\n" + "description": "Sort the results by one or more fields. Use `+` for ascending and `-` for descending order.\n\n**Available fields:**\n- `run_id`\n- `application_id`\n- `version_number`\n- `custom_metadata`\n- `submitted_at`\n- `submitted_by`\n- `terminated_at`\n- `termination_reason`\n\n**Examples:**\n- `?sort=submitted_at` - Sort by creation time (ascending)\n- `?sort=-submitted_at` - Sort by creation time (descending)\n- `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending)\n" } ], "responses": { @@ -1104,6 +1123,79 @@ } } }, + "/v1/runs/{run_id}/artifacts/{artifact_id}/file": { + "get": { + "tags": [ + "Public" + ], + "summary": "Get Artifact Url", + "description": "Download the artifact file with the specified artifact_id, belonging to the specified run.\nThe artifact_is is returned by the `GET /v1/runs/{run_id}/items` endpoint as part of the item results, and can also\nbe retrieved via `GET /v1/runs/{run_id}/items/{external_id}`.\n\nThe endpoint may return a redirect response with a presigned URL to download the artifact file from the storage\nbucket. The presigned URL is valid for a limited time, so it should be used immediately after receiving the response.", + "operationId": "get_artifact_url_v1_runs__run_id__artifacts__artifact_id__file_get", + "security": [ + { + "OAuth2AuthorizationCodeBearer": [] + } + ], + "parameters": [ + { + "name": "run_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "Run id, returned by `POST /runs/` endpoint", + "title": "Run Id" + }, + "description": "Run id, returned by `POST /runs/` endpoint" + }, + { + "name": "artifact_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "description": "The artifact id to download", + "title": "Artifact Id" + }, + "description": "The artifact id to download" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "404": { + "description": "Not Found - Artifact not found for the specified run" + }, + "307": { + "description": "Temporary Redirect - Redirect to the artifact file URL" + }, + "403": { + "description": "Forbidden - You don't have permission to download this artifact" + }, + "410": { + "description": "Gone - Artifact has been deleted" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, "/v1/runs/{run_id}/artifacts": { "delete": { "tags": [ @@ -1461,6 +1553,7 @@ "properties": { "number": { "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", "title": "Number", "description": "The number of the latest version", "examples": [ @@ -1518,6 +1611,7 @@ "custom_metadata": { "anyOf": [ { + "additionalProperties": true, "type": "object" }, { @@ -1602,6 +1696,7 @@ ] }, "metadata_schema": { + "additionalProperties": true, "type": "object", "title": "Metadata Schema" } @@ -1636,6 +1731,7 @@ ] }, "metadata": { + "additionalProperties": true, "type": "object", "title": "Metadata", "description": "The metadata of the artifact, required by the application version. The JSON schema of the metadata can be requested by `/v1/versions/{application_version_id}`. The schema is located in `input_artifacts.[].metadata_schema`", @@ -1675,6 +1771,7 @@ "custom_metadata": { "anyOf": [ { + "additionalProperties": true, "type": "object" }, { @@ -1753,6 +1850,7 @@ "custom_metadata": { "anyOf": [ { + "additionalProperties": true, "type": "object" }, { @@ -1820,6 +1918,17 @@ ], "description": "\nWhen the `state` is `TERMINATED` this will explain why\n`SUCCEEDED` -> Successful processing.\n`USER_ERROR` -> Failed because the provided input was invalid.\n`SYSTEM_ERROR` -> There was an error in the model or platform.\n`SKIPPED` -> Was cancelled\n" }, + "error_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Code" + }, "error_message": { "anyOf": [ { @@ -1833,7 +1942,8 @@ "description": "\n The error message in case the `termination_reason` is in `USER_ERROR` or `SYSTEM_ERROR`\n ", "examples": [ "This item was not processed because the threshold of 3 items finishing in error state (user or system error) was reached before the item was processed.", - "The item was not processed because the run was cancelled by the user before the item was processed.User error raised by Application because the input data provided by the user cannot be processed:\nThe image width is 123000 px, but the maximum width is 100000 px", + "The item was not processed because the run was cancelled by the user before the item was processed.", + "User error raised by Application because the input data provided by the user cannot be processed:\nThe image width is 123000 px, but the maximum width is 100000 px", "A system error occurred during the item execution:\n System went out of memory in cell classification", "An unknown system error occurred during the item execution" ] @@ -1861,19 +1971,6 @@ "type": "array", "title": "Output Artifacts", "description": "\nThe list of the results generated by the application algorithm. The number of files and their\ntypes depend on the particular application version, call `/v1/versions/{version_id}` to get\nthe details.\n " - }, - "error_code": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "title": "Error Code", - "description": "Error code describing the error that occurred during item processing.", - "readOnly": true } }, "type": "object", @@ -1883,8 +1980,7 @@ "custom_metadata", "state", "output", - "output_artifacts", - "error_code" + "output_artifacts" ], "title": "ItemResultReadResponse", "description": "Response schema for items in `List Run Items` endpoint" @@ -2042,6 +2138,7 @@ ] }, "metadata_schema": { + "additionalProperties": true, "type": "object", "title": "Metadata Schema" }, @@ -2081,6 +2178,7 @@ "metadata": { "anyOf": [ { + "additionalProperties": true, "type": "object" }, { @@ -2109,7 +2207,7 @@ "$ref": "#/components/schemas/ArtifactOutput", "description": "The output status of the artifact (NONE, FULL)" }, - "error_message": { + "error_code": { "anyOf": [ { "type": "string" @@ -2118,36 +2216,34 @@ "type": "null" } ], - "title": "Error Message", - "description": "Error message when artifact is in error state" + "title": "Error Code" }, - "download_url": { + "error_message": { "anyOf": [ { - "type": "string", - "maxLength": 2083, - "minLength": 1, - "format": "uri" + "type": "string" }, { "type": "null" } ], - "title": "Download Url", - "description": "\nThe download URL to the output file. The URL is valid for 1 hour after the endpoint is called.\nA new URL is generated every time the endpoint is called.\n " + "title": "Error Message" }, - "error_code": { + "download_url": { "anyOf": [ { - "type": "string" + "type": "string", + "maxLength": 2083, + "minLength": 1, + "format": "uri" }, { "type": "null" } ], - "title": "Error Code", - "description": "Error code describing the error that occurred during artifact processing.", - "readOnly": true + "title": "Download Url", + "description": "\nThe download URL to the output file. The URL is valid for 1 hour after the endpoint is called.\nA new URL is generated every time the endpoint is called.\n ", + "deprecated": true } }, "type": "object", @@ -2155,9 +2251,7 @@ "output_artifact_id", "name", "state", - "output", - "download_url", - "error_code" + "output" ], "title": "OutputArtifactResultReadResponse" }, @@ -2205,6 +2299,7 @@ "custom_metadata": { "anyOf": [ { + "additionalProperties": true, "type": "object" }, { @@ -2220,6 +2315,23 @@ } ] }, + "scheduling": { + "anyOf": [ + { + "$ref": "#/components/schemas/SchedulingRequest" + }, + { + "type": "null" + } + ], + "description": "Optional scheduling constraints for this run.", + "examples": [ + { + "deadline": "2026-03-05T23:59:59Z", + "due_date": "2026-03-04T23:59:59Z" + } + ] + }, "items": { "items": { "$ref": "#/components/schemas/ItemCreationRequest" @@ -2269,13 +2381,15 @@ "type": "string", "format": "uuid", "title": "Run Id", - "default": "Run id", "examples": [ "3fa85f64-5717-4562-b3fc-2c963f66afa6" ] } }, "type": "object", + "required": [ + "run_id" + ], "title": "RunCreationResponse" }, "RunItemStatistics": { @@ -2417,6 +2531,7 @@ "custom_metadata": { "anyOf": [ { + "additionalProperties": true, "type": "object" }, { @@ -2500,6 +2615,17 @@ ], "title": "Num Preceding Items Platform", "description": "How many Items from other Runs are due to begin processing before this Run's next Item does." + }, + "scheduling": { + "anyOf": [ + { + "$ref": "#/components/schemas/SchedulingResponse" + }, + { + "type": "null" + } + ], + "description": "Scheduling constraints set for this run." } }, "type": "object", @@ -2537,6 +2663,76 @@ ], "title": "RunTerminationReason" }, + "SchedulingRequest": { + "properties": { + "due_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Due Date", + "description": "Requested completion time. Items are prioritized to meet this target.", + "examples": [ + "2026-03-04T23:59:59Z" + ] + }, + "deadline": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Deadline", + "description": "Hard deadline. The run will be cancelled if not completed by this time.", + "examples": [ + "2026-03-05T23:59:59Z" + ] + } + }, + "type": "object", + "title": "SchedulingRequest", + "description": "Scheduling constraints for a run." + }, + "SchedulingResponse": { + "properties": { + "due_date": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Due Date" + }, + "deadline": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Deadline" + } + }, + "type": "object", + "title": "SchedulingResponse", + "description": "Scheduling fields returned in run responses." + }, "UserReadResponse": { "properties": { "id": { @@ -2693,6 +2889,13 @@ "type": { "type": "string", "title": "Error Type" + }, + "input": { + "title": "Input" + }, + "ctx": { + "type": "object", + "title": "Context" } }, "type": "object", @@ -2707,6 +2910,7 @@ "properties": { "version_number": { "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", "title": "Version Number", "description": "Semantic version of the application" }, diff --git a/codegen/out/.openapi-generator/FILES b/codegen/out/.openapi-generator/FILES index f28d03b19..ee99c756f 100644 --- a/codegen/out/.openapi-generator/FILES +++ b/codegen/out/.openapi-generator/FILES @@ -32,6 +32,8 @@ aignx/codegen/models/run_output.py aignx/codegen/models/run_read_response.py aignx/codegen/models/run_state.py aignx/codegen/models/run_termination_reason.py +aignx/codegen/models/scheduling_request.py +aignx/codegen/models/scheduling_response.py aignx/codegen/models/user_read_response.py aignx/codegen/models/validation_error.py aignx/codegen/models/validation_error_loc_inner.py diff --git a/codegen/out/aignx/codegen/api/public_api.py b/codegen/out/aignx/codegen/api/public_api.py index 8351bc614..fdaaedae8 100644 --- a/codegen/out/aignx/codegen/api/public_api.py +++ b/codegen/out/aignx/codegen/api/public_api.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -16,7 +16,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union from typing_extensions import Annotated -from pydantic import Field, StrictStr +from pydantic import Field, StrictStr, field_validator from typing import Any, List, Optional from typing_extensions import Annotated from aignx.codegen.models.application_read_response import ApplicationReadResponse @@ -54,7 +54,7 @@ def __init__(self, api_client=None) -> None: def application_version_details_v1_applications_application_id_versions_version_get( self, application_id: StrictStr, - version: StrictStr, + version: Annotated[str, Field(strict=True)], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -128,7 +128,7 @@ def application_version_details_v1_applications_application_id_versions_version_ def application_version_details_v1_applications_application_id_versions_version_get_with_http_info( self, application_id: StrictStr, - version: StrictStr, + version: Annotated[str, Field(strict=True)], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -202,7 +202,7 @@ def application_version_details_v1_applications_application_id_versions_version_ def application_version_details_v1_applications_application_id_versions_version_get_without_preload_content( self, application_id: StrictStr, - version: StrictStr, + version: Annotated[str, Field(strict=True)], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -1161,6 +1161,297 @@ def _delete_run_items_v1_runs_run_id_artifacts_delete_serialize( + @validate_call + def get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get( + self, + run_id: Annotated[StrictStr, Field(description="Run id, returned by `POST /runs/` endpoint")], + artifact_id: Annotated[StrictStr, Field(description="The artifact id to download")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> object: + """Get Artifact Url + + Download the artifact file with the specified artifact_id, belonging to the specified run. The artifact_is is returned by the `GET /v1/runs/{run_id}/items` endpoint as part of the item results, and can also be retrieved via `GET /v1/runs/{run_id}/items/{external_id}`. The endpoint may return a redirect response with a presigned URL to download the artifact file from the storage bucket. The presigned URL is valid for a limited time, so it should be used immediately after receiving the response. + + :param run_id: Run id, returned by `POST /runs/` endpoint (required) + :type run_id: str + :param artifact_id: The artifact id to download (required) + :type artifact_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get_serialize( + run_id=run_id, + artifact_id=artifact_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '404': None, + '307': None, + '403': None, + '410': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get_with_http_info( + self, + run_id: Annotated[StrictStr, Field(description="Run id, returned by `POST /runs/` endpoint")], + artifact_id: Annotated[StrictStr, Field(description="The artifact id to download")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[object]: + """Get Artifact Url + + Download the artifact file with the specified artifact_id, belonging to the specified run. The artifact_is is returned by the `GET /v1/runs/{run_id}/items` endpoint as part of the item results, and can also be retrieved via `GET /v1/runs/{run_id}/items/{external_id}`. The endpoint may return a redirect response with a presigned URL to download the artifact file from the storage bucket. The presigned URL is valid for a limited time, so it should be used immediately after receiving the response. + + :param run_id: Run id, returned by `POST /runs/` endpoint (required) + :type run_id: str + :param artifact_id: The artifact id to download (required) + :type artifact_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get_serialize( + run_id=run_id, + artifact_id=artifact_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '404': None, + '307': None, + '403': None, + '410': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get_without_preload_content( + self, + run_id: Annotated[StrictStr, Field(description="Run id, returned by `POST /runs/` endpoint")], + artifact_id: Annotated[StrictStr, Field(description="The artifact id to download")], + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get Artifact Url + + Download the artifact file with the specified artifact_id, belonging to the specified run. The artifact_is is returned by the `GET /v1/runs/{run_id}/items` endpoint as part of the item results, and can also be retrieved via `GET /v1/runs/{run_id}/items/{external_id}`. The endpoint may return a redirect response with a presigned URL to download the artifact file from the storage bucket. The presigned URL is valid for a limited time, so it should be used immediately after receiving the response. + + :param run_id: Run id, returned by `POST /runs/` endpoint (required) + :type run_id: str + :param artifact_id: The artifact id to download (required) + :type artifact_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get_serialize( + run_id=run_id, + artifact_id=artifact_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "object", + '404': None, + '307': None, + '403': None, + '410': None, + '422': "HTTPValidationError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get_serialize( + self, + run_id, + artifact_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if run_id is not None: + _path_params['run_id'] = run_id + if artifact_id is not None: + _path_params['artifact_id'] = artifact_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'OAuth2AuthorizationCodeBearer' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/api/v1/runs/{run_id}/artifacts/{artifact_id}/file', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + @validate_call def get_item_by_run_v1_runs_run_id_items_external_id_get( self, @@ -1983,7 +2274,7 @@ def list_applications_v1_applications_get( ) -> List[ApplicationReadShortResponse]: """List available applications - Returns the list of the applications, available to the caller. The application is available if any of the versions of the application is assigned to the caller’s organization. The response is paginated and sorted according to the provided parameters. + Returns the list of the applications, available to the caller. The application is available if any of the versions of the application is assigned to the caller's organization. The response is paginated and sorted according to the provided parameters. :param page: :type page: int @@ -2060,7 +2351,7 @@ def list_applications_v1_applications_get_with_http_info( ) -> ApiResponse[List[ApplicationReadShortResponse]]: """List available applications - Returns the list of the applications, available to the caller. The application is available if any of the versions of the application is assigned to the caller’s organization. The response is paginated and sorted according to the provided parameters. + Returns the list of the applications, available to the caller. The application is available if any of the versions of the application is assigned to the caller's organization. The response is paginated and sorted according to the provided parameters. :param page: :type page: int @@ -2137,7 +2428,7 @@ def list_applications_v1_applications_get_without_preload_content( ) -> RESTResponseType: """List available applications - Returns the list of the applications, available to the caller. The application is available if any of the versions of the application is assigned to the caller’s organization. The response is paginated and sorted according to the provided parameters. + Returns the list of the applications, available to the caller. The application is available if any of the versions of the application is assigned to the caller's organization. The response is paginated and sorted according to the provided parameters. :param page: :type page: int @@ -2681,7 +2972,8 @@ def list_runs_v1_runs_get( custom_metadata: Annotated[Optional[Annotated[str, Field(strict=True, max_length=1000)]], Field(description="Use PostgreSQL JSONPath expressions to filter runs by their custom_metadata. #### URL Encoding Required **Important**: JSONPath expressions contain special characters that must be URL-encoded when used in query parameters. Most HTTP clients handle this automatically, but when constructing URLs manually, please ensure proper encoding. #### Examples (Clear Format): - **Field existence**: `$.study` - Runs that have a study field defined - **Exact value match**: `$.study ? (@ == \"high\")` - Runs with specific study value - **Numeric comparison**: `$.confidence_score ? (@ > 0.75)` - Runs with confidence score greater than 0.75 - **Array operations**: `$.tags[*] ? (@ == \"draft\")` - Runs with tags array containing \"draft\" - **Complex conditions**: `$.resources ? (@.gpu_count > 2 && @.memory_gb >= 16)` - Runs with high resource requirements #### Examples (URL-Encoded Format): - **Field existence**: `%24.study` - **Exact value match**: `%24.study%20%3F%20(%40%20%3D%3D%20%22high%22)` - **Numeric comparison**: `%24.confidence_score%20%3F%20(%40%20%3E%200.75)` - **Array operations**: `%24.tags%5B*%5D%20%3F%20(%40%20%3D%3D%20%22draft%22)` - **Complex conditions**: `%24.resources%20%3F%20(%40.gpu_count%20%3E%202%20%26%26%20%40.memory_gb%20%3E%3D%2016)` #### Notes - JSONPath expressions are evaluated using PostgreSQL's `@?` operator - The `$.` prefix is automatically added to root-level field references if missing - String values in conditions must be enclosed in double quotes - Use `&&` for AND operations and `||` for OR operations - Regular expressions use `like_regex` with standard regex syntax - **Please remember to URL-encode the entire JSONPath expression when making HTTP requests** ")] = None, page: Optional[Annotated[int, Field(strict=True, ge=1)]] = None, page_size: Optional[Annotated[int, Field(le=100, strict=True, ge=5)]] = None, - sort: Annotated[Optional[List[StrictStr]], Field(description="Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `statistics` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) ")] = None, + for_organization: Annotated[Optional[StrictStr], Field(description="Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs.")] = None, + sort: Annotated[Optional[List[StrictStr]], Field(description="Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) ")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -2711,7 +3003,9 @@ def list_runs_v1_runs_get( :type page: int :param page_size: :type page_size: int - :param sort: Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `statistics` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) + :param for_organization: Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs. + :type for_organization: str + :param sort: Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) :type sort: List[str] :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -2742,6 +3036,7 @@ def list_runs_v1_runs_get( custom_metadata=custom_metadata, page=page, page_size=page_size, + for_organization=for_organization, sort=sort, _request_auth=_request_auth, _content_type=_content_type, @@ -2774,7 +3069,8 @@ def list_runs_v1_runs_get_with_http_info( custom_metadata: Annotated[Optional[Annotated[str, Field(strict=True, max_length=1000)]], Field(description="Use PostgreSQL JSONPath expressions to filter runs by their custom_metadata. #### URL Encoding Required **Important**: JSONPath expressions contain special characters that must be URL-encoded when used in query parameters. Most HTTP clients handle this automatically, but when constructing URLs manually, please ensure proper encoding. #### Examples (Clear Format): - **Field existence**: `$.study` - Runs that have a study field defined - **Exact value match**: `$.study ? (@ == \"high\")` - Runs with specific study value - **Numeric comparison**: `$.confidence_score ? (@ > 0.75)` - Runs with confidence score greater than 0.75 - **Array operations**: `$.tags[*] ? (@ == \"draft\")` - Runs with tags array containing \"draft\" - **Complex conditions**: `$.resources ? (@.gpu_count > 2 && @.memory_gb >= 16)` - Runs with high resource requirements #### Examples (URL-Encoded Format): - **Field existence**: `%24.study` - **Exact value match**: `%24.study%20%3F%20(%40%20%3D%3D%20%22high%22)` - **Numeric comparison**: `%24.confidence_score%20%3F%20(%40%20%3E%200.75)` - **Array operations**: `%24.tags%5B*%5D%20%3F%20(%40%20%3D%3D%20%22draft%22)` - **Complex conditions**: `%24.resources%20%3F%20(%40.gpu_count%20%3E%202%20%26%26%20%40.memory_gb%20%3E%3D%2016)` #### Notes - JSONPath expressions are evaluated using PostgreSQL's `@?` operator - The `$.` prefix is automatically added to root-level field references if missing - String values in conditions must be enclosed in double quotes - Use `&&` for AND operations and `||` for OR operations - Regular expressions use `like_regex` with standard regex syntax - **Please remember to URL-encode the entire JSONPath expression when making HTTP requests** ")] = None, page: Optional[Annotated[int, Field(strict=True, ge=1)]] = None, page_size: Optional[Annotated[int, Field(le=100, strict=True, ge=5)]] = None, - sort: Annotated[Optional[List[StrictStr]], Field(description="Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `statistics` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) ")] = None, + for_organization: Annotated[Optional[StrictStr], Field(description="Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs.")] = None, + sort: Annotated[Optional[List[StrictStr]], Field(description="Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) ")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -2804,7 +3100,9 @@ def list_runs_v1_runs_get_with_http_info( :type page: int :param page_size: :type page_size: int - :param sort: Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `statistics` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) + :param for_organization: Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs. + :type for_organization: str + :param sort: Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) :type sort: List[str] :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -2835,6 +3133,7 @@ def list_runs_v1_runs_get_with_http_info( custom_metadata=custom_metadata, page=page, page_size=page_size, + for_organization=for_organization, sort=sort, _request_auth=_request_auth, _content_type=_content_type, @@ -2867,7 +3166,8 @@ def list_runs_v1_runs_get_without_preload_content( custom_metadata: Annotated[Optional[Annotated[str, Field(strict=True, max_length=1000)]], Field(description="Use PostgreSQL JSONPath expressions to filter runs by their custom_metadata. #### URL Encoding Required **Important**: JSONPath expressions contain special characters that must be URL-encoded when used in query parameters. Most HTTP clients handle this automatically, but when constructing URLs manually, please ensure proper encoding. #### Examples (Clear Format): - **Field existence**: `$.study` - Runs that have a study field defined - **Exact value match**: `$.study ? (@ == \"high\")` - Runs with specific study value - **Numeric comparison**: `$.confidence_score ? (@ > 0.75)` - Runs with confidence score greater than 0.75 - **Array operations**: `$.tags[*] ? (@ == \"draft\")` - Runs with tags array containing \"draft\" - **Complex conditions**: `$.resources ? (@.gpu_count > 2 && @.memory_gb >= 16)` - Runs with high resource requirements #### Examples (URL-Encoded Format): - **Field existence**: `%24.study` - **Exact value match**: `%24.study%20%3F%20(%40%20%3D%3D%20%22high%22)` - **Numeric comparison**: `%24.confidence_score%20%3F%20(%40%20%3E%200.75)` - **Array operations**: `%24.tags%5B*%5D%20%3F%20(%40%20%3D%3D%20%22draft%22)` - **Complex conditions**: `%24.resources%20%3F%20(%40.gpu_count%20%3E%202%20%26%26%20%40.memory_gb%20%3E%3D%2016)` #### Notes - JSONPath expressions are evaluated using PostgreSQL's `@?` operator - The `$.` prefix is automatically added to root-level field references if missing - String values in conditions must be enclosed in double quotes - Use `&&` for AND operations and `||` for OR operations - Regular expressions use `like_regex` with standard regex syntax - **Please remember to URL-encode the entire JSONPath expression when making HTTP requests** ")] = None, page: Optional[Annotated[int, Field(strict=True, ge=1)]] = None, page_size: Optional[Annotated[int, Field(le=100, strict=True, ge=5)]] = None, - sort: Annotated[Optional[List[StrictStr]], Field(description="Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `statistics` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) ")] = None, + for_organization: Annotated[Optional[StrictStr], Field(description="Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs.")] = None, + sort: Annotated[Optional[List[StrictStr]], Field(description="Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) ")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -2897,7 +3197,9 @@ def list_runs_v1_runs_get_without_preload_content( :type page: int :param page_size: :type page_size: int - :param sort: Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `statistics` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) + :param for_organization: Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs. + :type for_organization: str + :param sort: Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) :type sort: List[str] :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -2928,6 +3230,7 @@ def list_runs_v1_runs_get_without_preload_content( custom_metadata=custom_metadata, page=page, page_size=page_size, + for_organization=for_organization, sort=sort, _request_auth=_request_auth, _content_type=_content_type, @@ -2955,6 +3258,7 @@ def _list_runs_v1_runs_get_serialize( custom_metadata, page, page_size, + for_organization, sort, _request_auth, _content_type, @@ -3003,6 +3307,10 @@ def _list_runs_v1_runs_get_serialize( _query_params.append(('page_size', page_size)) + if for_organization is not None: + + _query_params.append(('for_organization', for_organization)) + if sort is not None: _query_params.append(('sort', sort)) diff --git a/codegen/out/aignx/codegen/api_client.py b/codegen/out/aignx/codegen/api_client.py index ab2292b5e..b56edae2b 100644 --- a/codegen/out/aignx/codegen/api_client.py +++ b/codegen/out/aignx/codegen/api_client.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/configuration.py b/codegen/out/aignx/codegen/configuration.py index aaf8956a4..ac221d92e 100644 --- a/codegen/out/aignx/codegen/configuration.py +++ b/codegen/out/aignx/codegen/configuration.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -502,7 +502,7 @@ def to_debug_report(self) -> str: return "Python SDK Debug Report:\n"\ "OS: {env}\n"\ "Python Version: {pyversion}\n"\ - "Version of the API: 1.0.0-ga\n"\ + "Version of the API: 1.4.0\n"\ "SDK Package Version: 1.0.0".\ format(env=sys.platform, pyversion=sys.version) diff --git a/codegen/out/aignx/codegen/exceptions.py b/codegen/out/aignx/codegen/exceptions.py index d5bf1d3e3..4f7dfe5b4 100644 --- a/codegen/out/aignx/codegen/exceptions.py +++ b/codegen/out/aignx/codegen/exceptions.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/__init__.py b/codegen/out/aignx/codegen/models/__init__.py index b806fec99..382b6ac7b 100644 --- a/codegen/out/aignx/codegen/models/__init__.py +++ b/codegen/out/aignx/codegen/models/__init__.py @@ -1,35 +1,37 @@ -from .output_artifact_visibility import * -from .organization_read_response import * -from .me_read_response import * -from .run_item_statistics import * -from .validation_error import * -from .output_artifact_result_read_response import * -from .version_read_response import * +from .item_result_read_response import * +from .run_output import * +from .artifact_state import * +from .validation_error_loc_inner import * +from .run_state import * from .item_output import * -from .run_termination_reason import * from .run_creation_response import * +from .scheduling_request import * +from .organization_read_response import * +from .validation_error import * +from .application_read_response import * +from .application_read_short_response import * from .output_artifact_scope import * -from .run_output import * -from .item_result_read_response import * -from .application_version import * -from .run_read_response import * -from .run_state import * +from .scheduling_response import * +from .me_read_response import * from .input_artifact_creation_request import * -from .custom_metadata_update_response import * -from .input_artifact import * -from .custom_metadata_update_request import * +from .item_creation_request import * from .item_state import * -from .artifact_state import * -from .application_read_short_response import * -from .output_artifact import * -from .user_read_response import * -from .item_termination_reason import * -from .artifact_output import * from .auth0_organization import * -from .auth0_user import * -from .item_creation_request import * +from .application_version import * from .http_validation_error import * -from .validation_error_loc_inner import * +from .custom_metadata_update_response import * +from .user_read_response import * +from .run_termination_reason import * +from .input_artifact import * +from .output_artifact_result_read_response import * +from .version_read_response import * +from .auth0_user import * +from .run_read_response import * from .artifact_termination_reason import * from .run_creation_request import * -from .application_read_response import * +from .item_termination_reason import * +from .run_item_statistics import * +from .output_artifact_visibility import * +from .custom_metadata_update_request import * +from .artifact_output import * +from .output_artifact import * diff --git a/codegen/out/aignx/codegen/models/application_read_response.py b/codegen/out/aignx/codegen/models/application_read_response.py index 64cd5739a..9fea43961 100644 --- a/codegen/out/aignx/codegen/models/application_read_response.py +++ b/codegen/out/aignx/codegen/models/application_read_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/application_read_short_response.py b/codegen/out/aignx/codegen/models/application_read_short_response.py index 0302af0b0..da128fa5e 100644 --- a/codegen/out/aignx/codegen/models/application_read_short_response.py +++ b/codegen/out/aignx/codegen/models/application_read_short_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/application_version.py b/codegen/out/aignx/codegen/models/application_version.py index 8ecf00c67..b7c6b700a 100644 --- a/codegen/out/aignx/codegen/models/application_version.py +++ b/codegen/out/aignx/codegen/models/application_version.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -18,8 +18,9 @@ import json from datetime import datetime -from pydantic import BaseModel, ConfigDict, Field, StrictStr +from pydantic import BaseModel, ConfigDict, Field, field_validator from typing import Any, ClassVar, Dict, List +from typing_extensions import Annotated from typing import Optional, Set from typing_extensions import Self @@ -27,10 +28,17 @@ class ApplicationVersion(BaseModel): """ ApplicationVersion """ # noqa: E501 - number: StrictStr = Field(description="The number of the latest version") + number: Annotated[str, Field(strict=True)] = Field(description="The number of the latest version") released_at: datetime = Field(description="The timestamp for when the application version was made available in the Platform") __properties: ClassVar[List[str]] = ["number", "released_at"] + @field_validator('number') + def number_validate_regular_expression(cls, value): + """Validates the regular expression""" + if not re.match(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", value): + raise ValueError(r"must validate the regular expression /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/") + return value + model_config = ConfigDict( populate_by_name=True, validate_assignment=True, diff --git a/codegen/out/aignx/codegen/models/artifact_output.py b/codegen/out/aignx/codegen/models/artifact_output.py index 5d8a8d9bf..150698d7c 100644 --- a/codegen/out/aignx/codegen/models/artifact_output.py +++ b/codegen/out/aignx/codegen/models/artifact_output.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/artifact_state.py b/codegen/out/aignx/codegen/models/artifact_state.py index aad53f962..b90f2272a 100644 --- a/codegen/out/aignx/codegen/models/artifact_state.py +++ b/codegen/out/aignx/codegen/models/artifact_state.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/artifact_termination_reason.py b/codegen/out/aignx/codegen/models/artifact_termination_reason.py index 018a8fe89..6f06896b0 100644 --- a/codegen/out/aignx/codegen/models/artifact_termination_reason.py +++ b/codegen/out/aignx/codegen/models/artifact_termination_reason.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/custom_metadata_update_request.py b/codegen/out/aignx/codegen/models/custom_metadata_update_request.py index 649eec35e..5cd0650b0 100644 --- a/codegen/out/aignx/codegen/models/custom_metadata_update_request.py +++ b/codegen/out/aignx/codegen/models/custom_metadata_update_request.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/custom_metadata_update_response.py b/codegen/out/aignx/codegen/models/custom_metadata_update_response.py index 01da04914..c1bf3b6db 100644 --- a/codegen/out/aignx/codegen/models/custom_metadata_update_response.py +++ b/codegen/out/aignx/codegen/models/custom_metadata_update_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/http_validation_error.py b/codegen/out/aignx/codegen/models/http_validation_error.py index 0e68b1426..f3834b746 100644 --- a/codegen/out/aignx/codegen/models/http_validation_error.py +++ b/codegen/out/aignx/codegen/models/http_validation_error.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/input_artifact.py b/codegen/out/aignx/codegen/models/input_artifact.py index f4877d5b4..02324f488 100644 --- a/codegen/out/aignx/codegen/models/input_artifact.py +++ b/codegen/out/aignx/codegen/models/input_artifact.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/input_artifact_creation_request.py b/codegen/out/aignx/codegen/models/input_artifact_creation_request.py index 60c6bb9c3..80af637ae 100644 --- a/codegen/out/aignx/codegen/models/input_artifact_creation_request.py +++ b/codegen/out/aignx/codegen/models/input_artifact_creation_request.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/item_creation_request.py b/codegen/out/aignx/codegen/models/item_creation_request.py index 6aee0f1f7..593eff96c 100644 --- a/codegen/out/aignx/codegen/models/item_creation_request.py +++ b/codegen/out/aignx/codegen/models/item_creation_request.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/item_output.py b/codegen/out/aignx/codegen/models/item_output.py index 90e8f9adb..d313e54c9 100644 --- a/codegen/out/aignx/codegen/models/item_output.py +++ b/codegen/out/aignx/codegen/models/item_output.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/item_result_read_response.py b/codegen/out/aignx/codegen/models/item_result_read_response.py index 11aba77d3..f4f334179 100644 --- a/codegen/out/aignx/codegen/models/item_result_read_response.py +++ b/codegen/out/aignx/codegen/models/item_result_read_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -40,11 +40,11 @@ class ItemResultReadResponse(BaseModel): state: ItemState = Field(description=" The item moves from `PENDING` to `PROCESSING` to `TERMINATED` state. When terminated, consult the `termination_reason` property to see whether it was successful. ") output: ItemOutput = Field(description="The output status of the item (NONE, FULL)") termination_reason: Optional[ItemTerminationReason] = None + error_code: Optional[StrictStr] = None error_message: Optional[StrictStr] = None terminated_at: Optional[datetime] = None output_artifacts: List[OutputArtifactResultReadResponse] = Field(description=" The list of the results generated by the application algorithm. The number of files and their types depend on the particular application version, call `/v1/versions/{version_id}` to get the details. ") - error_code: Optional[StrictStr] - __properties: ClassVar[List[str]] = ["item_id", "external_id", "custom_metadata", "custom_metadata_checksum", "queue_position_org", "queue_position_platform", "state", "output", "termination_reason", "error_message", "terminated_at", "output_artifacts", "error_code"] + __properties: ClassVar[List[str]] = ["item_id", "external_id", "custom_metadata", "custom_metadata_checksum", "queue_position_org", "queue_position_platform", "state", "output", "termination_reason", "error_code", "error_message", "terminated_at", "output_artifacts"] model_config = ConfigDict( populate_by_name=True, @@ -117,6 +117,11 @@ def to_dict(self) -> Dict[str, Any]: if self.termination_reason is None and "termination_reason" in self.model_fields_set: _dict['termination_reason'] = None + # set to None if error_code (nullable) is None + # and model_fields_set contains the field + if self.error_code is None and "error_code" in self.model_fields_set: + _dict['error_code'] = None + # set to None if error_message (nullable) is None # and model_fields_set contains the field if self.error_message is None and "error_message" in self.model_fields_set: @@ -127,11 +132,6 @@ def to_dict(self) -> Dict[str, Any]: if self.terminated_at is None and "terminated_at" in self.model_fields_set: _dict['terminated_at'] = None - # set to None if error_code (nullable) is None - # and model_fields_set contains the field - if self.error_code is None and "error_code" in self.model_fields_set: - _dict['error_code'] = None - return _dict @classmethod @@ -153,10 +153,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "state": obj.get("state"), "output": obj.get("output"), "termination_reason": obj.get("termination_reason"), + "error_code": obj.get("error_code"), "error_message": obj.get("error_message"), "terminated_at": obj.get("terminated_at"), - "output_artifacts": [OutputArtifactResultReadResponse.from_dict(_item) for _item in obj["output_artifacts"]] if obj.get("output_artifacts") is not None else None, - "error_code": obj.get("error_code") + "output_artifacts": [OutputArtifactResultReadResponse.from_dict(_item) for _item in obj["output_artifacts"]] if obj.get("output_artifacts") is not None else None }) return _obj diff --git a/codegen/out/aignx/codegen/models/item_state.py b/codegen/out/aignx/codegen/models/item_state.py index 737d8fbe3..8e4928c16 100644 --- a/codegen/out/aignx/codegen/models/item_state.py +++ b/codegen/out/aignx/codegen/models/item_state.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/item_termination_reason.py b/codegen/out/aignx/codegen/models/item_termination_reason.py index 7ffdcb5fa..04070e10b 100644 --- a/codegen/out/aignx/codegen/models/item_termination_reason.py +++ b/codegen/out/aignx/codegen/models/item_termination_reason.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/me_read_response.py b/codegen/out/aignx/codegen/models/me_read_response.py index 45ae03b77..b25865ec2 100644 --- a/codegen/out/aignx/codegen/models/me_read_response.py +++ b/codegen/out/aignx/codegen/models/me_read_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/organization_read_response.py b/codegen/out/aignx/codegen/models/organization_read_response.py index 34a15cf44..7b3b5c4ee 100644 --- a/codegen/out/aignx/codegen/models/organization_read_response.py +++ b/codegen/out/aignx/codegen/models/organization_read_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/output_artifact.py b/codegen/out/aignx/codegen/models/output_artifact.py index 837ac7818..dd62295a7 100644 --- a/codegen/out/aignx/codegen/models/output_artifact.py +++ b/codegen/out/aignx/codegen/models/output_artifact.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py b/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py index cb6cb2dae..131c0101f 100644 --- a/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py +++ b/codegen/out/aignx/codegen/models/output_artifact_result_read_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -36,10 +36,10 @@ class OutputArtifactResultReadResponse(BaseModel): state: ArtifactState = Field(description="The current state of the artifact (PENDING, PROCESSING, TERMINATED)") termination_reason: Optional[ArtifactTerminationReason] = None output: ArtifactOutput = Field(description="The output status of the artifact (NONE, FULL)") + error_code: Optional[StrictStr] = None error_message: Optional[StrictStr] = None - download_url: Optional[Annotated[str, Field(min_length=1, strict=True, max_length=2083)]] - error_code: Optional[StrictStr] - __properties: ClassVar[List[str]] = ["output_artifact_id", "name", "metadata", "state", "termination_reason", "output", "error_message", "download_url", "error_code"] + download_url: Optional[Annotated[str, Field(min_length=1, strict=True, max_length=2083)]] = None + __properties: ClassVar[List[str]] = ["output_artifact_id", "name", "metadata", "state", "termination_reason", "output", "error_code", "error_message", "download_url"] model_config = ConfigDict( populate_by_name=True, @@ -90,6 +90,11 @@ def to_dict(self) -> Dict[str, Any]: if self.termination_reason is None and "termination_reason" in self.model_fields_set: _dict['termination_reason'] = None + # set to None if error_code (nullable) is None + # and model_fields_set contains the field + if self.error_code is None and "error_code" in self.model_fields_set: + _dict['error_code'] = None + # set to None if error_message (nullable) is None # and model_fields_set contains the field if self.error_message is None and "error_message" in self.model_fields_set: @@ -100,11 +105,6 @@ def to_dict(self) -> Dict[str, Any]: if self.download_url is None and "download_url" in self.model_fields_set: _dict['download_url'] = None - # set to None if error_code (nullable) is None - # and model_fields_set contains the field - if self.error_code is None and "error_code" in self.model_fields_set: - _dict['error_code'] = None - return _dict @classmethod @@ -123,9 +123,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "state": obj.get("state"), "termination_reason": obj.get("termination_reason"), "output": obj.get("output"), + "error_code": obj.get("error_code"), "error_message": obj.get("error_message"), - "download_url": obj.get("download_url"), - "error_code": obj.get("error_code") + "download_url": obj.get("download_url") }) return _obj diff --git a/codegen/out/aignx/codegen/models/output_artifact_scope.py b/codegen/out/aignx/codegen/models/output_artifact_scope.py index 0cf11f0cd..d1f927a4c 100644 --- a/codegen/out/aignx/codegen/models/output_artifact_scope.py +++ b/codegen/out/aignx/codegen/models/output_artifact_scope.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/output_artifact_visibility.py b/codegen/out/aignx/codegen/models/output_artifact_visibility.py index 619684588..48a346d0e 100644 --- a/codegen/out/aignx/codegen/models/output_artifact_visibility.py +++ b/codegen/out/aignx/codegen/models/output_artifact_visibility.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/run_creation_request.py b/codegen/out/aignx/codegen/models/run_creation_request.py index 7b004a37d..c6e7bfb95 100644 --- a/codegen/out/aignx/codegen/models/run_creation_request.py +++ b/codegen/out/aignx/codegen/models/run_creation_request.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -21,6 +21,7 @@ from typing import Any, ClassVar, Dict, List, Optional from typing_extensions import Annotated from aignx.codegen.models.item_creation_request import ItemCreationRequest +from aignx.codegen.models.scheduling_request import SchedulingRequest from typing import Optional, Set from typing_extensions import Self @@ -31,8 +32,9 @@ class RunCreationRequest(BaseModel): application_id: StrictStr = Field(description="Unique ID for the application to use for processing") version_number: Optional[StrictStr] = None custom_metadata: Optional[Dict[str, Any]] = None + scheduling: Optional[SchedulingRequest] = None items: Annotated[List[ItemCreationRequest], Field(min_length=1)] = Field(description="List of items (slides) to process. Each item represents a whole slide image (WSI) with its associated metadata and artifacts") - __properties: ClassVar[List[str]] = ["application_id", "version_number", "custom_metadata", "items"] + __properties: ClassVar[List[str]] = ["application_id", "version_number", "custom_metadata", "scheduling", "items"] model_config = ConfigDict( populate_by_name=True, @@ -73,6 +75,9 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of scheduling + if self.scheduling: + _dict['scheduling'] = self.scheduling.to_dict() # override the default output from pydantic by calling `to_dict()` of each item in items (list) _items = [] if self.items: @@ -90,6 +95,11 @@ def to_dict(self) -> Dict[str, Any]: if self.custom_metadata is None and "custom_metadata" in self.model_fields_set: _dict['custom_metadata'] = None + # set to None if scheduling (nullable) is None + # and model_fields_set contains the field + if self.scheduling is None and "scheduling" in self.model_fields_set: + _dict['scheduling'] = None + return _dict @classmethod @@ -105,6 +115,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "application_id": obj.get("application_id"), "version_number": obj.get("version_number"), "custom_metadata": obj.get("custom_metadata"), + "scheduling": SchedulingRequest.from_dict(obj["scheduling"]) if obj.get("scheduling") is not None else None, "items": [ItemCreationRequest.from_dict(_item) for _item in obj["items"]] if obj.get("items") is not None else None }) return _obj diff --git a/codegen/out/aignx/codegen/models/run_creation_response.py b/codegen/out/aignx/codegen/models/run_creation_response.py index 7419f92e9..7277899ff 100644 --- a/codegen/out/aignx/codegen/models/run_creation_response.py +++ b/codegen/out/aignx/codegen/models/run_creation_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -18,7 +18,7 @@ import json from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List, Optional +from typing import Any, ClassVar, Dict, List from typing import Optional, Set from typing_extensions import Self @@ -26,7 +26,7 @@ class RunCreationResponse(BaseModel): """ RunCreationResponse """ # noqa: E501 - run_id: Optional[StrictStr] = 'Run id' + run_id: StrictStr __properties: ClassVar[List[str]] = ["run_id"] model_config = ConfigDict( @@ -80,7 +80,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "run_id": obj.get("run_id") if obj.get("run_id") is not None else 'Run id' + "run_id": obj.get("run_id") }) return _obj diff --git a/codegen/out/aignx/codegen/models/run_item_statistics.py b/codegen/out/aignx/codegen/models/run_item_statistics.py index 33412d18e..f3d24fa07 100644 --- a/codegen/out/aignx/codegen/models/run_item_statistics.py +++ b/codegen/out/aignx/codegen/models/run_item_statistics.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/run_output.py b/codegen/out/aignx/codegen/models/run_output.py index f2af3f3e8..29837ab76 100644 --- a/codegen/out/aignx/codegen/models/run_output.py +++ b/codegen/out/aignx/codegen/models/run_output.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/run_read_response.py b/codegen/out/aignx/codegen/models/run_read_response.py index 53f0f8ca5..0e3ff1a31 100644 --- a/codegen/out/aignx/codegen/models/run_read_response.py +++ b/codegen/out/aignx/codegen/models/run_read_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -24,6 +24,7 @@ from aignx.codegen.models.run_output import RunOutput from aignx.codegen.models.run_state import RunState from aignx.codegen.models.run_termination_reason import RunTerminationReason +from aignx.codegen.models.scheduling_response import SchedulingResponse from typing import Optional, Set from typing_extensions import Self @@ -47,7 +48,8 @@ class RunReadResponse(BaseModel): terminated_at: Optional[datetime] = None num_preceding_items_org: Optional[StrictInt] = None num_preceding_items_platform: Optional[StrictInt] = None - __properties: ClassVar[List[str]] = ["run_id", "application_id", "version_number", "state", "output", "termination_reason", "error_code", "error_message", "statistics", "custom_metadata", "custom_metadata_checksum", "submitted_at", "submitted_by", "terminated_at", "num_preceding_items_org", "num_preceding_items_platform"] + scheduling: Optional[SchedulingResponse] = None + __properties: ClassVar[List[str]] = ["run_id", "application_id", "version_number", "state", "output", "termination_reason", "error_code", "error_message", "statistics", "custom_metadata", "custom_metadata_checksum", "submitted_at", "submitted_by", "terminated_at", "num_preceding_items_org", "num_preceding_items_platform", "scheduling"] model_config = ConfigDict( populate_by_name=True, @@ -91,6 +93,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of statistics if self.statistics: _dict['statistics'] = self.statistics.to_dict() + # override the default output from pydantic by calling `to_dict()` of scheduling + if self.scheduling: + _dict['scheduling'] = self.scheduling.to_dict() # set to None if termination_reason (nullable) is None # and model_fields_set contains the field if self.termination_reason is None and "termination_reason" in self.model_fields_set: @@ -131,6 +136,11 @@ def to_dict(self) -> Dict[str, Any]: if self.num_preceding_items_platform is None and "num_preceding_items_platform" in self.model_fields_set: _dict['num_preceding_items_platform'] = None + # set to None if scheduling (nullable) is None + # and model_fields_set contains the field + if self.scheduling is None and "scheduling" in self.model_fields_set: + _dict['scheduling'] = None + return _dict @classmethod @@ -158,7 +168,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "submitted_by": obj.get("submitted_by"), "terminated_at": obj.get("terminated_at"), "num_preceding_items_org": obj.get("num_preceding_items_org"), - "num_preceding_items_platform": obj.get("num_preceding_items_platform") + "num_preceding_items_platform": obj.get("num_preceding_items_platform"), + "scheduling": SchedulingResponse.from_dict(obj["scheduling"]) if obj.get("scheduling") is not None else None }) return _obj diff --git a/codegen/out/aignx/codegen/models/run_state.py b/codegen/out/aignx/codegen/models/run_state.py index 22f32e7be..734e55890 100644 --- a/codegen/out/aignx/codegen/models/run_state.py +++ b/codegen/out/aignx/codegen/models/run_state.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/run_termination_reason.py b/codegen/out/aignx/codegen/models/run_termination_reason.py index 44b8a5653..5e700de27 100644 --- a/codegen/out/aignx/codegen/models/run_termination_reason.py +++ b/codegen/out/aignx/codegen/models/run_termination_reason.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/scheduling_request.py b/codegen/out/aignx/codegen/models/scheduling_request.py new file mode 100644 index 000000000..6b3be7d0d --- /dev/null +++ b/codegen/out/aignx/codegen/models/scheduling_request.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" + Aignostics Platform API + + The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. + + The version of the OpenAPI document: 1.4.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class SchedulingRequest(BaseModel): + """ + Scheduling constraints for a run. + """ # noqa: E501 + due_date: Optional[datetime] = None + deadline: Optional[datetime] = None + __properties: ClassVar[List[str]] = ["due_date", "deadline"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of SchedulingRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if due_date (nullable) is None + # and model_fields_set contains the field + if self.due_date is None and "due_date" in self.model_fields_set: + _dict['due_date'] = None + + # set to None if deadline (nullable) is None + # and model_fields_set contains the field + if self.deadline is None and "deadline" in self.model_fields_set: + _dict['deadline'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SchedulingRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "due_date": obj.get("due_date"), + "deadline": obj.get("deadline") + }) + return _obj + + diff --git a/codegen/out/aignx/codegen/models/scheduling_response.py b/codegen/out/aignx/codegen/models/scheduling_response.py new file mode 100644 index 000000000..fd647acce --- /dev/null +++ b/codegen/out/aignx/codegen/models/scheduling_response.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" + Aignostics Platform API + + The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. + + The version of the OpenAPI document: 1.4.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class SchedulingResponse(BaseModel): + """ + Scheduling fields returned in run responses. + """ # noqa: E501 + due_date: Optional[datetime] = None + deadline: Optional[datetime] = None + __properties: ClassVar[List[str]] = ["due_date", "deadline"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of SchedulingResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if due_date (nullable) is None + # and model_fields_set contains the field + if self.due_date is None and "due_date" in self.model_fields_set: + _dict['due_date'] = None + + # set to None if deadline (nullable) is None + # and model_fields_set contains the field + if self.deadline is None and "deadline" in self.model_fields_set: + _dict['deadline'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SchedulingResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "due_date": obj.get("due_date"), + "deadline": obj.get("deadline") + }) + return _obj + + diff --git a/codegen/out/aignx/codegen/models/user_read_response.py b/codegen/out/aignx/codegen/models/user_read_response.py index b82796ccd..542122424 100644 --- a/codegen/out/aignx/codegen/models/user_read_response.py +++ b/codegen/out/aignx/codegen/models/user_read_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/validation_error.py b/codegen/out/aignx/codegen/models/validation_error.py index 0f0574bdb..17fa7ef39 100644 --- a/codegen/out/aignx/codegen/models/validation_error.py +++ b/codegen/out/aignx/codegen/models/validation_error.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -18,7 +18,7 @@ import json from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List +from typing import Any, ClassVar, Dict, List, Optional from aignx.codegen.models.validation_error_loc_inner import ValidationErrorLocInner from typing import Optional, Set from typing_extensions import Self @@ -30,7 +30,9 @@ class ValidationError(BaseModel): loc: List[ValidationErrorLocInner] msg: StrictStr type: StrictStr - __properties: ClassVar[List[str]] = ["loc", "msg", "type"] + input: Optional[Any] = None + ctx: Optional[Dict[str, Any]] = None + __properties: ClassVar[List[str]] = ["loc", "msg", "type", "input", "ctx"] model_config = ConfigDict( populate_by_name=True, @@ -78,6 +80,11 @@ def to_dict(self) -> Dict[str, Any]: if _item_loc: _items.append(_item_loc.to_dict()) _dict['loc'] = _items + # set to None if input (nullable) is None + # and model_fields_set contains the field + if self.input is None and "input" in self.model_fields_set: + _dict['input'] = None + return _dict @classmethod @@ -92,7 +99,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "loc": [ValidationErrorLocInner.from_dict(_item) for _item in obj["loc"]] if obj.get("loc") is not None else None, "msg": obj.get("msg"), - "type": obj.get("type") + "type": obj.get("type"), + "input": obj.get("input"), + "ctx": obj.get("ctx") }) return _obj diff --git a/codegen/out/aignx/codegen/models/validation_error_loc_inner.py b/codegen/out/aignx/codegen/models/validation_error_loc_inner.py index b65d82b77..8f81623fe 100644 --- a/codegen/out/aignx/codegen/models/validation_error_loc_inner.py +++ b/codegen/out/aignx/codegen/models/validation_error_loc_inner.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/aignx/codegen/models/version_read_response.py b/codegen/out/aignx/codegen/models/version_read_response.py index e56dcd7d6..55e4cf4c4 100644 --- a/codegen/out/aignx/codegen/models/version_read_response.py +++ b/codegen/out/aignx/codegen/models/version_read_response.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. @@ -18,8 +18,9 @@ import json from datetime import datetime -from pydantic import BaseModel, ConfigDict, Field, StrictStr +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator from typing import Any, ClassVar, Dict, List +from typing_extensions import Annotated from aignx.codegen.models.input_artifact import InputArtifact from aignx.codegen.models.output_artifact import OutputArtifact from typing import Optional, Set @@ -29,13 +30,20 @@ class VersionReadResponse(BaseModel): """ Base Response schema for the `Application Version Details` endpoint """ # noqa: E501 - version_number: StrictStr = Field(description="Semantic version of the application") + version_number: Annotated[str, Field(strict=True)] = Field(description="Semantic version of the application") changelog: StrictStr = Field(description="Description of the changes relative to the previous version") input_artifacts: List[InputArtifact] = Field(description="List of the input fields, provided by the User") output_artifacts: List[OutputArtifact] = Field(description="List of the output fields, generated by the application") released_at: datetime = Field(description="The timestamp when the application version was registered") __properties: ClassVar[List[str]] = ["version_number", "changelog", "input_artifacts", "output_artifacts", "released_at"] + @field_validator('version_number') + def version_number_validate_regular_expression(cls, value): + """Validates the regular expression""" + if not re.match(r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", value): + raise ValueError(r"must validate the regular expression /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/") + return value + model_config = ConfigDict( populate_by_name=True, validate_assignment=True, diff --git a/codegen/out/aignx/codegen/rest.py b/codegen/out/aignx/codegen/rest.py index 972b94da5..824e7f3d3 100644 --- a/codegen/out/aignx/codegen/rest.py +++ b/codegen/out/aignx/codegen/rest.py @@ -5,7 +5,7 @@ The Aignostics Platform is a cloud-based service that enables organizations to access advanced computational pathology applications through a secure API. The platform provides standardized access to Aignostics' portfolio of computational pathology solutions, with Atlas H&E-TME serving as an example of the available API endpoints. To begin using the platform, your organization must first be registered by our business support team. If you don't have an account yet, please contact your account manager or email support@aignostics.com to get started. More information about our applications can be found on [https://platform.aignostics.com](https://platform.aignostics.com). **How to authorize and test API endpoints:** 1. Click the \"Authorize\" button in the right corner below 3. Click \"Authorize\" button in the dialog to log in with your Aignostics Platform credentials 4. After successful login, you'll be redirected back and can use \"Try it out\" on any endpoint **Note**: You only need to authorize once per session. The lock icons next to endpoints will show green when authorized. - The version of the OpenAPI document: 1.0.0-ga + The version of the OpenAPI document: 1.4.0 Generated by OpenAPI Generator (https://openapi-generator.tech) Do not edit the class manually. diff --git a/codegen/out/docs/PublicApi.md b/codegen/out/docs/PublicApi.md index 965f56879..82fdb6bd2 100644 --- a/codegen/out/docs/PublicApi.md +++ b/codegen/out/docs/PublicApi.md @@ -8,6 +8,7 @@ Method | HTTP request | Description [**cancel_run_v1_runs_run_id_cancel_post**](PublicApi.md#cancel_run_v1_runs_run_id_cancel_post) | **POST** /v1/runs/{run_id}/cancel | Cancel Run [**create_run_v1_runs_post**](PublicApi.md#create_run_v1_runs_post) | **POST** /v1/runs | Initiate Run [**delete_run_items_v1_runs_run_id_artifacts_delete**](PublicApi.md#delete_run_items_v1_runs_run_id_artifacts_delete) | **DELETE** /v1/runs/{run_id}/artifacts | Delete Run Items +[**get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get**](PublicApi.md#get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get) | **GET** /v1/runs/{run_id}/artifacts/{artifact_id}/file | Get Artifact Url [**get_item_by_run_v1_runs_run_id_items_external_id_get**](PublicApi.md#get_item_by_run_v1_runs_run_id_items_external_id_get) | **GET** /v1/runs/{run_id}/items/{external_id} | Get Item By Run [**get_me_v1_me_get**](PublicApi.md#get_me_v1_me_get) | **GET** /v1/me | Get current user [**get_run_v1_runs_run_id_get**](PublicApi.md#get_run_v1_runs_run_id_get) | **GET** /v1/runs/{run_id} | Get run details @@ -333,6 +334,87 @@ Name | Type | Description | Notes [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get** +> object get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get(run_id, artifact_id) + +Get Artifact Url + +Download the artifact file with the specified artifact_id, belonging to the specified run. The artifact_is is returned by the `GET /v1/runs/{run_id}/items` endpoint as part of the item results, and can also be retrieved via `GET /v1/runs/{run_id}/items/{external_id}`. The endpoint may return a redirect response with a presigned URL to download the artifact file from the storage bucket. The presigned URL is valid for a limited time, so it should be used immediately after receiving the response. + +### Example + +* OAuth Authentication (OAuth2AuthorizationCodeBearer): + +```python +import aignx.codegen +from aignx.codegen.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to /api +# See configuration.py for a list of all supported configuration parameters. +configuration = aignx.codegen.Configuration( + host = "/api" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +configuration.access_token = os.environ["ACCESS_TOKEN"] + +# Enter a context with an instance of the API client +with aignx.codegen.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = aignx.codegen.PublicApi(api_client) + run_id = 'run_id_example' # str | Run id, returned by `POST /runs/` endpoint + artifact_id = 'artifact_id_example' # str | The artifact id to download + + try: + # Get Artifact Url + api_response = api_instance.get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get(run_id, artifact_id) + print("The response of PublicApi->get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling PublicApi->get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **run_id** | **str**| Run id, returned by `POST /runs/` endpoint | + **artifact_id** | **str**| The artifact id to download | + +### Return type + +**object** + +### Authorization + +[OAuth2AuthorizationCodeBearer](../README.md#OAuth2AuthorizationCodeBearer) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | Successful Response | - | +**404** | Not Found - Artifact not found for the specified run | - | +**307** | Temporary Redirect - Redirect to the artifact file URL | - | +**403** | Forbidden - You don't have permission to download this artifact | - | +**410** | Gone - Artifact has been deleted | - | +**422** | Validation Error | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **get_item_by_run_v1_runs_run_id_items_external_id_get** > ItemResultReadResponse get_item_by_run_v1_runs_run_id_items_external_id_get(run_id, external_id) @@ -567,7 +649,7 @@ Name | Type | Description | Notes List available applications -Returns the list of the applications, available to the caller. The application is available if any of the versions of the application is assigned to the caller’s organization. The response is paginated and sorted according to the provided parameters. +Returns the list of the applications, available to the caller. The application is available if any of the versions of the application is assigned to the caller's organization. The response is paginated and sorted according to the provided parameters. ### Example @@ -739,7 +821,7 @@ Name | Type | Description | Notes [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) # **list_runs_v1_runs_get** -> List[RunReadResponse] list_runs_v1_runs_get(application_id=application_id, application_version=application_version, external_id=external_id, custom_metadata=custom_metadata, page=page, page_size=page_size, sort=sort) +> List[RunReadResponse] list_runs_v1_runs_get(application_id=application_id, application_version=application_version, external_id=external_id, custom_metadata=custom_metadata, page=page, page_size=page_size, for_organization=for_organization, sort=sort) List Runs @@ -778,11 +860,12 @@ with aignx.codegen.ApiClient(configuration) as api_client: custom_metadata = '$' # str | Use PostgreSQL JSONPath expressions to filter runs by their custom_metadata. #### URL Encoding Required **Important**: JSONPath expressions contain special characters that must be URL-encoded when used in query parameters. Most HTTP clients handle this automatically, but when constructing URLs manually, please ensure proper encoding. #### Examples (Clear Format): - **Field existence**: `$.study` - Runs that have a study field defined - **Exact value match**: `$.study ? (@ == \"high\")` - Runs with specific study value - **Numeric comparison**: `$.confidence_score ? (@ > 0.75)` - Runs with confidence score greater than 0.75 - **Array operations**: `$.tags[*] ? (@ == \"draft\")` - Runs with tags array containing \"draft\" - **Complex conditions**: `$.resources ? (@.gpu_count > 2 && @.memory_gb >= 16)` - Runs with high resource requirements #### Examples (URL-Encoded Format): - **Field existence**: `%24.study` - **Exact value match**: `%24.study%20%3F%20(%40%20%3D%3D%20%22high%22)` - **Numeric comparison**: `%24.confidence_score%20%3F%20(%40%20%3E%200.75)` - **Array operations**: `%24.tags%5B*%5D%20%3F%20(%40%20%3D%3D%20%22draft%22)` - **Complex conditions**: `%24.resources%20%3F%20(%40.gpu_count%20%3E%202%20%26%26%20%40.memory_gb%20%3E%3D%2016)` #### Notes - JSONPath expressions are evaluated using PostgreSQL's `@?` operator - The `$.` prefix is automatically added to root-level field references if missing - String values in conditions must be enclosed in double quotes - Use `&&` for AND operations and `||` for OR operations - Regular expressions use `like_regex` with standard regex syntax - **Please remember to URL-encode the entire JSONPath expression when making HTTP requests** (optional) page = 1 # int | (optional) (default to 1) page_size = 50 # int | (optional) (default to 50) - sort = ['sort_example'] # List[str] | Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `statistics` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) (optional) + for_organization = 'for_organization_example' # str | Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs. (optional) + sort = ['sort_example'] # List[str] | Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) (optional) try: # List Runs - api_response = api_instance.list_runs_v1_runs_get(application_id=application_id, application_version=application_version, external_id=external_id, custom_metadata=custom_metadata, page=page, page_size=page_size, sort=sort) + api_response = api_instance.list_runs_v1_runs_get(application_id=application_id, application_version=application_version, external_id=external_id, custom_metadata=custom_metadata, page=page, page_size=page_size, for_organization=for_organization, sort=sort) print("The response of PublicApi->list_runs_v1_runs_get:\n") pprint(api_response) except Exception as e: @@ -802,7 +885,8 @@ Name | Type | Description | Notes **custom_metadata** | **str**| Use PostgreSQL JSONPath expressions to filter runs by their custom_metadata. #### URL Encoding Required **Important**: JSONPath expressions contain special characters that must be URL-encoded when used in query parameters. Most HTTP clients handle this automatically, but when constructing URLs manually, please ensure proper encoding. #### Examples (Clear Format): - **Field existence**: `$.study` - Runs that have a study field defined - **Exact value match**: `$.study ? (@ == \"high\")` - Runs with specific study value - **Numeric comparison**: `$.confidence_score ? (@ > 0.75)` - Runs with confidence score greater than 0.75 - **Array operations**: `$.tags[*] ? (@ == \"draft\")` - Runs with tags array containing \"draft\" - **Complex conditions**: `$.resources ? (@.gpu_count > 2 && @.memory_gb >= 16)` - Runs with high resource requirements #### Examples (URL-Encoded Format): - **Field existence**: `%24.study` - **Exact value match**: `%24.study%20%3F%20(%40%20%3D%3D%20%22high%22)` - **Numeric comparison**: `%24.confidence_score%20%3F%20(%40%20%3E%200.75)` - **Array operations**: `%24.tags%5B*%5D%20%3F%20(%40%20%3D%3D%20%22draft%22)` - **Complex conditions**: `%24.resources%20%3F%20(%40.gpu_count%20%3E%202%20%26%26%20%40.memory_gb%20%3E%3D%2016)` #### Notes - JSONPath expressions are evaluated using PostgreSQL's `@?` operator - The `$.` prefix is automatically added to root-level field references if missing - String values in conditions must be enclosed in double quotes - Use `&&` for AND operations and `||` for OR operations - Regular expressions use `like_regex` with standard regex syntax - **Please remember to URL-encode the entire JSONPath expression when making HTTP requests** | [optional] **page** | **int**| | [optional] [default to 1] **page_size** | **int**| | [optional] [default to 50] - **sort** | [**List[str]**](str.md)| Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `statistics` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) | [optional] + **for_organization** | **str**| Filter runs by organization ID. Available for superadmins (any org) and admins (own org only). When provided, returns all runs for the specified organization instead of only the caller's own runs. | [optional] + **sort** | [**List[str]**](str.md)| Sort the results by one or more fields. Use `+` for ascending and `-` for descending order. **Available fields:** - `run_id` - `application_id` - `version_number` - `custom_metadata` - `submitted_at` - `submitted_by` - `terminated_at` - `termination_reason` **Examples:** - `?sort=submitted_at` - Sort by creation time (ascending) - `?sort=-submitted_at` - Sort by creation time (descending) - `?sort=state&sort=-submitted_at` - Sort by state, then by time (descending) | [optional] ### Return type diff --git a/src/aignostics/application/_download.py b/src/aignostics/application/_download.py index acdd4b312..474142585 100644 --- a/src/aignostics/application/_download.py +++ b/src/aignostics/application/_download.py @@ -203,6 +203,7 @@ def download_available_items( # noqa: PLR0913, PLR0917 download_item_artifact( progress, + application_run, artifact, item_directory, item.external_id if not create_subdirectory_per_item else "", @@ -215,6 +216,7 @@ def download_available_items( # noqa: PLR0913, PLR0917 def download_item_artifact( # noqa: PLR0913, PLR0917 progress: DownloadProgress, + run: Run, artifact: Any, # noqa: ANN401 destination_directory: Path, prefix: str = "", @@ -223,17 +225,22 @@ def download_item_artifact( # noqa: PLR0913, PLR0917 ) -> None: """Download an artifact of a result item with progress tracking. + Fetches a fresh presigned download URL via + ``GET /v1/runs/{run_id}/artifacts/{artifact_id}/file`` before downloading. + Args: progress (DownloadProgress): Progress tracking object for GUI or CLI updates. - artifact (Any): The artifact to download. + run (Run): The application run that owns the artifact, used to fetch the + presigned download URL from the platform API. + artifact (Any): The artifact to download + (:class:`~aignx.codegen.models.OutputArtifactResultReadResponse`). destination_directory (Path): Directory to save the file. prefix (str): Prefix for the file name, if needed. download_progress_queue (Queue | None): Queue for GUI progress updates. download_progress_callable (Callable | None): Callback for CLI progress updates. Raises: - ValueError: If - no checksum metadata is found for the artifact. + ValueError: If no checksum metadata is found for the artifact. requests.HTTPError: If the download fails. """ metadata = artifact.metadata or {} @@ -258,9 +265,10 @@ def download_item_artifact( # noqa: PLR0913, PLR0917 logger.trace("File {} already exists with correct checksum", artifact_path) return + artifact_download_url = run.get_artifact_download_url(artifact.output_artifact_id) download_file_with_progress( progress, - artifact.download_url, + artifact_download_url, artifact_path, metadata_checksum, download_progress_queue, diff --git a/src/aignostics/application/_gui/_page_application_run_describe.py b/src/aignostics/application/_gui/_page_application_run_describe.py index f897ae768..e8ea1b6ea 100644 --- a/src/aignostics/application/_gui/_page_application_run_describe.py +++ b/src/aignostics/application/_gui/_page_application_run_describe.py @@ -15,9 +15,10 @@ ) from nicegui import run as nicegui_run -from aignostics.platform import ItemOutput, ItemResult, ItemState, RunState +from aignostics.platform import ItemOutput, ItemResult, ItemState, RunState, Run from aignostics.third_party.showinfm.showinfm import show_in_file_manager from aignostics.utils import GUILocalFilePicker, get_user_data_directory +from aignx.codegen.models import ArtifactOutput if TYPE_CHECKING: from aignx.codegen.models import RunReadResponse @@ -430,9 +431,10 @@ def csv_view_dialog_content(title: str | None, url: str | None) -> None: with ui.row(align_items="end").classes("w-full"), ui.column(align_items="end").classes("w-full"): ui.button("Close", on_click=csv_view_dialog.close) - def csv_dialog_open(title: str, url: str) -> None: + def csv_dialog_open(title: str, artifact_id: str) -> None: """Open the CSV dialog.""" - csv_view_dialog_content.refresh(title=title, url=url) + download_url = Run.for_run_id(run_id).get_artifact_download_url(artifact_id) + csv_view_dialog_content.refresh(title=title, url=download_url) csv_view_dialog.open() @ui.refreshable @@ -478,15 +480,16 @@ def tiff_view_dialog_content(title: str | None, url: str | None) -> None: with ui.row(align_items="end").classes("w-full"), ui.column(align_items="end").classes("w-full"): ui.button("Close", on_click=tiff_view_dialog.close) - def tiff_dialog_open(title: str, url: str) -> None: + def tiff_dialog_open(title: str, artifact_id: str) -> None: """Open the TIFF dialog. Args: title (str): The title of the TIFF dialog. - url (str): The URL of the TIFF image. + artifact_id: (str): The ID of the artifact containing the TIFF to display. """ - tiff_view_dialog_content.refresh(title=title, url=url) + download_url = Run.for_run_id(run_id).get_artifact_download_url(artifact_id) + tiff_view_dialog_content.refresh(title=title, url=download_url) tiff_view_dialog.open() @ui.refreshable @@ -516,6 +519,10 @@ def custom_metadata_dialog_open(title: str, custom_metadata: dict[str, Any]) -> custom_metadata_dialog_content.refresh(title=title, custom_metadata=custom_metadata) custom_metadata_dialog.open() + def open_browser(_, artifact_id): + download_url = Run.for_run_id(run_id).get_artifact_download_url(artifact_id) + webbrowser.open(download_url) + async def open_qupath( project: Path | None = None, image: Path | str | None = None, button: ui.button | None = None ) -> None: @@ -760,8 +767,8 @@ def render_item(item: ItemResult) -> None: # noqa: C901, PLR0912, PLR0915 icon=mime_type_to_icon(mime_type), group="artifacts", ).classes("w-full"): - if artifact.download_url: - url = artifact.download_url + if artifact.output == ArtifactOutput.AVAILABLE: + artifact_id = artifact.output_artifact_id title = artifact.name metadata = artifact.metadata with ui.button_group(): @@ -769,20 +776,19 @@ def render_item(item: ItemResult) -> None: # noqa: C901, PLR0912, PLR0915 ui.button( "Preview", icon=mime_type_to_icon(mime_type), - on_click=lambda _, url=url, title=title: tiff_dialog_open(title, url), + on_click=lambda _, artifact_id=artifact_id, title=title: tiff_dialog_open(title, artifact_id), ) if mime_type == "text/csv": ui.button( "Preview", icon=mime_type_to_icon(mime_type), - on_click=lambda _, url=url, title=title: csv_dialog_open(title, url), - ) - if url: - ui.button( - text="Download", - icon="cloud_download", - on_click=lambda _, url=url: webbrowser.open(url), + on_click=lambda _, artifact_id=artifact_id, title=title: csv_dialog_open(title, artifact_id), ) + ui.button( + text="Download", + icon="cloud_download", + on_click=lambda _, artifact_id=artifact_id: open_browser(_, artifact_id), + ) if metadata: ui.button( text="Schema", diff --git a/src/aignostics/application/_utils.py b/src/aignostics/application/_utils.py index 1538a230e..daf4a192b 100644 --- a/src/aignostics/application/_utils.py +++ b/src/aignostics/application/_utils.py @@ -325,7 +325,6 @@ def _retrieve_and_print_run_items(run_handle: Run, summarize: bool = False) -> N f"\n - Name: {artifact.name}" f"\n MIME Type: {get_mime_type_for_artifact(artifact)}" f"\n Artifact ID: {artifact.output_artifact_id}" - f"\n Download URL: {artifact.download_url}" ) item_output += artifacts_output diff --git a/src/aignostics/platform/resources/runs.py b/src/aignostics/platform/resources/runs.py index 418f9924b..51e566f31 100644 --- a/src/aignostics/platform/resources/runs.py +++ b/src/aignostics/platform/resources/runs.py @@ -12,9 +12,11 @@ from time import sleep from typing import Any, cast +import requests from aignx.codegen.api.public_api import PublicApi from aignx.codegen.exceptions import NotFoundException, ServiceException from aignx.codegen.models import ( + ArtifactOutput, CustomMetadataUpdateRequest, ItemCreationRequest, ItemOutput, @@ -267,6 +269,60 @@ def results_with_retry(run_id: str, **kwargs: object) -> list[ItemResultData]: return paginate(lambda **kwargs: results_with_retry(self.run_id, nocache=nocache, **filter_kwargs, **kwargs)) + def get_artifact_download_url(self, artifact_id: str) -> str: + """Fetch a fresh presigned download URL for a specific output artifact. + + Calls ``GET /v1/runs/{run_id}/artifacts/{artifact_id}/file``. The + endpoint responds with a ``307 Temporary Redirect`` whose ``Location`` + header carries the presigned download URL. Because urllib3 follows + redirects automatically the URL is captured by intercepting the redirect + with ``requests`` (``allow_redirects=False``), using the endpoint URL + and auth headers obtained from the generated client's serializer so that + no path strings are hardcoded here. + + Args: + artifact_id: The ``output_artifact_id`` from + :class:`~aignx.codegen.models.OutputArtifactResultReadResponse`. + + Returns: + str: A time-limited presigned URL that can be used to download the + file. + + Raises: + RuntimeError: If the redirect ``Location`` header is missing or the + response status is unexpected. + """ + # Generated client follows redirect automatically which prevents us from getting the presigned URL, + # but we need the presigned URL to get query the metadata of the file (e.g. checksum) before downloading it. + serialize = ( + self._api._get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get_serialize # noqa: SLF001 + ) + _method, url, header_params, *_ = serialize( + run_id=self.run_id, + artifact_id=artifact_id, + _request_auth=None, + _content_type=None, + _headers={"User-Agent": user_agent()}, + _host_index=0, + ) + with requests.get( + url, + headers=dict(header_params), + allow_redirects=False, + timeout=settings().run_timeout, + ) as response: + if response.status_code == requests.codes.temporary_redirect: + location = response.headers.get("Location") + if not location: + msg = f"307 redirect received but Location header is absent for artifact {artifact_id!r}" + raise RuntimeError(msg) + return location + msg = ( + f"Unexpected status {response.status_code} from artifact URL endpoint " + f"for artifact {artifact_id!r}; expected 307 redirect" + ) + raise RuntimeError(msg) + def download_to_folder( # noqa: C901 self, download_base: Path | str, @@ -344,8 +400,8 @@ def download_to_folder( # noqa: C901 msg = f"Download operation failed unexpectedly for run {self.run_id}: {e}" raise RuntimeError(msg) from e - @staticmethod def ensure_artifacts_downloaded( + self, base_folder: Path, item: ItemResultReadResponse, checksum_attribute_key: str = "checksum_base64_crc32c", @@ -354,6 +410,8 @@ def ensure_artifacts_downloaded( """Ensures all artifacts for an item are downloaded. Downloads missing or partially downloaded artifacts and verifies their integrity. + Uses ``GET /v1/runs/{run_id}/artifacts/{artifact_id}/file`` to obtain fresh + presigned download URLs instead of the deprecated ``download_url`` field. Args: base_folder (Path): Base directory to download artifacts to. @@ -369,7 +427,7 @@ def ensure_artifacts_downloaded( downloaded_at_least_one_artifact = False for artifact in item.output_artifacts: - if artifact.download_url: + if artifact.output == ArtifactOutput.AVAILABLE: item_dir.mkdir(exist_ok=True, parents=True) file_ending = mime_type_to_file_ending(get_mime_type_for_artifact(artifact)) file_path = item_dir / f"{artifact.name}{file_ending}" @@ -395,8 +453,8 @@ def ensure_artifacts_downloaded( logger.trace("Download for {} to {}", artifact.name, file_path) print(f"> Download for {artifact.name} to {file_path}") if print_status else None - # if file is not there at all or only partially downloaded yet - download_file(artifact.download_url, str(file_path), checksum) + artifact_download_url = self.get_artifact_download_url(artifact.output_artifact_id) + download_file(artifact_download_url, str(file_path), checksum) if downloaded_at_least_one_artifact: logger.trace("Downloaded results for item: {} to {}", item.external_id, item_dir) diff --git a/tests/aignostics/application/download_test.py b/tests/aignostics/application/download_test.py index e5537ef62..60b550a40 100644 --- a/tests/aignostics/application/download_test.py +++ b/tests/aignostics/application/download_test.py @@ -6,7 +6,10 @@ import pytest import requests -from aignostics.application._download import download_url_to_file_with_progress, extract_filename_from_url +from aignostics.application._download import ( + download_url_to_file_with_progress, + extract_filename_from_url, +) from aignostics.application._models import DownloadProgress, DownloadProgressState diff --git a/tests/aignostics/platform/resources/runs_test.py b/tests/aignostics/platform/resources/runs_test.py index c8367196e..7c713d758 100644 --- a/tests/aignostics/platform/resources/runs_test.py +++ b/tests/aignostics/platform/resources/runs_test.py @@ -4,9 +4,10 @@ verifying their functionality for listing, creating, and managing application runs. """ -from unittest.mock import Mock +from unittest.mock import MagicMock, Mock, patch import pytest +import requests from aignx.codegen.api.public_api import PublicApi from aignx.codegen.models import ( InputArtifactCreationRequest, @@ -703,6 +704,150 @@ def test_run_details_raises_not_found_after_timeout(app_run, mock_api) -> None: assert mock_api.get_run_v1_runs_run_id_get.call_count > 1 +@pytest.fixture +def mock_serialize(mock_api) -> Mock: + """Configure the serialize method on mock_api to return a valid (method, url, headers) tuple. + + Returns: + Mock: The configured serialize mock. + """ + serialize = Mock(return_value=("GET", "https://api.example.com/v1/runs/test-run-id/artifacts/art-1/file", {}, None)) + mock_api._get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get_serialize = serialize + return serialize + + +@pytest.mark.unit +def test_get_artifact_download_url_returns_location_on_307(app_run, mock_serialize) -> None: + """Test that get_artifact_download_url returns the Location header value on a 307 redirect. + + Args: + app_run: Run instance with mock API. + mock_serialize: Mock serializer configured on the API. + """ + # Arrange + presigned_url = "https://storage.example.com/artifact?sig=abc123" + mock_response = MagicMock() + mock_response.__enter__ = Mock(return_value=mock_response) + mock_response.__exit__ = Mock(return_value=False) + mock_response.status_code = requests.codes.temporary_redirect + mock_response.headers = {"Location": presigned_url} + + with patch("aignostics.platform.resources.runs.requests.get", return_value=mock_response) as mock_get: + # Act + result = app_run.get_artifact_download_url("art-1") + + # Assert + assert result == presigned_url + mock_get.assert_called_once_with( + "https://api.example.com/v1/runs/test-run-id/artifacts/art-1/file", + headers={}, + allow_redirects=False, + timeout=mock_get.call_args[1]["timeout"], + ) + + +@pytest.mark.parametrize( + ("status_code", "expected_message"), + [ + (200, "Unexpected status 200 from artifact URL endpoint"), + (307, "307 redirect received but Location header is absent"), + (404, "Unexpected status 404 from artifact URL endpoint for artifact 'art-1'; expected 307 redirect"), + ], +) +@pytest.mark.unit +def test_get_artifact_download_url_errors(app_run, mock_serialize, status_code, expected_message) -> None: + """Test that get_artifact_download_url raises RuntimeError after unexpected result. + + Args: + app_run: Run instance with mock API. + mock_serialize: Mock serializer configured on the API. + status_code: The HTTP status code to simulate in the response. + expected_message: The expected error message to be included in the RuntimeError. + """ + # Arrange + mock_response = MagicMock() + mock_response.__enter__ = Mock(return_value=mock_response) + mock_response.__exit__ = Mock(return_value=False) + mock_response.status_code = status_code + mock_response.headers = {} # No Location header + + with ( + patch("aignostics.platform.resources.runs.requests.get", return_value=mock_response), + pytest.raises(RuntimeError, match=expected_message), + ): + app_run.get_artifact_download_url("art-1") + + +@pytest.mark.unit +def test_get_artifact_download_url_passes_correct_artifact_id(app_run, mock_api) -> None: + """Test that get_artifact_download_url passes the artifact_id to the serializer. + + Args: + app_run: Run instance with mock API. + mock_api: Mock ExternalsApi instance. + """ + # Arrange + artifact_id = "specific-artifact-xyz" + serialize = Mock( + return_value=( + "GET", + "https://api.example.com/v1/runs/test-run-id/artifacts/specific-artifact-xyz/file", + {}, + None, + ) + ) + mock_api._get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get_serialize = serialize + + presigned_url = "https://storage.example.com/file?sig=xyz" + mock_response = MagicMock() + mock_response.__enter__ = Mock(return_value=mock_response) + mock_response.__exit__ = Mock(return_value=False) + mock_response.status_code = requests.codes.temporary_redirect + mock_response.headers = {"Location": presigned_url} + + with patch("aignostics.platform.resources.runs.requests.get", return_value=mock_response): + # Act + result = app_run.get_artifact_download_url(artifact_id) + + # Assert + assert result == presigned_url + serialize.assert_called_once() + call_kwargs = serialize.call_args[1] + assert call_kwargs["run_id"] == app_run.run_id + assert call_kwargs["artifact_id"] == artifact_id + + +@pytest.mark.unit +def test_get_artifact_download_url_uses_headers_from_serializer(app_run, mock_api) -> None: + """Test that get_artifact_download_url passes serializer-provided headers to requests.get. + + Args: + app_run: Run instance with mock API. + mock_api: Mock ExternalsApi instance. + """ + # Arrange + auth_headers = [("Authorization", "Bearer token123"), ("X-Custom", "header-value")] + serialize = Mock( + return_value=("GET", "https://api.example.com/v1/runs/test-run-id/artifacts/art-1/file", auth_headers, None) + ) + mock_api._get_artifact_url_v1_runs_run_id_artifacts_artifact_id_file_get_serialize = serialize + + mock_response = MagicMock() + mock_response.__enter__ = Mock(return_value=mock_response) + mock_response.__exit__ = Mock(return_value=False) + mock_response.status_code = requests.codes.temporary_redirect + mock_response.headers = {"Location": "https://storage.example.com/file"} + + with patch("aignostics.platform.resources.runs.requests.get", return_value=mock_response) as mock_get: + # Act + app_run.get_artifact_download_url("art-1") + + # Assert + call_kwargs = mock_get.call_args[1] + assert call_kwargs["headers"] == dict(auth_headers) + assert call_kwargs["allow_redirects"] is False + + @pytest.mark.unit def test_run_details_does_not_retry_other_exceptions(app_run, mock_api) -> None: """Test that the outer retry does not catch non-NotFoundException errors.