arcane-os 0.37.0 → 0.39.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 +33 -0
- package/README.md +1 -1
- package/browser-runtime/pwa-install.mjs +42 -3
- package/browser-runtime/pwa.mjs +16 -0
- package/docs/reference/inventory/package-api.json +6 -6
- package/docs/reference/inventory/runtime-components.json +8 -6
- package/docs/reference/inventory/runtime-entities.json +2 -2
- package/docs/reference/inventory/runtime-modules.json +20 -8
- package/docs/reference/pwa.md +68 -6
- package/docs/reference/runtime-components.md +44 -9
- package/docs/reference/runtime-entities.md +35 -2
- package/docs/reference/runtime-modules.md +151 -10
- package/docs/reference/sdk-api.md +31 -8
- package/package.json +1 -1
- package/runtime/arcane/components/chat.html +11 -2
- package/runtime/arcane/components/file-manager.html +24 -3
- package/runtime/arcane/components/header.html +5 -18
- package/runtime/arcane/components/pwa-install.html +43 -10
- package/runtime/arcane/css/layout.css +8 -201
- package/runtime/arcane/css/theme.css +278 -61
- package/runtime/arcane/entities/Chat.js +15 -3
- package/runtime/arcane/entities/User.js +20 -0
- package/runtime/arcane/modules/PersistentAIChatSession.js +28 -25
- package/runtime/arcane/modules/ThemeBootstrap.js +31 -3
- package/runtime/arcane/modules/ThemeManager.js +33 -1
- package/runtime/arcane/modules/ThemePresentation.js +138 -0
- package/src/pwa-worker.mjs +88 -2
|
@@ -82,7 +82,7 @@ appropriate.
|
|
|
82
82
|
| [`modal.html`](#modalhtml) | Generic modal with population, configurable user dismissal, actions, and concurrent task execution. | `configure()`<br>`populate()`<br>`open()`<br>`close()`<br>`runTasks()`<br>`destroy()`<br>`running`<br>`opened` | `modal-ready`<br>`modal-opened`<br>`modal-closed`<br>`modal-action` | Modal state normalized; injected task results mixed |
|
|
83
83
|
| [`output-panel.html`](#output-panelhtml) | Presents status, output, body, coverage, actions, pending, error, and cleared states. | `configure()`<br>`setOutput()`<br>`setBody()`<br>`setCoverage()`<br>`setActions()`<br>`setPending()`<br>`setStatus()`<br>`setError()`<br>`clear()`<br>`destroy()` | `output-panel-ready`<br>`output-panel-state`<br>`output-panel-change`<br>`output-panel-action`<br>`output-panel-error`<br>`output-panel-cleared` | DOM-normalized |
|
|
84
84
|
| [`preferences-form.html`](#preferences-formhtml) | Builds a schema-driven preferences form with submit, reset, busy, and status behavior. | `configure()`<br>`getValues()`<br>`setValues()`<br>`setBusy()`<br>`setStatus()`<br>`destroy()` | `preferences-form-ready`<br>`preferences-change`<br>`preferences-submit`<br>`preferences-reset` | Normalized form values |
|
|
85
|
-
| [`pwa-install.html`](#pwa-installhtml) | Presents
|
|
85
|
+
| [`pwa-install.html`](#pwa-installhtml) | Presents independent installation and explicit update/reload actions with floating or inline placement. | `configure()`<br>`install()`<br>`dismiss()`<br>`update()`<br>`dismissUpdate()`<br>`destroy()`<br>`state`<br>`ready` | `pwa-install-ready`<br>`pwa-install-change`<br>`pwa-install-dismissed` | Complete labels and independent installation/update state; native unload cancellation leaves Update available |
|
|
86
86
|
| [`record-timeline.html`](#record-timelinehtml) | Displays complete chronological records/evidence and emits open actions. | `setItems()`<br>`populate()`<br>`destroy()` | `record-timeline-ready`<br>`record-timeline-open` | Complete item fields and inventories preserved |
|
|
87
87
|
| [`relationship-board.html`](#relationship-boardhtml) | Displays complete normalized relationship nodes/edges in graph and list forms. | `setGraph()`<br>`populate()`<br>`destroy()` | `relationship-board-ready`<br>`relationship-node-open`<br>`relationship-edge-open` | Complete graph inventories and fields preserved |
|
|
88
88
|
| [`screen-capture.html`](#screen-capturehtml) | Presents image, video, or GIF display-capture workflow. | `capture` (`ScreenCapture` instance)<br>`destroy()` | `screen-capture-ready`<br>`screen-capture-result` | State/result normalized; media permission/codec failures mixed |
|
|
@@ -351,6 +351,15 @@ restored or new message uses a separate semantic `<time>` element at the card's
|
|
|
351
351
|
lower-right with an ISO `datetime`, full local title, and local 24-hour `HH:MM`
|
|
352
352
|
text.
|
|
353
353
|
|
|
354
|
+
Restored assistant cards use the record's exact nonblank string `name`, or
|
|
355
|
+
`AI` when absent. The current profile/model/voice name never renames older
|
|
356
|
+
messages. For live session replies, the card starts with `session.aiName`
|
|
357
|
+
when nonblank, otherwise the existing `host.aiName` display value; the terminal
|
|
358
|
+
result aligns it with the name captured by the session for that operation.
|
|
359
|
+
Set the session/entity name as well as the live component label when the
|
|
360
|
+
application intends new saved turns to retain that attribution. The shared
|
|
361
|
+
component does not persist the profile name or choose a naming policy.
|
|
362
|
+
|
|
354
363
|
Assistant structural calls render their nonempty `function.arguments.message`
|
|
355
364
|
as ordinary visible progress. The exact call name and argument string are
|
|
356
365
|
retained inside a collapsed `Tool call details` inspection surface. Displaying
|
|
@@ -844,7 +853,11 @@ Each descriptor accepts an optional `title`. Supported shapes are:
|
|
|
844
853
|
| `image`, `audio`, `pdf`, `download` | `content`: a `Blob` or `File`, or a function receiving `{signal}` and resolving to one |
|
|
845
854
|
|
|
846
855
|
Conversation `role` and complete Markdown `content` are strings. Optional
|
|
847
|
-
`name`
|
|
856
|
+
assistant `name` is displayed exactly when it is a nonblank string; otherwise
|
|
857
|
+
the assistant label is `AI`, without a role suffix. User and other role labels
|
|
858
|
+
retain their supplied name alongside the role. User and assistant cards use
|
|
859
|
+
distinct shared-theme backgrounds, and each card retains its original
|
|
860
|
+
`data-role`. Optional `status` is displayed beside the time. Valid supplied
|
|
848
861
|
timestamps are displayed in local time with their real ISO datetime; absent
|
|
849
862
|
timestamps display `Time unavailable`, and an unrecognized supplied timestamp
|
|
850
863
|
is displayed as supplied. No timestamp is invented.
|
|
@@ -1253,9 +1266,10 @@ Events: `preferences-form-ready`, `preferences-change`, `preferences-submit`, `p
|
|
|
1253
1266
|
|
|
1254
1267
|
### Overview
|
|
1255
1268
|
|
|
1256
|
-
A compact installation suggestion using the shared [PWA
|
|
1257
|
-
The default floating panel appears near the top right
|
|
1258
|
-
installation
|
|
1269
|
+
A compact installation and update suggestion using the shared [PWA owner](pwa.md).
|
|
1270
|
+
The default floating panel appears near the top right when the browser offers
|
|
1271
|
+
installation or a completed resource refresh establishes an update. It has an
|
|
1272
|
+
Install or Update action and an explicit close button, takes no
|
|
1259
1273
|
focus automatically, and has no dismissal timer. It uses the Arcane theme and
|
|
1260
1274
|
primitives, wraps complete labels and errors, and scrolls its own content when
|
|
1261
1275
|
the available height is limited. The parent page loads `ThemeBootstrap.js` to
|
|
@@ -1264,7 +1278,8 @@ apply the user's appearance preferences.
|
|
|
1264
1278
|
### Public surface
|
|
1265
1279
|
|
|
1266
1280
|
`configure({appName, installLabel, closeLabel, promptingLabel, description,
|
|
1267
|
-
presentation})`
|
|
1281
|
+
updateTitle, updateLabel, updateDescription, updateCloseLabel, presentation})`
|
|
1282
|
+
updates display configuration and returns its current record.
|
|
1268
1283
|
Labels remain complete strings. `appName` initially uses `data-app-name` or
|
|
1269
1284
|
`this app`; the default button label is `Install`. `presentation` is `floating`
|
|
1270
1285
|
by default or `inline`, initially read from `data-presentation`. Inline placement
|
|
@@ -1278,6 +1293,20 @@ An explicit request's complete failure message remains visible until dismissed;
|
|
|
1278
1293
|
the method rejects with the same error. The browser controls actual installation.
|
|
1279
1294
|
Acceptance hides the suggestion without claiming installation has completed.
|
|
1280
1295
|
|
|
1296
|
+
When an update is available, the same panel shows `Update available`, `Update`,
|
|
1297
|
+
`Reload this page to use the updated app.`, and the close label `Close update
|
|
1298
|
+
suggestion`. Each string has its matching configuration key. This presentation
|
|
1299
|
+
takes precedence over installation, including for installed/running apps and
|
|
1300
|
+
previously dismissed installation suggestions.
|
|
1301
|
+
|
|
1302
|
+
`update()` calls the shared owner's ordinary `location.reload()` synchronously,
|
|
1303
|
+
returning true when available and false when unavailable or destroyed. It leaves
|
|
1304
|
+
availability intact if a native unload handler cancels navigation. Native reload
|
|
1305
|
+
errors propagate; the button observes them through developer diagnostics. There
|
|
1306
|
+
is no automatic reload, extra SDK confirmation, cache reset, or guarantee of
|
|
1307
|
+
preserving transient application state. `dismissUpdate()` hides only the update
|
|
1308
|
+
suggestion for this page owner and returns true, or false after destruction.
|
|
1309
|
+
|
|
1281
1310
|
`dismiss()` closes the component. Floating dismissal also uses the owner's
|
|
1282
1311
|
session dismissal; an explicit inline component ignores that shared dismissal
|
|
1283
1312
|
and closes only its own instance. Closing retains any unused native prompt at
|
|
@@ -1286,22 +1315,28 @@ disposes its event source, hides its host, and marks `ready` false; it does not
|
|
|
1286
1315
|
dispose the shared owner or change browser installation state. Both methods
|
|
1287
1316
|
return true while active and false after destruction; `destroy()` is idempotent.
|
|
1288
1317
|
|
|
1289
|
-
The readonly `state` property returns the shared owner's current install-state
|
|
1318
|
+
The readonly `state` property returns the shared owner's current install/update-state
|
|
1290
1319
|
record; `ready` becomes true after methods and the state subscription are attached.
|
|
1291
1320
|
`pwa-install-ready` carries `{ready, state}`; `pwa-install-change` carries
|
|
1292
1321
|
`{state, visible}` for each observed owner update; `pwa-install-dismissed` carries
|
|
1293
|
-
`{presentation, state}
|
|
1322
|
+
`{presentation, state}`, with `kind: 'update'` for update dismissal. These follow
|
|
1323
|
+
the canonical event projection contract.
|
|
1294
1324
|
|
|
1295
1325
|
### Availability and normalization
|
|
1296
1326
|
|
|
1297
1327
|
The component requires HTMLImport and a DOM renderer. Native installation
|
|
1298
1328
|
availability comes from the browser's `beforeinstallprompt` event through
|
|
1299
|
-
`getPwaInstall()`. Without an available event, the suggestion stays hidden;
|
|
1329
|
+
`getPwaInstall()`. Without an available event, the installation suggestion stays hidden;
|
|
1300
1330
|
absence does not identify why installation is unavailable. Installed-app events,
|
|
1301
1331
|
accepted prompts, and an already running installed display mode hide it.
|
|
1302
1332
|
The shared SDK owner persists browser-reported installation in app-scoped
|
|
1303
1333
|
DBOPFS. Both floating and inline controls stay hidden while that record is
|
|
1304
1334
|
loading and remain hidden on later visits when installation is remembered.
|
|
1335
|
+
Those installation conditions do not hide an available update. Update state
|
|
1336
|
+
comes from the existing page-scoped registration owner, including a current-state
|
|
1337
|
+
read when the prompt is created after the refresh. A new page does not replay a
|
|
1338
|
+
completed update from an earlier page. Update dismissal is independent of saved
|
|
1339
|
+
installation state and performs no durable write.
|
|
1305
1340
|
Acceptance alone does not save installation. The component's `ready` means
|
|
1306
1341
|
its methods and subscription are attached; storage completion belongs to the
|
|
1307
1342
|
shared owner's `ready` promise and does not delay page rendering.
|
|
@@ -78,8 +78,9 @@ call and its matching results remain raw only through their one active provider
|
|
|
78
78
|
continuation. Once that continuation settles, `messages` replaces the protocol
|
|
79
79
|
with complete ordinary visible call, public result, and assistant content.
|
|
80
80
|
`transcript` returns the narrow human-readable projection owned by the durable
|
|
81
|
-
storage boundary. User and assistant records contain
|
|
82
|
-
visible content, and their real timestamp.
|
|
81
|
+
storage boundary. User and assistant records contain role, complete
|
|
82
|
+
visible content, and their real timestamp. An assistant record may also carry
|
|
83
|
+
its application-owned display `name`. A visible tool record may
|
|
83
84
|
additionally carry its public name and plain result status, while its `content`
|
|
84
85
|
comes only from the tool call's required user-facing `message`. System prompts,
|
|
85
86
|
reasoning, provider-extension fields, memory flags, raw tool calls, call IDs,
|
|
@@ -90,6 +91,15 @@ One complete nonblank assistant record is also a durable conversation entry, so
|
|
|
90
91
|
a model-authored opening can be stored and survive maintenance before the first
|
|
91
92
|
ordinary user turn. No synthetic user record is required or written.
|
|
92
93
|
|
|
94
|
+
`aiName` defaults to an empty string. `addAIMessage(text,{name=chat.aiName,...})`
|
|
95
|
+
and `addTurn({name=chat.aiName,...})` capture that application-owned name on the
|
|
96
|
+
new assistant record. A nonblank string is preserved exactly; blank or
|
|
97
|
+
nonstring names are omitted. Provider `message.name` never establishes that
|
|
98
|
+
display attribution. The name is transcript-only metadata: `messages` and
|
|
99
|
+
memory extraction omit it, including during a pending tool continuation.
|
|
100
|
+
Changing `aiName` affects later messages only; loading existing records does
|
|
101
|
+
not rename or rewrite them.
|
|
102
|
+
|
|
93
103
|
An assistant record may open an ordered array of structural calls with unique
|
|
94
104
|
IDs in transient provider state. Until every pending ID receives exactly one
|
|
95
105
|
matching nonblank `role:'tool'` result in the same active session, another
|
|
@@ -274,6 +284,29 @@ Owns persisted user preference/profile fields, explicit-preference updates,
|
|
|
274
284
|
fresh reads, saves, and JSON projection. It installs `window.user` after its
|
|
275
285
|
DBLS/DBOPFS lifecycle and emits `user-entity-loaded`.
|
|
276
286
|
|
|
287
|
+
### AI_name
|
|
288
|
+
|
|
289
|
+
Saved AI-name preference alongside `AI_personality`. It is a string with an
|
|
290
|
+
empty-string default and preserves the complete supplied text, including
|
|
291
|
+
Unicode, whitespace, and an explicitly empty value. The property setter follows
|
|
292
|
+
the same persistence setting as `AI_personality`; non-string assignments throw
|
|
293
|
+
`Error('AI_name must be string')`.
|
|
294
|
+
|
|
295
|
+
`explicit`, `toJSON()`, `load()`, `refresh()`, and `updateExplicit()` include
|
|
296
|
+
this field through the existing profile schema. Loading an older record that
|
|
297
|
+
omits it leaves a new entity's empty default in memory and does not rewrite the
|
|
298
|
+
stored record. Partial updates that omit it retain the current value.
|
|
299
|
+
|
|
300
|
+
```javascript
|
|
301
|
+
await user.updateExplicit(
|
|
302
|
+
{AI_name: 'Captain Moonboots'}
|
|
303
|
+
);
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
The application owns naming choices and any mapping to its AI display name;
|
|
307
|
+
this preference changes neither the human `username` nor chat history. No
|
|
308
|
+
automatic migration or naming policy runs when it is loaded or saved.
|
|
309
|
+
|
|
277
310
|
### updateExplicit(update)
|
|
278
311
|
|
|
279
312
|
Accepts an ordinary partial profile object, a JSON string, or a function
|
|
@@ -125,8 +125,9 @@ own asynchronous work, cancellation, and backpressure.
|
|
|
125
125
|
| [`SystemToolRegistry.js`](#systemtoolregistryjs) | esm | Registers validated command builders and constructs command strings without executing them. | Cross-host | Fully normalized definitions/quoting. |
|
|
126
126
|
| [`TerminalClient.js`](#terminalclientjs) | esm | Maps native terminal sessions and Arcane events into an EventTarget client. | Native bridge | Client events/state normalized; native result/error mixed. |
|
|
127
127
|
| [`TerminalCommandRegistry.js`](#terminalcommandregistryjs) | esm | Routes parsed command lines to injected handlers and provides definitions/completions. | Cross-host | Parsing/routing normalized; handler result/error preserved. |
|
|
128
|
-
| [`ThemeBootstrap.js`](#themebootstrapjs) | esm |
|
|
128
|
+
| [`ThemeBootstrap.js`](#themebootstrapjs) | esm | Loads authoritative appearance preferences and observes existing User readiness without blocking rendering. | Browser/native hybrid | Theme state normalized; storage/native errors mixed. |
|
|
129
129
|
| [`ThemeManager.js`](#thememanagerjs) | esm | Loads, applies, previews, saves, resets, and synchronizes semantic Arcane themes. | Browser/native hybrid | Theme values/events normalized; storage/native failures mixed. |
|
|
130
|
+
| [`ThemePresentation.js`](#themepresentationjs) | classic-script | Restores app-scoped presentation before CSS and owns complete skin-class application. | Browser / native WebView classic script | Synchronous presentation only; saved profile and preferences remain authoritative. |
|
|
130
131
|
| [`TimeGuard.js`](#timeguardjs) | esm | Persists and evaluates clock rollback and grace-period state. | Browser / native WebView | Time decisions normalized; storage lifecycle mixed. |
|
|
131
132
|
| [`ToolCallRouter.js`](#toolcallrouterjs) | esm | Parses OpenAI-style tool calls and dispatches complete or streamed calls to injected handlers. | Cross-host | Argument records validated; handler results returned or all-settled. |
|
|
132
133
|
| [`uPlot.iife.min.js`](#uplotiifeminjs) | classic-script | Vendored uPlot chart constructor and rendering runtime. | Browser vendor script | Vendor-native. |
|
|
@@ -3013,13 +3014,24 @@ semantics; it does not define a new storage protocol.
|
|
|
3013
3014
|
Exact exports: `PersistentAIChatSession`, `createPersistentAIChatSession`, and
|
|
3014
3015
|
`default`.
|
|
3015
3016
|
|
|
3016
|
-
Constructor and factory options are `{ai,chat,chatEntity,chatFileName,
|
|
3017
|
+
Constructor and factory options are `{ai,aiName,chat,chatEntity,chatFileName,
|
|
3017
3018
|
contextBuilder,loadExisting,memory,request,responseLength,systemPrompt}`. Public members are
|
|
3018
3019
|
static `create()`, getters `ai`, `chatEntity`, and `fileName`, and `ready()`,
|
|
3019
3020
|
`history()`, `transcript()`, `settleMemory()`, `open(input)`, `send(input)`, and
|
|
3020
3021
|
`stream(input,handlers)`.
|
|
3021
3022
|
`ready()` waits for initialization and resolves the same session instance.
|
|
3022
3023
|
|
|
3024
|
+
Optional `aiName` is an application-owned string, also exposed through the
|
|
3025
|
+
session's getter/setter. `open()`, `send()`, and `stream()` capture it at operation
|
|
3026
|
+
entry before awaiting readiness, memory, or the provider, so later name changes
|
|
3027
|
+
apply only to subsequent operations. A nonblank name is preserved exactly on
|
|
3028
|
+
the copied terminal `message.name` and the retained assistant transcript record;
|
|
3029
|
+
the terminal copy carries the assistant record's real timestamp when one exists.
|
|
3030
|
+
Empty or whitespace-only names omit this display field. The complete raw
|
|
3031
|
+
`providerResponse` stays unchanged. Configured model context and memory inputs
|
|
3032
|
+
omit the application display name. Existing stored history is never renamed or
|
|
3033
|
+
rewritten when `aiName` changes; `persist:false` remains operation-only.
|
|
3034
|
+
|
|
3023
3035
|
`open({message:{content,persist:false?},request?,signal?})` performs one
|
|
3024
3036
|
application-authored bootstrap request only when the retained conversation is
|
|
3025
3037
|
otherwise empty. The bootstrap is never committed. After a complete nonblank
|
|
@@ -3049,8 +3061,9 @@ system prompt and every complete ordinary visible committed turn. Only a
|
|
|
3049
3061
|
currently unresolved structural-call tail remains raw for its matching active
|
|
3050
3062
|
continuation. `transcript()` returns the sanitized human-readable ChatEntity
|
|
3051
3063
|
projection.
|
|
3052
|
-
User and assistant records retain
|
|
3053
|
-
real timestamp
|
|
3064
|
+
User and assistant records retain role, complete visible content, and the
|
|
3065
|
+
real timestamp, with an optional exact nonblank application display name on
|
|
3066
|
+
assistant records. Tool records retain only role, the required user-facing
|
|
3054
3067
|
`message` as content, and optional public `name` and result `status`.
|
|
3055
3068
|
|
|
3056
3069
|
`stream()` accepts the same input as `send()` and optional
|
|
@@ -3755,7 +3768,12 @@ console.log(Object.keys(module));
|
|
|
3755
3768
|
|
|
3756
3769
|
### Overview
|
|
3757
3770
|
|
|
3758
|
-
Performs import-time Arcane theme loading
|
|
3771
|
+
Performs import-time Arcane theme loading, reuses the shared presentation
|
|
3772
|
+
owner, and subscribes to native appearance changes and
|
|
3773
|
+
the canonical user's readiness event. Rendering does not wait for profile
|
|
3774
|
+
loading. A ready user is replayed immediately; its saved skin supersedes the
|
|
3775
|
+
presentation cache. Bootstrap observes the existing User lifecycle rather than
|
|
3776
|
+
creating a profile or migrating saved data.
|
|
3759
3777
|
|
|
3760
3778
|
### Public surface
|
|
3761
3779
|
|
|
@@ -3764,6 +3782,16 @@ Performs import-time Arcane theme loading and subscribes to native appearance ch
|
|
|
3764
3782
|
Exact exports: `arcaneThemeReady`, `bootstrapArcaneTheme`, `default`, and
|
|
3765
3783
|
`disposeArcaneThemeBootstrap`.
|
|
3766
3784
|
|
|
3785
|
+
`disposeArcaneThemeBootstrap()` removes both bootstrap-owned subscriptions.
|
|
3786
|
+
The cache is a presentation hint, not the authority for preferences or user
|
|
3787
|
+
data. Preference loading and User readiness independently reconcile it; cache
|
|
3788
|
+
failures are logged without blocking the page.
|
|
3789
|
+
|
|
3790
|
+
Module evaluation follows its import graph, so importing ThemeBootstrap alone
|
|
3791
|
+
does not establish restoration before the first paint. Use the classic
|
|
3792
|
+
[ThemePresentation head entry](#themepresentationjs) before CSS for that early
|
|
3793
|
+
restoration. Neither entry imports User or starts its storage lifecycle.
|
|
3794
|
+
|
|
3767
3795
|
### Availability and normalization
|
|
3768
3796
|
|
|
3769
3797
|
**Browser/native hybrid.** Theme state normalized; storage/native errors mixed. Transport: ThemeManager + Arcane.events. [Deep protocol details](protocols.md).
|
|
@@ -3784,9 +3812,56 @@ Loads, applies, previews, saves, resets, and synchronizes semantic Arcane themes
|
|
|
3784
3812
|
|
|
3785
3813
|
### Public surface
|
|
3786
3814
|
|
|
3787
|
-
default `ThemeManager`, `loadAndApplyTheme()
|
|
3788
|
-
|
|
3789
|
-
|
|
3815
|
+
default `ThemeManager`, `loadAndApplyTheme()`, `applyUserSkin()`;
|
|
3816
|
+
scheme/custom/system APIs and `arcane-theme-change`.
|
|
3817
|
+
|
|
3818
|
+
Exact exports: `default`, `loadAndApplyTheme`, `applyUserSkin`.
|
|
3819
|
+
|
|
3820
|
+
`applyUserSkin(skin,{root?,body?,cache=true}={})` synchronously applies the
|
|
3821
|
+
application's saved skin classes without replacing unrelated body classes.
|
|
3822
|
+
The default root is the current document element; the default body belongs to
|
|
3823
|
+
that root's document. It accepts the
|
|
3824
|
+
existing string/number skin values and whitespace-separated class lists;
|
|
3825
|
+
unknown application classes remain usable. It selects the shared named
|
|
3826
|
+
palette on the root through `data-user-skin`, returning its name or `null`
|
|
3827
|
+
when there is no applicable skin/root. The palette selection does not rewrite
|
|
3828
|
+
the supplied skin or save a User record. Set `cache:false` for a presentation
|
|
3829
|
+
that should not be remembered across navigation.
|
|
3830
|
+
This export delegates to the same owner installed by `ThemePresentation.js`.
|
|
3831
|
+
Falsy skin values retain the current presentation. Complete supplied strings
|
|
3832
|
+
remain exact in the presentation cache; numbers use their complete class-text
|
|
3833
|
+
representation, leaving the profile value unchanged. If the body does not yet
|
|
3834
|
+
exist, root selection happens immediately and the latest complete class list
|
|
3835
|
+
is applied once the body is available.
|
|
3836
|
+
|
|
3837
|
+
The shared `theme.css` owns the default, warm, curious, hopeful, harmony, and
|
|
3838
|
+
warrior palettes. Each works with explicit light/dark or system appearance.
|
|
3839
|
+
`layout.css` imports that same owner. Explicit custom themes retain precedence
|
|
3840
|
+
through `data-arcane-skin="custom"` and their inline tokens.
|
|
3841
|
+
The bare root retains the generic neutral light/dark baseline; the prior
|
|
3842
|
+
layout default palette is selected explicitly through `data-user-skin="default"`,
|
|
3843
|
+
`body.default` compatibility, or the default swatch.
|
|
3844
|
+
|
|
3845
|
+
A scoped `data-arcane-palette="warm"` element exposes the same palette variables
|
|
3846
|
+
for a chooser preview without changing the page's selection. Use any of the
|
|
3847
|
+
six named palettes and paint the preview with ordinary shared variables such
|
|
3848
|
+
as `--background`, `--text-color`, and `--primary-color`; applications need no
|
|
3849
|
+
copied palette values. The scoped preview follows the page's appearance scheme.
|
|
3850
|
+
Set `data-color-scheme="light"` or `data-color-scheme="dark"` on that same
|
|
3851
|
+
`data-arcane-palette` element to preview either variant independently of the
|
|
3852
|
+
page scheme. Leaving it unset follows the page. Applications own preview order,
|
|
3853
|
+
layout, and any toggle; the scoped attribute leaves the page mode unchanged.
|
|
3854
|
+
|
|
3855
|
+
`loadAndApplyTheme()` restores the last app-scoped presentation before its
|
|
3856
|
+
asynchronous preference loads. The complete saved skin and applied
|
|
3857
|
+
appearance/custom presentation are cached by `ThemePresentation` only as
|
|
3858
|
+
nonauthoritative UI state;
|
|
3859
|
+
User and preference stores retain ownership of saved settings. No page hiding,
|
|
3860
|
+
profile-read barrier, polling, or history migration is involved.
|
|
3861
|
+
`apply()` remembers only its applied appearance attributes and the custom CSS
|
|
3862
|
+
properties owned by Theme's existing token list. `preview()` remains transient.
|
|
3863
|
+
The module's side-effect import also installs the presentation owner when no
|
|
3864
|
+
classic head script was selected; it does not provide a first-paint guarantee.
|
|
3790
3865
|
|
|
3791
3866
|
### Availability and normalization
|
|
3792
3867
|
|
|
@@ -3795,9 +3870,75 @@ Exact exports: `default`, `loadAndApplyTheme`.
|
|
|
3795
3870
|
### Example
|
|
3796
3871
|
|
|
3797
3872
|
```javascript
|
|
3798
|
-
import
|
|
3873
|
+
import {applyUserSkin} from '/arcane/modules/ThemeManager.js';
|
|
3799
3874
|
|
|
3800
|
-
|
|
3875
|
+
applyUserSkin('warm dragon-observatory');
|
|
3876
|
+
```
|
|
3877
|
+
|
|
3878
|
+
## ThemePresentation.js
|
|
3879
|
+
|
|
3880
|
+
### Overview
|
|
3881
|
+
|
|
3882
|
+
A dependency-free classic head entry restores the last application-scoped
|
|
3883
|
+
presentation synchronously, before following stylesheets are loaded. It
|
|
3884
|
+
does not import modules, User, OPFS, or a model, hide the page, or wait for
|
|
3885
|
+
profile or preference readiness. ThemeManager reuses the same per-realm owner.
|
|
3886
|
+
|
|
3887
|
+
### Public surface
|
|
3888
|
+
|
|
3889
|
+
No ESM exports. The first evaluation installs
|
|
3890
|
+
`globalThis.arcaneThemePresentation` and calls `restore()`; later evaluations
|
|
3891
|
+
reuse the installed object.
|
|
3892
|
+
|
|
3893
|
+
- `applyUserSkin(skin,{root?,body?,cache=true}={})` is the same synchronous skin
|
|
3894
|
+
operation exported through ThemeManager. It preserves independently owned
|
|
3895
|
+
body classes, selects `data-user-skin`, and returns the selected palette name
|
|
3896
|
+
or `null` for a falsy skin or missing root. Numeric presentation is cached as
|
|
3897
|
+
its complete class text; supplied strings remain exact.
|
|
3898
|
+
- `remember(fields,root=document.documentElement)` merges the supplied
|
|
3899
|
+
presentation fields with the current cache and returns whether the write
|
|
3900
|
+
succeeded. The SDK supplies `skin`, `palette`,
|
|
3901
|
+
`appearance:{colorScheme,density,reduceMotion,fontSize}`, and
|
|
3902
|
+
`customProperties` (the applied Theme-owned CSS property map, or `null`).
|
|
3903
|
+
- `restore(root=document.documentElement)` applies cached root appearance and
|
|
3904
|
+
owned custom properties plus the complete skin classes. It returns the
|
|
3905
|
+
cached record, an empty record on a cache miss, or `null` when restoration
|
|
3906
|
+
is unavailable or fails. If the body is still absent, one DOMContentLoaded
|
|
3907
|
+
callback applies the latest class list; root colors are already selected.
|
|
3908
|
+
- `reportError(message,error)` initially forwards the complete Error to
|
|
3909
|
+
`console.warn`; ThemeManager connects it to `arcaneLogging.warn` when its
|
|
3910
|
+
module evaluates.
|
|
3911
|
+
|
|
3912
|
+
The cache key is `arcane.apps.<application-id>:arcane.theme.presentation`, using
|
|
3913
|
+
the existing `arcane-app-id` meta declaration or `data-arcane-app-id` on the
|
|
3914
|
+
document root. Missing identity or storage skips caching. Conflicting identity,
|
|
3915
|
+
storage failures, and malformed JSON are logged without stopping rendering.
|
|
3916
|
+
Malformed JSON does not prevent a later authoritative presentation write.
|
|
3917
|
+
Only presentation is remembered; no User record, unrelated inline style,
|
|
3918
|
+
profile snapshot, model state, or history is captured or migrated.
|
|
3919
|
+
|
|
3920
|
+
Canonical already-ready User state and later `user-entity-loaded` events
|
|
3921
|
+
reconcile the cached skin through ThemeBootstrap; loaded appearance/custom
|
|
3922
|
+
preferences remain authoritative through ThemeManager. A cache miss cannot
|
|
3923
|
+
know an unloaded saved profile skin, and a module-only import may evaluate
|
|
3924
|
+
after first paint.
|
|
3925
|
+
|
|
3926
|
+
### Availability and normalization
|
|
3927
|
+
|
|
3928
|
+
**Browser / native WebView classic script.** DOM and optional application-scoped
|
|
3929
|
+
localStorage only. No native capability is required.
|
|
3930
|
+
|
|
3931
|
+
### Example
|
|
3932
|
+
|
|
3933
|
+
Place the ordinary classic script after the existing app-id declaration and
|
|
3934
|
+
before theme/layout styles. Do not use `type="module"`, `async`, or `defer` on
|
|
3935
|
+
this early entry; retain the application's normal ThemeBootstrap module use.
|
|
3936
|
+
|
|
3937
|
+
```html
|
|
3938
|
+
<meta name="arcane-app-id" content="dragon-observatory">
|
|
3939
|
+
<script src="/arcane/modules/ThemePresentation.js"></script>
|
|
3940
|
+
<link rel="stylesheet" href="/arcane/css/theme.css">
|
|
3941
|
+
<script type="module" src="/arcane/modules/ThemeBootstrap.js"></script>
|
|
3801
3942
|
```
|
|
3802
3943
|
|
|
3803
3944
|
## TimeGuard.js
|
|
@@ -6407,8 +6407,8 @@ console.log(deviceClass); // mobile or desktop
|
|
|
6407
6407
|
|
|
6408
6408
|
### Overview
|
|
6409
6409
|
|
|
6410
|
-
The event name `arcane.pwa.state` identifies PWA registration
|
|
6411
|
-
lifecycle
|
|
6410
|
+
The event name `arcane.pwa.state` identifies PWA registration, native worker
|
|
6411
|
+
lifecycle and page-local update availability published through the existing Arcane event owner.
|
|
6412
6412
|
|
|
6413
6413
|
### Example
|
|
6414
6414
|
|
|
@@ -6434,7 +6434,15 @@ It stores one `lastChecked` timestamp per app/cache in DBOPFS, advancing it only
|
|
|
6434
6434
|
after the full resource check succeeds, and revalidates on page load after
|
|
6435
6435
|
120 seconds in development or 15 minutes in packaged delivery. Complete
|
|
6436
6436
|
responses remain cached without SDK expiration; `304` retains the response
|
|
6437
|
-
and a successful replacement updates it.
|
|
6437
|
+
and a successful replacement updates it. A complete successful refresh latches
|
|
6438
|
+
`state.updateAvailable` when parseable old/new `Last-Modified` dates differ or
|
|
6439
|
+
a successfully checked resource was absent from the prior durable inventory.
|
|
6440
|
+
Initial population, eviction repair, `304`, and unknown/equal modification
|
|
6441
|
+
dates do not announce updates. Partial-change evidence survives worker restart
|
|
6442
|
+
until complete success; existing scoped window clients receive the completed
|
|
6443
|
+
signal. The state replays to subscribers and remains true for this page owner.
|
|
6444
|
+
The registration owner's `update()` only requests a native worker update check;
|
|
6445
|
+
it does not reload the page. See the [PWA guide](pwa.md).
|
|
6438
6446
|
|
|
6439
6447
|
### Example
|
|
6440
6448
|
|
|
@@ -6456,7 +6464,7 @@ entry point and must observe its `ready` rejection.
|
|
|
6456
6464
|
### Overview
|
|
6457
6465
|
|
|
6458
6466
|
The exact event name `arcane.pwa.install.state` identifies native installation
|
|
6459
|
-
availability and
|
|
6467
|
+
availability, choice and shared update-prompt state through the existing Arcane event owner. It is
|
|
6460
6468
|
separate from service-worker registration state. Importing it starts no
|
|
6461
6469
|
observation or installation.
|
|
6462
6470
|
|
|
@@ -6475,16 +6483,17 @@ payload and current-state subscription behavior.
|
|
|
6475
6483
|
### Overview
|
|
6476
6484
|
|
|
6477
6485
|
`getPwaInstall()` returns one synchronous page owner exposing `state`, `ready`,
|
|
6478
|
-
`subscribe`, `prompt`, `dismiss` and `dispose`. It captures the browser's
|
|
6486
|
+
`subscribe`, `prompt`, `dismiss`, `update`, `dismissUpdate` and `dispose`. It captures the browser's
|
|
6479
6487
|
`beforeinstallprompt` event and observes `appinstalled` and app display-mode
|
|
6480
6488
|
changes. A missing event leaves installation availability unknown and the owner
|
|
6481
6489
|
waiting; it does not prove browser incompatibility.
|
|
6482
6490
|
|
|
6483
|
-
State contains `status`, `available`, `installed`, `dismissed`, `
|
|
6491
|
+
State contains `status`, `available`, `installed`, `dismissed`, `updateAvailable`,
|
|
6492
|
+
`updateDismissed`, `outcome`,
|
|
6484
6493
|
`error` and `storageError`. The owner restores `pwa/installed.json` through the
|
|
6485
6494
|
app-scoped DBOPFS singleton and saves `{installed: true}` after `appinstalled`
|
|
6486
6495
|
or an installed-app launch. Remembered installation suppresses both floating
|
|
6487
|
-
and inline controls on later visits. Acceptance alone and ordinary fullscreen
|
|
6496
|
+
and inline installation controls on later visits. Acceptance alone and ordinary fullscreen
|
|
6488
6497
|
do not record installation.
|
|
6489
6498
|
|
|
6490
6499
|
`ready` resolves to the state once the initial read settles. Native events are
|
|
@@ -6498,6 +6507,18 @@ consumes the event once and returns the browser choice, resolves to `null` when
|
|
|
6498
6507
|
unavailable, or rejects with the actual error. `dismiss()` remembers the
|
|
6499
6508
|
session's floating-suggestion dismissal without consuming a retained event.
|
|
6500
6509
|
|
|
6510
|
+
The generated bootstrap starts this owner before worker registration, so it
|
|
6511
|
+
observes the current page scope's `arcane.pwa.state` update signal while the
|
|
6512
|
+
component loads. A late-created prompt also reads current state from live
|
|
6513
|
+
registration owners. `updateAvailable` remains true for the page owner;
|
|
6514
|
+
`updateDismissed` is a separate page-local choice. An explicit `update()` calls
|
|
6515
|
+
ordinary `location.reload()` synchronously and returns true, or false when
|
|
6516
|
+
unavailable/disposed; native errors propagate. It preserves native unload
|
|
6517
|
+
handling and application draft ownership without promising transient-state
|
|
6518
|
+
survival. `dismissUpdate()` returns the current state and writes no durable
|
|
6519
|
+
record. Installed/running state or installation dismissal does not suppress
|
|
6520
|
+
the update suggestion. A fresh page does not replay an old completed update.
|
|
6521
|
+
|
|
6501
6522
|
### Example
|
|
6502
6523
|
|
|
6503
6524
|
```javascript
|
|
@@ -6537,7 +6558,9 @@ supplies the initial app name.
|
|
|
6537
6558
|
The generated PWA bootstrap calls this automatically with the manifest name.
|
|
6538
6559
|
Component mounting and worker registration run independently, and application
|
|
6539
6560
|
rendering must not await them. The floating component offers Install and a
|
|
6540
|
-
manual close control
|
|
6561
|
+
manual close control, or Update available with an explicit Update action after
|
|
6562
|
+
a completed changed refresh. Update dismissal is separate from installation
|
|
6563
|
+
dismissal. An application can also place the same component inline.
|
|
6541
6564
|
|
|
6542
6565
|
### Example
|
|
6543
6566
|
|
package/package.json
CHANGED
|
@@ -1576,7 +1576,9 @@
|
|
|
1576
1576
|
:'Tool'
|
|
1577
1577
|
:message.role==='system'
|
|
1578
1578
|
?'System'
|
|
1579
|
-
:
|
|
1579
|
+
:is.string(message.name)&&message.name.trim()
|
|
1580
|
+
?message.name
|
|
1581
|
+
:'AI';
|
|
1580
1582
|
item=createTranscriptMessage(message.role,message.content,name,{
|
|
1581
1583
|
timestamp:message.timestamp,
|
|
1582
1584
|
toolCalls:calls,
|
|
@@ -3245,6 +3247,9 @@
|
|
|
3245
3247
|
const previousPendingToolCalls=[...pendingStructuralToolCalls];
|
|
3246
3248
|
const streamedStructuralToolCalls=[];
|
|
3247
3249
|
const messageId=`session-${++sessionMessageSequence}`;
|
|
3250
|
+
const responseName=is.string(session.aiName)&&session.aiName.trim()
|
|
3251
|
+
?session.aiName
|
|
3252
|
+
:host.aiName;
|
|
3248
3253
|
const sessionMessageToken=Symbol(messageId);
|
|
3249
3254
|
const transientCards=retainTurn?[]:[...requestMessages];
|
|
3250
3255
|
function removeTransientSessionCards(){
|
|
@@ -3259,7 +3264,7 @@
|
|
|
3259
3264
|
applyAIAvailability(host.aiAvailability);
|
|
3260
3265
|
setSessionStatus('sending','AI is responding…');
|
|
3261
3266
|
try{
|
|
3262
|
-
const responseCard=receivedMessage(
|
|
3267
|
+
const responseCard=receivedMessage(responseName, '', messageId);
|
|
3263
3268
|
if(!retainTurn) transientCards.push(responseCard);
|
|
3264
3269
|
await streamMessage('',messageId,true);
|
|
3265
3270
|
setMessageProgress(
|
|
@@ -3344,6 +3349,10 @@
|
|
|
3344
3349
|
result.message.content,
|
|
3345
3350
|
committedTurn?.response?.timestamp??result.message.timestamp
|
|
3346
3351
|
);
|
|
3352
|
+
const assistantName=committedTurn?.response?.name??result.message.name;
|
|
3353
|
+
if(is.string(assistantName)&&assistantName.trim()){
|
|
3354
|
+
message.querySelector('.message_header strong').textContent=assistantName;
|
|
3355
|
+
}
|
|
3347
3356
|
for(const [index,requestMessage] of requestMessages.entries()){
|
|
3348
3357
|
setTranscriptMessageTimestamp(
|
|
3349
3358
|
requestMessage,
|
|
@@ -387,6 +387,21 @@
|
|
|
387
387
|
background:var(--background);
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
+
.file-preview-message[data-role="user"]{
|
|
391
|
+
background:var(--arcane-action,var(--primary-color));
|
|
392
|
+
color:var(--arcane-action-text,var(--button-text-color,var(--text-color)));
|
|
393
|
+
border-color:var(--arcane-action,var(--primary-color));
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.file-preview-message[data-role="user"] a{
|
|
397
|
+
color:inherit;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.file-preview-message[data-role="assistant"]{
|
|
401
|
+
background:var(--arcane-surface,var(--background));
|
|
402
|
+
color:var(--text-color);
|
|
403
|
+
}
|
|
404
|
+
|
|
390
405
|
.file-preview-message header,
|
|
391
406
|
.file-preview-message footer{
|
|
392
407
|
display:flex;
|
|
@@ -1740,9 +1755,15 @@
|
|
|
1740
1755
|
const time=document.createElement('time');
|
|
1741
1756
|
article.className='file-preview-message';
|
|
1742
1757
|
article.dataset.role=message.role;
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1758
|
+
if(message.role==='assistant'){
|
|
1759
|
+
speaker.textContent=is.string(message.name)&&message.name.trim()
|
|
1760
|
+
?message.name
|
|
1761
|
+
:'AI';
|
|
1762
|
+
}else{
|
|
1763
|
+
speaker.textContent=message.name===undefined
|
|
1764
|
+
?message.role
|
|
1765
|
+
:`${message.name} · ${message.role}`;
|
|
1766
|
+
}
|
|
1746
1767
|
header.append(speaker);
|
|
1747
1768
|
if(message.timestamp===undefined||message.timestamp===null){
|
|
1748
1769
|
time.textContent='Time unavailable';
|
|
@@ -78,12 +78,14 @@
|
|
|
78
78
|
</header>
|
|
79
79
|
|
|
80
80
|
<script type="module">
|
|
81
|
-
const {arcaneLogging}=await
|
|
81
|
+
const [{arcaneLogging},{applyUserSkin}]=await Promise.all([
|
|
82
|
+
import('arcane-os/logging'),
|
|
83
|
+
import('../modules/ThemeManager.js')
|
|
84
|
+
]);
|
|
82
85
|
|
|
83
86
|
import('../entities/User.js');
|
|
84
87
|
|
|
85
88
|
const host=this;
|
|
86
|
-
const appliedSkinClasses=new Set();
|
|
87
89
|
|
|
88
90
|
window.addEventListener('user-entity-loaded', setSkin);
|
|
89
91
|
window.addEventListener('online', checkInternet);
|
|
@@ -124,22 +126,7 @@
|
|
|
124
126
|
try {
|
|
125
127
|
const skin = window.user?.skin;
|
|
126
128
|
if (skin) {
|
|
127
|
-
|
|
128
|
-
const classes=document.body.classList;
|
|
129
|
-
// Only replace classes added by this header; application layout
|
|
130
|
-
// and independently owned theme classes stay with their owners.
|
|
131
|
-
for(const name of appliedSkinClasses){
|
|
132
|
-
if(!nextClasses.has(name)){
|
|
133
|
-
classes.remove(name);
|
|
134
|
-
appliedSkinClasses.delete(name);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
for(const name of nextClasses){
|
|
138
|
-
if(!classes.contains(name)){
|
|
139
|
-
classes.add(name);
|
|
140
|
-
appliedSkinClasses.add(name);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
129
|
+
applyUserSkin(skin);
|
|
143
130
|
} else {
|
|
144
131
|
arcaneLogging.log('No saved skin found. Using default.');
|
|
145
132
|
}
|