arcane-os 0.56.0 → 0.57.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 (41) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +1 -1
  3. package/browser-runtime/ai/core-local.mjs +306 -0
  4. package/docs/reference/README.md +20 -0
  5. package/docs/reference/cli.md +9 -1
  6. package/docs/reference/core-native-packaging.md +195 -11
  7. package/docs/reference/inventory/package-api.json +138 -12
  8. package/docs/reference/local-ai.md +197 -0
  9. package/docs/reference/protocols.md +69 -1
  10. package/docs/reference/runtime-modules.md +6 -5
  11. package/docs/reference/sdk-api.md +165 -26
  12. package/package.json +5 -1
  13. package/runtime/arcane/modules/LocalAIReadiness.js +3 -1
  14. package/schemas/arcane-app.schema.json +54 -0
  15. package/schemas/arcane-package.schema.json +44 -0
  16. package/src/app-descriptor.mjs +17 -1
  17. package/src/cli/main.mjs +8 -2
  18. package/src/core/host.mjs +23 -0
  19. package/src/core/hosts/macos/ArcaneCoreProcess.h +85 -0
  20. package/src/core/hosts/macos/ArcaneCoreProcess.m +357 -0
  21. package/src/core/hosts/windows/ArcaneCoreProcess.cs +3 -3
  22. package/src/core/hosts/windows/ArcaneHost.cs +695 -0
  23. package/src/core/hosts/windows/ArcaneHost.manifest +22 -0
  24. package/src/core/hosts/windows/ArcaneLauncher.cs +239 -0
  25. package/src/core/services/local-ai.mjs +543 -0
  26. package/src/dev-server.mjs +7 -0
  27. package/src/import-map.mjs +1 -0
  28. package/src/local-ai/archive.mjs +52 -0
  29. package/src/local-ai/config.mjs +62 -0
  30. package/src/local-ai/dev.mjs +390 -0
  31. package/src/local-ai/discover.mjs +71 -0
  32. package/src/local-ai/http.mjs +106 -0
  33. package/src/local-ai/install.mjs +344 -0
  34. package/src/local-ai/server.mjs +262 -0
  35. package/src/native/portable-layout.mjs +29 -4
  36. package/src/native/portable-provider.mjs +39 -8
  37. package/src/native/windows-provider.mjs +262 -0
  38. package/src/native-provider-loader.mjs +8 -2
  39. package/src/packager/core.mjs +6 -2
  40. package/src/process.mjs +66 -8
  41. package/src/toolchain.mjs +33 -5
@@ -55,6 +55,8 @@ runtime layouts.
55
55
  | `arcane-os/core/runtime` | App-neutral native Core dispatcher and service lifecycle. |
56
56
  | `arcane-os/core/stdio` | Framed Node stdio transport with graceful runtime drain. |
57
57
  | `arcane-os/core/host` | Node-only reusable Core host lifecycle with explicitly supplied services. |
58
+ | `arcane-os/core/local-ai` | Native llama.cpp and Ollama Core service, model readiness, complete streaming and owned process lifecycle. See [local AI through Core](local-ai.md). |
59
+ | `arcane-os/local-ai` | Official runtime installation and native artifact bundling for selected llama.cpp/Ollama requirements. |
58
60
  | `arcane-os/integrated-provider` | Fixed integrated shared-development provider. |
59
61
  | `arcane-os/packager` | Low-level browser app packager. |
60
62
  | `arcane-os/release-bundle` | Deterministic external release bundles. |
@@ -83,6 +85,7 @@ runtime layouts.
83
85
  | `arcane-os/browser-device` | Synchronous mobile or desktop identity hints for application-owned settings. |
84
86
  | `arcane-os/pwa` | Nonblocking PWA registration, worker updates, native installation state and a dismissible installation component. |
85
87
  | `arcane-os/ai/browser-wasm` | Caller-selected browser-local Wllama inference, complete DBOPFS model storage, streaming, cancellation, and structural tool-call results. |
88
+ | `arcane-os/ai/core-local` | Browser llama.cpp provider through an available Core connection; browser-local Wllama and ONNX remain independently available. |
86
89
  | `arcane-os/ai/browser-decisions` | Explicit-load Laya FP16 and Julia-1 FP32 typed decisions through the shared Transformers.js Worker owner. |
87
90
  | `arcane-os/ai/tool-text-stream` | Shared selected tool-argument text observer for provider integration. |
