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
@@ -55,8 +55,12 @@ runtime layouts.
55
55
  | `arcane-os/core/contracts` | Shared Core protocol, frame, method and diagnostic error contracts. |
56
56
  | `arcane-os/core/classic-source` | Node generator for the canonical classic-script Core client projection. |
57
57
  | `arcane-os/core/runtime` | App-neutral native Core dispatcher and service lifecycle. |
58
+ | `arcane-os/core/development` | App-service composition and document-owned Core transport during source development, independently of local AI. |
58
59
  | `arcane-os/core/stdio` | Framed Node stdio transport with graceful runtime drain. |
59
60
  | `arcane-os/core/host` | Node-only reusable Core host lifecycle with explicitly supplied services. |
61
+ | `arcane-os/codex/app-server` | Explicit native Codex App Server session, complete live turns, server requests and recovery. |
62
+ | `arcane-os/mcp/stdio` | Node MCP STDIO server for app-owned tools and static resources. |
63
+ | `arcane-os/core/repositories` | Native persistent ArcaneData paths and explicitly selected connected working repositories. |
60
64
  | `arcane-os/core/packaged-web` | Core-owned packaged web listener with a persisted loopback origin and ready/failure events. |
61
65
  | `arcane-os/core/preferences` | Existing preference RPC methods with an application-selected file, ordered writes and owned drain. |
62
66
  | `arcane-os/core/diarization` | Lazy native speaker-diarization service, explicit stream methods and lifecycle/result events. |
@@ -69,6 +73,7 @@ runtime layouts.
69
73
  | `arcane-os/local-ai/image` | Retained native stable-diffusion.cpp context, complete PNG generation and owned worker lifetime. |
70
74
  | `arcane-os/ai/core-image` | Browser image lifecycle and complete PNG Blobs through an available Core service. |
71
75
  | `arcane-os/core/image` | Native image Core service with independent runtime preparation and retained model ownership. |
76
+ | `arcane-os/core/speech` | Independent injected STT/TTS engine loading, request cancellation and joined Core service lifetime. |
72
77
  | `arcane-os/ai/core-model-assets` | Complete stored browser model members projected through Core into native working files. |
73
78
  | `arcane-os/core/model-assets` | Native working-file preparation, engine retain handles and joined cleanup. |
74
79
  | `arcane-os/integrated-provider` | Fixed integrated shared-development provider. |
@@ -381,6 +386,13 @@ The remaining data-only subpaths are eight JSON Schemas and package metadata.
381
386
  | `createCoreFacade()` | function | `arcane-os/core/client` | Core browser client | Browser and native WebView JavaScript hosts |
382
387
  | `installCoreClient()` | function | `arcane-os/core/client` | Core browser client | Browser and native WebView JavaScript hosts |
383
388
  | `getInstalledCoreClient()` | function | `arcane-os/core/client` | Core browser client | Browser and native WebView JavaScript hosts |
389
+ | `subscribeCoreClient()` | function | `arcane-os/core/client` | Core browser client | Browser and native WebView JavaScript hosts |
390
+ | `createDevelopmentCore()` | function | `arcane-os/core/development`, `arcane-os` | Core source development | Node on Windows, Linux and macOS; Android requires host adaptation |
391
+ | `createCodexAppServerSession()` | function | `arcane-os/codex/app-server` | Native Codex sessions | Node with an explicitly selected Codex App Server executable |
392
+ | `openCodexAppServerSession()` | function | `arcane-os/codex/app-server` | Native Codex sessions | Node with an explicitly selected Codex App Server executable |
393
+ | `createMcpStdioServer()` | function | `arcane-os/mcp/stdio` | MCP STDIO | Node streams on Windows, Linux and macOS; Android needs host adaptation |
394
+ | `MCP_PROTOCOL_VERSION` | constant | `arcane-os/mcp/stdio` | MCP STDIO | Node |
395
+ | `McpProtocolError` | class | `arcane-os/mcp/stdio` | MCP STDIO | Node |
384
396
  | `createCoreClassicSource()` | function | `arcane-os/core/classic-source` | Core classic client projection | Node; generated source runs in browser and native WebView renderers |
385
397
  | `createCoreRuntime()` | function | `arcane-os/core/runtime` | Native Core runtime | Node on Windows, Linux and macOS native hosts; Android requires host adaptation |
386
398
  | `encodeCoreFrame()` | function | `arcane-os/core/stdio` | Native Core stdio transport | Node |
@@ -391,6 +403,8 @@ The remaining data-only subpaths are eight JSON Schemas and package metadata.
391
403
  | `arcaneNativeBuilderProvider default export` | singleton | `arcane-os/native/portable-provider` | Portable native provider | Node; produces a portable payload rather than an executable host |
392
404
  | `startCoreHost()` | function | `arcane-os/core/host` | Native Core host composition | Node with readable input and writable output streams |
393
405
  | `readCoreLaunchContext()` | function | `arcane-os/core/host` | Native Core host composition | Node; reads explicitly selected launch JSON |
