diff --git a/.sdk-version b/.sdk-version index c2d2cb0b..c4475d31 100644 --- a/.sdk-version +++ b/.sdk-version @@ -1 +1 @@ -v4.5.0 +v4.13.0 diff --git a/README.md b/README.md index 5332d506..be55b59e 100644 --- a/README.md +++ b/README.md @@ -151,8 +151,6 @@ Class | Method | HTTP request | Description *ExternalSourcesApi* | [**create_external_task_vt**](docs/ExternalSourcesApi.md#create_external_task_vt) | **POST** /v2/analysis/{analysis_id}/external/vt | Pulls data from VirusTotal *ExternalSourcesApi* | [**get_vt_data**](docs/ExternalSourcesApi.md#get_vt_data) | **GET** /v2/analysis/{analysis_id}/external/vt | Get VirusTotal data *ExternalSourcesApi* | [**get_vt_task_status**](docs/ExternalSourcesApi.md#get_vt_task_status) | **GET** /v2/analysis/{analysis_id}/external/vt/status | Check the status of VirusTotal data retrieval -*FirmwareApi* | [**get_binaries_for_firmware_task**](docs/FirmwareApi.md#get_binaries_for_firmware_task) | **GET** /v2/firmware/get-binaries/{task_id} | Upload firmware for unpacking -*FirmwareApi* | [**upload_firmware**](docs/FirmwareApi.md#upload_firmware) | **POST** /v2/firmware | Upload firmware for unpacking *FunctionsAIDecompilationApi* | [**create_ai_decompilation**](docs/FunctionsAIDecompilationApi.md#create_ai_decompilation) | **POST** /v3/functions/{function_id}/ai-decompilation | Start AI decompilation *FunctionsAIDecompilationApi* | [**delete_ai_decompilation_inline_comment**](docs/FunctionsAIDecompilationApi.md#delete_ai_decompilation_inline_comment) | **DELETE** /v3/functions/{function_id}/ai-decompilation/inline-comments/{line} | Delete a single inline comment *FunctionsAIDecompilationApi* | [**get_ai_decompilation**](docs/FunctionsAIDecompilationApi.md#get_ai_decompilation) | **GET** /v3/functions/{function_id}/ai-decompilation | Get AI decompilation result @@ -650,6 +648,7 @@ Class | Method | HTTP request | Description - [ScheduledTaskEntry](docs/ScheduledTaskEntry.md) - [ScrapeThirdPartyConfig](docs/ScrapeThirdPartyConfig.md) - [SectionModel](docs/SectionModel.md) + - [SecurityFinding](docs/SecurityFinding.md) - [SecurityModel](docs/SecurityModel.md) - [SecurityScanMetadata](docs/SecurityScanMetadata.md) - [SecurityScanResult](docs/SecurityScanResult.md) diff --git a/docs/FirmwareApi.md b/docs/FirmwareApi.md deleted file mode 100644 index 7baf42ac..00000000 --- a/docs/FirmwareApi.md +++ /dev/null @@ -1,183 +0,0 @@ -# revengai.FirmwareApi - -All URIs are relative to *https://api.reveng.ai* - -Method | HTTP request | Description -------------- | ------------- | ------------- -[**get_binaries_for_firmware_task**](FirmwareApi.md#get_binaries_for_firmware_task) | **GET** /v2/firmware/get-binaries/{task_id} | Upload firmware for unpacking -[**upload_firmware**](FirmwareApi.md#upload_firmware) | **POST** /v2/firmware | Upload firmware for unpacking - - -# **get_binaries_for_firmware_task** -> object get_binaries_for_firmware_task(task_id) - -Upload firmware for unpacking - -Uploads a firmware file and begins a 'Firmware Unpacker' task. Returns a result identifier, which can be used to poll for the response. - -### Example - -* Api Key Authentication (APIKey): -* Bearer Authentication (bearerAuth): - -```python -import revengai -from revengai.rest import ApiException -from pprint import pprint - -# Defining the host is optional and defaults to https://api.reveng.ai -# See configuration.py for a list of all supported configuration parameters. -configuration = revengai.Configuration( - host = "https://api.reveng.ai" -) - -# 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. - -# Configure API key authorization: APIKey -configuration.api_key['APIKey'] = os.environ["API_KEY"] - -# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed -# configuration.api_key_prefix['APIKey'] = 'Bearer' - -# Configure Bearer authorization: bearerAuth -configuration = revengai.Configuration( - access_token = os.environ["BEARER_TOKEN"] -) - -# Enter a context with an instance of the API client -with revengai.ApiClient(configuration) as api_client: - # Create an instance of the API class - api_instance = revengai.FirmwareApi(api_client) - task_id = 'task_id_example' # str | - - try: - # Upload firmware for unpacking - api_response = api_instance.get_binaries_for_firmware_task(task_id) - print("The response of FirmwareApi->get_binaries_for_firmware_task:\n") - pprint(api_response) - except Exception as e: - print("Exception when calling FirmwareApi->get_binaries_for_firmware_task: %s\n" % e) -``` - - - -### Parameters - - -Name | Type | Description | Notes -------------- | ------------- | ------------- | ------------- - **task_id** | **str**| | - -### Return type - -**object** - -### Authorization - -[APIKey](../README.md#APIKey), [bearerAuth](../README.md#bearerAuth) - -### HTTP request headers - - - **Content-Type**: Not defined - - **Accept**: application/json - -### HTTP response details - -| Status code | Description | Response headers | -|-------------|-------------|------------------| -**200** | Successful Response | - | -**422** | Invalid request parameters | - | - -[[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) - -# **upload_firmware** -> object upload_firmware(file, password=password) - -Upload firmware for unpacking - -Uploads a firmware file and begins a 'Firmware Unpacker' task. Returns a result identifier, which can be used to poll for the response. - -### Example - -* Api Key Authentication (APIKey): -* Bearer Authentication (bearerAuth): - -```python -import revengai -from revengai.rest import ApiException -from pprint import pprint - -# Defining the host is optional and defaults to https://api.reveng.ai -# See configuration.py for a list of all supported configuration parameters. -configuration = revengai.Configuration( - host = "https://api.reveng.ai" -) - -# 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. - -# Configure API key authorization: APIKey -configuration.api_key['APIKey'] = os.environ["API_KEY"] - -# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed -# configuration.api_key_prefix['APIKey'] = 'Bearer' - -# Configure Bearer authorization: bearerAuth -configuration = revengai.Configuration( - access_token = os.environ["BEARER_TOKEN"] -) - -# Enter a context with an instance of the API client -with revengai.ApiClient(configuration) as api_client: - # Create an instance of the API class - api_instance = revengai.FirmwareApi(api_client) - file = 'file_example' # str | - password = 'password_example' # str | (optional) - - try: - # Upload firmware for unpacking - api_response = api_instance.upload_firmware(file, password=password) - print("The response of FirmwareApi->upload_firmware:\n") - pprint(api_response) - except Exception as e: - print("Exception when calling FirmwareApi->upload_firmware: %s\n" % e) -``` - - - -### Parameters - - -Name | Type | Description | Notes -------------- | ------------- | ------------- | ------------- - **file** | **str**| | - **password** | **str**| | [optional] - -### Return type - -**object** - -### Authorization - -[APIKey](../README.md#APIKey), [bearerAuth](../README.md#bearerAuth) - -### HTTP request headers - - - **Content-Type**: multipart/form-data - - **Accept**: application/json - -### HTTP response details - -| Status code | Description | Response headers | -|-------------|-------------|------------------| -**201** | Successful Response | - | -**422** | Unprocessable Entity | - | -**500** | Internal Server 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) - diff --git a/docs/GetMatchesStatusOutputBody.md b/docs/GetMatchesStatusOutputBody.md index 15964a45..f40126c4 100644 --- a/docs/GetMatchesStatusOutputBody.md +++ b/docs/GetMatchesStatusOutputBody.md @@ -6,10 +6,15 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **messages** | [**List[ProgressMessage]**](ProgressMessage.md) | Log messages emitted during execution | +**percent** | **int** | Overall completion as a percentage, weighted by step duration | **status** | **str** | Current workflow status | **step** | **str** | Name of the current step | **step_index** | **int** | Zero-based index of the current step | +**step_share** | **int** | Percentage points the current step contributes when it completes | **steps_total** | **int** | Total number of steps in the workflow | +**sub_step** | **str** | Phase within the current step, when the step reports one | [optional] +**sub_step_done** | **int** | Items completed in the current phase | [optional] +**sub_step_total** | **int** | Items the current phase will process, 0 when unknown | [optional] ## Example diff --git a/docs/SecurityFinding.md b/docs/SecurityFinding.md new file mode 100644 index 00000000..cdc202b2 --- /dev/null +++ b/docs/SecurityFinding.md @@ -0,0 +1,40 @@ +# SecurityFinding + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**check_id** | **str** | Semgrep rule ID that matched | [optional] +**confidence** | **str** | Semgrep's confidence in the finding | [optional] +**cwe** | **List[str]** | CWE identifiers associated with the finding | [optional] +**end_line** | **int** | Line the finding ends on | [optional] +**function_id** | **int** | ID of the function the finding was reported in | [optional] +**function_name** | **str** | Name of the function the finding was reported in | [optional] +**impact** | **str** | Estimated impact of the finding | [optional] +**message** | **str** | Human-readable description of the finding | [optional] +**severity** | **str** | Severity of the finding | [optional] +**snippet_lines** | **List[str]** | Source lines making up the reported snippet | [optional] +**snippet_start_line** | **int** | Line the reported snippet starts on | [optional] +**start_line** | **int** | Line the finding starts on | [optional] + +## Example + +```python +from revengai.models.security_finding import SecurityFinding + +# TODO update the JSON string below +json = "{}" +# create an instance of SecurityFinding from a JSON string +security_finding_instance = SecurityFinding.from_json(json) +# print the JSON string representation of the object +print(SecurityFinding.to_json()) + +# convert the object into a dict +security_finding_dict = security_finding_instance.to_dict() +# create an instance of SecurityFinding from a dict +security_finding_from_dict = SecurityFinding.from_dict(security_finding_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/docs/SecurityScanResult.md b/docs/SecurityScanResult.md index 77149fc1..29dd4ce6 100644 --- a/docs/SecurityScanResult.md +++ b/docs/SecurityScanResult.md @@ -9,8 +9,7 @@ Name | Type | Description | Notes **cancelled** | **bool** | Whether the run was cancelled before it covered every function | **decompiled** | **int** | Functions successfully decompiled and scanned | **failed** | **int** | Functions whose decompilation or scan attempt errored | -**security_scan** | **Dict[str, object]** | Raw semgrep findings, keyed by the scanner's own result shape | [optional] -**source** | **str** | Decompiler that produced the source scanned | +**security_scan** | [**List[SecurityFinding]**](SecurityFinding.md) | Shaped semgrep findings, one per result | [optional] **total** | **int** | Functions the run considered | ## Example diff --git a/docs/StartBatchMatchingInputBody.md b/docs/StartBatchMatchingInputBody.md index 59b53034..79bc0aab 100644 --- a/docs/StartBatchMatchingInputBody.md +++ b/docs/StartBatchMatchingInputBody.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes **binary_ids** | **List[int]** | Binary IDs to match the analysis against, one workflow per binary. | **debug_types** | **List[Optional[str]]** | Restrict matches to candidates with these debug source types. Defaults to [\"SYSTEM\"]. | [optional] **min_similarity** | **float** | Similarity floor as a percentage. Defaults to 90. | [optional] +**no_cache** | **bool** | By default a completed matching run is reused per binary (that binary reports status=COMPLETED, no new run). Set true to force fresh runs for every binary. | [optional] **results_per_function** | **int** | Max matches returned per source function. Defaults to 1. | [optional] ## Example diff --git a/docs/StartMatchingOutputBody.md b/docs/StartMatchingOutputBody.md index 11ae8fb6..2eeb88f5 100644 --- a/docs/StartMatchingOutputBody.md +++ b/docs/StartMatchingOutputBody.md @@ -7,10 +7,15 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **match_id** | **str** | Opaque token for this matching run. Pass it to the GET/status endpoints' match_id query parameter to fetch this exact run. | **messages** | [**List[ProgressMessage]**](ProgressMessage.md) | Log messages emitted during execution | +**percent** | **int** | Overall completion as a percentage, weighted by step duration | **status** | **str** | Current workflow status | **step** | **str** | Name of the current step | **step_index** | **int** | Zero-based index of the current step | +**step_share** | **int** | Percentage points the current step contributes when it completes | **steps_total** | **int** | Total number of steps in the workflow | +**sub_step** | **str** | Phase within the current step, when the step reports one | [optional] +**sub_step_done** | **int** | Items completed in the current phase | [optional] +**sub_step_total** | **int** | Items the current phase will process, 0 when unknown | [optional] ## Example diff --git a/docs/SummaryData.md b/docs/SummaryData.md index 4c638999..0e3b44b4 100644 --- a/docs/SummaryData.md +++ b/docs/SummaryData.md @@ -6,6 +6,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **ai_summary** | **str** | Summary with code tags removed | +**predicted_function_name** | **str** | Name the model proposes for this function, produced alongside the summary. | [optional] **summary** | **str** | Raw summary from the model | **task_status** | **str** | Task status | diff --git a/docs/WorkflowProgress.md b/docs/WorkflowProgress.md index 301b3fbb..1e2b8cdb 100644 --- a/docs/WorkflowProgress.md +++ b/docs/WorkflowProgress.md @@ -6,10 +6,15 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **messages** | [**List[ProgressMessage]**](ProgressMessage.md) | Log messages emitted during execution | +**percent** | **int** | Overall completion as a percentage, weighted by step duration | **status** | **str** | Current workflow status | **step** | **str** | Name of the current step | **step_index** | **int** | Zero-based index of the current step | +**step_share** | **int** | Percentage points the current step contributes when it completes | **steps_total** | **int** | Total number of steps in the workflow | +**sub_step** | **str** | Phase within the current step, when the step reports one | [optional] +**sub_step_done** | **int** | Items completed in the current phase | [optional] +**sub_step_total** | **int** | Items the current phase will process, 0 when unknown | [optional] ## Example diff --git a/revengai/__init__.py b/revengai/__init__.py index 1f06742d..df9dfe2f 100644 --- a/revengai/__init__.py +++ b/revengai/__init__.py @@ -13,7 +13,7 @@ """ # noqa: E501 -__version__ = "v4.5.0" +__version__ = "v4.13.0" # Define package exports __all__ = [ @@ -30,7 +30,6 @@ "ConversationsApi", "DataTypesApi", "ExternalSourcesApi", - "FirmwareApi", "FunctionsAIDecompilationApi", "FunctionsCoreApi", "FunctionsRenamingHistoryApi", @@ -481,6 +480,7 @@ "ScheduledTaskEntry", "ScrapeThirdPartyConfig", "SectionModel", + "SecurityFinding", "SecurityModel", "SecurityScanMetadata", "SecurityScanResult", @@ -614,7 +614,6 @@ from revengai.api.conversations_api import ConversationsApi as ConversationsApi from revengai.api.data_types_api import DataTypesApi as DataTypesApi from revengai.api.external_sources_api import ExternalSourcesApi as ExternalSourcesApi -from revengai.api.firmware_api import FirmwareApi as FirmwareApi from revengai.api.functions_ai_decompilation_api import FunctionsAIDecompilationApi as FunctionsAIDecompilationApi from revengai.api.functions_core_api import FunctionsCoreApi as FunctionsCoreApi from revengai.api.functions_renaming_history_api import FunctionsRenamingHistoryApi as FunctionsRenamingHistoryApi @@ -1069,6 +1068,7 @@ from revengai.models.scheduled_task_entry import ScheduledTaskEntry as ScheduledTaskEntry from revengai.models.scrape_third_party_config import ScrapeThirdPartyConfig as ScrapeThirdPartyConfig from revengai.models.section_model import SectionModel as SectionModel +from revengai.models.security_finding import SecurityFinding as SecurityFinding from revengai.models.security_model import SecurityModel as SecurityModel from revengai.models.security_scan_metadata import SecurityScanMetadata as SecurityScanMetadata from revengai.models.security_scan_result import SecurityScanResult as SecurityScanResult diff --git a/revengai/api/__init__.py b/revengai/api/__init__.py index a8178527..294059fe 100644 --- a/revengai/api/__init__.py +++ b/revengai/api/__init__.py @@ -14,7 +14,6 @@ from revengai.api.conversations_api import ConversationsApi from revengai.api.data_types_api import DataTypesApi from revengai.api.external_sources_api import ExternalSourcesApi -from revengai.api.firmware_api import FirmwareApi from revengai.api.functions_ai_decompilation_api import FunctionsAIDecompilationApi from revengai.api.functions_core_api import FunctionsCoreApi from revengai.api.functions_renaming_history_api import FunctionsRenamingHistoryApi diff --git a/revengai/api/firmware_api.py b/revengai/api/firmware_api.py deleted file mode 100644 index 557468b5..00000000 --- a/revengai/api/firmware_api.py +++ /dev/null @@ -1,597 +0,0 @@ -# coding: utf-8 - -""" - RevEng.AI API - - RevEng.AI is an AI-powered binary analysis platform for reverse engineering and malware analysis. It provides similarity search across executable binaries and functions, AI-driven decompilation, dynamic execution analysis, firmware unpacking, and integration with external threat intelligence sources like VirusTotal. - - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - -import warnings -from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt -from typing import Any, Dict, List, Optional, Tuple, Union -from typing_extensions import Annotated - -from pydantic import StrictStr -from typing import Any, Optional - -from revengai.api_client import ApiClient, RequestSerialized -from revengai.api_response import ApiResponse -from revengai.rest import RESTResponseType - - -class FirmwareApi: - """NOTE: This class is auto generated by OpenAPI Generator - Ref: https://openapi-generator.tech - - Do not edit the class manually. - """ - - def __init__(self, api_client=None) -> None: - if api_client is None: - api_client = ApiClient.get_default() - self.api_client = api_client - - - @validate_call - def get_binaries_for_firmware_task( - self, - task_id: StrictStr, - _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: - """Upload firmware for unpacking - - Uploads a firmware file and begins a 'Firmware Unpacker' task. Returns a result identifier, which can be used to poll for the response. - - :param task_id: (required) - :type task_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_binaries_for_firmware_task_serialize( - task_id=task_id, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "object", - '422': "BaseResponse", - } - 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_binaries_for_firmware_task_with_http_info( - self, - task_id: StrictStr, - _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]: - """Upload firmware for unpacking - - Uploads a firmware file and begins a 'Firmware Unpacker' task. Returns a result identifier, which can be used to poll for the response. - - :param task_id: (required) - :type task_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_binaries_for_firmware_task_serialize( - task_id=task_id, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "object", - '422': "BaseResponse", - } - 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_binaries_for_firmware_task_without_preload_content( - self, - task_id: StrictStr, - _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: - """Upload firmware for unpacking - - Uploads a firmware file and begins a 'Firmware Unpacker' task. Returns a result identifier, which can be used to poll for the response. - - :param task_id: (required) - :type task_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_binaries_for_firmware_task_serialize( - task_id=task_id, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "object", - '422': "BaseResponse", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - return response_data.response - - - def _get_binaries_for_firmware_task_serialize( - self, - task_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 task_id is not None: - _path_params['task_id'] = task_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] = [ - 'APIKey', - 'bearerAuth' - ] - - return self.api_client.param_serialize( - method='GET', - resource_path='/v2/firmware/get-binaries/{task_id}', - 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 upload_firmware( - self, - file: StrictStr, - password: Optional[StrictStr] = None, - _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: - """Upload firmware for unpacking - - Uploads a firmware file and begins a 'Firmware Unpacker' task. Returns a result identifier, which can be used to poll for the response. - - :param file: (required) - :type file: str - :param password: - :type password: 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._upload_firmware_serialize( - file=file, - password=password, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '201': "object", - '422': "BaseResponse", - '500': "BaseResponse", - } - 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 upload_firmware_with_http_info( - self, - file: StrictStr, - password: Optional[StrictStr] = None, - _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]: - """Upload firmware for unpacking - - Uploads a firmware file and begins a 'Firmware Unpacker' task. Returns a result identifier, which can be used to poll for the response. - - :param file: (required) - :type file: str - :param password: - :type password: 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._upload_firmware_serialize( - file=file, - password=password, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '201': "object", - '422': "BaseResponse", - '500': "BaseResponse", - } - 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 upload_firmware_without_preload_content( - self, - file: StrictStr, - password: Optional[StrictStr] = None, - _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: - """Upload firmware for unpacking - - Uploads a firmware file and begins a 'Firmware Unpacker' task. Returns a result identifier, which can be used to poll for the response. - - :param file: (required) - :type file: str - :param password: - :type password: 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._upload_firmware_serialize( - file=file, - password=password, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '201': "object", - '422': "BaseResponse", - '500': "BaseResponse", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - return response_data.response - - - def _upload_firmware_serialize( - self, - file, - password, - _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 - # process the query parameters - # process the header parameters - # process the form parameters - if file is not None: - _form_params.append(('file', file)) - if password is not None: - _form_params.append(('password', password)) - # 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' - ] - ) - - # set the HTTP header `Content-Type` - if _content_type: - _header_params['Content-Type'] = _content_type - else: - _default_content_type = ( - self.api_client.select_header_content_type( - [ - 'multipart/form-data' - ] - ) - ) - if _default_content_type is not None: - _header_params['Content-Type'] = _default_content_type - - # authentication setting - _auth_settings: List[str] = [ - 'APIKey', - 'bearerAuth' - ] - - return self.api_client.param_serialize( - method='POST', - resource_path='/v2/firmware', - 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 - ) - - diff --git a/revengai/api_client.py b/revengai/api_client.py index 9261e2d5..2d3aea36 100644 --- a/revengai/api_client.py +++ b/revengai/api_client.py @@ -90,7 +90,7 @@ def __init__( self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = 'OpenAPI-Generator/v4.5.0/python' + self.user_agent = 'OpenAPI-Generator/v4.13.0/python' self.client_side_validation = configuration.client_side_validation def __enter__(self): diff --git a/revengai/configuration.py b/revengai/configuration.py index cf0a4d8b..41fd19f2 100644 --- a/revengai/configuration.py +++ b/revengai/configuration.py @@ -541,8 +541,8 @@ def to_debug_report(self) -> str: return "Python SDK Debug Report:\n"\ "OS: {env}\n"\ "Python Version: {pyversion}\n"\ - "Version of the API: v4.5.0\n"\ - "SDK Package Version: v4.5.0".\ + "Version of the API: v4.13.0\n"\ + "SDK Package Version: v4.13.0".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self) -> List[HostSetting]: diff --git a/revengai/models/__init__.py b/revengai/models/__init__.py index 2201a889..3eaf3ff9 100644 --- a/revengai/models/__init__.py +++ b/revengai/models/__init__.py @@ -446,6 +446,7 @@ from revengai.models.scheduled_task_entry import ScheduledTaskEntry from revengai.models.scrape_third_party_config import ScrapeThirdPartyConfig from revengai.models.section_model import SectionModel +from revengai.models.security_finding import SecurityFinding from revengai.models.security_model import SecurityModel from revengai.models.security_scan_metadata import SecurityScanMetadata from revengai.models.security_scan_result import SecurityScanResult diff --git a/revengai/models/get_matches_status_output_body.py b/revengai/models/get_matches_status_output_body.py index aa0dde39..ace1af37 100644 --- a/revengai/models/get_matches_status_output_body.py +++ b/revengai/models/get_matches_status_output_body.py @@ -27,12 +27,17 @@ class GetMatchesStatusOutputBody(BaseModel): GetMatchesStatusOutputBody """ # noqa: E501 messages: Optional[List[ProgressMessage]] = Field(description="Log messages emitted during execution") + percent: StrictInt = Field(description="Overall completion as a percentage, weighted by step duration") status: StrictStr = Field(description="Current workflow status") step: StrictStr = Field(description="Name of the current step") step_index: StrictInt = Field(description="Zero-based index of the current step") + step_share: StrictInt = Field(description="Percentage points the current step contributes when it completes") steps_total: StrictInt = Field(description="Total number of steps in the workflow") + sub_step: Optional[StrictStr] = Field(default=None, description="Phase within the current step, when the step reports one") + sub_step_done: Optional[StrictInt] = Field(default=None, description="Items completed in the current phase") + sub_step_total: Optional[StrictInt] = Field(default=None, description="Items the current phase will process, 0 when unknown") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["messages", "status", "step", "step_index", "steps_total"] + __properties: ClassVar[List[str]] = ["messages", "percent", "status", "step", "step_index", "step_share", "steps_total", "sub_step", "sub_step_done", "sub_step_total"] @field_validator('status') def status_validate_enum(cls, value): @@ -112,10 +117,15 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "messages": [ProgressMessage.from_dict(_item) for _item in obj["messages"]] if obj.get("messages") is not None else None, + "percent": obj.get("percent"), "status": obj.get("status"), "step": obj.get("step"), "step_index": obj.get("step_index"), - "steps_total": obj.get("steps_total") + "step_share": obj.get("step_share"), + "steps_total": obj.get("steps_total"), + "sub_step": obj.get("sub_step"), + "sub_step_done": obj.get("sub_step_done"), + "sub_step_total": obj.get("sub_step_total") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/revengai/models/security_finding.py b/revengai/models/security_finding.py new file mode 100644 index 00000000..c908e4d6 --- /dev/null +++ b/revengai/models/security_finding.py @@ -0,0 +1,161 @@ +# coding: utf-8 + +""" + RevEng.AI API + + RevEng.AI is an AI-powered binary analysis platform for reverse engineering and malware analysis. It provides similarity search across executable binaries and functions, AI-driven decompilation, dynamic execution analysis, firmware unpacking, and integration with external threat intelligence sources like VirusTotal. + + 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 pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class SecurityFinding(BaseModel): + """ + SecurityFinding + """ # noqa: E501 + check_id: Optional[StrictStr] = Field(default=None, description="Semgrep rule ID that matched") + confidence: Optional[StrictStr] = Field(default=None, description="Semgrep's confidence in the finding") + cwe: Optional[List[StrictStr]] = Field(default=None, description="CWE identifiers associated with the finding") + end_line: Optional[StrictInt] = Field(default=None, description="Line the finding ends on") + function_id: Optional[StrictInt] = Field(default=None, description="ID of the function the finding was reported in") + function_name: Optional[StrictStr] = Field(default=None, description="Name of the function the finding was reported in") + impact: Optional[StrictStr] = Field(default=None, description="Estimated impact of the finding") + message: Optional[StrictStr] = Field(default=None, description="Human-readable description of the finding") + severity: Optional[StrictStr] = Field(default=None, description="Severity of the finding") + snippet_lines: Optional[List[StrictStr]] = Field(default=None, description="Source lines making up the reported snippet") + snippet_start_line: Optional[StrictInt] = Field(default=None, description="Line the reported snippet starts on") + start_line: Optional[StrictInt] = Field(default=None, description="Line the finding starts on") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["check_id", "confidence", "cwe", "end_line", "function_id", "function_name", "impact", "message", "severity", "snippet_lines", "snippet_start_line", "start_line"] + + @field_validator('confidence') + def confidence_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['LOW', 'MEDIUM', 'HIGH', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('LOW', 'MEDIUM', 'HIGH', 'unknown_default_open_api')") + return value + + @field_validator('impact') + def impact_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['LOW', 'MEDIUM', 'HIGH', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('LOW', 'MEDIUM', 'HIGH', 'unknown_default_open_api')") + return value + + @field_validator('severity') + def severity_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('LOW', 'MEDIUM', 'HIGH', 'CRITICAL', 'unknown_default_open_api')") + return value + + 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 SecurityFinding 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. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if cwe (nullable) is None + # and model_fields_set contains the field + if self.cwe is None and "cwe" in self.model_fields_set: + _dict['cwe'] = None + + # set to None if snippet_lines (nullable) is None + # and model_fields_set contains the field + if self.snippet_lines is None and "snippet_lines" in self.model_fields_set: + _dict['snippet_lines'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SecurityFinding from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "check_id": obj.get("check_id"), + "confidence": obj.get("confidence"), + "cwe": obj.get("cwe"), + "end_line": obj.get("end_line"), + "function_id": obj.get("function_id"), + "function_name": obj.get("function_name"), + "impact": obj.get("impact"), + "message": obj.get("message"), + "severity": obj.get("severity"), + "snippet_lines": obj.get("snippet_lines"), + "snippet_start_line": obj.get("snippet_start_line"), + "start_line": obj.get("start_line") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/revengai/models/security_scan_result.py b/revengai/models/security_scan_result.py index fb28dc2b..59ac644c 100644 --- a/revengai/models/security_scan_result.py +++ b/revengai/models/security_scan_result.py @@ -16,8 +16,9 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt from typing import Any, ClassVar, Dict, List, Optional +from revengai.models.security_finding import SecurityFinding from typing import Optional, Set from typing_extensions import Self @@ -29,11 +30,10 @@ class SecurityScanResult(BaseModel): cancelled: StrictBool = Field(description="Whether the run was cancelled before it covered every function") decompiled: StrictInt = Field(description="Functions successfully decompiled and scanned") failed: StrictInt = Field(description="Functions whose decompilation or scan attempt errored") - security_scan: Optional[Dict[str, Any]] = Field(default=None, description="Raw semgrep findings, keyed by the scanner's own result shape") - source: StrictStr = Field(description="Decompiler that produced the source scanned") + security_scan: Optional[List[SecurityFinding]] = Field(default=None, description="Shaped semgrep findings, one per result") total: StrictInt = Field(description="Functions the run considered") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["analysis_id", "cancelled", "decompiled", "failed", "security_scan", "source", "total"] + __properties: ClassVar[List[str]] = ["analysis_id", "cancelled", "decompiled", "failed", "security_scan", "total"] model_config = ConfigDict( populate_by_name=True, @@ -76,11 +76,23 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of each item in security_scan (list) + _items = [] + if self.security_scan: + for _item_security_scan in self.security_scan: + if _item_security_scan: + _items.append(_item_security_scan.to_dict()) + _dict['security_scan'] = _items # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: for _key, _value in self.additional_properties.items(): _dict[_key] = _value + # set to None if security_scan (nullable) is None + # and model_fields_set contains the field + if self.security_scan is None and "security_scan" in self.model_fields_set: + _dict['security_scan'] = None + return _dict @classmethod @@ -97,8 +109,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "cancelled": obj.get("cancelled"), "decompiled": obj.get("decompiled"), "failed": obj.get("failed"), - "security_scan": obj.get("security_scan"), - "source": obj.get("source"), + "security_scan": [SecurityFinding.from_dict(_item) for _item in obj["security_scan"]] if obj.get("security_scan") is not None else None, "total": obj.get("total") }) # store additional fields in additional_properties diff --git a/revengai/models/start_batch_matching_input_body.py b/revengai/models/start_batch_matching_input_body.py index 7ca717f5..63083981 100644 --- a/revengai/models/start_batch_matching_input_body.py +++ b/revengai/models/start_batch_matching_input_body.py @@ -16,7 +16,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from typing import Optional, Set @@ -29,9 +29,10 @@ class StartBatchMatchingInputBody(BaseModel): binary_ids: Optional[Annotated[List[StrictInt], Field(min_length=1)]] = Field(description="Binary IDs to match the analysis against, one workflow per binary.") debug_types: Optional[List[Optional[StrictStr]]] = Field(default=None, description="Restrict matches to candidates with these debug source types. Defaults to [\"SYSTEM\"].") min_similarity: Optional[Union[Annotated[float, Field(le=100, strict=True, ge=0)], Annotated[int, Field(le=100, strict=True, ge=0)]]] = Field(default=None, description="Similarity floor as a percentage. Defaults to 90.") + no_cache: Optional[StrictBool] = Field(default=None, description="By default a completed matching run is reused per binary (that binary reports status=COMPLETED, no new run). Set true to force fresh runs for every binary.") results_per_function: Optional[Annotated[int, Field(le=30, strict=True, ge=1)]] = Field(default=None, description="Max matches returned per source function. Defaults to 1.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["binary_ids", "debug_types", "min_similarity", "results_per_function"] + __properties: ClassVar[List[str]] = ["binary_ids", "debug_types", "min_similarity", "no_cache", "results_per_function"] model_config = ConfigDict( populate_by_name=True, @@ -104,6 +105,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "binary_ids": obj.get("binary_ids"), "debug_types": obj.get("debug_types"), "min_similarity": obj.get("min_similarity"), + "no_cache": obj.get("no_cache"), "results_per_function": obj.get("results_per_function") }) # store additional fields in additional_properties diff --git a/revengai/models/start_matching_output_body.py b/revengai/models/start_matching_output_body.py index 7a3a3ec9..7faf1752 100644 --- a/revengai/models/start_matching_output_body.py +++ b/revengai/models/start_matching_output_body.py @@ -28,12 +28,17 @@ class StartMatchingOutputBody(BaseModel): """ # noqa: E501 match_id: StrictStr = Field(description="Opaque token for this matching run. Pass it to the GET/status endpoints' match_id query parameter to fetch this exact run.") messages: Optional[List[ProgressMessage]] = Field(description="Log messages emitted during execution") + percent: StrictInt = Field(description="Overall completion as a percentage, weighted by step duration") status: StrictStr = Field(description="Current workflow status") step: StrictStr = Field(description="Name of the current step") step_index: StrictInt = Field(description="Zero-based index of the current step") + step_share: StrictInt = Field(description="Percentage points the current step contributes when it completes") steps_total: StrictInt = Field(description="Total number of steps in the workflow") + sub_step: Optional[StrictStr] = Field(default=None, description="Phase within the current step, when the step reports one") + sub_step_done: Optional[StrictInt] = Field(default=None, description="Items completed in the current phase") + sub_step_total: Optional[StrictInt] = Field(default=None, description="Items the current phase will process, 0 when unknown") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["match_id", "messages", "status", "step", "step_index", "steps_total"] + __properties: ClassVar[List[str]] = ["match_id", "messages", "percent", "status", "step", "step_index", "step_share", "steps_total", "sub_step", "sub_step_done", "sub_step_total"] @field_validator('status') def status_validate_enum(cls, value): @@ -114,10 +119,15 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "match_id": obj.get("match_id"), "messages": [ProgressMessage.from_dict(_item) for _item in obj["messages"]] if obj.get("messages") is not None else None, + "percent": obj.get("percent"), "status": obj.get("status"), "step": obj.get("step"), "step_index": obj.get("step_index"), - "steps_total": obj.get("steps_total") + "step_share": obj.get("step_share"), + "steps_total": obj.get("steps_total"), + "sub_step": obj.get("sub_step"), + "sub_step_done": obj.get("sub_step_done"), + "sub_step_total": obj.get("sub_step_total") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/revengai/models/summary_data.py b/revengai/models/summary_data.py index 2d0c98fe..edfa0610 100644 --- a/revengai/models/summary_data.py +++ b/revengai/models/summary_data.py @@ -17,7 +17,7 @@ import json from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator -from typing import Any, ClassVar, Dict, List +from typing import Any, ClassVar, Dict, List, Optional from typing import Optional, Set from typing_extensions import Self @@ -26,10 +26,11 @@ class SummaryData(BaseModel): SummaryData """ # noqa: E501 ai_summary: StrictStr = Field(description="Summary with code tags removed") + predicted_function_name: Optional[StrictStr] = Field(default=None, description="Name the model proposes for this function, produced alongside the summary.") summary: StrictStr = Field(description="Raw summary from the model") task_status: StrictStr = Field(description="Task status") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["ai_summary", "summary", "task_status"] + __properties: ClassVar[List[str]] = ["ai_summary", "predicted_function_name", "summary", "task_status"] @field_validator('task_status') def task_status_validate_enum(cls, value): @@ -97,6 +98,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "ai_summary": obj.get("ai_summary"), + "predicted_function_name": obj.get("predicted_function_name"), "summary": obj.get("summary"), "task_status": obj.get("task_status") }) diff --git a/revengai/models/workflow_progress.py b/revengai/models/workflow_progress.py index 96ca5848..f280deb0 100644 --- a/revengai/models/workflow_progress.py +++ b/revengai/models/workflow_progress.py @@ -27,12 +27,17 @@ class WorkflowProgress(BaseModel): WorkflowProgress """ # noqa: E501 messages: Optional[List[ProgressMessage]] = Field(description="Log messages emitted during execution") + percent: StrictInt = Field(description="Overall completion as a percentage, weighted by step duration") status: StrictStr = Field(description="Current workflow status") step: StrictStr = Field(description="Name of the current step") step_index: StrictInt = Field(description="Zero-based index of the current step") + step_share: StrictInt = Field(description="Percentage points the current step contributes when it completes") steps_total: StrictInt = Field(description="Total number of steps in the workflow") + sub_step: Optional[StrictStr] = Field(default=None, description="Phase within the current step, when the step reports one") + sub_step_done: Optional[StrictInt] = Field(default=None, description="Items completed in the current phase") + sub_step_total: Optional[StrictInt] = Field(default=None, description="Items the current phase will process, 0 when unknown") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["messages", "status", "step", "step_index", "steps_total"] + __properties: ClassVar[List[str]] = ["messages", "percent", "status", "step", "step_index", "step_share", "steps_total", "sub_step", "sub_step_done", "sub_step_total"] @field_validator('status') def status_validate_enum(cls, value): @@ -112,10 +117,15 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "messages": [ProgressMessage.from_dict(_item) for _item in obj["messages"]] if obj.get("messages") is not None else None, + "percent": obj.get("percent"), "status": obj.get("status"), "step": obj.get("step"), "step_index": obj.get("step_index"), - "steps_total": obj.get("steps_total") + "step_share": obj.get("step_share"), + "steps_total": obj.get("steps_total"), + "sub_step": obj.get("sub_step"), + "sub_step_done": obj.get("sub_step_done"), + "sub_step_total": obj.get("sub_step_total") }) # store additional fields in additional_properties for _key in obj.keys():