88
91
  | `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. |
@@ -362,6 +365,7 @@ The remaining data-only subpaths are eight JSON Schemas and package metadata.
362
365
  | `createCoreClient()` | function | `arcane-os/core/client` | Core browser client | Browser and native WebView JavaScript hosts |
363
366
  | `createCoreFacade()` | function | `arcane-os/core/client` | Core browser client | Browser and native WebView JavaScript hosts |
364
367
  | `installCoreClient()` | function | `arcane-os/core/client` | Core browser client | Browser and native WebView JavaScript hosts |
368
+ | `getInstalledCoreClient()` | function | `arcane-os/core/client` | Core browser client | Browser and native WebView JavaScript hosts |
365
369
  | `createCoreClassicSource()` | function | `arcane-os/core/classic-source` | Core classic client projection | Node; generated source runs in browser and native WebView renderers |
366
370
  | `createCoreRuntime()` | function | `arcane-os/core/runtime` | Native Core runtime | Node on Windows, Linux and macOS native hosts; Android requires host adaptation |
367
371
  | `encodeCoreFrame()` | function | `arcane-os/core/stdio` | Native Core stdio transport | Node |
@@ -807,7 +811,7 @@ descriptor-selected browser document inventory.
807
811
  ### Signature and result
808
812
 
809
813
  ```text
810
- async inspectApp({workspaceRoot, appId, signal}={})
814
+ async inspectApp({workspaceRoot, appId, signal, target, outputDirectory}={})
811
815
  ```
812
816
 
813
817
  Import it from `arcane-os` or `arcane-os/packager`. The result includes the
@@ -834,9 +838,18 @@ such as `apps/hello-world/index.html`. The complete `files` inventory uses
834
838
  package-relative paths and includes the root `index.html`. Shared
835
839
  files retain their configured route destinations.
836
840
 
837
- `output` is the selected workspace-relative final package directory. It uses
838
- the app's optional `arcane-package.json` `outputDirectory` directly, or
839
- `dist/<app-id>` when omitted; the SDK appends no app ID to an explicit value.
841
+ `target` defaults to `'browser'`. A selected nonbrowser target adds the app's
842
+ explicit `nativeResources` to `files`, without adding those native-only paths
843
+ to `browserDocuments`. The optional normalized `nativeResources` record is
844
+ returned when authored. This inspection copies or executes no resources.
845
+
846
+ `output` is the selected workspace-relative final package directory. An explicit
847
+ operation `outputDirectory` wins. Otherwise, a nonbrowser target with a nonempty
848
+ native include list uses `dist/.native/<target>/<app-id>`; the app's saved browser
849
+ destination remains separate. Browser selection, omitted native resources and
850
+ an empty native include list use the app's saved `outputDirectory` or
851
+ `dist/<app-id>`. The SDK appends no app ID to an explicit destination. See
852
+ [native-only application resources](protocols.md#native-only-application-resources).
840
853
 
841
854
  ### Availability and normalization
842
855
 
@@ -881,9 +894,10 @@ console.log(normalizeRelativePath('apps/example/index.html'));
881
894
 
882
895
  ### Overview
883
896
 
884
- Builds one complete browser application release through the low-level packager
885
- API. It does not run tests or checks automatically; verification occurs only
886
- when explicitly requested or when required for this selected release output.
897
+ Builds one complete selected application release through the low-level packager
898
+ API, with browser selection by default. It does not run tests or checks
899
+ automatically; verification occurs only when explicitly requested or when
900
+ required for this selected release output.
887
901
 
888
902
  ### Signature and result
889
903
 
@@ -898,6 +912,21 @@ The package preserves the complete selected content, applying the documented
898
912
  asset-version and enabled browser-PWA transformations to resource references.
899
913
  Malformed configuration or descriptors fail while preserving the prior output.
900
914
 
915
+ `target` defaults to `'browser'`; supported target names are `browser`,
916
+ `portable`, `windows-x64`, `linux-x64`, `linux-arm64` and `android-arm64`.
917
+ A nonbrowser target adds the app's explicit `nativeResources` selection and
918
+ sets the effective `browserPwa` value to `false`. It does not compile or launch
919
+ that platform. Browser calls preserve the existing `browserPwa` default and
920
+ explicit setting. The app adapter's `buildArcanePackage()` context receives
921
+ the actual `target` and effective `browserPwa` alongside its existing fields.
922
+ `copyBase()` retains the browser/shared selection; native-only resources are
923
+ copied afterward, outside browser rewriting and PWA processing.
924
+
925
+ `moduleFormat` controls browser module representation independently of `target`.
926
+ In particular, `moduleFormat:'native'` alone remains a browser package and does
927
+ not add native resources. The complete selection and separate-output rules are
928
+ documented under [native-only application resources](protocols.md#native-only-application-resources).
929
+
901
930
  `moduleFormat` defaults to `'import-map'`, preserving the ordinary browser
902
931
  package. Select `'native'` to resolve saved document import maps into native
903
932
  module URLs in the package stage and emit executable inline scripts as external
@@ -938,8 +967,8 @@ manifest or an operating-system launcher. Native-mode dry runs report selected
938
967
  input files; generated script/context files are included in the completed
939
968
  package's full returned inventory.
940
969
 
941
- The app's optional schema-1 `outputDirectory` selects the final
942
- workspace-relative destination. For example, `"ai"` emits directly into
970
+ For browser selection, the app's optional schema-1 `outputDirectory` selects the
971
+ final workspace-relative destination. For example, `"ai"` emits directly into
943
972
  `<workspace>/ai`; omission retains `dist/<app-id>`. The selected directory is
944
973
  wholly replaced through the existing staged swap, not merged. Changing the
945
974
  destination preserves the former output and siblings. Conflicting source,
@@ -947,6 +976,13 @@ selected input, or required control paths fail before output writes. Source
947
976
  layout, app identity, OPFS scope, and internal package paths remain unchanged.
948
977
  See [app-selected package output](protocols.md#app-selected-package-output).
949
978
 
979
+ For a nonbrowser target with a nonempty native include list, the default is
980
+ instead `dist/.native/<target>/<app-id>`, preserving a separately emitted browser
981
+ output even when its saved destination is custom. An explicit operation
982
+ `outputDirectory` still wins; choose a dedicated destination because packaging
983
+ replaces that selected directory. Omitted or empty native resources retain the
984
+ existing destination rules.
985
+
950
986
  Root app files retain their paths at the output root; explicitly nested apps
951
987
  retain their `apps/<id>/` paths. Shared files retain their configured route
952
988
  destinations. When the selected content supplies no root `index.html`, the SDK
@@ -1147,9 +1183,15 @@ console.log(validateAppBundlePath('payload/apps/example/index.html'));
1147
1183
 
1148
1184
  Validates one schema-1 packager app configuration and its relationship to the root config.
1149
1185
 
1150
- Optional `outputDirectory` is the final workspace-relative package directory;
1151
- omission preserves `dist/<app-id>`. It is an app package field, not a change to
1152
- the root configuration's `distRoot` or the schema-2 app identity. Packaging
1186
+ Optional `nativeResources` contains a required literal-path `include` array
1187
+ (which may be empty) and optional `exclude` array (default `[]`). It selects
1188
+ additional app-owned resources only for a nonbrowser packaging target. Ordinary
1189
+ `include`, `exclude`, shared routes and document selection remain unchanged.
1190
+
1191
+ Optional `outputDirectory` is the saved workspace-relative browser package
1192
+ directory; omission preserves `dist/<app-id>`. Nonempty native selection uses
1193
+ the separate target-selected default described above. It is an app package
1194
+ field, not a change to the root configuration's `distRoot` or the schema-2 app identity. Packaging
1153
1195
  reports conflicting output/input selections with `ARCANE_PACKAGE_INVALID`
1154
1196
  before output writes. Authored-descriptor comparison treats the destination
1155
1197
  as package-local, and descriptor refresh preserves the existing setting.
@@ -1216,7 +1258,8 @@ async function usevalidateRootConfig(...arguments_) {
1216
1258
 
1217
1259
  ### Overview
1218
1260
 
1219
- Authenticates one existing browser app release through the low-level packager API.
1261
+ Reads one existing application release and compares its complete file inventory
1262
+ with its release manifest through the low-level packager API.
1220
1263
 
1221
1264
  ### Signature and result
1222
1265
 
@@ -1228,6 +1271,9 @@ Import it from `arcane-os` or `arcane-os/packager`. The signature above states w
1228
1271
 
1229
1272
  Optional `outputDirectory` selects the same workspace-relative override accepted
1230
1273
  by `packageApp`, without changing the app's saved destination.
1274
+ For a target-selected native input release, pass the returned `release.output`
1275
+ as this override. `verifyApp` has no target option and does not infer the native
1276
+ directory or execute the application, its services or a platform host.
1231
1277
 
1232
1278
  ### Availability and normalization
1233
1279
 
@@ -1238,9 +1284,13 @@ by `packageApp`, without changing the app's saved destination.
1238
1284
  ```javascript
