arcane-os 0.60.0 → 0.62.0
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/CHANGELOG.md +40 -0
- package/README.md +1 -1
- package/browser-runtime/ai/core-image.mjs +392 -0
- package/docs/reference/local-image-editing.md +102 -16
- package/docs/reference/local-image-generation.md +267 -0
- package/docs/reference/model-assets.md +14 -11
- package/docs/reference/sdk-api.md +32 -0
- package/package.json +6 -1
- package/schemas/arcane-app.schema.json +2 -2
- package/schemas/arcane-package.schema.json +2 -2
- package/src/core/services/image.mjs +605 -0
- package/src/core/services/local-ai.mjs +8 -3
- package/src/import-map.mjs +2 -0
- package/src/local-ai/config.mjs +41 -1
- package/src/local-ai/dev.mjs +46 -9
- package/src/local-ai/image-library.mjs +985 -0
- package/src/local-ai/image-models/sd14.mjs +15 -0
- package/src/local-ai/image-png.mjs +74 -0
- package/src/local-ai/image-runtime.mjs +358 -0
- package/src/local-ai/image-worker.mjs +232 -0
- package/src/local-ai/install.mjs +326 -10
- package/src/native/portable-layout.mjs +28 -2
package/src/local-ai/config.mjs
CHANGED
|
@@ -2,9 +2,48 @@ import {readFile, writeFile} from 'node:fs/promises';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import Is from 'strong-type';
|
|
4
4
|
import {ArcaneError, ERROR_CODES, throwIfAborted} from '../errors.mjs';
|
|
5
|
+
import {SD14_MODEL} from './image-models/sd14.mjs';
|
|
5
6
|
|
|
6
7
|
const is = new Is(false);
|
|
7
|
-
export const LOCAL_AI_RUNTIME_IDS = ['llama.cpp', 'ollama', 'onnx'];
|
|
8
|
+
export const LOCAL_AI_RUNTIME_IDS = ['llama.cpp', 'ollama', 'onnx', 'stable-diffusion.cpp'];
|
|
9
|
+
|
|
10
|
+
/** Image requirements describe assets without acquiring or loading a model. */
|
|
11
|
+
export function normalizeImageRuntimeRequirement(record) {
|
|
12
|
+
const backend = record.backend ?? 'auto';
|
|
13
|
+
if (!['auto', 'metal', 'cpu'].includes(backend)) {
|
|
14
|
+
throw new ArcaneError(ERROR_CODES.usage, `Unknown stable-diffusion.cpp backend: ${String(backend)}.`);
|
|
15
|
+
}
|
|
16
|
+
if (record.models !== undefined && !is.array(record.models)) {
|
|
17
|
+
throw new ArcaneError(ERROR_CODES.usage, 'stable-diffusion.cpp models must be an array of model IDs or descriptors.');
|
|
18
|
+
}
|
|
19
|
+
const models = (record.models ?? []).map(
|
|
20
|
+
function selectedImageModel(value) {
|
|
21
|
+
const model = value === 'sd14' ? SD14_MODEL : value;
|
|
22
|
+
if (!model || !is.object(model) || is.array(model) || !is.string(model.id) || !model.id) {
|
|
23
|
+
throw new ArcaneError(ERROR_CODES.usage, 'An image model needs a descriptor with an id, or the built-in sd14 ID.');
|
|
24
|
+
}
|
|
25
|
+
if (!model.resources || !is.object(model.resources) || is.array(model.resources)) {
|
|
26
|
+
throw new ArcaneError(ERROR_CODES.usage, `Image model ${model.id} needs resources keyed by model role.`);
|
|
27
|
+
}
|
|
28
|
+
if (model.operations !== undefined && !is.array(model.operations)) {
|
|
29
|
+
throw new ArcaneError(ERROR_CODES.usage, `Image model ${model.id} operations must be an array.`);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
...model,
|
|
33
|
+
resources: {...model.resources},
|
|
34
|
+
context: {...model.context},
|
|
35
|
+
defaults: {...model.defaults},
|
|
36
|
+
operations: [...(model.operations ?? [])]
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
return {
|
|
41
|
+
...record,
|
|
42
|
+
version: record.version ?? 'master-929-3f8527a',
|
|
43
|
+
backend,
|
|
44
|
+
models
|
|
45
|
+
};
|
|
46
|
+
}
|
|
8
47
|
|
|
9
48
|
/** Runtime requirements are application configuration, separate from models. */
|
|
10
49
|
export function normalizeLocalAIConfig(value) {
|
|
@@ -17,6 +56,7 @@ export function normalizeLocalAIConfig(value) {
|
|
|
17
56
|
if (!record || !LOCAL_AI_RUNTIME_IDS.includes(record.id)) {
|
|
18
57
|
throw new ArcaneError(ERROR_CODES.usage, `Unknown local AI runtime: ${String(record?.id ?? item)}.`);
|
|
19
58
|
}
|
|
59
|
+
if (record.id === 'stable-diffusion.cpp') return normalizeImageRuntimeRequirement(record);
|
|
20
60
|
return {...record};
|
|
21
61
|
});
|
|
22
62
|
return {...value, runtimes};
|
package/src/local-ai/dev.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import Is from 'strong-type';
|
|
2
2
|
import {createCoreRuntime} from '../core/runtime.mjs';
|
|
3
3
|
import {createLocalAIService} from '../core/services/local-ai.mjs';
|
|
4
|
+
import {createLocalImageService} from '../core/services/image.mjs';
|
|
5
|
+
import {createModelAssetService} from '../core/services/model-assets.mjs';
|
|
4
6
|
import {CORE_PROTOCOL, CoreError, serializeCoreError} from '../../browser-runtime/core/contracts.mjs';
|
|
5
7
|
import {normalizeLocalAIConfig} from './config.mjs';
|
|
6
8
|
import {discoverLocalAIRuntimes} from './discover.mjs';
|
|
@@ -81,6 +83,8 @@ export function createDevelopmentLocalAI({config, appRoot, directory, applicatio
|
|
|
81
83
|
const incoming = new Set();
|
|
82
84
|
let runtime;
|
|
83
85
|
let service;
|
|
86
|
+
let imageService;
|
|
87
|
+
let modelAssets;
|
|
84
88
|
let stopFrames;
|
|
85
89
|
let preparationError = null;
|
|
86
90
|
let closing = null;
|
|
@@ -157,17 +161,49 @@ export function createDevelopmentLocalAI({config, appRoot, directory, applicatio
|
|
|
157
161
|
writeFrame(connection, event('core.state', current));
|
|
158
162
|
for (const record of current.services) writeFrame(connection, event('core.service.state', record));
|
|
159
163
|
writeFrame(connection, event('localai.state', service.current()));
|
|
164
|
+
if (imageService) writeFrame(connection, event('image.state', imageService.current()));
|
|
165
|
+
if (modelAssets) writeFrame(connection, event('modelAssets.state', modelAssets.current()));
|
|
160
166
|
}
|
|
161
167
|
|
|
162
|
-
const ready = Promise.resolve().then(
|
|
168
|
+
const ready = Promise.resolve().then(function prepareLocalAI() {
|
|
163
169
|
operationSignal.throwIfAborted();
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
170
|
+
const localConfig = {
|
|
171
|
+
...selected,
|
|
172
|
+
runtimes: selected.runtimes.filter(function selectedChatRuntime(requirement) {
|
|
173
|
+
return requirement.id !== 'stable-diffusion.cpp';
|
|
174
|
+
})
|
|
175
|
+
};
|
|
176
|
+
service = createLocalAIService(
|
|
177
|
+
localConfig,
|
|
178
|
+
{
|
|
179
|
+
appRoot, signal: operationSignal, onEvent,
|
|
180
|
+
async prepare({signal, onEvent: report}) {
|
|
181
|
+
const discovered = await discoverLocalAIRuntimes({config: localConfig, appRoot, signal});
|
|
182
|
+
const installed = await ensureLocalAIRuntimes({runtimes: discovered.missing, directory, signal, onEvent: report});
|
|
183
|
+
return [...discovered.available, ...installed];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
const services = [service];
|
|
188
|
+
if (selected.runtimes.some(function selectedImageRuntime(requirement) {
|
|
189
|
+
return requirement.id === 'stable-diffusion.cpp';
|
|
190
|
+
})) {
|
|
191
|
+
modelAssets = createModelAssetService({appRoot});
|
|
192
|
+
imageService = createLocalImageService(
|
|
193
|
+
selected,
|
|
194
|
+
{
|
|
195
|
+
appRoot, modelAssets, signal: operationSignal, onEvent,
|
|
196
|
+
async prepare({requirement, signal, onEvent: report}) {
|
|
197
|
+
const installed = await ensureLocalAIRuntimes(
|
|
198
|
+
{runtimes: [requirement], directory, signal, onEvent: report}
|
|
199
|
+
);
|
|
200
|
+
return installed[0];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
);
|
|
204
|
+
services.push(modelAssets, imageService);
|
|
205
|
+
}
|
|
206
|
+
runtime = createCoreRuntime({application, version, services});
|
|
171
207
|
stopFrames = runtime.onFrame(routeFrame);
|
|
172
208
|
runtime.start();
|
|
173
209
|
return runtime;
|
|
@@ -350,7 +386,8 @@ export function createDevelopmentLocalAI({config, appRoot, directory, applicatio
|
|
|
350
386
|
function current() {
|
|
351
387
|
return {state: closed ? 'closed' : preparationError ? 'error' : runtime ? 'ready' : 'preparing',
|
|
352
388
|
error: preparationError ? serializeCoreError(preparationError) : null,
|
|
353
|
-
core: runtime?.current() ?? null, localAI: service?.current() ?? null
|
|
389
|
+
core: runtime?.current() ?? null, localAI: service?.current() ?? null,
|
|
390
|
+
image: imageService?.current() ?? null};
|
|
354
391
|
}
|
|
355
392
|
|
|
356
393
|
function close() {
|