arcane-os 0.69.0 → 0.71.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 +28 -0
- package/README.md +1 -1
- package/browser-runtime/ai/browser-decisions.mjs +46 -2
- package/browser-runtime/ai/browser-speech-artifacts.mjs +58 -62
- package/browser-runtime/ai/browser-speech-providers.mjs +3 -0
- package/browser-runtime/ai/browser-wasm-llm-provider.mjs +76 -164
- package/browser-runtime/ai/dbopfs-model-parts.mjs +344 -0
- package/browser-runtime/ai/dbopfs-model-resources.mjs +190 -0
- package/browser-runtime/ai/decision-runtime.mjs +17 -1
- package/browser-runtime/ai/decision-worker.mjs +21 -1
- package/browser-runtime/ai/model-resource-bridge.mjs +231 -0
- package/browser-runtime/ai/speech-worker-client.mjs +68 -28
- package/browser-runtime/ai/speech-worker-runtime.mjs +212 -97
- package/browser-runtime/core/contracts.mjs +1 -1
- package/docs/reference/README.md +2 -0
- package/docs/reference/ai/browser-decisions.md +57 -3
- package/docs/reference/ai/browser-speech.md +45 -17
- package/docs/reference/ai/browser-wasm.md +28 -20
- package/docs/reference/core-native-packaging.md +13 -0
- package/docs/reference/core-runtime.md +9 -0
- package/docs/reference/core-shared-host.md +190 -0
- package/docs/reference/inventory/package-api.json +3 -3
- package/docs/reference/inventory/runtime-components.json +2 -2
- package/docs/reference/inventory/runtime-modules.json +6 -6
- package/docs/reference/runtime-components.md +35 -1
- package/docs/reference/runtime-modules.md +97 -7
- package/docs/reference/sdk-api.md +69 -31
- package/package.json +2 -2
- package/runtime/arcane/components/theme-switcher.html +4 -4
- package/runtime/arcane/modules/AI.js +2 -18
- package/runtime/arcane/modules/AIProviderRuntime.js +77 -3
- package/runtime/arcane/modules/DBOPFS.js +180 -26
- package/src/core/host.mjs +2 -0
- package/src/core/runtime.mjs +9 -4
- package/src/core/services/packaged-web.mjs +8 -1
- package/src/core/shared-host.mjs +500 -0
- package/src/native/portable-layout.mjs +66 -34
|
@@ -842,6 +842,14 @@ cancellation signal. Cancelling one handle detaches that caller; the shared
|
|
|
842
842
|
preparation is aborted only when its last pending caller cancels. Different AI
|
|
843
843
|
instances do not share an in-flight synthesis operation. Complete stored
|
|
844
844
|
results remain reusable through the same application storage.
|
|
845
|
+
|
|
846
|
+
Missing audio participates in the provider runtime's shared TTS activation with
|
|
847
|
+
the preparation's cancellation signal. Cancelling the final pending interest
|
|
848
|
+
aborts that activation; another preparation, explicit playback activation, or
|
|
849
|
+
direct TTS load joining it keeps the load alive. Cancellation does not unload a
|
|
850
|
+
model whose activation has already completed. A complete audio-cache hit never
|
|
851
|
+
requests model activation. Provider cancellation and cleanup remain cooperative;
|
|
852
|
+
an aborted caller wait alone is not evidence that native work has stopped.
|
|
845
853
|
After a durable preparation completes, a later preparation call rereads its
|
|
846
854
|
manifest and saved-file presence, regenerating only missing segments. A
|
|
847
855
|
completed preparation without storage reuses its retained Blobs.
|
|
@@ -874,9 +882,10 @@ The supplied signal observes preparation until `ready` settles. Manual
|
|
|
874
882
|
handle. If a raw audio write has already begun when cancellation arrives,
|
|
875
883
|
its metadata transaction finishes so that successful audio can be reused;
|
|
876
884
|
no later queued write starts for that cancelled preparation.
|
|
877
|
-
Cancelling preparation prevents later synthesis
|
|
878
|
-
|
|
879
|
-
|
|
885
|
+
Cancelling preparation prevents later synthesis and releases its pending
|
|
886
|
+
activation interest. Other pending interests retain the shared load; cancelling
|
|
887
|
+
the final interest forwards abort to its provider-owned activation. Actual
|
|
888
|
+
provider cleanup remains observable through that operation's settlement.
|
|
880
889
|
|
|
881
890
|
### Playback controls and independent lifetimes
|
|
882
891
|
|
|
@@ -1497,23 +1506,39 @@ The Worker installs one private module router before importing the entrypoint:
|
|
|
1497
1506
|
- a dynamic import whose target is known imports the materialized URL;
|
|
1498
1507
|
- a fetch whose target is known reads the materialized URL;
|
|
1499
1508
|
- a Worker whose target is known starts the SDK role Worker and imports the
|
|
1500
|
-
materialized target there
|
|
1501
|
-
- a Cache match whose target is known returns the materialized file.
|
|
1509
|
+
materialized target there.
|
|
1502
1510
|
|
|
1503
|
-
|
|
1511
|
+
Resource ownership extends to ordinary self-contained speech runtimes as well
|
|
1512
|
+
as graph runtimes:
|
|
1504
1513
|
|
|
1505
1514
|
- an unmapped relative or URL-like import resolves against the calling module's
|
|
1506
1515
|
original source URL, while a bare specifier remains unchanged for native
|
|
1507
1516
|
import-map resolution;
|
|
1508
|
-
- an unmapped
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
+
- an unmapped HTTP fetch preserves the caller's request options and reaches
|
|
1518
|
+
the parent DBOPFS resource store; Blob/data resources remain local;
|
|
1519
|
+
- an unmapped module Worker starts through the SDK role Worker and forwards
|
|
1520
|
+
its resource fetches to that same store; and
|
|
1521
|
+
- an unmapped classic Worker retains native execution. Its internal fetches
|
|
1522
|
+
are outside this module-Worker routing contract.
|
|
1523
|
+
|
|
1524
|
+
Inside the dedicated speech Worker, native CacheStorage is temporarily
|
|
1525
|
+
unavailable before runtime import, so the selected runtime takes its existing
|
|
1526
|
+
fetch path. Transformers' public browser/custom/filesystem cache switches are
|
|
1527
|
+
disabled there. The SDK does not fabricate Cache matches or mutation results,
|
|
1528
|
+
and it neither clears nor changes saved native caches. The original Worker
|
|
1529
|
+
environment is restored on unload or failed import. Existing explicit
|
|
1530
|
+
`removeBrowserSpeechModelCache()` remains a separate caller-selected operation.
|
|
1531
|
+
|
|
1532
|
+
The existing speech store exposes `fetchResource(input, options)` for its
|
|
1533
|
+
Worker loaders, returning `{file,status,statusText,headers,url,redirected}`.
|
|
1534
|
+
New declared files and fetched model, voice, configuration, and WASM resources
|
|
1535
|
+
stream into ordered DBOPFS parts even without a response length. Closed-part
|
|
1536
|
+
progress uses `unit:'shards'`; declared-file progress retains `unit:'files'`
|
|
1537
|
+
with the current shard record in `resource`. Complete declared peer files and
|
|
1538
|
+
closed resource parts survive cancellation. Existing whole-file caches remain
|
|
1539
|
+
readable without migration. HTTP resume is used only when the server returns
|
|
1540
|
+
the requested range; otherwise the complete resource is downloaded anew.
|
|
1541
|
+
Worker termination aborts and joins its parent-owned resource operations.
|
|
1517
1542
|
|
|
1518
1543
|
Routing discovery is best effort and is not an admission gate. If the scanner
|
|
1519
1544
|
cannot interpret a module, that module is left unchanged and follows its native
|
|
@@ -1535,11 +1560,14 @@ provider:
|
|
|
1535
1560
|
`namespace.env.backends.onnx.wasm.wasmPaths = {mjs,wasm}`, keeps remote model
|
|
1536
1561
|
loading enabled, and applies caller-selected `numThreads` when present.
|
|
1537
1562
|
|
|
1538
|
-
Transformers and Kokoro
|
|
1539
|
-
|
|
1563
|
+
Transformers and Kokoro use their normal provider request semantics through
|
|
1564
|
+
the selected DBOPFS resource owner. Kokoro voice aliases and Transformers
|
|
1540
1565
|
model aliases may be listed in `runtimeRequestUrls` so an upstream request for a
|
|
1541
1566
|
known file resolves to the already materialized local file. Model, voice, and
|
|
1542
1567
|
runtime selection remains with the application and upstream publisher.
|
|
1568
|
+
Native ESM imports remain platform-owned; only declared runtime modules are
|
|
1569
|
+
materialized by artifact preparation. Custom classic Worker internals are not
|
|
1570
|
+
claimed as stored by this contract.
|
|
1543
1571
|
|
|
1544
1572
|
## Providers
|
|
1545
1573
|
|
|
@@ -117,21 +117,15 @@ current mutable status snapshot. Provider states are `unloaded`, `loading`, `rea
|
|
|
117
117
|
|
|
118
118
|
Browser-WASM model loads report `cache-check`, `download`, and `initialize`
|
|
119
119
|
phases. Download records preserve the ordered model-file fields `completed`,
|
|
120
|
-
`total`, and `unit:'files'`.
|
|
121
|
-
`
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
bound, and `transferMode` identifies `probing`, `files`, `ranges`, or `single`.
|
|
130
|
-
The store coalesces chunk-driven changes on a 250 ms cadence and publishes
|
|
131
|
-
immediately when download starts, the transfer plan or total becomes known,
|
|
132
|
-
active-worker count changes, and the download completes. At known completion, remaining bytes and ETA are zero
|
|
133
|
-
and active transfers are zero. Applications format the raw measures into B,
|
|
134
|
-
KB, MB, GB, transfer-rate, and duration labels.
|
|
120
|
+
`total`, and `unit:'files'`. Their ordered `members` records contain each file's
|
|
121
|
+
`name`, committed-part `completed`, `total`, and `unit:'shards'`. A streaming
|
|
122
|
+
response has `total:null` until its end is observed; completion then supplies
|
|
123
|
+
the actual committed-part count. Previously complete members identify
|
|
124
|
+
`state:'cached'`. `activeTransfers` is the current transfer-worker count,
|
|
125
|
+
`transferLimit` is the selected concurrency, and `transferMode` identifies
|
|
126
|
+
`probing`, `files`, `ranges`, or `single`. No byte progress, rate, or estimated
|
|
127
|
+
completion time is produced. Closed-part and lifecycle changes publish promptly;
|
|
128
|
+
the existing 250 ms heartbeat retains the current semantic state.
|
|
135
129
|
|
|
136
130
|
Initialization keeps `phase:'initialize'` and reports a `stage` and a readable
|
|
137
131
|
`message` from the packaged runtime's existing log signals: runtime startup,
|
|
@@ -172,8 +166,11 @@ optional descriptor `bytes` divides that member into deterministic contiguous
|
|
|
172
166
|
parts of roughly 4 MB each, up to 4,096 parts. Each exact completed part is
|
|
173
167
|
committed separately in OPFS, so retry or refresh fetches only the small
|
|
174
168
|
in-flight parts plus any other missing parts; the ordered parts are exposed to
|
|
175
|
-
Wllama as one logical model Blob.
|
|
176
|
-
|
|
169
|
+
Wllama as one logical model Blob. Ordinary full responses, including unknown
|
|
170
|
+
content lengths and single-file models, also stream directly into ordered OPFS
|
|
171
|
+
parts. Model data is not accumulated in one JavaScript buffer. Range offsets
|
|
172
|
+
and physical part framing remain storage/transport-local; progress describes
|
|
173
|
+
completed files and parts.
|
|
177
174
|
|
|
178
175
|
## Model selection, optional hardening, and cache
|
|
179
176
|
|
|
@@ -181,7 +178,7 @@ The canonical model descriptor is
|
|
|
181
178
|
`{id, files:[{name?,url,bytes?},...]}`. The ordered `files` array is nonempty;
|
|
182
179
|
names and URLs are unique. Each URL must be absolute HTTPS without credentials
|
|
183
180
|
or a fragment. An optional positive safe-integer `bytes` value is used only for
|
|
184
|
-
|
|
181
|
+
HTTP Range planning. Missing or unusable metadata never blocks a
|
|
185
182
|
download, and a declared value is not a content-length check.
|
|
186
183
|
|
|
187
184
|
Fetch follows HTTPS redirects and records the requested and final HTTPS URL. A
|
|
@@ -205,11 +202,22 @@ admission work. Observational byte counting and exact HTTP Range framing remain
|
|
|
205
202
|
transport-local. A load succeeds only after Wllama reports that the model is
|
|
206
203
|
loaded.
|
|
207
204
|
|
|
208
|
-
The DBOPFS adapter commits
|
|
209
|
-
|
|
205
|
+
The DBOPFS adapter commits ordered parts independently and exposes only a
|
|
206
|
+
complete ordered model set as a cache hit. Existing whole-file and Range-part
|
|
207
|
+
caches remain readable without migration. Closed parts survive interrupted
|
|
208
|
+
writes; a source without supported resume starts that member's next transfer
|
|
209
|
+
from its beginning. Complete peer members remain cached.
|
|
210
210
|
`load({offline:true})` never performs a model request; it uses a compatible
|
|
211
211
|
cached entry or rejects with `ARCANE_AI_MODEL_OFFLINE_MISS`.
|
|
212
212
|
|
|
213
|
+
The same store exposes `fetchResource(input, options)` for SDK-owned browser
|
|
214
|
+
model loaders. It returns `{file,status,statusText,headers,url,redirected}`
|
|
215
|
+
after storing the complete response through the shared part owner. Ordinary
|
|
216
|
+
Fetch request options, `signal`, and semantic `onProgress` are supported.
|
|
217
|
+
The browser decision model accepts this store through its additive `store`
|
|
218
|
+
option; resource acquisition stays with the SDK while model selection stays
|
|
219
|
+
with the application. See [browser decisions](browser-decisions.md).
|
|
220
|
+
|
|
213
221
|
```javascript
|
|
214
222
|
const {security, cache} = ai.status().llm;
|
|
215
223
|
console.log(security?.secure === true); // false when the optional field is absent
|
|
@@ -210,6 +210,19 @@ details and [the client contract](core-client.md) for native bridge integration.
|
|
|
210
210
|
|
|
211
211
|
## Launch-time locations
|
|
212
212
|
|
|
213
|
+
For one app-owned Core shared by the native window and a separate MCP process,
|
|
214
|
+
the launch context may explicitly select `sharedHost:{endpoint,logFile}`. The
|
|
215
|
+
generated native child then connects through a stdio bridge, starting an
|
|
216
|
+
independent headless Core only when the selected endpoint is absent. Its
|
|
217
|
+
endpoint claim precedes application service imports/factories. Closing a native
|
|
218
|
+
window disconnects its bridge; explicit shared-host shutdown drains services.
|
|
219
|
+
Omitting `sharedHost` preserves the existing stdio-owned Core lifetime.
|
|
220
|
+
See [shared Core host ownership](core-shared-host.md) for exact startup,
|
|
221
|
+
connection, cancellation, diagnostics, endpoint, and platform contracts.
|
|
222
|
+
The packaged-web service exposes `current()` as its active `{origin,url,port}`
|
|
223
|
+
or `null`; the shared host replays that current listener to a newly attached
|
|
224
|
+
macOS bridge, without restarting the server or retaining historical events.
|
|
225
|
+
|
|
213
226
|
The generated Core entry accepts `--arcane-launch-config <path>`. The public
|
|
214
227
|
`readCoreLaunchContext({argv=process.argv.slice(2)}={})` function in
|
|
215
228
|
`arcane-os/core/host` reads that explicitly selected JSON object. A native host
|
|
@@ -71,6 +71,15 @@ receives `(parameters, {application, service, emit, getService, requestId, signa
|
|
|
71
71
|
`this` bound to its service definition. A hook or handler may publish a complete
|
|
72
72
|
service-owned event through `emit(event, data)`.
|
|
73
73
|
|
|
74
|
+
A request handler's `emit` places its owning request ID in the event frame's
|
|
75
|
+
optional top-level `requestId`, leaving `data` unchanged. Multi-connection hosts
|
|
76
|
+
can route those frames to the requesting connection even when different clients
|
|
77
|
+
choose the same application `streamId`. Lifecycle-hook `emit` and public
|
|
78
|
+
`runtime.emit` remain uncorrelated service-wide events. Retain that service
|
|
79
|
+
context when an application intentionally publishes a change to every client;
|
|
80
|
+
request-context events belong to the originating request. The ordinary Core
|
|
81
|
+
client still delivers the complete original event data to its listeners.
|
|
82
|
+
|
|
74
83
|
### Native service composition
|
|
75
84
|
|
|
76
85
|
`await runtime.getService(name)` and `await context.getService(name)` return the
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# One application, one shared Core host
|
|
2
|
+
|
|
3
|
+
`arcane-os/core/host` provides a Node local-IPC owner for applications whose
|
|
4
|
+
native UI and separate MCP process use the same catalog, drafts, review queue,
|
|
5
|
+
and Git service. The application chooses one endpoint and one set of services.
|
|
6
|
+
The endpoint is a nonempty local pipe/socket path. The SDK connects to it,
|
|
7
|
+
optionally starts an explicit headless entry,
|
|
8
|
+
and keeps client disconnection separate from service shutdown.
|
|
9
|
+
|
|
10
|
+
This is an explicit same-application connection. It does not scan applications
|
|
11
|
+
or processes, share preference files, copy a catalog, retry requests, or retain
|
|
12
|
+
event history. Application methods and policy stay in the application services.
|
|
13
|
+
Use the [MCP server](mcp-stdio.md) for external MCP framing; local Core continues
|
|
14
|
+
to use the existing `arcane/1` protocol and Content-Length stream framing.
|
|
15
|
+
|
|
16
|
+
## Host entry
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
import {runSharedCoreHost} from 'arcane-os/core/host';
|
|
20
|
+
|
|
21
|
+
const host = await runSharedCoreHost({
|
|
22
|
+
endpoint: process.env.MOON_CORE_ENDPOINT,
|
|
23
|
+
application: {id: 'moon-cheese-ledger'},
|
|
24
|
+
version: '1.0.0',
|
|
25
|
+
async configure(runtime, {signal}) {
|
|
26
|
+
// Only the successful endpoint owner imports and constructs services.
|
|
27
|
+
const {default: createLedger} = await import('./ledger.mjs');
|
|
28
|
+
signal.throwIfAborted();
|
|
29
|
+
runtime.registerService(createLedger());
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
await host?.closed;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`startSharedCoreHost({endpoint,application,version,configure,getReplayEvents,
|
|
36
|
+
signal,onError})` binds the selected endpoint **before** calling `configure`.
|
|
37
|
+
The callback receives the existing runtime and the host's lifetime signal.
|
|
38
|
+
Register each service as it is constructed so its drain/disposal belongs to the
|
|
39
|
+
runtime even if a later factory fails. Put asynchronous service initialization
|
|
40
|
+
in `start`, as with ordinary Core composition. Factory imports can run
|
|
41
|
+
concurrently; requests wait for composition, then only their own service's
|
|
42
|
+
startup. Dispatcher readiness does not claim model or service readiness.
|
|
43
|
+
|
|
44
|
+
It resolves to `{runtime,endpoint,closed,close}`. `close()` rejects new work,
|
|
45
|
+
joins composition, closes the runtime, drains complete queued frames, and
|
|
46
|
+
closes its connections. It retains the endpoint claim through service cleanup
|
|
47
|
+
before stopping the listener, so a new launcher cannot start a second service
|
|
48
|
+
owner during an accepted save. Accepted service-lifetime requests finish
|
|
49
|
+
before service drain/disposal. A supplied signal begins this same shutdown;
|
|
50
|
+
the lazy factory receives cancellation and is joined before cleanup. Register
|
|
51
|
+
resources before rejecting after creation. Startup and shutdown errors remain
|
|
52
|
+
observable; `closed` rejects on host shutdown failure. `onError` observes
|
|
53
|
+
transport/background errors, with console diagnostics by default.
|
|
54
|
+
|
|
55
|
+
An endpoint already in use rejects with the native `EADDRINUSE` error and
|
|
56
|
+
`coreHostPhase:'listen'`, without invoking the factory.
|
|
57
|
+
`runSharedCoreHost(options)` adds the explicit headless startup handshake: a
|
|
58
|
+
losing launcher connects to the existing owner and confirms dispatcher response
|
|
59
|
+
without importing its own application service modules. It returns `null` in
|
|
60
|
+
that case. The winning launcher returns the same host object. It reports startup
|
|
61
|
+
success or the complete failure to a parent Node IPC channel when present and
|
|
62
|
+
never calls `process.exit()`.
|
|
63
|
+
|
|
64
|
+
## Connect, reuse, or start headlessly
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
import {connectSharedCoreHost} from 'arcane-os/core/host';
|
|
68
|
+
|
|
69
|
+
const connection = await connectSharedCoreHost({
|
|
70
|
+
endpoint: selectedEndpoint,
|
|
71
|
+
start: {
|
|
72
|
+
command: process.execPath,
|
|
73
|
+
args: [selectedHostEntry],
|
|
74
|
+
logFile: selectedDiagnosticLog
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
const catalog = await connection.client.invoke('catalog.read', {});
|
|
78
|
+
// The UI or MCP process is finished. Shared services remain alive.
|
|
79
|
+
await connection.close();
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`connectSharedCoreHost({endpoint,start,signal,onError})` first connects to the
|
|
83
|
+
selected endpoint. Only connection absence (`ENOENT` or `ECONNREFUSED`) selects
|
|
84
|
+
`start`; other errors propagate unchanged. Omit `start` for connect-only use.
|
|
85
|
+
The optional record is `{command,args=[],cwd,env,logFile}`. Its arguments and
|
|
86
|
+
environment are captured at acceptance. The selected entry must call
|
|
87
|
+
`runSharedCoreHost`. Parent directories for the endpoint and diagnostic file
|
|
88
|
+
must already exist. No shell, runtime installer, service manager, or automatic
|
|
89
|
+
request retry is involved.
|
|
90
|
+
|
|
91
|
+
Headless startup uses an independent child with ignored stdin and complete
|
|
92
|
+
stdout/stderr appended to the explicit diagnostic file. The child reports its
|
|
93
|
+
endpoint claim/composition result through its startup IPC channel; the launcher
|
|
94
|
+
then disconnects that channel and releases the child process reference. An
|
|
95
|
+
aborted connection/start wait rejects or closes the connecting client; it does
|
|
96
|
+
not kill a host that another connection may already use. The host may therefore
|
|
97
|
+
continue running after a launch wait is cancelled. Startup diagnostics and the
|
|
98
|
+
endpoint remain the actual outcome owners. No startup timeout is imposed by
|
|
99
|
+
this layer; supply a signal when the caller needs a bounded wait.
|
|
100
|
+
|
|
101
|
+
The result is `{client,endpoint,closed,close,shutdown}`. `client` is the existing
|
|
102
|
+
[Core client](core-client.md), with full invoke/cancellation/event behavior and
|
|
103
|
+
current-runtime replay enabled. A connected transport is not a ready model.
|
|
104
|
+
`close()` and `client.close()` cancel this connection's request-lifetime work
|
|
105
|
+
and disconnect it. They leave accepted service-lifetime work and the host
|
|
106
|
+
running. `closed` observes connection termination and rejects on a transport
|
|
107
|
+
error. A subsequent connection uses the still-running owner. Reconnection is
|
|
108
|
+
explicit; failed or uncertain requests are never resubmitted.
|
|
109
|
+
|
|
110
|
+
`await connection.shutdown(invokeOptions)` explicitly invokes the host-owned
|
|
111
|
+
`core.host.shutdown` operation. It drains the shared runtime, returns
|
|
112
|
+
`{state:'closed'}` after successful service cleanup, then closes the connection.
|
|
113
|
+
A drain failure returns the full Core error. Shutdown affects **all** clients
|
|
114
|
+
of that app endpoint and belongs to the application owner's explicit lifecycle,
|
|
115
|
+
not ordinary UI/MCP cleanup. The host reserves this one method; application
|
|
116
|
+
services should use their own namespaces. Cancelling the caller's invoke wait
|
|
117
|
+
after shutdown acceptance does not undo the shared shutdown.
|
|
118
|
+
|
|
119
|
+
## Correlation, events, and state
|
|
120
|
+
|
|
121
|
+
Each connection has its own request-ID space. The transport substitutes an
|
|
122
|
+
internal Core request ID and restores the originating ID on responses and
|
|
123
|
+
the optional top-level event `requestId`. Existing `data.requestId` values that
|
|
124
|
+
carry that same Core correlation ID are restored too. `parameters`, returned results, schemas,
|
|
125
|
+
documents, and content remain complete and unchanged. A handler's
|
|
126
|
+
`context.requestId` is the Core-side correlation ID; put it in the event's
|
|
127
|
+
separate `requestId` field, not inside application content.
|
|
128
|
+
|
|
129
|
+
Responses and request-context events go to the originating connection in
|
|
130
|
+
order. Core supplies the top-level request correlation outside `data`, so two
|
|
131
|
+
clients may choose the same `streamId` without receiving each other's chunks.
|
|
132
|
+
Retired request frames are never routed to another connection. Ordinary
|
|
133
|
+
application/service events from the lifecycle context or `runtime.emit` are broadcast to
|
|
134
|
+
connected clients. Runtime state includes all active work and translates this
|
|
135
|
+
connection's IDs; other connections' active requests retain Core-side IDs.
|
|
136
|
+
`request.cancel` and `requests.cancelAll` affect only the sending connection's
|
|
137
|
+
requests. A disconnect performs the same scoped cancellation. The underlying
|
|
138
|
+
runtime continues to preserve service-lifetime acceptance.
|
|
139
|
+
|
|
140
|
+
`runtime.replay` sends only that connection the current `core.ready`,
|
|
141
|
+
`core.state`, and `core.service.state` snapshot. Optional synchronous
|
|
142
|
+
`getReplayEvents()` returns current `{event,data}` records from their actual
|
|
143
|
+
service owners. It is for current domain state, not historical chunks or
|
|
144
|
+
retired requests. Subscribe before requesting a domain snapshot when its live
|
|
145
|
+
events may change; applications own those domain methods and state.
|
|
146
|
+
|
|
147
|
+
## Native launch and platforms
|
|
148
|
+
|
|
149
|
+
The generated portable Core entry keeps ordinary stdio behavior unless the
|
|
150
|
+
explicit launch context contains:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"sharedHost": {
|
|
155
|
+
"endpoint": "APPLICATION-SELECTED-LOCAL-ENDPOINT",
|
|
156
|
+
"logFile": "APPLICATION-SELECTED-DIAGNOSTIC-FILE"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Both native UI and external MCP clients select the same endpoint. With this
|
|
162
|
+
option, the native Core child is a stdio-to-shared-Core bridge. It connects or
|
|
163
|
+
launches the same entry with `--arcane-core-headless`; the headless entry claims
|
|
164
|
+
the endpoint before importing services. Closing the native window ends its
|
|
165
|
+
bridge, while the independent Core host remains available. Service options and
|
|
166
|
+
the complete launch context retain their existing values. There is no implicit
|
|
167
|
+
shared mode or new application descriptor field.
|
|
168
|
+
|
|
169
|
+
`startSharedCoreBridge({endpoint,start,input=process.stdin,
|
|
170
|
+
output=process.stdout,signal,onError})` is also public. It returns
|
|
171
|
+
`{endpoint,closed,close}` and forwards full framed requests, events, and
|
|
172
|
+
responses. EOF or bridge cancellation disconnects that client only. Terminal
|
|
173
|
+
stream errors settle pending writes and reject `closed`; output is neither
|
|
174
|
+
truncated nor replaced with a fabricated response.
|
|
175
|
+
|
|
176
|
+
On Windows use an app-selected named pipe such as
|
|
177
|
+
`\\.\pipe\moon-cheese-core`; on Linux/macOS use an app-selected Unix-domain
|
|
178
|
+
socket path in an existing writable directory. Select the same absolute Unix
|
|
179
|
+
path across UI and MCP launch contexts so differing working directories do not
|
|
180
|
+
select different endpoints. Node and the operating system
|
|
181
|
+
own their native endpoint requirements. A Unix socket left after an abnormal
|
|
182
|
+
host exit is reported as a connection/bind failure; the SDK does not delete an
|
|
183
|
+
existing endpoint to take ownership. The app owner can resolve that actual
|
|
184
|
+
stale endpoint after establishing its stopped lifecycle. Android requires its
|
|
185
|
+
host adaptation for local IPC and independent process ownership; application
|
|
186
|
+
services and `arcane/1` client semantics remain the shared boundary.
|
|
187
|
+
|
|
188
|
+
This source contract is distinct from a selected package/native artifact or
|
|
189
|
+
execution on a particular platform. Applications adopt it through the published
|
|
190
|
+
SDK and their corresponding native package build, not by copying this source.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"sdkVersion": "0.
|
|
3
|
+
"sdkVersion": "0.69.0",
|
|
4
4
|
"environment": {
|
|
5
5
|
"runtime": "Node.js for Node entrypoints; browser for browser-only entrypoints",
|
|
6
6
|
"minimumVersion": "22.23.2 for Node entrypoints",
|
|
@@ -4374,7 +4374,7 @@
|
|
|
4374
4374
|
"summary": "Creates the SDK-owned provider that assembles one selected app and explicit services into a portable Core payload.",
|
|
4375
4375
|
"availability": "Node; produces a portable payload rather than an executable host",
|
|
4376
4376
|
"protocol": "arcane-native-builder/1 portable provider",
|
|
4377
|
-
"normalization": "Preserves complete selected app and dependency releases; an explicit services selection overrides appDescriptor.native.services, otherwise the descriptor selection is used; reports executable:false and never substitutes for an unavailable platform host"
|
|
4377
|
+
"normalization": "Preserves complete selected app and dependency releases; an explicit services selection overrides appDescriptor.native.services, otherwise the descriptor selection is used; optional appDescriptor.native.window carries positive integral logical client width/height and optional resizable into manifest.window with omitted fields preserved; reports executable:false and never substitutes for an unavailable platform host"
|
|
4378
4378
|
},
|
|
4379
4379
|
{
|
|
4380
4380
|
"id": "native-portable-provider:arcaneNativeBuilderProvider",
|
|
@@ -4416,7 +4416,7 @@
|
|
|
4416
4416
|
"summary": "Assembles selected application services and browser content with the SDK-owned Windows x64 WebView2 and SEA host.",
|
|
4417
4417
|
"availability": "Node for assembly; Windows x64 with WebView2 Runtime for execution",
|
|
4418
4418
|
"protocol": "arcane-native-builder/1 windows-x64 provider",
|
|
4419
|
-
"normalization": "Uses a selected hostDirectory or the exact installed SDK version's numeric release asset; preserves complete payloads; app displayName plus .exe (app ID fallback) and matching .exe.config use Windows filename substitutions only; manifest.host.executable owns inventory, icon, verify and run while generic cache/Core names remain unchanged; native.icon PNG/ICO derives the copied executable and host.icon without an app compiler, while other formats retain assembly with native.icon.unsupported and executableIcon:false; the matching host loads the selected window/taskbar icon and handles window.setTheme with per-field applied/unsupported results; run cancellation closes stdin and waits for host-owned graceful shutdown"
|
|
4419
|
+
"normalization": "Uses a selected hostDirectory or the exact installed SDK version's numeric release asset; preserves complete payloads; app displayName plus .exe (app ID fallback) and matching .exe.config use Windows filename substitutions only; manifest.host.executable owns inventory, icon, verify and run while generic cache/Core names remain unchanged; native.icon PNG/ICO derives the copied executable and host.icon without an app compiler, while other formats retain assembly with native.icon.unsupported and executableIcon:false; the matching host loads the selected window/taskbar icon and handles window.setTheme with per-field applied/unsupported results; native.window selects initial 96-DPI logical client width/height and optional resizable through manifest.window, the matching host scales to actual DPI and fits initial placement to the usable screen while omitted fields and existing restored non-normal state remain unchanged; no saved-bounds subsystem is added and initial-fit logic is not reapplied during later resizing; run cancellation closes stdin and waits for host-owned graceful shutdown"
|
|
4420
4420
|
},
|
|
4421
4421
|
{
|
|
4422
4422
|
"id": "native-windows-provider:arcaneNativeBuilderProvider",
|
|
@@ -967,7 +967,7 @@
|
|
|
967
967
|
{
|
|
968
968
|
"file": "runtime/arcane/components/theme-switcher.html",
|
|
969
969
|
"name": "theme-switcher.html",
|
|
970
|
-
"purpose": "Selects and refreshes system, light, dark, or custom theme mode with per-instance choices and
|
|
970
|
+
"purpose": "Selects and refreshes system, light, dark, or custom theme mode with per-instance choices, labels, and CSS-configurable group/option radii, option font and group background.",
|
|
971
971
|
"methods": [
|
|
972
972
|
"configure()",
|
|
973
973
|
"setMode()",
|
|
@@ -980,7 +980,7 @@
|
|
|
980
980
|
],
|
|
981
981
|
"availability": "Browser and supported native WebViews",
|
|
982
982
|
"transport": "HTMLImport + DOM; injected Arcane/provider modules where listed",
|
|
983
|
-
"normalization": "Preference/native appearance behavior mixed; no component-ready contract"
|
|
983
|
+
"normalization": "Preference/native appearance behavior mixed; selected button background, text and outline remain visible during hover while the hover fill applies only to unselected enabled buttons; no component-ready contract"
|
|
984
984
|
},
|
|
985
985
|
{
|
|
986
986
|
"file": "runtime/arcane/components/unified-inbox.html",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"summary": "Owns provider-selectable chat and the one-time caller-authority browser STT/TTS configuration, lifecycle, synthesis, transcription, and playback boundary.",
|
|
30
30
|
"availability": "Browser + native bridge + TWiN Cloud",
|
|
31
31
|
"protocol": "arcane-ai-browser-speech-configuration/1, AIProviderRuntime arcane-ai-provider/2 routes, globalThis.arcaneEvents, TWiN Cloud HTTPS, Arcane.ollama, Arcane.speech, Android WebView bridge",
|
|
32
|
-
"normalization": "Complete mutable caller-owned browser speech authority, SDK-owned provider registration/replacement/disposal, explicit STT/TTS activation, normalized Whisper STT and Kokoro TTS execution with default capacities 1 and 4 respectively, explicit provider-neutral execution snapshots through status(role,{execution:true}), sticky readiness, canonical window.user readiness without compatibility-event object-identity admission or polling, exact ordered structural calls with required arguments.message, atomic nonblank all-ID tool-result sequencing, complete all-choice streaming/data validation, native Ollama structural adaptation, complete-response then all validated tool callbacks then completion ordering, observed async callbacks, Blob/File transcription,
|
|
33
|
-
"surface": "Native fetchTTS(payload,signal) and fetchSTT(audio,signal) forward caller cancellation separately from their complete Core speech payloads, normalize aborts to AbortError and suppress late results; actual engine interruption remains service-owned. prepareTTSPlayback(payload,signal) silently returns a real Blob or native-speech descriptor; native controls expose finished/released/state/error/pause/resume/stop, and actual release owns the playback lane. fetchTTS and durable prepareTTS report ARCANE_AI_TTS_AUDIO_EXPORT_UNAVAILABLE for native voices. Request-local model overrides remain exact and never mutate the configured model. Browser-speech protocol/event/error/reason constants; default `AI`; read-only `providerRuntime`, `browserSpeechConfiguration`, and `browserSpeechDescriptor`; explicit `providerRuntime.status(role,{execution:true})` snapshots; `streamTTS(text,end,options={})` with optional voice, speed, pauseAfterMs, and waitForPlayback;
|
|
32
|
+
"normalization": "Complete mutable caller-owned browser speech authority, SDK-owned provider registration/replacement/disposal, explicit STT/TTS activation, normalized Whisper STT and Kokoro TTS execution with default capacities 1 and 4 respectively, explicit provider-neutral execution snapshots through status(role,{execution:true}), sticky readiness, canonical window.user readiness without compatibility-event object-identity admission or polling, exact ordered structural calls with required arguments.message, atomic nonblank all-ID tool-result sequencing, complete all-choice streaming/data validation, native Ollama structural adaptation, complete-response then all validated tool callbacks then completion ordering, observed async callbacks, Blob/File transcription, default repeated-formatting-mark removal from cloned outbound TTS input, explicit textFormat:'plain' preservation for complete synthesis/preparation while streaming cleanup remains automatic and caller/visible content stays exact, immediate exact-segment synthesis, per-call voice/speed capture, optional final-segment pause on the existing audio clock, optional per-call terminal playback completion, detached preparation with complete semantic DBOPFS audio reuse and same-owner pending request sharing, independent prepared playback without a model load for cached audio, ordered audio-clock scheduling, playable audio, active-generation TTS operation-failure routing, mute, and cancellation are normalized; provider/model/runtime/voice policy remains caller-owned. Both speech roles default execution.device to auto: webnn-npu when navigator.ml.createContext is exposed, then webgpu when navigator.gpu is exposed, then wasm for CPU execution. Failed backend loads clean up the pool before trying fresh Workers with the same prepared model and dtype; explicit devices never fall back. STT capacity only accepts 1; TTS accepts 1 through 4. Execution snapshots expose requestedDevice, selectedDevice, maxConcurrentRequests, and activeRequestCount for both roles; selectedDevice is null while unloaded and names the successful upstream session backend request when loaded. It does not prove every operation used the physical NPU: WebNN unsupported operations may use WASM, and compatibility depends on the browser, driver, hardware, and graph.",
|
|
33
|
+
"surface": "Native fetchTTS(payload,signal) and fetchSTT(audio,signal) forward caller cancellation separately from their complete Core speech payloads, normalize aborts to AbortError and suppress late results; actual engine interruption remains service-owned. prepareTTSPlayback(payload,signal) silently returns a real Blob or native-speech descriptor; native controls expose finished/released/state/error/pause/resume/stop, and actual release owns the playback lane. fetchTTS and durable prepareTTS report ARCANE_AI_TTS_AUDIO_EXPORT_UNAVAILABLE for native voices. Request-local model overrides remain exact and never mutate the configured model. Browser-speech protocol/event/error/reason constants; default `AI`; read-only `providerRuntime`, `browserSpeechConfiguration`, and `browserSpeechDescriptor`; explicit `providerRuntime.status(role,{execution:true})` snapshots; `streamTTS(text,end,options={})` with optional voice, speed, pauseAfterMs, and waitForPlayback; default speech-input cleanup with SDK-internal preparation metadata and explicit complete-call textFormat:'plain' consumed before engine dispatch; `prepareTTS({parts,storage,identity,textFormat,signal,onState})` returning ordered segments, state, ready, getAudio(index), and cancel(); `playPreparedTTS(prepared,{signal,onState})` returning state, error, finished, pause(), resume(), and stop() with one playback lane per AI and observational state/error callbacks; configure/dispose speech, route lifecycle, declaration-validated chat/stream requests with exact ordered calls; optional streamRequest toolText:{name,field} and onToolText(text,call,displayId) for decoded selected argument text with actual call identity, distinct from ordinary prose and terminal tool execution; synthesis/transcription and playback controls; initializes from current canonical user readiness, installs `window.ai`, and projects `ai-ready` plus active-generation `ai-tts-failure`."
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"file": "runtime/arcane/modules/AIModelSelectionController.js",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"summary": "Provider-neutral selection, lifecycle, routing, startup, request, streaming, cancellation, and independent LLM/STT/TTS state.",
|
|
91
91
|
"availability": "Cross-host in-process runtime; registered providers remain browser, native, or cloud specific",
|
|
92
92
|
"protocol": "arcane-ai-runtime/2, arcane-ai-provider/2, arcane-ai-model-authority/1",
|
|
93
|
-
"normalization": "Normalizes mutable complete per-role routes, lifecycle/status, cancellation, streaming cleanup, capacity-1 FIFO LLM/STT lanes, bounded provider-declared parallel TTS requests with FIFO overflow,
|
|
93
|
+
"normalization": "Normalizes mutable complete per-role routes, lifecycle/status, cancellation, streaming cleanup, capacity-1 FIFO LLM/STT lanes, bounded provider-declared parallel TTS requests with FIFO overflow, default repeated-formatting-mark removal from cloned direct TTS payloads or explicit textFormat:'plain' preservation with the control consumed before engine dispatch, local-only selection, direct LLM history/declaration/terminal structural contracts, complete all-choice content/reasoning FIFO iteration, private automatic provider draining with result-first buffering, terminal-only structural calls, exact per-choice observed/terminal correlation, and a separate complete validated terminal result without creating a fallback.",
|
|
94
94
|
"surface": "Protocol constants; singleton-only `AIProviderRuntime`; `aiProviderRuntime`; `getAIProviderRuntime()`; provider registration/identity/selection, closed three-role and STT/TTS-only validation/configuration/replacement, status/catalog/inspection, startup, per-role load/unload/dispose/cancel, dispose-all, request/stream/speech aliases, SDK-internal speech-input preparation metadata, and mute controls."
|
|
95
95
|
},
|
|
96
96
|
{
|
|
@@ -578,11 +578,11 @@
|
|
|
578
578
|
"DBOPFS_REASONS",
|
|
579
579
|
"default"
|
|
580
580
|
],
|
|
581
|
-
"summary": "Provides app-scoped OPFS tables, explicit non-recursive empty-table removal, worker I/O, backup/restore, compression, and CRUD/batch APIs.",
|
|
581
|
+
"summary": "Provides app-scoped OPFS tables, committed-change subscriptions with targeted cache freshness, explicit non-recursive empty-table removal, worker I/O, backup/restore, compression, and CRUD/batch APIs.",
|
|
582
582
|
"availability": "Browser / native WebView",
|
|
583
|
-
"protocol": "OPFS, DBOPFSWorker, Compression Streams,
|
|
583
|
+
"protocol": "OPFS, DBOPFSWorker, Compression Streams, per-realm globalThis.arcaneEvents authority, and native BroadcastChannel for live same-app/storage-partition committed changes",
|
|
584
584
|
"normalization": "App scope and recognized file parsing are normalized; nonblank unreadable JSONL rows remain complete raw strings, empty-table removal reports removed, absent, or not-empty after a create:false directory lookup and without scanning or recursively clearing a directory, same-named files are preserved, aliases and cached handles are invalidated only when the directory is gone, and unexpected DOM/storage errors are preserved.",
|
|
585
|
-
"surface": "default `DBOPFS`; installs `window.dbopfs`, emits `dbopfs-ready`; table/file/backup APIs
|
|
585
|
+
"surface": "default `DBOPFS`; installs `window.dbopfs`, emits `dbopfs-ready`; subscribeChanges(listener,{signal,once}) observes DBOPFS_EVENT_TYPES.change (dbopfs-change), returns idempotent unsubscribe/.dispose, and publishes metadata {applicationId,storagePath,tableName,directoryName,fileName,action,originId,sequence,changeId,remote} after successful storage commits only. Actions are write/append/delete/table-delete; batches preserve partial success, remote receipts invalidate targeted aliases before local publication and never rebroadcast, and pagehide/pageshow closes/reopens the native channel and clears memory caches without replay or fabricated changes. Local subscription/storage continue when BroadcastChannel is unavailable. Table/file/backup APIs include removeEmptyTable(tableName). createCompressedPNG({tableNames,additionalTables,signal}) returns a PNG Blob without download or record writes; omitted names select all, [] none, and supplied tables replace matching saved tables in the export. downloadCompressedPNG(name,options) reuses the same preparation and initiates one download; cancellation prevents it. restoreFromPNG(file,{selectTables}) closes the decoded image after pixel extraction, awaits the optional caller selection/projection before any writes, and rejects DBOPFS_RESTORE_WRITE_FAILED AggregateError after all selected table batches settle when records fail, preserving original errors and failures {tableName,fileName,reason}; successful writes remain. No-options restore and setMany retain their contracts."
|
|
586
586
|
},
|
|
587
587
|
{
|
|
588
588
|
"file": "runtime/arcane/modules/DBOPFSDocumentLibrary.js",
|
|
@@ -112,7 +112,7 @@ snapshot remains owned until the browser's `afterprint` event.
|
|
|
112
112
|
| [`task-progress.html`](#task-progresshtml) | Runs and displays a task list with started/change/complete/error state. | `configure()`<br>`setTasks()`<br>`updateTask()`<br>`runTasks()`<br>`clear()`<br>`destroy()` | `task-progress-ready`<br>`task-progress-started`<br>`task-progress-change`<br>`task-progress-complete`<br>`task-progress-error` | Task state normalized; injected task results mixed |
|
|
113
113
|
| [`terminal-workspace.html`](#terminal-workspacehtml) | Presents multiple terminal sessions, output, active selection, theme, and terminal actions. | `configure()`<br>`addSession()`<br>`removeSession()`<br>`activateSession()`<br>`append()`<br>`clear()`<br>`setState()`<br>`setTheme()`<br>`focus()`<br>`destroy()` | `terminal-workspace-ready`<br>`terminal-submit`<br>`terminal-interrupt`<br>`terminal-clear`<br>`terminal-session-new`<br>`terminal-session-close`<br>`terminal-session-select`<br>`terminal-settings` | UI/session state normalized; native command results supplied externally |
|
|
114
114
|
| [`theme-editor.html`](#theme-editorhtml) | Edits, previews, saves, and resets semantic custom theme tokens. | `configure()`<br>`getTheme()`<br>`setTheme()`<br>`setBusy()`<br>`setStatus()`<br>`destroy()` | `theme-editor-ready`<br>`theme-preview`<br>`theme-save`<br>`theme-reset` | Fully normalized Theme values |
|
|
115
|
-
| [`theme-switcher.html`](#theme-switcherhtml) | Selects and refreshes system, light, dark, or custom theme mode with per-instance choices and
|
|
115
|
+
| [`theme-switcher.html`](#theme-switcherhtml) | Selects and refreshes system, light, dark, or custom theme mode with per-instance choices, labels, and CSS-configurable group/option radii, option font and group background. | `configure()`<br>`setMode()`<br>`refresh()` | No component-specific event | Preference/native appearance behavior mixed; no component-ready contract |
|
|
116
116
|
| [`unified-inbox.html`](#unified-inboxhtml) | Displays provider-neutral communication threads with active/loading state. | `configure()`<br>`setThreads()`<br>`setActive()`<br>`setLoading()`<br>`destroy()` | `unified-inbox-ready`<br>`inbox-refresh`<br>`thread-select` | DOM-normalized |
|
|
117
117
|
| [`voice-transcription.html`](#voice-transcriptionhtml) | Records manual clips or optional continuous microphone audio with pause/periodic segments, ordered transcription and saves, retained failures, and complete transcript delivery. | `configure()`<br>`requestSTTActivation()`<br>`startRecording()`<br>`stopRecording()`<br>`retryTranscription()`<br>`cancelRecording()`<br>`save()`<br>`completeTranscription()/complete()`<br>`clear()`<br>`reset()`<br>`destroy()` | `voice-transcription-ready`<br>`voice-transcription-state`<br>`voice-transcription-segment`<br>`voice-transcription-empty`<br>`voice-transcription-error`<br>`voice-transcription-change`<br>`voice-transcription-complete`<br>`speech-transcription-complete`<br>`speech-transcription-cancelled`<br>`speech-stt-activation-request`<br>`speech-stt-activation-error` | Sticky STT readiness, capture/queue lifecycle, retry, cancellation, and complete state/text are normalized; media/provider behavior remains external |
|
|
118
118
|
| [`weather-widget.html`](#weather-widgethtml) | Displays normalized current and daily weather with refresh intent. | `setWeather()`<br>`clear()`<br>`destroy()` | `weather-widget-ready`<br>`weather-refresh` | Display normalized; provider supplied externally |
|
|
@@ -2073,6 +2073,24 @@ The host inherits text color. Existing `--app-bar-border` (falling back to
|
|
|
2073
2073
|
remain supported. Applications own their palette and surrounding placement;
|
|
2074
2074
|
the component adds no application-specific palette or settings section.
|
|
2075
2075
|
|
|
2076
|
+
Set these public CSS custom properties on the `html-import` host or an ancestor
|
|
2077
|
+
to style one instance through the ordinary cascade. Omitting them preserves the
|
|
2078
|
+
existing presentation:
|
|
2079
|
+
|
|
2080
|
+
| Property | Controls | Default |
|
|
2081
|
+
| --- | --- | --- |
|
|
2082
|
+
| `--theme-switcher-radius` | Outer group border radius | `1.6rem` |
|
|
2083
|
+
| `--theme-switcher-option-radius` | Each option's border radius | `1.4rem` |
|
|
2084
|
+
| `--theme-switcher-font` | Complete option `font` shorthand | `700 .875rem/1.25 system-ui,sans-serif` |
|
|
2085
|
+
| `--theme-switcher-background` | Group background, independent of option state | `color-mix(in srgb,currentColor 8%,transparent)` |
|
|
2086
|
+
|
|
2087
|
+
The font value includes its size and family, plus any weight and line height.
|
|
2088
|
+
Use an application-owned complete font token or value, rather than the
|
|
2089
|
+
CSS-wide keyword `inherit` as the custom-property value. The host still inherits
|
|
2090
|
+
text color. These properties do not alter the `2.75rem` minimum targets,
|
|
2091
|
+
full-label wrapping, selected/hover/focus/disabled states, or theme persistence.
|
|
2092
|
+
Applications retain responsibility for readable font and color choices.
|
|
2093
|
+
|
|
2076
2094
|
This fragment declares no component-specific readiness or action event; use the loader's `html-import-ready` only to know that import execution completed.
|
|
2077
2095
|
|
|
2078
2096
|
Shared dependencies: [`ThemeManager.js`](runtime-modules.md#thememanagerjs).
|
|
@@ -2097,6 +2115,22 @@ the two configuration attributes retains all four default choices. Both use
|
|
|
2097
2115
|
the existing shared preference owner; presentation does not create a new store
|
|
2098
2116
|
or migrate saved themes.
|
|
2099
2117
|
|
|
2118
|
+
An application can give that instance modest rounded corners and its own
|
|
2119
|
+
ordinary label font without accessing the shadow root:
|
|
2120
|
+
|
|
2121
|
+
```css
|
|
2122
|
+
#theme-switcher {
|
|
2123
|
+
--theme-switcher-radius: .65rem;
|
|
2124
|
+
--theme-switcher-option-radius: .5rem;
|
|
2125
|
+
--theme-switcher-font: 400 1rem/1.25 var(--app-font-family, system-ui, sans-serif);
|
|
2126
|
+
--theme-switcher-background: transparent;
|
|
2127
|
+
--app-bar-border: var(--border-color);
|
|
2128
|
+
}
|
|
2129
|
+
```
|
|
2130
|
+
|
|
2131
|
+
These are example application values, not new component defaults. Other
|
|
2132
|
+
instances retain the defaults unless the application cascades overrides to them.
|
|
2133
|
+
|
|
2100
2134
|
## unified-inbox.html
|
|
2101
2135
|
|
|
2102
2136
|
### Overview
|