Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions vertexai/src/GenerativeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,12 @@ private string GetURL() {

private async Task SetRequestHeaders(HttpRequestMessage request) {
request.Headers.Add("x-goog-api-key", _firebaseApp.Options.ApiKey);
// TODO: Get the Version from the Firebase.VersionInfo.SdkVersion (requires exposing it via App)
request.Headers.Add("x-goog-api-client", "genai-csharp/0.1.0");
string version = FirebaseInterops.GetVersionInfoSdkVersion();
request.Headers.Add("x-goog-api-client", $"genai-csharp/{version}");
if (FirebaseInterops.GetIsDataCollectionDefaultEnabled(_firebaseApp)) {
request.Headers.Add("X-Firebase-AppId", _firebaseApp.Options.AppId);
request.Headers.Add("X-Firebase-AppVersion", UnityEngine.Application.version);
}
// Add additional Firebase tokens to the header.
await FirebaseInterops.AddFirebaseTokensAsync(request, _firebaseApp);
}
Expand Down
70 changes: 69 additions & 1 deletion vertexai/src/Internal/FirebaseInterops.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ namespace Firebase.VertexAI.Internal {

// Contains internal helper methods for interacting with other Firebase libraries.
internal static class FirebaseInterops {
// The cached fields for FirebaseApp reflection.
private static PropertyInfo _dataCollectionProperty = null;

// The various App Check types needed to retrieve the token, cached via reflection on startup.
private static Type _appCheckType;
Expand All @@ -48,6 +50,7 @@ internal static class FirebaseInterops {
private const string authHeader = "Authorization";

static FirebaseInterops() {
InitializeAppReflection();
InitializeAppCheckReflection();
InitializeAuthReflection();
}
Expand All @@ -58,6 +61,72 @@ private static void LogError(string message) {
#endif
}

// Cache the methods needed for FirebaseApp reflection.
private static void InitializeAppReflection() {
try {
_dataCollectionProperty = typeof(FirebaseApp).GetProperty(
"IsDataCollectionDefaultEnabled",
BindingFlags.Instance | BindingFlags.NonPublic);
if (_dataCollectionProperty == null) {
LogError("Could not find FirebaseApp.IsDataCollectionDefaultEnabled property via reflection.");
return;
}
if (_dataCollectionProperty.PropertyType != typeof(bool)) {
LogError("FirebaseApp.IsDataCollectionDefaultEnabled is not a bool, " +
$"but is {_dataCollectionProperty.PropertyType}");
return;
}
} catch (Exception e) {
LogError($"Failed to initialize FirebaseApp reflection: {e}");
}
}

// Gets the property FirebaseApp.IsDataCollectionDefaultEnabled.
public static bool GetIsDataCollectionDefaultEnabled(FirebaseApp firebaseApp) {
if (firebaseApp == null || _dataCollectionProperty == null) {
return false;
}

try {
return (bool)_dataCollectionProperty.GetValue(firebaseApp);
} catch (Exception e) {
LogError($"Error accessing 'IsDataCollectionDefaultEnabled': {e}");
return false;
}
}

// SDK version to use if unable to find it.
private const string _unknownSdkVersion = "unknown";
private static readonly Lazy<string> _sdkVersionFetcher = new(() => {
try {
// Get the type Firebase.VersionInfo from the assembly that defines FirebaseApp.
Type versionInfoType = typeof(FirebaseApp).Assembly.GetType("Firebase.VersionInfo");
if (versionInfoType == null) {
LogError("Firebase.VersionInfo type not found via reflection");
return _unknownSdkVersion;
}

// Firebase.VersionInfo.SdkVersion
PropertyInfo sdkVersionProperty = versionInfoType.GetProperty(
"SdkVersion",
BindingFlags.Static | BindingFlags.NonPublic);
if (sdkVersionProperty == null) {
LogError("Firebase.VersionInfo.SdkVersion property not found via reflection.");
return _unknownSdkVersion;
}

return sdkVersionProperty.GetValue(null) as string ?? _unknownSdkVersion;
} catch (Exception e) {
LogError($"Error accessing SdkVersion via reflection: {e}");
return _unknownSdkVersion;
}
});

// Gets the internal property Firebase.VersionInfo.SdkVersion
internal static string GetVersionInfoSdkVersion() {
return _sdkVersionFetcher.Value;
}

// Cache the various types and methods needed for AppCheck token retrieval.
private static void InitializeAppCheckReflection() {
const string firebaseAppCheckTypeName = "Firebase.AppCheck.FirebaseAppCheck, Firebase.AppCheck";
Expand Down Expand Up @@ -301,7 +370,6 @@ internal static async Task AddFirebaseTokensAsync(ClientWebSocket socket, Fireba
socket.Options.SetRequestHeader(authHeader, $"Firebase {authToken}");
}
}

}

}
8 changes: 6 additions & 2 deletions vertexai/src/LiveGenerativeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,12 @@ public async Task<LiveSession> ConnectAsync(CancellationToken cancellationToken
string endpoint = GetURL();

// Set initial headers
// TODO: Get the Version from the Firebase.VersionInfo.SdkVersion (requires exposing it via App)
clientWebSocket.Options.SetRequestHeader("x-goog-api-client", "genai-csharp/0.1.0");
string version = FirebaseInterops.GetVersionInfoSdkVersion();
clientWebSocket.Options.SetRequestHeader("x-goog-api-client", $"genai-csharp/{version}");
if (FirebaseInterops.GetIsDataCollectionDefaultEnabled(_firebaseApp)) {
clientWebSocket.Options.SetRequestHeader("X-Firebase-AppId", _firebaseApp.Options.AppId);
clientWebSocket.Options.SetRequestHeader("X-Firebase-AppVersion", UnityEngine.Application.version);
}
// Add additional Firebase tokens to the header.
await FirebaseInterops.AddFirebaseTokensAsync(clientWebSocket, _firebaseApp);

Expand Down