bleam 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/ai.cjs +1872 -1182
  2. package/dist/ai.d.cts +267 -234
  3. package/dist/ai.d.ts +267 -234
  4. package/dist/ai.js +1859 -1167
  5. package/dist/cli.cjs +3 -183
  6. package/dist/cli.d.cts +3 -47
  7. package/dist/cli.d.ts +3 -47
  8. package/dist/cli.js +3 -183
  9. package/dist/config.d.cts +1 -1
  10. package/dist/config.d.ts +1 -1
  11. package/dist/{files-Ds1wT8C2.js → files-BXVkPrPN.js} +6 -1
  12. package/dist/{files-Bo7h9fik.cjs → files-DxaQ-Nv0.cjs} +11 -0
  13. package/dist/files.cjs +1 -1
  14. package/dist/files.js +1 -1
  15. package/dist/index.d.cts +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/platform.cjs +1 -13
  18. package/dist/platform.d.cts +1 -28
  19. package/dist/platform.d.ts +1 -28
  20. package/dist/platform.js +1 -10
  21. package/dist/schema-B5BfdswF.js +226 -0
  22. package/dist/schema-BnVZOXfu.cjs +286 -0
  23. package/dist/schema-D5eImHxu.d.cts +125 -0
  24. package/dist/schema-SSjokbtw.d.ts +125 -0
  25. package/dist/schema.cjs +10 -2
  26. package/dist/schema.d.cts +2 -2
  27. package/dist/schema.d.ts +2 -2
  28. package/dist/schema.js +2 -2
  29. package/dist/state-Dh3HLixb.js +874 -0
  30. package/dist/state-LssDgpff.cjs +973 -0
  31. package/dist/state.cjs +16 -12
  32. package/dist/state.d.cts +144 -140
  33. package/dist/state.d.ts +145 -140
  34. package/dist/state.js +3 -3
  35. package/dist/{ui-Bg11tvlc.d.ts → ui-1WepaMS4.d.cts} +1 -1
  36. package/dist/{ui-Dd7SXdbg.d.cts → ui-D7bRLYee.d.ts} +7 -7
  37. package/dist/ui.d.cts +1 -1
  38. package/dist/ui.d.ts +1 -1
  39. package/dist/window.d.cts +1 -1
  40. package/dist/window.d.ts +1 -1
  41. package/package.json +3 -1
  42. package/templates/foundation-models/app/index.tsx +77 -15
  43. package/templates/image-generation/app/index.tsx +4 -2
  44. package/templates/native/ios/Bleam/AI/Flux2/Configuration/ModelRegistry.swift +1 -1
  45. package/templates/native/ios/Bleam/AI/Flux2/Pipeline/FluxImageRunner.swift +7 -2
  46. package/templates/native/ios/Bleam/AI/TextGeneration/Bonsai/BonsaiTextGenerator.swift +46 -0
  47. package/templates/native/ios/Bleam/AI/TextGeneration/Bonsai/BonsaiTextModel.swift +107 -0
  48. package/templates/native/ios/Bleam/AI/TextGeneration/Bonsai/BonsaiTextSnapshotValidator.swift +201 -0
  49. package/templates/native/ios/Bleam/AI/TextGeneration/Core/GenerationTypes.swift +85 -0
  50. package/templates/native/ios/Bleam/AI/TextGeneration/Core/ModelCapabilities.swift +21 -0
  51. package/templates/native/ios/Bleam/AI/TextGeneration/Core/TextKVCache.swift +23 -0
  52. package/templates/native/ios/Bleam/AI/TextGeneration/Core/TokenSampler.swift +79 -0
  53. package/templates/native/ios/Bleam/AI/TextGeneration/Qwen3/Qwen3CheckpointLoader.swift +161 -0
  54. package/templates/native/ios/Bleam/AI/TextGeneration/Qwen3/Qwen3Configuration.swift +119 -0
  55. package/templates/native/ios/Bleam/AI/TextGeneration/Qwen3/Qwen3InferenceSession.swift +84 -0
  56. package/templates/native/ios/Bleam/AI/TextGeneration/Qwen3/Qwen3Layers.swift +197 -0
  57. package/templates/native/ios/Bleam/AI/TextGeneration/Qwen3/Qwen3Model.swift +130 -0
  58. package/templates/native/ios/Bleam/AI/TextGeneration/Qwen35/Qwen35Checkpoint.swift +102 -0
  59. package/templates/native/ios/Bleam/AI/TextGeneration/Qwen35/Qwen35Configuration.swift +140 -0
  60. package/templates/native/ios/Bleam/AI/TextGeneration/Qwen35/Qwen35Model.swift +112 -0
  61. package/templates/native/ios/Bleam/AI/TextGeneration/Qwen35/Qwen35Session.swift +121 -0
  62. package/templates/native/ios/Bleam/AI/TextGeneration/QwenHybrid/QwenHybridCache.swift +42 -0
  63. package/templates/native/ios/Bleam/AI/TextGeneration/QwenHybrid/QwenHybridFullAttention.swift +57 -0
  64. package/templates/native/ios/Bleam/AI/TextGeneration/QwenHybrid/QwenHybridLayers.swift +58 -0
  65. package/templates/native/ios/Bleam/AI/TextGeneration/QwenHybrid/QwenHybridLinearAttention.swift +111 -0
  66. package/templates/native/ios/Bleam/AppDelegate.swift +0 -206
  67. package/templates/native/ios/Bleam.xcodeproj/project.pbxproj +135 -129
  68. package/templates/native/ios/GenerationService/BonsaiTextGenerationRunner.swift +103 -0
  69. package/templates/native/ios/GenerationService/ImageGenerationRunner.swift +19 -7
  70. package/templates/native/ios/GenerationService/main.swift +174 -48
  71. package/templates/native/ios/Podfile.lock +173 -173
  72. package/templates/native/ios/Shared/Generation/GenerationServiceProtocol.swift +3 -0
  73. package/templates/native/ios/Shared/Generation/GenerationWorkerProtocol.swift +44 -0
  74. package/templates/native/modules/bleam-runtime/ios/AIModule.swift +239 -341
  75. package/templates/native/modules/bleam-runtime/ios/GenerationContracts.swift +47 -0
  76. package/templates/native/modules/bleam-runtime/ios/PlatformModule.swift +0 -191
  77. package/templates/text-generation/app/index.tsx +124 -0
  78. package/templates/text-generation/app.config.ts +5 -0
  79. package/templates/updates/README.md +43 -199
  80. package/templates/updates/src/index.ts +5 -98
  81. package/templates/updates/src/schema.ts +18 -173
  82. package/dist/schema-Bo5Jvqus.js +0 -90
  83. package/dist/schema-DOOjfXvs.d.ts +0 -58
  84. package/dist/schema-ENSMX_1t.d.cts +0 -58
  85. package/dist/schema-rQ13mrpD.cjs +0 -102
  86. package/dist/state-Bx0VlTlO.cjs +0 -852
  87. package/dist/state-CAwe-Vw1.js +0 -767
  88. package/templates/native/ios/PlatformHelper/main.swift +0 -726
  89. /package/dist/{config-Cms0rvqg.d.ts → config-COcRnn5a.d.cts} +0 -0
  90. /package/dist/{config-CufOVJV3.d.cts → config-Chi-flpJ.d.ts} +0 -0
