From ce8e98e9031f02efe25d467033e93163fb99e648 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 2 Sep 2026 14:32:44 +0000 Subject: [PATCH] Update SDK to version v4.20.0 - Generated from OpenAPI spec version v4.20.0 - Auto-generated by GitHub Actions --- .sdk-version | 2 +- README.md | 16 + docs/AgentApi.md | 193 ++++++ docs/CryptoCall.md | 33 + docs/CryptoDirectMatch.md | 32 + docs/CryptoFinding.md | 38 ++ docs/CryptoScanMetadata.md | 30 + docs/CryptoScanResult.md | 31 + docs/EventTypesSuggested.md | 32 + docs/FunctionsAIDecompilationApi.md | 113 +++- docs/FunctionsRenamingHistoryApi.md | 2 +- ...ationCryptoScanMetadataCryptoScanResult.md | 33 + docs/RenameInputBody.md | 1 + docs/ResolvedEntity.md | 1 + docs/SuggestedHole.md | 30 + docs/SuggestedMemberView.md | 38 ++ docs/SuggestedTypeView.md | 36 ++ docs/TriggerCryptoScanInputBody.md | 31 + docs/TypeSuggestionsData.md | 31 + docs/TypesSuggestedEvent.md | 33 + revengai/__init__.py | 28 +- revengai/api/agent_api.py | 581 ++++++++++++++++++ .../api/functions_ai_decompilation_api.py | 302 ++++++++- .../api/functions_renaming_history_api.py | 6 +- revengai/api_client.py | 2 +- revengai/configuration.py | 4 +- revengai/models/__init__.py | 13 + revengai/models/crypto_call.py | 128 ++++ revengai/models/crypto_direct_match.py | 126 ++++ revengai/models/crypto_finding.py | 182 ++++++ revengai/models/crypto_scan_metadata.py | 114 ++++ revengai/models/crypto_scan_result.py | 116 ++++ revengai/models/event_types_suggested.py | 103 ++++ ...crypto_scan_metadata_crypto_scan_result.py | 119 ++++ revengai/models/rename_input_body.py | 18 +- revengai/models/resolved_entity.py | 13 +- ...ream_ai_decompilation200_response_inner.py | 32 +- revengai/models/suggested_hole.py | 101 +++ revengai/models/suggested_member_view.py | 159 +++++ revengai/models/suggested_type_view.py | 139 +++++ .../models/trigger_crypto_scan_input_body.py | 135 ++++ revengai/models/type_suggestions_data.py | 123 ++++ revengai/models/types_suggested_event.py | 107 ++++ 43 files changed, 3371 insertions(+), 36 deletions(-) create mode 100644 docs/CryptoCall.md create mode 100644 docs/CryptoDirectMatch.md create mode 100644 docs/CryptoFinding.md create mode 100644 docs/CryptoScanMetadata.md create mode 100644 docs/CryptoScanResult.md create mode 100644 docs/EventTypesSuggested.md create mode 100644 docs/OperationCryptoScanMetadataCryptoScanResult.md create mode 100644 docs/SuggestedHole.md create mode 100644 docs/SuggestedMemberView.md create mode 100644 docs/SuggestedTypeView.md create mode 100644 docs/TriggerCryptoScanInputBody.md create mode 100644 docs/TypeSuggestionsData.md create mode 100644 docs/TypesSuggestedEvent.md create mode 100644 revengai/models/crypto_call.py create mode 100644 revengai/models/crypto_direct_match.py create mode 100644 revengai/models/crypto_finding.py create mode 100644 revengai/models/crypto_scan_metadata.py create mode 100644 revengai/models/crypto_scan_result.py create mode 100644 revengai/models/event_types_suggested.py create mode 100644 revengai/models/operation_crypto_scan_metadata_crypto_scan_result.py create mode 100644 revengai/models/suggested_hole.py create mode 100644 revengai/models/suggested_member_view.py create mode 100644 revengai/models/suggested_type_view.py create mode 100644 revengai/models/trigger_crypto_scan_input_body.py create mode 100644 revengai/models/type_suggestions_data.py create mode 100644 revengai/models/types_suggested_event.py diff --git a/.sdk-version b/.sdk-version index c4475d31..1beef590 100644 --- a/.sdk-version +++ b/.sdk-version @@ -1 +1 @@ -v4.13.0 +v4.20.0 diff --git a/README.md b/README.md index be55b59e..ea4af387 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,11 @@ Class | Method | HTTP request | Description *AgentApi* | [**get_triage_result_v2_analyses_analysis_id_agent_triage_get**](docs/AgentApi.md#get_triage_result_v2_analyses_analysis_id_agent_triage_get) | **GET** /v2/analyses/{analysis_id}/agent/triage | Get Triage Result *AgentApi* | [**v3_cancel_rename_unnamed_functions**](docs/AgentApi.md#v3_cancel_rename_unnamed_functions) | **POST** /v3/analyses/{analysis_id}/agents/rename-unnamed-functions/cancel | Cancel the rename-unnamed-functions agent. *AgentApi* | [**v3_cancel_security_scan_operation**](docs/AgentApi.md#v3_cancel_security_scan_operation) | **POST** /v3/operations/security-scan/{analysis_id}:cancel | Cancel a security-scan operation. +*AgentApi* | [**v3_get_crypto_scan_operation**](docs/AgentApi.md#v3_get_crypto_scan_operation) | **GET** /v3/operations/crypto-scan/{analysis_id} | Get a crypto-scan operation. *AgentApi* | [**v3_get_rename_unnamed_functions_result**](docs/AgentApi.md#v3_get_rename_unnamed_functions_result) | **GET** /v3/analyses/{analysis_id}/agents/rename-unnamed-functions | Get rename-unnamed-functions agent result. *AgentApi* | [**v3_get_rename_unnamed_functions_status**](docs/AgentApi.md#v3_get_rename_unnamed_functions_status) | **GET** /v3/analyses/{analysis_id}/agents/rename-unnamed-functions/status | Get rename-unnamed-functions agent status. *AgentApi* | [**v3_get_security_scan_operation**](docs/AgentApi.md#v3_get_security_scan_operation) | **GET** /v3/operations/security-scan/{analysis_id} | Get a security-scan operation. +*AgentApi* | [**v3_run_crypto_scan**](docs/AgentApi.md#v3_run_crypto_scan) | **POST** /v3/analyses/{analysis_id}/crypto-scan:run | Run the crypto-scan agent. *AgentApi* | [**v3_run_security_scan**](docs/AgentApi.md#v3_run_security_scan) | **POST** /v3/analyses/{analysis_id}/security-scan:run | Run the security-scan agent. *AgentApi* | [**v3_trigger_rename_unnamed_functions**](docs/AgentApi.md#v3_trigger_rename_unnamed_functions) | **POST** /v3/analyses/{analysis_id}/agents/rename-unnamed-functions | Run the rename-unnamed-functions agent. *AnalysesBulkActionsApi* | [**bulk_add_analysis_tags**](docs/AnalysesBulkActionsApi.md#bulk_add_analysis_tags) | **PATCH** /v2/analyses/tags/add | Bulk Add Analysis Tags @@ -167,6 +169,7 @@ Class | Method | HTTP request | Description *FunctionsAIDecompilationApi* | [**upsert_ai_decompilation_rating**](docs/FunctionsAIDecompilationApi.md#upsert_ai_decompilation_rating) | **PATCH** /v2/functions/{function_id}/ai-decompilation/rating | Upsert rating for AI decompilation *FunctionsAIDecompilationApi* | [**v3_get_ai_decompilation_line_attributions**](docs/FunctionsAIDecompilationApi.md#v3_get_ai_decompilation_line_attributions) | **GET** /v3/functions/{function_id}/ai-decompilation/line-attributions | Get AI decompilation line attributions *FunctionsAIDecompilationApi* | [**v3_get_ai_decompilation_tokens**](docs/FunctionsAIDecompilationApi.md#v3_get_ai_decompilation_tokens) | **GET** /v3/functions/{function_id}/ai-decompilation/tokens | Get AI decompilation tokens and user overrides +*FunctionsAIDecompilationApi* | [**v3_get_ai_decompilation_type_suggestions**](docs/FunctionsAIDecompilationApi.md#v3_get_ai_decompilation_type_suggestions) | **GET** /v3/functions/{function_id}/ai-decompilation/type-suggestions | Get AI decompilation type suggestions *FunctionsAIDecompilationApi* | [**v3_upsert_ai_decompilation_overrides**](docs/FunctionsAIDecompilationApi.md#v3_upsert_ai_decompilation_overrides) | **PATCH** /v3/functions/{function_id}/ai-decompilation/overrides | Upsert variable/function name overrides *FunctionsCoreApi* | [**add_function_callee**](docs/FunctionsCoreApi.md#add_function_callee) | **POST** /v3/functions/{function_id}/callees | Add a callee to a function *FunctionsCoreApi* | [**add_user_string_to_function**](docs/FunctionsCoreApi.md#add_user_string_to_function) | **POST** /v3/functions/{function_id}/user-provided-strings | Add a user-provided string to a function. @@ -423,6 +426,11 @@ Class | Method | HTTP request | Description - [CreateUnknownDataType](docs/CreateUnknownDataType.md) - [CreateUserInputBody](docs/CreateUserInputBody.md) - [Created](docs/Created.md) + - [CryptoCall](docs/CryptoCall.md) + - [CryptoDirectMatch](docs/CryptoDirectMatch.md) + - [CryptoFinding](docs/CryptoFinding.md) + - [CryptoScanMetadata](docs/CryptoScanMetadata.md) + - [CryptoScanResult](docs/CryptoScanResult.md) - [DataTypeEntry](docs/DataTypeEntry.md) - [DataTypeEnumValueEntry](docs/DataTypeEnumValueEntry.md) - [DataTypeFunctionEntry](docs/DataTypeFunctionEntry.md) @@ -479,6 +487,7 @@ Class | Method | HTTP request | Description - [EventTOOLCALLRESULT](docs/EventTOOLCALLRESULT.md) - [EventTOOLCALLSTART](docs/EventTOOLCALLSTART.md) - [EventTOOLCONFIRMATIONREQUIRED](docs/EventTOOLCONFIRMATIONREQUIRED.md) + - [EventTypesSuggested](docs/EventTypesSuggested.md) - [EventWarning](docs/EventWarning.md) - [Example](docs/Example.md) - [ExportModel](docs/ExportModel.md) @@ -583,6 +592,7 @@ Class | Method | HTTP request | Description - [NamesFinishedEvent](docs/NamesFinishedEvent.md) - [NetworkActivity](docs/NetworkActivity.md) - [OIDCCallbackInputBody](docs/OIDCCallbackInputBody.md) + - [OperationCryptoScanMetadataCryptoScanResult](docs/OperationCryptoScanMetadataCryptoScanResult.md) - [OperationSecurityScanMetadataSecurityScanResult](docs/OperationSecurityScanMetadataSecurityScanResult.md) - [OperationWorkflowProgressResultBody](docs/OperationWorkflowProgressResultBody.md) - [Order](docs/Order.md) @@ -700,6 +710,9 @@ Class | Method | HTTP request | Description - [StructDataType](docs/StructDataType.md) - [StructDefinition](docs/StructDefinition.md) - [SubmitUserFeedbackRequest](docs/SubmitUserFeedbackRequest.md) + - [SuggestedHole](docs/SuggestedHole.md) + - [SuggestedMemberView](docs/SuggestedMemberView.md) + - [SuggestedTypeView](docs/SuggestedTypeView.md) - [SummaryData](docs/SummaryData.md) - [Symbols](docs/Symbols.md) - [Tag](docs/Tag.md) @@ -720,12 +733,15 @@ Class | Method | HTTP request | Description - [TokenisedData](docs/TokenisedData.md) - [TriageFunctionResponse](docs/TriageFunctionResponse.md) - [TriageReportResponse](docs/TriageReportResponse.md) + - [TriggerCryptoScanInputBody](docs/TriggerCryptoScanInputBody.md) - [TriggerDynamicExecutionInputBody](docs/TriggerDynamicExecutionInputBody.md) - [TriggerRenameUnnamedFunctionsInputBody](docs/TriggerRenameUnnamedFunctionsInputBody.md) - [TriggerSecurityScanInputBody](docs/TriggerSecurityScanInputBody.md) - [Ttp](docs/Ttp.md) + - [TypeSuggestionsData](docs/TypeSuggestionsData.md) - [TypedefDataType](docs/TypedefDataType.md) - [TypedefDefinition](docs/TypedefDefinition.md) + - [TypesSuggestedEvent](docs/TypesSuggestedEvent.md) - [UnionDataType](docs/UnionDataType.md) - [UnionDefinition](docs/UnionDefinition.md) - [UnknownDataType](docs/UnknownDataType.md) diff --git a/docs/AgentApi.md b/docs/AgentApi.md index eeaac386..35d00aea 100644 --- a/docs/AgentApi.md +++ b/docs/AgentApi.md @@ -18,9 +18,11 @@ Method | HTTP request | Description [**get_triage_result_v2_analyses_analysis_id_agent_triage_get**](AgentApi.md#get_triage_result_v2_analyses_analysis_id_agent_triage_get) | **GET** /v2/analyses/{analysis_id}/agent/triage | Get Triage Result [**v3_cancel_rename_unnamed_functions**](AgentApi.md#v3_cancel_rename_unnamed_functions) | **POST** /v3/analyses/{analysis_id}/agents/rename-unnamed-functions/cancel | Cancel the rename-unnamed-functions agent. [**v3_cancel_security_scan_operation**](AgentApi.md#v3_cancel_security_scan_operation) | **POST** /v3/operations/security-scan/{analysis_id}:cancel | Cancel a security-scan operation. +[**v3_get_crypto_scan_operation**](AgentApi.md#v3_get_crypto_scan_operation) | **GET** /v3/operations/crypto-scan/{analysis_id} | Get a crypto-scan operation. [**v3_get_rename_unnamed_functions_result**](AgentApi.md#v3_get_rename_unnamed_functions_result) | **GET** /v3/analyses/{analysis_id}/agents/rename-unnamed-functions | Get rename-unnamed-functions agent result. [**v3_get_rename_unnamed_functions_status**](AgentApi.md#v3_get_rename_unnamed_functions_status) | **GET** /v3/analyses/{analysis_id}/agents/rename-unnamed-functions/status | Get rename-unnamed-functions agent status. [**v3_get_security_scan_operation**](AgentApi.md#v3_get_security_scan_operation) | **GET** /v3/operations/security-scan/{analysis_id} | Get a security-scan operation. +[**v3_run_crypto_scan**](AgentApi.md#v3_run_crypto_scan) | **POST** /v3/analyses/{analysis_id}/crypto-scan:run | Run the crypto-scan agent. [**v3_run_security_scan**](AgentApi.md#v3_run_security_scan) | **POST** /v3/analyses/{analysis_id}/security-scan:run | Run the security-scan agent. [**v3_trigger_rename_unnamed_functions**](AgentApi.md#v3_trigger_rename_unnamed_functions) | **POST** /v3/analyses/{analysis_id}/agents/rename-unnamed-functions | Run the rename-unnamed-functions agent. @@ -1229,6 +1231,99 @@ void (empty response body) [[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) +# **v3_get_crypto_scan_operation** +> OperationCryptoScanMetadataCryptoScanResult v3_get_crypto_scan_operation(analysis_id) + +Get a crypto-scan operation. + +Returns the current state of the crypto-scan run for this analysis. + +**Error codes:** +- `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found +- `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied + +### Example + +* Api Key Authentication (APIKey): +* Bearer Authentication (bearerAuth): + +```python +import revengai +from revengai.models.operation_crypto_scan_metadata_crypto_scan_result import OperationCryptoScanMetadataCryptoScanResult +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.AgentApi(api_client) + analysis_id = 56 # int | Analysis ID + + try: + # Get a crypto-scan operation. + api_response = api_instance.v3_get_crypto_scan_operation(analysis_id) + print("The response of AgentApi->v3_get_crypto_scan_operation:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling AgentApi->v3_get_crypto_scan_operation: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **analysis_id** | **int**| Analysis ID | + +### Return type + +[**OperationCryptoScanMetadataCryptoScanResult**](OperationCryptoScanMetadataCryptoScanResult.md) + +### 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** | OK | - | +**403** | Forbidden | - | +**404** | Not Found | - | +**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) + # **v3_get_rename_unnamed_functions_result** > RenameUnnamedFunctionsResult v3_get_rename_unnamed_functions_result(analysis_id) @@ -1510,6 +1605,104 @@ 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) +# **v3_run_crypto_scan** +> OperationCryptoScanMetadataCryptoScanResult v3_run_crypto_scan(analysis_id, trigger_crypto_scan_input_body) + +Run the crypto-scan agent. + +Starts an agent that name-matches the analysis' functions and their callees against known crypto-library APIs, and returns the operation to poll for its outcome. Purely name-based — never triggers AI decompilation, so it costs no credits and runs in seconds. Returns 409 while a run is already in progress for this analysis. + +**Error codes:** +- `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found +- `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied +- `409` [`CONFLICT`](/errors/CONFLICT) — Conflict + +### Example + +* Api Key Authentication (APIKey): +* Bearer Authentication (bearerAuth): + +```python +import revengai +from revengai.models.operation_crypto_scan_metadata_crypto_scan_result import OperationCryptoScanMetadataCryptoScanResult +from revengai.models.trigger_crypto_scan_input_body import TriggerCryptoScanInputBody +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.AgentApi(api_client) + analysis_id = 56 # int | Analysis ID + trigger_crypto_scan_input_body = revengai.TriggerCryptoScanInputBody() # TriggerCryptoScanInputBody | + + try: + # Run the crypto-scan agent. + api_response = api_instance.v3_run_crypto_scan(analysis_id, trigger_crypto_scan_input_body) + print("The response of AgentApi->v3_run_crypto_scan:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling AgentApi->v3_run_crypto_scan: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **analysis_id** | **int**| Analysis ID | + **trigger_crypto_scan_input_body** | [**TriggerCryptoScanInputBody**](TriggerCryptoScanInputBody.md)| | + +### Return type + +[**OperationCryptoScanMetadataCryptoScanResult**](OperationCryptoScanMetadataCryptoScanResult.md) + +### Authorization + +[APIKey](../README.md#APIKey), [bearerAuth](../README.md#bearerAuth) + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**403** | Forbidden | - | +**404** | Not Found | - | +**409** | Conflict | - | +**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) + # **v3_run_security_scan** > OperationSecurityScanMetadataSecurityScanResult v3_run_security_scan(analysis_id, trigger_security_scan_input_body) diff --git a/docs/CryptoCall.md b/docs/CryptoCall.md new file mode 100644 index 00000000..7de7c2b3 --- /dev/null +++ b/docs/CryptoCall.md @@ -0,0 +1,33 @@ +# CryptoCall + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**callee_name** | **str** | Name of the called function | +**category** | **str** | Crypto category of the match | +**how** | **str** | Detection tier that produced the match | +**library** | **str** | Crypto library the match belongs to | +**matched_name** | **str** | Name or token that matched | + +## Example + +```python +from revengai.models.crypto_call import CryptoCall + +# TODO update the JSON string below +json = "{}" +# create an instance of CryptoCall from a JSON string +crypto_call_instance = CryptoCall.from_json(json) +# print the JSON string representation of the object +print(CryptoCall.to_json()) + +# convert the object into a dict +crypto_call_dict = crypto_call_instance.to_dict() +# create an instance of CryptoCall from a dict +crypto_call_from_dict = CryptoCall.from_dict(crypto_call_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/CryptoDirectMatch.md b/docs/CryptoDirectMatch.md new file mode 100644 index 00000000..59f72d21 --- /dev/null +++ b/docs/CryptoDirectMatch.md @@ -0,0 +1,32 @@ +# CryptoDirectMatch + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**category** | **str** | Crypto category of the match | +**how** | **str** | Detection tier that produced the match | +**library** | **str** | Crypto library the match belongs to | +**matched_name** | **str** | Name or token that matched | + +## Example + +```python +from revengai.models.crypto_direct_match import CryptoDirectMatch + +# TODO update the JSON string below +json = "{}" +# create an instance of CryptoDirectMatch from a JSON string +crypto_direct_match_instance = CryptoDirectMatch.from_json(json) +# print the JSON string representation of the object +print(CryptoDirectMatch.to_json()) + +# convert the object into a dict +crypto_direct_match_dict = crypto_direct_match_instance.to_dict() +# create an instance of CryptoDirectMatch from a dict +crypto_direct_match_from_dict = CryptoDirectMatch.from_dict(crypto_direct_match_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/CryptoFinding.md b/docs/CryptoFinding.md new file mode 100644 index 00000000..b4e29885 --- /dev/null +++ b/docs/CryptoFinding.md @@ -0,0 +1,38 @@ +# CryptoFinding + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**address** | **str** | Function's virtual address, hex-encoded | +**categories** | **List[str]** | Distinct crypto categories evidenced by this function | +**confidence** | **str** | High when a direct name match was found, medium when the function only calls into crypto APIs | +**crypto_calls** | [**List[CryptoCall]**](CryptoCall.md) | Matches against names this function calls | [optional] +**direct_matches** | [**List[CryptoDirectMatch]**](CryptoDirectMatch.md) | Matches against the function's own name | [optional] +**evidence_count** | **int** | Total number of direct matches and crypto calls | +**function_id** | **int** | ID of the function the finding was reported in | +**function_name** | **str** | Name of the function the finding was reported in | +**function_size** | **int** | Size of the function in bytes | +**libraries** | **List[str]** | Distinct crypto libraries evidenced by this function | + +## Example + +```python +from revengai.models.crypto_finding import CryptoFinding + +# TODO update the JSON string below +json = "{}" +# create an instance of CryptoFinding from a JSON string +crypto_finding_instance = CryptoFinding.from_json(json) +# print the JSON string representation of the object +print(CryptoFinding.to_json()) + +# convert the object into a dict +crypto_finding_dict = crypto_finding_instance.to_dict() +# create an instance of CryptoFinding from a dict +crypto_finding_from_dict = CryptoFinding.from_dict(crypto_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/CryptoScanMetadata.md b/docs/CryptoScanMetadata.md new file mode 100644 index 00000000..c12e35c5 --- /dev/null +++ b/docs/CryptoScanMetadata.md @@ -0,0 +1,30 @@ +# CryptoScanMetadata + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**log_history** | **List[List[object]]** | Progress messages the run recorded, oldest first. | [optional] +**status** | **str** | Run status. UNINITIALISED means the agent has never been triggered for this analysis. | + +## Example + +```python +from revengai.models.crypto_scan_metadata import CryptoScanMetadata + +# TODO update the JSON string below +json = "{}" +# create an instance of CryptoScanMetadata from a JSON string +crypto_scan_metadata_instance = CryptoScanMetadata.from_json(json) +# print the JSON string representation of the object +print(CryptoScanMetadata.to_json()) + +# convert the object into a dict +crypto_scan_metadata_dict = crypto_scan_metadata_instance.to_dict() +# create an instance of CryptoScanMetadata from a dict +crypto_scan_metadata_from_dict = CryptoScanMetadata.from_dict(crypto_scan_metadata_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/CryptoScanResult.md b/docs/CryptoScanResult.md new file mode 100644 index 00000000..6297a46a --- /dev/null +++ b/docs/CryptoScanResult.md @@ -0,0 +1,31 @@ +# CryptoScanResult + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**analysis_id** | **int** | Analysis the run was performed against | +**findings** | [**List[CryptoFinding]**](CryptoFinding.md) | Functions with crypto-related evidence, sorted by confidence then evidence count | [optional] +**total_functions** | **int** | Functions the run considered | + +## Example + +```python +from revengai.models.crypto_scan_result import CryptoScanResult + +# TODO update the JSON string below +json = "{}" +# create an instance of CryptoScanResult from a JSON string +crypto_scan_result_instance = CryptoScanResult.from_json(json) +# print the JSON string representation of the object +print(CryptoScanResult.to_json()) + +# convert the object into a dict +crypto_scan_result_dict = crypto_scan_result_instance.to_dict() +# create an instance of CryptoScanResult from a dict +crypto_scan_result_from_dict = CryptoScanResult.from_dict(crypto_scan_result_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/EventTypesSuggested.md b/docs/EventTypesSuggested.md new file mode 100644 index 00000000..14629821 --- /dev/null +++ b/docs/EventTypesSuggested.md @@ -0,0 +1,32 @@ +# EventTypesSuggested + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**data** | [**TypesSuggestedEvent**](TypesSuggestedEvent.md) | | +**event** | **str** | The event name. | +**id** | **int** | The event ID. | [optional] +**retry** | **int** | The retry time in milliseconds. | [optional] + +## Example + +```python +from revengai.models.event_types_suggested import EventTypesSuggested + +# TODO update the JSON string below +json = "{}" +# create an instance of EventTypesSuggested from a JSON string +event_types_suggested_instance = EventTypesSuggested.from_json(json) +# print the JSON string representation of the object +print(EventTypesSuggested.to_json()) + +# convert the object into a dict +event_types_suggested_dict = event_types_suggested_instance.to_dict() +# create an instance of EventTypesSuggested from a dict +event_types_suggested_from_dict = EventTypesSuggested.from_dict(event_types_suggested_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/FunctionsAIDecompilationApi.md b/docs/FunctionsAIDecompilationApi.md index d19dfe23..16a058d9 100644 --- a/docs/FunctionsAIDecompilationApi.md +++ b/docs/FunctionsAIDecompilationApi.md @@ -20,6 +20,7 @@ Method | HTTP request | Description [**upsert_ai_decompilation_rating**](FunctionsAIDecompilationApi.md#upsert_ai_decompilation_rating) | **PATCH** /v2/functions/{function_id}/ai-decompilation/rating | Upsert rating for AI decompilation [**v3_get_ai_decompilation_line_attributions**](FunctionsAIDecompilationApi.md#v3_get_ai_decompilation_line_attributions) | **GET** /v3/functions/{function_id}/ai-decompilation/line-attributions | Get AI decompilation line attributions [**v3_get_ai_decompilation_tokens**](FunctionsAIDecompilationApi.md#v3_get_ai_decompilation_tokens) | **GET** /v3/functions/{function_id}/ai-decompilation/tokens | Get AI decompilation tokens and user overrides +[**v3_get_ai_decompilation_type_suggestions**](FunctionsAIDecompilationApi.md#v3_get_ai_decompilation_type_suggestions) | **GET** /v3/functions/{function_id}/ai-decompilation/type-suggestions | Get AI decompilation type suggestions [**v3_upsert_ai_decompilation_overrides**](FunctionsAIDecompilationApi.md#v3_upsert_ai_decompilation_overrides) | **PATCH** /v3/functions/{function_id}/ai-decompilation/overrides | Upsert variable/function name overrides @@ -961,11 +962,13 @@ Name | Type | Description | Notes Regenerate AI decompilation inline comments -Starts a new inline comments generation workflow for the function. Requires an existing decompilation with a summary. +Starts a new inline comments generation workflow for the function. Requires an existing decompilation with a summary. Rejected while a decompilation is running: its naming and type-suggestion passes are still changing the identifiers the comments would reference. Poll the inline comments status endpoint, which reports PENDING until then. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found +- `400` [`BAD_REQUEST`](/errors/BAD_REQUEST) — Bad Request +- `409` [`CONFLICT`](/errors/CONFLICT) — Conflict ### Example @@ -1042,8 +1045,10 @@ Name | Type | Description | Notes | Status code | Description | Response headers | |-------------|-------------|------------------| **202** | Accepted | - | +**400** | Bad Request | - | **403** | Forbidden | - | **404** | Not Found | - | +**409** | Conflict | - | **422** | Unprocessable Entity | - | **500** | Internal Server Error | - | @@ -1054,11 +1059,12 @@ Name | Type | Description | Notes Regenerate AI decompilation summary -Starts a new summary generation workflow for the function. Requires an existing decompilation. +Starts a new summary generation workflow for the function. Requires an existing decompilation. Rejected while a decompilation is running: its naming and type-suggestion passes are still changing the identifiers a summary would describe. Poll the summary status endpoint, which reports PENDING until then. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found +- `409` [`CONFLICT`](/errors/CONFLICT) — Conflict ### Example @@ -1137,6 +1143,7 @@ Name | Type | Description | Notes **202** | Accepted | - | **403** | Forbidden | - | **404** | Not Found | - | +**409** | Conflict | - | **422** | Unprocessable Entity | - | **500** | Internal Server Error | - | @@ -1147,7 +1154,13 @@ Name | Type | Description | Notes Stream live AI decompilation output (SSE) -Opens a Server-Sent Events stream of incremental decompilation events for the given function. Each event has a `type` discriminator (also used as the SSE `event:` line) and a per-attempt monotonic `seq`. Terminal events: `decomp_finished` (success) or `decomp_failed` (all retries exhausted). `attempt_failed` is per-attempt and non-terminal — Temporal may retry the activity. Clients should treat `attempt` changes as a reset signal. `last_event_id` is not supported — clients fall back to polling the standard GET endpoint after the stream ends. +Opens a Server-Sent Events stream of incremental decompilation events for the given function. Each event has a `type` discriminator (also used as the SSE `event:` line) and a per-attempt monotonic `seq`. + +**Terminal events — the stream closes on these:** `names_finished` (success) and `decomp_failed` (all retries exhausted). `names_finished` is published on every success path, including when the naming pass is disabled, produces nothing, or fails, so a successful run always closes. + +**`decomp_finished` is NOT terminal.** It marks the end of the model call, not the end of the run: entity restore, the result write, the placeholder-naming pass and the type-suggestion pass all follow it, and the last two rewrite the identifiers the source renders with. Reading the decompilation at `decomp_finished` therefore returns names that are about to change — wait for `names_finished`. `attempt_failed` is per-attempt and non-terminal too: Temporal may retry, and clients disambiguate on `attempt`, which they should treat as a reset signal. + +`last_event_id` is not supported — clients fall back to polling the standard GET endpoint after the stream ends. ### Example @@ -1503,6 +1516,100 @@ 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) +# **v3_get_ai_decompilation_type_suggestions** +> TypeSuggestionsData v3_get_ai_decompilation_type_suggestions(function_id) + +Get AI decompilation type suggestions + +Returns the aggregate types the AI decompilation inferred for this function: a suggested name for each type and each of its members, the members' offsets and widths, and the gaps between them. Members revealed only by a caller or callee are included and marked by origin, as are members the model placed rather than observed. Nothing here is a data type row — these are proposals, and creating a row from one is the client's call. The list is empty until a run has produced suggestions, which is ordinary and not an error. + +**Error codes:** +- `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied +- `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found +- `500` [`INTERNAL_ERROR`](/errors/INTERNAL_ERROR) — Internal Server Error + +### Example + +* Api Key Authentication (APIKey): +* Bearer Authentication (bearerAuth): + +```python +import revengai +from revengai.models.type_suggestions_data import TypeSuggestionsData +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.FunctionsAIDecompilationApi(api_client) + function_id = 56 # int | Function ID + + try: + # Get AI decompilation type suggestions + api_response = api_instance.v3_get_ai_decompilation_type_suggestions(function_id) + print("The response of FunctionsAIDecompilationApi->v3_get_ai_decompilation_type_suggestions:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling FunctionsAIDecompilationApi->v3_get_ai_decompilation_type_suggestions: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **function_id** | **int**| Function ID | + +### Return type + +[**TypeSuggestionsData**](TypeSuggestionsData.md) + +### 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** | OK | - | +**403** | Forbidden | - | +**404** | Not Found | - | +**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) + # **v3_upsert_ai_decompilation_overrides** > UpsertOverridesData v3_upsert_ai_decompilation_overrides(function_id, upsert_overrides_input_body) diff --git a/docs/FunctionsRenamingHistoryApi.md b/docs/FunctionsRenamingHistoryApi.md index 65a9dfdb..2702d652 100644 --- a/docs/FunctionsRenamingHistoryApi.md +++ b/docs/FunctionsRenamingHistoryApi.md @@ -380,7 +380,7 @@ Name | Type | Description | Notes Rename a function -Renames a single function and records the change in history. +Renames a single function and records the change in history. `source_type` defaults to USER when omitted. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied diff --git a/docs/OperationCryptoScanMetadataCryptoScanResult.md b/docs/OperationCryptoScanMetadataCryptoScanResult.md new file mode 100644 index 00000000..c6b223cb --- /dev/null +++ b/docs/OperationCryptoScanMetadataCryptoScanResult.md @@ -0,0 +1,33 @@ +# OperationCryptoScanMetadataCryptoScanResult + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**done** | **bool** | Whether the operation has reached a terminal state. | +**error** | [**Status**](Status.md) | Failure detail, populated only when done is true and the operation failed. | [optional] +**metadata** | [**CryptoScanMetadata**](CryptoScanMetadata.md) | In-flight information and details. | [optional] +**name** | **str** | API resource name. | +**response** | [**CryptoScanResult**](CryptoScanResult.md) | Result, set only when done is true and the operation succeeded. | [optional] + +## Example + +```python +from revengai.models.operation_crypto_scan_metadata_crypto_scan_result import OperationCryptoScanMetadataCryptoScanResult + +# TODO update the JSON string below +json = "{}" +# create an instance of OperationCryptoScanMetadataCryptoScanResult from a JSON string +operation_crypto_scan_metadata_crypto_scan_result_instance = OperationCryptoScanMetadataCryptoScanResult.from_json(json) +# print the JSON string representation of the object +print(OperationCryptoScanMetadataCryptoScanResult.to_json()) + +# convert the object into a dict +operation_crypto_scan_metadata_crypto_scan_result_dict = operation_crypto_scan_metadata_crypto_scan_result_instance.to_dict() +# create an instance of OperationCryptoScanMetadataCryptoScanResult from a dict +operation_crypto_scan_metadata_crypto_scan_result_from_dict = OperationCryptoScanMetadataCryptoScanResult.from_dict(operation_crypto_scan_metadata_crypto_scan_result_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/RenameInputBody.md b/docs/RenameInputBody.md index 2b181139..50329d0c 100644 --- a/docs/RenameInputBody.md +++ b/docs/RenameInputBody.md @@ -7,6 +7,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **new_mangled_name** | **str** | New mangled function name | [optional] **new_name** | **str** | New function name | +**source_type** | **str** | Source that triggered the rename | [optional] ## Example diff --git a/docs/ResolvedEntity.md b/docs/ResolvedEntity.md index cf19e93e..3c69a4cb 100644 --- a/docs/ResolvedEntity.md +++ b/docs/ResolvedEntity.md @@ -21,6 +21,7 @@ Name | Type | Description | Notes **needs_naming** | **bool** | | **provenance** | **str** | | **resolved_name** | **str** | | +**suggested_name** | **str** | | [optional] **suggested_type** | **str** | | **suggestion_confidence** | **str** | | **token** | **str** | | diff --git a/docs/SuggestedHole.md b/docs/SuggestedHole.md new file mode 100644 index 00000000..0021d5ce --- /dev/null +++ b/docs/SuggestedHole.md @@ -0,0 +1,30 @@ +# SuggestedHole + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**byte_offset** | **int** | | +**byte_size** | **int** | | + +## Example + +```python +from revengai.models.suggested_hole import SuggestedHole + +# TODO update the JSON string below +json = "{}" +# create an instance of SuggestedHole from a JSON string +suggested_hole_instance = SuggestedHole.from_json(json) +# print the JSON string representation of the object +print(SuggestedHole.to_json()) + +# convert the object into a dict +suggested_hole_dict = suggested_hole_instance.to_dict() +# create an instance of SuggestedHole from a dict +suggested_hole_from_dict = SuggestedHole.from_dict(suggested_hole_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/SuggestedMemberView.md b/docs/SuggestedMemberView.md new file mode 100644 index 00000000..149552dc --- /dev/null +++ b/docs/SuggestedMemberView.md @@ -0,0 +1,38 @@ +# SuggestedMemberView + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**bit_offset** | **int** | Bit offset within the containing word for a bitfield member. | +**byte_offset** | **int** | Offset within the type. Null when no placement could be established. | +**byte_size** | **int** | Width of the access in bytes. | +**confidence** | **str** | Where suggested_type came from. declared and inferred were observed; width knows only the access width; model is the language model's proposal. | +**name** | **str** | Name the member renders as: a database or frozen name where one exists, else the suggested one. | +**origin** | **str** | Which function revealed this member: self, caller:<function_id> or callee:<function_id>. | +**packed** | **bool** | The member sits at an offset its own width does not divide. | +**placement** | **str** | observed means the offset was read off an access; guessed means the model proposed it; unplaced means the member has no offset. | +**suggested_type** | **str** | Type expression for the member. | +**token** | **str** | Placeholder this member renders as in the tokenised source. Absent for a member no access in this function revealed. | [optional] + +## Example + +```python +from revengai.models.suggested_member_view import SuggestedMemberView + +# TODO update the JSON string below +json = "{}" +# create an instance of SuggestedMemberView from a JSON string +suggested_member_view_instance = SuggestedMemberView.from_json(json) +# print the JSON string representation of the object +print(SuggestedMemberView.to_json()) + +# convert the object into a dict +suggested_member_view_dict = suggested_member_view_instance.to_dict() +# create an instance of SuggestedMemberView from a dict +suggested_member_view_from_dict = SuggestedMemberView.from_dict(suggested_member_view_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/SuggestedTypeView.md b/docs/SuggestedTypeView.md new file mode 100644 index 00000000..c893aca2 --- /dev/null +++ b/docs/SuggestedTypeView.md @@ -0,0 +1,36 @@ +# SuggestedTypeView + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**data_type_id** | **int** | Existing data type the members were accessed through. Null when nothing resolved to a row; never minted for a suggestion. | [optional] +**holes** | [**List[SuggestedHole]**](SuggestedHole.md) | Gaps between consecutive placed members, in offset order. | +**implied_size** | **int** | Highest byte_offset+byte_size across the members. A lower bound on the type's size, not its size. | [optional] +**key** | **str** | Identity of the suggestion: index:<data_type_id> where the access named a row, else token:<type_token>. | +**members** | [**List[SuggestedMemberView]**](SuggestedMemberView.md) | Members in offset order, unplaced ones last. | +**name** | **str** | Name the type renders as: a database or frozen name where one exists, else the suggested one. | +**type_token** | **str** | Placeholder the type renders as, when it appears in this function's source. | [optional] +**underlying_type** | **str** | Set only for a type with no observed members, where the suggestion is a name and a scalar type rather than a layout. | [optional] + +## Example + +```python +from revengai.models.suggested_type_view import SuggestedTypeView + +# TODO update the JSON string below +json = "{}" +# create an instance of SuggestedTypeView from a JSON string +suggested_type_view_instance = SuggestedTypeView.from_json(json) +# print the JSON string representation of the object +print(SuggestedTypeView.to_json()) + +# convert the object into a dict +suggested_type_view_dict = suggested_type_view_instance.to_dict() +# create an instance of SuggestedTypeView from a dict +suggested_type_view_from_dict = SuggestedTypeView.from_dict(suggested_type_view_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/TriggerCryptoScanInputBody.md b/docs/TriggerCryptoScanInputBody.md new file mode 100644 index 00000000..46e90deb --- /dev/null +++ b/docs/TriggerCryptoScanInputBody.md @@ -0,0 +1,31 @@ +# TriggerCryptoScanInputBody + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**categories** | **List[str]** | Restrict findings to these categories. Omit to scan every category. | [optional] +**direct_only** | **bool** | Only report functions whose own name matches a known crypto API; skips the calls-into-crypto pass, avoiding a bulk call-graph fetch. | [optional] +**libraries** | **List[str]** | Restrict findings to these libraries. Omit to scan every library. | [optional] + +## Example + +```python +from revengai.models.trigger_crypto_scan_input_body import TriggerCryptoScanInputBody + +# TODO update the JSON string below +json = "{}" +# create an instance of TriggerCryptoScanInputBody from a JSON string +trigger_crypto_scan_input_body_instance = TriggerCryptoScanInputBody.from_json(json) +# print the JSON string representation of the object +print(TriggerCryptoScanInputBody.to_json()) + +# convert the object into a dict +trigger_crypto_scan_input_body_dict = trigger_crypto_scan_input_body_instance.to_dict() +# create an instance of TriggerCryptoScanInputBody from a dict +trigger_crypto_scan_input_body_from_dict = TriggerCryptoScanInputBody.from_dict(trigger_crypto_scan_input_body_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/TypeSuggestionsData.md b/docs/TypeSuggestionsData.md new file mode 100644 index 00000000..9e639106 --- /dev/null +++ b/docs/TypeSuggestionsData.md @@ -0,0 +1,31 @@ +# TypeSuggestionsData + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**model** | **str** | Language model that produced the suggestions. | [optional] +**status** | **str** | Status of the AI decompilation run that would have produced these suggestions. | +**types** | [**List[SuggestedTypeView]**](SuggestedTypeView.md) | One entry per suggested type. Empty for a run that produced none, and for a run that predates type suggestion — the two are not distinguished. | + +## Example + +```python +from revengai.models.type_suggestions_data import TypeSuggestionsData + +# TODO update the JSON string below +json = "{}" +# create an instance of TypeSuggestionsData from a JSON string +type_suggestions_data_instance = TypeSuggestionsData.from_json(json) +# print the JSON string representation of the object +print(TypeSuggestionsData.to_json()) + +# convert the object into a dict +type_suggestions_data_dict = type_suggestions_data_instance.to_dict() +# create an instance of TypeSuggestionsData from a dict +type_suggestions_data_from_dict = TypeSuggestionsData.from_dict(type_suggestions_data_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/TypesSuggestedEvent.md b/docs/TypesSuggestedEvent.md new file mode 100644 index 00000000..5cdaa391 --- /dev/null +++ b/docs/TypesSuggestedEvent.md @@ -0,0 +1,33 @@ +# TypesSuggestedEvent + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**attempt** | **int** | | +**members** | **int** | | +**seq** | **int** | | +**type** | **str** | | +**types** | **int** | | + +## Example + +```python +from revengai.models.types_suggested_event import TypesSuggestedEvent + +# TODO update the JSON string below +json = "{}" +# create an instance of TypesSuggestedEvent from a JSON string +types_suggested_event_instance = TypesSuggestedEvent.from_json(json) +# print the JSON string representation of the object +print(TypesSuggestedEvent.to_json()) + +# convert the object into a dict +types_suggested_event_dict = types_suggested_event_instance.to_dict() +# create an instance of TypesSuggestedEvent from a dict +types_suggested_event_from_dict = TypesSuggestedEvent.from_dict(types_suggested_event_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/revengai/__init__.py b/revengai/__init__.py index df9dfe2f..f4331fab 100644 --- a/revengai/__init__.py +++ b/revengai/__init__.py @@ -13,7 +13,7 @@ """ # noqa: E501 -__version__ = "v4.13.0" +__version__ = "v4.20.0" # Define package exports __all__ = [ @@ -255,6 +255,11 @@ "CreateUnknownDataType", "CreateUserInputBody", "Created", + "CryptoCall", + "CryptoDirectMatch", + "CryptoFinding", + "CryptoScanMetadata", + "CryptoScanResult", "DataTypeEntry", "DataTypeEnumValueEntry", "DataTypeFunctionEntry", @@ -311,6 +316,7 @@ "EventTOOLCALLRESULT", "EventTOOLCALLSTART", "EventTOOLCONFIRMATIONREQUIRED", + "EventTypesSuggested", "EventWarning", "Example", "ExportModel", @@ -415,6 +421,7 @@ "NamesFinishedEvent", "NetworkActivity", "OIDCCallbackInputBody", + "OperationCryptoScanMetadataCryptoScanResult", "OperationSecurityScanMetadataSecurityScanResult", "OperationWorkflowProgressResultBody", "Order", @@ -532,6 +539,9 @@ "StructDataType", "StructDefinition", "SubmitUserFeedbackRequest", + "SuggestedHole", + "SuggestedMemberView", + "SuggestedTypeView", "SummaryData", "Symbols", "Tag", @@ -552,12 +562,15 @@ "TokenisedData", "TriageFunctionResponse", "TriageReportResponse", + "TriggerCryptoScanInputBody", "TriggerDynamicExecutionInputBody", "TriggerRenameUnnamedFunctionsInputBody", "TriggerSecurityScanInputBody", "Ttp", + "TypeSuggestionsData", "TypedefDataType", "TypedefDefinition", + "TypesSuggestedEvent", "UnionDataType", "UnionDefinition", "UnknownDataType", @@ -843,6 +856,11 @@ from revengai.models.create_unknown_data_type import CreateUnknownDataType as CreateUnknownDataType from revengai.models.create_user_input_body import CreateUserInputBody as CreateUserInputBody from revengai.models.created import Created as Created +from revengai.models.crypto_call import CryptoCall as CryptoCall +from revengai.models.crypto_direct_match import CryptoDirectMatch as CryptoDirectMatch +from revengai.models.crypto_finding import CryptoFinding as CryptoFinding +from revengai.models.crypto_scan_metadata import CryptoScanMetadata as CryptoScanMetadata +from revengai.models.crypto_scan_result import CryptoScanResult as CryptoScanResult from revengai.models.data_type_entry import DataTypeEntry as DataTypeEntry from revengai.models.data_type_enum_value_entry import DataTypeEnumValueEntry as DataTypeEnumValueEntry from revengai.models.data_type_function_entry import DataTypeFunctionEntry as DataTypeFunctionEntry @@ -899,6 +917,7 @@ from revengai.models.event_toolcallresult import EventTOOLCALLRESULT as EventTOOLCALLRESULT from revengai.models.event_toolcallstart import EventTOOLCALLSTART as EventTOOLCALLSTART from revengai.models.event_toolconfirmationrequired import EventTOOLCONFIRMATIONREQUIRED as EventTOOLCONFIRMATIONREQUIRED +from revengai.models.event_types_suggested import EventTypesSuggested as EventTypesSuggested from revengai.models.event_warning import EventWarning as EventWarning from revengai.models.example import Example as Example from revengai.models.export_model import ExportModel as ExportModel @@ -1003,6 +1022,7 @@ from revengai.models.names_finished_event import NamesFinishedEvent as NamesFinishedEvent from revengai.models.network_activity import NetworkActivity as NetworkActivity from revengai.models.oidc_callback_input_body import OIDCCallbackInputBody as OIDCCallbackInputBody +from revengai.models.operation_crypto_scan_metadata_crypto_scan_result import OperationCryptoScanMetadataCryptoScanResult as OperationCryptoScanMetadataCryptoScanResult from revengai.models.operation_security_scan_metadata_security_scan_result import OperationSecurityScanMetadataSecurityScanResult as OperationSecurityScanMetadataSecurityScanResult from revengai.models.operation_workflow_progress_result_body import OperationWorkflowProgressResultBody as OperationWorkflowProgressResultBody from revengai.models.order import Order as Order @@ -1120,6 +1140,9 @@ from revengai.models.struct_data_type import StructDataType as StructDataType from revengai.models.struct_definition import StructDefinition as StructDefinition from revengai.models.submit_user_feedback_request import SubmitUserFeedbackRequest as SubmitUserFeedbackRequest +from revengai.models.suggested_hole import SuggestedHole as SuggestedHole +from revengai.models.suggested_member_view import SuggestedMemberView as SuggestedMemberView +from revengai.models.suggested_type_view import SuggestedTypeView as SuggestedTypeView from revengai.models.summary_data import SummaryData as SummaryData from revengai.models.symbols import Symbols as Symbols from revengai.models.tag import Tag as Tag @@ -1140,12 +1163,15 @@ from revengai.models.tokenised_data import TokenisedData as TokenisedData from revengai.models.triage_function_response import TriageFunctionResponse as TriageFunctionResponse from revengai.models.triage_report_response import TriageReportResponse as TriageReportResponse +from revengai.models.trigger_crypto_scan_input_body import TriggerCryptoScanInputBody as TriggerCryptoScanInputBody from revengai.models.trigger_dynamic_execution_input_body import TriggerDynamicExecutionInputBody as TriggerDynamicExecutionInputBody from revengai.models.trigger_rename_unnamed_functions_input_body import TriggerRenameUnnamedFunctionsInputBody as TriggerRenameUnnamedFunctionsInputBody from revengai.models.trigger_security_scan_input_body import TriggerSecurityScanInputBody as TriggerSecurityScanInputBody from revengai.models.ttp import Ttp as Ttp +from revengai.models.type_suggestions_data import TypeSuggestionsData as TypeSuggestionsData from revengai.models.typedef_data_type import TypedefDataType as TypedefDataType from revengai.models.typedef_definition import TypedefDefinition as TypedefDefinition +from revengai.models.types_suggested_event import TypesSuggestedEvent as TypesSuggestedEvent from revengai.models.union_data_type import UnionDataType as UnionDataType from revengai.models.union_definition import UnionDefinition as UnionDefinition from revengai.models.unknown_data_type import UnknownDataType as UnknownDataType diff --git a/revengai/api/agent_api.py b/revengai/api/agent_api.py index 37fac099..2cb0a580 100644 --- a/revengai/api/agent_api.py +++ b/revengai/api/agent_api.py @@ -22,11 +22,13 @@ from revengai.models.base_response_remediation_agent_response import BaseResponseRemediationAgentResponse from revengai.models.base_response_report_analysis_response import BaseResponseReportAnalysisResponse from revengai.models.base_response_triage_report_response import BaseResponseTriageReportResponse +from revengai.models.operation_crypto_scan_metadata_crypto_scan_result import OperationCryptoScanMetadataCryptoScanResult from revengai.models.operation_security_scan_metadata_security_scan_result import OperationSecurityScanMetadataSecurityScanResult from revengai.models.queued_workflow_task_response import QueuedWorkflowTaskResponse from revengai.models.rename_unnamed_functions_result import RenameUnnamedFunctionsResult from revengai.models.status_body import StatusBody from revengai.models.task_status_response import TaskStatusResponse +from revengai.models.trigger_crypto_scan_input_body import TriggerCryptoScanInputBody from revengai.models.trigger_rename_unnamed_functions_input_body import TriggerRenameUnnamedFunctionsInputBody from revengai.models.trigger_security_scan_input_body import TriggerSecurityScanInputBody @@ -3749,6 +3751,280 @@ def _v3_cancel_security_scan_operation_serialize( + @validate_call + def v3_get_crypto_scan_operation( + self, + analysis_id: Annotated[int, Field(strict=True, ge=1, description="Analysis ID")], + _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, + ) -> OperationCryptoScanMetadataCryptoScanResult: + """Get a crypto-scan operation. + + Returns the current state of the crypto-scan run for this analysis. **Error codes:** - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied + + :param analysis_id: Analysis ID (required) + :type analysis_id: int + :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._v3_get_crypto_scan_operation_serialize( + analysis_id=analysis_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OperationCryptoScanMetadataCryptoScanResult", + '403': "APIError", + '404': "APIError", + '422': "APIError", + '500': "APIError", + } + 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 v3_get_crypto_scan_operation_with_http_info( + self, + analysis_id: Annotated[int, Field(strict=True, ge=1, description="Analysis ID")], + _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[OperationCryptoScanMetadataCryptoScanResult]: + """Get a crypto-scan operation. + + Returns the current state of the crypto-scan run for this analysis. **Error codes:** - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied + + :param analysis_id: Analysis ID (required) + :type analysis_id: int + :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._v3_get_crypto_scan_operation_serialize( + analysis_id=analysis_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OperationCryptoScanMetadataCryptoScanResult", + '403': "APIError", + '404': "APIError", + '422': "APIError", + '500': "APIError", + } + 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 v3_get_crypto_scan_operation_without_preload_content( + self, + analysis_id: Annotated[int, Field(strict=True, ge=1, description="Analysis ID")], + _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 a crypto-scan operation. + + Returns the current state of the crypto-scan run for this analysis. **Error codes:** - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied + + :param analysis_id: Analysis ID (required) + :type analysis_id: int + :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._v3_get_crypto_scan_operation_serialize( + analysis_id=analysis_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OperationCryptoScanMetadataCryptoScanResult", + '403': "APIError", + '404': "APIError", + '422': "APIError", + '500': "APIError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _v3_get_crypto_scan_operation_serialize( + self, + analysis_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 analysis_id is not None: + _path_params['analysis_id'] = analysis_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='/v3/operations/crypto-scan/{analysis_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 v3_get_rename_unnamed_functions_result( self, @@ -4574,6 +4850,311 @@ def _v3_get_security_scan_operation_serialize( + @validate_call + def v3_run_crypto_scan( + self, + analysis_id: Annotated[int, Field(strict=True, ge=1, description="Analysis ID")], + trigger_crypto_scan_input_body: TriggerCryptoScanInputBody, + _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, + ) -> OperationCryptoScanMetadataCryptoScanResult: + """Run the crypto-scan agent. + + Starts an agent that name-matches the analysis' functions and their callees against known crypto-library APIs, and returns the operation to poll for its outcome. Purely name-based — never triggers AI decompilation, so it costs no credits and runs in seconds. Returns 409 while a run is already in progress for this analysis. **Error codes:** - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `409` [`CONFLICT`](/errors/CONFLICT) — Conflict + + :param analysis_id: Analysis ID (required) + :type analysis_id: int + :param trigger_crypto_scan_input_body: (required) + :type trigger_crypto_scan_input_body: TriggerCryptoScanInputBody + :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._v3_run_crypto_scan_serialize( + analysis_id=analysis_id, + trigger_crypto_scan_input_body=trigger_crypto_scan_input_body, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OperationCryptoScanMetadataCryptoScanResult", + '403': "APIError", + '404': "APIError", + '409': "APIError", + '422': "APIError", + '500': "APIError", + } + 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 v3_run_crypto_scan_with_http_info( + self, + analysis_id: Annotated[int, Field(strict=True, ge=1, description="Analysis ID")], + trigger_crypto_scan_input_body: TriggerCryptoScanInputBody, + _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[OperationCryptoScanMetadataCryptoScanResult]: + """Run the crypto-scan agent. + + Starts an agent that name-matches the analysis' functions and their callees against known crypto-library APIs, and returns the operation to poll for its outcome. Purely name-based — never triggers AI decompilation, so it costs no credits and runs in seconds. Returns 409 while a run is already in progress for this analysis. **Error codes:** - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `409` [`CONFLICT`](/errors/CONFLICT) — Conflict + + :param analysis_id: Analysis ID (required) + :type analysis_id: int + :param trigger_crypto_scan_input_body: (required) + :type trigger_crypto_scan_input_body: TriggerCryptoScanInputBody + :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._v3_run_crypto_scan_serialize( + analysis_id=analysis_id, + trigger_crypto_scan_input_body=trigger_crypto_scan_input_body, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OperationCryptoScanMetadataCryptoScanResult", + '403': "APIError", + '404': "APIError", + '409': "APIError", + '422': "APIError", + '500': "APIError", + } + 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 v3_run_crypto_scan_without_preload_content( + self, + analysis_id: Annotated[int, Field(strict=True, ge=1, description="Analysis ID")], + trigger_crypto_scan_input_body: TriggerCryptoScanInputBody, + _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: + """Run the crypto-scan agent. + + Starts an agent that name-matches the analysis' functions and their callees against known crypto-library APIs, and returns the operation to poll for its outcome. Purely name-based — never triggers AI decompilation, so it costs no credits and runs in seconds. Returns 409 while a run is already in progress for this analysis. **Error codes:** - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `409` [`CONFLICT`](/errors/CONFLICT) — Conflict + + :param analysis_id: Analysis ID (required) + :type analysis_id: int + :param trigger_crypto_scan_input_body: (required) + :type trigger_crypto_scan_input_body: TriggerCryptoScanInputBody + :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._v3_run_crypto_scan_serialize( + analysis_id=analysis_id, + trigger_crypto_scan_input_body=trigger_crypto_scan_input_body, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "OperationCryptoScanMetadataCryptoScanResult", + '403': "APIError", + '404': "APIError", + '409': "APIError", + '422': "APIError", + '500': "APIError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _v3_run_crypto_scan_serialize( + self, + analysis_id, + trigger_crypto_scan_input_body, + _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 analysis_id is not None: + _path_params['analysis_id'] = analysis_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if trigger_crypto_scan_input_body is not None: + _body_params = trigger_crypto_scan_input_body + + + # 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( + [ + 'application/json' + ] + ) + ) + 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='/v3/analyses/{analysis_id}/crypto-scan:run', + 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 v3_run_security_scan( self, diff --git a/revengai/api/functions_ai_decompilation_api.py b/revengai/api/functions_ai_decompilation_api.py index baa27a13..2df3b606 100644 --- a/revengai/api/functions_ai_decompilation_api.py +++ b/revengai/api/functions_ai_decompilation_api.py @@ -29,6 +29,7 @@ from revengai.models.regenerate_output_body import RegenerateOutputBody from revengai.models.stream_ai_decompilation200_response_inner import StreamAiDecompilation200ResponseInner from revengai.models.summary_data import SummaryData +from revengai.models.type_suggestions_data import TypeSuggestionsData from revengai.models.upsert_ai_decomplation_rating_request import UpsertAiDecomplationRatingRequest from revengai.models.upsert_overrides_data import UpsertOverridesData from revengai.models.upsert_overrides_input_body import UpsertOverridesInputBody @@ -2865,7 +2866,7 @@ def regenerate_ai_decompilation_inline_comments( ) -> RegenerateOutputBody: """Regenerate AI decompilation inline comments - Starts a new inline comments generation workflow for the function. Requires an existing decompilation with a summary. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found + Starts a new inline comments generation workflow for the function. Requires an existing decompilation with a summary. Rejected while a decompilation is running: its naming and type-suggestion passes are still changing the identifiers the comments would reference. Poll the inline comments status endpoint, which reports PENDING until then. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `400` [`BAD_REQUEST`](/errors/BAD_REQUEST) — Bad Request - `409` [`CONFLICT`](/errors/CONFLICT) — Conflict :param function_id: Function ID (required) :type function_id: int @@ -2901,8 +2902,10 @@ def regenerate_ai_decompilation_inline_comments( _response_types_map: Dict[str, Optional[str]] = { '202': "RegenerateOutputBody", + '400': "APIError", '403': "APIError", '404': "APIError", + '409': "APIError", '422': "APIError", '500': "APIError", } @@ -2936,7 +2939,7 @@ def regenerate_ai_decompilation_inline_comments_with_http_info( ) -> ApiResponse[RegenerateOutputBody]: """Regenerate AI decompilation inline comments - Starts a new inline comments generation workflow for the function. Requires an existing decompilation with a summary. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found + Starts a new inline comments generation workflow for the function. Requires an existing decompilation with a summary. Rejected while a decompilation is running: its naming and type-suggestion passes are still changing the identifiers the comments would reference. Poll the inline comments status endpoint, which reports PENDING until then. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `400` [`BAD_REQUEST`](/errors/BAD_REQUEST) — Bad Request - `409` [`CONFLICT`](/errors/CONFLICT) — Conflict :param function_id: Function ID (required) :type function_id: int @@ -2972,8 +2975,10 @@ def regenerate_ai_decompilation_inline_comments_with_http_info( _response_types_map: Dict[str, Optional[str]] = { '202': "RegenerateOutputBody", + '400': "APIError", '403': "APIError", '404': "APIError", + '409': "APIError", '422': "APIError", '500': "APIError", } @@ -3007,7 +3012,7 @@ def regenerate_ai_decompilation_inline_comments_without_preload_content( ) -> RESTResponseType: """Regenerate AI decompilation inline comments - Starts a new inline comments generation workflow for the function. Requires an existing decompilation with a summary. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found + Starts a new inline comments generation workflow for the function. Requires an existing decompilation with a summary. Rejected while a decompilation is running: its naming and type-suggestion passes are still changing the identifiers the comments would reference. Poll the inline comments status endpoint, which reports PENDING until then. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `400` [`BAD_REQUEST`](/errors/BAD_REQUEST) — Bad Request - `409` [`CONFLICT`](/errors/CONFLICT) — Conflict :param function_id: Function ID (required) :type function_id: int @@ -3043,8 +3048,10 @@ def regenerate_ai_decompilation_inline_comments_without_preload_content( _response_types_map: Dict[str, Optional[str]] = { '202': "RegenerateOutputBody", + '400': "APIError", '403': "APIError", '404': "APIError", + '409': "APIError", '422': "APIError", '500': "APIError", } @@ -3139,7 +3146,7 @@ def regenerate_ai_decompilation_summary( ) -> RegenerateOutputBody: """Regenerate AI decompilation summary - Starts a new summary generation workflow for the function. Requires an existing decompilation. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found + Starts a new summary generation workflow for the function. Requires an existing decompilation. Rejected while a decompilation is running: its naming and type-suggestion passes are still changing the identifiers a summary would describe. Poll the summary status endpoint, which reports PENDING until then. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `409` [`CONFLICT`](/errors/CONFLICT) — Conflict :param function_id: Function ID (required) :type function_id: int @@ -3177,6 +3184,7 @@ def regenerate_ai_decompilation_summary( '202': "RegenerateOutputBody", '403': "APIError", '404': "APIError", + '409': "APIError", '422': "APIError", '500': "APIError", } @@ -3210,7 +3218,7 @@ def regenerate_ai_decompilation_summary_with_http_info( ) -> ApiResponse[RegenerateOutputBody]: """Regenerate AI decompilation summary - Starts a new summary generation workflow for the function. Requires an existing decompilation. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found + Starts a new summary generation workflow for the function. Requires an existing decompilation. Rejected while a decompilation is running: its naming and type-suggestion passes are still changing the identifiers a summary would describe. Poll the summary status endpoint, which reports PENDING until then. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `409` [`CONFLICT`](/errors/CONFLICT) — Conflict :param function_id: Function ID (required) :type function_id: int @@ -3248,6 +3256,7 @@ def regenerate_ai_decompilation_summary_with_http_info( '202': "RegenerateOutputBody", '403': "APIError", '404': "APIError", + '409': "APIError", '422': "APIError", '500': "APIError", } @@ -3281,7 +3290,7 @@ def regenerate_ai_decompilation_summary_without_preload_content( ) -> RESTResponseType: """Regenerate AI decompilation summary - Starts a new summary generation workflow for the function. Requires an existing decompilation. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found + Starts a new summary generation workflow for the function. Requires an existing decompilation. Rejected while a decompilation is running: its naming and type-suggestion passes are still changing the identifiers a summary would describe. Poll the summary status endpoint, which reports PENDING until then. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `409` [`CONFLICT`](/errors/CONFLICT) — Conflict :param function_id: Function ID (required) :type function_id: int @@ -3319,6 +3328,7 @@ def regenerate_ai_decompilation_summary_without_preload_content( '202': "RegenerateOutputBody", '403': "APIError", '404': "APIError", + '409': "APIError", '422': "APIError", '500': "APIError", } @@ -3413,7 +3423,7 @@ def stream_ai_decompilation( ) -> List[StreamAiDecompilation200ResponseInner]: """Stream live AI decompilation output (SSE) - Opens a Server-Sent Events stream of incremental decompilation events for the given function. Each event has a `type` discriminator (also used as the SSE `event:` line) and a per-attempt monotonic `seq`. Terminal events: `decomp_finished` (success) or `decomp_failed` (all retries exhausted). `attempt_failed` is per-attempt and non-terminal — Temporal may retry the activity. Clients should treat `attempt` changes as a reset signal. `last_event_id` is not supported — clients fall back to polling the standard GET endpoint after the stream ends. + Opens a Server-Sent Events stream of incremental decompilation events for the given function. Each event has a `type` discriminator (also used as the SSE `event:` line) and a per-attempt monotonic `seq`. **Terminal events — the stream closes on these:** `names_finished` (success) and `decomp_failed` (all retries exhausted). `names_finished` is published on every success path, including when the naming pass is disabled, produces nothing, or fails, so a successful run always closes. **`decomp_finished` is NOT terminal.** It marks the end of the model call, not the end of the run: entity restore, the result write, the placeholder-naming pass and the type-suggestion pass all follow it, and the last two rewrite the identifiers the source renders with. Reading the decompilation at `decomp_finished` therefore returns names that are about to change — wait for `names_finished`. `attempt_failed` is per-attempt and non-terminal too: Temporal may retry, and clients disambiguate on `attempt`, which they should treat as a reset signal. `last_event_id` is not supported — clients fall back to polling the standard GET endpoint after the stream ends. :param function_id: Function ID (required) :type function_id: int @@ -3480,7 +3490,7 @@ def stream_ai_decompilation_with_http_info( ) -> ApiResponse[List[StreamAiDecompilation200ResponseInner]]: """Stream live AI decompilation output (SSE) - Opens a Server-Sent Events stream of incremental decompilation events for the given function. Each event has a `type` discriminator (also used as the SSE `event:` line) and a per-attempt monotonic `seq`. Terminal events: `decomp_finished` (success) or `decomp_failed` (all retries exhausted). `attempt_failed` is per-attempt and non-terminal — Temporal may retry the activity. Clients should treat `attempt` changes as a reset signal. `last_event_id` is not supported — clients fall back to polling the standard GET endpoint after the stream ends. + Opens a Server-Sent Events stream of incremental decompilation events for the given function. Each event has a `type` discriminator (also used as the SSE `event:` line) and a per-attempt monotonic `seq`. **Terminal events — the stream closes on these:** `names_finished` (success) and `decomp_failed` (all retries exhausted). `names_finished` is published on every success path, including when the naming pass is disabled, produces nothing, or fails, so a successful run always closes. **`decomp_finished` is NOT terminal.** It marks the end of the model call, not the end of the run: entity restore, the result write, the placeholder-naming pass and the type-suggestion pass all follow it, and the last two rewrite the identifiers the source renders with. Reading the decompilation at `decomp_finished` therefore returns names that are about to change — wait for `names_finished`. `attempt_failed` is per-attempt and non-terminal too: Temporal may retry, and clients disambiguate on `attempt`, which they should treat as a reset signal. `last_event_id` is not supported — clients fall back to polling the standard GET endpoint after the stream ends. :param function_id: Function ID (required) :type function_id: int @@ -3547,7 +3557,7 @@ def stream_ai_decompilation_without_preload_content( ) -> RESTResponseType: """Stream live AI decompilation output (SSE) - Opens a Server-Sent Events stream of incremental decompilation events for the given function. Each event has a `type` discriminator (also used as the SSE `event:` line) and a per-attempt monotonic `seq`. Terminal events: `decomp_finished` (success) or `decomp_failed` (all retries exhausted). `attempt_failed` is per-attempt and non-terminal — Temporal may retry the activity. Clients should treat `attempt` changes as a reset signal. `last_event_id` is not supported — clients fall back to polling the standard GET endpoint after the stream ends. + Opens a Server-Sent Events stream of incremental decompilation events for the given function. Each event has a `type` discriminator (also used as the SSE `event:` line) and a per-attempt monotonic `seq`. **Terminal events — the stream closes on these:** `names_finished` (success) and `decomp_failed` (all retries exhausted). `names_finished` is published on every success path, including when the naming pass is disabled, produces nothing, or fails, so a successful run always closes. **`decomp_finished` is NOT terminal.** It marks the end of the model call, not the end of the run: entity restore, the result write, the placeholder-naming pass and the type-suggestion pass all follow it, and the last two rewrite the identifiers the source renders with. Reading the decompilation at `decomp_finished` therefore returns names that are about to change — wait for `names_finished`. `attempt_failed` is per-attempt and non-terminal too: Temporal may retry, and clients disambiguate on `attempt`, which they should treat as a reset signal. `last_event_id` is not supported — clients fall back to polling the standard GET endpoint after the stream ends. :param function_id: Function ID (required) :type function_id: int @@ -4495,6 +4505,280 @@ def _v3_get_ai_decompilation_tokens_serialize( + @validate_call + def v3_get_ai_decompilation_type_suggestions( + self, + function_id: Annotated[int, Field(strict=True, ge=1, description="Function ID")], + _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, + ) -> TypeSuggestionsData: + """Get AI decompilation type suggestions + + Returns the aggregate types the AI decompilation inferred for this function: a suggested name for each type and each of its members, the members' offsets and widths, and the gaps between them. Members revealed only by a caller or callee are included and marked by origin, as are members the model placed rather than observed. Nothing here is a data type row — these are proposals, and creating a row from one is the client's call. The list is empty until a run has produced suggestions, which is ordinary and not an error. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `500` [`INTERNAL_ERROR`](/errors/INTERNAL_ERROR) — Internal Server Error + + :param function_id: Function ID (required) + :type function_id: int + :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._v3_get_ai_decompilation_type_suggestions_serialize( + function_id=function_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypeSuggestionsData", + '403': "APIError", + '404': "APIError", + '422': "APIError", + '500': "APIError", + } + 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 v3_get_ai_decompilation_type_suggestions_with_http_info( + self, + function_id: Annotated[int, Field(strict=True, ge=1, description="Function ID")], + _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[TypeSuggestionsData]: + """Get AI decompilation type suggestions + + Returns the aggregate types the AI decompilation inferred for this function: a suggested name for each type and each of its members, the members' offsets and widths, and the gaps between them. Members revealed only by a caller or callee are included and marked by origin, as are members the model placed rather than observed. Nothing here is a data type row — these are proposals, and creating a row from one is the client's call. The list is empty until a run has produced suggestions, which is ordinary and not an error. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `500` [`INTERNAL_ERROR`](/errors/INTERNAL_ERROR) — Internal Server Error + + :param function_id: Function ID (required) + :type function_id: int + :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._v3_get_ai_decompilation_type_suggestions_serialize( + function_id=function_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypeSuggestionsData", + '403': "APIError", + '404': "APIError", + '422': "APIError", + '500': "APIError", + } + 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 v3_get_ai_decompilation_type_suggestions_without_preload_content( + self, + function_id: Annotated[int, Field(strict=True, ge=1, description="Function ID")], + _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 AI decompilation type suggestions + + Returns the aggregate types the AI decompilation inferred for this function: a suggested name for each type and each of its members, the members' offsets and widths, and the gaps between them. Members revealed only by a caller or callee are included and marked by origin, as are members the model placed rather than observed. Nothing here is a data type row — these are proposals, and creating a row from one is the client's call. The list is empty until a run has produced suggestions, which is ordinary and not an error. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found - `500` [`INTERNAL_ERROR`](/errors/INTERNAL_ERROR) — Internal Server Error + + :param function_id: Function ID (required) + :type function_id: int + :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._v3_get_ai_decompilation_type_suggestions_serialize( + function_id=function_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "TypeSuggestionsData", + '403': "APIError", + '404': "APIError", + '422': "APIError", + '500': "APIError", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _v3_get_ai_decompilation_type_suggestions_serialize( + self, + function_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 function_id is not None: + _path_params['function_id'] = function_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='/v3/functions/{function_id}/ai-decompilation/type-suggestions', + 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 v3_upsert_ai_decompilation_overrides( self, diff --git a/revengai/api/functions_renaming_history_api.py b/revengai/api/functions_renaming_history_api.py index f80a471c..79671652 100644 --- a/revengai/api/functions_renaming_history_api.py +++ b/revengai/api/functions_renaming_history_api.py @@ -1176,7 +1176,7 @@ def rename_function( ) -> RenameOutputBody: """Rename a function - Renames a single function and records the change in history. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found + Renames a single function and records the change in history. `source_type` defaults to USER when omitted. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found :param function_id: Function ID (required) :type function_id: int @@ -1251,7 +1251,7 @@ def rename_function_with_http_info( ) -> ApiResponse[RenameOutputBody]: """Rename a function - Renames a single function and records the change in history. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found + Renames a single function and records the change in history. `source_type` defaults to USER when omitted. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found :param function_id: Function ID (required) :type function_id: int @@ -1326,7 +1326,7 @@ def rename_function_without_preload_content( ) -> RESTResponseType: """Rename a function - Renames a single function and records the change in history. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found + Renames a single function and records the change in history. `source_type` defaults to USER when omitted. **Error codes:** - `403` [`ACCESS_DENIED`](/errors/ACCESS_DENIED) — Access Denied - `404` [`NOT_FOUND`](/errors/NOT_FOUND) — Not Found :param function_id: Function ID (required) :type function_id: int diff --git a/revengai/api_client.py b/revengai/api_client.py index 2d3aea36..6bd4cb74 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.13.0/python' + self.user_agent = 'OpenAPI-Generator/v4.20.0/python' self.client_side_validation = configuration.client_side_validation def __enter__(self): diff --git a/revengai/configuration.py b/revengai/configuration.py index 41fd19f2..f6483978 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.13.0\n"\ - "SDK Package Version: v4.13.0".\ + "Version of the API: v4.20.0\n"\ + "SDK Package Version: v4.20.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 3eaf3ff9..8d091c46 100644 --- a/revengai/models/__init__.py +++ b/revengai/models/__init__.py @@ -221,6 +221,11 @@ from revengai.models.create_unknown_data_type import CreateUnknownDataType from revengai.models.create_user_input_body import CreateUserInputBody from revengai.models.created import Created +from revengai.models.crypto_call import CryptoCall +from revengai.models.crypto_direct_match import CryptoDirectMatch +from revengai.models.crypto_finding import CryptoFinding +from revengai.models.crypto_scan_metadata import CryptoScanMetadata +from revengai.models.crypto_scan_result import CryptoScanResult from revengai.models.data_type_entry import DataTypeEntry from revengai.models.data_type_enum_value_entry import DataTypeEnumValueEntry from revengai.models.data_type_function_entry import DataTypeFunctionEntry @@ -277,6 +282,7 @@ from revengai.models.event_toolcallresult import EventTOOLCALLRESULT from revengai.models.event_toolcallstart import EventTOOLCALLSTART from revengai.models.event_toolconfirmationrequired import EventTOOLCONFIRMATIONREQUIRED +from revengai.models.event_types_suggested import EventTypesSuggested from revengai.models.event_warning import EventWarning from revengai.models.example import Example from revengai.models.export_model import ExportModel @@ -381,6 +387,7 @@ from revengai.models.names_finished_event import NamesFinishedEvent from revengai.models.network_activity import NetworkActivity from revengai.models.oidc_callback_input_body import OIDCCallbackInputBody +from revengai.models.operation_crypto_scan_metadata_crypto_scan_result import OperationCryptoScanMetadataCryptoScanResult from revengai.models.operation_security_scan_metadata_security_scan_result import OperationSecurityScanMetadataSecurityScanResult from revengai.models.operation_workflow_progress_result_body import OperationWorkflowProgressResultBody from revengai.models.order import Order @@ -498,6 +505,9 @@ from revengai.models.struct_data_type import StructDataType from revengai.models.struct_definition import StructDefinition from revengai.models.submit_user_feedback_request import SubmitUserFeedbackRequest +from revengai.models.suggested_hole import SuggestedHole +from revengai.models.suggested_member_view import SuggestedMemberView +from revengai.models.suggested_type_view import SuggestedTypeView from revengai.models.summary_data import SummaryData from revengai.models.symbols import Symbols from revengai.models.tag import Tag @@ -518,12 +528,15 @@ from revengai.models.tokenised_data import TokenisedData from revengai.models.triage_function_response import TriageFunctionResponse from revengai.models.triage_report_response import TriageReportResponse +from revengai.models.trigger_crypto_scan_input_body import TriggerCryptoScanInputBody from revengai.models.trigger_dynamic_execution_input_body import TriggerDynamicExecutionInputBody from revengai.models.trigger_rename_unnamed_functions_input_body import TriggerRenameUnnamedFunctionsInputBody from revengai.models.trigger_security_scan_input_body import TriggerSecurityScanInputBody from revengai.models.ttp import Ttp +from revengai.models.type_suggestions_data import TypeSuggestionsData from revengai.models.typedef_data_type import TypedefDataType from revengai.models.typedef_definition import TypedefDefinition +from revengai.models.types_suggested_event import TypesSuggestedEvent from revengai.models.union_data_type import UnionDataType from revengai.models.union_definition import UnionDefinition from revengai.models.unknown_data_type import UnknownDataType diff --git a/revengai/models/crypto_call.py b/revengai/models/crypto_call.py new file mode 100644 index 00000000..d17c2de9 --- /dev/null +++ b/revengai/models/crypto_call.py @@ -0,0 +1,128 @@ +# 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, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class CryptoCall(BaseModel): + """ + CryptoCall + """ # noqa: E501 + callee_name: StrictStr = Field(description="Name of the called function") + category: StrictStr = Field(description="Crypto category of the match") + how: StrictStr = Field(description="Detection tier that produced the match") + library: StrictStr = Field(description="Crypto library the match belongs to") + matched_name: StrictStr = Field(description="Name or token that matched") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["callee_name", "category", "how", "library", "matched_name"] + + @field_validator('category') + def category_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['symmetric', 'asymmetric', 'hashing', 'mac', 'kdf', 'rng', 'generic', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('symmetric', 'asymmetric', 'hashing', 'mac', 'kdf', 'rng', 'generic', 'unknown_default_open_api')") + return value + + @field_validator('how') + def how_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['library-api', 'cpp-class-token', 'generic-keyword', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('library-api', 'cpp-class-token', 'generic-keyword', 'unknown_default_open_api')") + return value + + @field_validator('library') + def library_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['openssl', 'mbedtls', 'wolfssl', 'libsodium', 'libgcrypt', 'windows_crypto_api', 'cryptopp', 'cpp-crypto', 'generic', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('openssl', 'mbedtls', 'wolfssl', 'libsodium', 'libgcrypt', 'windows_crypto_api', 'cryptopp', 'cpp-crypto', 'generic', '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 CryptoCall 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 + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CryptoCall from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "callee_name": obj.get("callee_name"), + "category": obj.get("category"), + "how": obj.get("how"), + "library": obj.get("library"), + "matched_name": obj.get("matched_name") + }) + # 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/crypto_direct_match.py b/revengai/models/crypto_direct_match.py new file mode 100644 index 00000000..2df10461 --- /dev/null +++ b/revengai/models/crypto_direct_match.py @@ -0,0 +1,126 @@ +# 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, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class CryptoDirectMatch(BaseModel): + """ + CryptoDirectMatch + """ # noqa: E501 + category: StrictStr = Field(description="Crypto category of the match") + how: StrictStr = Field(description="Detection tier that produced the match") + library: StrictStr = Field(description="Crypto library the match belongs to") + matched_name: StrictStr = Field(description="Name or token that matched") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["category", "how", "library", "matched_name"] + + @field_validator('category') + def category_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['symmetric', 'asymmetric', 'hashing', 'mac', 'kdf', 'rng', 'generic', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('symmetric', 'asymmetric', 'hashing', 'mac', 'kdf', 'rng', 'generic', 'unknown_default_open_api')") + return value + + @field_validator('how') + def how_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['library-api', 'cpp-class-token', 'generic-keyword', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('library-api', 'cpp-class-token', 'generic-keyword', 'unknown_default_open_api')") + return value + + @field_validator('library') + def library_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['openssl', 'mbedtls', 'wolfssl', 'libsodium', 'libgcrypt', 'windows_crypto_api', 'cryptopp', 'cpp-crypto', 'generic', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('openssl', 'mbedtls', 'wolfssl', 'libsodium', 'libgcrypt', 'windows_crypto_api', 'cryptopp', 'cpp-crypto', 'generic', '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 CryptoDirectMatch 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 + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CryptoDirectMatch from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "category": obj.get("category"), + "how": obj.get("how"), + "library": obj.get("library"), + "matched_name": obj.get("matched_name") + }) + # 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/crypto_finding.py b/revengai/models/crypto_finding.py new file mode 100644 index 00000000..3d631a75 --- /dev/null +++ b/revengai/models/crypto_finding.py @@ -0,0 +1,182 @@ +# 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 revengai.models.crypto_call import CryptoCall +from revengai.models.crypto_direct_match import CryptoDirectMatch +from typing import Optional, Set +from typing_extensions import Self + +class CryptoFinding(BaseModel): + """ + CryptoFinding + """ # noqa: E501 + address: StrictStr = Field(description="Function's virtual address, hex-encoded") + categories: Optional[List[StrictStr]] = Field(description="Distinct crypto categories evidenced by this function") + confidence: StrictStr = Field(description="High when a direct name match was found, medium when the function only calls into crypto APIs") + crypto_calls: Optional[List[CryptoCall]] = Field(default=None, description="Matches against names this function calls") + direct_matches: Optional[List[CryptoDirectMatch]] = Field(default=None, description="Matches against the function's own name") + evidence_count: StrictInt = Field(description="Total number of direct matches and crypto calls") + function_id: StrictInt = Field(description="ID of the function the finding was reported in") + function_name: StrictStr = Field(description="Name of the function the finding was reported in") + function_size: StrictInt = Field(description="Size of the function in bytes") + libraries: Optional[List[StrictStr]] = Field(description="Distinct crypto libraries evidenced by this function") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["address", "categories", "confidence", "crypto_calls", "direct_matches", "evidence_count", "function_id", "function_name", "function_size", "libraries"] + + @field_validator('categories') + def categories_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + for i in value: + if i not in set(['symmetric', 'asymmetric', 'hashing', 'mac', 'kdf', 'rng', 'generic', 'unknown_default_open_api']): + raise ValueError("each list item must be one of ('symmetric', 'asymmetric', 'hashing', 'mac', 'kdf', 'rng', 'generic', 'unknown_default_open_api')") + return value + + @field_validator('confidence') + def confidence_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['high', 'medium', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('high', 'medium', 'unknown_default_open_api')") + return value + + @field_validator('libraries') + def libraries_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + for i in value: + if i not in set(['openssl', 'mbedtls', 'wolfssl', 'libsodium', 'libgcrypt', 'windows_crypto_api', 'cryptopp', 'cpp-crypto', 'generic', 'unknown_default_open_api']): + raise ValueError("each list item must be one of ('openssl', 'mbedtls', 'wolfssl', 'libsodium', 'libgcrypt', 'windows_crypto_api', 'cryptopp', 'cpp-crypto', 'generic', '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 CryptoFinding 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, + ) + # override the default output from pydantic by calling `to_dict()` of each item in crypto_calls (list) + _items = [] + if self.crypto_calls: + for _item_crypto_calls in self.crypto_calls: + if _item_crypto_calls: + _items.append(_item_crypto_calls.to_dict()) + _dict['crypto_calls'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in direct_matches (list) + _items = [] + if self.direct_matches: + for _item_direct_matches in self.direct_matches: + if _item_direct_matches: + _items.append(_item_direct_matches.to_dict()) + _dict['direct_matches'] = _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 categories (nullable) is None + # and model_fields_set contains the field + if self.categories is None and "categories" in self.model_fields_set: + _dict['categories'] = None + + # set to None if crypto_calls (nullable) is None + # and model_fields_set contains the field + if self.crypto_calls is None and "crypto_calls" in self.model_fields_set: + _dict['crypto_calls'] = None + + # set to None if direct_matches (nullable) is None + # and model_fields_set contains the field + if self.direct_matches is None and "direct_matches" in self.model_fields_set: + _dict['direct_matches'] = None + + # set to None if libraries (nullable) is None + # and model_fields_set contains the field + if self.libraries is None and "libraries" in self.model_fields_set: + _dict['libraries'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CryptoFinding from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "address": obj.get("address"), + "categories": obj.get("categories"), + "confidence": obj.get("confidence"), + "crypto_calls": [CryptoCall.from_dict(_item) for _item in obj["crypto_calls"]] if obj.get("crypto_calls") is not None else None, + "direct_matches": [CryptoDirectMatch.from_dict(_item) for _item in obj["direct_matches"]] if obj.get("direct_matches") is not None else None, + "evidence_count": obj.get("evidence_count"), + "function_id": obj.get("function_id"), + "function_name": obj.get("function_name"), + "function_size": obj.get("function_size"), + "libraries": obj.get("libraries") + }) + # 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/crypto_scan_metadata.py b/revengai/models/crypto_scan_metadata.py new file mode 100644 index 00000000..acb86b67 --- /dev/null +++ b/revengai/models/crypto_scan_metadata.py @@ -0,0 +1,114 @@ +# 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, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self + +class CryptoScanMetadata(BaseModel): + """ + CryptoScanMetadata + """ # noqa: E501 + log_history: Optional[List[Annotated[List[Any], Field(min_length=2, max_length=2)]]] = Field(default=None, description="Progress messages the run recorded, oldest first.") + status: StrictStr = Field(description="Run status. UNINITIALISED means the agent has never been triggered for this analysis.") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["log_history", "status"] + + @field_validator('status') + def status_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['UNINITIALISED', 'PENDING', 'RUNNING', 'COMPLETED', 'FAILED', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('UNINITIALISED', 'PENDING', 'RUNNING', 'COMPLETED', 'FAILED', '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 CryptoScanMetadata 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 log_history (nullable) is None + # and model_fields_set contains the field + if self.log_history is None and "log_history" in self.model_fields_set: + _dict['log_history'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CryptoScanMetadata from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "log_history": obj.get("log_history"), + "status": obj.get("status") + }) + # 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/crypto_scan_result.py b/revengai/models/crypto_scan_result.py new file mode 100644 index 00000000..d44b7d20 --- /dev/null +++ b/revengai/models/crypto_scan_result.py @@ -0,0 +1,116 @@ +# 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 +from typing import Any, ClassVar, Dict, List, Optional +from revengai.models.crypto_finding import CryptoFinding +from typing import Optional, Set +from typing_extensions import Self + +class CryptoScanResult(BaseModel): + """ + CryptoScanResult + """ # noqa: E501 + analysis_id: StrictInt = Field(description="Analysis the run was performed against") + findings: Optional[List[CryptoFinding]] = Field(default=None, description="Functions with crypto-related evidence, sorted by confidence then evidence count") + total_functions: StrictInt = Field(description="Functions the run considered") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["analysis_id", "findings", "total_functions"] + + 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 CryptoScanResult 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, + ) + # override the default output from pydantic by calling `to_dict()` of each item in findings (list) + _items = [] + if self.findings: + for _item_findings in self.findings: + if _item_findings: + _items.append(_item_findings.to_dict()) + _dict['findings'] = _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 findings (nullable) is None + # and model_fields_set contains the field + if self.findings is None and "findings" in self.model_fields_set: + _dict['findings'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CryptoScanResult from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "analysis_id": obj.get("analysis_id"), + "findings": [CryptoFinding.from_dict(_item) for _item in obj["findings"]] if obj.get("findings") is not None else None, + "total_functions": obj.get("total_functions") + }) + # 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/event_types_suggested.py b/revengai/models/event_types_suggested.py new file mode 100644 index 00000000..056e9229 --- /dev/null +++ b/revengai/models/event_types_suggested.py @@ -0,0 +1,103 @@ +# 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 revengai.models.types_suggested_event import TypesSuggestedEvent +from typing import Optional, Set +from typing_extensions import Self + +class EventTypesSuggested(BaseModel): + """ + EventTypesSuggested + """ # noqa: E501 + data: TypesSuggestedEvent + event: StrictStr = Field(description="The event name.") + id: Optional[StrictInt] = Field(default=None, description="The event ID.") + retry: Optional[StrictInt] = Field(default=None, description="The retry time in milliseconds.") + __properties: ClassVar[List[str]] = ["data", "event", "id", "retry"] + + @field_validator('event') + def event_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['types_suggested', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('types_suggested', '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 EventTypesSuggested 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, + ) + # override the default output from pydantic by calling `to_dict()` of data + if self.data: + _dict['data'] = self.data.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of EventTypesSuggested from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "data": TypesSuggestedEvent.from_dict(obj["data"]) if obj.get("data") is not None else None, + "event": obj.get("event"), + "id": obj.get("id"), + "retry": obj.get("retry") + }) + return _obj + + diff --git a/revengai/models/operation_crypto_scan_metadata_crypto_scan_result.py b/revengai/models/operation_crypto_scan_metadata_crypto_scan_result.py new file mode 100644 index 00000000..b9728195 --- /dev/null +++ b/revengai/models/operation_crypto_scan_metadata_crypto_scan_result.py @@ -0,0 +1,119 @@ +# 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, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from revengai.models.crypto_scan_metadata import CryptoScanMetadata +from revengai.models.crypto_scan_result import CryptoScanResult +from revengai.models.status import Status +from typing import Optional, Set +from typing_extensions import Self + +class OperationCryptoScanMetadataCryptoScanResult(BaseModel): + """ + OperationCryptoScanMetadataCryptoScanResult + """ # noqa: E501 + done: StrictBool = Field(description="Whether the operation has reached a terminal state.") + error: Optional[Status] = Field(default=None, description="Failure detail, populated only when done is true and the operation failed.") + metadata: Optional[CryptoScanMetadata] = Field(default=None, description="In-flight information and details.") + name: StrictStr = Field(description="API resource name.") + response: Optional[CryptoScanResult] = Field(default=None, description="Result, set only when done is true and the operation succeeded.") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["done", "error", "metadata", "name", "response"] + + 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 OperationCryptoScanMetadataCryptoScanResult 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, + ) + # override the default output from pydantic by calling `to_dict()` of error + if self.error: + _dict['error'] = self.error.to_dict() + # override the default output from pydantic by calling `to_dict()` of metadata + if self.metadata: + _dict['metadata'] = self.metadata.to_dict() + # override the default output from pydantic by calling `to_dict()` of response + if self.response: + _dict['response'] = self.response.to_dict() + # 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 + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of OperationCryptoScanMetadataCryptoScanResult from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "done": obj.get("done"), + "error": Status.from_dict(obj["error"]) if obj.get("error") is not None else None, + "metadata": CryptoScanMetadata.from_dict(obj["metadata"]) if obj.get("metadata") is not None else None, + "name": obj.get("name"), + "response": CryptoScanResult.from_dict(obj["response"]) if obj.get("response") is not None else None + }) + # 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/rename_input_body.py b/revengai/models/rename_input_body.py index b7e2a69c..7dfdb337 100644 --- a/revengai/models/rename_input_body.py +++ b/revengai/models/rename_input_body.py @@ -16,7 +16,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator from typing import Any, ClassVar, Dict, List, Optional from typing_extensions import Annotated from typing import Optional, Set @@ -28,8 +28,19 @@ class RenameInputBody(BaseModel): """ # noqa: E501 new_mangled_name: Optional[Annotated[str, Field(strict=True, max_length=2048)]] = Field(default=None, description="New mangled function name") new_name: Annotated[str, Field(min_length=1, strict=True, max_length=2048)] = Field(description="New function name") + source_type: Optional[StrictStr] = Field(default=None, description="Source that triggered the rename") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["new_mangled_name", "new_name"] + __properties: ClassVar[List[str]] = ["new_mangled_name", "new_name", "source_type"] + + @field_validator('source_type') + def source_type_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['SYSTEM', 'USER', 'EXTERNAL', 'AUTO_UNSTRIP', 'AI_UNSTRIP', 'AI_AGENT', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('SYSTEM', 'USER', 'EXTERNAL', 'AUTO_UNSTRIP', 'AI_UNSTRIP', 'AI_AGENT', 'unknown_default_open_api')") + return value model_config = ConfigDict( populate_by_name=True, @@ -90,7 +101,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "new_mangled_name": obj.get("new_mangled_name"), - "new_name": obj.get("new_name") + "new_name": obj.get("new_name"), + "source_type": obj.get("source_type") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/revengai/models/resolved_entity.py b/revengai/models/resolved_entity.py index 101f03b3..9091b19f 100644 --- a/revengai/models/resolved_entity.py +++ b/revengai/models/resolved_entity.py @@ -41,6 +41,7 @@ class ResolvedEntity(BaseModel): needs_naming: StrictBool provenance: Optional[StrictStr] resolved_name: Optional[StrictStr] + suggested_name: Optional[StrictStr] = None suggested_type: Optional[StrictStr] suggestion_confidence: Optional[StrictStr] token: Optional[StrictStr] @@ -50,7 +51,7 @@ class ResolvedEntity(BaseModel): value_confidence: Optional[StrictStr] value_type: Optional[StrictStr] additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["addr_token", "all_addr_tokens", "bit_offset", "byte_offset", "byte_size", "count", "data_type_index", "field_status", "function_id", "imported_function_id", "kind", "name", "name_source", "needs_naming", "provenance", "resolved_name", "suggested_type", "suggestion_confidence", "token", "type_index", "vaddr", "value", "value_confidence", "value_type"] + __properties: ClassVar[List[str]] = ["addr_token", "all_addr_tokens", "bit_offset", "byte_offset", "byte_size", "count", "data_type_index", "field_status", "function_id", "imported_function_id", "kind", "name", "name_source", "needs_naming", "provenance", "resolved_name", "suggested_name", "suggested_type", "suggestion_confidence", "token", "type_index", "vaddr", "value", "value_confidence", "value_type"] @field_validator('field_status') def field_status_validate_enum(cls, value): @@ -65,8 +66,8 @@ def field_status_validate_enum(cls, value): @field_validator('name_source') def name_source_validate_enum(cls, value): """Validates the enum""" - if value not in set(['database', 'frozen', 'default', 'unknown_default_open_api']): - raise ValueError("must be one of enum values ('database', 'frozen', 'default', 'unknown_default_open_api')") + if value not in set(['database', 'frozen', 'default', 'suggested', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('database', 'frozen', 'default', 'suggested', 'unknown_default_open_api')") return value model_config = ConfigDict( @@ -165,6 +166,11 @@ def to_dict(self) -> Dict[str, Any]: if self.resolved_name is None and "resolved_name" in self.model_fields_set: _dict['resolved_name'] = None + # set to None if suggested_name (nullable) is None + # and model_fields_set contains the field + if self.suggested_name is None and "suggested_name" in self.model_fields_set: + _dict['suggested_name'] = None + # set to None if suggested_type (nullable) is None # and model_fields_set contains the field if self.suggested_type is None and "suggested_type" in self.model_fields_set: @@ -233,6 +239,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "needs_naming": obj.get("needs_naming"), "provenance": obj.get("provenance"), "resolved_name": obj.get("resolved_name"), + "suggested_name": obj.get("suggested_name"), "suggested_type": obj.get("suggested_type"), "suggestion_confidence": obj.get("suggestion_confidence"), "token": obj.get("token"), diff --git a/revengai/models/stream_ai_decompilation200_response_inner.py b/revengai/models/stream_ai_decompilation200_response_inner.py index 913d466a..4ac47da0 100644 --- a/revengai/models/stream_ai_decompilation200_response_inner.py +++ b/revengai/models/stream_ai_decompilation200_response_inner.py @@ -25,12 +25,13 @@ from revengai.models.event_rename_applied import EventRenameApplied from revengai.models.event_source_delta import EventSourceDelta from revengai.models.event_source_reset import EventSourceReset +from revengai.models.event_types_suggested import EventTypesSuggested from revengai.models.event_warning import EventWarning from pydantic import StrictStr, Field from typing import Union, List, Set, Optional, Dict from typing_extensions import Literal, Self -STREAMAIDECOMPILATION200RESPONSEINNER_ONE_OF_SCHEMAS = ["EventAttemptFailed", "EventAttemptStarted", "EventDecompFailed", "EventDecompFinished", "EventNamesFinished", "EventProse", "EventRenameApplied", "EventSourceDelta", "EventSourceReset", "EventWarning"] +STREAMAIDECOMPILATION200RESPONSEINNER_ONE_OF_SCHEMAS = ["EventAttemptFailed", "EventAttemptStarted", "EventDecompFailed", "EventDecompFinished", "EventNamesFinished", "EventProse", "EventRenameApplied", "EventSourceDelta", "EventSourceReset", "EventTypesSuggested", "EventWarning"] class StreamAiDecompilation200ResponseInner(BaseModel): """ @@ -54,10 +55,12 @@ class StreamAiDecompilation200ResponseInner(BaseModel): oneof_schema_8_validator: Optional[EventSourceDelta] = None # data type: EventSourceReset oneof_schema_9_validator: Optional[EventSourceReset] = None + # data type: EventTypesSuggested + oneof_schema_10_validator: Optional[EventTypesSuggested] = None # data type: EventWarning - oneof_schema_10_validator: Optional[EventWarning] = None - actual_instance: Optional[Union[EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventWarning]] = None - one_of_schemas: Set[str] = { "EventAttemptFailed", "EventAttemptStarted", "EventDecompFailed", "EventDecompFinished", "EventNamesFinished", "EventProse", "EventRenameApplied", "EventSourceDelta", "EventSourceReset", "EventWarning" } + oneof_schema_11_validator: Optional[EventWarning] = None + actual_instance: Optional[Union[EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventTypesSuggested, EventWarning]] = None + one_of_schemas: Set[str] = { "EventAttemptFailed", "EventAttemptStarted", "EventDecompFailed", "EventDecompFinished", "EventNamesFinished", "EventProse", "EventRenameApplied", "EventSourceDelta", "EventSourceReset", "EventTypesSuggested", "EventWarning" } model_config = ConfigDict( validate_assignment=True, @@ -125,6 +128,11 @@ def actual_instance_must_validate_oneof(cls, v): error_messages.append(f"Error! Input type `{type(v)}` is not `EventSourceReset`") else: match += 1 + # validate data type: EventTypesSuggested + if not isinstance(v, EventTypesSuggested): + error_messages.append(f"Error! Input type `{type(v)}` is not `EventTypesSuggested`") + else: + match += 1 # validate data type: EventWarning if not isinstance(v, EventWarning): error_messages.append(f"Error! Input type `{type(v)}` is not `EventWarning`") @@ -132,10 +140,10 @@ def actual_instance_must_validate_oneof(cls, v): match += 1 if match > 1: # more than 1 match - raise ValueError("Multiple matches found when setting `actual_instance` in StreamAiDecompilation200ResponseInner with oneOf schemas: EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventWarning. Details: " + ", ".join(error_messages)) + raise ValueError("Multiple matches found when setting `actual_instance` in StreamAiDecompilation200ResponseInner with oneOf schemas: EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventTypesSuggested, EventWarning. Details: " + ", ".join(error_messages)) elif match == 0: # no match - raise ValueError("No match found when setting `actual_instance` in StreamAiDecompilation200ResponseInner with oneOf schemas: EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventWarning. Details: " + ", ".join(error_messages)) + raise ValueError("No match found when setting `actual_instance` in StreamAiDecompilation200ResponseInner with oneOf schemas: EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventTypesSuggested, EventWarning. Details: " + ", ".join(error_messages)) else: return v @@ -204,6 +212,12 @@ def from_json(cls, json_str: str) -> Self: match += 1 except (ValidationError, ValueError) as e: error_messages.append(str(e)) + # deserialize data into EventTypesSuggested + try: + instance.actual_instance = EventTypesSuggested.from_json(json_str) + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) # deserialize data into EventWarning try: instance.actual_instance = EventWarning.from_json(json_str) @@ -213,10 +227,10 @@ def from_json(cls, json_str: str) -> Self: if match > 1: # more than 1 match - raise ValueError("Multiple matches found when deserializing the JSON string into StreamAiDecompilation200ResponseInner with oneOf schemas: EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventWarning. Details: " + ", ".join(error_messages)) + raise ValueError("Multiple matches found when deserializing the JSON string into StreamAiDecompilation200ResponseInner with oneOf schemas: EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventTypesSuggested, EventWarning. Details: " + ", ".join(error_messages)) elif match == 0: # no match - raise ValueError("No match found when deserializing the JSON string into StreamAiDecompilation200ResponseInner with oneOf schemas: EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventWarning. Details: " + ", ".join(error_messages)) + raise ValueError("No match found when deserializing the JSON string into StreamAiDecompilation200ResponseInner with oneOf schemas: EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventTypesSuggested, EventWarning. Details: " + ", ".join(error_messages)) else: return instance @@ -230,7 +244,7 @@ def to_json(self) -> str: else: return json.dumps(self.actual_instance) - def to_dict(self) -> Optional[Union[Dict[str, Any], EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventWarning]]: + def to_dict(self) -> Optional[Union[Dict[str, Any], EventAttemptFailed, EventAttemptStarted, EventDecompFailed, EventDecompFinished, EventNamesFinished, EventProse, EventRenameApplied, EventSourceDelta, EventSourceReset, EventTypesSuggested, EventWarning]]: """Returns the dict representation of the actual instance""" if self.actual_instance is None: return None diff --git a/revengai/models/suggested_hole.py b/revengai/models/suggested_hole.py new file mode 100644 index 00000000..3bde18cc --- /dev/null +++ b/revengai/models/suggested_hole.py @@ -0,0 +1,101 @@ +# 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, StrictInt +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class SuggestedHole(BaseModel): + """ + SuggestedHole + """ # noqa: E501 + byte_offset: StrictInt + byte_size: StrictInt + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["byte_offset", "byte_size"] + + 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 SuggestedHole 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 + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SuggestedHole from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "byte_offset": obj.get("byte_offset"), + "byte_size": obj.get("byte_size") + }) + # 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/suggested_member_view.py b/revengai/models/suggested_member_view.py new file mode 100644 index 00000000..7403a28e --- /dev/null +++ b/revengai/models/suggested_member_view.py @@ -0,0 +1,159 @@ +# 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, StrictBool, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class SuggestedMemberView(BaseModel): + """ + SuggestedMemberView + """ # noqa: E501 + bit_offset: Optional[StrictInt] = Field(description="Bit offset within the containing word for a bitfield member.") + byte_offset: Optional[StrictInt] = Field(description="Offset within the type. Null when no placement could be established.") + byte_size: Optional[StrictInt] = Field(description="Width of the access in bytes.") + confidence: Optional[StrictStr] = Field(description="Where suggested_type came from. declared and inferred were observed; width knows only the access width; model is the language model's proposal.") + name: StrictStr = Field(description="Name the member renders as: a database or frozen name where one exists, else the suggested one.") + origin: StrictStr = Field(description="Which function revealed this member: self, caller: or callee:.") + packed: StrictBool = Field(description="The member sits at an offset its own width does not divide.") + placement: StrictStr = Field(description="observed means the offset was read off an access; guessed means the model proposed it; unplaced means the member has no offset.") + suggested_type: Optional[StrictStr] = Field(description="Type expression for the member.") + token: Optional[StrictStr] = Field(default=None, description="Placeholder this member renders as in the tokenised source. Absent for a member no access in this function revealed.") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["bit_offset", "byte_offset", "byte_size", "confidence", "name", "origin", "packed", "placement", "suggested_type", "token"] + + @field_validator('confidence') + def confidence_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['declared', 'inferred', 'width', 'model', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('declared', 'inferred', 'width', 'model', 'unknown_default_open_api')") + return value + + @field_validator('placement') + def placement_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['observed', 'guessed', 'unplaced', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('observed', 'guessed', 'unplaced', '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 SuggestedMemberView 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 bit_offset (nullable) is None + # and model_fields_set contains the field + if self.bit_offset is None and "bit_offset" in self.model_fields_set: + _dict['bit_offset'] = None + + # set to None if byte_offset (nullable) is None + # and model_fields_set contains the field + if self.byte_offset is None and "byte_offset" in self.model_fields_set: + _dict['byte_offset'] = None + + # set to None if byte_size (nullable) is None + # and model_fields_set contains the field + if self.byte_size is None and "byte_size" in self.model_fields_set: + _dict['byte_size'] = None + + # set to None if confidence (nullable) is None + # and model_fields_set contains the field + if self.confidence is None and "confidence" in self.model_fields_set: + _dict['confidence'] = None + + # set to None if suggested_type (nullable) is None + # and model_fields_set contains the field + if self.suggested_type is None and "suggested_type" in self.model_fields_set: + _dict['suggested_type'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SuggestedMemberView from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "bit_offset": obj.get("bit_offset"), + "byte_offset": obj.get("byte_offset"), + "byte_size": obj.get("byte_size"), + "confidence": obj.get("confidence"), + "name": obj.get("name"), + "origin": obj.get("origin"), + "packed": obj.get("packed"), + "placement": obj.get("placement"), + "suggested_type": obj.get("suggested_type"), + "token": obj.get("token") + }) + # 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/suggested_type_view.py b/revengai/models/suggested_type_view.py new file mode 100644 index 00000000..9d5be66e --- /dev/null +++ b/revengai/models/suggested_type_view.py @@ -0,0 +1,139 @@ +# 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 +from typing import Any, ClassVar, Dict, List, Optional +from revengai.models.suggested_hole import SuggestedHole +from revengai.models.suggested_member_view import SuggestedMemberView +from typing import Optional, Set +from typing_extensions import Self + +class SuggestedTypeView(BaseModel): + """ + SuggestedTypeView + """ # noqa: E501 + data_type_id: Optional[StrictInt] = Field(default=None, description="Existing data type the members were accessed through. Null when nothing resolved to a row; never minted for a suggestion.") + holes: Optional[List[SuggestedHole]] = Field(description="Gaps between consecutive placed members, in offset order.") + implied_size: Optional[StrictInt] = Field(default=None, description="Highest byte_offset+byte_size across the members. A lower bound on the type's size, not its size.") + key: StrictStr = Field(description="Identity of the suggestion: index: where the access named a row, else token:.") + members: Optional[List[SuggestedMemberView]] = Field(description="Members in offset order, unplaced ones last.") + name: StrictStr = Field(description="Name the type renders as: a database or frozen name where one exists, else the suggested one.") + type_token: Optional[StrictStr] = Field(default=None, description="Placeholder the type renders as, when it appears in this function's source.") + underlying_type: Optional[StrictStr] = Field(default=None, description="Set only for a type with no observed members, where the suggestion is a name and a scalar type rather than a layout.") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["data_type_id", "holes", "implied_size", "key", "members", "name", "type_token", "underlying_type"] + + 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 SuggestedTypeView 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, + ) + # override the default output from pydantic by calling `to_dict()` of each item in holes (list) + _items = [] + if self.holes: + for _item_holes in self.holes: + if _item_holes: + _items.append(_item_holes.to_dict()) + _dict['holes'] = _items + # override the default output from pydantic by calling `to_dict()` of each item in members (list) + _items = [] + if self.members: + for _item_members in self.members: + if _item_members: + _items.append(_item_members.to_dict()) + _dict['members'] = _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 holes (nullable) is None + # and model_fields_set contains the field + if self.holes is None and "holes" in self.model_fields_set: + _dict['holes'] = None + + # set to None if members (nullable) is None + # and model_fields_set contains the field + if self.members is None and "members" in self.model_fields_set: + _dict['members'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of SuggestedTypeView from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "data_type_id": obj.get("data_type_id"), + "holes": [SuggestedHole.from_dict(_item) for _item in obj["holes"]] if obj.get("holes") is not None else None, + "implied_size": obj.get("implied_size"), + "key": obj.get("key"), + "members": [SuggestedMemberView.from_dict(_item) for _item in obj["members"]] if obj.get("members") is not None else None, + "name": obj.get("name"), + "type_token": obj.get("type_token"), + "underlying_type": obj.get("underlying_type") + }) + # 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/trigger_crypto_scan_input_body.py b/revengai/models/trigger_crypto_scan_input_body.py new file mode 100644 index 00000000..9d25e68f --- /dev/null +++ b/revengai/models/trigger_crypto_scan_input_body.py @@ -0,0 +1,135 @@ +# 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, StrictBool, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class TriggerCryptoScanInputBody(BaseModel): + """ + TriggerCryptoScanInputBody + """ # noqa: E501 + categories: Optional[List[StrictStr]] = Field(default=None, description="Restrict findings to these categories. Omit to scan every category.") + direct_only: Optional[StrictBool] = Field(default=None, description="Only report functions whose own name matches a known crypto API; skips the calls-into-crypto pass, avoiding a bulk call-graph fetch.") + libraries: Optional[List[StrictStr]] = Field(default=None, description="Restrict findings to these libraries. Omit to scan every library.") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["categories", "direct_only", "libraries"] + + @field_validator('categories') + def categories_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + for i in value: + if i not in set(['symmetric', 'asymmetric', 'hashing', 'mac', 'kdf', 'rng', 'generic', 'unknown_default_open_api']): + raise ValueError("each list item must be one of ('symmetric', 'asymmetric', 'hashing', 'mac', 'kdf', 'rng', 'generic', 'unknown_default_open_api')") + return value + + @field_validator('libraries') + def libraries_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + for i in value: + if i not in set(['openssl', 'mbedtls', 'wolfssl', 'libsodium', 'libgcrypt', 'windows_crypto_api', 'cryptopp', 'cpp-crypto', 'generic', 'unknown_default_open_api']): + raise ValueError("each list item must be one of ('openssl', 'mbedtls', 'wolfssl', 'libsodium', 'libgcrypt', 'windows_crypto_api', 'cryptopp', 'cpp-crypto', 'generic', '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 TriggerCryptoScanInputBody 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 categories (nullable) is None + # and model_fields_set contains the field + if self.categories is None and "categories" in self.model_fields_set: + _dict['categories'] = None + + # set to None if libraries (nullable) is None + # and model_fields_set contains the field + if self.libraries is None and "libraries" in self.model_fields_set: + _dict['libraries'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TriggerCryptoScanInputBody from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "categories": obj.get("categories"), + "direct_only": obj.get("direct_only"), + "libraries": obj.get("libraries") + }) + # 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/type_suggestions_data.py b/revengai/models/type_suggestions_data.py new file mode 100644 index 00000000..c85ca44f --- /dev/null +++ b/revengai/models/type_suggestions_data.py @@ -0,0 +1,123 @@ +# 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, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from revengai.models.suggested_type_view import SuggestedTypeView +from typing import Optional, Set +from typing_extensions import Self + +class TypeSuggestionsData(BaseModel): + """ + TypeSuggestionsData + """ # noqa: E501 + model: Optional[StrictStr] = Field(default=None, description="Language model that produced the suggestions.") + status: StrictStr = Field(description="Status of the AI decompilation run that would have produced these suggestions.") + types: Optional[List[SuggestedTypeView]] = Field(description="One entry per suggested type. Empty for a run that produced none, and for a run that predates type suggestion — the two are not distinguished.") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["model", "status", "types"] + + @field_validator('status') + def status_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['UNINITIALISED', 'PENDING', 'RUNNING', 'COMPLETED', 'FAILED', 'unknown_default_open_api']): + raise ValueError("must be one of enum values ('UNINITIALISED', 'PENDING', 'RUNNING', 'COMPLETED', 'FAILED', '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 TypeSuggestionsData 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, + ) + # override the default output from pydantic by calling `to_dict()` of each item in types (list) + _items = [] + if self.types: + for _item_types in self.types: + if _item_types: + _items.append(_item_types.to_dict()) + _dict['types'] = _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 types (nullable) is None + # and model_fields_set contains the field + if self.types is None and "types" in self.model_fields_set: + _dict['types'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TypeSuggestionsData from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "model": obj.get("model"), + "status": obj.get("status"), + "types": [SuggestedTypeView.from_dict(_item) for _item in obj["types"]] if obj.get("types") is not None else None + }) + # 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/types_suggested_event.py b/revengai/models/types_suggested_event.py new file mode 100644 index 00000000..826a1d58 --- /dev/null +++ b/revengai/models/types_suggested_event.py @@ -0,0 +1,107 @@ +# 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, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class TypesSuggestedEvent(BaseModel): + """ + TypesSuggestedEvent + """ # noqa: E501 + attempt: StrictInt + members: StrictInt + seq: StrictInt + type: StrictStr + types: StrictInt + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["attempt", "members", "seq", "type", "types"] + + 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 TypesSuggestedEvent 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 + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of TypesSuggestedEvent from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "attempt": obj.get("attempt"), + "members": obj.get("members"), + "seq": obj.get("seq"), + "type": obj.get("type"), + "types": obj.get("types") + }) + # 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 + +