#!/usr/bin/env python3 """Download raw config and analyze binary structure around action mappings""" import sys sys.path.insert(0, r'C:\DEV\COPILOT\geutebruck-api\src\api') import grpc import struct from protos import configuration_pb2 from protos import configuration_pb2_grpc def analyze_raw_config(): """Download raw config via gRPC and save for analysis""" print("Connecting to SDK Bridge...") with grpc.insecure_channel('localhost:50051') as channel: stub = configuration_pb2_grpc.ConfigurationServiceStub(channel) # First get action mappings to find offsets print("Getting action mapping offsets...") mappings_request = configuration_pb2.ReadActionMappingsRequest() mappings_response = stub.ReadActionMappings(mappings_request) if not mappings_response.success: print("Failed to get action mappings") return False print(f"Got {mappings_response.total_count} action mappings") print(f"\nFirst 3 mappings:") for i, mapping in enumerate(mappings_response.mappings[:3]): print(f" [{i}] offset {mapping.start_offset}-{mapping.end_offset}, actions: {len(mapping.actions)}") for j, action in enumerate(mapping.actions): print(f" Action {j}: {action}") # Now export full config as JSON which includes all nodes print("\nExporting full configuration...") export_request = configuration_pb2.ExportJsonRequest() export_response = stub.ExportConfigurationJson(export_request) if not export_response.success: print(f"Export failed: {export_response.error_message}") return False print(f"Exported {export_response.json_size} bytes of JSON") # Save to file with open("full_config_export.json", "w", encoding="utf-8") as f: f.write(export_response.json_data) print("Saved to full_config_export.json") # Parse JSON to examine nodes around first action mapping import json config = json.loads(export_response.json_data) print(f"\nTotal nodes in config: {len(config['rootNodes'])}") # Find "ules" markers ules_markers = [i for i, node in enumerate(config['rootNodes']) if node['nodeType'] == 'marker' and 'ules' in (node.get('name') or '')] print(f"Found {len(ules_markers)} ules markers in exported JSON") if ules_markers: # Examine first marker marker_idx = ules_markers[0] marker = config['rootNodes'][marker_idx] print(f"\nFirst ules marker at index {marker_idx}, offset {marker['startOffset']}:") print(f" Name length: {len(marker.get('name', ''))}") print(f" Name (first 200 chars): {marker.get('name', '')[:200]}") print(f" Value type: {marker.get('valueType', '')}") print(f" Value: {str(marker.get('value', ''))[:200]}") # Show surrounding nodes print(f"\n Nodes around this marker (10 before, 30 after):") start_idx = max(0, marker_idx - 10) end_idx = min(len(config['rootNodes']), marker_idx + 30) for i in range(start_idx, end_idx): node = config['rootNodes'][i] prefix = ">>>" if i == marker_idx else " " name = (node.get('name', '') or '')[:40] value = str(node.get('value', ''))[:60] print(f"{prefix} [{i:4d}] offset={node['startOffset']:6d}, type={node['nodeType']:8s}, name={name!r}, value={value!r}") return True if __name__ == '__main__': analyze_raw_config()