arcane-os 0.65.0 → 0.67.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 (40) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +1 -1
  3. package/browser-runtime/ai/browser-decisions.mjs +3 -2
  4. package/browser-runtime/ai/core-image.mjs +84 -34
  5. package/browser-runtime/ai/core-local.mjs +195 -43
  6. package/browser-runtime/ai/core-onnx.mjs +71 -12
  7. package/browser-runtime/ai/decision-runtime.mjs +14 -24
  8. package/docs/publishing.md +39 -0
  9. package/docs/reference/README.md +8 -1
  10. package/docs/reference/ai/browser-decisions.md +7 -4
  11. package/docs/reference/core-native-packaging.md +11 -4
  12. package/docs/reference/core-repositories.md +214 -11
  13. package/docs/reference/core-runtime.md +32 -5
  14. package/docs/reference/git-text-snapshot.md +15 -1
  15. package/docs/reference/inventory/package-api.json +41 -13
  16. package/docs/reference/inventory/runtime-modules.json +5 -4
  17. package/docs/reference/local-ai.md +119 -2
  18. package/docs/reference/local-image-generation.md +15 -4
  19. package/docs/reference/local-whisper.md +7 -1
  20. package/docs/reference/mcp-stdio.md +1 -1
  21. package/docs/reference/model-assets.md +50 -3
  22. package/docs/reference/native-decisions.md +181 -0
  23. package/docs/reference/native-speech.md +6 -0
  24. package/docs/reference/sdk-api.md +151 -16
  25. package/package.json +5 -2
  26. package/src/core/repositories.mjs +37 -14
  27. package/src/core/runtime.mjs +11 -0
  28. package/src/core/services/decisions.mjs +144 -0
  29. package/src/core/services/local-ai.mjs +31 -9
  30. package/src/core/services/model-assets.mjs +98 -13
  31. package/src/git-identity.mjs +96 -0
  32. package/src/git-text-snapshot.mjs +5 -3
  33. package/src/local-ai/decision-tokenizer-worker.mjs +31 -0
  34. package/src/local-ai/decision-tokenizer.mjs +109 -0
  35. package/src/local-ai/decisions.mjs +273 -0
  36. package/src/local-ai/dev.mjs +8 -2
  37. package/src/local-ai/onnx-worker.mjs +67 -7
  38. package/src/local-ai/onnx.mjs +23 -12
  39. package/src/native/portable-layout.mjs +8 -3
  40. package/src/repository.mjs +144 -4
@@ -60,7 +60,7 @@ runtime layouts.
60
60
  | `arcane-os/core/host` | Node-only reusable Core host lifecycle with explicitly supplied services. |
61
61
  | `arcane-os/codex/app-server` | Explicit native Codex App Server session, complete live turns, server requests and recovery. |
62
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. |
63
+ | `arcane-os/core/repositories` | Native persistent ArcaneData paths, connected working repositories and scoped non-secret Git identity configuration. |
64
64
  | `arcane-os/core/packaged-web` | Core-owned packaged web listener with a persisted loopback origin and ready/failure events. |
65
65
  | `arcane-os/core/preferences` | Existing preference RPC methods with an application-selected file, ordered writes and owned drain. |
66
66
  | `arcane-os/core/diarization` | Lazy native speaker-diarization service, explicit stream methods and lifecycle/result events. |
@@ -74,6 +74,9 @@ runtime layouts.
74
74
  | `arcane-os/ai/core-image` | Browser image lifecycle and complete PNG Blobs through an available Core service. |
75
75
  | `arcane-os/core/image` | Native image Core service with independent runtime preparation and retained model ownership. |
76
76
  | `arcane-os/core/speech` | Independent injected STT/TTS engine loading, request cancellation and joined Core service lifetime. |
77
+ | `arcane-os/local-ai/whisper` | Retained native Whisper model, complete recordings and joined helper lifetime. |
78
+ | `arcane-os/local-ai/whisper/build` | First-party persistent helper build against selected installed Whisper headers and libraries. |
79
+ | `arcane-os/local-ai/whisper/openvino-build` | Optional Windows x64 Intel NPU encoder runtime producer using selected installed sources and toolchain. |
77
80
  | `arcane-os/ai/core-model-assets` | Complete stored browser model members projected through Core into native working files. |
78
81
  | `arcane-os/core/model-assets` | Native working-file preparation, engine retain handles and joined cleanup. |
79
82
  | `arcane-os/integrated-provider` | Fixed integrated shared-development provider. |
@@ -105,7 +108,7 @@ runtime layouts.
105
108
  | `arcane-os/pwa` | Nonblocking PWA registration, worker updates, native installation state and a dismissible installation component. |
