bleam 0.0.12 → 0.0.14
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.
- package/dist/ai.cjs +5 -4
- package/dist/ai.js +4 -3
- package/dist/app-storage-D8W4n8ey.cjs +39 -0
- package/dist/app-storage-Isi5Bo0R.js +34 -0
- package/dist/cli.cjs +149 -23
- package/dist/cli.d.cts +13 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.js +149 -23
- package/dist/elements-DX_YUveu.d.ts +341 -0
- package/dist/elements-gEI8YGl1.d.cts +341 -0
- package/dist/elements.cjs +1031 -0
- package/dist/elements.d.cts +2 -0
- package/dist/elements.d.ts +2 -0
- package/dist/elements.js +999 -0
- package/dist/{files-BXVkPrPN.js → files-DErLhzCB.js} +5 -11
- package/dist/{files-DxaQ-Nv0.cjs → files-lMk-CpL_.cjs} +5 -11
- package/dist/files.cjs +1 -1
- package/dist/files.js +1 -1
- package/dist/schema.cjs +1 -1
- package/dist/schema.d.cts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +1 -1
- package/dist/secrets.cjs +146 -0
- package/dist/secrets.d.cts +14 -0
- package/dist/secrets.d.ts +14 -0
- package/dist/secrets.js +142 -0
- package/dist/{state-LssDgpff.cjs → state-Bm9GiRnU.cjs} +61 -47
- package/dist/{state-Dh3HLixb.js → state-D8Firo9w.js} +60 -41
- package/dist/state.cjs +3 -2
- package/dist/state.d.cts +1 -1
- package/dist/state.d.ts +1 -1
- package/dist/state.js +3 -2
- package/dist/window.d.cts +1 -1
- package/dist/window.d.ts +1 -1
- package/package.json +14 -11
- package/templates/basic/app/index.tsx +7 -129
- package/templates/foundation-models/app/index.tsx +100 -41
- package/templates/image-generation/app/index.tsx +2 -2
- package/templates/native/ios/Podfile.lock +6 -0
- package/templates/native/modules/bleam-runtime/ios/AIModule.swift +7 -8
- package/templates/native/package.json +6 -1
- package/templates/native/yarn.lock +5392 -3749
- package/templates/state/app/index.tsx +2 -2
- package/templates/text-generation/app/index.tsx +4 -4
- package/templates/updates/README.md +1 -1
- package/dist/native-sqlite-xcGdamRD.js +0 -64
- package/dist/native-sqlite-yQLD5s9i.cjs +0 -66
- package/dist/ui-1WepaMS4.d.cts +0 -92
- package/dist/ui-D7bRLYee.d.ts +0 -92
- package/dist/ui.cjs +0 -364
- package/dist/ui.d.cts +0 -2
- package/dist/ui.d.ts +0 -2
- package/dist/ui.js +0 -357
- /package/dist/{schema-B5BfdswF.js → schema-B7ELMpuI.js} +0 -0
- /package/dist/{schema-BnVZOXfu.cjs → schema-B7SLUBLN.cjs} +0 -0
- /package/dist/{schema-D5eImHxu.d.cts → schema-BWsDPc6c.d.cts} +0 -0
- /package/dist/{schema-SSjokbtw.d.ts → schema-DsXZBnvc.d.ts} +0 -0
|
@@ -1,41 +1,11 @@
|
|
|
1
|
-
import { t as ensureNativeScript } from "./native-runtime-C85Nuc4F.js";
|
|
2
1
|
import { t as crypto } from "./crypto-BB92-Upx.js";
|
|
3
|
-
import {
|
|
2
|
+
import { t as currentAppStorageKey } from "./app-storage-Isi5Bo0R.js";
|
|
3
|
+
import { l as schema } from "./schema-B7ELMpuI.js";
|
|
4
4
|
import { useAtom, useAtomValue, useSetAtom } from "jotai/react";
|
|
5
5
|
import { atom, getDefaultStore } from "jotai/vanilla";
|
|
6
6
|
import { atomFamily } from "jotai-family";
|
|
7
|
+
import { openDatabaseAsync } from "expo-sqlite";
|
|
7
8
|
|
|
8
|
-
//#region src/app-storage.ts
|
|
9
|
-
let cachedStorageKey;
|
|
10
|
-
function launchArgument(name) {
|
|
11
|
-
const argumentsList = NSProcessInfo.processInfo.arguments();
|
|
12
|
-
const count = Number(argumentsList.count ?? 0);
|
|
13
|
-
for (let index = 0; index < count - 1; index += 1) if (String(argumentsList.objectAtIndex(index)) === name) return String(argumentsList.objectAtIndex(index + 1));
|
|
14
|
-
}
|
|
15
|
-
function storageKey$1(name) {
|
|
16
|
-
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "app";
|
|
17
|
-
}
|
|
18
|
-
function currentAppStorageKey() {
|
|
19
|
-
if (cachedStorageKey) return cachedStorageKey;
|
|
20
|
-
ensureNativeScript();
|
|
21
|
-
const configPath = launchArgument("--bleam-project-config");
|
|
22
|
-
if (configPath) try {
|
|
23
|
-
const text = String(NSString.stringWithContentsOfFileEncodingError(configPath, NSUTF8StringEncoding, null));
|
|
24
|
-
const config = JSON.parse(text);
|
|
25
|
-
if (typeof config.id === "string" && config.id) {
|
|
26
|
-
cachedStorageKey = config.id;
|
|
27
|
-
return cachedStorageKey;
|
|
28
|
-
}
|
|
29
|
-
if (typeof config.name === "string" && config.name) {
|
|
30
|
-
cachedStorageKey = storageKey$1(config.name);
|
|
31
|
-
return cachedStorageKey;
|
|
32
|
-
}
|
|
33
|
-
} catch {}
|
|
34
|
-
cachedStorageKey = "app";
|
|
35
|
-
return cachedStorageKey;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
//#endregion
|
|
39
9
|
//#region src/state/atom.ts
|
|
40
10
|
const storedAtomsKey = Symbol.for("bleam.state.storedAtoms.v1");
|
|
41
11
|
function storedAtoms() {
|
|
@@ -155,6 +125,55 @@ function internalJotaiWritableAtom(value) {
|
|
|
155
125
|
}
|
|
156
126
|
const internalStore = getDefaultStore();
|
|
157
127
|
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/native-sqlite.ts
|
|
130
|
+
const databases = /* @__PURE__ */ new Map();
|
|
131
|
+
function toExpoParameters(parameters) {
|
|
132
|
+
return parameters;
|
|
133
|
+
}
|
|
134
|
+
function toSQLiteValue(value) {
|
|
135
|
+
if (typeof value === "string" || typeof value === "number" || value === null) return value;
|
|
136
|
+
throw new Error("SQLite blobs are not supported by Bleam state yet");
|
|
137
|
+
}
|
|
138
|
+
function toSQLiteRow(row) {
|
|
139
|
+
const output = {};
|
|
140
|
+
for (const [key, value] of Object.entries(row)) output[key] = toSQLiteValue(value);
|
|
141
|
+
return output;
|
|
142
|
+
}
|
|
143
|
+
var NativeSQLiteDatabase = class NativeSQLiteDatabase {
|
|
144
|
+
constructor(database) {
|
|
145
|
+
this.database = database;
|
|
146
|
+
}
|
|
147
|
+
async execute(query, parameters) {
|
|
148
|
+
await this.database.runAsync(query, toExpoParameters(parameters) ?? []);
|
|
149
|
+
}
|
|
150
|
+
async select(query, parameters) {
|
|
151
|
+
return (await this.database.getAllAsync(query, toExpoParameters(parameters) ?? [])).map(toSQLiteRow);
|
|
152
|
+
}
|
|
153
|
+
async get(query, parameters) {
|
|
154
|
+
const row = await this.database.getFirstAsync(query, toExpoParameters(parameters) ?? []);
|
|
155
|
+
return row ? toSQLiteRow(row) : void 0;
|
|
156
|
+
}
|
|
157
|
+
async transaction(action) {
|
|
158
|
+
let result;
|
|
159
|
+
await this.database.withExclusiveTransactionAsync(async (transaction) => {
|
|
160
|
+
result = await action(new NativeSQLiteDatabase(transaction));
|
|
161
|
+
});
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
close() {
|
|
165
|
+
return this.database.closeAsync();
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
function openNativeSQLiteDatabase(name = "bleam.sqlite3") {
|
|
169
|
+
let database = databases.get(name);
|
|
170
|
+
if (!database) {
|
|
171
|
+
database = openDatabaseAsync(name).then((value) => new NativeSQLiteDatabase(value));
|
|
172
|
+
databases.set(name, database);
|
|
173
|
+
}
|
|
174
|
+
return database;
|
|
175
|
+
}
|
|
176
|
+
|
|
158
177
|
//#endregion
|
|
159
178
|
//#region src/state/collection.ts
|
|
160
179
|
var CollectionVersionConflictError = class extends Error {
|
|
@@ -182,18 +201,18 @@ let jsonSqlSupportPromise;
|
|
|
182
201
|
let mutationPipeline = Promise.resolve();
|
|
183
202
|
let transactionCallbackStarting = false;
|
|
184
203
|
function getDatabase() {
|
|
185
|
-
databasePromise ??=
|
|
204
|
+
databasePromise ??= Promise.resolve().then(() => openNativeSQLiteDatabase(`${currentAppStorageKey()}.sqlite3`));
|
|
186
205
|
return databasePromise;
|
|
187
206
|
}
|
|
188
207
|
async function initializedDatabase() {
|
|
189
208
|
initializedPromise ??= (async () => {
|
|
190
209
|
const database = await getDatabase();
|
|
191
210
|
await database.execute("PRAGMA journal_mode = WAL");
|
|
192
|
-
if (numberValue(await database.get("PRAGMA user_version"), "user_version", 0) !== schemaVersion) await database.transaction(async () => {
|
|
193
|
-
await
|
|
194
|
-
await
|
|
195
|
-
await createTables(
|
|
196
|
-
await
|
|
211
|
+
if (numberValue(await database.get("PRAGMA user_version"), "user_version", 0) !== schemaVersion) await database.transaction(async (transaction) => {
|
|
212
|
+
await transaction.execute("DROP TABLE IF EXISTS links");
|
|
213
|
+
await transaction.execute("DROP TABLE IF EXISTS collections");
|
|
214
|
+
await createTables(transaction);
|
|
215
|
+
await transaction.execute(`PRAGMA user_version = ${schemaVersion}`);
|
|
197
216
|
});
|
|
198
217
|
else await createTables(database);
|
|
199
218
|
return database;
|
|
@@ -675,7 +694,7 @@ function enqueueMutation(action) {
|
|
|
675
694
|
const database = await initializedDatabase();
|
|
676
695
|
const changes = /* @__PURE__ */ new Map();
|
|
677
696
|
try {
|
|
678
|
-
const value = await database.transaction(() => action(
|
|
697
|
+
const value = await database.transaction((transaction) => action(transaction, changes));
|
|
679
698
|
publishChanges(changes);
|
|
680
699
|
resolve(value);
|
|
681
700
|
} catch (error) {
|
|
@@ -871,4 +890,4 @@ function useField(collection, id, path) {
|
|
|
871
890
|
}
|
|
872
891
|
|
|
873
892
|
//#endregion
|
|
874
|
-
export { transactionAtom as a, useRow as c, internalJotaiWritableAtom as d, internalStore as f,
|
|
893
|
+
export { transactionAtom as a, useRow as c, internalJotaiWritableAtom as d, internalStore as f, useSetAtom$1 as h, queryAtom as i, atom$1 as l, useAtomValue$1 as m, atomCollection as n, useField as o, useAtom$1 as p, mutateAtom as r, useList as s, CollectionVersionConflictError as t, internalJotaiAtom as u };
|
package/dist/state.cjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
require('./native-runtime-CsXnXkQn.cjs');
|
|
2
2
|
require('./crypto-CT3VZ7lF.cjs');
|
|
3
|
-
|
|
4
|
-
const
|
|
3
|
+
require('./app-storage-D8W4n8ey.cjs');
|
|
4
|
+
const require_schema = require('./schema-B7SLUBLN.cjs');
|
|
5
|
+
const require_state = require('./state-Bm9GiRnU.cjs');
|
|
5
6
|
|
|
6
7
|
exports.CollectionVersionConflictError = require_state.CollectionVersionConflictError;
|
|
7
8
|
exports.array = require_schema.array;
|
package/dist/state.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as array, C as SchemaOutput, E as SchemaShape, F as number, I as object, P as literal, R as string, _ as ObjectField, b as SchemaInput, c as FieldPath, j as boolean, k as ValueAtFieldPath, s as FieldOutput, w as SchemaPatch } from "./schema-
|
|
1
|
+
import { A as array, C as SchemaOutput, E as SchemaShape, F as number, I as object, P as literal, R as string, _ as ObjectField, b as SchemaInput, c as FieldPath, j as boolean, k as ValueAtFieldPath, s as FieldOutput, w as SchemaPatch } from "./schema-BWsDPc6c.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/state/atom.d.ts
|
|
4
4
|
declare const atomValue: unique symbol;
|
package/dist/state.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as array, C as SchemaOutput, E as SchemaShape, F as number, I as object, P as literal, R as string, _ as ObjectField, b as SchemaInput, c as FieldPath, j as boolean, k as ValueAtFieldPath, s as FieldOutput, w as SchemaPatch } from "./schema-
|
|
1
|
+
import { A as array, C as SchemaOutput, E as SchemaShape, F as number, I as object, P as literal, R as string, _ as ObjectField, b as SchemaInput, c as FieldPath, j as boolean, k as ValueAtFieldPath, s as FieldOutput, w as SchemaPatch } from "./schema-DsXZBnvc.js";
|
|
2
2
|
import "jotai/vanilla";
|
|
3
3
|
|
|
4
4
|
//#region src/state/atom.d.ts
|
package/dist/state.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import "./native-runtime-C85Nuc4F.js";
|
|
2
2
|
import "./crypto-BB92-Upx.js";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
3
|
+
import "./app-storage-Isi5Bo0R.js";
|
|
4
|
+
import { c as object, n as array, o as literal, r as boolean, s as number, u as string } from "./schema-B7ELMpuI.js";
|
|
5
|
+
import { a as transactionAtom, c as useRow, h as useSetAtom, i as queryAtom, l as atom, m as useAtomValue, n as atomCollection, o as useField, p as useAtom, r as mutateAtom, s as useList, t as CollectionVersionConflictError } from "./state-D8Firo9w.js";
|
|
5
6
|
|
|
6
7
|
export { CollectionVersionConflictError, array, atom, atomCollection, boolean, literal, mutateAtom, number, object, queryAtom, string, transactionAtom, useAtom, useAtomValue, useField, useList, useRow, useSetAtom };
|
package/dist/window.d.cts
CHANGED
package/dist/window.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bleam",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"packageManager": "yarn@
|
|
3
|
+
"version": "0.0.14",
|
|
4
|
+
"packageManager": "yarn@4.17.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
@@ -10,9 +10,7 @@
|
|
|
10
10
|
"tsconfig.json",
|
|
11
11
|
"tsconfig.base.json"
|
|
12
12
|
],
|
|
13
|
-
"bin":
|
|
14
|
-
"bleam": "dist/cli.js"
|
|
15
|
-
},
|
|
13
|
+
"bin": "dist/cli.js",
|
|
16
14
|
"scripts": {
|
|
17
15
|
"build": "tsdown",
|
|
18
16
|
"prepublishOnly": "tsdown",
|
|
@@ -30,11 +28,11 @@
|
|
|
30
28
|
"dependencies": {
|
|
31
29
|
"@biomejs/biome": "^2.2.0",
|
|
32
30
|
"@expo/metro": "56.0.0",
|
|
33
|
-
"@nativescript-community/sqlite": "^3.5.9",
|
|
34
31
|
"@nativescript/react-native": "9.0.0-preview.4",
|
|
35
32
|
"@types/react": "~19.2.17",
|
|
36
33
|
"expo": "57",
|
|
37
34
|
"expo-splash-screen": "57.0.2",
|
|
35
|
+
"expo-sqlite": "~57.0.1",
|
|
38
36
|
"jotai": "2.20.2",
|
|
39
37
|
"jotai-family": "1.0.2",
|
|
40
38
|
"react": "19.2.3",
|
|
@@ -97,6 +95,11 @@
|
|
|
97
95
|
"import": "./dist/dev-protocol.js",
|
|
98
96
|
"require": "./dist/dev-protocol.cjs"
|
|
99
97
|
},
|
|
98
|
+
"./elements": {
|
|
99
|
+
"types": "./dist/elements.d.ts",
|
|
100
|
+
"import": "./dist/elements.js",
|
|
101
|
+
"require": "./dist/elements.cjs"
|
|
102
|
+
},
|
|
100
103
|
"./files": {
|
|
101
104
|
"types": "./dist/files.d.ts",
|
|
102
105
|
"import": "./dist/files.js",
|
|
@@ -117,6 +120,11 @@
|
|
|
117
120
|
"import": "./dist/schema.js",
|
|
118
121
|
"require": "./dist/schema.cjs"
|
|
119
122
|
},
|
|
123
|
+
"./secrets": {
|
|
124
|
+
"types": "./dist/secrets.d.ts",
|
|
125
|
+
"import": "./dist/secrets.js",
|
|
126
|
+
"require": "./dist/secrets.cjs"
|
|
127
|
+
},
|
|
120
128
|
"./state": {
|
|
121
129
|
"types": "./dist/state.d.ts",
|
|
122
130
|
"import": "./dist/state.js",
|
|
@@ -127,11 +135,6 @@
|
|
|
127
135
|
"import": "./dist/styles.js",
|
|
128
136
|
"require": "./dist/styles.cjs"
|
|
129
137
|
},
|
|
130
|
-
"./ui": {
|
|
131
|
-
"types": "./dist/ui.d.ts",
|
|
132
|
-
"import": "./dist/ui.js",
|
|
133
|
-
"require": "./dist/ui.cjs"
|
|
134
|
-
},
|
|
135
138
|
"./window": {
|
|
136
139
|
"types": "./dist/window.d.ts",
|
|
137
140
|
"import": "./dist/window.js",
|
|
@@ -1,139 +1,17 @@
|
|
|
1
|
-
import { atom, useAtom } from 'bleam/state'
|
|
2
1
|
import { sx } from 'bleam/styles'
|
|
3
|
-
import {
|
|
4
|
-
import { Toolbar, Window } from 'bleam/window'
|
|
2
|
+
import { Window } from 'bleam/window'
|
|
5
3
|
import { Text, View } from 'react-native'
|
|
6
4
|
|
|
7
5
|
const appName = 'Bleam Basic'
|
|
8
|
-
const counter = atom(0)
|
|
9
6
|
|
|
10
7
|
export default function App() {
|
|
11
|
-
const [count, setCount] = useAtom(counter)
|
|
12
|
-
|
|
13
8
|
return (
|
|
14
|
-
<View style={sx('flex-1')}>
|
|
15
|
-
<Window title={appName}
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<View style={sx('flex-1', 'items-center', 'justify-center', 'px-6')}>
|
|
21
|
-
<View style={sx('items-center', 'gap-8')}>
|
|
22
|
-
<View
|
|
23
|
-
style={sx('h-44', 'w-44', 'items-center', 'justify-center')}
|
|
24
|
-
>
|
|
25
|
-
<View
|
|
26
|
-
style={sx(
|
|
27
|
-
'absolute',
|
|
28
|
-
'top-0',
|
|
29
|
-
'h-24',
|
|
30
|
-
'w-32',
|
|
31
|
-
'rounded-2xl',
|
|
32
|
-
'border',
|
|
33
|
-
'border-tertiary-label',
|
|
34
|
-
'bg-system',
|
|
35
|
-
'items-center',
|
|
36
|
-
'justify-center',
|
|
37
|
-
'rotate-30',
|
|
38
|
-
)}
|
|
39
|
-
>
|
|
40
|
-
<Text
|
|
41
|
-
style={sx(
|
|
42
|
-
'text-3xl',
|
|
43
|
-
'font-semibold',
|
|
44
|
-
'text-system-cyan',
|
|
45
|
-
'-rotate-30',
|
|
46
|
-
)}
|
|
47
|
-
>
|
|
48
|
-
B
|
|
49
|
-
</Text>
|
|
50
|
-
</View>
|
|
51
|
-
|
|
52
|
-
<View
|
|
53
|
-
style={sx(
|
|
54
|
-
'absolute',
|
|
55
|
-
'bottom-2',
|
|
56
|
-
'h-24',
|
|
57
|
-
'w-32',
|
|
58
|
-
'rounded-2xl',
|
|
59
|
-
'border-2',
|
|
60
|
-
'border-system-purple',
|
|
61
|
-
'bg-secondary-system',
|
|
62
|
-
'items-center',
|
|
63
|
-
'justify-center',
|
|
64
|
-
'rotate-30',
|
|
65
|
-
)}
|
|
66
|
-
>
|
|
67
|
-
<Text
|
|
68
|
-
style={sx(
|
|
69
|
-
'text-3xl',
|
|
70
|
-
'font-bold',
|
|
71
|
-
'text-system-purple',
|
|
72
|
-
'-rotate-30',
|
|
73
|
-
)}
|
|
74
|
-
>
|
|
75
|
-
JS
|
|
76
|
-
</Text>
|
|
77
|
-
</View>
|
|
78
|
-
</View>
|
|
79
|
-
|
|
80
|
-
<View style={sx('items-center')}>
|
|
81
|
-
<Text
|
|
82
|
-
style={sx(
|
|
83
|
-
'text-5xl',
|
|
84
|
-
'font-semibold',
|
|
85
|
-
'tracking-tighter',
|
|
86
|
-
'text-label',
|
|
87
|
-
'text-center',
|
|
88
|
-
)}
|
|
89
|
-
>
|
|
90
|
-
Get started
|
|
91
|
-
</Text>
|
|
92
|
-
<Text
|
|
93
|
-
style={sx(
|
|
94
|
-
'mt-6',
|
|
95
|
-
'text-lg',
|
|
96
|
-
'text-secondary-label',
|
|
97
|
-
'text-center',
|
|
98
|
-
)}
|
|
99
|
-
>
|
|
100
|
-
Edit{' '}
|
|
101
|
-
<Text
|
|
102
|
-
style={sx(
|
|
103
|
-
'rounded-md',
|
|
104
|
-
'italic',
|
|
105
|
-
'px-2',
|
|
106
|
-
'py-1',
|
|
107
|
-
'text-label',
|
|
108
|
-
)}
|
|
109
|
-
>
|
|
110
|
-
app/index.tsx
|
|
111
|
-
</Text>{' '}
|
|
112
|
-
and save to test{' '}
|
|
113
|
-
<Text
|
|
114
|
-
style={sx(
|
|
115
|
-
'rounded-md',
|
|
116
|
-
'italic',
|
|
117
|
-
'px-2',
|
|
118
|
-
'py-1',
|
|
119
|
-
'text-label',
|
|
120
|
-
)}
|
|
121
|
-
>
|
|
122
|
-
live reload
|
|
123
|
-
</Text>
|
|
124
|
-
</Text>
|
|
125
|
-
</View>
|
|
126
|
-
|
|
127
|
-
<Button
|
|
128
|
-
title={`Count is ${count}`}
|
|
129
|
-
variant="secondary"
|
|
130
|
-
size="regular"
|
|
131
|
-
onPress={() => setCount((value) => value + 1)}
|
|
132
|
-
/>
|
|
133
|
-
</View>
|
|
134
|
-
</View>
|
|
135
|
-
</View>
|
|
136
|
-
</View>
|
|
9
|
+
<View style={sx('flex-1', 'items-center', 'justify-center', 'px-6')}>
|
|
10
|
+
<Window title={appName} />
|
|
11
|
+
<Text style={sx('text-3xl', 'font-bold', 'text-label')}>{appName}</Text>
|
|
12
|
+
<Text style={sx('mt-2', 'text-base', 'text-secondary-label')}>
|
|
13
|
+
Open app/index.tsx to start working on your app.
|
|
14
|
+
</Text>
|
|
137
15
|
</View>
|
|
138
16
|
)
|
|
139
17
|
}
|
|
@@ -1,13 +1,47 @@
|
|
|
1
1
|
import { chat, useChat, useChatList } from 'bleam/ai'
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Conversation,
|
|
5
|
+
ConversationContent,
|
|
6
|
+
ConversationEmptyState,
|
|
7
|
+
ConversationScrollButton,
|
|
8
|
+
Message,
|
|
9
|
+
MessageActions,
|
|
10
|
+
MessageContent,
|
|
11
|
+
MessageStatus,
|
|
12
|
+
MessageText,
|
|
13
|
+
PromptInput,
|
|
14
|
+
PromptInputFooter,
|
|
15
|
+
PromptInputSubmit,
|
|
16
|
+
PromptInputTextarea,
|
|
17
|
+
} from 'bleam/elements'
|
|
2
18
|
import { sx } from 'bleam/styles'
|
|
3
|
-
import { Button } from 'bleam/ui'
|
|
4
19
|
import { Window } from 'bleam/window'
|
|
5
|
-
import { useEffect, useRef, useState } from 'react'
|
|
6
|
-
import { Text,
|
|
20
|
+
import { Suspense, useEffect, useRef, useState } from 'react'
|
|
21
|
+
import { Text, View } from 'react-native'
|
|
7
22
|
|
|
8
23
|
const appName = 'Bleam Basic'
|
|
9
24
|
|
|
10
25
|
export default function App() {
|
|
26
|
+
return (
|
|
27
|
+
<View style={sx('flex-1', 'p-8', 'gap-6')}>
|
|
28
|
+
<Window title={appName} />
|
|
29
|
+
<Text style={sx('text-3xl', 'font-semibold')}>Foundation Models</Text>
|
|
30
|
+
<Text style={sx('text-secondary-label')}>
|
|
31
|
+
Chats persist on this Mac and use Apple Foundation Models by default.
|
|
32
|
+
</Text>
|
|
33
|
+
<Suspense
|
|
34
|
+
fallback={
|
|
35
|
+
<Text style={sx('text-secondary-label')}>Loading local chats...</Text>
|
|
36
|
+
}
|
|
37
|
+
>
|
|
38
|
+
<ChatSession />
|
|
39
|
+
</Suspense>
|
|
40
|
+
</View>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function ChatSession() {
|
|
11
45
|
const chats = useChatList()
|
|
12
46
|
const creating = useRef(false)
|
|
13
47
|
const [error, setError] = useState('')
|
|
@@ -25,15 +59,10 @@ export default function App() {
|
|
|
25
59
|
}, [chats.length])
|
|
26
60
|
|
|
27
61
|
return (
|
|
28
|
-
<View style={sx('flex-1'
|
|
29
|
-
<Window title={appName} />
|
|
30
|
-
<Text style={sx('text-3xl', 'font-semibold')}>Foundation Models</Text>
|
|
31
|
-
<Text style={sx('text-secondary-label')}>
|
|
32
|
-
Chats persist on this Mac and use Apple Foundation Models by default.
|
|
33
|
-
</Text>
|
|
62
|
+
<View style={sx('flex-1')}>
|
|
34
63
|
{error ? <Text style={sx('text-system-red')}>{error}</Text> : null}
|
|
35
64
|
{chats[0] ? (
|
|
36
|
-
<
|
|
65
|
+
<ChatConversation id={chats[0].id} />
|
|
37
66
|
) : (
|
|
38
67
|
<Text>Creating chat...</Text>
|
|
39
68
|
)}
|
|
@@ -41,7 +70,7 @@ export default function App() {
|
|
|
41
70
|
)
|
|
42
71
|
}
|
|
43
72
|
|
|
44
|
-
function
|
|
73
|
+
function ChatConversation({ id }: { id: string }) {
|
|
45
74
|
const conversation = useChat(id, {
|
|
46
75
|
system: 'You suggest practical, concise native Mac app ideas.',
|
|
47
76
|
})
|
|
@@ -56,39 +85,69 @@ function Conversation({ id }: { id: string }) {
|
|
|
56
85
|
: null
|
|
57
86
|
|
|
58
87
|
return (
|
|
59
|
-
<View style={sx('gap-4')}>
|
|
60
|
-
<
|
|
88
|
+
<View style={sx('flex-1', 'gap-4')}>
|
|
89
|
+
<Conversation>
|
|
90
|
+
<ConversationContent
|
|
91
|
+
data={conversation.messages}
|
|
92
|
+
keyExtractor={(message) => message.id}
|
|
93
|
+
ListEmptyComponent={
|
|
94
|
+
<ConversationEmptyState
|
|
95
|
+
title="Start a conversation"
|
|
96
|
+
description="Ask for a practical native Mac app idea."
|
|
97
|
+
/>
|
|
98
|
+
}
|
|
99
|
+
renderItem={({ item: message }) => (
|
|
100
|
+
<Message from={message.role}>
|
|
101
|
+
{message.content ? (
|
|
102
|
+
<MessageContent>
|
|
103
|
+
<MessageText>{message.content}</MessageText>
|
|
104
|
+
</MessageContent>
|
|
105
|
+
) : null}
|
|
106
|
+
{message.status !== 'completed' ? (
|
|
107
|
+
<MessageStatus status={message.status} />
|
|
108
|
+
) : null}
|
|
109
|
+
{retryable?.id === message.id ? (
|
|
110
|
+
<MessageActions>
|
|
111
|
+
<Button
|
|
112
|
+
label="Retry"
|
|
113
|
+
size="small"
|
|
114
|
+
variant="secondary"
|
|
115
|
+
onPress={() => void conversation.retry(message.id)}
|
|
116
|
+
/>
|
|
117
|
+
</MessageActions>
|
|
118
|
+
) : null}
|
|
119
|
+
</Message>
|
|
120
|
+
)}
|
|
121
|
+
/>
|
|
122
|
+
<ConversationScrollButton />
|
|
123
|
+
</Conversation>
|
|
124
|
+
|
|
125
|
+
<PromptInput
|
|
126
|
+
disabled={!conversation.canSend && !conversation.canCancel}
|
|
127
|
+
status={conversation.status}
|
|
61
128
|
value={prompt}
|
|
62
129
|
onChangeText={setPrompt}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
variant="secondary"
|
|
82
|
-
onPress={() => void conversation.retry(retryable.id)}
|
|
130
|
+
onSubmit={({ text }) => {
|
|
131
|
+
setPrompt('')
|
|
132
|
+
void conversation.send(text)
|
|
133
|
+
}}
|
|
134
|
+
>
|
|
135
|
+
<PromptInputTextarea />
|
|
136
|
+
<PromptInputFooter>
|
|
137
|
+
<View />
|
|
138
|
+
<PromptInputSubmit
|
|
139
|
+
disabled={!conversation.canCancel && !prompt.trim()}
|
|
140
|
+
onPress={({ text }) => {
|
|
141
|
+
if (conversation.canCancel) {
|
|
142
|
+
void conversation.cancel()
|
|
143
|
+
} else {
|
|
144
|
+
setPrompt('')
|
|
145
|
+
void conversation.send(text)
|
|
146
|
+
}
|
|
147
|
+
}}
|
|
83
148
|
/>
|
|
84
|
-
|
|
85
|
-
</
|
|
86
|
-
{conversation.messages.map((message) => (
|
|
87
|
-
<Text key={message.id} style={sx('text-lg', 'text-label')}>
|
|
88
|
-
{message.role === 'user' ? 'You: ' : 'Assistant: '}
|
|
89
|
-
{message.content || message.status}
|
|
90
|
-
</Text>
|
|
91
|
-
))}
|
|
149
|
+
</PromptInputFooter>
|
|
150
|
+
</PromptInput>
|
|
92
151
|
</View>
|
|
93
152
|
)
|
|
94
153
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { bonsai, image } from 'bleam/ai'
|
|
2
|
+
import { Button } from 'bleam/elements'
|
|
2
3
|
import { sx } from 'bleam/styles'
|
|
3
|
-
import { Button } from 'bleam/ui'
|
|
4
4
|
import { Window } from 'bleam/window'
|
|
5
5
|
import { useState } from 'react'
|
|
6
6
|
import { Image, Text, View } from 'react-native'
|
|
@@ -35,7 +35,7 @@ export default function App() {
|
|
|
35
35
|
<Image source={{ uri }} style={sx('w-96', 'h-96', 'rounded-xl')} />
|
|
36
36
|
) : null}
|
|
37
37
|
<Text style={sx('text-secondary-label')}>{status}</Text>
|
|
38
|
-
<Button
|
|
38
|
+
<Button label="Generate image" onPress={create} />
|
|
39
39
|
</View>
|
|
40
40
|
)
|
|
41
41
|
}
|
|
@@ -71,6 +71,8 @@ PODS:
|
|
|
71
71
|
- ExpoModulesWorklets (57.0.2):
|
|
72
72
|
- ExpoModulesCore
|
|
73
73
|
- ExpoModulesJSI
|
|
74
|
+
- ExpoSQLite (57.0.1):
|
|
75
|
+
- ExpoModulesCore
|
|
74
76
|
- FBLazyVector (0.86.0)
|
|
75
77
|
- hermes-engine (250829098.0.14):
|
|
76
78
|
- hermes-engine/Pre-built (= 250829098.0.14)
|
|
@@ -1932,6 +1934,7 @@ DEPENDENCIES:
|
|
|
1932
1934
|
- ExpoModulesCore (from `../node_modules/expo-modules-core`)
|
|
1933
1935
|
- ExpoModulesJSI (from `../node_modules/expo-modules-jsi/apple`)
|
|
1934
1936
|
- ExpoModulesWorklets (from `../node_modules/expo-modules-core`)
|
|
1937
|
+
- ExpoSQLite (from `../node_modules/expo-sqlite/ios`)
|
|
1935
1938
|
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
|
|
1936
1939
|
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
|
|
1937
1940
|
- "NativeScriptNativeApi (from `../node_modules/@nativescript/react-native`)"
|
|
@@ -2035,6 +2038,8 @@ EXTERNAL SOURCES:
|
|
|
2035
2038
|
:path: "../node_modules/expo-modules-jsi/apple"
|
|
2036
2039
|
ExpoModulesWorklets:
|
|
2037
2040
|
:path: "../node_modules/expo-modules-core"
|
|
2041
|
+
ExpoSQLite:
|
|
2042
|
+
:path: "../node_modules/expo-sqlite/ios"
|
|
2038
2043
|
FBLazyVector:
|
|
2039
2044
|
:path: "../node_modules/react-native/Libraries/FBLazyVector"
|
|
2040
2045
|
hermes-engine:
|
|
@@ -2202,6 +2207,7 @@ SPEC CHECKSUMS:
|
|
|
2202
2207
|
ExpoModulesCore: 747a01dfe7af61ad2e869f80bf983af1caa63378
|
|
2203
2208
|
ExpoModulesJSI: ef7f197a8e7eeb245557f560ade794bfc1abdc79
|
|
2204
2209
|
ExpoModulesWorklets: 0340ed9a30017f8597b90a1ef9aa210c43e44c4b
|
|
2210
|
+
ExpoSQLite: ddd65ed74bdebcff20f6766e682f9321ecb28ab8
|
|
2205
2211
|
FBLazyVector: b3e7ad108f0d882e30445c5527d774e3fd432f3d
|
|
2206
2212
|
hermes-engine: 6f298675a7f5d45e1a61a3c664a2b9618befb1e1
|
|
2207
2213
|
NativeScriptNativeApi: b35cf5bb2727adf20eb13d2b1bd8651d0698a362
|
|
@@ -9,9 +9,6 @@ import FoundationModels
|
|
|
9
9
|
|
|
10
10
|
public final class AIModule: Module {
|
|
11
11
|
@MainActor private let textGeneration = TextGenerationCoordinator()
|
|
12
|
-
private static var appGroupIdentifier: String {
|
|
13
|
-
Bundle.main.object(forInfoDictionaryKey: "AppGroupIdentifier") as? String ?? "group.dev.bleam.app"
|
|
14
|
-
}
|
|
15
12
|
|
|
16
13
|
public func definition() -> ModuleDefinition {
|
|
17
14
|
Name("AI")
|
|
@@ -382,13 +379,15 @@ public final class AIModule: Module {
|
|
|
382
379
|
|
|
383
380
|
private static func workerRequest(from request: FluxImageRequest) throws -> GenerationWorkerRequest {
|
|
384
381
|
let jobID = UUID()
|
|
385
|
-
guard let
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
382
|
+
guard let cacheDirectory = FileManager.default.urls(
|
|
383
|
+
for: .cachesDirectory,
|
|
384
|
+
in: .userDomainMask
|
|
385
|
+
).first else {
|
|
386
|
+
throw ModuleError.imageGeneration("Generation cache is unavailable")
|
|
389
387
|
}
|
|
390
388
|
|
|
391
|
-
let stagingDirectory =
|
|
389
|
+
let stagingDirectory = cacheDirectory
|
|
390
|
+
.appendingPathComponent("Bleam", isDirectory: true)
|
|
392
391
|
.appendingPathComponent("GenerationRuns", isDirectory: true)
|
|
393
392
|
.appendingPathComponent("bleam-generation-jobs", isDirectory: true)
|
|
394
393
|
.appendingPathComponent(jobID.uuidString, isDirectory: true)
|