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
@@ -3,12 +3,15 @@ import Foundation
3
3
  @objc protocol GenerationServiceProtocol {
4
4
  func startGeneration(requestData: Data, reply: @escaping (Bool) -> Void)
5
5
  func cancelGeneration(reply: @escaping (Bool) -> Void)
6
+ func startTextGeneration(requestData: Data, reply: @escaping (Bool) -> Void)
7
+ func cancelTextGeneration(id: String, reply: @escaping (Bool) -> Void)
6
8
  func memoryTelemetry(reply: @escaping (Data?) -> Void)
7
9
  func shutdown(reply: @escaping (Bool) -> Void)
8
10
  }
9
11
 
10
12
  @objc protocol GenerationServiceClientProtocol {
11
13
  func generationWorkerDidEmit(eventData: Data)
14
+ func textGenerationWorkerDidEmit(eventData: Data)
12
15
  }
13
16
 
14
17
  struct GenerationWorkerRequest: Codable, Sendable {
@@ -133,3 +136,47 @@ struct GenerationWorkerLoRA: Codable, Sendable {
133
136
  let path: String
134
137
  let scale: Double
135
138
  }
139
+
140
+ struct BonsaiTextGenerationRequest: Codable, Sendable {
141
+ let id: String
142
+ let model: String
143
+ let modelPath: String
144
+ let inputIDs: [Int]
145
+ let endTokenIDs: [Int]
146
+ let maximumNewTokens: Int?
147
+ let temperature: Double?
148
+ let topP: Double?
149
+ let topK: Int?
150
+ let repetitionPenalty: Double?
151
+ let repetitionContextSize: Int?
152
+ let seed: Int?
153
+ }
154
+
155
+ struct BonsaiTextGenerationEvent: Codable, Sendable {
156
+ enum EventType: String, Codable, Sendable {
157
+ case update
158
+ case completed
159
+ case canceled
160
+ case failed
161
+ }
162
+
163
+ let type: EventType
164
+ let id: String
165
+ let tokenIDs: [Int]
166
+ let finishReason: String?
167
+ let message: String?
168
+
169
+ init(
170
+ type: EventType,
171
+ id: String,
172
+ tokenIDs: [Int] = [],
173
+ finishReason: String? = nil,
174
+ message: String? = nil
175
+ ) {
176
+ self.type = type
177
+ self.id = id
178
+ self.tokenIDs = tokenIDs
179
+ self.finishReason = finishReason
180
+ self.message = message
181
+ }
182
+ }
@@ -6,70 +6,10 @@ import ExpoModulesCore
6
6
  import Foundation
7
7
  import Photos
8
8
 
9
- @objc private protocol PlatformHelperProtocol {
10
- func health(reply: @escaping (Data?) -> Void)
11
- func downloadPlatformUpdate(requestData: Data, reply: @escaping (Data?) -> Void)
12
- func applyPlatformUpdate(requestData: Data, reply: @escaping (Bool) -> Void)
13
- }
14
-
15
9
  public final class PlatformModule: Module {
16
10
  public func definition() -> ModuleDefinition {
17
11
  Name("Platform")
18
12
 
19
- AsyncFunction("helperStatus") { (promise: Promise) in
20
- guard Self.isSupportedInstallLocation else {
21
- UserDefaults.standard.set(false, forKey: "BleamPlatformUpdatesSupported")
22
- promise.resolve([
23
- "healthy": false,
24
- "protocolVersion": 1,
25
- "helperVersion": "unavailable",
26
- "platformVersion": "unavailable",
27
- "capabilities": [],
28
- "updatesSupported": false,
29
- "installPath": Bundle.main.bundleURL.path,
30
- "reason": "reinstall_required",
31
- ])
32
- return
33
- }
34
- let serviceName = "\(Bundle.main.bundleIdentifier ?? "dev.bleam.app").PlatformHelper"
35
- guard let connection = Self.makeConnection(serviceName: serviceName) else {
36
- promise.reject("HELPER_UNAVAILABLE", "The app helper is unavailable")
37
- return
38
- }
39
- connection.remoteObjectInterface = NSXPCInterface(with: PlatformHelperProtocol.self)
40
- connection.resume()
41
-
42
- guard let service = connection.remoteObjectProxyWithErrorHandler({ error in
43
- connection.invalidate()
44
- promise.reject("HELPER_UNAVAILABLE", error.localizedDescription)
45
- }) as? PlatformHelperProtocol else {
46
- connection.invalidate()
47
- promise.reject("HELPER_UNAVAILABLE", "The app helper is unavailable")
48
- return
49
- }
50
-
51
- service.health { data in
52
- defer { connection.invalidate() }
53
- guard
54
- let data,
55
- var status = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
56
- else {
57
- promise.reject("HELPER_INVALID_RESPONSE", "The app helper returned an invalid response")
58
- return
59
- }
60
- let supported = Self.isSupportedInstallLocation
61
- status["updatesSupported"] = supported
62
- status["installPath"] = Bundle.main.bundleURL.path
63
- if !supported {
64
- status["reason"] = "reinstall_required"
65
- }
66
- UserDefaults.standard.set(status["healthy"], forKey: "BleamHelperHealthy")
67
- UserDefaults.standard.set(status["platformVersion"], forKey: "BleamHelperPlatformVersion")
68
- UserDefaults.standard.set(supported, forKey: "BleamPlatformUpdatesSupported")
69
- promise.resolve(status)
70
- }
71
- }
72
-
73
13
  AsyncFunction("permissionState") { (capability: String, promise: Promise) in
74
14
  guard let state = Self.permissionState(capability) else {
75
15
  promise.reject("INVALID_CAPABILITY", "Unknown permission capability: \(capability)")
@@ -85,132 +25,6 @@ public final class PlatformModule: Module {
85
25
  }
86
26
  promise.resolve(states)
87
27
  }
88
-
89
- AsyncFunction("downloadPlatformUpdate") { (promise: Promise) in
90
- guard Self.isSupportedInstallLocation else {
91
- promise.reject("REINSTALL_REQUIRED", "Platform updates require the app to be installed directly in ~/Applications")
92
- return
93
- }
94
- guard
95
- let serviceURL = Bundle.main.object(forInfoDictionaryKey: "BleamUpdateServiceURL") as? String,
96
- let bundleIdentifier = Bundle.main.bundleIdentifier,
97
- let teamIdentifier = Bundle.main.object(forInfoDictionaryKey: "BleamTeamIdentifier") as? String,
98
- let platformVersion = Bundle.main.object(forInfoDictionaryKey: "BleamRuntimeVersion") as? String,
99
- let platformFingerprint = Bundle.main.object(forInfoDictionaryKey: "BleamPlatformFingerprint") as? String,
100
- let requestData = try? JSONSerialization.data(withJSONObject: [
101
- "serviceURL": serviceURL,
102
- "bundleIdentifier": bundleIdentifier,
103
- "teamIdentifier": teamIdentifier,
104
- "platformVersion": platformVersion,
105
- "platformFingerprint": platformFingerprint,
106
- ])
107
- else {
108
- promise.reject("UPDATES_UNAVAILABLE", "Platform updates are not configured")
109
- return
110
- }
111
-
112
- guard let connection = Self.makeConnection(serviceName: "\(bundleIdentifier).PlatformHelper") else {
113
- promise.reject("HELPER_UNAVAILABLE", "The app helper is unavailable")
114
- return
115
- }
116
- connection.remoteObjectInterface = NSXPCInterface(with: PlatformHelperProtocol.self)
117
- connection.resume()
118
- guard let service = connection.remoteObjectProxyWithErrorHandler({ error in
119
- connection.invalidate()
120
- promise.reject("PLATFORM_DOWNLOAD_FAILED", error.localizedDescription)
121
- }) as? PlatformHelperProtocol else {
122
- connection.invalidate()
123
- promise.reject("HELPER_UNAVAILABLE", "The app helper is unavailable")
124
- return
125
- }
126
-
127
- service.downloadPlatformUpdate(requestData: requestData) { data in
128
- defer { connection.invalidate() }
129
- guard
130
- let data,
131
- let result = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
132
- else {
133
- promise.reject("PLATFORM_DOWNLOAD_FAILED", "The platform update could not be downloaded")
134
- return
135
- }
136
- if let error = result["error"] as? String {
137
- UserDefaults.standard.set(error, forKey: "BleamPlatformDownloadError")
138
- promise.reject("PLATFORM_VERIFICATION_FAILED", error)
139
- return
140
- }
141
- UserDefaults.standard.set(result["releaseId"], forKey: "BleamPlatformDownloadRelease")
142
- promise.resolve(result)
143
- }
144
- }
145
-
146
- AsyncFunction("updateAndRelaunch") { (releaseId: String, promise: Promise) in
147
- guard Self.isSupportedInstallLocation else {
148
- promise.reject("REINSTALL_REQUIRED", "Platform updates require the app to be installed directly in ~/Applications")
149
- return
150
- }
151
- guard
152
- let bundleIdentifier = Bundle.main.bundleIdentifier,
153
- let teamIdentifier = Bundle.main.object(forInfoDictionaryKey: "BleamTeamIdentifier") as? String,
154
- let requestData = try? JSONSerialization.data(withJSONObject: [
155
- "releaseId": releaseId,
156
- "bundleIdentifier": bundleIdentifier,
157
- "teamIdentifier": teamIdentifier,
158
- "installedAppPath": Bundle.main.bundleURL.path,
159
- "appPID": ProcessInfo.processInfo.processIdentifier,
160
- ]),
161
- let connection = Self.makeConnection(serviceName: "\(bundleIdentifier).PlatformHelper")
162
- else {
163
- promise.reject("PLATFORM_UPDATE_UNAVAILABLE", "The platform update cannot be applied")
164
- return
165
- }
166
- connection.remoteObjectInterface = NSXPCInterface(with: PlatformHelperProtocol.self)
167
- connection.resume()
168
- guard let service = connection.remoteObjectProxyWithErrorHandler({ error in
169
- connection.invalidate()
170
- promise.reject("PLATFORM_UPDATE_FAILED", error.localizedDescription)
171
- }) as? PlatformHelperProtocol else {
172
- connection.invalidate()
173
- promise.reject("HELPER_UNAVAILABLE", "The app helper is unavailable")
174
- return
175
- }
176
- service.applyPlatformUpdate(requestData: requestData) { accepted in
177
- connection.invalidate()
178
- UserDefaults.standard.set(accepted, forKey: "BleamPlatformApplyAccepted")
179
- guard accepted else {
180
- promise.reject("PLATFORM_UPDATE_REJECTED", "The platform update is not verified or the app is not installed in ~/Applications")
181
- return
182
- }
183
- promise.resolve(nil)
184
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
185
- exit(0)
186
- }
187
- }
188
- }
189
- }
190
-
191
- private static func makeConnection(serviceName: String) -> NSXPCConnection? {
192
- #if targetEnvironment(macCatalyst)
193
- let connectionClass: AnyObject = NSXPCConnection.self as AnyObject
194
- let allocated = connectionClass.perform(NSSelectorFromString("alloc"))?.takeUnretainedValue() as AnyObject?
195
- let selector = NSSelectorFromString("initWithMachServiceName:options:")
196
- guard let allocated, allocated.responds(to: selector) else { return nil }
197
-
198
- typealias Initializer = @convention(c) (
199
- AnyObject,
200
- Selector,
201
- NSString,
202
- UInt
203
- ) -> Unmanaged<AnyObject>
204
- let initialize = unsafeBitCast(allocated.method(for: selector), to: Initializer.self)
205
- return initialize(
206
- allocated,
207
- selector,
208
- serviceName as NSString,
209
- 0
210
- ).takeRetainedValue() as? NSXPCConnection
211
- #else
212
- return NSXPCConnection(machServiceName: serviceName)
213
- #endif
214
28
  }
215
29
 
216
30
  private static let permissionCapabilities = [
@@ -321,9 +135,4 @@ public final class PlatformModule: Module {
321
135
  }
322
136
  }
323
137
 
324
- private static var isSupportedInstallLocation: Bool {
325
- let applications = URL(fileURLWithPath: NSHomeDirectory(), isDirectory: true)
326
- .appendingPathComponent("Applications", isDirectory: true).standardizedFileURL
327
- return Bundle.main.bundleURL.standardizedFileURL.deletingLastPathComponent() == applications
328
- }
329
138
  }
@@ -0,0 +1,124 @@
1
+ import { bonsai, chat, prepareTextModel, useChat, useChatList } from 'bleam/ai'
2
+ import { sx } from 'bleam/styles'
3
+ import { Button } from 'bleam/ui'
4
+ import { Window } from 'bleam/window'
5
+ import { useEffect, useRef, useState } from 'react'
6
+ import { Text, TextInput, View } from 'react-native'
7
+
8
+ const appName = 'Bleam Basic'
9
+ const model = bonsai('ternary-bonsai-4b')
10
+
11
+ export default function App() {
12
+ const chats = useChatList()
13
+ const creating = useRef(false)
14
+ const [path, setPath] = useState<string | null>(null)
15
+ const [status, setStatus] = useState('Preparing local model...')
16
+
17
+ useEffect(() => {
18
+ if (chats.length > 0 || creating.current) return
19
+ creating.current = true
20
+ void chat.create({ title: 'Private writing' }).catch((error) => {
21
+ setStatus(error instanceof Error ? error.message : String(error))
22
+ })
23
+ }, [chats.length])
24
+
25
+ useEffect(() => {
26
+ const controller = new AbortController()
27
+ void prepareTextModel(model, {
28
+ signal: controller.signal,
29
+ onProgress(progress) {
30
+ setStatus(
31
+ `Preparing model ${Math.round(progress.modelFraction * 100)}%`,
32
+ )
33
+ },
34
+ })
35
+ .then((prepared) => {
36
+ setPath(prepared.path)
37
+ setStatus('Ready')
38
+ })
39
+ .catch((error) => {
40
+ if (!controller.signal.aborted) {
41
+ setStatus(error instanceof Error ? error.message : String(error))
42
+ }
43
+ })
44
+ return () => controller.abort()
45
+ }, [])
46
+
47
+ return (
48
+ <View style={sx('flex-1', 'p-8', 'gap-6')}>
49
+ <Window title={appName} />
50
+ <Text style={sx('text-3xl', 'font-semibold')}>
51
+ Private Writing Assistant
52
+ </Text>
53
+ <Text style={sx('text-secondary-label')}>
54
+ Ternary Bonsai runs locally after its first model download. Chats return
55
+ after relaunch.
56
+ </Text>
57
+ <Text style={sx('text-secondary-label')}>{status}</Text>
58
+ {path && chats[0] ? <Conversation id={chats[0].id} path={path} /> : null}
59
+ </View>
60
+ )
61
+ }
62
+
63
+ function Conversation({ id, path }: { id: string; path: string }) {
64
+ const conversation = useChat(id, {
65
+ model,
66
+ path,
67
+ system: 'You are a concise private writing assistant.',
68
+ })
69
+ const [prompt, setPrompt] = useState(
70
+ 'Rewrite this note so it is clear and concise: We should probably meet sometime next week to discuss the launch.',
71
+ )
72
+ const latestAssistant = conversation.messages.findLast(
73
+ (message) => message.role === 'assistant',
74
+ )
75
+ const retryable =
76
+ latestAssistant?.status === 'failed' ||
77
+ latestAssistant?.status === 'canceled'
78
+ ? latestAssistant
79
+ : null
80
+
81
+ return (
82
+ <View style={sx('gap-6')}>
83
+ <TextInput
84
+ multiline
85
+ value={prompt}
86
+ onChangeText={setPrompt}
87
+ style={sx(
88
+ { minHeight: 128 },
89
+ 'rounded-xl',
90
+ 'border',
91
+ 'border-separator',
92
+ 'p-4',
93
+ )}
94
+ />
95
+ <View style={sx('flex-row', 'gap-3')}>
96
+ <Button
97
+ title="Send"
98
+ loading={conversation.isGenerating}
99
+ disabled={!conversation.canSend}
100
+ onPress={() => void conversation.send(prompt)}
101
+ />
102
+ <Button
103
+ title="Cancel"
104
+ variant="secondary"
105
+ disabled={!conversation.canCancel}
106
+ onPress={() => void conversation.cancel()}
107
+ />
108
+ {retryable ? (
109
+ <Button
110
+ title="Retry"
111
+ variant="secondary"
112
+ onPress={() => void conversation.retry(retryable.id)}
113
+ />
114
+ ) : null}
115
+ </View>
116
+ {conversation.messages.map((message) => (
117
+ <Text key={message.id} style={sx('text-lg', 'text-label')}>
118
+ {message.role === 'user' ? 'You: ' : 'Assistant: '}
119
+ {message.content || message.status}
120
+ </Text>
121
+ ))}
122
+ </View>
123
+ )
124
+ }
@@ -0,0 +1,5 @@
1
+ import { appConfig } from 'bleam'
2
+
3
+ export default appConfig({
4
+ name: 'Bleam Basic',
5
+ })