@@ -0,0 +1,111 @@
1
+ import Foundation
2
+ import MLX
3
+ import MLXNN
4
+
5
+ public final class QwenHybridLinearAttention: Module, @unchecked Sendable {
6
+ private let numValueHeads: Int
7
+ private let numKeyHeads: Int
8
+ private let keyHeadDim: Int
9
+ private let valueHeadDim: Int
10
+ private let keyDimension: Int
11
+ private let valueDimension: Int
12
+ private let convolutionDimension: Int
13
+ private let kernelSize: Int
14
+ private let keyNormWeight: MLXArray
15
+
16
+ @ModuleInfo public var in_proj_qkv: Linear
17
+ @ModuleInfo public var in_proj_z: Linear
18
+ @ModuleInfo public var in_proj_b: Linear
19
+ @ModuleInfo public var in_proj_a: Linear
20
+ @ModuleInfo public var out_proj: Linear
21
+ @ModuleInfo public var norm: QwenHybridGatedRMSNorm
22
+ @ModuleInfo public var conv1d: QwenHybridDepthwiseConv1D
23
+ @ParameterInfo public var dt_bias: MLXArray
24
+ @ParameterInfo public var A_log: MLXArray
25
+
26
+ public init(config: any QwenHybridConfiguration) {
27
+ numValueHeads = config.linearNumValueHeads
28
+ numKeyHeads = config.linearNumKeyHeads
29
+ keyHeadDim = config.linearKeyHeadDim
30
+ valueHeadDim = config.linearValueHeadDim
31
+ keyDimension = config.linearNumKeyHeads * config.linearKeyHeadDim
32
+ valueDimension = config.linearNumValueHeads * config.linearValueHeadDim
33
+ convolutionDimension = keyDimension * 2 + valueDimension
34
+ kernelSize = config.linearConvKernelDim
35
+ keyNormWeight = MLX.ones([config.linearKeyHeadDim])
36
+ _in_proj_qkv = ModuleInfo(wrappedValue: Linear(config.hiddenSize, convolutionDimension, bias: false))
37
+ _in_proj_z = ModuleInfo(wrappedValue: Linear(config.hiddenSize, valueDimension, bias: false))
38
+ _in_proj_b = ModuleInfo(wrappedValue: Linear(config.hiddenSize, numValueHeads, bias: false))
39
+ _in_proj_a = ModuleInfo(wrappedValue: Linear(config.hiddenSize, numValueHeads, bias: false))
40
+ _out_proj = ModuleInfo(wrappedValue: Linear(valueDimension, config.hiddenSize, bias: false))
41
+ _norm = ModuleInfo(wrappedValue: QwenHybridGatedRMSNorm(dimensions: valueHeadDim, epsilon: config.rmsNormEps))
42
+ _conv1d = ModuleInfo(wrappedValue: QwenHybridDepthwiseConv1D(channels: convolutionDimension, kernelSize: kernelSize))
43
+ _dt_bias = ParameterInfo(wrappedValue: MLX.ones([numValueHeads]))
44
+ _A_log = ParameterInfo(wrappedValue: MLX.zeros([numValueHeads]))
45
+ super.init()
46
+ }
47
+
48
+ public func callAsFunction(_ input: MLXArray, cache: QwenHybridLayerCache) -> MLXArray {
49
+ let batch = input.dim(0)
50
+ let length = input.dim(1)
51
+ let mixed = causalConvolution(in_proj_qkv(input), cache: cache)
52
+ let pieces = mixed.split(indices: [keyDimension, keyDimension * 2], axis: -1)
53
+ var query = pieces[0].reshaped([batch, length, numKeyHeads, keyHeadDim])
54
+ var key = pieces[1].reshaped([batch, length, numKeyHeads, keyHeadDim])
55
+ let value = pieces[2].reshaped([batch, length, numValueHeads, valueHeadDim]).asType(.float32)
56
+ query = MLXFast.rmsNorm(query.asType(.float32), weight: keyNormWeight, eps: 1e-6) / Float(keyHeadDim)
57
+ key = MLXFast.rmsNorm(key.asType(.float32), weight: keyNormWeight, eps: 1e-6) / sqrt(Float(keyHeadDim))
58
+ let gate = MLX.exp(-MLX.exp(A_log.asType(.float32)) * MLXNN.softplus(in_proj_a(input).asType(.float32) + dt_bias))
59
+ let beta = MLX.sigmoid(in_proj_b(input)).asType(.float32)
60
+ let initialState = cache.recurrentState ?? MLX.zeros([batch, numValueHeads, valueHeadDim, keyHeadDim], dtype: .float32)
61
+ let updated = QwenHybridGatedDelta.update(query: query, key: key, value: value, gate: gate, beta: beta, state: initialState)
62
+ cache.recurrentState = updated.state
63
+ let normalized = norm(
64
+ updated.output.asType(input.dtype).reshaped([-1, valueHeadDim]),
65
+ gate: in_proj_z(input).reshaped([-1, valueHeadDim])
66
+ )
67
+ return out_proj(normalized.reshaped([batch, length, valueDimension]))
68
+ }
69
+
70
+ private func causalConvolution(_ input: MLXArray, cache: QwenHybridLayerCache) -> MLXArray {
71
+ let length = input.dim(1)
72
+ if let previous = cache.convolutionState {
73
+ let combined = MLX.concatenated([previous, input], axis: 1)
74
+ cache.convolutionState = combined[0..., (combined.dim(1) - kernelSize + 1)..., 0...]
75
+ return MLXNN.silu(MLX.conv1d(combined, conv1d.weight, padding: 0, groups: convolutionDimension))
76
+ }
77
+ let result = MLXNN.silu(MLX.conv1d(input, conv1d.weight, padding: kernelSize - 1, groups: convolutionDimension))
78
+ let paddedInput = padded(input, widths: [[0, 0], [max(0, kernelSize - 1 - length), 0], [0, 0]])
79
+ cache.convolutionState = paddedInput[0..., (paddedInput.dim(1) - kernelSize + 1)..., 0...]
80
+ return result[0..., 0..<length, 0...]
81
+ }
82
+ }
83
+
84
+ public enum QwenHybridGatedDelta {
85
+ public static func update(
86
+ query: MLXArray,
87
+ key: MLXArray,
88
+ value: MLXArray,
89
+ gate: MLXArray,
90
+ beta: MLXArray,
91
+ state initialState: MLXArray
92
+ ) -> (output: MLXArray, state: MLXArray) {
93
+ let repeats = value.dim(2) / key.dim(2)
94
+ let query = repeats == 1 ? query : MLX.repeated(query, count: repeats, axis: 2)
95
+ let key = repeats == 1 ? key : MLX.repeated(key, count: repeats, axis: 2)
96
+ var state = initialState
97
+ var outputs: [MLXArray] = []
98
+ outputs.reserveCapacity(query.dim(1))
99
+ for index in 0..<query.dim(1) {
100
+ let q = query[0..., index, 0..., 0...]
101
+ let k = key[0..., index, 0..., 0...]
102
+ let v = value[0..., index, 0..., 0...]
103
+ state = state * gate[0..., index, 0...].expandedDimensions(axes: [2, 3])
104
+ let remembered = (state * k.expandedDimensions(axis: 2)).sum(axis: -1)
105
+ let delta = (v - remembered) * beta[0..., index, 0...].expandedDimensions(axis: -1)
106
+ state = state + k.expandedDimensions(axis: 2) * delta.expandedDimensions(axis: -1)
107
+ outputs.append((state * q.expandedDimensions(axis: 2)).sum(axis: -1))
108
+ }
109
+ return (MLX.stacked(outputs, axis: 1), state)
110
+ }
111
+ }
@@ -4,7 +4,6 @@ import ReactAppDependencyProvider
4
4
  import UIKit
