arcane-os 0.80.0 → 0.82.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 +44 -0
- package/README.md +1 -1
- package/browser-runtime/ai/browser-wasm-llm-provider.mjs +97 -19
- package/browser-runtime/ai/dbopfs-model-parts.mjs +12 -5
- package/browser-runtime/ai/dbopfs-model-resources.mjs +2 -5
- package/browser-runtime/core/app-control.mjs +439 -0
- package/docs/reference/ai/browser-speech.md +11 -0
- package/docs/reference/ai/browser-wasm.md +21 -10
- package/docs/reference/cli.md +9 -1
- package/docs/reference/core-native-packaging.md +14 -0
- package/docs/reference/inventory/package-api.json +23 -9
- package/docs/reference/inventory/runtime-components.json +2 -1
- package/docs/reference/native-app-control.md +147 -0
- package/docs/reference/native-decisions.md +74 -16
- package/docs/reference/runtime-components.md +20 -0
- package/docs/reference/sdk-api.md +49 -6
- package/package.json +2 -1
- package/runtime/arcane/components/chat.html +140 -18
- package/runtime/arcane/modules/AI.js +10 -5
- package/src/cli/app-control.mjs +106 -0
- package/src/cli/main.mjs +5 -0
- package/src/core/app-control.mjs +23 -0
- package/src/core/hosts/windows/ArcaneAppControl.cs +525 -0
- package/src/core/hosts/windows/ArcaneCoreProcess.cs +2 -63
- package/src/core/hosts/windows/ArcaneFrameTransport.cs +80 -0
- package/src/core/hosts/windows/ArcaneHost.cs +45 -7
- package/src/core/hosts/windows/ArcaneLauncher.cs +5 -0
- package/src/core/hosts/windows/ArcaneWindowControl.cs +248 -0
- package/src/core/services/decisions.mjs +16 -2
- package/src/core/shared-host.mjs +7 -91
- package/src/core/socket-connection.mjs +109 -0
- package/src/local-ai/decision-tokenizer-worker.mjs +1 -1
- package/src/local-ai/decision-tokenizer.mjs +2 -2
- package/src/local-ai/decisions.mjs +33 -10
package/src/core/shared-host.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {spawn} from 'node:child_process';
|
|
2
2
|
import {open} from 'node:fs/promises';
|
|
3
|
-
import {
|
|
3
|
+
import {createServer} from 'node:net';
|
|
4
4
|
import {randomUUID} from 'node:crypto';
|
|
5
|
-
import {createCoreClient} from '../../browser-runtime/core/client.mjs';
|
|
6
5
|
import {CORE_PROTOCOL, CoreError, serializeCoreError} from '../../browser-runtime/core/contracts.mjs';
|
|
7
6
|
import {createCoreRuntime} from './runtime.mjs';
|
|
8
7
|
import {createCoreFrameDecoder, encodeCoreFrame} from './stdio.mjs';
|
|
8
|
+
import {connectCoreSocket, createCoreSocketConnection, writeCoreSocket as write} from './socket-connection.mjs';
|
|
9
9
|
|
|
10
10
|
function failure(code, message) { return new CoreError({code, message}); }
|
|
11
11
|
function reportError(error) { console.error('Shared Arcane Core failed:', error); }
|
|
@@ -23,29 +23,6 @@ function response(id, result, error) {
|
|
|
23
23
|
time: new Date().toISOString()};
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// A stream write owns terminal events as well as its callback. Some destroyed
|
|
27
|
-
// streams never deliver that callback; retirement must still settle the write.
|
|
28
|
-
function write(output, content) {
|
|
29
|
-
return new Promise(function writeFrame(resolve, reject) {
|
|
30
|
-
let settled = false;
|
|
31
|
-
function finish(error) {
|
|
32
|
-
if (settled) return;
|
|
33
|
-
settled = true;
|
|
34
|
-
output.off('error', finish);
|
|
35
|
-
output.off('close', closed);
|
|
36
|
-
output.off('finish', closed);
|
|
37
|
-
if (error) reject(error);
|
|
38
|
-
else resolve();
|
|
39
|
-
}
|
|
40
|
-
function closed() { finish(failure('CORE_CONNECTION_CLOSED', 'The Core output closed during a write.')); }
|
|
41
|
-
output.once('error', finish);
|
|
42
|
-
output.once('close', closed);
|
|
43
|
-
output.once('finish', closed);
|
|
44
|
-
if (output.destroyed || output.writableEnded) { closed(); return; }
|
|
45
|
-
try { output.write(content, finish); } catch (error) { finish(error); }
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
26
|
/** Claim one app-selected pipe/socket before importing or creating services. */
|
|
50
27
|
export async function startSharedCoreHost({
|
|
51
28
|
endpoint, application, version, configure, getReplayEvents, signal, onError = reportError
|
|
@@ -268,29 +245,7 @@ export async function startSharedCoreHost({
|
|
|
268
245
|
}
|
|
269
246
|
|
|
270
247
|
function connectSocket(endpoint, signal) {
|
|
271
|
-
signal
|
|
272
|
-
if (typeof endpoint !== 'string' || !endpoint) throw new TypeError('A shared Core endpoint must be a nonempty local pipe/socket path.');
|
|
273
|
-
return new Promise(function connect(resolve, reject) {
|
|
274
|
-
const socket = createConnection({path: endpoint});
|
|
275
|
-
socket.pause();
|
|
276
|
-
function cleanup() {
|
|
277
|
-
signal?.removeEventListener('abort', abort);
|
|
278
|
-
socket.off('connect', connected);
|
|
279
|
-
socket.off('error', failed);
|
|
280
|
-
}
|
|
281
|
-
function failed(error) {
|
|
282
|
-
cleanup();
|
|
283
|
-
socket.on('error', reportError);
|
|
284
|
-
socket.destroy();
|
|
285
|
-
reject(error);
|
|
286
|
-
}
|
|
287
|
-
function abort() { failed(signal.reason); }
|
|
288
|
-
function connected() { cleanup(); resolve(socket); }
|
|
289
|
-
socket.once('connect', connected);
|
|
290
|
-
socket.once('error', failed);
|
|
291
|
-
signal?.addEventListener('abort', abort, {once: true});
|
|
292
|
-
if (signal?.aborted) abort();
|
|
293
|
-
});
|
|
248
|
+
return connectCoreSocket(endpoint, signal, reportError);
|
|
294
249
|
}
|
|
295
250
|
|
|
296
251
|
// The child retains its own listener and complete diagnostic file after the
|
|
@@ -354,49 +309,10 @@ function launchSelection(start) {
|
|
|
354
309
|
/** Connect/reuse, optionally starting an explicit independent headless entry. */
|
|
355
310
|
export async function connectSharedCoreHost({endpoint, start, signal, onError = reportError} = {}) {
|
|
356
311
|
const socket = await discover({endpoint, start: launchSelection(start), signal});
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
let resolveClosed;
|
|
362
|
-
let rejectClosed;
|
|
363
|
-
const closed = new Promise(function ownConnection(resolve, reject) { resolveClosed = resolve; rejectClosed = reject; });
|
|
364
|
-
closed.catch(function observeConnectionFailure() {});
|
|
365
|
-
function diagnostic(error) { report(onError, error); }
|
|
366
|
-
function failed(error) { client?.failTransport(error); socket.destroy(); rejectClosed(error); }
|
|
367
|
-
const decoder = createCoreFrameDecoder(function frame(value) { receive(value); });
|
|
368
|
-
socket.on('data', function data(chunk) { try { decoder.push(chunk); } catch (error) { failed(error); } });
|
|
369
|
-
socket.on('error', failed);
|
|
370
|
-
socket.on('end', function ended() {
|
|
371
|
-
try { decoder.finish(); } catch (error) { failed(error); }
|
|
372
|
-
});
|
|
373
|
-
socket.on('close', function disconnected() {
|
|
374
|
-
signal?.removeEventListener('abort', abort);
|
|
375
|
-
if (!closing) client?.failTransport(failure('CORE_CONNECTION_CLOSED', 'The shared Core connection closed.'));
|
|
376
|
-
resolveClosed();
|
|
377
|
-
});
|
|
378
|
-
const transport = {
|
|
379
|
-
name: 'shared-core',
|
|
380
|
-
subscribe(listener) {
|
|
381
|
-
receive = listener;
|
|
382
|
-
return function disconnect() {
|
|
383
|
-
closing = true;
|
|
384
|
-
writes.finally(function retireSocket() { socket.end(); }).catch(diagnostic);
|
|
385
|
-
};
|
|
386
|
-
},
|
|
387
|
-
send(frame) {
|
|
388
|
-
const content = encodeCoreFrame(frame);
|
|
389
|
-
writes = writes.then(function sendFrame() { return write(socket, content); });
|
|
390
|
-
writes.catch(failed);
|
|
391
|
-
return writes;
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
client = createCoreClient({transport, replayRuntimeState: true, onError: diagnostic});
|
|
395
|
-
function abort() { client.close(); }
|
|
396
|
-
signal?.addEventListener('abort', abort, {once: true});
|
|
397
|
-
if (signal?.aborted) abort();
|
|
398
|
-
socket.resume();
|
|
399
|
-
return {client, endpoint, closed, close: function close() { client.close(); return closed; },
|
|
312
|
+
const connection = createCoreSocketConnection({socket, endpoint, signal, onError,
|
|
313
|
+
replayRuntimeState: true, name: 'shared-core', closedMessage: 'The shared Core connection closed.'});
|
|
314
|
+
const {client, closed} = connection;
|
|
315
|
+
return {...connection,
|
|
400
316
|
async shutdown(options) {
|
|
401
317
|
const result = await client.invoke('core.host.shutdown', {}, options);
|
|
402
318
|
client.close();
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import {createConnection} from 'node:net';
|
|
2
|
+
import {createCoreClient} from '../../browser-runtime/core/client.mjs';
|
|
3
|
+
import {CoreError} from '../../browser-runtime/core/contracts.mjs';
|
|
4
|
+
import {createCoreFrameDecoder, encodeCoreFrame} from './stdio.mjs';
|
|
5
|
+
|
|
6
|
+
function failure(code, message) { return new CoreError({code, message}); }
|
|
7
|
+
function reportSocketError(error) { console.error('Arcane Core connection failed:', error); }
|
|
8
|
+
function report(observer, error) {
|
|
9
|
+
try {
|
|
10
|
+
Promise.resolve(observer(error)).catch(function observerFailed(cause) { console.error(cause, error); });
|
|
11
|
+
} catch (cause) { console.error(cause, error); }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Terminal events settle writes even when a destroyed stream omits its callback.
|
|
15
|
+
export function writeCoreSocket(output, content) {
|
|
16
|
+
return new Promise(function writeFrame(resolve, reject) {
|
|
17
|
+
let settled = false;
|
|
18
|
+
function finish(error) {
|
|
19
|
+
if (settled) return;
|
|
20
|
+
settled = true;
|
|
21
|
+
output.off('error', finish);
|
|
22
|
+
output.off('close', closed);
|
|
23
|
+
output.off('finish', closed);
|
|
24
|
+
if (error) reject(error);
|
|
25
|
+
else resolve();
|
|
26
|
+
}
|
|
27
|
+
function closed() { finish(failure('CORE_CONNECTION_CLOSED', 'The Core output closed during a write.')); }
|
|
28
|
+
output.once('error', finish);
|
|
29
|
+
output.once('close', closed);
|
|
30
|
+
output.once('finish', closed);
|
|
31
|
+
if (output.destroyed || output.writableEnded) { closed(); return; }
|
|
32
|
+
try { output.write(content, finish); } catch (error) { finish(error); }
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Connect once and pause incoming frames until their owner is attached. */
|
|
37
|
+
export function connectCoreSocket(endpoint, signal, onError = reportSocketError) {
|
|
38
|
+
signal?.throwIfAborted();
|
|
39
|
+
if (typeof endpoint !== 'string' || !endpoint) throw new TypeError('A shared Core endpoint must be a nonempty local pipe/socket path.');
|
|
40
|
+
return new Promise(function connect(resolve, reject) {
|
|
41
|
+
const socket = createConnection({path: endpoint});
|
|
42
|
+
socket.pause();
|
|
43
|
+
function cleanup() {
|
|
44
|
+
signal?.removeEventListener('abort', abort);
|
|
45
|
+
socket.off('connect', connected);
|
|
46
|
+
socket.off('error', failed);
|
|
47
|
+
}
|
|
48
|
+
function failed(error) {
|
|
49
|
+
cleanup();
|
|
50
|
+
socket.on('error', function connectionFailed(error) { report(onError, error); });
|
|
51
|
+
socket.destroy();
|
|
52
|
+
reject(error);
|
|
53
|
+
}
|
|
54
|
+
function abort() { failed(signal.reason); }
|
|
55
|
+
function connected() { cleanup(); resolve(socket); }
|
|
56
|
+
socket.once('connect', connected);
|
|
57
|
+
socket.once('error', failed);
|
|
58
|
+
signal?.addEventListener('abort', abort, {once: true});
|
|
59
|
+
if (signal?.aborted) abort();
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Own one connected socket; the caller decides which RPC methods to expose. */
|
|
64
|
+
export function createCoreSocketConnection({socket, endpoint, signal, onError = reportSocketError,
|
|
65
|
+
replayRuntimeState = false, name = 'core', closedMessage = 'The Core connection closed.'}) {
|
|
66
|
+
let client;
|
|
67
|
+
let receive;
|
|
68
|
+
let closing = false;
|
|
69
|
+
let writes = Promise.resolve();
|
|
70
|
+
let resolveClosed;
|
|
71
|
+
let rejectClosed;
|
|
72
|
+
const closed = new Promise(function ownConnection(resolve, reject) { resolveClosed = resolve; rejectClosed = reject; });
|
|
73
|
+
closed.catch(function observeConnectionFailure() {});
|
|
74
|
+
function diagnostic(error) { report(onError, error); }
|
|
75
|
+
function failed(error) { client?.failTransport(error); socket.destroy(); rejectClosed(error); }
|
|
76
|
+
const decoder = createCoreFrameDecoder(function frame(value) { receive(value); });
|
|
77
|
+
socket.on('data', function data(chunk) { try { decoder.push(chunk); } catch (error) { failed(error); } });
|
|
78
|
+
socket.on('error', failed);
|
|
79
|
+
socket.on('end', function ended() {
|
|
80
|
+
try { decoder.finish(); } catch (error) { failed(error); }
|
|
81
|
+
});
|
|
82
|
+
socket.on('close', function disconnected() {
|
|
83
|
+
signal?.removeEventListener('abort', abort);
|
|
84
|
+
if (!closing) client?.failTransport(failure('CORE_CONNECTION_CLOSED', closedMessage));
|
|
85
|
+
resolveClosed();
|
|
86
|
+
});
|
|
87
|
+
const transport = {
|
|
88
|
+
name,
|
|
89
|
+
subscribe(listener) {
|
|
90
|
+
receive = listener;
|
|
91
|
+
return function disconnect() {
|
|
92
|
+
closing = true;
|
|
93
|
+
writes.finally(function retireSocket() { socket.end(); }).catch(diagnostic);
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
send(frame) {
|
|
97
|
+
const content = encodeCoreFrame(frame);
|
|
98
|
+
writes = writes.then(function sendFrame() { return writeCoreSocket(socket, content); });
|
|
99
|
+
writes.catch(failed);
|
|
100
|
+
return writes;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
client = createCoreClient({transport, replayRuntimeState, onError: diagnostic});
|
|
104
|
+
function abort() { client.close(); }
|
|
105
|
+
signal?.addEventListener('abort', abort, {once: true});
|
|
106
|
+
if (signal?.aborted) abort();
|
|
107
|
+
socket.resume();
|
|
108
|
+
return {client, endpoint, closed, close: function close() { client.close(); return closed; }};
|
|
109
|
+
}
|
|
@@ -17,7 +17,7 @@ try {
|
|
|
17
17
|
};
|
|
18
18
|
parentPort.on('message', function encodeRequest({id, rows}) {
|
|
19
19
|
try {
|
|
20
|
-
const {encoded, pad} = encodeDecisionRows(interfaceAdapter, rows,
|
|
20
|
+
const {encoded, pad} = encodeDecisionRows(interfaceAdapter, rows, workerData.family);
|
|
21
21
|
const inputs = createDecisionInputs(encoded, pad);
|
|
22
22
|
parentPort.postMessage({id, result: inputs});
|
|
23
23
|
} catch (error) {
|
|
@@ -6,7 +6,7 @@ function cancelled() {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
/** One tokenizer worker owned by one native model activation. */
|
|
9
|
-
export function createDecisionTokenizer({tokenizerPath, tokenizerConfigPath, signal, onError}) {
|
|
9
|
+
export function createDecisionTokenizer({family = 'laya', tokenizerPath, tokenizerConfigPath, signal, onError}) {
|
|
10
10
|
signal?.throwIfAborted();
|
|
11
11
|
const pending = new Map();
|
|
12
12
|
let nextId = 0;
|
|
@@ -14,7 +14,7 @@ export function createDecisionTokenizer({tokenizerPath, tokenizerConfigPath, sig
|
|
|
14
14
|
let terminalError;
|
|
15
15
|
let exited = false;
|
|
16
16
|
const worker = new Worker(new URL('./decision-tokenizer-worker.mjs', import.meta.url), {
|
|
17
|
-
workerData: {tokenizerPath, tokenizerConfigPath}
|
|
17
|
+
workerData: {family, tokenizerPath, tokenizerConfigPath}
|
|
18
18
|
});
|
|
19
19
|
let resolveExit;
|
|
20
20
|
const exit = new Promise(function tokenizerExit(resolve) { resolveExit = resolve; });
|
|
@@ -5,7 +5,13 @@ import {decodeDecisionOutputs} from '../../browser-runtime/ai/decision-runtime.m
|
|
|
5
5
|
import {createDecisionTokenizer} from './decision-tokenizer.mjs';
|
|
6
6
|
|
|
7
7
|
const STATE_EVENT = 'ai.decisions.state';
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
function selectedGraph(family, dtype) {
|
|
10
|
+
if (family === 'laya' && dtype === 'fp32') return 'onnx/model.onnx';
|
|
11
|
+
if (family === 'laya' && dtype === 'fp16') return 'onnx/model_fp16.onnx';
|
|
12
|
+
if (family === 'julia' && dtype === 'fp32') return 'model.onnx';
|
|
13
|
+
throw new TypeError('Native decisions support Laya fp32/fp16 and Julia fp32 graph selections.');
|
|
14
|
+
}
|
|
9
15
|
|
|
10
16
|
function cancellation(message) {
|
|
11
17
|
return new CoreError({name: 'AbortError', code: 'ARCANE_AI_REQUEST_ABORTED', message});
|
|
@@ -18,6 +24,7 @@ function sameExecutionTarget(left, right) {
|
|
|
18
24
|
}
|
|
19
25
|
|
|
20
26
|
function sameActivation(left, right) {
|
|
27
|
+
if (left.family !== right.family || left.model !== right.model || left.revision !== right.revision || left.dtype !== right.dtype) return false;
|
|
21
28
|
if (!sameExecutionTarget(left.executionTarget, right.executionTarget) || left.assetProjectionId !== right.assetProjectionId) return false;
|
|
22
29
|
if (left.resourcePaths === right.resourcePaths) return true;
|
|
23
30
|
if (!left.resourcePaths || !right.resourcePaths) return false;
|
|
@@ -27,15 +34,15 @@ function sameActivation(left, right) {
|
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
/**
|
|
30
|
-
* One explicitly activated
|
|
37
|
+
* One explicitly activated typed-decision model using an existing native ONNX owner.
|
|
31
38
|
* It does not create another inference runtime or load on construction.
|
|
32
39
|
*/
|
|
33
40
|
export function createNativeDecisionModel({
|
|
34
41
|
onnx, modelAssets, workingDirectory, paths, assetProjectionId, resourcePaths,
|
|
35
|
-
model = 'onnx-community/laya-typed-decisions-ONNX', revision = 'main',
|
|
42
|
+
family = 'laya', model = 'onnx-community/laya-typed-decisions-ONNX', revision = 'main',
|
|
36
43
|
dtype = 'fp32', sessionOptions, executionPreference = 'gpu', executionTarget, signal
|
|
37
44
|
} = {}) {
|
|
38
|
-
|
|
45
|
+
selectedGraph(family, dtype);
|
|
39
46
|
const owner = {};
|
|
40
47
|
const events = createArcaneEventSource(owner, {source: 'native-decisions', eventTypes: [STATE_EVENT]});
|
|
41
48
|
const loads = new Set();
|
|
@@ -49,15 +56,17 @@ export function createNativeDecisionModel({
|
|
|
49
56
|
let lastError = null;
|
|
50
57
|
let execution = null;
|
|
51
58
|
let selectedActivation = {
|
|
52
|
-
executionTarget,
|
|
59
|
+
family, model, revision, dtype, executionTarget,
|
|
53
60
|
...(assetProjectionId == null ? {} : {assetProjectionId, resourcePaths: resourcePaths && {...resourcePaths}})
|
|
54
61
|
};
|
|
62
|
+
let activeSelection = selectedActivation;
|
|
55
63
|
let pendingActivation;
|
|
56
64
|
|
|
57
65
|
function current() {
|
|
58
66
|
const pending = pendingActivation && (state !== 'ready' || pendingActivation.entry !== activation) ? pendingActivation : null;
|
|
59
67
|
return {
|
|
60
|
-
family:
|
|
68
|
+
family: activeSelection.family, model: activeSelection.model,
|
|
69
|
+
revision: activeSelection.revision, dtype: activeSelection.dtype, state,
|
|
61
70
|
loaded: state === 'ready', busy: state === 'loading' || Boolean(pending) || Boolean(activation?.jobs.size),
|
|
62
71
|
activeRequests: activation?.jobs.size ?? 0, progress,
|
|
63
72
|
error: lastError ? serializeCoreError(lastError) : null,
|
|
@@ -163,10 +172,14 @@ export function createNativeDecisionModel({
|
|
|
163
172
|
}
|
|
164
173
|
if (paths) return paths;
|
|
165
174
|
if (!modelAssets) throw new CoreError({code: 'ARCANE_DECISION_ASSETS_UNAVAILABLE', message: 'Native decisions need prepared paths or the Core model-assets owner.'});
|
|
166
|
-
const
|
|
175
|
+
const {family: selectedFamily, model: selectedModel, revision: selectedRevision, dtype: selectedDtype} = entry.selection;
|
|
176
|
+
const graph = selectedGraph(selectedFamily, selectedDtype);
|
|
177
|
+
const companion = selectedFamily === 'laya' ? `${graph}_data` : `${graph}.data`;
|
|
178
|
+
const members = [graph, companion, 'tokenizer.json', 'tokenizer_config.json'];
|
|
179
|
+
const base = `https://huggingface.co/${selectedModel}/resolve/${encodeURIComponent(selectedRevision)}/`;
|
|
167
180
|
const projection = await modelAssets.prepare({
|
|
168
181
|
id: entry.id, workingDirectory,
|
|
169
|
-
members:
|
|
182
|
+
members: members.map(function selectFile(path) { return {path, url: new URL(path, base).href}; }),
|
|
170
183
|
signal: entry.controller.signal,
|
|
171
184
|
onProgress(value) { updateProgress(entry, value); }
|
|
172
185
|
});
|
|
@@ -176,7 +189,7 @@ export function createNativeDecisionModel({
|
|
|
176
189
|
await modelAssets.release(entry.id);
|
|
177
190
|
entry.prepared = false;
|
|
178
191
|
const files = Object.fromEntries(projection.members.map(function memberFile(member) { return [member.path, member.nativePath]; }));
|
|
179
|
-
return {model: files[
|
|
192
|
+
return {model: files[graph], tokenizer: files['tokenizer.json'], tokenizerConfig: files['tokenizer_config.json']};
|
|
180
193
|
}
|
|
181
194
|
|
|
182
195
|
function beginActivation(request) {
|
|
@@ -187,6 +200,7 @@ export function createNativeDecisionModel({
|
|
|
187
200
|
request.retained = undefined;
|
|
188
201
|
request.entry = entry;
|
|
189
202
|
activation = entry;
|
|
203
|
+
activeSelection = entry.selection;
|
|
190
204
|
state = 'loading';
|
|
191
205
|
progress = {phase: 'preparing-model'};
|
|
192
206
|
lastError = null;
|
|
@@ -196,6 +210,7 @@ export function createNativeDecisionModel({
|
|
|
196
210
|
entry.controller.signal.throwIfAborted();
|
|
197
211
|
updateProgress(entry, {phase: 'loading-model'});
|
|
198
212
|
entry.tokenizer = createDecisionTokenizer({
|
|
213
|
+
family: entry.selection.family,
|
|
199
214
|
tokenizerPath: files.tokenizer, tokenizerConfigPath: files.tokenizerConfig,
|
|
200
215
|
signal: entry.controller.signal,
|
|
201
216
|
onError(error) {
|
|
@@ -258,14 +273,22 @@ export function createNativeDecisionModel({
|
|
|
258
273
|
}).finally(function detachLoadCaller() { operationSignal?.removeEventListener('abort', abort); });
|
|
259
274
|
}
|
|
260
275
|
|
|
261
|
-
async function load({
|
|
276
|
+
async function load({
|
|
277
|
+
family: requestedFamily, model: requestedModel, revision: requestedRevision, dtype: requestedDtype,
|
|
278
|
+
signal: operationSignal, executionTarget: requestedTarget, assetProjectionId: requestedProjection, resourcePaths: requestedPaths
|
|
279
|
+
} = {}) {
|
|
262
280
|
assertOpen(operationSignal);
|
|
263
281
|
const projection = requestedProjection === undefined ? selectedActivation.assetProjectionId : requestedProjection;
|
|
264
282
|
const mapping = requestedPaths === undefined ? selectedActivation.resourcePaths : requestedPaths;
|
|
265
283
|
const selection = {
|
|
284
|
+
family: requestedFamily === undefined ? selectedActivation.family : requestedFamily,
|
|
285
|
+
model: requestedModel === undefined ? selectedActivation.model : requestedModel,
|
|
286
|
+
revision: requestedRevision === undefined ? selectedActivation.revision : requestedRevision,
|
|
287
|
+
dtype: requestedDtype === undefined ? selectedActivation.dtype : requestedDtype,
|
|
266
288
|
executionTarget: requestedTarget === undefined ? selectedActivation.executionTarget : requestedTarget,
|
|
267
289
|
...(projection == null ? {} : {assetProjectionId: projection, resourcePaths: mapping && typeof mapping === 'object' && !Array.isArray(mapping) ? {...mapping} : mapping})
|
|
268
290
|
};
|
|
291
|
+
selectedGraph(selection.family, selection.dtype);
|
|
269
292
|
if (pendingActivation && !pendingActivation.controller.signal.aborted && sameActivation(pendingActivation.selection, selection)) {
|
|
270
293
|
return observeLoad(pendingActivation, operationSignal);
|
|
271
294
|
}
|