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
|
@@ -110,17 +110,18 @@ try {
|
|
|
110
110
|
}
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
`prepare({id,workingDirectory,members,signal,onProgress,refresh=false})` reuses
|
|
113
|
+
`prepare({id,workingDirectory,members,archives,signal,onProgress,refresh=false})` reuses
|
|
114
114
|
a complete native acquisition or fetches the explicitly selected members.
|
|
115
115
|
Every member has its original relative `path` and selected `url`; the caller
|
|
116
116
|
supplies the complete companion-file set. Independent members download
|
|
117
|
-
concurrently. Each complete response stream is written directly to its native
|
|
117
|
+
concurrently, with up to four independent source transfers active. Each complete response stream is written directly to its native
|
|
118
118
|
file, without a whole-model buffer or base64 conversion. No model or runtime
|
|
119
119
|
is selected or downloaded by service startup. The result remains the ready
|
|
120
120
|
projection snapshot with ordered `members: [{path,nativePath}]`.
|
|
121
121
|
|
|
122
|
-
Complete acquisitions persist under
|
|
123
|
-
release, native unload, service disposal
|
|
122
|
+
Complete acquisitions and interrupted transfer state persist under
|
|
123
|
+
`workingDirectory/model-assets/` across release, native unload, service disposal
|
|
124
|
+
and process restart. Relative working
|
|
124
125
|
directories resolve from `appRoot`. Reuse matches the entire ordered
|
|
125
126
|
`[{path,url}]` selection in that actual store; the operation `id` is a separate
|
|
126
127
|
live lifetime, not the stored selection. Different URLs, relative paths, member
|
|
@@ -136,14 +137,193 @@ untouched. Later ordinary preparations reuse the newer completed selection.
|
|
|
136
137
|
A failed refresh leaves the earlier completed acquisition available. Refresh
|
|
137
138
|
does not change the selected URLs or imply upstream revision discovery.
|
|
138
139
|
|
|
139
|
-
Progress
|
|
140
|
-
`
|
|
141
|
-
|
|
140
|
+
Progress includes `open`, `download`, `resume`, `restart`, `complete`, `reuse`
|
|
141
|
+
and `ready`, plus waiting, heartbeat, stalled and terminal interruption states.
|
|
142
|
+
Records carry `state`, a user-facing `message`, `completed`, `total` and
|
|
143
|
+
`unit:'files'`; member progress additionally includes `memberIndex` and `path`.
|
|
144
|
+
Recovery guidance belongs in `recovery`; a complete serialized `error` belongs
|
|
145
|
+
in developer inspection. A stalled state means no recent transfer activity was
|
|
146
|
+
observed, not that the SDK has established an Internet outage. Render active
|
|
147
|
+
transfers without inventing a per-file percentage. Progress callbacks may return a promise, which the
|
|
142
148
|
preparation observes in order. Each caller owns its callbacks; a slow or failed
|
|
143
149
|
callback does not hold another caller's transfer or result. Callbacks must not
|
|
144
150
|
await cleanup of the preparation currently calling them. Callback failures
|
|
145
151
|
reject that caller's preparation. HTTP failures
|
|
146
152
|
retain `url`, `status` and the complete response text in `response`.
|
|
153
|
+
During an active member, repeated activity notifications are emitted at most
|
|
154
|
+
once per second; opening, member completion and terminal phases remain distinct.
|
|
155
|
+
Progress describes files and phases, never transfer volume.
|
|
156
|
+
|
|
157
|
+
### Selected archive companions
|
|
158
|
+
|
|
159
|
+
An optional `archives` array acquires exact companion members from an upstream
|
|
160
|
+
uncompressed TAR source through this same acquisition owner:
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
const projection = await modelAssets.prepare({
|
|
164
|
+
id: selectedOperationId,
|
|
165
|
+
workingDirectory: selectedModelDirectory,
|
|
166
|
+
members: selectedModelFiles,
|
|
167
|
+
archives: [{
|
|
168
|
+
url: selectedArchiveURL,
|
|
169
|
+
format: 'tar',
|
|
170
|
+
members: [
|
|
171
|
+
{path: 'tokenizer/model_config.yaml', member: 'model_config.yaml'},
|
|
172
|
+
{path: 'tokenizer/speakers.json', member: 'speakers.json'}
|
|
173
|
+
]
|
|
174
|
+
}],
|
|
175
|
+
signal,
|
|
176
|
+
onProgress
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The result orders ordinary members first, followed by each archive's declared
|
|
181
|
+
members. Extraction preserves each complete selected file. TAR names and PAX
|
|
182
|
+
path records select members; a leading `./` is archive path framing. Missing
|
|
183
|
+
selected members reject preparation and identify the missing names. Gzip and
|
|
184
|
+
other archive formats are outside this reader's contract.
|
|
185
|
+
|
|
186
|
+
When the upstream catalog supplies aligned TAR segments, an archive may include
|
|
187
|
+
`ranges:[{start,end,stopBefore?}]`. The reader requests each inclusive HTTP range
|
|
188
|
+
once and parses its TAR framing; `stopBefore` ends that segment before the
|
|
189
|
+
specified member. Offsets and TAR lengths are solely external transport framing.
|
|
190
|
+
They are never download progress, model readiness criteria or content identity.
|
|
191
|
+
Ranges require the matching HTTP partial-content response; no complete-archive
|
|
192
|
+
fallback is silently substituted. Native reuse identifies archive members by
|
|
193
|
+
their selected URL, archive member name and output path, alongside ordinary
|
|
194
|
+
members, without re-fetching an already completed set.
|
|
195
|
+
|
|
196
|
+
## Discover and open installed files
|
|
197
|
+
|
|
198
|
+
`discover({directories,catalog=[],recursive=true,signal})` inspects only the
|
|
199
|
+
explicit directories, without downloading, copying, loading or selecting a
|
|
200
|
+
model. Paths resolve from `appRoot`. It returns:
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
{
|
|
204
|
+
directories: [{directory, exists, error}], // error is present only on failure
|
|
205
|
+
models: [{
|
|
206
|
+
directory,
|
|
207
|
+
entryPath,
|
|
208
|
+
members: [{path, nativePath, available}],
|
|
209
|
+
missingMembers: [],
|
|
210
|
+
complete: true,
|
|
211
|
+
source: 'directory', // or 'catalog' or 'acquisition'
|
|
212
|
+
catalogId // present for a matching caller-owned catalog entry
|
|
213
|
+
}]
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Ordinary `.gguf` files are candidates. Split names such as
|
|
218
|
+
`moon-00001-of-00003.gguf` form one candidate with all expected members in numeric
|
|
219
|
+
order, including explicit missing members. The first shard is `entryPath`,
|
|
220
|
+
including when a completed acquisition declared only later shards or listed
|
|
221
|
+
them out of order. Acquisition candidates retain all their ordinary and
|
|
222
|
+
companion members alongside these required shards; separate filename groups
|
|
223
|
+
are never inferred to be one model. Symlinked model files and directories are
|
|
224
|
+
followed, with already visited directory targets reused rather than rescanned.
|
|
225
|
+
Discovery does not establish a model's role, runtime compatibility or successful
|
|
226
|
+
inference. Those selections remain with the application and engine owners.
|
|
227
|
+
|
|
228
|
+
Catalog entries are `{id,members:[{path,url?}],archives?,entryPath?}`. They describe
|
|
229
|
+
an exact companion set and can include nested tokenizer files or multiple model
|
|
230
|
+
files. A discovered catalog candidate reports every expected member, including
|
|
231
|
+
missing companions. Completed native acquisition records are also discoverable;
|
|
232
|
+
when the catalog supplies URLs or archive member names, acquisition matching
|
|
233
|
+
also preserves those recorded source selections. A different pinned source with
|
|
234
|
+
the same filenames is not relabeled as that catalog selection. Path-only catalogs
|
|
235
|
+
and ordinary installed-directory candidates make no source-revision claim.
|
|
236
|
+
Unfinished acquisition attempts are ignored. Discovery never removes either.
|
|
237
|
+
Set `recursive:false` for a directory-only inspection. Missing root directories
|
|
238
|
+
are reported with `exists:false`; other root access failures include their
|
|
239
|
+
complete serialized error. A failure while reading a descendant is surfaced.
|
|
240
|
+
|
|
241
|
+
`openExisting({id,directory,members:[{path}],signal})` opens a complete selected
|
|
242
|
+
set as an ordinary ready projection. It rechecks every member and reports
|
|
243
|
+
`MODEL_ASSET_MEMBERS_MISSING` with `members` when files are absent. It performs
|
|
244
|
+
no copy or network request. Engines use the same `retain(id)` lifecycle.
|
|
245
|
+
Preparation release, engine unload and service disposal never delete borrowed
|
|
246
|
+
originals. External edits or deletion remain controlled by the files' owner.
|
|
247
|
+
|
|
248
|
+
The application supplies persistent model directories separately from disposable
|
|
249
|
+
build output. The native launch context exposes its platform-specific
|
|
250
|
+
`modelsDirectory`; apps may additionally inspect selected application directories.
|
|
251
|
+
The model-assets service creates no platform directory policy of its own.
|
|
252
|
+
|
|
253
|
+
`resolveNativeLaunchContext({appId,context})` defaults `modelsDirectory` to
|
|
254
|
+
one shared location for the operating-system user, independent of the app ID.
|
|
255
|
+
It preserves an explicitly supplied `modelsDirectory` unchanged and creates,
|
|
256
|
+
moves or migrates no files:
|
|
257
|
+
|
|
258
|
+
| Host | Default shared model directory |
|
|
259
|
+
| --- | --- |
|
|
260
|
+
| Windows | `%LOCALAPPDATA%/Arcane/Models`; the user's `AppData/Local` when that environment variable is absent |
|
|
261
|
+
| macOS | `~/Library/Application Support/Arcane/Models` |
|
|
262
|
+
| Linux | `$XDG_DATA_HOME/Arcane/Models` when absolute, otherwise `~/.local/share/Arcane/Models` |
|
|
263
|
+
| Android or another host adaptation | `<stateRoot>/Models`; the host supplies an explicit shared `modelsDirectory` when its platform allows sharing |
|
|
264
|
+
|
|
265
|
+
Pass this `modelsDirectory` as the acquisition `workingDirectory` and as one
|
|
266
|
+
discovery directory. Completed files then live beneath its `model-assets`
|
|
267
|
+
subdirectory, separate from replaceable application builds. Additional selected
|
|
268
|
+
application directories can participate in the same discovery call.
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
import {resolveNativeLaunchContext} from 'arcane-os/core/host';
|
|
272
|
+
|
|
273
|
+
const {modelsDirectory} = resolveNativeLaunchContext({appId: 'moon-radio'});
|
|
274
|
+
const projection = await modelAssets.prepare({
|
|
275
|
+
id: selectedOperationId,
|
|
276
|
+
workingDirectory: modelsDirectory,
|
|
277
|
+
members: selectedMembers,
|
|
278
|
+
signal,
|
|
279
|
+
onProgress: renderPreparationProgress
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
App settings, profiles, chat history, workspace and IPC retain their app-private
|
|
284
|
+
locations. This default applies to applications using the native launch resolver;
|
|
285
|
+
explicit acquisition directories and other provider-owned model stores keep
|
|
286
|
+
their existing contracts. Discover existing app-local models and open them in
|
|
287
|
+
place rather than copying or removing them.
|
|
288
|
+
|
|
289
|
+
### Prepare a selected local runtime on demand
|
|
290
|
+
|
|
291
|
+
`createLocalAIService(configuration,{autoStart:false,...options})` registers the
|
|
292
|
+
existing local-AI owner without preparing or starting its selected runtimes at
|
|
293
|
+
Core startup. The default remains `autoStart:true`, preserving existing startup
|
|
294
|
+
behavior. After the user explicitly requests preparation, invoke
|
|
295
|
+
`client.invoke('localai.prepare', {}, {signal,timeoutMs:0})`. The operation uses
|
|
296
|
+
the configured existing runtime preparation callback and returns the current
|
|
297
|
+
local-AI state; it does not invent a runtime or model selection.
|
|
298
|
+
|
|
299
|
+
Preparation callback events are published as `localai.preparation` with their
|
|
300
|
+
complete original event payload. Subscribe through the existing Core event
|
|
301
|
+
owner to display actual preparation phases. Concurrent preparation requests
|
|
302
|
+
reuse the owner's in-flight work, and subsequent completed calls reuse its
|
|
303
|
+
prepared state. Runtime and model selection, explicit model acquisition and
|
|
304
|
+
microphone activation remain app-owned; preparation is not an inference or
|
|
305
|
+
microphone operation. Rendering the interface and
|
|
306
|
+
discovering installed files need not wait for runtime preparation.
|
|
307
|
+
|
|
308
|
+
### Browser discovery and explicit download
|
|
309
|
+
|
|
310
|
+
`arcane-os/ai/core-model-assets` additionally exports
|
|
311
|
+
`discoverCoreModelAssets({client,directories,catalog,recursive,signal})`,
|
|
312
|
+
`openExistingCoreModelAssets({client,directory,members,signal})`, and
|
|
313
|
+
`downloadCoreModelAssets({client,workingDirectory,members,archives,refresh,signal,onProgress})`.
|
|
314
|
+
`client` defaults to the installed Core client. Discovery returns the native
|
|
315
|
+
record above; opening and downloading return `{id,directory,members,release}`.
|
|
316
|
+
The existing Blob-based `prepareCoreModelAssets` keeps its original contract.
|
|
317
|
+
|
|
318
|
+
Download progress callbacks receive the complete semantic progress record,
|
|
319
|
+
correlated to this preparation and observed in order. On request failure, queued
|
|
320
|
+
terminal progress is delivered before internal cleanup cancellation and promise
|
|
321
|
+
rejection. Explicit caller cancellation retains its no-late-callback boundary.
|
|
322
|
+
Callback failure cancels the operation. Cancellation joins explicit native cleanup and local callback
|
|
323
|
+
delivery before the helper settles; cleanup failures remain observable.
|
|
324
|
+
Callbacks must not await their own enclosing preparation or cancellation join.
|
|
325
|
+
Applications initiate downloads explicitly and display actual phases, selected
|
|
326
|
+
member paths, completed-file counts and errors in the appropriate surface.
|
|
147
327
|
|
|
148
328
|
`release(id)` relinquishes preparation ownership without a request signal.
|
|
149
329
|
Same-process callers sharing the actual store, complete source selection and
|
|
@@ -151,24 +331,31 @@ refresh mode share an acquisition, including across service instances. They
|
|
|
151
331
|
keep independent operation IDs, retain handles, cancellation and callbacks.
|
|
152
332
|
Cancelling, releasing or disposing one interested caller leaves the others
|
|
153
333
|
running. The final interested caller aborts the acquisition and joins its
|
|
154
|
-
streams, writes and closes
|
|
334
|
+
streams, writes and closes while preserving completed members and resumable
|
|
335
|
+
partial transfers. Original
|
|
155
336
|
failures and cleanup failures remain observable. A completed acquisition stays
|
|
156
337
|
available even if a caller cancels or its callback fails after completion.
|
|
157
338
|
|
|
158
|
-
The service
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
339
|
+
The service promotes each file from its partial-transfer location only after
|
|
340
|
+
the complete response and file close finish. It records whole-acquisition
|
|
341
|
+
completion after every selected member is complete. These records describe
|
|
342
|
+
ordinary transfer and cache state, not content hashes or admission receipts.
|
|
343
|
+
Retry reuses completed members and resumes saved ordinary-file transfers with
|
|
344
|
+
HTTP Range and available HTTP continuation metadata. HTTP offsets and validators
|
|
345
|
+
remain transport-local and never become progress or model policy. If the source
|
|
346
|
+
cannot continue the saved representation, the SDK reports a restart of that
|
|
347
|
+
member; completed siblings remain available. Selected TAR companions preserve
|
|
348
|
+
completed files; an interrupted member may require replaying its TAR segment to
|
|
349
|
+
restore the archive parser's framing. No full-archive substitute is selected.
|
|
350
|
+
|
|
351
|
+
Processes selecting the same ordered sources and actual store coordinate a
|
|
352
|
+
short selection operation and one transfer owner. Another process waits with
|
|
353
|
+
observable status rather than starting a duplicate transfer. Cancelling a
|
|
354
|
+
waiting request stops its wait; it does not cancel the other process. If a
|
|
355
|
+
transfer owner exits, a later contender can reclaim its recorded operation and
|
|
356
|
+
continue retained data. This requires no additional application server, copied
|
|
357
|
+
cache implementation or new shared Core process. Existing completed models and
|
|
358
|
+
unrelated attempts are never swept or migrated automatically.
|
|
172
359
|
|
|
173
360
|
```javascript
|
|
174
361
|
import {createModelAssetService} from 'arcane-os/core/model-assets';
|
|
@@ -186,7 +373,8 @@ try {
|
|
|
186
373
|
```
|
|
187
374
|
|
|
188
375
|
`createModelAssetService({appRoot})` returns a Core service with `current()`,
|
|
189
|
-
`
|
|
376
|
+
`discover(options)`, `openExisting(options)`, `prepare(options)`, `retain(id)`,
|
|
377
|
+
`release(id)` and `dispose()`. `retain()` accepts only a completed projection
|
|
190
378
|
and returns `{id,directory,members,release}`. A native engine takes this handle
|
|
191
379
|
before loading and releases it after actual unload, failed-load cleanup or
|
|
192
380
|
worker exit. A rejected inference/load promise alone does not establish native
|
|
@@ -249,6 +437,10 @@ for source selection, cancellation and complete row/output contracts.
|
|
|
249
437
|
| Method | Parameters | Result |
|
|
250
438
|
| --- | --- | --- |
|
|
251
439
|
| `modelAssets.open` | `{id,workingDirectory,members:[{path}]}` | Preparing projection and native member paths |
|
|
440
|
+
| `modelAssets.discover` | `{directories,catalog?,recursive?}` | Directory status and complete/incomplete model candidates |
|
|
441
|
+
| `modelAssets.openExisting` | `{id,directory,members:[{path}]}` | Ready retained projection of existing originals |
|
|
442
|
+
| `modelAssets.prepare` | `{id,workingDirectory,members,archives?,refresh?}` | Ready persistent acquisition; request-scoped `modelAssets.progress` emits `{id,progress}` |
|
|
443
|
+
| `modelAssets.cancelPrepare` | `{id}` | Cancel and join the matching native preparation, then release its preparation ownership |
|
|
252
444
|
| `modelAssets.write` | `{id,memberIndex,contentBase64}` | `{id,memberIndex,written:true}` after the native write |
|
|
253
445
|
| `modelAssets.complete` | `{id}` | Ready projection after all files close |
|
|
254
446
|
| `modelAssets.release` | `{id}` | Released preparation ownership; native uses may retain the files |
|
|
@@ -258,6 +450,10 @@ The browser helper owns this transport sequence. Correlation IDs identify
|
|
|
258
450
|
operations; they are unrelated to content identity. Original model files remain
|
|
259
451
|
separate and complete. A retry creates a new working projection from the stored
|
|
260
452
|
assets; it does not redownload them or replace the authoritative DBOPFS record.
|
|
453
|
+
`cancelPrepare` and `release` have service lifetime so cancellation of the
|
|
454
|
+
original request cannot cancel its cleanup control. Native preparation follows
|
|
455
|
+
the original request signal, including connection cancellation; raw RPC callers
|
|
456
|
+
join `cancelPrepare` when cancelling and release any successful unused projection.
|
|
261
457
|
|
|
262
458
|
The implementation uses browser streams, the existing portable Core JSON
|
|
263
459
|
transport and Node filesystem operations. Native paths and cleanup follow the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Native speech service
|
|
2
2
|
|
|
3
|
-
`createSpeechService({stt, tts, signal} = {})` composes independently selected
|
|
3
|
+
`createSpeechService({stt, tts, signal, autoLoad = true} = {})` composes independently selected
|
|
4
4
|
native speech engines into one Core service. It is the named and default export
|
|
5
5
|
from `arcane-os/core/speech`.
|
|
6
6
|
|
|
@@ -50,6 +50,13 @@ independently. It returns immediately, allowing Core and `speech.status` to
|
|
|
50
50
|
respond while models load. A failure in one role leaves the other role usable.
|
|
51
51
|
Each engine publishes the actual state of its selected model.
|
|
52
52
|
|
|
53
|
+
Use `autoLoad: false` when the host first needs the user to select or download
|
|
54
|
+
model files. Startup still subscribes and exposes the ordinary unloaded state;
|
|
55
|
+
it does not call either engine's `load()`. Explicit `speech.load({role,
|
|
56
|
+
...selection})` activates the prepared role afterward. The default remains
|
|
57
|
+
`true` for existing hosts. This option changes service startup, not the selected
|
|
58
|
+
engine's missing-model errors or inference readiness requirement.
|
|
59
|
+
|
|
53
60
|
`current()` and `speech.status` return the same snapshot:
|
|
54
61
|
|
|
55
62
|
| Field | Meaning |
|
|
@@ -66,9 +73,10 @@ An engine's state includes `providerId`, `modelId`, `state`, `loaded`, and
|
|
|
66
73
|
`busy`, with its complete error or progress information when present. An
|
|
67
74
|
omitted role has `state: 'unavailable'`, `loaded: false`, and `busy: false`.
|
|
68
75
|
File presence, a spawned process, and a callable bridge do not establish loaded
|
|
69
|
-
model readiness.
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
model readiness. The shared AI adapter follows the selected engine identity
|
|
77
|
+
and model in these per-role snapshots, including Nemotron and Magpie. Only the
|
|
78
|
+
older aggregate-only fallback retains fixed `whisper.cpp`/`whisper-small` and
|
|
79
|
+
`kokoro-onnx`/`kokoro` expectations.
|
|
72
80
|
|
|
73
81
|
Each role also reports `supportsStreaming`: STT requires the configured
|
|
74
82
|
engine's `openStream()` method, and TTS requires its `synthesizeStream()` method.
|
|
@@ -288,6 +296,122 @@ share one shutdown promise. Actual engine cleanup failures reject with an
|
|
|
288
296
|
releases the service's event subscriptions. New work after shutdown begins
|
|
289
297
|
rejects with `CORE_CLOSING`.
|
|
290
298
|
|
|
299
|
+
## Selected NeMo model acquisition
|
|
300
|
+
|
|
301
|
+
`NEMO_SPEECH_MODELS`, `prepareNemotronModels`, and `prepareMagpieModels` are
|
|
302
|
+
named exports from `arcane-os/local-ai/nemotron`. Importing them performs no
|
|
303
|
+
network access, installation, model loading, or inference. The catalog records
|
|
304
|
+
NVIDIA's selected [NeMo-Speech.cpp v0.2.0 model index](https://github.com/NVIDIA/NeMo-Speech.cpp/blob/v0.2.0/models/index.json):
|
|
305
|
+
|
|
306
|
+
| Role | Complete default selection |
|
|
307
|
+
|---|---|
|
|
308
|
+
| `stt` | Nemotron 3.5 streaming ASR Q8_0 and Nemotron 3 Diarization Q8_0. |
|
|
309
|
+
| `tts` | Magpie multilingual v2607 F16, NanoCodec 22 kHz F16 decoder, and all ten matching tokenizer/configuration/speaker-map members from the same Magpie revision. |
|
|
310
|
+
|
|
311
|
+
Each role exposes `{modelId, providerId, name, members, resourcePaths}`.
|
|
312
|
+
`members` contains ordered `{path, url}` file sources. TTS also exposes
|
|
313
|
+
`archives`, with the upstream uncompressed `.nemo` TAR source, its selected
|
|
314
|
+
transport ranges, and exact `{path, member}` tokenizer entries. The shared
|
|
315
|
+
[model-assets service](model-assets.md) owns discovery, acquisition, progress,
|
|
316
|
+
cancellation, persistence, and projection lifetime; these helpers do not create
|
|
317
|
+
another downloader or store. Tokenizer files retain their complete original
|
|
318
|
+
contents. The selected tokenizer configuration and its referenced JSON speaker
|
|
319
|
+
map continue to own voice IDs.
|
|
320
|
+
|
|
321
|
+
```js
|
|
322
|
+
import {createNemotronRuntime, prepareNemotronModels} from 'arcane-os/local-ai/nemotron';
|
|
323
|
+
import {createSpeechService} from 'arcane-os/core/speech';
|
|
324
|
+
|
|
325
|
+
const stt = createNemotronRuntime({runtime, modelAssets, gpu: -1});
|
|
326
|
+
const speech = createSpeechService({stt, autoLoad: false});
|
|
327
|
+
// Run this only for the user's explicit model preparation action.
|
|
328
|
+
const prepared = await prepareNemotronModels({
|
|
329
|
+
modelAssets,
|
|
330
|
+
workingDirectory: modelsDirectory,
|
|
331
|
+
directories: [modelsDirectory, appModelsDirectory],
|
|
332
|
+
signal,
|
|
333
|
+
onProgress: showModelProgress
|
|
334
|
+
});
|
|
335
|
+
try {
|
|
336
|
+
await stt.load({
|
|
337
|
+
assetProjectionId: prepared.assetProjectionId,
|
|
338
|
+
resourcePaths: prepared.resourcePaths,
|
|
339
|
+
signal
|
|
340
|
+
});
|
|
341
|
+
} finally {
|
|
342
|
+
await prepared.release();
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Both preparation helpers accept `{modelAssets, workingDirectory, directories,
|
|
347
|
+
id, signal, onProgress, refresh = false}`. With `directories`, they ask the
|
|
348
|
+
shared owner for the first complete matching catalog selection in those roots
|
|
349
|
+
before downloading. `openExisting()` borrows its original files and never
|
|
350
|
+
deletes them. Incomplete selections stay visible through the owner's discovery
|
|
351
|
+
results and are not mistaken for a complete model. When no complete match is
|
|
352
|
+
available, the existing acquisition path prepares the complete selected set;
|
|
353
|
+
its completed members and closed partial files remain available after an
|
|
354
|
+
interruption or cancellation. Explicit retry reuses those members and resumes
|
|
355
|
+
ordinary HTTP transfers when the source accepts their conditional range;
|
|
356
|
+
otherwise only that member restarts with an explicit progress event. TAR
|
|
357
|
+
segments replay while completed tokenizer companions remain reusable.
|
|
358
|
+
Matching cross-process selections wait for the actual transfer owner, then
|
|
359
|
+
reuse or resume its recorded attempt; unrelated downloads remain concurrent.
|
|
360
|
+
See [native acquisition and recovery](model-assets.md#native-ownership) for the
|
|
361
|
+
shared owner's complete contract. Explicit `refresh: true` requests a
|
|
362
|
+
fresh acquisition. The host chooses the roots: on Windows, Linux and macOS its
|
|
363
|
+
portable native launch-context resolver defaults `modelsDirectory` to the
|
|
364
|
+
operating-system user's shared `Arcane/Models` directory, independently of
|
|
365
|
+
app-private state and workspace. Explicit directory overrides remain unchanged;
|
|
366
|
+
other adapted hosts supply their shared directory explicitly or retain the
|
|
367
|
+
resolver's app-state fallback. This location applies to services using that
|
|
368
|
+
resolver value, not every provider store. Resolution moves no existing files.
|
|
369
|
+
An application may include its own `models` directory and prior app-local
|
|
370
|
+
model locations among the discovery roots, borrowing those originals in place.
|
|
371
|
+
|
|
372
|
+
The result is `{assetProjectionId, directory, members, resourcePaths, release}`.
|
|
373
|
+
`release()` is idempotent and releases preparation ownership. Each engine
|
|
374
|
+
retains the projection synchronously when `load()` accepts it, so the caller
|
|
375
|
+
may release its preparation after starting that load. Nemotron accepts
|
|
376
|
+
`modelAssets`, `assetProjectionId`, and `resourcePaths` in its constructor and
|
|
377
|
+
`assetProjectionId`/`resourcePaths` in `load()`, with roles `{model, diarization}`.
|
|
378
|
+
Magpie uses `{model, codec, tokenizerConfig}`. Native file paths still work
|
|
379
|
+
through the engines' existing options. Nemotron requires unloading before
|
|
380
|
+
changing an active selection; its retained files are released only after
|
|
381
|
+
native work and helper exit have joined. Load failures also join asset cleanup,
|
|
382
|
+
and cleanup failures remain observable.
|
|
383
|
+
|
|
384
|
+
`onProgress` receives ordered, awaited shared-owner phase and file-completion
|
|
385
|
+
events. Native acquisition includes `state`, plain `message`, file counts and
|
|
386
|
+
optional member, reason, recovery, error or other-owner activity. Its five-second
|
|
387
|
+
heartbeat and fifteen-second no-source-activity `stalled` state describe actual
|
|
388
|
+
transfer observations, not an inferred outage or percentage. `interrupted`,
|
|
389
|
+
`cancelled`, `failed` and `ready` are distinct terminal states. Direct
|
|
390
|
+
installed-directory reuse retains the existing `reuse`/`ready` records with
|
|
391
|
+
`completed`, `total` and `unit:'files'`.
|
|
392
|
+
|
|
393
|
+
Signal cancellation stops that caller's preparation interest; another interested
|
|
394
|
+
caller may continue the shared acquisition. The final cancellation joins I/O
|
|
395
|
+
and retains resumable data; cancelled subscribers keep their existing callback
|
|
396
|
+
boundary. An abort after projection creation releases preparation ownership
|
|
397
|
+
before rejecting. Engine load cancellation remains separate: cancelling the
|
|
398
|
+
caller's wait does not cancel a shared activation; explicit engine unload/close
|
|
399
|
+
owns that cancellation.
|
|
400
|
+
|
|
401
|
+
The default GGUF selections are individual complete upstream files. The shared
|
|
402
|
+
owner also discovers ordered GGUF shard sets and reports their missing members;
|
|
403
|
+
HTTP range transfers and tokenizer TAR ranges are transport mechanisms, not
|
|
404
|
+
additional model shards. A discovered shard set alone does not establish that a
|
|
405
|
+
selected native engine can load that model. The engine remains the authority
|
|
406
|
+
for model compatibility and actual readiness.
|
|
407
|
+
|
|
408
|
+
The [upstream native runtime](https://github.com/NVIDIA/NeMo-Speech.cpp/blob/v0.2.0/docs/install.md)
|
|
409
|
+
provides Windows, Linux, and macOS distributions. Model files and that runtime
|
|
410
|
+
remain separate upstream assets, not vendored SDK payloads. This acquisition
|
|
411
|
+
integration received source review only; no download, inference, or new platform
|
|
412
|
+
execution is claimed here. See the [Nemotron](native-nemotron.md) and
|
|
413
|
+
[Magpie](native-magpie.md) contracts for native preparation and execution evidence.
|
|
414
|
+
|
|
291
415
|
## Native Kokoro engine
|
|
292
416
|
|
|
293
417
|
`createNativeKokoroRuntime` is the named and default export from
|