406
+ | `resolveArcaneDataPaths()` | function | `arcane-os/core/repositories` | Native repository workspaces | Node on Windows, Linux and macOS; Android supplies its data root |
407
+ | `createRepositoryWorkspace()` | function | `arcane-os/core/repositories` | Native repository workspaces | Node with Git; Android requires host process adaptation |
394
408
  | `createWindowsNativeProvider()` | function | `arcane-os/native/windows-provider` | Windows native provider | Node assembly; Windows x64/WebView2 execution |
395
409
  | `arcaneNativeBuilderProvider` | singleton | `arcane-os/native/windows-provider` | Windows native provider | Node assembly; Windows x64/WebView2 execution |
396
410
  | `arcaneNativeBuilderProvider default export` | singleton | `arcane-os/native/windows-provider` | Windows native provider | Node assembly; Windows x64/WebView2 execution |
@@ -412,6 +426,11 @@ The remaining data-only subpaths are eight JSON Schemas and package metadata.
412
426
  | `createCoreImageRuntime()` | function | `arcane-os/ai/core-image` | Core local images | Browser with an available Core image service |
413
427
  | `createLocalImageService()` | function | `arcane-os/core/image` | Core local images | Node Core with selected stable-diffusion.cpp requirements |
414
428
  | `createLocalImageService default export` | function | `arcane-os/core/image` | Core local images | Same native image service factory |
429
+ | `createSpeechService()` | function | `arcane-os/core/speech` | Core native speech | Node Core with explicitly supplied speech engines |
430
+ | `createWhisperRuntime()` | function | `arcane-os/local-ai/whisper` | Core native speech | Node with a prepared matching helper, runtime, decoder and selected model |
431
+ | `createWhisperRuntime default export` | function | `arcane-os/local-ai/whisper` | Core native speech | Same retained native engine factory |
432
+ | `buildWhisperHelper()` | function | `arcane-os/local-ai/whisper/build` | Core native speech | Node with installed CMake/C++17 toolchain and matching Whisper source/runtime |
433
+ | `createSpeechService default export` | function | `arcane-os/core/speech` | Core native speech | Same shared speech service factory |
415
434
  | `prepareCoreModelAssets()` | function | `arcane-os/ai/core-model-assets` | Core model assets | Browser with complete Blob/File members and available Core service |
416
435
  | `createModelAssetService()` | function | `arcane-os/core/model-assets` | Core model assets | Node Core with an application-selected working directory |
417
436
  | `createModelAssetService default export` | function | `arcane-os/core/model-assets` | Core model assets | Same native working-file service factory |
@@ -4132,6 +4151,11 @@ inspection is distinct from executing them or verifying a browser deployment.
4132
4151
 
4133
4152
  Starts one owned browser development server with exact runtime/app route mappings and a caller-selected bind address.
4134
4153
 
