arcane-os 0.63.0 → 0.65.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +1 -1
  3. package/browser-runtime/core/client.mjs +69 -7
  4. package/docs/guides/native-whisper-openvino.md +334 -0
  5. package/docs/reference/README.md +6 -0
  6. package/docs/reference/arcane-ollama.md +1 -1
  7. package/docs/reference/codex-app-server.md +269 -0
  8. package/docs/reference/core-client.md +71 -4
  9. package/docs/reference/core-development.md +157 -0
  10. package/docs/reference/core-native-packaging.md +48 -6
  11. package/docs/reference/core-repositories.md +258 -0
  12. package/docs/reference/inventory/package-api.json +199 -3
  13. package/docs/reference/inventory/runtime-modules.json +3 -2
  14. package/docs/reference/local-ai.md +77 -4
  15. package/docs/reference/local-image-flux.md +1 -1
  16. package/docs/reference/local-image-generation.md +11 -0
  17. package/docs/reference/local-image-sdxl.md +139 -0
  18. package/docs/reference/local-whisper.md +219 -0
  19. package/docs/reference/mcp-stdio.md +263 -0
  20. package/docs/reference/native-speech.md +51 -2
  21. package/docs/reference/runtime-components.md +18 -1
  22. package/docs/reference/runtime-modules.md +26 -4
  23. package/docs/reference/sdk-api.md +412 -2
  24. package/package.json +9 -2
  25. package/runtime/arcane/components/speech.html +15 -3
  26. package/runtime/arcane/components/voice-transcription.html +19 -3
  27. package/runtime/arcane/modules/AI.js +406 -40
  28. package/runtime/arcane/modules/AIProviderRuntime.js +20 -3
  29. package/runtime/arcane/modules/AIRuntimeState.js +15 -2
  30. package/runtime/arcane/modules/ComponentContracts.js +3 -0
  31. package/runtime/arcane/modules/Ollama.js +1 -1
  32. package/runtime/arcane/modules/OllamaModelIdentifier.js +13 -0
  33. package/schemas/arcane-app.schema.json +60 -2
  34. package/schemas/arcane-package.schema.json +60 -2
  35. package/src/codex/app-server.mjs +845 -0
  36. package/src/core/development.mjs +457 -0
  37. package/src/core/repositories.mjs +375 -0
  38. package/src/core/services/local-ai.mjs +80 -10
  39. package/src/core/services/speech.mjs +1 -0
  40. package/src/dev-server.mjs +3 -2
  41. package/src/index.mjs +1 -0
  42. package/src/local-ai/config.mjs +7 -3
  43. package/src/local-ai/dev.mjs +85 -401
  44. package/src/local-ai/image-library.mjs +9 -0
  45. package/src/local-ai/image-models/sdxl.mjs +18 -0
  46. package/src/local-ai/install.mjs +26 -7
  47. package/src/local-ai/whisper/build.mjs +48 -0
  48. package/src/local-ai/whisper/config.mjs +89 -0
  49. package/src/local-ai/whisper/index.mjs +572 -0
  50. package/src/local-ai/whisper/install.mjs +332 -0
  51. package/src/local-ai/whisper/native/CMakeLists.txt +98 -0
  52. package/src/local-ai/whisper/native/NOTICE +18 -0
  53. package/src/local-ai/whisper/native/README.md +104 -0
  54. package/src/local-ai/whisper/native/main.cpp +520 -0
  55. package/src/local-ai/whisper/openvino-build.mjs +138 -0
  56. package/src/mcp/stdio-server.mjs +579 -0
  57. package/src/native/portable-layout.mjs +39 -7
  58. package/src/toolchain.mjs +19 -8
@@ -4037,6 +4037,15 @@ export class AIProviderRuntime {
4037
4037
  payload: options.payload,
4038
4038
  signal: controller.signal
4039
4039
  };
4040
+ if (role === 'stt') {
4041
+ providerRequest.refreshState = function refreshActiveProviderState() {
4042
+ if (slot.generation === generation && !slot.unloadPromise
4043
+ && !slot.disposePromise && !controller.signal.aborted
4044
+ && slot.activeRequests.get(requestSequence) === requestRecord) {
4045
+ runtime.#publishRoleRequestState(slot);
4046
+ }
4047
+ };
4048
+ }
4040
4049
  if (SPEECH_ROLES.includes(role)) {
4041
4050
  arcaneLogging.debug('[Arcane speech runtime] provider.request', {generation, requestSequence, operationId}, providerRequest);
4042
4051
  }
