arcane-os 0.95.0 → 0.97.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 +32 -0
- package/README.md +1 -1
- package/browser-runtime/ai/core-model-assets.mjs +79 -0
- package/docs/reference/README.md +14 -0
- package/docs/reference/ai/browser-speech.md +61 -10
- package/docs/reference/core-client.md +35 -0
- package/docs/reference/core-native-packaging.md +51 -9
- package/docs/reference/inventory/package-api.json +239 -15
- package/docs/reference/inventory/runtime-modules.json +39 -13
- package/docs/reference/model-assets.md +219 -23
- package/docs/reference/native-speech.md +128 -4
- package/docs/reference/runtime-modules.md +157 -11
- package/docs/reference/sdk-api.md +475 -18
- package/package.json +3 -3
- package/src/core/host.mjs +22 -17
- package/src/core/services/local-ai.mjs +46 -12
- package/src/core/services/model-assets.mjs +885 -96
- package/src/core/services/speech.mjs +2 -2
- package/src/local-ai/nemo-models.mjs +160 -0
- package/src/local-ai/nemotron/index.mjs +63 -7
- package/src/native/macos-provider.mjs +14 -7
- package/src/native/portable-assembly.mjs +180 -0
- package/src/native/portable-provider.mjs +17 -161
- package/src/native/publish-output.mjs +101 -0
- package/src/native/windows-provider.mjs +12 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arcane-os",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.97.0",
|
|
4
4
|
"description": "Arcane OS JavaScript SDK, project-local CLI, browser runtime, and repository-portable application packager.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.mjs",
|
|
@@ -137,8 +137,8 @@
|
|
|
137
137
|
"test": "npm run test:unit && npm run test:functional && npm run test:integration && npm run test:regression",
|
|
138
138
|
"test:release": "node ./bin/arcane-test.mjs test/npm-release.test.mjs",
|
|
139
139
|
"test:unit": "node ./bin/arcane-test.mjs test/app-descriptor.test.mjs test/app-schema.test.mjs test/app-selection.test.mjs test/contracts.test.mjs test/conversation-closing-report.test.mjs test/doctor.test.mjs test/mail-credentials.test.mjs test/mail-outbox.test.mjs test/mail-public-api.test.mjs test/mail-send.test.mjs test/mail-transport.test.mjs test/native-windows-icon.test.mjs test/risk-signal-analyzer.test.mjs test/targets.test.mjs test/workspace-operation-lock.test.mjs",
|
|
140
|
-
"test:functional": "node ./bin/arcane-test.mjs test/ai-ollama-readiness.test.mjs test/core-ollama-lifecycle.test.mjs test/ai-request-model.test.mjs test/ai-request-retry.test.mjs test/ai-stream-cancellation.test.mjs test/browser-decisions.test.mjs test/browser-kokoro-complete-input.test.mjs test/browser-speech-providers.test.mjs test/browser-speech-artifacts.test.mjs test/browser-speech-resource-bridge.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/chat-input.test.mjs test/chat-stream-speech.test.mjs test/chat-transcript-scroll.test.mjs test/chat-transient-retention.test.mjs test/cli.test.mjs test/continuous-voice-capture.test.mjs test/codex-app-server.test.mjs test/mcp-stdio-server.test.mjs test/core-classic-source.test.mjs test/core-client.test.mjs test/core-client-installation.test.mjs test/core-ai-installation.test.mjs test/core-llama-lifecycle.test.mjs test/core-development.test.mjs test/core-host.test.mjs test/core-shared-host.test.mjs test/core-model-assets.test.mjs test/core-native-services.test.mjs test/core-packaged-web.test.mjs test/core-runtime.test.mjs test/core-stdio.test.mjs test/dbopfs-committed-events.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs-model-resources.test.mjs test/dbopfs-png.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/document-acquisition.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/execution-devices.test.mjs test/file-preview.test.mjs test/import-map.test.mjs test/local-image-editing.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/markdown-editor.test.mjs test/markdown-media.test.mjs test/markdown-source-map.test.mjs test/modal.test.mjs test/model-resource-bridge.test.mjs test/native-decisions.test.mjs test/native-onnx.test.mjs test/native-module-packaging.test.mjs test/native-module-resource-references.test.mjs test/packaging.test.mjs test/pwa-packaging.test.mjs test/pwa-client.test.mjs test/pwa-install.test.mjs test/pwa-worker.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/rendered-print.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/theme-manager.test.mjs test/twin-cloud-images.test.mjs test/twin-cloud.test.mjs test/websocket-client-import-map.test.mjs test/websocket.test.mjs test/update-check.test.mjs test/user-explicit-updates.test.mjs",
|
|
141
|
-
"test:integration": "node ./bin/arcane-test.mjs test/installed-package-runtime.test.mjs test/root-app-layout.test.mjs test/integrated-shared.test.mjs test/integrated-workspace.test.mjs test/mail-browser.test.mjs test/native-macos-provider.test.mjs test/native-plan.test.mjs test/native-portable-provider.test.mjs test/native-provider-loader.test.mjs test/npm-release.test.mjs test/release-bundle.test.mjs test/release-capability-smoke.test.mjs test/shared-payload-batch.test.mjs test/tarball.test.mjs test/browser-wasm-cpu.test.mjs test/wllama-webgpu-runtime.test.mjs",
|
|
140
|
+
"test:functional": "node ./bin/arcane-test.mjs test/ai-ollama-readiness.test.mjs test/core-ollama-lifecycle.test.mjs test/ai-request-model.test.mjs test/ai-request-retry.test.mjs test/ai-stream-cancellation.test.mjs test/browser-decisions.test.mjs test/browser-kokoro-complete-input.test.mjs test/browser-speech-providers.test.mjs test/browser-speech-artifacts.test.mjs test/browser-speech-resource-bridge.test.mjs test/browser-wasm-gpu-notice.test.mjs test/browser-wasm-download-resume.test.mjs test/chat-input.test.mjs test/chat-stream-speech.test.mjs test/chat-transcript-scroll.test.mjs test/chat-transient-retention.test.mjs test/cli.test.mjs test/continuous-voice-capture.test.mjs test/codex-app-server.test.mjs test/mcp-stdio-server.test.mjs test/core-classic-source.test.mjs test/core-client.test.mjs test/core-client-installation.test.mjs test/core-ai-installation.test.mjs test/core-llama-lifecycle.test.mjs test/core-development.test.mjs test/core-host.test.mjs test/core-shared-host.test.mjs test/core-model-assets.test.mjs test/core-native-services.test.mjs test/core-packaged-web.test.mjs test/core-runtime.test.mjs test/core-stdio.test.mjs test/dbopfs-committed-events.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs-model-resources.test.mjs test/dbopfs-png.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/document-acquisition.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.test.mjs test/execution-devices.test.mjs test/file-preview.test.mjs test/import-map.test.mjs test/local-image-editing.test.mjs test/mail-cli.test.mjs test/mail-runtime.test.mjs test/mail-server.test.mjs test/markdown-editor.test.mjs test/markdown-media.test.mjs test/markdown-source-map.test.mjs test/modal.test.mjs test/model-resource-bridge.test.mjs test/nemo-models.test.mjs test/native-decisions.test.mjs test/native-onnx.test.mjs test/native-module-packaging.test.mjs test/native-module-resource-references.test.mjs test/packaging.test.mjs test/pwa-packaging.test.mjs test/pwa-client.test.mjs test/pwa-install.test.mjs test/pwa-worker.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/rendered-print.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/theme-manager.test.mjs test/twin-cloud-images.test.mjs test/twin-cloud.test.mjs test/websocket-client-import-map.test.mjs test/websocket.test.mjs test/update-check.test.mjs test/user-explicit-updates.test.mjs",
|
|
141
|
+
"test:integration": "node ./bin/arcane-test.mjs test/installed-package-runtime.test.mjs test/root-app-layout.test.mjs test/integrated-shared.test.mjs test/integrated-workspace.test.mjs test/mail-browser.test.mjs test/native-macos-provider.test.mjs test/native-plan.test.mjs test/native-portable-provider.test.mjs test/native-provider-loader.test.mjs test/native-publish-output.test.mjs test/npm-release.test.mjs test/release-bundle.test.mjs test/release-capability-smoke.test.mjs test/shared-payload-batch.test.mjs test/tarball.test.mjs test/browser-wasm-cpu.test.mjs test/wllama-webgpu-runtime.test.mjs",
|
|
142
142
|
"test:regression": "node ./bin/arcane-test.mjs test/channel-workflows.test.mjs test/html-import-registration.test.mjs test/html-import-packaged-script.test.mjs test/logging-regression.test.mjs test/markdown-speech.test.mjs test/prepared-speech.test.mjs test/ai-audio-output.test.mjs test/native-provider-generation.test.mjs test/speech-queue-regression.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
|
|
143
143
|
"check": "node tools/check-source.mjs && npm test",
|
|
144
144
|
"check:release": "node tools/check-source.mjs --package-only && npm run test:release",
|
package/src/core/host.mjs
CHANGED
|
@@ -9,36 +9,41 @@ export {startCoreListener, startSharedCoreHost, connectSharedCoreHost, runShared
|
|
|
9
9
|
|
|
10
10
|
const is = new Is(false);
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
function userDataDirectory() {
|
|
13
|
+
const home = homedir();
|
|
14
|
+
switch (process.platform) {
|
|
15
|
+
case 'win32': return process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local');
|
|
16
|
+
case 'darwin': return path.join(home, 'Library', 'Application Support');
|
|
17
|
+
case 'linux': {
|
|
18
|
+
const xdg = process.env.XDG_DATA_HOME;
|
|
19
|
+
return xdg && path.isAbsolute(xdg) ? xdg : path.join(home, '.local', 'share');
|
|
20
|
+
}
|
|
21
|
+
default: return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Resolve app-private state and same-user shared models without moving data. */
|
|
13
26
|
export function resolveNativeLaunchContext({appId, context = {}} = {}) {
|
|
14
27
|
if (!is.string(appId) || !appId) throw new TypeError('Native launch resolution requires an appId.');
|
|
15
28
|
if (context === null || !is.object(context) || is.array(context)) {
|
|
16
29
|
throw new TypeError('Native launch context must be an object.');
|
|
17
30
|
}
|
|
31
|
+
const userDirectory = userDataDirectory();
|
|
18
32
|
let stateRoot = context.stateRoot;
|
|
19
33
|
if (stateRoot === undefined) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
case 'win32':
|
|
23
|
-
stateRoot = path.join(process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local'), 'Arcane', appId);
|
|
24
|
-
break;
|
|
25
|
-
case 'darwin':
|
|
26
|
-
stateRoot = path.join(home, 'Library', 'Application Support', 'Arcane', appId);
|
|
27
|
-
break;
|
|
28
|
-
case 'linux': {
|
|
29
|
-
const xdg = process.env.XDG_DATA_HOME;
|
|
30
|
-
stateRoot = path.join(xdg && path.isAbsolute(xdg) ? xdg : path.join(home, '.local', 'share'), 'Arcane', appId);
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
default:
|
|
34
|
-
throw new TypeError('This native host must supply its persistent stateRoot.');
|
|
35
|
-
}
|
|
34
|
+
if (!userDirectory) throw new TypeError('This native host must supply its persistent stateRoot.');
|
|
35
|
+
stateRoot = path.join(userDirectory, 'Arcane', appId);
|
|
36
36
|
}
|
|
37
37
|
if (!is.string(stateRoot) || !stateRoot) throw new TypeError('Native stateRoot must be a nonempty directory path.');
|
|
38
38
|
const root = path.resolve(stateRoot);
|
|
39
39
|
const resolved = {
|
|
40
40
|
...context,
|
|
41
41
|
stateRoot,
|
|
42
|
+
// Model files are reusable resources; preferences, profiles and chat stay
|
|
43
|
+
// under the application's stateRoot. Other hosts supply their shared path.
|
|
44
|
+
modelsDirectory: context.modelsDirectory === undefined
|
|
45
|
+
? userDirectory ? path.join(userDirectory, 'Arcane', 'Models') : path.join(root, 'Models')
|
|
46
|
+
: context.modelsDirectory,
|
|
42
47
|
workspaceRoot: context.workspaceRoot === undefined ? path.join(root, 'Workspace') : context.workspaceRoot
|
|
43
48
|
};
|
|
44
49
|
if (context.sharedHost !== undefined) {
|
|
@@ -121,7 +121,7 @@ function collectCompletion(completion, chunk) {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
/** Core owns native processes; applications own runtime and model selection. */
|
|
124
|
-
export function createLocalAIService(configuration, {appRoot, runtimes = [], signal, onEvent, prepare, executionDevices} = {}) {
|
|
124
|
+
export function createLocalAIService(configuration, {appRoot, runtimes = [], signal, onEvent, prepare, executionDevices, autoStart = true} = {}) {
|
|
125
125
|
const config = normalizeLocalAIConfig(configuration) ?? {runtimes: []};
|
|
126
126
|
const lifetime = new AbortController();
|
|
127
127
|
const lifetimeSignal = signal ? AbortSignal.any([signal, lifetime.signal]) : lifetime.signal;
|
|
@@ -130,6 +130,8 @@ export function createLocalAIService(configuration, {appRoot, runtimes = [], sig
|
|
|
130
130
|
const owner = {};
|
|
131
131
|
const events = createArcaneEventSource(owner, {source: 'core-local-ai', eventTypes: ['localai.state']});
|
|
132
132
|
let context;
|
|
133
|
+
let preparing;
|
|
134
|
+
let prepared = false;
|
|
133
135
|
let modelAssetOwner;
|
|
134
136
|
let closed = false;
|
|
135
137
|
let onnx;
|
|
@@ -738,17 +740,20 @@ export function createLocalAIService(configuration, {appRoot, runtimes = [], sig
|
|
|
738
740
|
});
|
|
739
741
|
}
|
|
740
742
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
async
|
|
748
|
-
|
|
743
|
+
function prepareEngines(requestSignal) {
|
|
744
|
+
lifetimeSignal.throwIfAborted();
|
|
745
|
+
requestSignal?.throwIfAborted();
|
|
746
|
+
if (prepared) return Promise.resolve(snapshot());
|
|
747
|
+
if (preparing) return awaitReadiness(preparing, requestSignal ?? lifetimeSignal);
|
|
748
|
+
const operationSignal = requestSignal ? AbortSignal.any([lifetimeSignal, requestSignal]) : lifetimeSignal;
|
|
749
|
+
const task = Promise.resolve().then(async function prepareSelectedEngines() {
|
|
750
|
+
operationSignal.throwIfAborted();
|
|
749
751
|
if (prepare) {
|
|
750
|
-
runtimes = await prepare({signal:
|
|
751
|
-
|
|
752
|
+
runtimes = await prepare({signal: operationSignal, onEvent: function preparationProgress(event) {
|
|
753
|
+
context?.emit('localai.preparation', event);
|
|
754
|
+
return onEvent?.(event);
|
|
755
|
+
}});
|
|
756
|
+
operationSignal.throwIfAborted();
|
|
752
757
|
onnxRecord = runtimes.find(function installedONNX(runtime) { return runtime.id === 'onnx'; });
|
|
753
758
|
}
|
|
754
759
|
for (const requirement of config.runtimes) {
|
|
@@ -764,11 +769,40 @@ export function createLocalAIService(configuration, {appRoot, runtimes = [], sig
|
|
|
764
769
|
state: {id: requirement.id, installed: runtimes.some(function installed(record) { return record.id === requirement.id && record.executable; }), available: false, state: 'starting'}
|
|
765
770
|
};
|
|
766
771
|
engines.set(engine.id, engine);
|
|
767
|
-
startEngine(engine);
|
|
772
|
+
try { startEngine(engine); }
|
|
773
|
+
catch (error) {
|
|
774
|
+
engines.delete(engine.id);
|
|
775
|
+
throw error;
|
|
776
|
+
}
|
|
768
777
|
}
|
|
769
778
|
publish();
|
|
779
|
+
prepared = true;
|
|
780
|
+
});
|
|
781
|
+
preparing = task;
|
|
782
|
+
jobs.add(task);
|
|
783
|
+
function releasePreparation() {
|
|
784
|
+
jobs.delete(task);
|
|
785
|
+
if (preparing === task) preparing = null;
|
|
786
|
+
}
|
|
787
|
+
task.then(releasePreparation, releasePreparation);
|
|
788
|
+
return task;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
const service = {
|
|
792
|
+
name: 'local-ai',
|
|
793
|
+
current: snapshot,
|
|
794
|
+
getONNXRuntime() {
|
|
795
|
+
return requireONNX();
|
|
796
|
+
},
|
|
797
|
+
async start(currentContext) {
|
|
798
|
+
context = currentContext;
|
|
799
|
+
if (autoStart === false) return;
|
|
800
|
+
return prepareEngines(lifetimeSignal);
|
|
770
801
|
},
|
|
771
802
|
methods: {
|
|
803
|
+
'localai.prepare': function prepareSelectedRuntime(_parameters, request) {
|
|
804
|
+
return prepareEngines(request.signal).then(snapshot);
|
|
805
|
+
},
|
|
772
806
|
'localai.services.recover': async function recoverServices({runtimes: selected = [...engines.keys(), ...(onnxSelected ? ['onnx'] : [])]} = {}, request) {
|
|
773
807
|
request.signal.throwIfAborted();
|
|
774
808
|
const selectedEngines = selected.map(function selectedEngine(id) {
|