4154
+ Source callers may pass `core`, a handle returned by
4155
+ [`createDevelopmentCore()`](#createdevelopmentcore). The server delegates the
4156
+ Core HTTP routes and closes that owner during shutdown. The existing internal
4157
+ `localAI` handle remains accepted; `core` takes precedence when explicitly supplied.
4158
+
4135
4159
  HTTP and HTTPS serving use published `node-http-server` 10.0.0. The SDK
4136
4160
  selects source routes and supplies generated representations; the module owns
4137
4161
  static-file conditional GET/HEAD handling and response delivery. The SDK
@@ -4652,6 +4676,14 @@ async function usedescribeTargets(...arguments_) {
4652
4676
 
4653
4677
  Starts one owned browser development server for the selected application.
4654
4678
 
4679
+ The selected descriptor's `native.services` composes application Core services
4680
+ independently of local AI. Programmatic `serviceModules:[{module,options}]`
4681
+ replaces that list; `services` adds constructed service definitions and `context`
4682
+ supplies app-owned launch fields. The result adds `core` when composed and retains
4683
+ `localAI` for selected native local AI. Page rendering and the listener do not
4684
+ wait for service readiness. See [source-development Core](core-development.md)
4685
+ for explicit `/arcane-core.js` loading, cancellation and current-state replay.
4686
+
4655
4687
  `http`, `https`, `certPath`, `keyPath`, and `tls` follow the
4656
4688
  [`startDevServer()` transport contract](#startdevserver), alongside `host`, `port`, and
4657
4689
  `httpPort`. By default, `port` selects HTTPS and `httpPort` selects the HTTP `308`
@@ -7056,6 +7088,46 @@ const client = getInstalledCoreClient();
7056
7088
  console.log(client ? client.runtime.current() : 'No SDK client is installed.');
7057
7089
  ```
7058
7090
 
7091
+ ## subscribeCoreClient()
7092
+
7093
+ ### Overview
7094
+
7095
+ Observes the selected global's SDK client installation without creating a
7096
+ transport or delaying rendering. Applications can subscribe before independently
7097
+ loaded development or native bootstrap code installs the client.
7098
+
7099
+ ### Signature and result
7100
+
7101
+ ```text
7102
+ subscribeCoreClient(listener,{global=globalThis,emitCurrent=true,signal}={})
7103
+ ```
7104
+
7105
+ Import from `arcane-os/core/client`. Returns an idempotent unsubscribe function.
7106
+ The listener receives `{client,previousClient,reason,error}` with the exact
7107
+ client and error objects. Reasons are `current`, `installed`, `closed` and
7108
+ `transport-failed`. Current state replays synchronously unless disabled; an
7109
+ already-aborted signal registers nothing. Close or terminal failure releases
7110
+ the prior installation before notification. A reentrant replacement is retained.
7111
+
7112
+ ### Availability and normalization
7113
+
7114
+ **Browser and native WebView JavaScript hosts.** Installation is distinct from
7115
+ Core, service or model readiness. Read `client.runtime.current()` and subscribe
7116
+ to that client's authoritative runtime/service events for those states. This
7117
+ observer starts no service and uses the shared event owner, not polling. See
7118
+ [Core client](core-client.md) and [source-development Core](core-development.md).
7119
+
7120
+ ### Example
7121
+
7122
+ ```javascript
7123
+ import {subscribeCoreClient} from 'arcane-os/core/client';
7124
+
7125
+ const unsubscribe = subscribeCoreClient(function installationChanged({client}) {
7126
+ console.log(client ? client.runtime.current() : 'Core is not installed.');
7127
+ });
7128
+ // The application owner calls unsubscribe() when this observer is retired.
7129
+ ```
7130
+
7059
7131
  ## createCoreClassicSource()
7060
7132
 
7061
7133
  ### Overview
@@ -7096,6 +7168,93 @@ const source = await createCoreClassicSource({
7096
7168
  nativeHost.setDocumentCreatedScript(source);
7097
7169
  ```
7098
7170
 
7171
+ ## createCodexAppServerSession()
7172
+
7173
+ Import from `arcane-os/codex/app-server`. Creates a synchronous session handle
7174
+ without starting a process. `connect()` starts the caller-selected executable
7175
+ and completes native JSONL initialization. The session owns explicit thread
7176
+ creation/resumption, complete native requests, live turn callbacks, exact-turn
7177
+ completion, interruption, real server-request replies and process retirement.
7178
+ Application-owned prompts, approvals and display policy stay with the caller.
7179
+ It neither attaches to desktop chats nor installs or authenticates Codex.
7180
+ See the complete [session options, methods, events, results, errors and recovery
7181
+ contract](codex-app-server.md).
7182
+
7183
+ ## openCodexAppServerSession()
7184
+
7185
+ Import from `arcane-os/codex/app-server`. Creates the same session, awaits
7186
+ `connect()`, and returns it; failed opening disposes the owned process before
7187
+ rejecting. Prefer `createCodexAppServerSession()` when the caller must retain
7188
+ the handle during initialization. Neither factory creates or resumes a thread.
7189
+ See [connection ownership](codex-app-server.md#open-an-explicitly-selected-connection).
7190
+
7191
+ ## createMcpStdioServer()
7192
+
7193
+ Import from `arcane-os/mcp/stdio`. Creates one optional Node STDIO session for
7194
+ application-owned tool and static-resource descriptors. `start()` attaches
7195
+ caller-owned streams; handlers receive complete arguments and return explicit
7196
+ MCP result containers. Requests run independently; protocol output writes are
7197
+ ordered. Normal EOF and `close()` drain accepted work. Cancellation is
7198
+ cooperative, and transport failures remain observable through `closed`.
7199
+ See [options, handlers, methods, errors and supported profile](mcp-stdio.md).
7200
+
7201
+ ## MCP_PROTOCOL_VERSION
7202
+
7203
+ Import from `arcane-os/mcp/stdio`. The supported initialization profile is
7204
+ exactly `'2025-11-25'`. This does not claim later profiles or every optional
7205
+ capability. See [protocol support](mcp-stdio.md#mcp_protocol_version).
7206
+
7207
+ ## McpProtocolError
7208
+
7209
+ Import from `arcane-os/mcp/stdio`. `new McpProtocolError(code,message,data)`
7210
+ represents an explicit JSON-RPC error with complete message and optional data.
7211
+ Ordinary domain tool failures use an explicit `CallToolResult` with `isError`.
7212
+ See [error outcomes](mcp-stdio.md#mcpprotocolerror).
7213
+
7214
+ ## createDevelopmentCore()
7215
+
7216
+ ### Overview
7217
+
7218
+ Composes application-selected Core services and the SDK-owned development HTTP
7219
+ transport independently of local AI. Import from `arcane-os/core/development`
7220
+ or `arcane-os`; ordinary applications normally use `developApplication()` with
7221
+ their descriptor's `native.services`.
7222
+
7223
+ ### Signature and result
7224
+
7225
+ `createDevelopmentCore({appRoot=process.cwd(),application,version,services=[],serviceModules=[],context={},getReplayEvents,signal,onEvent}={})`
7226
+ returns `{ready,handler,current,close}` synchronously. Module default factories
7227
+ receive unchanged `(options,context)`. `ready` reports composed dispatcher
7228
+ startup, not readiness of every service. `current()` returns complete
7229
+ `{state,error,core}`; `handler(request,response)` owns `/rpc`, `/events` and both
7230
+ bootstrap aliases; idempotent `close()` joins accepted service work and output.
7231
+
7232
+ ### Availability and example
7233
+
7234
+ Node on Windows, Linux and macOS. Browser callers use the public Core client.
7235
+ Android needs its host adapter. This adds no cross-process host discovery.
7236
+
7237
+ ```javascript
7238
+ import {createDevelopmentCore, startDevServer} from 'arcane-os';
7239
+
7240
+ const core = createDevelopmentCore({
7241
+ appRoot: process.cwd(),
7242
+ serviceModules: [{module: 'bridge/moon-cheese.mjs', options: {shelf: 'Lunar cheddar'}}]
7243
+ });
7244
+ let server;
7245
+ try {
7246
+ server = await startDevServer({workspaceRoot: process.cwd(), core});
7247
+ await server.closed;
7248
+ } finally {
7249
+ await core.close();
7250
+ }
7251
+ ```
7252
+
7253
+ The [complete guide](core-development.md) defines document cancellation,
7254
+ service-lifetime drain, diagnostics, optional explicit service snapshots and
7255
+ non-blocking page bootstrap. App policy and explicit native process activation
7256
+ remain app-owned.
7257
+
7099
7258
  ## createCoreRuntime()
7100
7259
 
7101
7260
  ### Overview
@@ -7421,12 +7580,23 @@ application builds. The build machine needs its normal Node/npm toolchain and
7421
7580
  The returned `arcane-native-builder/1` provider exposes `describe`, `doctor`,
7422
7581
  `prepare`, `build`, `verify` and `run`. Build returns `{app,target,manifest}`
7423
7582
  with the actual directory at `target.rootDir`. Verification reads the artifact;
7424
- it does not launch the window. Run launches `Arcane.exe` and observes complete
7425
- diagnostics and exit. Cancellation closes input and waits for host-owned drain,
7583
+ it does not launch the window. Run launches the executable recorded in the
7584
+ saved `manifest.host.executable` and observes complete diagnostics and exit.
7585
+ Cancellation closes input and waits for host-owned drain,
7426
7586
  including accepted service work, without a forced termination deadline. Missing
7427
7587
  prerequisites, download/extraction failures and host failures remain observable
7428
7588
  through the operation's error/event boundary.
7429
7589
 
7590
+ Assembly names the launcher from `appDescriptor.displayName` plus `.exe`,
7591
+ with a matching `.exe.config` file. Low-level compositions without a nonempty
7592
+ string display name use the app ID. Windows-reserved filename characters and
7593
+ control characters become underscores; reserved DOS device basenames receive
7594
+ an underscore prefix. Supported Unicode, spaces and case remain, as do the
7595
+ original descriptor and title. Icon embedding, file inventory, verification
7596
+ and run use this same name. Existing artifacts retain the executable recorded
7597
+ in their manifest; the reusable downloaded host retains `Arcane.exe` and
7598
+ `Arcane.exe.config`, and `runtime/ArcaneCore.exe` remains unchanged.
7599
+
7430
7600
  During assembly, `appDescriptor.native.icon` selects the app's existing image.
7431
7601
  PNG and ICO inputs produce a derived `runtime/arcane-app.ico` and update only
7432
7602
  the copied application's executable icon. Source assets, the selected host
@@ -7676,6 +7846,71 @@ separate argument; other composing hosts may use the same seam. This JavaScript
7676
7846
  contract does not establish a compiled host or matching release archive. See
7677
7847
  [launch-time locations](core-native-packaging.md#launch-time-locations).
7678
7848
 
7849
+ ## resolveArcaneDataPaths()
7850
+
7851
+ ### Overview
7852
+
7853
+ Resolves the native per-user `ArcaneData` directory and its `Repos` child without
7854
+ creating directories or changing application state.
7855
+
7856
+ ### Signature and result
7857
+
7858
+ ```text
7859
+ resolveArcaneDataPaths({dataRoot}={})
7860
+ ```
7861
+
7862
+ Returns absolute `{dataRoot,repositoriesRoot}`. Defaults use Windows LocalAppData,
7863
+ Linux XDG data home or `~/.local/share`, and macOS user Application Support.
7864
+ Android and other adapted hosts supply their persistent `dataRoot`. An explicit
7865
+ root is used directly, with relative paths resolved from the process working
7866
+ directory. See [native repository locations](core-repositories.md#persistent-locations).
7867
+
7868
+ ```javascript
7869
+ import {resolveArcaneDataPaths} from 'arcane-os/core/repositories';
7870
+
7871
+ const {repositoriesRoot} = resolveArcaneDataPaths();
7872
+ ```
7873
+
7874
+ ## createRepositoryWorkspace()
7875
+
7876
+ ### Overview
7877
+
7878
+ Owns one native connected working checkout under `ArcaneData/Repos/<name>` or an
7879
+ explicit existing path. The application owns the remote, branch and Core API.
7880
+
7881
+ ### Signature and result
7882
+
7883
+ ```text
7884
+ createRepositoryWorkspace({name,directory,dataRoot,remote,branch,onEvent,run=runProcess}={})
7885
+ ```
7886
+
7887
+ Returns `{directory,open,status,pull,push,write,close,drain,dispose}`. Construction does
7888
+ no I/O. Operations accept `{signal}`; a missing or empty destination clones once,
7889
+ while existing checkout files, branches, remotes and local changes remain intact.
7890
+ Same-directory calls are ordered within the process. Shutdown drains accepted
7891
+ work and preserves the checkout. No CLI cwd, launch state, preference, snapshot
7892
+ cache or existing user-data location changes. See the [complete inputs, results,
7893
+ errors and lifecycle](core-repositories.md#one-connected-working-checkout).
7894
+
7895
+ `write({files:[{path,content}],message,signal})` snapshots the exact selected
7896
+ strings, writes those repository-relative files, commits only their literal
7897
+ paths and performs an ordinary non-force push. It retains unrelated staged
7898
+ paths and existing Git filters/hooks. Results and causal failures distinguish
7899
+ confirmed local writes, commits, pushes and uncertain attempted side effects;
7900
+ complete process output is retained. See [the complete writer outcome
7901
+ contract](core-repositories.md#write-commit-and-push-selected-text).
7902
+
7903
+ ```javascript
7904
+ import {createRepositoryWorkspace} from 'arcane-os/core/repositories';
7905
+
7906
+ const repository = createRepositoryWorkspace({
7907
+ name: 'moon-cheese-dispatches',
7908
+ remote: applicationConnection.remote
7909
+ });
7910
+ await repository.open({signal});
7911
+ await repository.close();
7912
+ ```
7913
+
7679
7914
  ## createCoreLocalAIProvider()
7680
7915
 
7681
7916
  ### Overview
@@ -7881,6 +8116,181 @@ selected model and native engine.
7881
8116
  The default export from `arcane-os/core/image` is the same
7882
8117
  `createLocalImageService` factory and lifecycle described above.
7883
8118
 
8119
+ ## createWhisperRuntime()
8120
+
8121
+ ### Overview
8122
+
8123
+ Creates one retained native Whisper engine from a prepared runtime or a lazy
8124
+ preparation function. Construction starts no helper, model load or inference.
8125
+ Import the named factory from `arcane-os/local-ai/whisper`.
8126
+
8127
+ ### Syntax and inputs
8128
+
8129
+ ```javascript
8130
+ createWhisperRuntime({runtime, prepare, modelId, temporaryDirectory, onEvent}={})
8131
+ ```
8132
+
8133
+ Supply `runtime` or `prepare({signal,onEvent})`, and an application-owned
8134
+ `temporaryDirectory`. `modelId` selects a model from the prepared runtime;
8135
+ omitting it uses the runtime's selected model. `onEvent` receives complete
8136
+ native preparation/process diagnostics. The runtime describes matching helper,
8137
+ Whisper backend libraries, decoder and model files; see the complete
8138
+ [native Whisper preparation contract](local-whisper.md).
8139
+
8140
+ ### Returned members and lifetime
8141
+
8142
+ | Member | Contract |
8143
+ | --- | --- |
8144
+ | `current()` | Returns `providerId`, `modelId`, `state`, `loaded`, `busy`, `requestId`, `requestedBackend`, `observedBackend`, `backendEvidence` and `error`. State reports actual helper/model readiness. |
8145
+ | `subscribe(listener,{replay=true,signal}={})` | Observes the current snapshot immediately by default, then each state change; returns the unsubscribe closure. |
8146
+ | `load({modelId,signal}={})` | Prepares the selected runtime if necessary and retains its initialized helper/model. Same-model loading is shared; replacement remains explicit. |
8147
+ | `transcribe(request,{signal,onProgress,requestId}={})` | Accepts the complete `{audioBase64,mimeType?,model?,language?,translate?}` recording for the loaded model and returns `{text,language,duration,segments}`. `audioBase64` transports the original media; the decoder recognizes its actual format. Progress is ordered; control metadata stays outside the request. |
8148
+ | `unload()` | Cancels owned loading/transcription, joins decoder/helper work and releases the retained model before resolving its state snapshot. |
8149
+ | `close()` | Performs joined unload and disposes state observation. Repeated calls share the closing result. |
8150
+
8151
+ The decoder consumes the complete submitted media into native 16 kHz mono PCM
8152
+ without changing the caller's recording. The result preserves the engine's
8153
+ complete text and segment order. Temporary operation files remain until decoder
8154
+ and inference settle. The engine accepts one active recording; overlapping
8155
+ requests report `WHISPER_BUSY`, and unavailable/closing/model failures retain
8156
+ their explicit diagnostics. Caller cancellation retains its supplied reason.
8157
+
8158
+ With `backend: 'auto'`, an eligible accelerated native failure may drain that
8159
+ helper and retry the same complete recording and selected model once on the
8160
+ prepared CPU backend. Its snapshot is `recovering`, unloaded and busy during
8161
+ recovery. Cancellation, malformed input, observer/protocol failure and explicit
8162
+ backend selection do not cause that retry. `requestId` is the actual optional
8163
+ transport correlation, never a generated replacement or payload field; it
8164
+ remains through terminal error settlement and clears or changes on the next
8165
+ request/load/unload/close. The [shared speech adapter](native-speech.md) preserves
8166
+ only that continuing owned request, while new requests require actual readiness.
8167
+
8168
+ ### Availability and example
8169
+
8170
+ Node on Windows, Linux and macOS with matching native resources; Android needs
8171
+ the corresponding host/process adaptation. Prepared files establish resource
8172
+ availability, not execution on every platform. This uses an already prepared
8173
+ runtime and the application's own temporary directory:
8174
+
8175
+ ```javascript
8176
+ import {createWhisperRuntime} from 'arcane-os/local-ai/whisper';
8177
+ import {createSpeechService} from 'arcane-os/core/speech';
8178
+
8179
+ const stt = createWhisperRuntime({runtime, modelId: 'whisper-small', temporaryDirectory});
8180
+ const speech = createSpeechService({stt});
8181
+ // Register speech with the existing Core owner; it owns start/drain/dispose.
8182
+ ```
8183
+
8184
+ ## createWhisperRuntime default export
8185
+
8186
+ The default binding from `arcane-os/local-ai/whisper` is identical to the named
8187
+ [`createWhisperRuntime()`](#createwhisperruntime) factory and has the same inputs,
8188
+ members, readiness, cancellation and native-resource requirements.
8189
+
8190
+ ## buildWhisperHelper()
8191
+
8192
+ `buildWhisperHelper({runtime,outputRoot,cmake='cmake',generator,cmakeArgs=[],env,
8193
+ signal,onEvent}={})` from `arcane-os/local-ai/whisper/build` builds the first-party
8194
+ persistent helper using the installed native toolchain. `runtime.directory`
8195
+ selects the prepared libraries and `runtime.sourceDirectory` selects their
8196
+ matching headers; `outputRoot` owns build/install output. Optional CMake
8197
+ arguments, generator and environment remain caller-selected.
8198
+
8199
+ The operation runs configure, Release build and install in order. It returns
8200
+ `{platform,architecture,root,executable,runtimeDirectory,diagnostics}`, with
8201
+ complete `configure`, `compile` and `install` process results. Cancellation and
8202
+ process errors use the existing owned process lifetime. It installs neither a
8203
+ toolchain nor a model and performs no inference. Windows helper installation
8204
+ includes the selected compiler's redistributable runtime closure. Use a
8205
+ toolchain and prepared runtime matching the target platform/architecture; a
8206
+ source package alone is not a compiled helper. See the [helper build procedure](local-whisper.md).
8207
+
8208
+ ## createSpeechService()
8209
+
8210
+ ### Overview and usage
8211
+
8212
+ `createSpeechService({stt,tts,signal}={})` from `arcane-os/core/speech` composes
8213
+ independently selected STT and TTS engines as one Core service. Supply either
8214
+ role or both. Construction downloads, installs and loads nothing; the host
8215
+ owns engine creation, model/device selection and supported formats.
8216
+
8217
+ ```javascript
8218
+ import {createCoreRuntime} from 'arcane-os/core/runtime';
8219
+ import {createSpeechService} from 'arcane-os/core/speech';
8220
+
8221
+ // transcriptionEngine is the host's already constructed, selected engine.
8222
+ const speech = createSpeechService({stt: transcriptionEngine});
8223
+ const core = createCoreRuntime({services: [speech]});
8224
+ core.start();
8225
+ ```
8226
+
8227
+ Each supplied engine exposes `current()`, replaying `subscribe(listener)`,
8228
+ `load({signal})`, `close()` and its role's
8229
+ `transcribe(request,{signal,onProgress})` or
8230
+ `synthesize(request,{signal,onProgress})`. The service forwards complete
8231
+ requests and results unchanged. Format decoding, model processing and encoding
8232
+ remain with that engine. This factory supplies no speech engine or automatic
8233
+ browser/native provider selection.
8234
+
8235
+ ### Members, results and events
8236
+
8237
+ The returned object has `name: 'speech'`, `current`, `subscribe`, `close`,
8238
+ `start`, `methods`, `drain` and `dispose`:
8239
+
8240
+ - `start(context)` subscribes and starts both configured engine loads
8241
+ independently, returning immediately. Core and status remain responsive
8242
+ during loading; one role's failure leaves the other usable.
8243
+ - `current()` and `methods['speech.status']()` return the same snapshot:
8244
+ `ready`, `transcriptionAvailable`, `synthesisAvailable`, `status`,
8245
+ `sttEngine`, `ttsEngine`, `roles.stt`, `roles.tts` and `closed`.
8246
+ `ready` requires both roles; each independent availability flag requires
8247
+ its model loaded in `ready` or `running` state while the service accepts work.
8248
+ `status` is `created`, `ok`, `closing` or `closed`; per-role state carries
8249
+ model loading, progress and complete errors. An omitted role is unavailable.
8250
+ - `subscribe(listener,{replay=true,signal}={})` replays current state by
8251
+ default and returns an unsubscribe function. Its signal owns only that
8252
+ subscription; a closed service can replay its final snapshot.
8253
+ - `methods['speech.transcribe'](request,context)` and
8254
+ `methods['speech.synthesize'](request,context)` are registered as the matching
8255
+ Core RPC methods. The context supplies `signal`, `requestId` and `emit`.
8256
+ The service publishes synchronous accepted `Thinking` before waiting for
8257
+ its role's load, then forwards the engine's complete progress and result.
8258
+ - `close()` and its `drain()` alias stop acceptance, abort the service lifetime,
8259
+ close both engines concurrently and await startup and request work. Repeated
8260
+ calls share one promise. `dispose()` also releases event subscriptions.
8261
+
8262
+ `speech.state` carries the complete snapshot. `speech.progress` carries
8263
+ `{requestId,role,status:'Thinking',progress}` with initial
8264
+ `progress:{phase:'accepted'}`. The service's subscription replays state; Core's
8265
+ generic runtime replay does not replay this custom event. Browser consumers
8266
+ subscribe before requesting `Arcane.speech.status()` and preserve any newer
8267
+ state event received while that request is pending.
8268
+
8269
+ ### Cancellation, errors and availability
8270
+
8271
+ The optional factory signal owns the service lifetime. A request signal is
8272
+ combined with that lifetime and reaches its selected engine. Cancelling one
8273
+ request waiting for a shared load settles that request without cancelling
8274
+ the other requests or role. No later cancelled progress or result is delivered.
8275
+ Actual queued/running native interruption belongs to the engine; it must settle
8276
+ before Core reaches service shutdown, because Core first cancels and awaits
8277
+ active requests.
8278
+
8279
+ Invalid engine interfaces or listeners throw `TypeError`. Missing roles reject
8280
+ their operation with `SPEECH_ENGINE_UNAVAILABLE`; work after shutdown begins
8281
+ rejects with `CORE_CLOSING`. Engine errors remain observable, and engine cleanup
8282
+ failures reject shutdown with `AggregateError`. Asynchronous listener failures
8283
+ reach developer diagnostics. Engine platform support remains its own contract;
8284
+ this Node composition layer adds no engine dependency. Existing AI readiness
8285
+ consumers recognize `whisper.cpp` and `kokoro-onnx` IDs independently of the
8286
+ service's engine-neutral interface. See the [complete engine and lifetime
8287
+ contract](native-speech.md).
8288
+
8289
+ ## createSpeechService default export
8290
+
8291
+ The default export from `arcane-os/core/speech` is the same
8292
+ `createSpeechService` factory, with identical inputs, results and lifecycle.
8293
+
7884
8294
  ## prepareCoreModelAssets()
7885
8295
 
7886
8296
  `prepareCoreModelAssets({client=getInstalledCoreClient(),workingDirectory,members,signal?,onProgress?})`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcane-os",
3
- "version": "0.63.0",
3
+ "version": "0.65.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",
@@ -59,8 +59,12 @@
59
59
  "./core/contracts": "./browser-runtime/core/contracts.mjs",
60
60
  "./core/classic-source": "./src/core-classic-source.mjs",
61
61
  "./core/runtime": "./src/core/runtime.mjs",
62
+ "./core/development": "./src/core/development.mjs",
62
63
  "./core/stdio": "./src/core/stdio.mjs",
63
64
  "./core/host": "./src/core/host.mjs",
65
+ "./codex/app-server": "./src/codex/app-server.mjs",
66
+ "./mcp/stdio": "./src/mcp/stdio-server.mjs",
67
+ "./core/repositories": "./src/core/repositories.mjs",
64
68
  "./core/packaged-web": "./src/core/services/packaged-web.mjs",
65
69
  "./core/preferences": "./src/core/services/preferences.mjs",
66
70
  "./core/diarization": "./src/diarization/service.mjs",
@@ -73,6 +77,9 @@
73
77
  "./local-ai": "./src/local-ai/install.mjs",
74
78
  "./local-ai/onnx": "./src/local-ai/onnx.mjs",
75
79
  "./local-ai/image": "./src/local-ai/image-runtime.mjs",
80
+ "./local-ai/whisper": "./src/local-ai/whisper/index.mjs",
81
+ "./local-ai/whisper/build": "./src/local-ai/whisper/build.mjs",
82
+ "./local-ai/whisper/openvino-build": "./src/local-ai/whisper/openvino-build.mjs",
76
83
  "./integrated-provider": "./src/integrated-provider-loader.mjs",
77
84
  "./packager": "./src/packager/core.mjs",
78
85
  "./release-bundle": "./src/release-bundle.mjs",
@@ -114,7 +121,7 @@
114
121
  "test": "npm run test:unit && npm run test:functional && npm run test:integration && npm run test:regression",
115
122
  "test:release": "node ./bin/arcane-test.mjs test/npm-release.test.mjs",
116
123
  "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/targets.test.mjs test/workspace-operation-lock.test.mjs",
117
- "test:functional": "node ./bin/arcane-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-speech-providers.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/core-classic-source.test.mjs test/core-client.test.mjs test/core-host.test.mjs test/core-packaged-web.test.mjs test/core-runtime.test.mjs test/core-stdio.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs-png.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.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/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",
124
+ "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-speech-providers.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-development.test.mjs test/core-host.test.mjs test/core-packaged-web.test.mjs test/core-runtime.test.mjs test/core-stdio.test.mjs test/dbopfs-document-library.test.mjs test/dbopfs-png.test.mjs test/dbopfs.test.mjs test/dev-server.test.mjs test/dev-pwa.test.mjs test/dom-event-instrumentation.test.mjs test/event-manager.test.mjs test/events.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/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",
118
125
  "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",
119
126
  "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/native-provider-generation.test.mjs test/speech-queue-regression.test.mjs test/testing.test.mjs test/test-sets.test.mjs",
120
127
  "check": "node tools/check-source.mjs && npm test",
@@ -295,6 +295,7 @@
295
295
  const aiModuleImport = import('../modules/AI.js');
296
296
  const providerRuntimeImport = import('../modules/AIProviderRuntime.js');
297
297
  const {
298
+ continuesAIRuntimeOperation,
298
299
  requestAIRuntimeIntent,
299
300
  subscribeAIRuntimeState
300
301
  } = await import('../modules/AIRuntimeState.js');
@@ -366,6 +367,7 @@
366
367
  let ttsIntentGeneration = 0;
367
368
  let eventOperationSequence = 0;
368
369
  let transcriptionOperationId = null;
370
+ let transcriptionRuntimeOperationId = null;
369
371
  let ttsOperationId = null;
370
372
  let destroyed = false;
371
373
  let recognitionLanguage = is.string(host.recognitionLanguage)
@@ -826,8 +828,10 @@
826
828
 
827
829
  function applyRoleTransitions(previousSTTRole, previousTTSRole) {
828
830
  sttActivationController?.synchronize(sttRole);
829
- const sttBecameUnready = previousSTTRole.state === 'ready'
830
- && sttRole.state !== 'ready';
831
+ const continuingTranscription = transcriptionActive && !nativeCaptureSession
832
+ && continuesAIRuntimeOperation(previousSTTRole, sttRole, transcriptionRuntimeOperationId);
833
+ const sttBecameUnready = ['ready', 'recovering'].includes(previousSTTRole.state)
834
+ && sttRole.state !== 'ready' && !continuingTranscription;
831
835
  const ttsBecameUnready = previousTTSRole.state === 'ready'
832
836
  && ttsRole.state !== 'ready';
833
837
 
@@ -2011,10 +2015,16 @@
2011
2015
  throw error;
2012
2016
  }
2013
2017
 
2014
- const transcription = await aiRuntime.fetchSTT(
2018
+ const previousRuntimeOperationId = providerRuntime.status('stt').operationId;
2019
+ const pendingTranscription = aiRuntime.fetchSTT(
2015
2020
  audioFile,
2016
2021
  controller.signal
2017
2022
  );
2023
+ const activeRole = providerRuntime.status('stt');
2024
+ transcriptionRuntimeOperationId = activeRole.busy
2025
+ && activeRole.operationId !== previousRuntimeOperationId
2026
+ ? activeRole.operationId : null;
2027
+ const transcription = await pendingTranscription;
2018
2028
  if (
2019
2029
  generation !== transcriptionGeneration
2020
2030
  || sttRole.state !== 'ready'
@@ -2044,6 +2054,7 @@
2044
2054
  } finally {
2045
2055
  if (transcriptionAbortController === controller) {
2046
2056
  transcriptionAbortController = null;
2057
+ transcriptionRuntimeOperationId = null;
2047
2058
  }
2048
2059
  if (generation === transcriptionGeneration) {
2049
2060
  transcriptionActive = false;
@@ -2144,6 +2155,7 @@
2144
2155
  transcriptionGeneration += 1;
2145
2156
  transcriptionAbortController?.abort();
2146
2157
  transcriptionAbortController = null;
2158
+ transcriptionRuntimeOperationId = null;
2147
2159
  recordingRequested = false;
2148
2160
  transcriptionActive = false;
2149
2161
  clearSilenceTimer();