@@ -4579,16 +4588,24 @@ export class AIProviderRuntime {
4579
4588
  if (!requestRecord && slot.requestQueue.length === 0) {
4580
4589
  return false;
4581
4590
  }
4591
+ const provider = this.#providerFor(slot);
4592
+ const providerState = slot.role === 'stt' && provider
4593
+ ? validateProviderStatus(provider.status()) : null;
4594
+ const pendingRecovery = requestRecord && providerState?.loaded === false
4595
+ && ['recovering', 'error'].includes(providerState.state);
4582
4596
  publishAIRuntimeRoleState(
4583
4597
  slot.role,
4584
4598
  roleRecord(
4585
4599
  slot.role,
4586
4600
  slot.selection,
4587
4601
  {
4588
- state: 'ready',
4589
- loaded: true,
4602
+ state: pendingRecovery ? providerState.state : 'ready',
4603
+ loaded: !pendingRecovery,
4590
4604
  busy: true,
4591
- operationId: requestRecord?.operationId ?? null
4605
+ operationId: requestRecord?.operationId ?? null,
4606
+ ...(pendingRecovery && providerState.state === 'error'
4607
+ ? {error: stateError(providerState.error, 'ARCANE_AI_PROVIDER_REQUEST_FAILED')}
4608
+ : {})
4592
4609
  }
4593
4610
  )
4594
4611
  );
@@ -21,12 +21,22 @@ export const AI_RUNTIME_STATES = completeValue([
21
21
  'unavailable',
22
22
  'unloaded',
23
23
  'loading',
24
+ 'recovering',
24
25
  'ready',
25
26
  'unloading',
26
27
  'error',
27
28
  'disposed'
28
29
  ]);
29
30
 
31
+ /** Keep only an already-owned operation through its truthful recovery/error state. */
32
+ export function continuesAIRuntimeOperation(previous, current, operationId) {
33
+ return is.string(operationId) && operationId.length > 0
34
+ && previous?.operationId === operationId && current?.operationId === operationId
35
+ && previous.providerId === current.providerId && previous.modelId === current.modelId
36
+ && current.loaded === false && current.busy === true
37
+ && ['recovering', 'error'].includes(current.state);
38
+ }
39
+
30
40
  const ROLE_KEYS = completeValue([
31
41
  'role',
32
42
  'state',
@@ -77,6 +87,7 @@ const MUST_BE_UNLOADED = new Set([
77
87
  'unavailable',
78
88
  'unloaded',
79
89
  'loading',
90
+ 'recovering',
80
91
  'disposed'
81
92
  ]);
82
93
  const STARTUP_TERMINAL_STATES = new Set([
@@ -291,8 +302,10 @@ function copyRoleRecord(role, record) {
291
302
  && (record.providerId === null || record.modelId === null)) {
292
303
  fail('a loaded role must identify its provider and model.');
293
304
  }
294
- if (record.busy && (record.state !== 'ready' || !record.loaded)) {
295
- fail('a busy role must be ready and loaded.');
305
+ const pendingRecovery = ['recovering', 'error'].includes(record.state)
306
+ && record.operationId !== null;
307
+ if (record.busy && !pendingRecovery && (record.state !== 'ready' || !record.loaded)) {
308
+ fail('a busy role must be ready and loaded or retain its recovering/error operation.');
296
309
  }
297
310
  if (record.state === 'error' && error === null) {
298
311
  fail('an error role state must include error details.');
@@ -607,6 +607,9 @@ function createSTTActivationController({
607
607
  if(role?.state==='loading'){
608
608
  return `Transcription ${formatAIRuntimeProgress(role.progress,'loading')}; Cancel is available.`;
609
609
  }
610
+ if(role?.state==='recovering'){
611
+ return 'Transcription is recovering the current request.';
612
+ }
610
613
  if(role?.state==='unloading'){
611
614
  return `Transcription ${formatAIRuntimeProgress(role.progress,'releasing')}.`;
612
615
  }
@@ -40,7 +40,7 @@ export class Ollama{
40
40
  version(){ return api().version() }
41
41
  models(){ return api().models() }
42
42
  list(){ return api().models() }
43
- running(){ return api().running() }
43
+ running(options){ return api().running(options) }
44
44
  show(model,options){ return api().show(model,options) }
45
45
  generate(request,options){ return api().generate(request,options) }
46
46
  chat(request,options){ return api().chat(request,options) }
@@ -22,3 +22,16 @@ export function normalizeOllamaModelIdentifier(value){
22
22
  export function isOllamaModelIdentifier(value){
23
23
  return normalizeOllamaModelIdentifier(value)!==null;
24
24
  }
25
+
26
+ /** Compare Ollama names with its default host, namespace and tag; never rewrite a request. */
27
+ export function sameOllamaModelIdentifier(left,right){
28
+ if(!is.string(left)||!is.string(right))return false;
29
+ function identity(value){
30
+ const parts=value.replace(/^[A-Za-z][A-Za-z0-9+.-]*:\/\//,'').split('/');
31
+ const model=parts.pop();
32
+ const namespace=parts.pop()??'library';
33
+ const host=parts.join('/')||'registry.ollama.ai';
34
+ return `${host}/${namespace}/${model.includes(':')?model:`${model}:latest`}`.toLowerCase();
35
+ }
36
+ return identity(left)===identity(right);
37
+ }
@@ -262,7 +262,7 @@
262
262
  "type": "array",
263
263
  "items": {
264
264
  "oneOf": [
265
- { "enum": ["llama.cpp", "ollama", "onnx", "stable-diffusion.cpp"] },
265
+ { "enum": ["llama.cpp", "ollama", "onnx", "stable-diffusion.cpp", "whisper.cpp"] },
266
266
  {
267
267
  "type": "object",
268
268
  "required": ["id"],
@@ -271,7 +271,8 @@
271
271
  "version": { "type": "string" },
272
272
  "url": { "type": "string" }
273
273
  }
274
- }
274
+ },
275
+ { "$ref": "#/$defs/whisperRuntime" }
275
276
  ]
276
277
  }
277
278
  },
@@ -294,6 +295,63 @@
294
295
  }
295
296
  }
296
297
  },
298
+ "whisperRuntime": {
299
+ "type": "object",
300
+ "required": ["id"],
301
+ "description": "Native Whisper transcription. Models are explicitly selected; describing a runtime acquires nothing. Automatic Windows x64 preparation selects intact CUDA and CPU distributions, an SDK helper, and FFmpeg. Other hosts supply their selected complete runtime and decoder trees.",
302
+ "properties": {
303
+ "id": { "const": "whisper.cpp" },
304
+ "version": { "type": "string", "default": "1.9.4" },
305
+ "backend": { "enum": ["auto", "cuda", "metal", "cpu"], "default": "auto" },
306
+ "encoder": { "const": "openvino-npu", "description": "Explicit Intel NPU encoder. Omit for ordinary GPU/CPU encoding. The precompiled Windows x64 runtime supports CUDA-first CPU recovery and requires a compatible installed Intel NPU driver." },
307
+ "helperRoot": { "type": "string", "description": "Complete helper directory copied into the native runtime, including its app-local libraries. Defaults to the directory containing helperExecutable." },
308
+ "helperExecutable": { "type": "string" },
309
+ "helperUrl": { "type": "string" },
310
+ "helperVersion": { "type": "string" },
311
+ "decoderRoot": { "type": "string" },
312
+ "decoderExecutable": { "type": "string" },
313
+ "decoderUrl": { "type": "string" },
314
+ "modelId": { "type": "string" },
315
+ "variants": {
316
+ "type": "array",
317
+ "items": {
318
+ "type": "object",
319
+ "required": ["backend"],
320
+ "properties": {
321
+ "backend": { "enum": ["cuda", "metal", "cpu"] },
322
+ "encoder": { "const": "openvino-npu" },
323
+ "root": { "type": "string" },
324
+ "url": { "type": "string" },
325
+ "libraryDirectory": { "type": "string" }
326
+ }
327
+ }
328
+ },
329
+ "models": {
330
+ "type": "array",
331
+ "default": [],
332
+ "items": {
333
+ "oneOf": [
334
+ { "const": "whisper-small" },
335
+ {
336
+ "type": "object",
337
+ "required": ["id"],
338
+ "properties": {
339
+ "id": { "type": "string" },
340
+ "path": { "type": "string" },
341
+ "url": { "type": "string" },
342
+ "filename": { "type": "string" },
343
+ "archiveUrl": { "type": "string", "description": "Complete model archive containing the declared model members." },
344
+ "encoderFilename": { "type": "string", "description": "Matching OpenVINO encoder XML filename in archiveUrl." },
345
+ "encoderDataFilename": { "type": "string", "description": "Matching OpenVINO encoder BIN filename in archiveUrl." },
346
+ "encoderPath": { "type": "string", "description": "Matching local OpenVINO encoder XML file." },
347
+ "encoderDataPath": { "type": "string", "description": "Matching local OpenVINO encoder BIN file." }
348
+ }
349
+ }
350
+ ]
351
+ }
352
+ }
353
+ }
354
+ },
297
355
  "pwa": {
298
356
  "type": "object",
299
357
  "additionalProperties": false,
@@ -156,7 +156,7 @@
156
156
  "type": "array",
157
157
  "items": {
158
158
  "oneOf": [
159
- { "enum": ["llama.cpp", "ollama", "onnx", "stable-diffusion.cpp"] },
159
+ { "enum": ["llama.cpp", "ollama", "onnx", "stable-diffusion.cpp", "whisper.cpp"] },
160
160
  {
161
161
  "type": "object",
162
162
  "required": ["id"],
@@ -165,7 +165,8 @@
165
165
  "version": { "type": "string" },
166
166
  "url": { "type": "string" }
167
167
  }
168
- }
168
+ },
169
+ { "$ref": "#/$defs/whisperRuntime" }
169
170
  ]
170
171
  }
171
172
  },
@@ -188,6 +189,63 @@
188
189
  }
189
190
  }
190
191
  },
192
+ "whisperRuntime": {
193
+ "type": "object",
194
+ "required": ["id"],
195
+ "description": "Native Whisper transcription. Models are explicitly selected; describing a runtime acquires nothing. Automatic Windows x64 preparation selects intact CUDA and CPU distributions, an SDK helper, and FFmpeg. Other hosts supply their selected complete runtime and decoder trees.",
196
+ "properties": {
197
+ "id": { "const": "whisper.cpp" },
198
+ "version": { "type": "string", "default": "1.9.4" },
199
+ "backend": { "enum": ["auto", "cuda", "metal", "cpu"], "default": "auto" },
200
+ "encoder": { "const": "openvino-npu", "description": "Explicit Intel NPU encoder. Omit for ordinary GPU/CPU encoding. The precompiled Windows x64 runtime supports CUDA-first CPU recovery and requires a compatible installed Intel NPU driver." },
201
+ "helperRoot": { "type": "string", "description": "Complete helper directory copied into the native runtime, including its app-local libraries. Defaults to the directory containing helperExecutable." },
202
+ "helperExecutable": { "type": "string" },
203
+ "helperUrl": { "type": "string" },
204
+ "helperVersion": { "type": "string" },
205
+ "decoderRoot": { "type": "string" },
206
+ "decoderExecutable": { "type": "string" },
207
+ "decoderUrl": { "type": "string" },
208
+ "modelId": { "type": "string" },
209
+ "variants": {
210
+ "type": "array",
211
+ "items": {
212
+ "type": "object",
213
+ "required": ["backend"],
214
+ "properties": {
215
+ "backend": { "enum": ["cuda", "metal", "cpu"] },
216
+ "encoder": { "const": "openvino-npu" },
217
+ "root": { "type": "string" },
218
+ "url": { "type": "string" },
219
+ "libraryDirectory": { "type": "string" }
220
+ }
221
+ }
222
+ },
223
+ "models": {
224
+ "type": "array",
225
+ "default": [],
226
+ "items": {
227
+ "oneOf": [
228
+ { "const": "whisper-small" },
229
+ {
230
+ "type": "object",
231
+ "required": ["id"],
232
+ "properties": {
233
+ "id": { "type": "string" },
234
+ "path": { "type": "string" },
235
+ "url": { "type": "string" },
236
+ "filename": { "type": "string" },
237
+ "archiveUrl": { "type": "string", "description": "Complete model archive containing the declared model members." },
238
+ "encoderFilename": { "type": "string", "description": "Matching OpenVINO encoder XML filename in archiveUrl." },
239
+ "encoderDataFilename": { "type": "string", "description": "Matching OpenVINO encoder BIN filename in archiveUrl." },
240
+ "encoderPath": { "type": "string", "description": "Matching local OpenVINO encoder XML file." },
241
+ "encoderDataPath": { "type": "string", "description": "Matching local OpenVINO encoder BIN file." }
242
+ }
243
+ }
244
+ ]
245
+ }
246
+ }
247
+ }
248
+ },
191
249
  "pwa": {
192
250
  "type": "object",
193
251
  "additionalProperties": false,