1239
1285
  import {verifyApp} from 'arcane-os';
1240
1286
 
1241
- async function useverifyApp(...arguments_) {
1242
- return verifyApp(...arguments_);
1243
- }
1287
+ // release is the result of packageApp() for this app and workspace.
1288
+ const inspected = await verifyApp({
1289
+ workspaceRoot,
1290
+ appId: 'moon-dashboard',
1291
+ outputDirectory: release.output
1292
+ });
1293
+ console.log(inspected.files);
1244
1294
  ```
1245
1295
 
1246
1296
  ## verifyAppReleaseBundle()
@@ -2210,6 +2260,13 @@ omitted and an authored empty list stays `[]`, so projection preserves automatic
2210
2260
  discovery versus entry-only selection. See
2211
2261
  [application document selection](protocols.md#application-document-selection).
2212
2262
 
2263
+ Optional `package.nativeResources` becomes top-level `nativeResources`.
2264
+ Omission remains omitted, an empty include remains `[]`, and an omitted exclude
2265
+ becomes `[]`. Package-only descriptor synthesis preserves the same selection.
2266
+ This is a packaging contract; `projectNativeDescriptor()` keeps its existing
2267
+ registry shape and ordinary include list. See
2268
+ [native-only application resources](protocols.md#native-only-application-resources).
2269
+
2213
2270
  ### Signature and result
2214
2271
 
2215
2272
  ```text
