arcane-os 0.56.0 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -0
- package/README.md +6 -2
- package/browser-runtime/ai/core-local.mjs +306 -0
- package/browser-runtime/ai/core-onnx.mjs +96 -0
- package/browser-runtime/ai/onnx-tensors.mjs +85 -0
- package/browser-runtime/core/client.mjs +151 -16
- package/docs/architecture.md +5 -2
- package/docs/platform-targets.md +30 -13
- package/docs/reference/README.md +38 -3
- package/docs/reference/availability-and-normalization.md +9 -6
- package/docs/reference/cli.md +29 -9
- package/docs/reference/core-client.md +80 -0
- package/docs/reference/core-native-packaging.md +304 -12
- package/docs/reference/core-preferences.md +49 -0
- package/docs/reference/diarization.md +206 -0
- package/docs/reference/git-text-snapshot.md +104 -0
- package/docs/reference/inventory/package-api.json +330 -22
- package/docs/reference/local-ai.md +331 -0
- package/docs/reference/protocols.md +97 -20
- package/docs/reference/pwa.md +5 -2
- package/docs/reference/runtime-modules.md +6 -5
- package/docs/reference/sdk-api.md +611 -63
- package/package.json +15 -3
- package/runtime/arcane/modules/LocalAIReadiness.js +3 -1
- package/schemas/arcane-app.schema.json +55 -1
- package/schemas/arcane-package.schema.json +44 -0
- package/schemas/native-build-plan.schema.json +27 -1
- package/schemas/target-adapter.schema.json +2 -0
- package/src/app-descriptor.mjs +18 -2
- package/src/cli/main.mjs +20 -4
- package/src/constants.mjs +2 -0
- package/src/core/host.mjs +23 -0
- package/src/core/hosts/macos/ArcaneCoreProcess.h +85 -0
- package/src/core/hosts/macos/ArcaneCoreProcess.m +357 -0
- package/src/core/hosts/macos/ArcaneHost.h +86 -0
- package/src/core/hosts/macos/ArcaneHost.m +455 -0
- package/src/core/hosts/macos/ArcaneLauncher.m +432 -0
- package/src/core/hosts/windows/ArcaneCoreProcess.cs +3 -3
- package/src/core/hosts/windows/ArcaneHost.cs +695 -0
- package/src/core/hosts/windows/ArcaneHost.manifest +22 -0
- package/src/core/hosts/windows/ArcaneLauncher.cs +239 -0
- package/src/core/services/local-ai.mjs +621 -0
- package/src/core/services/packaged-web.mjs +89 -0
- package/src/core/services/preferences.mjs +201 -0
- package/src/core-classic-source.mjs +2 -2
- package/src/dev-server.mjs +9 -5
- package/src/diarization/build.mjs +35 -0
- package/src/diarization/index.mjs +432 -0
- package/src/diarization/native/CMakeLists.txt +9 -0
- package/src/diarization/native/main.cpp +269 -0
- package/src/diarization/service.mjs +129 -0
- package/src/git-text-snapshot.mjs +265 -0
- package/src/import-map.mjs +2 -0
- package/src/index.mjs +1 -0
- package/src/local-ai/archive.mjs +52 -0
- package/src/local-ai/config.mjs +62 -0
- package/src/local-ai/dev.mjs +390 -0
- package/src/local-ai/discover.mjs +71 -0
- package/src/local-ai/http.mjs +106 -0
- package/src/local-ai/install.mjs +459 -0
- package/src/local-ai/onnx-worker.mjs +85 -0
- package/src/local-ai/onnx.mjs +368 -0
- package/src/local-ai/server.mjs +262 -0
- package/src/native/macos-provider.mjs +291 -0
- package/src/native/portable-layout.mjs +37 -4
- package/src/native/portable-provider.mjs +44 -8
- package/src/native/windows-provider.mjs +262 -0
- package/src/native-plan.mjs +9 -1
- package/src/native-provider-loader.mjs +10 -2
- package/src/packager/core.mjs +6 -2
- package/src/process.mjs +184 -20
- package/src/scaffold.mjs +1 -1
- package/src/targets/index.mjs +11 -1
- package/src/templates/workspace-template.mjs +6 -5
- package/src/toolchain.mjs +33 -5
|
@@ -124,6 +124,86 @@ developer diagnostics, rather than ordinary
|
|
|
124
124
|
product status surfaces. The optional `onError(error)` callback observes
|
|
125
125
|
transport/event-owner failures outside individual request promises.
|
|
126
126
|
|
|
127
|
+
## Optional WebKit document lifetime
|
|
128
|
+
|
|
129
|
+
`webKitDocumentLifecycle:true` on `createCoreClient`, `installCoreClient` or
|
|
130
|
+
`createCoreClassicSource` selects document lifetime handling for the native
|
|
131
|
+
WebKit `arcane` handler with replies. It defaults to `false`; existing WebKit
|
|
132
|
+
plain-JSON and alternate acknowledgement transports, WebView2, Android,
|
|
133
|
+
development HTTP and supplied transports keep their existing behavior. The
|
|
134
|
+
selected host must implement this contract and the existing `runtime.replay`
|
|
135
|
+
control. Install the classic source at document start in the page's world.
|
|
136
|
+
|
|
137
|
+
The client owns a fresh activation for the current JavaScript realm and each
|
|
138
|
+
restoration from the browser's page cache. WithReply receives these transport
|
|
139
|
+
records; the Core JSON string remains unchanged in its separate `json` field:
|
|
140
|
+
|
|
141
|
+
| Record | Meaning |
|
|
142
|
+
| --- | --- |
|
|
143
|
+
| `{type:'activate', activation}` | Attach this activation before sending its Core frames. |
|
|
144
|
+
| `{type:'frame', activation, json}` | Send the complete serialized Core request or control. |
|
|
145
|
+
| `{type:'retire', activation, json}` | Retire this activation; `json` is the existing `requests.cancelAll` control. |
|
|
146
|
+
|
|
147
|
+
Reply with `{accepted:true}` or `{accepted:false,error}` on the initiating
|
|
148
|
+
WithReply promise. Frame and retirement acceptance follows the actual complete
|
|
149
|
+
process write. Queue admission alone is insufficient. Activation acceptance
|
|
150
|
+
follows the host's current-realm probe and any required prior-owner cancellation.
|
|
151
|
+
Only this activation's outgoing frames wait for attachment; page rendering,
|
|
152
|
+
facade installation and independent Core startup remain concurrent.
|
|
153
|
+
An aborted, timed-out or otherwise cancelled request awaiting attachment is
|
|
154
|
+
never submitted afterward; its existing cancellation control remains observable.
|
|
155
|
+
|
|
156
|
+
The host calls `__arcaneWebKitDocumentCurrent(activation)` in the current main
|
|
157
|
+
document's page world to probe a candidate. A token or native frame descriptor
|
|
158
|
+
alone does not identify the active document. Serialize candidate probes and
|
|
159
|
+
Core ingress ownership changes: finish each candidate's probe before processing
|
|
160
|
+
the next announcement, and leave the current owner unchanged when a probe is
|
|
161
|
+
false. Announcement arrival order cannot establish document order. A true
|
|
162
|
+
probe establishes the realm at that execution instant; every later delivery
|
|
163
|
+
still checks its target at execution time.
|
|
164
|
+
|
|
165
|
+
Before accepting a replacement activation, write the existing
|
|
166
|
+
`requests.cancelAll` control for the prior ingress owner. Do not wait for a
|
|
167
|
+
retirement announcement that a destroyed document may never send. Write a
|
|
168
|
+
retirement record's JSON only while that activation still owns ingress;
|
|
169
|
+
reject a late retirement without cancelling the replacement's requests.
|
|
170
|
+
Record request-ID-to-origin-activation correlation before submitting each
|
|
171
|
+
request to Core. Responses retain that origin. Existing generic service events
|
|
172
|
+
remain broadcasts to the current activation; no request association is added.
|
|
173
|
+
Complete native diagnostics retain frames received while no document is active;
|
|
174
|
+
restoration uses current-state replay rather than historical event delivery.
|
|
175
|
+
|
|
176
|
+
Deliver through `__arcaneReceive(json, activation)` and
|
|
177
|
+
`__arcaneTransportFailed(error, activation)`, passing payloads as native
|
|
178
|
+
JavaScript call arguments. Both return `false` for a retired or different
|
|
179
|
+
activation. Receive also returns `false` for an unrecognized frame or a
|
|
180
|
+
response with no pending request; `true` means the client accepted delivery,
|
|
181
|
+
which may still await its shared event owner. Failure returns `true` when it
|
|
182
|
+
ends that active installation. Preserve actual evaluation failures through the
|
|
183
|
+
native diagnostic owner; a `false` result is not a JavaScript exception.
|
|
184
|
+
`client.acceptsNativeDelivery(activation)` exposes the same synchronous lifetime
|
|
185
|
+
predicate. It accepts any activation while a client using an ordinary transport
|
|
186
|
+
is live. Direct owner calls to `client.failTransport(error)` retain their
|
|
187
|
+
existing terminal-failure semantics.
|
|
188
|
+
|
|
189
|
+
Page hide synchronously retires the activation even with no pending requests.
|
|
190
|
+
It clears completed ready state and rejects every pending renderer promise with
|
|
191
|
+
the existing `ARCANE_REQUEST_ABORTED`/`AbortError`. This ends the page's wait;
|
|
192
|
+
the runtime's cancellation skips service-lifetime work, so an accepted save
|
|
193
|
+
continues and participates in graceful drain. Its eventual response stays with
|
|
194
|
+
the retired activation and cannot settle a restored page's request. The client
|
|
195
|
+
does not claim that cancellation rolled back persistence.
|
|
196
|
+
|
|
197
|
+
Persisted page restoration creates a fresh activation and sends exactly one
|
|
198
|
+
`runtime.replay` after native attachment. Initial attachment sends that replay
|
|
199
|
+
only when `replayRuntimeState:true`. Application subscriptions survive page
|
|
200
|
+
hide and restoration, including registrations awaiting the shared event owner
|
|
201
|
+
and ready listeners awaiting their replay microtask. Queued deliveries from a
|
|
202
|
+
retired activation are no longer applicable to those subscriptions. Replay
|
|
203
|
+
supplies current Core/service state, not prior responses or request promises.
|
|
204
|
+
Closing the client retires once, removes lifecycle listeners and restores its
|
|
205
|
+
owned callbacks. It does not close the process or control application shutdown.
|
|
206
|
+
|
|
127
207
|
## Classic native-host injection
|
|
128
208
|
|
|
129
209
|
```js
|
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
# Portable Core packaging
|
|
2
2
|
|
|
3
3
|
`arcane-os/native/portable-provider` owns the portable native payload in the SDK
|
|
4
|
-
package. It does not load Arcane OS source, choose models
|
|
5
|
-
|
|
4
|
+
package. It does not load Arcane OS source, choose models or compile an
|
|
5
|
+
executable. An application's explicit `native.localAI` selection can include
|
|
6
|
+
its selected upstream runtimes through the SDK local-AI installer. Without that
|
|
7
|
+
selection, assembly does no local-AI runtime preparation. Windows, Linux and macOS hosts may compose this
|
|
6
8
|
Node-based payload; Android needs its separate native host adaptation. The
|
|
7
|
-
current CLI's portable platform selections
|
|
9
|
+
current CLI's portable platform selections include Windows, Linux and macOS. A portable
|
|
8
10
|
artifact is not a Windows executable, Linux package or Android application.
|
|
9
11
|
|
|
10
12
|
`loadArcaneNativeProvider({target:'portable'})` selects the installed SDK provider
|
|
11
13
|
without an `arcaneRoot`. Supplying an explicit `arcaneRoot` retains the existing
|
|
12
|
-
checkout-provider route.
|
|
14
|
+
checkout-provider route. The SDK also owns the `windows-x64` executable provider
|
|
15
|
+
described below. Other native targets remain with their actual platform
|
|
13
16
|
providers; the loader does not substitute this payload for an unavailable host.
|
|
14
17
|
|
|
15
18
|
## Provider and selected input
|
|
16
19
|
|
|
17
20
|
The default export and `arcaneNativeBuilderProvider` are the same provider.
|
|
18
|
-
`createPortableNativeProvider({services
|
|
19
|
-
service configuration.
|
|
21
|
+
`createPortableNativeProvider({services,packagedWeb=false,webKitDocumentLifecycle=false})` creates one with application-owned
|
|
22
|
+
service configuration. Without that override, the provider uses the selected
|
|
23
|
+
app descriptor's `native.services`, or an empty selection when omitted. An
|
|
24
|
+
explicit `services:[]` overrides the descriptor with no app services.
|
|
25
|
+
The Mac provider selects `packagedWeb:true` to compose the SDK's packaged-web
|
|
26
|
+
Core service and `webKitDocumentLifecycle:true` for the canonical classic-client
|
|
27
|
+
activation/replay contract. Both default to false, preserving ordinary portable
|
|
28
|
+
and Windows composition.
|
|
29
|
+
All implement `arcane-native-builder/1`:
|
|
20
30
|
|
|
21
31
|
- `describe()` identifies the portable target and `executable:false`.
|
|
22
32
|
- `doctor({targetRequest, signal, onEvent})` reports missing SDK Core source files.
|
|
@@ -42,6 +52,45 @@ receipts, hashes, content limits or security policy. The package-relative source
|
|
|
42
52
|
root comes from the provider module's own location, not `toolchainRoot` or an
|
|
43
53
|
Arcane OS machine bundle.
|
|
44
54
|
|
|
55
|
+
## Native-only application resources
|
|
56
|
+
|
|
57
|
+
Select application service modules and their complete local source closure in
|
|
58
|
+
the authored schema-2 descriptor's `package.nativeResources`, separately from
|
|
59
|
+
its browser `include`/`exclude` selection:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"package": {
|
|
64
|
+
"nativeResources": {
|
|
65
|
+
"include": ["native", "src", "package.json"],
|
|
66
|
+
"exclude": ["native/drafts"]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This is a descriptor excerpt for the app-owned service example below. The
|
|
73
|
+
projected schema-1 field is top-level `nativeResources`. Paths are literal and
|
|
74
|
+
app-relative; directories include descendants. Omission or an empty include
|
|
75
|
+
keeps previous selection and output behavior. The app supplies every required
|
|
76
|
+
source file explicitly; packaging does not discover or execute services.
|
|
77
|
+
|
|
78
|
+
Paired `buildApplication()` passes the actual native target to the selected app
|
|
79
|
+
and every explicitly bundled app. With a nonempty native include list, their
|
|
80
|
+
input releases use `dist/.native/<target>/<app-id>` instead of the saved browser
|
|
81
|
+
output, preserving existing browser/PWA artifacts. Each app's own selection is
|
|
82
|
+
applied; complete releases and actual roots are forwarded to the provider.
|
|
83
|
+
The provider then copies them unchanged into its artifact layout described below.
|
|
84
|
+
|
|
85
|
+
At the low-level `packageApp()` boundary, `target` defaults to `'browser'` and
|
|
86
|
+
is independent of `moduleFormat`. Nonbrowser selection disables generated PWA
|
|
87
|
+
content. Native-only files bypass browser document/module/asset transformations;
|
|
88
|
+
a file also in the ordinary browser selection retains that existing processing.
|
|
89
|
+
An explicit low-level `outputDirectory` still wins. Inspect the emitted input
|
|
90
|
+
with `verifyApp({workspaceRoot,appId,outputDirectory:release.output})`; neither
|
|
91
|
+
that inventory verification nor packaging launches the service or platform host.
|
|
92
|
+
See [the complete selection contract](protocols.md#native-only-application-resources).
|
|
93
|
+
|
|
45
94
|
## Output and host contract
|
|
46
95
|
|
|
47
96
|
Each build creates a fresh `arcane-portable-*` directory beneath `outputRoot`.
|
|
@@ -85,7 +134,9 @@ host must:
|
|
|
85
134
|
1. Mount `app/` at the root of its local application URL origin, preserving the
|
|
86
135
|
selected start path and all navigable documents.
|
|
87
136
|
2. Inject `runtime/arcane-api.js` at document creation. It is produced by the
|
|
88
|
-
canonical `createCoreClassicSource()` generator
|
|
137
|
+
canonical `createCoreClassicSource()` generator with `replayRuntimeState:true`.
|
|
138
|
+
Once its transport listener is attached, each document requests the current
|
|
139
|
+
Core and service state without starting services again.
|
|
89
140
|
3. Start `runtime/arcane-core.mjs` with the host's supported Node runtime and
|
|
90
141
|
connect the existing framed stdin/stdout transport.
|
|
91
142
|
4. Close input and await Core's drain before terminating the child process.
|
|
@@ -100,7 +151,21 @@ is not the native serving contract. No host is launched during packaging.
|
|
|
100
151
|
|
|
101
152
|
## Explicit application services
|
|
102
153
|
|
|
103
|
-
|
|
154
|
+
For the ordinary SDK build command, select native service modules in the
|
|
155
|
+
application's authored descriptor. Include their source closure through
|
|
156
|
+
`package.nativeResources` as described above:
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
{
|
|
160
|
+
"native": {
|
|
161
|
+
"services": [
|
|
162
|
+
{"module":"native/moon-ledger.mjs", "options":{"ledgerName":"Cheese debts"}}
|
|
163
|
+
]
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Direct SDK compositions can instead pass that selection to the provider:
|
|
104
169
|
|
|
105
170
|
```js
|
|
106
171
|
import {createPortableNativeProvider} from 'arcane-os/native/portable-provider';
|
|
@@ -111,7 +176,8 @@ const nativeBuilder = createPortableNativeProvider({
|
|
|
111
176
|
```
|
|
112
177
|
|
|
113
178
|
Each module default-exports a synchronous factory returning the existing Core
|
|
114
|
-
service definition. Its
|
|
179
|
+
service definition. Its first argument is the complete authored options record;
|
|
180
|
+
its second is the shared launch context described below. Options must be JSON-serializable data. Module imports
|
|
115
181
|
and factories run only when the generated Core entry is launched, never during
|
|
116
182
|
packaging. Put asynchronous initialization in `start()`, not a top-level await
|
|
117
183
|
or asynchronous factory, so unrelated services and dispatcher readiness remain
|
|
@@ -142,8 +208,234 @@ observable through `onError` and `closed`; no process is killed or forcibly exit
|
|
|
142
208
|
See [the Core runtime contract](core-runtime.md) for request and service lifetime
|
|
143
209
|
details and [the client contract](core-client.md) for native bridge integration.
|
|
144
210
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
211
|
+
## Launch-time locations
|
|
212
|
+
|
|
213
|
+
The generated Core entry accepts `--arcane-launch-config <path>`. The public
|
|
214
|
+
`readCoreLaunchContext({argv=process.argv.slice(2)}={})` function in
|
|
215
|
+
`arcane-os/core/host` reads that explicitly selected JSON object. Without the
|
|
216
|
+
flag it returns `{}`. Missing files, missing flag values and malformed JSON
|
|
217
|
+
report their actual errors; the reader does not search for configuration,
|
|
218
|
+
rewrite it or change the process environment.
|
|
219
|
+
|
|
220
|
+
The generated entry supplies an artifact-derived `appRoot` and then applies the
|
|
221
|
+
complete explicit launch context. Every service factory receives that same
|
|
222
|
+
object as its second argument, preserving its authored first argument. A
|
|
223
|
+
launcher can supply the user's selected `workspaceRoot` and writable
|
|
224
|
+
`stateRoot` at launch instead of embedding this machine's paths in an app
|
|
225
|
+
package. The host owns those selections; the SDK does not choose a product's
|
|
226
|
+
workspace, namespace, saved preferences or models. JSON values and additional
|
|
227
|
+
application-owned fields remain unchanged.
|
|
228
|
+
|
|
229
|
+
## Selected local-AI runtimes
|
|
230
|
+
|
|
231
|
+
When `appDescriptor.native.localAI` is present, portable assembly calls the
|
|
232
|
+
SDK's `bundleLocalAIRuntimes()` owner with its `runtimes` selection and the
|
|
233
|
+
requested target platform/architecture. Its reusable installation directory is
|
|
234
|
+
`<outputRoot>/local-ai-runtimes`; each new payload receives the complete selected
|
|
235
|
+
runtime trees beneath `runtime/local-ai/`. Runtime preparation and app copying
|
|
236
|
+
proceed independently and both settle before assembly can clean up an incomplete
|
|
237
|
+
output. No application service or model executes during packaging.
|
|
238
|
+
|
|
239
|
+
`manifest.core.localAIRuntimes` records the bundled runtime locations relative
|
|
240
|
+
to the artifact root. Only the explicitly configured entry imports
|
|
241
|
+
`createLocalAIService` from `arcane-os/core/local-ai`. It resolves those bundled
|
|
242
|
+
locations against the installed artifact and supplies them in the launch
|
|
243
|
+
context's `runtimes` array, alongside `appRoot`, before applying explicit launch
|
|
244
|
+
configuration. It passes the complete authored `native.localAI` record to the
|
|
245
|
+
factory. Applications without that selection have no generated local-AI import
|
|
246
|
+
or service. Availability of a particular engine belongs to the selected
|
|
247
|
+
local-AI installer and service; a generic ONNX runtime is not a speech model.
|
|
248
|
+
|
|
249
|
+
Selected `onnx` bundles its complete managed `onnxruntime-node` dependency tree.
|
|
250
|
+
Its `modulePath` resolves against the artifact root just as a server runtime's
|
|
251
|
+
`executable` does. Library/module records need no executable. The generated Core
|
|
252
|
+
service exposes retained worker sessions through `onnx.load/run/unload/status`;
|
|
253
|
+
model files remain caller-selected application resources. See
|
|
254
|
+
[native ONNX sessions](local-ai.md#native-onnx-sessions).
|
|
255
|
+
|
|
256
|
+
## Windows executable
|
|
257
|
+
|
|
258
|
+
The ordinary application command is:
|
|
259
|
+
|
|
260
|
+
```sh
|
|
261
|
+
npm exec -- arcane build --target windows-x64
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
`loadArcaneNativeProvider({target:'windows-x64'})` selects the SDK's own
|
|
265
|
+
`arcane-os/native/windows-provider` without an OS checkout or `arcaneRoot`.
|
|
266
|
+
Its default export and `arcaneNativeBuilderProvider` are the same provider;
|
|
267
|
+
`createWindowsNativeProvider({services,hostDirectory})` permits explicit
|
|
268
|
+
same-project composition. Service selection follows the portable provider's
|
|
269
|
+
descriptor/override contract above.
|
|
270
|
+
|
|
271
|
+
The provider assembles the selected app with the precompiled host asset
|
|
272
|
+
`arcane-native-windows-x64.tar.gz` from the numeric GitHub release matching the
|
|
273
|
+
builder's installed SDK version. The asset contains the launcher, WebView2
|
|
274
|
+
support libraries, Node SEA Core executable and required license files. It does
|
|
275
|
+
not select the newest host independently of that package. Downloads occur only
|
|
276
|
+
during `build()`, use the caller's output directory, and are reused from
|
|
277
|
+
`<outputRoot>/.arcane-native-hosts/<sdk-version>/windows-x64`. The build machine
|
|
278
|
+
needs the standard `tar` command for extraction; application builds do not need
|
|
279
|
+
a C# compiler, system Node installation for the generated executable, or host
|
|
280
|
+
source scripts. The SDK build command itself still runs through the application's
|
|
281
|
+
normal Node/npm toolchain.
|
|
282
|
+
|
|
283
|
+
An explicit `hostDirectory` selects an already-built complete host tree instead
|
|
284
|
+
of downloading one. This is useful for SDK collaborators verifying the next
|
|
285
|
+
host output; downstream applications use the published package and matching
|
|
286
|
+
release asset. `doctor()` reports the selected prerequisites and missing files;
|
|
287
|
+
it does not download the host or probe the installed WebView runtime.
|
|
288
|
+
|
|
289
|
+
The assembled directory contains `Arcane.exe`, the unchanged `app/` payload,
|
|
290
|
+
Core runtime and semantic `arcane-native.json`. Launch `Arcane.exe` on Windows
|
|
291
|
+
x64 with the Microsoft Edge WebView2 Runtime installed. It opens the selected
|
|
292
|
+
app in WebView2 and owns its framed connection to the bundled Core process.
|
|
293
|
+
`verify()` observes the assembled files and manifest; it does not execute the
|
|
294
|
+
window or prove application behavior. `run()` launches the executable and
|
|
295
|
+
observes complete diagnostics and exit. Cancelling that operation closes its
|
|
296
|
+
input, allowing the window and accepted Core service work to drain without a
|
|
297
|
+
forced process termination.
|
|
298
|
+
|
|
299
|
+
For explicit user-selected workspace/state locations, launch:
|
|
300
|
+
|
|
301
|
+
```sh
|
|
302
|
+
Arcane.exe --arcane-launch-config path/to/launch.json
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
The complete JSON object reaches the service factories as their second
|
|
306
|
+
argument. A supplied `stateRoot` also owns the WebView2 profile and diagnostic
|
|
307
|
+
directory. Otherwise the launcher uses the current user's local application
|
|
308
|
+
data under `Arcane/<app-id>`. The launcher does not invent an application
|
|
309
|
+
workspace. Relative launch-file paths resolve from the invocation's working
|
|
310
|
+
directory. `--close-on-stdin-eof` is an explicit process-owner option used by the
|
|
311
|
+
SDK runner; an ordinary double-clicked window closes through its own UI.
|
|
312
|
+
|
|
313
|
+
## Windows host source and selected output
|
|
314
|
+
|
|
315
|
+
The SDK's `src/core/hosts/windows/ArcaneCoreProcess.cs` owns an explicitly
|
|
316
|
+
selected executable, argument string and working directory. It reads complete
|
|
317
|
+
framed Core messages and diagnostics, acknowledges ordered asynchronous writes,
|
|
318
|
+
and closes stdin before awaiting accepted Core work, final output and process
|
|
319
|
+
exit. It does not kill the child on an ordinary close.
|
|
320
|
+
|
|
321
|
+
`ArcaneHost.cs` composes that process with a WebView2 window through
|
|
322
|
+
`ArcaneHost.Run(options,onDiagnostic,onError)` or `ArcaneHostForm`. Options
|
|
323
|
+
select the app root/start path, stable virtual HTTPS origin, profile directory,
|
|
324
|
+
title, canonical classic-client source and Core process inputs. The form exposes
|
|
325
|
+
`Ready`, `Completion` and `CloseAsync()`. Page navigation, transport connection,
|
|
326
|
+
Core readiness and service readiness are separate states. Accepted work drains
|
|
327
|
+
before the window closes; complete engineering errors go to the supplied
|
|
328
|
+
diagnostic/error callbacks. Callbacks must not synchronously wait for the
|
|
329
|
+
window's lifetime promises.
|
|
330
|
+
|
|
331
|
+
`ArcaneLauncher.cs` supplies the executable entry point for that composition.
|
|
332
|
+
`tools/build-core-windows-host.mjs` builds the selected SDK host output from the
|
|
333
|
+
approved WebView2 package, existing .NET Framework compiler and selected Node
|
|
334
|
+
SEA output. It retains complete compiler diagnostics and produces a fresh
|
|
335
|
+
directory rather than overwriting an earlier artifact. The host requires
|
|
336
|
+
.NET Framework 4.6.2 or later. This is SDK release tooling, not an application
|
|
337
|
+
build requirement. Source compilation, selected host execution and real
|
|
338
|
+
application behavior are separate evidence boundaries; an assembled app is not
|
|
339
|
+
an installer or proof of its domain behavior.
|
|
340
|
+
|
|
341
|
+
Linux, macOS, Android dispatch and each platform's output verification retain
|
|
342
|
+
their separate delivery boundaries. Published
|
|
148
343
|
consumers must adopt the numeric package that includes this increment; a source
|
|
149
344
|
checkout or a successful source push is not that public package authority.
|
|
345
|
+
|
|
346
|
+
## macOS process source
|
|
347
|
+
|
|
348
|
+
`src/core/hosts/macos/ArcaneCoreProcess.h` and `.m` provide a Foundation-only
|
|
349
|
+
adapter for macOS 11 or later, compiled with Objective-C ARC and blocks. A
|
|
350
|
+
composing host explicitly supplies the executable URL, arguments, working
|
|
351
|
+
directory and delegate; startup is asynchronous. Delegate callbacks deliver
|
|
352
|
+
every raw stdout/stderr chunk and complete opaque framed JSON bodies, plus
|
|
353
|
+
launch, error, exit and final completion observations. Each stream and accepted
|
|
354
|
+
write retains its own order; UI dispatch belongs to the host. Callbacks must
|
|
355
|
+
return normally and must not wait for another callback or completion.
|
|
356
|
+
|
|
357
|
+
`sendJSONData:completion:error:` accepts an ordered write or reports a
|
|
358
|
+
synchronous rejection. Write completion means the frame reached stdin, not that
|
|
359
|
+
the RPC succeeded. `closeInput` rejects new sends, finishes accepted writes and
|
|
360
|
+
closes stdin, then keeps observing output and child exit without a forced
|
|
361
|
+
termination deadline. The delegate is retained through final completion.
|
|
362
|
+
The AppKit `ArcaneHost` and launcher compose that source as described below.
|
|
363
|
+
Compilation and execution on macOS remain separate evidence from the selected
|
|
364
|
+
Windows output.
|
|
365
|
+
|
|
366
|
+
## macOS application composition
|
|
367
|
+
|
|
368
|
+
`arcane-os/native/macos-provider` exports
|
|
369
|
+
`createMacOSNativeProvider({services,hostDirectory}={})`, its named
|
|
370
|
+
`arcaneNativeBuilderProvider`, and the same provider as default. The six-method
|
|
371
|
+
contract accepts `macos-arm64` or `macos-x64`, `platform:'macos'`, `format:'app'`
|
|
372
|
+
and the existing unsigned local development selection. Ordinary CLI routing
|
|
373
|
+
uses the SDK package, not an Arcane OS checkout:
|
|
374
|
+
|
|
375
|
+
```sh
|
|
376
|
+
npm exec -- arcane build --target macos-arm64
|
|
377
|
+
npm exec -- arcane run --target macos-arm64
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Select `macos-x64` for Intel. The descriptor must declare the selected target.
|
|
381
|
+
Source implementation does not establish that an architecture's host artifact
|
|
382
|
+
has been built, executed or published. Consumer assembly needs the exact numeric
|
|
383
|
+
SDK release asset `arcane-native-macos-<architecture>.tar.gz`; unavailable assets
|
|
384
|
+
produce their actual download error. SDK collaborators may select an existing
|
|
385
|
+
`hostDirectory` explicitly. There is no fallback to source checkout, another
|
|
386
|
+
version, another architecture or a browser-only artifact.
|
|
387
|
+
|
|
388
|
+
The complete unchanged portable payload lives at
|
|
389
|
+
`<app-id>.app/Contents/Resources/`. That directory remains `target.rootDir` and
|
|
390
|
+
contains `arcane-native.json`, `app/`, dependency releases, installed SDK files,
|
|
391
|
+
Core entry/client and `runtime/node`. The additive `bundleRoot` identifies the
|
|
392
|
+
`.app` directory. `Contents/MacOS/Arcane` and `Contents/Info.plist` belong to the
|
|
393
|
+
bundle rather than the web root; the Mac owner checks these separately from the
|
|
394
|
+
Resources file inventory. Application identity supplies the stable bundle ID
|
|
395
|
+
`org.arcane.<app-id>`. Executable permissions are preserved for the launcher and
|
|
396
|
+
selected Node runtime.
|
|
397
|
+
|
|
398
|
+
The launcher opens its window immediately and starts one Core child. The
|
|
399
|
+
generated Core entry starts the `packaged-web` service alongside application
|
|
400
|
+
services, without waiting for models. Only `core.web.ready`, emitted after the
|
|
401
|
+
actual listener is ready and the initial port is saved, supplies the application
|
|
402
|
+
URL to WebKit. It serves the complete `manifest.webRoot` at `/` and resolves the
|
|
403
|
+
complete `manifest.start`, including query and fragment, against that origin.
|
|
404
|
+
The classic client selects current-document activation and sticky state replay;
|
|
405
|
+
navigation does not restart the Core service or replay retired requests.
|
|
406
|
+
The host's main-thread readonly `isClosing` accessor exposes its existing close
|
|
407
|
+
intent; an unsolicited Core exit is therefore reported separately from an
|
|
408
|
+
ordinary user-requested drain, even when the process exits successfully.
|
|
409
|
+
|
|
410
|
+
`createPackagedWebService({artifactRoot}, context={})` is available from
|
|
411
|
+
`arcane-os/core/packaged-web`. It uses the existing
|
|
412
|
+
`startDevServer({mode:'packaged',http:true,host:'127.0.0.1',port,releaseRoot})`
|
|
413
|
+
owner and published `node-http-server`, not a second HTTP implementation.
|
|
414
|
+
`context.stateRoot` takes precedence over the launcher's separate
|
|
415
|
+
`--arcane-host-state-root` argument. The launcher defaults to
|
|
416
|
+
`~/Library/Application Support/Arcane/<app-id>`; an explicitly supplied launch
|
|
417
|
+
file remains unchanged and is forwarded to Core. The first successful listener
|
|
418
|
+
stores its selected port in `packaged-web-origin.json`. Later launches reuse it;
|
|
419
|
+
a port conflict or unreadable saved record is reported without changing origins
|
|
420
|
+
or discarding stored state.
|
|
421
|
+
|
|
422
|
+
The app's persistent default `WKWebsiteDataStore` uses its bundle identity.
|
|
423
|
+
`stateRoot` selects Core state and diagnostics, not a custom WebKit profile
|
|
424
|
+
directory. Browser API availability, OPFS and secure-context behavior remain
|
|
425
|
+
WebKit-owned and require actual Mac verification; the SDK bypasses no browser
|
|
426
|
+
policy. Startup failures use `core.service.state` for `name:'packaged-web'`;
|
|
427
|
+
unexpected listener closure or failure uses `core.web.failed` with the complete
|
|
428
|
+
serialized error. Native alerts show a concise outcome, with full diagnostics
|
|
429
|
+
outside the conversation. Core drains accepted work and the listener before
|
|
430
|
+
the native close completes. The optional runner stdin-EOF signal uses that same
|
|
431
|
+
path; ordinary double-click startup does not wait on stdin.
|
|
432
|
+
|
|
433
|
+
`tools/build-core-macos-host.mjs` is SDK host-release tooling, not an application
|
|
434
|
+
compiler requirement. It accepts an explicit Darwin Node executable and its
|
|
435
|
+
license, compiler path, `arm64` or `x64`, and output directory. It uses Objective-C
|
|
436
|
+
ARC/blocks and Apple's Foundation, AppKit and WebKit frameworks. The host source
|
|
437
|
+
targets macOS 11; the selected Node runtime may require a newer macOS version.
|
|
438
|
+
Its actual runtime/platform/architecture and the SDK Node engine requirement
|
|
439
|
+
must agree. Compiler/runtime execution and redistribution belong to the
|
|
440
|
+
separately authorized selected host output. This source increment runs none of
|
|
441
|
+
them and claims no Mac build or execution result.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Core preferences service
|
|
2
|
+
|
|
3
|
+
`createPreferencesService({file})` from `arcane-os/core/preferences` supplies the
|
|
4
|
+
existing `Arcane.preferences` RPC methods to a native Core host. The default
|
|
5
|
+
export is the same factory. Construction performs no filesystem work. The
|
|
6
|
+
application selects its writable file and owns preference names, defaults and
|
|
7
|
+
schemas; this service does not invent them or alter operating-system settings.
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import {createPreferencesService} from 'arcane-os/core/preferences';
|
|
12
|
+
|
|
13
|
+
export default function createMoonPreferences(options, context) {
|
|
14
|
+
return createPreferencesService({
|
|
15
|
+
file: path.join(context.stateRoot, 'moon-preferences.json')
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Select this application-owned factory through `native.services`, and include it
|
|
21
|
+
in `package.nativeResources`. Supply the application's selected `stateRoot`
|
|
22
|
+
through the explicit launch configuration. See [native packaging](core-native-packaging.md#launch-time-locations).
|
|
23
|
+
|
|
24
|
+
| Method | Input | Result |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| `preferences.list` | `{}` | `{keys}` in sorted order |
|
|
27
|
+
| `preferences.get` | `{key}` | `{key,found,value}`; missing value is `null` |
|
|
28
|
+
| `preferences.set` | `{key,value}` | `{key,value}` after file replacement |
|
|
29
|
+
| `preferences.setMany` | `{entries}` | `{keys,count}` after file replacement |
|
|
30
|
+
| `preferences.delete` | `{key}` | `{key,deleted}` |
|
|
31
|
+
|
|
32
|
+
Storage remains `{schemaVersion:1,entries}`. Exact keys, complete JSON values and
|
|
33
|
+
additional existing document metadata are retained. A missing file starts with
|
|
34
|
+
empty entries; reading it does not create a file. Unreadable or malformed files
|
|
35
|
+
report their real errors and are not replaced with an empty record. Values that
|
|
36
|
+
JSON cannot represent completely fail before replacement. There is no migration,
|
|
37
|
+
truncation, namespace rewrite, default injection or frozen result.
|
|
38
|
+
|
|
39
|
+
Operations selecting the same resolved filename share one ordered queue within
|
|
40
|
+
the Core process. This is not a cross-process file lock. Writes flush their new
|
|
41
|
+
content and replace the selected file before acknowledgment. Filesystem failures
|
|
42
|
+
remain observable, including cleanup errors; this is not a claim of survival
|
|
43
|
+
across every hardware or operating-system failure.
|
|
44
|
+
|
|
45
|
+
`set`, `setMany` and `delete` use `lifetime:'service'`: renderer cancellation does
|
|
46
|
+
not discard accepted writes. `drain()` and `dispose()` stop acceptance and wait
|
|
47
|
+
for accepted operations; later calls reject with `CORE_CLOSING`. Read operations
|
|
48
|
+
observe their request cancellation. Use the existing Core host shutdown owner
|
|
49
|
+
so saved preferences finish before the native process exits.
|