106
109
  | `arcane-os/ai/browser-wasm` | Caller-selected browser-local Wllama inference, complete DBOPFS model storage, streaming, cancellation, and structural tool-call results. |
107
110
  | `arcane-os/ai/core-local` | Browser llama.cpp provider through an available Core connection; browser-local Wllama and ONNX remain independently available. |
108
- | `arcane-os/ai/browser-decisions` | Explicit-load Laya FP16 and Julia-1 FP32 typed decisions through the shared Transformers.js Worker owner. |
111
+ | `arcane-os/ai/browser-decisions` | Explicit-load Laya and Julia-1 typed decisions with caller-selected precision through the shared Transformers.js Worker owner. |
109
112
  | `arcane-os/ai/tool-text-stream` | Shared selected tool-argument text observer for provider integration. |
110
113
  | `arcane-os/ai/twin-cloud` | Stateless chat, System One state/questions and image generation with explicit key/model, complete results and operation-specific retry/cancellation. |
111
114
  | `arcane-os/ai/browser-speech` | Caller-selected Whisper/Kokoro, native browser recognition/synthesis, cloud TTS, upstream assets, role lifecycle and cancellation. |
@@ -405,6 +408,7 @@ The remaining data-only subpaths are eight JSON Schemas and package metadata.
405
408
  | `readCoreLaunchContext()` | function | `arcane-os/core/host` | Native Core host composition | Node; reads explicitly selected launch JSON |
406
409
  | `resolveArcaneDataPaths()` | function | `arcane-os/core/repositories` | Native repository workspaces | Node on Windows, Linux and macOS; Android supplies its data root |
407
410
  | `createRepositoryWorkspace()` | function | `arcane-os/core/repositories` | Native repository workspaces | Node with Git; Android requires host process adaptation |
411
+ | `readGitIdentity()` | function | `arcane-os/core/repositories` | Native repository workspaces | Node with Git; Android requires host process adaptation |
408
412
  | `createWindowsNativeProvider()` | function | `arcane-os/native/windows-provider` | Windows native provider | Node assembly; Windows x64/WebView2 execution |
409
413
  | `arcaneNativeBuilderProvider` | singleton | `arcane-os/native/windows-provider` | Windows native provider | Node assembly; Windows x64/WebView2 execution |
410
414
  | `arcaneNativeBuilderProvider default export` | singleton | `arcane-os/native/windows-provider` | Windows native provider | Node assembly; Windows x64/WebView2 execution |
@@ -430,6 +434,7 @@ The remaining data-only subpaths are eight JSON Schemas and package metadata.
430
434
  | `createWhisperRuntime()` | function | `arcane-os/local-ai/whisper` | Core native speech | Node with a prepared matching helper, runtime, decoder and selected model |
431
435
  | `createWhisperRuntime default export` | function | `arcane-os/local-ai/whisper` | Core native speech | Same retained native engine factory |
432
436
  | `buildWhisperHelper()` | function | `arcane-os/local-ai/whisper/build` | Core native speech | Node with installed CMake/C++17 toolchain and matching Whisper source/runtime |
437
+ | `buildWhisperOpenVinoRuntime()` | function | `arcane-os/local-ai/whisper/openvino-build` | Core native speech | Windows x64 Node with installed matching Whisper/OpenVINO sources and CMake/MSVC toolchain |
433
438
  | `createSpeechService default export` | function | `arcane-os/core/speech` | Core native speech | Same shared speech service factory |
434
439
  | `prepareCoreModelAssets()` | function | `arcane-os/ai/core-model-assets` | Core model assets | Browser with complete Blob/File members and available Core service |
435
440
  | `createModelAssetService()` | function | `arcane-os/core/model-assets` | Core model assets | Node Core with an application-selected working directory |
@@ -3737,11 +3742,19 @@ Runs one fast-forward-only pull after proving the selected repository worktree i
3737
3742
  ### Signature and result
3738
3743
 
3739
3744
  ```text
3740
- async repositoryPull({ workspaceRoot=process.cwd(), signal, onEvent, run=runProcess }={})
3745
+ async repositoryPull({ workspaceRoot=process.cwd(), target, signal, onEvent, run=runProcess }={})
3741
3746
  ```
3742
3747
 
3743
3748
  Import it from `arcane-os`. The signature above states whether settlement is synchronous or promise-based. The overview and owning group define result authority, side effects, callbacks, events, cancellation, and lifecycle.
3744
3749
 