@@ -4336,7 +4393,17 @@ console.log(validation.sdkInstallation?.packageVersion);
4336
4393
 
4337
4394
  ### Overview
4338
4395
 
4339
- Builds and retained-verifies one explicitly selected native target through one paired provider.
4396
+ Builds one explicitly selected target through its adapter. A paired native
4397
+ builder packages the selected app and its explicit bundled-app closure, then
4398
+ passes those complete releases to the provider. Provider verification and host
4399
+ launch remain separate operations.
4400
+
4401
+ The selected target reaches each app's packager, so every app's own
4402
+ `nativeResources` and separate native input directory apply consistently to
4403
+ both copying and output-overlap calculations. The provider receives the actual
4404
+ release roots, manifests and complete file readers. An explicit `nativeBuilder`
4405
+ retains its existing identity and contract. See
4406
+ [portable Core packaging](core-native-packaging.md#native-only-application-resources).
4340
4407
 
4341
4408
  ### Signature and result
4342
4409
 
@@ -4632,8 +4699,10 @@ described by `packageApp()`.
4632
4699
  The same low-level operation resolves the app's optional `outputDirectory`;
4633
4700
  there is no separate high-level destination override. `release.outputRoot`
4634
4701
  names the resulting complete release directory, with omitted configuration
4635
- retaining `dist/<app-id>`. Browser preview, bundle creation, and native
4636
- browser-content input use that selected root.
4702
+ retaining `dist/<app-id>`. Browser preview and bundle creation use that selected
4703
+ root. This ordinary package operation retains browser selection; paired native
4704
+ assembly through `buildApplication()` separately passes its actual target and
4705
+ applies each app's native-resource output selection.
4637
4706
 
4638
4707
  Packaging does not automatically run tests or checks. Verification occurs only
4639
4708
  when explicitly requested or when required for the selected release output.
@@ -6505,8 +6574,8 @@ console.log(CORE_READY_EVENTS.includes('core.ready')); // true
6505
6574
  ### Overview
6506
6575
 
6507
6576
  Describes the public fields for request, response, event, single-request
6508
- cancellation and all-request cancellation frames. These are wire descriptions,
6509
- not application validation or method admission.
6577
+ cancellation, all-request cancellation and `runtime.replay` control frames.
6578
+ These are wire descriptions, not application validation or method admission.
6510
6579
 
6511
6580
  ### Value and import
6512
6581
 
@@ -6640,11 +6709,11 @@ the client.
6640
6709
  ### Signature and result
6641
6710
 
6642
6711
  ```text
6643
- createCoreClient({global=globalThis, transport=null, eventOwner=arcaneEvents, eventOwnerReady, autoConnect=true, onError}={})
6712
+ createCoreClient({global=globalThis, transport=null, eventOwner=arcaneEvents, eventOwnerReady, autoConnect=true, replayRuntimeState=false, onError}={})
6644
6713
  ```
6645
6714
 
6646
6715
  Import it from `arcane-os/core/client`. The result exposes `invoke`, `receive`,
6647
- `connect`, `close`, `cancelAll`, `events`, `eventsReady`, `runtime.current()`,
6716
+ `connect`, `close`, `failTransport`, `cancelAll`, `events`, `eventsReady`, `runtime.current()`,
6648
6717
  `uuid`, `protocol` and `Error`. A supplied transport must provide callable
6649
6718
  `send(frame)`; an invalid transport stays disconnected and reports
6650
6719
  `ARCANE_TRANSPORT_INVALID`. Optional `subscribe(receive)` may return its cleanup
@@ -6656,6 +6725,21 @@ its still-pending request; a failure arriving after response, cancellation or
6656
6725
  timeout reaches `onError`. Deferred event-owner connection preserves the FIFO
6657
6726
  order of queued frames and subscription actions, including reentrant delivery.
6658
6727
 
6728
+ `replayRuntimeState:true` sends one observed `runtime.replay` control after the
6729
+ receive listener and `transport.ready` are established, without delaying page
6730
+ startup. The default is `false`; select replay only with a supporting host.
6731
+ Repeated connection calls do not repeat that control, and send failures reach
6732
+ `onError`. The host replays actual dispatcher and service state without
6733
+ restarting services; transport, Core and service readiness remain distinct.
6734
+
6735
+ `failTransport(error)` ends the client after an actual terminal transport
6736
+ failure. Pending RPCs and WebKit acknowledgements reject with the complete
6737
+ `CoreError`, future invocations reject with that failure, and `onError` observes
6738
+ it once. The client releases its owned listeners, callbacks and timers without
6739
+ sending cancellation frames to the failed transport. The first terminal failure
6740
+ returns `true`; an already closed client returns `false`. Ordinary `close()`
6741
+ retains its separate cancellation behavior.
6742
+
6659
6743
  ### Availability and normalization
6660
6744
 
6661
6745
  **Browser and native WebView JavaScript hosts.** Built-in transports select
@@ -6729,8 +6813,8 @@ client.close();
6729
6813
  ### Overview
6730
6814
 
6731
6815
  Installs one synchronous `globalThis.Arcane` facade and native
6732
- `__arcaneReceive` callback. Repeated installation returns the same client for
6733
- that global lifetime.
6816
+ `__arcaneReceive` and `__arcaneTransportFailed` callbacks. Repeated installation
6817
+ returns the same client for that global lifetime.
6734
6818
 
6735
6819
  ### Signature and result
6736
6820
 
@@ -6742,6 +6826,12 @@ Import it from `arcane-os/core/client`. The returned client is the same contract
6742
6826
  as `createCoreClient()`. Closing it releases subscriptions, native callbacks,
6743
6827
  timers and pending renderer requests; it does not kill Core.
6744
6828
 
6829
+ `__arcaneTransportFailed(error)` delegates actual terminal host failures to
6830
+ `client.failTransport(error)`. Closing or failing restores previous facade and
6831
+ callback globals only while the installation still owns them, preserving later
6832
+ replacements. `getInstalledCoreClient()` returns `null` after release, including
6833
+ before an installed terminal failure reaches `onError`.
6834
+
6745
6835
  ### Availability and normalization
6746
6836
 
6747
6837
  **Browser and native WebView JavaScript hosts.** Installation makes synchronous
@@ -6761,6 +6851,41 @@ try {
6761
6851
  }
6762
6852
  ```
6763
6853
 
6854
+ ## getInstalledCoreClient()
6855
+
6856
+ ### Overview
6857
+
6858
+ Reads the existing live SDK-installed client without installing, connecting or
6859
+ replacing a facade. Applications use this accessor instead of private fields.
6860
+
6861
+ ### Signature and result
6862
+
6863
+ ```text
6864
+ getInstalledCoreClient(global=globalThis)
6865
+ ```
6866
+
6867
+ Import it from `arcane-os/core/client`. It returns the exact client installed in
6868
+ the selected global, including a classic document-created installation, or
6869
+ `null` when no live SDK installation exists. A foreign `Arcane` facade does not
6870
+ constitute an SDK installation. Close and terminal failure release the
6871
+ installation before subsequent reads.
6872
+
6873
+ ### Availability and normalization
6874
+
6875
+ **Browser and native WebView JavaScript hosts.** This synchronous read changes
6876
+ no globals and starts no service, transport or model. The returned client's
6877
+ `runtime.current()` describes transport state; service readiness remains with
6878
+ its authoritative owner. See [Core browser client](core-client.md).
6879
+
6880
+ ### Example
6881
+
6882
+ ```javascript
6883
+ import {getInstalledCoreClient} from 'arcane-os/core/client';
6884
+
6885
+ const client = getInstalledCoreClient();
6886
+ console.log(client ? client.runtime.current() : 'No SDK client is installed.');
6887
+ ```
6888
+
6764
6889
  ## createCoreClassicSource()
6765
6890
 
6766
6891
  ### Overview
@@ -6771,13 +6896,17 @@ client and contracts. It creates no copied client implementation or bundler.
6771
6896
  ### Signature and result
6772
6897
 
6773
6898
  ```text
6774
- async createCoreClassicSource({eventOwnerModuleURL}={})
6899
+ async createCoreClassicSource({eventOwnerModuleURL,replayRuntimeState=false}={})
6775
6900
  ```
6776
6901
 
6777
6902
  Import it from `arcane-os/core/classic-source`. Supply the actual served URL for
6778
6903
  the selected SDK event-manager module. The promise resolves to the complete
6779
6904
  classic-script source.
6780
6905
 
6906
+ Optional `replayRuntimeState:true` forwards the current runtime-replay selection
6907
+ to the installed client. Omission retains the existing no-replay behavior; use
6908
+ `true` only when the composing host supports `runtime.replay`.
6909
+
6781
6910
  ### Availability and normalization
6782
6911
 
6783
6912
  **Node; generated source runs in browser and native WebView renderers.** The
@@ -6821,6 +6950,11 @@ Shutdown stops admission, waits accepted responses, then runs each service's
6821
6950
  startup, drain and dispose in order while independent services close
6822
6951
  concurrently.
6823
6952
 
6953
+ The `runtime.replay` control publishes current dispatcher and service state
6954
+ without restarting services. Its snapshot preserves complete service errors
6955
+ and active request state; see [runtime replay](core-runtime.md#state-and-frames)
6956
+ for authoritative readiness and reentrant lifecycle ordering.
6957
+
6824
6958
  ### Availability and normalization
6825
6959
 
6826
6960
  **Node on Windows, Linux and macOS native hosts; Android requires its native host
@@ -9419,3 +9553,8 @@ const cancelled = normalizeAIRequestAbort(new DOMException('Cancelled', 'AbortEr
9419
9553
  ## Data export subpaths
9420
9554
 
9421
9555
  The package also exposes eight JSON Schemas (including `arcane-os/schemas/event-stack.json`) and its package manifest. These are data contracts, not callable JavaScript members. See [schema contracts](../architecture.md) and the files under `schemas/`.
9556
+
9557
+ `arcane-os/schemas/arcane-app.json` describes schema-2 `package.nativeResources`;
9558
+ `arcane-os/schemas/arcane-package.json` describes the projected schema-1
9559
+ `nativeResources`. Both use the existing literal application-relative path
9560
+ contract. See [native-only application resources](protocols.md#native-only-application-resources).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcane-os",
3
- "version": "0.56.0",
3
+ "version": "0.57.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",
@@ -39,6 +39,7 @@
39
39
  "./speech-playback": "./runtime/arcane/modules/SpeechPlayback.js",
40
40
  "./speech-text": "./browser-runtime/speech-text.mjs",
41
41
  "./ai/browser-wasm": "./browser-runtime/ai/browser-wasm.mjs",
42
+ "./ai/core-local": "./browser-runtime/ai/core-local.mjs",
42
43
  "./ai/browser-decisions": "./browser-runtime/ai/browser-decisions.mjs",
43
44
  "./ai/tool-text-stream": "./browser-runtime/ai/tool-text-stream.mjs",
44
45
  "./ai/twin-cloud": "./browser-runtime/ai/twin-cloud.mjs",
@@ -49,12 +50,15 @@
49
50
  "./native": "./src/native-plan.mjs",
50
51
  "./native-provider": "./src/native-provider-loader.mjs",
51
52
  "./native/portable-provider": "./src/native/portable-provider.mjs",
53
+ "./native/windows-provider": "./src/native/windows-provider.mjs",
52
54
  "./core/client": "./browser-runtime/core/client.mjs",
53
55
  "./core/contracts": "./browser-runtime/core/contracts.mjs",
54
56
  "./core/classic-source": "./src/core-classic-source.mjs",
55
57
  "./core/runtime": "./src/core/runtime.mjs",
56
58
  "./core/stdio": "./src/core/stdio.mjs",
57
59
  "./core/host": "./src/core/host.mjs",
60
+ "./core/local-ai": "./src/core/services/local-ai.mjs",
61
+ "./local-ai": "./src/local-ai/install.mjs",
58
62
  "./integrated-provider": "./src/integrated-provider-loader.mjs",
59
63
  "./packager": "./src/packager/core.mjs",
60
64
  "./release-bundle": "./src/release-bundle.mjs",
@@ -555,7 +555,9 @@ async function probeRequiredServices({
555
555
  arcane,
556
556
  requirements.llm.model
557
557
  )
558
- :unavailableBrowserOllama()
558
+ :is.function(arcane?.localAI?.status)
559
+ ?probeNativeOllama(arcane,requirements.llm.model)
560
+ :unavailableBrowserOllama()
559
561
  :null,
560
562
  requiresSpeech
561
563
  ?mode==='native'
@@ -119,6 +119,19 @@
119
119
  "oneOf": [{ "$ref": "#/$defs/rasterIcon" }, { "type": "null" }]
120
120
  },
121
121
  "order": { "type": "integer", "minimum": 0 },
122
+ "services": {
123
+ "description": "Explicit application-owned Core factory modules from the selected native release. Factories receive authored options first and launch context second.",
124
+ "type": "array",
125
+ "items": {
126
+ "type": "object",
127
+ "required": ["module"],
128
+ "properties": {
129
+ "module": { "$ref": "#/$defs/relativePath" },
130
+ "options": {}
131
+ }
132
+ }
133
+ },
134
+ "localAI": { "$ref": "#/$defs/localAI" },
122
135
  "bundledApps": {
123
136
  "type": "array",
124
137
  "uniqueItems": true,
@@ -240,6 +253,47 @@
240
253
  }
241
254
  ],
242
255
  "$defs": {
256
+ "localAI": {
257
+ "type": "object",
258
+ "required": ["runtimes"],
259
+ "description": "Required Core AI runtimes. Development ensures selected runtimes locally; native builds bundle their upstream runtime distributions. Model selection remains application-owned.",
260
+ "properties": {
261
+ "runtimes": {
262
+ "type": "array",
263
+ "items": {
264
+ "oneOf": [
265
+ { "enum": ["llama.cpp", "ollama"] },
266
+ {
267
+ "type": "object",
268
+ "required": ["id"],
269
+ "properties": {
270
+ "id": { "enum": ["llama.cpp", "ollama"] },
271
+ "version": { "type": "string" },
272
+ "url": { "type": "string" }
273
+ }
274
+ }
275
+ ]
276
+ }
277
+ },
278
+ "llamaCpp": {
279
+ "type": "object",
280
+ "properties": {
281
+ "url": { "type": "string" },
282
+ "model": { "type": "string" },
283
+ "modelsDirectory": { "type": "string" },
284
+ "args": { "type": "array", "items": { "type": "string" } }
285
+ }
286
+ },
287
+ "ollama": {
288
+ "type": "object",
289
+ "properties": {
290
+ "url": { "type": "string" },
291
+ "modelsDirectory": { "type": "string" },
292
+ "args": { "type": "array", "items": { "type": "string" } }
293
+ }
294
+ }
295
+ }
296
+ },
243
297
  "pwa": {
244
298
  "type": "object",
245
299
  "additionalProperties": false,
@@ -57,6 +57,9 @@
57
57
  "localAIModelPolicy": {
58
58
  "$ref": "#/$defs/localAIModelPolicy"
59
59
  },
60
+ "localAI": {
61
+ "$ref": "#/$defs/localAI"
62
+ },
60
63
  "pwa": {
61
64
  "$ref": "#/$defs/pwa"
62
65
  },
@@ -144,6 +147,47 @@
144
147
  }
145
148
  ],
146
149
  "$defs": {
150
+ "localAI": {
151
+ "type": "object",
152
+ "required": ["runtimes"],
153
+ "description": "Required Core AI runtimes. Development ensures selected runtimes locally; native builds bundle their upstream runtime distributions. Model selection remains application-owned.",
154
+ "properties": {
155
+ "runtimes": {
156
+ "type": "array",
157
+ "items": {
158
+ "oneOf": [
159
+ { "enum": ["llama.cpp", "ollama"] },
160
+ {
161
+ "type": "object",
162
+ "required": ["id"],
163
+ "properties": {
164
+ "id": { "enum": ["llama.cpp", "ollama"] },
165
+ "version": { "type": "string" },
166
+ "url": { "type": "string" }
167
+ }
168
+ }
169
+ ]
170
+ }
171
+ },
172
+ "llamaCpp": {
173
+ "type": "object",
174
+ "properties": {
175
+ "url": { "type": "string" },
176
+ "model": { "type": "string" },
177
+ "modelsDirectory": { "type": "string" },
178
+ "args": { "type": "array", "items": { "type": "string" } }
179
+ }
180
+ },
181
+ "ollama": {
182
+ "type": "object",
183
+ "properties": {
184
+ "url": { "type": "string" },
185
+ "modelsDirectory": { "type": "string" },
186
+ "args": { "type": "array", "items": { "type": "string" } }
187
+ }
188
+ }
189
+ }
190
+ },
147
191
  "pwa": {
148
192
  "type": "object",
149
193
  "additionalProperties": false,
@@ -5,6 +5,7 @@ import {readFile, writeFile} from 'node:fs/promises';
5
5
  import path from 'node:path';
6
6
  import {throwIfAborted} from './errors.mjs';
7
7
  import {normalizePwaConfig} from './pwa.mjs';
8
+ import {normalizeLocalAIConfig} from './local-ai/config.mjs';
8
9
  import {
9
10
  ARCANE_MACHINE_BUNDLE_VERSION,
10
11
  ARCANE_PROTOCOL,
@@ -235,7 +236,7 @@ function validateDocumentCatalog(value){
235
236
  }
236
237
 
237
238
  function validateNative(value,appId){
238
- assertOnlyKeys(value,new Set(['type','icon','order','bundledApps','documentCatalog']),'descriptor.native');
239
+ assertOnlyKeys(value,new Set(['type','icon','order','bundledApps','documentCatalog','localAI','services']),'descriptor.native');
239
240
  if(!NATIVE_TYPES.has(value.type))fail('descriptor.native.type is unsupported.');
240
241
  const icon=value.icon===null?null:normalizeRelativePath(value.icon,'descriptor.native.icon');
241
242
  if(!is.integer(value.order)||value.order<0){
@@ -245,11 +246,21 @@ function validateNative(value,appId){
245
246
  pattern:APP_ID_PATTERN
246
247
  });
247
248
  const documentCatalog=validateDocumentCatalog(value.documentCatalog);
249
+ let services;
250
+ if(value.services!==undefined){
251
+ if(!is.array(value.services))fail('descriptor.native.services must be an array.');
252
+ services=value.services.map(function nativeService(service,index){
253
+ if(!isObject(service))fail(`descriptor.native.services[${index}] must be an object.`);
254
+ return {...service,module:normalizeRelativePath(service.module,`descriptor.native.services[${index}].module`)};
255
+ });
256
+ }
248
257
  return completeValue({
249
258
  type:value.type,
250
259
  icon,
251
260
  order:value.order,
252
261
  bundledApps,
262
+ ...(services===undefined?{}:{services}),
263
+ ...(value.localAI===undefined?{}:{localAI:normalizeLocalAIConfig(value.localAI)}),
253
264
  ...(documentCatalog?{documentCatalog}:{})
254
265
  });
255
266
  }
@@ -337,6 +348,7 @@ export function projectPackageManifest(descriptor){
337
348
  mediaOrigins:[...value.security.mediaOrigins]
338
349
  }}:{}),
339
350
  ...(value.package.localAIModelPolicy?{localAIModelPolicy:value.package.localAIModelPolicy}:{}),
351
+ ...(value.native.localAI===undefined?{}:{localAI:value.native.localAI}),
340
352
  ...(value.package.pwa===undefined?{}:{pwa:value.package.pwa}),
341
353
  include:[...value.package.include],
342
354
  exclude:[...value.package.exclude],
@@ -382,6 +394,8 @@ export function projectNativeDescriptor(descriptor,{source}={}){
382
394
  }}:{}),
383
395
  ...(value.native.bundledApps.length?{bundledApps:[...value.native.bundledApps]}:{}),
384
396
  ...(value.native.documentCatalog?{documentCatalog:value.native.documentCatalog}:{}),
397
+ ...(value.native.services===undefined?{}:{services:value.native.services}),
398
+ ...(value.native.localAI===undefined?{}:{localAI:value.native.localAI}),
385
399
  include:[...value.package.include]
386
400
  };
387
401
  }
@@ -425,6 +439,8 @@ function synthesizedDescriptor(packageManifest,nativeDescriptor){
425
439
  icon:native.icon??null,
426
440
  order:is.integer(native.order)?native.order:100,
427
441
  bundledApps:[...(native.bundledApps??[])],
442
+ ...(native.services===undefined?{}:{services:native.services}),
443
+ ...((packageManifest.localAI??native.localAI)===undefined?{}:{localAI:packageManifest.localAI??native.localAI}),
428
444
  ...(native.documentCatalog?{documentCatalog:native.documentCatalog}:{})
429
445
  },
430
446
  requirements:{
package/src/cli/main.mjs CHANGED
@@ -16,6 +16,7 @@ const VALUE_OPTIONS=new Set([
16
16
  'app',
17
17
  'apps-root',
18
18
  'sdk-runtime-source',
19
+ 'local-ai',
19
20
  'arcane-root',
20
21
  'host',
21
22
  'port',
@@ -66,7 +67,7 @@ Usage:
66
67
  ${CLI_NAME} upgrade [--workspace <directory>] [--app <id>]
67
68
  ${CLI_NAME} doctor [--workspace <directory>] [--arcane-root <directory>]
68
69
  ${CLI_NAME} import-map [--workspace <directory>] [--app <id>]
69
- ${CLI_NAME} dev [--app <id>] [--public] [--http | --https] [--cert <pem>] [--key <pem>] [--host <address>] [--port 8000] [--http-port 0] [--sdk-runtime-source <sdk-root>]
70
+ ${CLI_NAME} dev [--app <id>] [--public] [--http | --https] [--cert <pem>] [--key <pem>] [--host <address>] [--port 8000] [--http-port 0] [--sdk-runtime-source <sdk-root>] [--local-ai llama.cpp,ollama]
70
71
  ${CLI_NAME} test [--app <id>] [--scope app]
71
72
  ${CLI_NAME} test --scope shared --test-file <repo-relative.test.mjs>
72
73
  ${CLI_NAME} check [--app <id>] [--scope app] [--skip-tests]
@@ -97,6 +98,7 @@ Development:
97
98
  --host <address> Override the bind address; takes precedence over --public.
98
99
  --http-port <port> Browser dev/run HTTP redirect port; 0 selects an available port (default).
99
100
  --sdk-runtime-source <sdk-root> Dev-only live SDK checkout; omitted preserves the workspace runtime mode.
101
+ --local-ai <runtimes> Add required Core runtimes to app config and ensure them for development.
100
102
 
101
103
  Global:
102
104
  --workspace <directory> Select an external or integrated Arcane workspace.
@@ -450,6 +452,9 @@ function operationOptions(command,parsed,cwd){
450
452
  if(values['sdk-runtime-source']!==undefined&&command!=='dev'){
451
453
  usage('--sdk-runtime-source is supported only by dev.');
452
454
  }
455
+ if(values['local-ai']!==undefined&&command!=='dev'){
456
+ usage('--local-ai is supported only by dev.');
457
+ }
453
458
  if(flags.has('public')&&command!=='dev'){
454
459
  usage('--public is supported only by dev.');
455
460
  }
@@ -546,6 +551,7 @@ function operationOptions(command,parsed,cwd){
546
551
  ...browserServerOptions,
547
552
  host:values.host??(flags.has('public')?'0.0.0.0':'127.0.0.1'),
548
553
  port:readPort(values.port,8000),
554
+ ...(values['local-ai']===undefined?{}:{localAI:values['local-ai']}),
549
555
  ...(values['sdk-runtime-source']===undefined?{}:{
550
556
  sdkRuntimeSourceRoot:path.resolve(cwd,values['sdk-runtime-source'])
551
557
  })
@@ -811,7 +817,7 @@ async function pairNativeProvider(command,options,loadProvider,{signal,onEvent}=
811
817
  usage(`${command} requires one native target.`);
812
818
  }
813
819
  const targetRequest=createNativeTargetRequest(options);
814
- if(!options.arcaneRoot&&options.target!=='portable'){
820
+ if(!options.arcaneRoot&&!['portable','windows-x64'].includes(options.target)){
815
821
  usage(`${command} for target ${options.target} requires --arcane-root <directory>.`);
816
822
  }
817
823
  const loaded=await loadProvider({