5
5
  import CryptoKit
6
6
  import Darwin
7
- import Security
8
7
 
9
8
  func launchArgument(_ name: String) -> String? {
10
9
  let arguments = ProcessInfo.processInfo.arguments
@@ -22,17 +21,6 @@ func launchArgument(_ name: String) -> String? {
22
21
 
23
22
  @main
24
23
  class AppDelegate: ExpoAppDelegate {
25
- public override func application(
26
- _ application: UIApplication,
27
- didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
28
- ) -> Bool {
29
- let launched = super.application(application, didFinishLaunchingWithOptions: launchOptions)
30
- if launched {
31
- PlatformHelperInstaller.refreshIfInstalledApp()
32
- }
33
- return launched
34
- }
35
-
36
24
  public func application(
37
25
  _ application: UIApplication,
38
26
  configurationForConnecting connectingSceneSession: UISceneSession,
@@ -63,200 +51,6 @@ class AppDelegate: ExpoAppDelegate {
63
51
  }
64
52
  }
65
53
 
66
- private enum PlatformHelperInstaller {
67
- static func refreshIfInstalledApp() {
68
- #if targetEnvironment(macCatalyst)
69
- let homeDirectory = URL(fileURLWithPath: NSHomeDirectory(), isDirectory: true)
70
- let homeApplications = homeDirectory
71
- .appendingPathComponent("Applications", isDirectory: true)
72
- .standardizedFileURL.path + "/"
73
- guard Bundle.main.bundleURL.standardizedFileURL.path.hasPrefix(homeApplications) else {
74
- return
75
- }
76
- guard let bundleIdentifier = Bundle.main.bundleIdentifier else { return }
77
-
78
- let serviceName = "PlatformHelper"
79
- let bundledHelper = Bundle.main.bundleURL
80
- .appendingPathComponent("Contents/Helpers/\(serviceName)")
81
- guard FileManager.default.isExecutableFile(atPath: bundledHelper.path) else {
82
- NSLog("Bleam helper unavailable: bundled executable is missing")
83
- return
84
- }
85
- guard
86
- let teamIdentifier = Bundle.main.object(forInfoDictionaryKey: "BleamTeamIdentifier") as? String,
87
- let platformVersion = Bundle.main.object(forInfoDictionaryKey: "BleamRuntimeVersion") as? String,
88
- validSignature(at: bundledHelper, teamIdentifier: teamIdentifier)
89
- else {
90
- NSLog("Bleam helper unavailable: bundled executable has an invalid identity")
91
- return
92
- }
93
-
94
- let label = "\(bundleIdentifier).PlatformHelper"
95
- let domain = "gui/\(getuid())"
96
- let helperRoot = homeDirectory
97
- .appendingPathComponent("Library/Application Support/Bleam/Helpers", isDirectory: true)
98
- .appendingPathComponent(bundleIdentifier, isDirectory: true)
99
- let installedHelper = helperRoot.appendingPathComponent(serviceName)
100
- let stagedHelper = helperRoot.appendingPathComponent(".\(serviceName).\(UUID().uuidString)")
101
- let backupHelper = helperRoot.appendingPathComponent(".\(serviceName).previous.\(UUID().uuidString)")
102
- let failedHelper = helperRoot.appendingPathComponent(".\(serviceName).failed.\(UUID().uuidString)")
103
- let pendingApply = homeDirectory
104
- .appendingPathComponent("Library/Application Support/Bleam/Updates", isDirectory: true)
105
- .appendingPathComponent(bundleIdentifier, isDirectory: true)
106
- .appendingPathComponent("platform-apply.pending")
107
- let launchAgents = homeDirectory
108
- .appendingPathComponent("Library/LaunchAgents", isDirectory: true)
109
- let plistURL = launchAgents.appendingPathComponent("\(label).plist")
110
- let propertyList: [String: Any] = [
111
- "Label": label,
112
- "ProgramArguments": [installedHelper.path],
113
- "ProcessType": "Background",
114
- "MachServices": [label: true],
115
- "KeepAlive": [
116
- "SuccessfulExit": false,
117
- "PathState": [pendingApply.path: true],
118
- ],
119
- "EnvironmentVariables": [
120
- "XPC_SERVICE_NAME": label,
121
- "BLEAM_BUNDLE_IDENTIFIER": bundleIdentifier,
122
- "BLEAM_TEAM_IDENTIFIER": teamIdentifier,
123
- "BLEAM_HELPER_VERSION": platformVersion,
124
- "BLEAM_PLATFORM_VERSION": platformVersion,
125
- ],
126
- ]
127
-
128
- do {
129
- defer { try? FileManager.default.removeItem(at: stagedHelper) }
130
- try FileManager.default.createDirectory(
131
- at: helperRoot,
132
- withIntermediateDirectories: true
133
- )
134
- try FileManager.default.copyItem(at: bundledHelper, to: stagedHelper)
135
- guard
136
- FileManager.default.isExecutableFile(atPath: stagedHelper.path),
137
- validSignature(at: stagedHelper, teamIdentifier: teamIdentifier)
138
- else {
139
- throw HelperInstallError.invalidSignature
140
- }
141
- try FileManager.default.createDirectory(
142
- at: launchAgents,
143
- withIntermediateDirectories: true
144
- )
145
- let data = try PropertyListSerialization.data(
146
- fromPropertyList: propertyList,
147
- format: .xml,
148
- options: 0
149
- )
150
- let previousPlist = try? Data(contentsOf: plistURL)
151
- let wasRegistered = runLaunchctl(["print", "\(domain)/\(label)"]) == 0
152
- if wasRegistered, runLaunchctl(["bootout", "\(domain)/\(label)"]) != 0 {
153
- throw HelperInstallError.registrationFailed
154
- }
155
-
156
- do {
157
- if FileManager.default.fileExists(atPath: installedHelper.path),
158
- rename(installedHelper.path, backupHelper.path) != 0
159
- {
160
- throw HelperInstallError.replacementFailed
161
- }
162
- guard rename(stagedHelper.path, installedHelper.path) == 0 else {
163
- throw HelperInstallError.replacementFailed
164
- }
165
- try data.write(to: plistURL, options: .atomic)
166
- let bootstrapStatus = runLaunchctl(["bootstrap", domain, plistURL.path])
167
- guard
168
- bootstrapStatus == 0 || runLaunchctl(["print", "\(domain)/\(label)"]) == 0
169
- else {
170
- throw HelperInstallError.registrationFailed
171
- }
172
- try? FileManager.default.removeItem(at: backupHelper)
173
- try? FileManager.default.removeItem(
174
- at: helperRoot.appendingPathComponent("PlatformHelper.xpc", isDirectory: true)
175
- )
176
- } catch let installError {
177
- do {
178
- let newJobRegistered = runLaunchctl(["print", "\(domain)/\(label)"]) == 0
179
- if newJobRegistered,
180
- runLaunchctl(["bootout", "\(domain)/\(label)"]) != 0
181
- {
182
- throw HelperInstallError.rollbackFailed
183
- }
184
- if FileManager.default.fileExists(atPath: installedHelper.path),
185
- rename(installedHelper.path, failedHelper.path) != 0
186
- {
187
- throw HelperInstallError.rollbackFailed
188
- }
189
- if FileManager.default.fileExists(atPath: backupHelper.path),
190
- rename(backupHelper.path, installedHelper.path) != 0
191
- {
192
- throw HelperInstallError.rollbackFailed
193
- }
194
- if let previousPlist {
195
- try previousPlist.write(to: plistURL, options: .atomic)
196
- if wasRegistered,
197
- runLaunchctl(["bootstrap", domain, plistURL.path]) != 0
198
- {
199
- throw HelperInstallError.rollbackFailed
200
- }
201
- } else {
202
- try? FileManager.default.removeItem(at: plistURL)
203
- }
204
- try? FileManager.default.removeItem(at: failedHelper)
205
- } catch {
206
- NSLog("Bleam helper rollback failed: %@", error.localizedDescription)
207
- throw error
208
- }
209
- throw installError
210
- }
211
- } catch {
212
- NSLog("Bleam helper install failed: %@", error.localizedDescription)
213
- return
214
- }
215
- #endif
216
- }
217
-
218
- private static func validSignature(at url: URL, teamIdentifier: String) -> Bool {
219
- var staticCode: SecStaticCode?
220
- guard
221
- SecStaticCodeCreateWithPath(url as CFURL, [], &staticCode) == errSecSuccess,
222
- let staticCode,
223
- SecStaticCodeCheckValidity(
224
- staticCode,
225
- SecCSFlags(rawValue: kSecCSStrictValidate),
226
- nil
227
- ) == errSecSuccess
228
- else { return false }
229
-
230
- var signingInfo: CFDictionary?
231
- guard
232
- SecCodeCopySigningInformation(
233
- staticCode,
234
- SecCSFlags(rawValue: kSecCSSigningInformation),
235
- &signingInfo
236
- ) == errSecSuccess
237
- else { return false }
238
- return (signingInfo as? [String: Any])?[kSecCodeInfoTeamIdentifier as String] as? String == teamIdentifier
239
- }
240
-
241
- private static func runLaunchctl(_ arguments: [String]) -> Int32 {
242
- let values = ["launchctl"] + arguments
243
- var argv = values.map { strdup($0) }
244
- argv.append(nil)
245
- defer { argv.compactMap { $0 }.forEach { free($0) } }
246
-
247
- var pid: pid_t = 0
248
- let result = posix_spawn(&pid, "/bin/launchctl", nil, nil, &argv, environ)
249
- guard result == 0 else { return Int32(result) }
250
- var status: Int32 = 0
251
- guard waitpid(pid, &status, 0) == pid else { return -1 }
252
- return status
253
- }
254
- }
255
-
256
- private enum HelperInstallError: Error {
257
- case invalidSignature, registrationFailed, replacementFailed, rollbackFailed
258
- }
259
-
260
54
  class ReactNativeDelegate: ExpoReactNativeFactoryDelegate {
261
55
  private let bundleOverrideURL: URL?
262
56