3750
+ Optional `target:{remote,ref}` captures exact nonempty native-representable
3751
+ strings before any wait and selects `git pull --ff-only -- <remote> <ref>:`.
3752
+ The current clean branch receives a fast-forward-only integration; the SDK
3753
+ never switches branches, resets or changes configuration. Without a target,
3754
+ the existing configured pull and result remain unchanged. Targeted results
3755
+ add `target`, complete `stdout` and `stderr` to the existing pull result.
3756
+ See [checkout configuration and selected targets](core-repositories.md#existing-checkout-configuration-and-selected-targets).
3757
+
3745
3758
  ### Availability and normalization
3746
3759
 
3747
3760
  **Node; network-assisted Git.** SDK-normalized inputs, errors, events, and documented result. Deep protocol: [Node ESM](protocols.md).
@@ -3765,7 +3778,7 @@ Pushes the selected attached branch through the repository's configured remote a
3765
3778
  ### Signature, parameters, and result
3766
3779
 
3767
3780
  ```text
3768
- async repositoryPush({ workspaceRoot=process.cwd(), signal, onEvent, run=runProcess }={})
3781
+ async repositoryPush({ workspaceRoot=process.cwd(), target, signal, onEvent, run=runProcess }={})
3769
3782
  ```
3770
3783
 
3771
3784
  Import it from `arcane-os`. `workspaceRoot` selects the Git worktree. `signal`
@@ -3776,10 +3789,16 @@ should keep the default.
3776
3789
 
3777
3790
  Before pushing, the SDK runs `git rev-parse --show-toplevel`,
3778
3791
  `git branch --show-current`, and `git status --short --branch` in order. It rejects a
3779
- detached HEAD, then runs plain `git push`; the repository's current branch,
3792
+ detached HEAD, then, without `target`, runs plain `git push`; the repository's current branch,
3780
3793
  configured upstream/remote, Git credentials, hooks, and server policy remain
3781
3794
  authoritative. Unlike `repositoryPull()`, this function does **not** require a
3782
- clean worktree. It does not create a commit or select a remote/refspec for you.
3795
+ clean worktree. It does not create a commit or choose an application destination.
3796
+ Optional `target:{remote,ref}` captures the original nonempty
3797
+ native-representable strings before any wait and runs
3798
+ `git push --no-follow-tags -- <remote> HEAD:<ref>`. This publishes current HEAD
3799
+ to the caller-selected ref without force or implicit configured tag following.
3800
+ It changes no branch or Git configuration; credentials, URL interpretation,
3801
+ hooks and remote rejection remain Git-owned.
3783
3802
 
3784
3803
  The promise resolves to
3785
3804
  `{action:'push', repositoryRoot, branch, output}`. `output` is trimmed stdout,
@@ -3787,6 +3806,9 @@ or trimmed stderr when stdout is empty. A missing Git executable, failed status
3787
3806
  probe, rejected/nonzero push, cancellation, or event-callback failure rejects
3788
3807
  with the normalized process error. Cancellation stops the local process tree;
3789
3808
  it cannot prove that a remote accepted no objects before the interruption.
3809
+ Targeted results also contain the captured `target` and complete
3810
+ `stdout`/`stderr`; omitting the target preserves the existing result shape.
3811
+ See [checkout configuration and selected targets](core-repositories.md#existing-checkout-configuration-and-selected-targets).
3790
3812
 
3791
3813
  ### Availability and normalization
3792
3814
 
@@ -5209,7 +5231,7 @@ a dedicated bare Git cache. It does not create or alter a working checkout.
5209
5231
  ### Signature, lifecycle, and result
5210
5232
 
5211
5233
  ```text
5212
- createGitTextSnapshot({cacheDirectory,remote,ref,selectPath,onEvent,run=runProcess}={})
5234
+ createGitTextSnapshot({cacheDirectory,remote,ref,selectPath,gitIdentity,onEvent,run=runProcess}={})
5213
5235
  ```
5214
5236
 
5215
5237
  Import from `arcane-os`. The application owns the cache location, remote, ref,
@@ -5221,6 +5243,11 @@ await accepted refresh/process cleanup. Errors remain observable instead of
5221
5243
  returning stale or partial success. See [Git text snapshots](git-text-snapshot.md)
5222
5244
  for complete inputs, text semantics, errors, events and Core service composition.
5223
5245
 
5246
+ Optional `gitIdentity:{name?,email?,username?}` captures a child-process-only
5247
+ selection for init/fetch and subsequent Git commands, preserving shared refresh
5248
+ cancellation and complete content. See [Git identity configuration](core-repositories.md#git-identity-configuration)
5249
+ for author precedence, scoped defaults and credential username semantics.
5250
+
5224
5251
  ### Example
5225
5252
 
5226
5253
  ```js
@@ -7881,18 +7908,42 @@ explicit existing path. The application owns the remote, branch and Core API.
7881
7908
  ### Signature and result
7882
7909
 
7883
7910
  ```text
7884
- createRepositoryWorkspace({name,directory,dataRoot,remote,branch,onEvent,run=runProcess}={})
7911
+ createRepositoryWorkspace({name,directory,dataRoot,remote,branch,gitIdentity,onEvent,run=runProcess}={})
7885
7912
  ```
7886
7913
 
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,
7914
+ Returns `{directory,open,status,configuration,pull,push,write,close,drain,dispose}`. Construction does
7915
+ no I/O. Preparing operations accept `{signal}`; a missing or empty destination clones once,
7889
7916
  while existing checkout files, branches, remotes and local changes remain intact.
7890
7917
  Same-directory calls are ordered within the process. Shutdown drains accepted
7891
7918
  work and preserves the checkout. No CLI cwd, launch state, preference, snapshot
7892
7919
  cache or existing user-data location changes. See the [complete inputs, results,
7893
7920
  errors and lifecycle](core-repositories.md#one-connected-working-checkout).
7894
7921
 
7895
- `write({files:[{path,content}],message,signal})` snapshots the exact selected
7922
+ Optional `gitIdentity:{name?,email?,username?}` captures explicit non-secret
7923
+ settings for child Git operations without writing global/local configuration.
7924
+ Selected author fields override inherited child author/committer fields;
7925
+ omitted fields remain inherited. Username remains a credential hint, with
7926
+ authentication owned by ordinary Git and its configured helper.
7927
+
7928
+ `configuration({signal})` observes an existing working root without clone,
7929
+ initialization or fetch. It returns `{repositoryRoot,headRef,origin,upstream}`:
7930
+ full symbolic HEAD (including unborn, null when detached), origin URL/pushURL
7931
+ arrays and current branch remote/merge/URL/pushURL arrays. Unset, empty and
7932
+ repeated configuration values remain distinct. These are ordinary configured
7933
+ values, not authentication or endpoint proof, and are not atomic with later
7934
+ operations. Raw stdout is decoded without replacement; unrepresentable text
7935
+ reports `ARCANE_GIT_CONFIGURATION_NOT_TEXT` with full diagnostics.
7936
+
7937
+ `pull({target,signal})`, `push({target,signal})` and
7938
+ `write({files:[{path,content}],message,target,signal})` accept optional
7939
+ `target:{remote,ref}`, captured as original strings at acceptance. The target
7940
+ selects a fast-forward-only pull into the current branch or a non-force push
7941
+ of current HEAD to the selected ref, without switching branches or changing
7942
+ configuration. It is independent of initial-clone `remote`/`branch`; omission
7943
+ preserves ordinary configured behavior. See the [complete configuration and
7944
+ target contract](core-repositories.md#existing-checkout-configuration-and-selected-targets).
7945
+
7946
+ `write` snapshots the exact selected
7896
7947
  strings, writes those repository-relative files, commits only their literal
7897
7948
  paths and performs an ordinary non-force push. It retains unrelated staged
7898
7949
  paths and existing Git filters/hooks. Results and causal failures distinguish
@@ -7911,6 +7962,45 @@ await repository.open({signal});
7911
7962
  await repository.close();
7912
7963
  ```
7913
7964
 
7965
+ ## readGitIdentity()
7966
+
7967
+ ### Overview
7968
+
7969
+ Reads non-secret global, repository-local and effective Git configuration
7970
+ without changing files or querying credentials.
7971
+
7972
+ ### Signature and result
7973
+
7974
+ ```text
7975
+ readGitIdentity({directory,signal,onEvent,run=runProcess}={})
7976
+ ```
7977
+
7978
+ Import from `arcane-os/core/repositories`. Returns a promise for
7979
+ `{global,local,effective}`, each observed scope containing `{name,email,githubUser}`.
7980
+ Fields preserve complete UTF-8 strings, including empty values, leading U+FEFF
7981
+ and newlines; unset fields are `null`. Git values outside UTF-8 fail with
7982
+ `ARCANE_GIT_IDENTITY_NOT_TEXT` instead of replacement characters.
7983
+ With no directory, only global configuration is read and local/effective
7984
+ are `null`. Existing repository directories, including bare caches, select the
7985
+ context for all three observations. Configured includes and ordinary Git
7986
+ precedence remain in effect. These are config observations, not authenticated
7987
+ accounts or environment-resolved commit identities.
7988
+
7989
+ Independent scope queries run concurrently and join cleanup before settlement.
7990
+ Raw stdout is parser-owned rather than emitted as text events; an injected
7991
+ `run` must honor the existing raw-output process contract. Lifecycle and stderr
7992
+ events retain their ordinary route. Errors preserve their original object,
7993
+ code, cause and process diagnostics, with complete captured output added as
7994
+ `rawStdout` (a Buffer). The raw-mode process result retains `stdout:null`.
7995
+ If that property already exists or cannot be attached, a wrapper retains the
7996
+ original as `cause`, its code/details/exit code and this observation's raw
7997
+ output; original causal failures remain on the cause. An attachment exception
7998
+ is retained as `attachmentError`. Existing property values remain untouched.
7999
+ Decoding failures include their cause, complete process details and raw output.
8000
+ Already-represented observer errors appear once; separate failures use
8001
+ `AggregateError`. See the [complete contract and
8002
+ per-process selection example](core-repositories.md#git-identity-configuration).
8003
+
7914
8004
  ## createCoreLocalAIProvider()
7915
8005
 
7916
8006
  ### Overview
@@ -8141,7 +8231,7 @@ Whisper backend libraries, decoder and model files; see the complete
8141
8231
 
8142
8232
  | Member | Contract |
8143
8233
  | --- | --- |
8144
- | `current()` | Returns `providerId`, `modelId`, `state`, `loaded`, `busy`, `requestId`, `requestedBackend`, `observedBackend`, `backendEvidence` and `error`. State reports actual helper/model readiness. |
8234
+ | `current()` | Returns `providerId`, `modelId`, `state`, `loaded`, `busy`, `requestId`, `requestedBackend`, `observedBackend`, `backendEvidence`, `requestedEncoder`, `observedEncoder`, `encoderEvidence` and `error`. State reports actual helper/model readiness; encoder and decoder initialization evidence remain separate. |
8145
8235
  | `subscribe(listener,{replay=true,signal}={})` | Observes the current snapshot immediately by default, then each state change; returns the unsubscribe closure. |
8146
8236
  | `load({modelId,signal}={})` | Prepares the selected runtime if necessary and retains its initialized helper/model. Same-model loading is shared; replacement remains explicit. |
8147
8237
  | `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. |
@@ -8205,6 +8295,43 @@ includes the selected compiler's redistributable runtime closure. Use a
8205
8295
  toolchain and prepared runtime matching the target platform/architecture; a
8206
8296
  source package alone is not a compiled helper. See the [helper build procedure](local-whisper.md).
8207
8297
 
8298
+ ## buildWhisperOpenVinoRuntime()
8299
+
8300
+ `buildWhisperOpenVinoRuntime({sourceDirectory,openvinoDirectory,cudaDirectory,
8301
+ outputRoot,cmake='cmake',generator,cmakeArgs=[],env,signal,onEvent}={})` from
8302
+ `arcane-os/local-ai/whisper/openvino-build` produces the optional native Intel
8303
+ NPU encoder runtime on Windows x64. This producer uses an already installed
8304
+ compatible CMake/MSVC environment, Whisper 1.9.4 source and OpenVINO 2026.3.1
8305
+ development tree. Required `sourceDirectory`, `openvinoDirectory` and
8306
+ `outputRoot` name those inputs and the producer-owned output. It installs no
8307
+ driver, toolchain or model and performs no inference.
8308
+
8309
+ The producer copies Whisper source into `outputRoot/source`, applies its
8310
+ encoder-failure propagation and stderr diagnostic corrections there, and runs
8311
+ CMake configure/build into `outputRoot/build`. The original source stays
8312
+ unchanged. It assembles the runtime under `outputRoot/runtime`, retaining
8313
+ OpenVINO/NPU, CPU, TBB, import libraries and packaging notices. Optional
8314
+ `cudaDirectory` names the matching upstream b5130 CUDA library directory;
8315
+ its selected precompiled backend libraries add CUDA alongside CPU. Omission
8316
+ produces the NPU-plus-CPU tree. `cmake`, `generator`, `cmakeArgs` and `env`
8317
+ configure the existing build environment.
8318
+
8319
+ The result is `{version,openvinoVersion,platform,architecture,encoder,backend,
8320
+ backends,root,directory,libraryDirectory,sourceDirectory,diagnostics}`.
8321
+ `directory` equals `root`; the returned `sourceDirectory` is the copied source.
8322
+ `diagnostics` retains complete `configure` and `compile` process results.
8323
+ `signal` and `onEvent` use the existing process cancellation and diagnostic
8324
+ contract. Missing required strings produce a `TypeError`; an unsupported
8325
+ producer host or unmatched source correction reports an error. Filesystem,
8326
+ process, cancellation and observer failures remain observable, with partial
8327
+ producer output left for its owner.
8328
+
8329
+ Build the matching first-party helper separately with `buildWhisperHelper`,
8330
+ then retain its complete installed `bin` alongside this runtime. The
8331
+ [complete producer example](../guides/native-whisper-openvino.md#produce-the-optional-native-runtime)
8332
+ covers that composition. Applications normally select the precompiled asset
8333
+ through `encoder: 'openvino-npu'`; they do not run this producer at startup.
8334
+
8208
8335
  ## createSpeechService()
8209
8336
 
8210
8337
  ### Overview and usage
@@ -8983,14 +9110,19 @@ native installation eligibility and URL-bar promotion.
8983
9110
 
8984
9111
  ### Overview
8985
9112
 
8986
- Creates an explicitly loaded browser model for Laya typed decisions in FP16 or
8987
- Julia-1 in FP32. The shared Worker owns Transformers.js loading, full-input
9113
+ Creates an explicitly loaded browser model for Laya typed decisions or
9114
+ Julia-1. Laya defaults to FP16 and Julia to FP32; callers may select `dtype`
9115
+ explicitly. The shared Worker owns Transformers.js loading, full-input
8988
9116
  encoding, batched inference, complete results, cancellation and resource lifetime.
8989
9117
  Applications own model selection, questions, option meanings and decision policy.
8990
9118
  Existing chat and speech providers are unchanged.
8991
9119
 
8992
9120
  ### Signature and result
8993
9121
 
9122
+ ```text
9123
+ createBrowserDecisionModel({family,model,revision,device,dtype,runtime}={})
9124
+ ```
9125
+
8994
9126
  ```js
8995
9127
  import {createBrowserDecisionModel} from 'arcane-os/ai/browser-decisions';
8996
9128
 
@@ -9015,8 +9147,11 @@ precision, tokenization, output meanings, lifecycle and model limitations.
9015
9147
  ### Availability and normalization
9016
9148
 
9017
9149
  Browser module Workers plus the selected Transformers.js backend are required
9018
- on explicit use. Import and construction do not activate a model. Laya fixes
9019
- `dtype: 'fp16'`; Julia fixes `dtype: 'fp32'`; there is no precision fallback.
9150
+ on explicit use. Import and construction do not activate a model. The optional
9151
+ nonempty `dtype` string defaults to `fp16` for Laya and `fp32` for Julia. An
9152
+ explicit value is forwarded unchanged to the upstream loader; unsupported
9153
+ selections report its failure without precision fallback. For Laya FP32, pass
9154
+ `dtype: 'fp32'`.
9020
9155
  Cancellation terminates that client's Worker and rejects its in-flight work.
9021
9156
  No decisions are inserted into chat history or durable storage.
9022
9157
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcane-os",
3
- "version": "0.65.0",
3
+ "version": "0.67.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",
@@ -69,6 +69,7 @@
69
69
  "./core/preferences": "./src/core/services/preferences.mjs",
70
70
  "./core/diarization": "./src/diarization/service.mjs",
71
71
  "./core/local-ai": "./src/core/services/local-ai.mjs",
72
+ "./core/decisions": "./src/core/services/decisions.mjs",
72
73
  "./core/image": "./src/core/services/image.mjs",
73
74
  "./core/speech": "./src/core/services/speech.mjs",
74
75
  "./core/model-assets": "./src/core/services/model-assets.mjs",
@@ -76,6 +77,7 @@
76
77
  "./diarization/build": "./src/diarization/build.mjs",
77
78
  "./local-ai": "./src/local-ai/install.mjs",
78
79
  "./local-ai/onnx": "./src/local-ai/onnx.mjs",
80
+ "./local-ai/decisions": "./src/local-ai/decisions.mjs",
79
81
  "./local-ai/image": "./src/local-ai/image-runtime.mjs",
80
82
  "./local-ai/whisper": "./src/local-ai/whisper/index.mjs",
81
83
  "./local-ai/whisper/build": "./src/local-ai/whisper/build.mjs",
@@ -121,7 +123,7 @@
121
123
  "test": "npm run test:unit && npm run test:functional && npm run test:integration && npm run test:regression",
122
124
  "test:release": "node ./bin/arcane-test.mjs test/npm-release.test.mjs",
123
125
  "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",
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",
126
+ "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-ai-installation.test.mjs test/core-llama-lifecycle.test.mjs test/core-development.test.mjs test/core-host.test.mjs test/core-model-assets.test.mjs test/core-native-services.test.mjs test/core-packaged-web.test.mjs test/core-runtime.test.mjs test/core-stdio.test.mjs test/dbopfs-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-decisions.test.mjs test/native-onnx.test.mjs test/native-module-packaging.test.mjs test/native-module-resource-references.test.mjs test/packaging.test.mjs test/pwa-packaging.test.mjs test/pwa-client.test.mjs test/pwa-install.test.mjs test/pwa-worker.test.mjs test/persistent-ai-chat-session.test.mjs test/reference-completeness.test.mjs test/rendered-print.test.mjs test/runtime-api-behavior.test.mjs test/runtime.test.mjs test/scaffold.test.mjs test/speech-playback.test.mjs test/site.test.mjs test/theme-manager.test.mjs test/twin-cloud-images.test.mjs test/twin-cloud.test.mjs test/websocket-client-import-map.test.mjs test/websocket.test.mjs test/update-check.test.mjs test/user-explicit-updates.test.mjs",
125
127
  "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",
126
128
  "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",
127
129
  "check": "node tools/check-source.mjs && npm test",
@@ -158,6 +160,7 @@
158
160
  "tag": "latest"
159
161
  },
160
162
  "dependencies": {
163
+ "@huggingface/tokenizers": "0.2.0",
161
164
  "event-pubsub": "6.1.1",
162
165
  "js-queue": "3.1.1",
163
166
  "node-http-server": "10.0.0",
@@ -4,7 +4,11 @@ import path from 'node:path';
4
4
  import Is from 'strong-type';
5
5
  import {ArcaneError, throwIfAborted} from '../errors.mjs';
6
6
  import {runProcess} from '../process.mjs';
7
- import {repositoryPull, repositoryPush, repositoryStatus} from '../repository.mjs';
7
+ import {captureRepositoryTarget, repositoryConfiguration, repositoryPull, repositoryPush,
8
+ repositoryPushArguments, repositoryStatus} from '../repository.mjs';
9
+ import {createGitIdentityRunner} from '../git-identity.mjs';
10
+
11
+ export {readGitIdentity} from '../git-identity.mjs';
8
12
 
9
13
  const is = new Is(false);
10
14
  const directoryOperations = new Map();
@@ -41,7 +45,7 @@ export function resolveArcaneDataPaths({dataRoot} = {}) {
41
45
 
42
46
  /** One connected checkout, composed into an application's own Core service. */
43
47
  export function createRepositoryWorkspace(
44
- {name, directory, dataRoot, remote, branch, onEvent, run = runProcess} = {}
48
+ {name, directory, dataRoot, remote, branch, gitIdentity, onEvent, run = runProcess} = {}
45
49
  ) {
46
50
  let selected = directory;
47
51
  if (selected === undefined) {
@@ -55,12 +59,13 @@ export function createRepositoryWorkspace(
55
59
  if (remote !== undefined) requireString(remote, 'remote');
56
60
  if (branch !== undefined) requireString(branch, 'branch');
57
61
  if (!is.function(run)) throw new TypeError('run must implement the SDK process adapter.');
62
+ const execute = createGitIdentityRunner(run, gitIdentity);
58
63
  const repositoryDirectory = path.resolve(selected);
59
64
  const pending = new Set();
60
65
  let opened = false;
61
66
  let closing = null;
62
67
 
63
- async function prepare(signal, execute = run) {
68
+ async function prepare(signal, prepareRun = execute) {
64
69
  throwIfAborted(signal);
65
70
  if (opened) return {directory: repositoryDirectory, cloned: false};
66
71
  let entries;
@@ -74,7 +79,7 @@ export function createRepositoryWorkspace(
74
79
  if (entries.length) {
75
80
  // A parent checkout or a bare object cache is not this connection's
76
81
  // working root. Inspection never changes an existing destination.
77
- const result = await execute(
82
+ const result = await prepareRun(
78
83
  'git',
79
84
  ['rev-parse', '--is-inside-work-tree', '--show-prefix'],
80
85
  {cwd: repositoryDirectory, signal, onEvent}
@@ -97,7 +102,7 @@ export function createRepositoryWorkspace(
97
102
  const arguments_ = ['clone', '--progress'];
98
103
  if (branch !== undefined) arguments_.push('--branch', branch);
99
104
  arguments_.push('--', remote, repositoryDirectory);
100
- const result = await execute(
105
+ const result = await prepareRun(
101
106
  'git',
102
107
  arguments_,
103
108
  {cwd: path.dirname(repositoryDirectory), signal, onEvent}
@@ -142,35 +147,52 @@ export function createRepositoryWorkspace(
142
147
  return accept(
143
148
  async function readRepositoryStatus() {
144
149
  await prepare(signal);
145
- return repositoryStatus({workspaceRoot: repositoryDirectory, signal, onEvent, run});
150
+ return repositoryStatus({workspaceRoot: repositoryDirectory, signal, onEvent, run: execute});
151
+ },
152
+ signal
153
+ );
154
+ }
155
+
156
+ function configuration({signal} = {}) {
157
+ return accept(
158
+ function readRepositoryConfiguration() {
159
+ return repositoryConfiguration({workspaceRoot: repositoryDirectory, signal, onEvent, run: execute});
146
160
  },
147
161
  signal
148
162
  );
149
163
  }
150
164
 
151
- function pull({signal} = {}) {
165
+ function pull({target, signal} = {}) {
166
+ let selectedTarget;
167
+ try { selectedTarget = captureRepositoryTarget(target); }
168
+ catch (error) { return Promise.reject(error); }
152
169
  return accept(
153
170
  async function pullRepository() {
154
171
  await prepare(signal);
155
- return repositoryPull({workspaceRoot: repositoryDirectory, signal, onEvent, run});
172
+ return repositoryPull({workspaceRoot: repositoryDirectory, target: selectedTarget, signal, onEvent, run: execute});
156
173
  },
157
174
  signal
158
175
  );
159
176
  }
160
177
 
161
- function push({signal} = {}) {
178
+ function push({target, signal} = {}) {
179
+ let selectedTarget;
180
+ try { selectedTarget = captureRepositoryTarget(target); }
181
+ catch (error) { return Promise.reject(error); }
162
182
  return accept(
163
183
  async function pushRepository() {
164
184
  await prepare(signal);
165
- return repositoryPush({workspaceRoot: repositoryDirectory, signal, onEvent, run});
185
+ return repositoryPush({workspaceRoot: repositoryDirectory, target: selectedTarget, signal, onEvent, run: execute});
166
186
  },
167
187
  signal
168
188
  );
169
189
  }
170
190
 
171
- function write({files, message, signal} = {}) {
191
+ function write({files, message, target, signal} = {}) {
172
192
  let selectedFiles;
193
+ let selectedTarget;
173
194
  try {
195
+ selectedTarget = captureRepositoryTarget(target);
174
196
  requireString(message, 'message');
175
197
  if (!message.isWellFormed()) throw new TypeError('message cannot be represented completely as UTF-8 text.');
176
198
  if (!is.array(files) || files.length === 0) {
@@ -206,6 +228,7 @@ export function createRepositoryWorkspace(
206
228
  async function writeRepositoryFiles() {
207
229
  const outcome = {
208
230
  directory: repositoryDirectory,
231
+ ...(selectedTarget === undefined ? {} : {target: {...selectedTarget}}),
209
232
  state: 'local',
210
233
  stage: 'prepare',
211
234
  paths: selectedFiles.map(function selectedPath(file) { return file.path; }),
@@ -260,7 +283,7 @@ export function createRepositoryWorkspace(
260
283
  }
261
284
 
262
285
  try {
263
- const result = await run(
286
+ const result = await execute(
264
287
  'git',
265
288
  args,
266
289
  {cwd: options.cwd ?? repositoryDirectory, signal, onEvent: observeEvent,
@@ -317,7 +340,7 @@ export function createRepositoryWorkspace(
317
340
  ['--literal-pathspecs', 'commit', '--only', '--cleanup=verbatim', '--file', '-', '--', ...outcome.paths],
318
341
  commitMessage()
319
342
  );
320
- await executeGit('push', ['push']);
343
+ await executeGit('push', repositoryPushArguments(selectedTarget));
321
344
  outcome.stage = 'complete';
322
345
  return outcome;
323
346
  } catch (cause) {
@@ -353,7 +376,7 @@ export function createRepositoryWorkspace(
353
376
  return closing;
354
377
  }
355
378
 
356
- return {directory: repositoryDirectory, open, status, pull, push, write, close, drain: close, dispose: close};
379
+ return {directory: repositoryDirectory, open, status, configuration, pull, push, write, close, drain: close, dispose: close};
357
380
  }
358
381
 
359
382
  function requireString(value, name) {
@@ -150,11 +150,22 @@ class CoreRuntime {
150
150
  };
151
151
  }
152
152
 
153
+ async getService(name) {
154
+ if (this.#closing) throw failure('CORE_CLOSING', 'Core is closing.');
155
+ const service = this.#services.get(name);
156
+ if (!service) throw failure('CORE_SERVICE_UNAVAILABLE', `Core service ${String(name)} is not registered.`);
157
+ await this.#startService(service);
158
+ return service.definition;
159
+ }
160
+
153
161
  #serviceContext(service) {
154
162
  const runtime = this;
155
163
  return {
156
164
  application: this.#application,
157
165
  service: service.name,
166
+ getService(name) {
167
+ return runtime.getService(name);
168
+ },
158
169
  emit(event, data) {
159
170
  return runtime.emit(event, data);
160
171
  }