On this page
Arcane components are reusable HTML fragments loaded through the shared <html-import> element. They are browser UI, so they run in an ordinary supported browser renderer and in native Arcane WebViews. They do not run in Node or as cloud services.
A component file does not register its own custom element. The <html-import> host fetches the fragment from the same origin, attaches an open shadow root, runs its inline scripts with this bound to the host, and publishes html-import-ready or html-import-error. Component methods and properties are attached to that host.
Import the loader through arcane-os/modules/HTMLImport.js and the SDK-managed
import map. Component href values are asset URLs, so use the application's
configured runtime route. The default root npm layout serves components from
/node_modules/arcane-os/runtime/arcane/components/. Other /arcane/...
examples on this page describe an explicitly configured physical or virtual
route; direct npm applications use their corresponding installed-package URLs.
Basic loading pattern
<script type="module">
import 'arcane-os/modules/HTMLImport.js';
</script>
<html-import id="widget" href="/node_modules/arcane-os/runtime/arcane/components/weather-widget.html"></html-import>
<script type="module">
const widget = document.querySelector('#widget');
widget.addEventListener('html-import-ready', () => {
console.log('Component methods are attached.', typeof widget.setWeather);
}, {once: true});
</script>
Shared semantic-event and lifecycle contract
Except for shared header.html and platform-owned theme-switcher.html,
each component owns exactly one source created through
createArcaneEventSource(host,{source:'arcane.component.<name>',eventTypes}).
That source publishes synchronously to the realm's branded
globalThis.arcaneEvents authority. Component DOM events are one-way
projections of the same canonical occurrence; they are never
republished into the authority. Every projected detail has the canonical
occurrenceId, arcaneSource, instanceId, and operationId fields in a
mutable complete record. A source payload's existing source field remains
source-local and may differ from arcaneSource; the payload may additionally
retain source-local browser or provider objects.
When a component uses a cancelable event before a requested operation, cancellation on
either the canonical occurrence or its DOM projection makes the publication
unaccepted, and the component does not continue the guarded operation. A
cancelable projected notification emitted after committed work does not
roll that work back unless its component section explicitly says otherwise.
Asynchronous work keeps its own AbortSignal, operation generation, and
promise ownership; canonical publication is synchronous and does not become an
async queue.
Every singleton-backed component publishes its ready event only after its host
members are installed. Its idempotent destroy() (unless a more specific
return is documented) disposes the canonical source and marks the host
unready. Cleanup of owned listeners, pending work, nested subscriptions, and
controllers is component-specific and is stated below where it forms part of
that component's public contract. Removing an <html-import> host calls an
imported component's destroy() through HTMLImport; callers that invoke
destroy() directly retain responsibility for removing the element when
appropriate.
Shared print presentation
The shared theme.css and document-site.css import print.css, the single
print-style owner. It provides a light paper palette and 1in (25.4mm) page
margins. During print, root/body/scoped palette tokens override screen colors;
the shared header/sidebar shell is hidden and its main scroller expands into
document flow. Screen layout, preferences, fonts, and media remain unchanged.
PrintView.js loads the same stylesheet for
rendered snapshots of Chat, the editor, and file previews. Its temporary
snapshot remains owned until the browser's afterprint event.
Canonical inventory
| Component | Capability | Principal methods | Events | Normalization |
|---|---|---|---|---|
app-bar.html |
Responsive application navigation, route state, status, and trailing actions. | setNavigation()setActiveRoute()setStatus()refresh()destroy() |
app-bar-ready |
DOM-normalized |
assistant-panel.html |
Reusable assistant drawer, message area, composer, pending/streaming/empty/error state, and actions. | open()close()toggle()send()clear()setState()focusComposer()scrollToEnd()destroy() |
assistant-readyassistant-openedassistant-closedassistant-sendassistant-clear |
DOM-normalized; caller/provider results remain external |
browser-ai-setup.html |
Browser API availability, reported GPU class, and copyable NPU/GPU settings addresses. | refresh()checkGpu()open()destroy()ready |
browser-ai-setup-ready |
Browser-reported adapter class; browser flag state and model execution remain browser-owned |
calculator.html |
Calculator keypad and result/error event surface backed by CalculatorEngine. | calculate()destroy() |
calculator-readycalculation-completecalculation-error |
Normalized Calculation/error events |
chart.html |
Accessible uPlot line, area, or point chart with normalized options and rows. | configure()populate()setData()addData()update()destroy() |
chart-readychart-remove |
Options/rows normalized; uPlot rendering is vendor-native |
chat.html |
Shared chat, visible selected-model activation request, file upload, streaming, structural tool settlement, speech, language, availability, and conversation-timebox surface. | streamMessage()setMessageProgress()setAIAvailability()setInitialSpeechMuted()setConversationComplete()bindConversationTimebox()bindSession()submitMessage()submitToolResult()submitToolResults()sendMessage()appendDraft()print()languageChanged()requestAIActivation()destroy() |
chat-readychat-session-boundchat-session-messagechat-session-errorchat-send-messagechat-send-errorchat-file-uploadedchat-file-upload-errorchat-language-changedchat-language-change-errorchat-ai-activation-requestchat-ai-activation-errorchat-speech-synthesis-errorconversation-timebox-error |
UI/runtime state, explicit user activation intent, and honest structural-call settlement normalized; AI/storage/media behavior mixed |
conversation-view.html |
Provider-neutral conversation display, advisory actions, composer, busy state, and status. | setConversation()setBusy()setStatus()clearComposer()destroy() |
conversation-view-readycommunication-sendcommunication-advisory-action |
DOM-normalized |
dashboard-config.html |
Selects which normalized chart definitions are visible on a dashboard. | configure()setDefinitions()setVisibility()getChartOptions()getEffectiveVisibility()open()close()destroy() |
dashboard-config-readydashboard-config-openeddashboard-config-closeddashboard-config-change |
Fully normalized definitions and visibility |
data-maintenance.html |
Runs destructive cleanup of empty chats and memories inside the current app data scope. | open()destroy() |
data-maintenance-readydata-maintenance-complete |
Normalized counts; DBOPFS failures mixed |
data-view.html |
Opens a modal file view and forwards application-owned preview and directory-filter callbacks. | beforeOpen()open()close()printPreview()destroy() |
data-view-ready |
DOM-native result; preview/filter configuration reaches the child before loading |
directory-picker.html |
Presents the provider-owned OS directory chooser with change/cancel/error states. | configure()focus()select()destroy() |
directory-picker-readydirectory-picker-changedirectory-picker-canceldirectory-picker-error |
Complete plain-text paths and native selection/error |
document-inspector.html |
Inspects PDF, text, or source documents and records review state. | loadDocument()selectView()markSaved()destroy() |
document-inspector-readydocument-review-change |
Document state normalized; browser document APIs mixed |
file-drop.html |
Acquires complete file selections by drag/drop or picker and presents busy, progress, error, and cleared state. | configure()openPicker()clear()setBusy()setError()setProgress()destroy() |
file-drop-readyfile-drop-selectedfile-drop-progressfile-drop-statefile-drop-error |
Complete selections preserved; browser File/drop errors mixed |
file-inspector.html |
Displays file metadata, preview, busy/error state, and caller-defined actions. | configure()show()clear()setActions()setBusy()setError()setPreview()destroy() |
file-inspector-readyfile-inspector-actionfile-inspector-changefile-inspector-clearedfile-inspector-error |
State normalized; preview/provider behavior mixed |
file-manager.html |
Browses app-scoped files, filters directories before reads, and renders application-described previews. | setProvider()loadAll()setFilter()setDirectoryFilter()select()clearSelection()close()printPreview()destroy() |
file-manager-readyfile-manager-selectfile-manager-openfile-manager-action |
Selection/filter state, neutral preview descriptors, cancellation, and media cleanup normalized; storage/provider behavior mixed |
header.html |
Shared title bar with history, reload, online marker, presentation labels, and 988 link. | None | No component-specific event | Browser/platform-native behavior; no component-ready contract |
integration-settings.html |
Edits non-secret communication service configuration and service actions. | configure()getValues()setStatus()destroy() |
integration-settings-readyintegration-settings-saveintegration-settings-closeintegration-action |
Normalized non-secret values |
local-ai-status.html |
Presents local-AI standby, failure, recovery, guidance, retry, and dismissal states. | configure()begin()present()destroy()hidden |
local-ai-status-readylocal-ai-status-dismissedlocal-ai-retry |
Fully normalized LocalAIReadiness report |
markdown-document.html |
Renders and navigates a complete Markdown document with focusable fragments. | configure()load()render()clear()fail()focus()focusFragment()destroy() |
markdown-document-readymarkdown-document-statemarkdown-document-loadingmarkdown-document-renderedmarkdown-document-emptymarkdown-document-errormarkdown-document-navigate |
Complete Markdown/state normalized; malformed input and Marked/DOM failures remain visible |
markdown-editor.html |
Configurable Markdown authoring with optional bounded input/preview panes, edit-position following, and rendered printing. | configure()focus()clear()insertMarkdown()saveEntry()print()destroy() |
markdown-editor-readymarkdown-editor-changemarkdown-editor-saved |
Editor values, opt-in fit layout, and preview following normalized; injected save result mixed |
media-embed.html |
Loads a parsed YouTube video or playlist embed with ordinary hosting by default, optional privacy enhancement, and an external-platform action. | configure()load()destroy() |
media-embed-readymedia-loadmedia-errormedia-open-platform |
URL/error normalized; iframe/platform behavior native |
modal.html |
Generic modal with population, configurable user dismissal, actions, and concurrent task execution. | configure()populate()open()close()runTasks()destroy()runningopened |
modal-readymodal-openedmodal-closedmodal-action |
Modal state normalized; injected task results mixed |
output-panel.html |
Presents status, output, body, coverage, actions, pending, error, and cleared states. | configure()setOutput()setBody()setCoverage()setActions()setPending()setStatus()setError()clear()destroy() |
output-panel-readyoutput-panel-stateoutput-panel-changeoutput-panel-actionoutput-panel-erroroutput-panel-cleared |
DOM-normalized |
preferences-form.html |
Builds a schema-driven preferences form with submit, reset, busy, and status behavior. | configure()getValues()setValues()setBusy()setStatus()destroy() |
preferences-form-readypreferences-changepreferences-submitpreferences-reset |
Normalized form values |
pwa-install.html |
Presents independent installation and explicit update/reload actions with floating or inline placement. | configure()install()dismiss()update()dismissUpdate()destroy()stateready |
pwa-install-readypwa-install-changepwa-install-dismissed |
Complete labels and independent installation/update state; native unload cancellation leaves Update available |
record-timeline.html |
Displays complete chronological records/evidence and emits open actions. | setItems()populate()destroy() |
record-timeline-readyrecord-timeline-open |
Complete item fields and inventories preserved |
relationship-board.html |
Displays complete normalized relationship nodes/edges in graph and list forms. | setGraph()populate()destroy() |
relationship-board-readyrelationship-node-openrelationship-edge-open |
Complete graph inventories and fields preserved |
screen-capture.html |
Presents image, video, or GIF display-capture workflow. | capture (ScreenCapture instance)destroy() |
screen-capture-readyscreen-capture-result |
State/result normalized; media permission/codec failures mixed |
source-code-viewer.html |
Renders complete line-addressable source code with load, error, focus, and state behavior. | configure()load()render()clear()fail()focus()focusLine()destroy() |
source-code-viewer-readysource-code-viewer-statesource-code-viewer-state-loadingsource-code-viewer-state-readysource-code-viewer-state-emptysource-code-viewer-state-error |
Complete mutable source/state |
source-explanation.html |
Presents an evidence finding, source selection, explanation, and save state. | showFinding()populate()selectSource()markSaved()destroy() |
source-explanation-readysource-explanation-savesource-explanation-source-selected |
DOM-normalized |
speech.html |
Coordinates explicit STT activation, speech controls, transcription completion, mute state, and microphone availability. | configure()setMuted()reportTTSError()requestSTTActivation()destroy()availabilitymutedinitialMutedrecognitionLanguagedisplayTranscriptioncomponentReady |
speech-readyspeech-transcription-progressspeech-transcription-completespeech-transcription-errorspeech-transcription-cancelledspeech-microphone-unavailablespeech-stt-activation-requestspeech-stt-activation-errorspeech-tts-lifecycle-errorspeech-synthesis-error |
Sticky runtime speech readiness, explicit STT activation, request cancellation, TTS mute lifecycle intent, and exact TTS operation failures normalized; provider/model authority remains external |
summary-strip.html |
Displays compact selectable KPI or summary items. | configure()setItems()updateItem()clear()destroy() |
summary-strip-readysummary-strip-changesummary-strip-select |
DOM-normalized |
table.html |
Builds and updates a simple header/body table. | buildHeader()buildTable()destroy() |
table-readyheader-updatebody-update |
DOM-normalized |
task-progress.html |
Runs and displays a task list with started/change/complete/error state. | configure()setTasks()updateTask()runTasks()clear()destroy() |
task-progress-readytask-progress-startedtask-progress-changetask-progress-completetask-progress-error |
Task state normalized; injected task results mixed |
terminal-workspace.html |
Presents multiple terminal sessions, output, active selection, theme, and terminal actions. | configure()addSession()removeSession()activateSession()append()clear()setState()setTheme()focus()destroy() |
terminal-workspace-readyterminal-submitterminal-interruptterminal-clearterminal-session-newterminal-session-closeterminal-session-selectterminal-settings |
UI/session state normalized; native command results supplied externally |
theme-editor.html |
Edits, previews, saves, and resets semantic custom theme tokens. | configure()getTheme()setTheme()setBusy()setStatus()destroy() |
theme-editor-readytheme-previewtheme-savetheme-reset |
Fully normalized Theme values |
theme-switcher.html |
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()setMode()refresh() |
No component-specific event | Preference/native appearance behavior mixed; no component-ready contract |
unified-inbox.html |
Displays provider-neutral communication threads with active/loading state. | configure()setThreads()setActive()setLoading()destroy() |
unified-inbox-readyinbox-refreshthread-select |
DOM-normalized |
voice-transcription.html |
Records manual clips or optional continuous microphone audio with pause/periodic segments, ordered transcription and saves, retained failures, and complete transcript delivery. | configure()requestSTTActivation()startRecording()stopRecording()retryTranscription()cancelRecording()save()completeTranscription()/complete()clear()reset()destroy() |
voice-transcription-readyvoice-transcription-statevoice-transcription-segmentvoice-transcription-emptyvoice-transcription-errorvoice-transcription-changevoice-transcription-completespeech-transcription-completespeech-transcription-cancelledspeech-stt-activation-requestspeech-stt-activation-error |
Sticky STT readiness, capture/queue lifecycle, retry, cancellation, and complete state/text are normalized; media/provider behavior remains external |
weather-widget.html |
Displays normalized current and daily weather with refresh intent. | setWeather()clear()destroy() |
weather-widget-readyweather-refresh |
Display normalized; provider supplied externally |
web-navigator.html |
Guards embedded/external navigation and surfaces allow/block/open intents. | configure()navigate()currentUrl()destroy() |
web-navigator-readyweb-navigateweb-navigation-blockedweb-open-external |
Navigation intent/decision normalized; browser navigation result platform-native |
app-bar.html
Overview
Responsive application navigation, route state, status, and trailing actions.
Public surface
Methods/properties: setNavigation(), setActiveRoute(), setStatus(), refresh(), destroy().
Events: app-bar-ready.
Slots: brand-mark, product-name, navigation, status, trailing.
Availability and normalization
Browser and supported native WebViews. DOM-normalized. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="app-bar.html"
href="/arcane/components/app-bar.html">
</html-import>
assistant-panel.html
Overview
Reusable assistant drawer, message area, composer, pending/streaming/empty/error state, and actions.
Public surface
Methods/properties: open(), close(), toggle(), send(), clear(), setState(), focusComposer(), scrollToEnd(), destroy().
Events: assistant-ready, assistant-opened, assistant-closed,
assistant-send, assistant-clear.
Slots: title, subtitle, identity, messages/message, composer, actions, pending, streaming, empty, error, footer.
Availability and normalization
Browser and supported native WebViews. DOM-normalized; caller/provider results remain external. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="assistant-panel.html"
href="/arcane/components/assistant-panel.html">
</html-import>
browser-ai-setup.html
Overview
Displays a short WebNN availability status and the detected WebGPU adapter.
Chrome and Edge receive a Copy NPU flag address button for their own browser;
unidentified browsers show both choices. Desktop Windows Chromium browsers
receive a Copy GPU flag address button for the matching browser,
including chrome://flags/#force-high-performance-gpu for identified Chrome.
Both controls remain available regardless of API availability, adapter class,
or detection failure. Each flag has one short explanation, followed by a shared
instruction: paste the address, enable the flag, save work, then close the
browser and reopen it. The closing and reopening instruction is underlined and emphasized.
Settings addresses use Copy controls and appear as selectable text if copying
fails. The component does not attempt navigation to internal browser pages.
Public surface
Methods/properties: refresh(), checkGpu(), open(browserId?), destroy(), ready.
Events: browser-ai-setup-ready.
refresh() synchronously updates API presence and browser guidance and returns
the current settings record: browserId, name, webnnFlagsURL,
highPerformanceGpu, webnnAvailable, and webgpuAvailable. It returns false
after destruction. Availability means that the browser exposes the API to this
page; it does not confirm a working adapter, loaded model, or hardware execution.
checkGpu() returns a promise for one adapter-availability record. Concurrent
calls share the pending promise. The component requests an adapter with the
"high-performance" power-preference hint; it does not create a GPU device or
load a model. An unavailable result contains available: false and a reason
of "api-unavailable" or "adapter-unavailable". An available result contains
available: true, the reported adapter name, isFallbackAdapter as a boolean
or null, adapterType as the browser's string or null, and
performanceStatus: "discrete", "integrated", "fallback", or "unknown".
Only the explicit browser type or fallback field establishes that status;
vendor names and the requested power preference do not. A discrete result
shows Already using the performance GPU. An unknown class shows GPU available.
and leaves performance selection unconfirmed. Adapter selection does not
prove that a browser flag is enabled, that the fastest GPU was selected, or that
a model is using it. Failure is displayed and logged, and the promise
resolves to false; destruction also yields false and suppresses late UI
updates.
Mounting starts one checkGpu() operation. Refresh calls both refresh()
and checkGpu(). Calling
refresh() directly remains synchronous and does not request an adapter.
ready and browser-ai-setup-ready describe component setup, which can complete
while adapter detection is still pending.
The retained open(browserId?) method now copies the matching NPU flags address
instead of navigating or showing an alert. Pass "chrome" or "edge" to choose
explicitly and invoke it from a user action. It returns a promise resolving to
true only after clipboard success, or false for destruction, an unsupported
target, or copy failure. The complete address remains selectable if clipboard
access fails. On-screen instructions explain pasting it into the address bar,
enabling WebNN, saving work, then closing the browser and reopening it.
destroy() aborts owned listeners, disposes the event source, marks ready
false, and suppresses UI updates from pending clipboard and adapter operations.
It does not cancel the browser-owned adapter request. It returns true the
first time and false thereafter. A BFCache-persisted pagehide preserves the
component; nonpersisted pagehide destroys it.
Availability and normalization
Browser and supported native WebViews. API presence, adapter availability, and setup instructions are normalized; browser flag state, clipboard support, and model execution remain platform-owned. Mounting requests one WebGPU adapter when that API is available. No GPU device, model, or WebNN context is created. The component saves no preferences, changes no browser settings, and does not restart the browser. It cannot report model state owned by another page.
Example
<html-import
id="browser-ai-setup"
href="/arcane/components/browser-ai-setup.html">
</html-import>
calculator.html
Overview
Calculator keypad and result/error event surface backed by CalculatorEngine.
Public surface
Methods/properties: calculate(), destroy().
Events: calculator-ready, calculation-complete, calculation-error.
Shared dependencies: CalculatorEngine.js.
Availability and normalization
Browser and supported native WebViews. Normalized Calculation/error events. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="calculator.html"
href="/arcane/components/calculator.html">
</html-import>
chart.html
Overview
Accessible uPlot line, area, or point chart with normalized options and rows.
Public surface
Methods/properties: configure(), populate(), setData(), addData(), update(), destroy().
Events: chart-ready, chart-remove.
Shared dependencies: ChartLibrary.js, ComponentContracts.js.
Availability and normalization
Browser and supported native WebViews. Options/rows normalized; uPlot rendering is vendor-native. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="chart.html"
href="/arcane/components/chart.html">
</html-import>
chat.html
Overview
Shared chat, visible selected-model activation request, file upload, streaming, speech, language, availability, and conversation-timebox surface.
Public surface
Methods/properties: streamMessage(), setMessageProgress(),
setAIAvailability(), setInitialSpeechMuted(),
setConversationComplete(), bindConversationTimebox(), bindSession(),
submitMessage(), submitToolResult(), submitToolResults(), sendMessage(),
languageChanged(), requestAIActivation(), session, sessionStatus,
pendingTool, pendingTools, pendingToolCall, pendingToolCalls, modelName,
transcriptionMode, recognitionLanguage, appendDraft(), print(),
printTitle, and destroy().
sendMessage(text) and languageChanged(text) are host-overridable async
extension callbacks. The component installs warning-only defaults when the host
does not supply them; applications may instead consume the corresponding
chat-send-message and chat-language-changed events.
The composer uses the shared browser-device classification: Enter inserts a newline on mobile devices and tablets; desktop Enter submits before the native newline is inserted. Shift+Enter and input-method composition retain native editing. The visible Send button remains available on every device. Input changes resize the composer without submitting; held desktop Enter does not submit repeatedly. All input listeners follow the component's existing cleanup.
transcriptionMode defaults to 'submit', preserving completed-transcription
submission. Set it to 'draft' for editable voice input with manual Send.
Native final words and interim hypotheses appear immediately in the existing
composer; later hypotheses replace only the recognition-owned interim range.
Typing elsewhere is preserved, and editing that range makes its text user-owned.
Completion does not append the same final text twice. Cancellation removes only
an unedited interim hypothesis; final words and user edits remain in the draft.
The shared Speech status stops repeating transcript text in draft mode.
appendDraft(text) appends complete text without submitting, preserves existing
draft text and selection, and emits the normal input event. It adds a newline
between entries only when neither boundary already has whitespace. It returns
false for empty input or a destroyed component.
recognitionLanguage forwards the Speech component's native BCP47 language
selection. If omitted, Speech uses the browser language. It is independent of
the existing conversation-language label and is latched when capture starts.
await print() delegates the current rendered transcript to shared PrintView;
printTitle optionally supplies the title (default Conversation). Controls,
status, transient thinking, and tool-inspection details are outside the printed
conversation; complete human-facing tool messages remain. Print uses
a document-flow transcript layout instead of left/right screen bubbles;
timestamps keep their own alignment and table headings can repeat across pages.
Native Print uses
the same registered view while it is visible and has transcript content. The
method resolves true when the browser print dialog is requested, not when a
PDF or paper output is produced; it resolves false when unavailable or
cancelled during preparation and rejects preparation failures. Complete errors
reach developer diagnostics and a concise recovery status stays outside the
transcript. Destruction cancels pending preparation, while an already requested
print retains its snapshot through afterprint.
Markdown images with local arcane-media: references saved through
MarkdownMedia display automatically in
new messages, live response chunks, final responses, and restored history.
Chat resolves references through the existing application-scoped DBOPFS owner
while preserving the complete original Markdown, model payloads, saved history,
image descriptions, and ordinary image URLs. Text appears immediately; local
image reads and decoding proceed independently without delaying streaming or
session readiness. Failed images retain complete developer diagnostics and show
a concise message beside that card; successful sibling images remain visible.
Each rendered card owns its display URLs. Re-rendering, history replacement,
transient-message removal, and destruction cancel obsolete display work and
release those URLs without deleting stored images. Back/Forward Cache retains
the existing component lifecycle. Explicit print() awaits the current images;
native Print reports images that are still loading or failed instead of claiming
they are ready. A requested print snapshot retains its image URLs across later
message changes or component destruction until afterprint releases them.
Applications continue to own image-record names, associations, and cleanup;
Chat introduces no renderer callback or additional storage API.
Before any session binding begins, callback-mode sessionStatus follows the
selected sticky LLM role and the existing application-owned modelName label
(or the selected model ID). Assigning modelName refreshes that status even
after component initialization. It reports Ready only for a selected provider and
model whose role is both ready and loaded; loading, unloaded, error, unloading,
unavailable, and disposed states remain distinct. The initial status waits for
runtime replay. This describes model readiness, not network connectivity.
Once bindSession() begins, session binding, message, tool, and error status
remain owned by that session lifecycle; runtime updates do not replace them.
submitMessage(textOverride='',context={}) returns Promise<boolean>.
context accepts source, preserveDraft, synthetic, an optional exact
operationId, and an optional caller-owned AbortSignal. The component owns a
derived signal for each submission, supplies it in the mutable complete source
{message,context} detail, and aborts it on canonical/DOM cancellation,
component destruction, or caller cancellation. chat-send-message is
cancelable and is the gate before sendMessage(text,context); a canceled event
never reaches the host callback. Rejected host promises are observed as
chat-send-error, and stale settlement after abort or destruction is
suppressed.
bindSession({ai,session,sessionOptions}) accepts exactly one of a public AI API
module or an existing compatible session, restores the UI transcript when
available, and uses provider-safe history as its restoration fallback. The
transcript is a masked vertical scroll viewport; status and composer remain
outside it. Initial restoration follows the true bottom. User, assistant, tool,
streaming, progress, and failure updates continue following it, including later
message-card, status, composer, or viewport resizing, until the reader scrolls
toward earlier content. Scrolling down to the bottom or submitting an accepted
non-synthetic user message resumes following. Canceled or rejected submissions
and synthetic requests preserve the reader's position. Layout
clamping, hidden views, and BFCache restoration preserve that choice;
destruction releases scroll observation. Each
restored or new message uses a separate semantic <time> element at the card's
lower-right with an ISO datetime, full local title, and local 24-hour HH:MM
text.
Restored assistant cards use the record's exact nonblank string name, or
AI when absent. The current profile/model/voice name never renames older
messages. For live session replies, the card starts with session.aiName
when nonblank, otherwise the existing host.aiName display value; the terminal
result aligns it with the name captured by the session for that operation.
Set the session/entity name as well as the live component label when the
application intends new saved turns to retain that attribution. The shared
component does not persist the profile name or choose a naming policy.
Assistant structural calls render their nonempty function.arguments.message
as ordinary visible progress. The exact call name and argument string are
retained inside a collapsed Tool call details inspection surface. Displaying
a call does not settle it or enable another user turn.
submitToolResults({results,request?},{operationId?,signal?}) atomically settles
the current ordered pending-call set. results supplies exactly one
{toolCallId,status,message,persist?} record for every pending ID, without
duplicates or omissions. status is executed, declined, cancelled,
or not-executed; every result in the batch uses the same persistence choice.
The method preserves pending order, persists and renders every human-readable
status plus complete message as matching role:'tool' requests, and then
renders one assistant continuation. Live submission and restored history both
require nonblank user-facing result content; accepted text is preserved exactly
rather than trimmed or rewritten.
submitToolResult({toolCallId?,status,message,persist?,request?},{operationId?,signal?})
is the single-call method. It infers the only pending ID when omitted
and rejects when zero or multiple calls are pending; parallel calls must use
submitToolResults().
Optional plain-object request contains per-turn generation choices forwarded
through the session; a visibility-only host can use
request:{toolChoice:'none'} after a not-executed result so that continuation
cannot open another tool loop. Session-owned messages, signal, and streaming
state remain unavailable through that field. Its
terminal chat-session-message event releases the completed request ownership
before publication, so a listener may call submitToolResult() immediately
without a timer or microtask workaround. Internal protocol diagnostics remain
in the developer console; they are not inserted as assistant content, and a
rejected user draft is restored without losing its text.
Visible Chat failure copy is opt-in: only an Error deliberately marked
userSafe:true may provide its nonblank userMessage or message. Every
unknown provider, protocol, dispatch, persistence, or settlement failure keeps
its complete Error object in the developer console and diagnostic event while
the transcript and status use a generic user outcome. New diagnostic codes
therefore cannot become conversational text merely because they are absent
from a finite internal-error list.
streamMessage(text,id,isThinking) accepts text content only. An Error supplied
as a stream chunk is logged and rejected rather than stringified into the
transcript; any other nontext chunk fails with
ARCANE_CHAT_STREAM_CONTENT_INVALID. setMessageProgress() preserves explicit
string labels/status, but routes Error objects through the same user-safe copy
boundary and otherwise displays generic progress text while logging the exact
diagnostic value. Finite fractional and over-total progress remains visible in
the status text and accessibility description; only the decorative track width
is constrained to its visual range.
pendingTools is the mutable ordered array of actionable {id,name,message}
summaries and never exposes raw arguments. pendingTool is that single-call
summary only when exactly one call is pending. pendingToolCalls exposes
complete copied call envelopes for an explicitly selected inspection or host
settlement surface, while pendingToolCall is its single-call view.
These pending-call views exist only for the active transient protocol. Durable
history stores each tool's required user-facing message as an ordinary
role:'tool' record with optional public name and result status; it stores no
call envelope or ID and therefore does not recreate a pending executable call
after reload. submitToolResult() and submitToolResults() accept status as
the public result term; disposition remains an accepted input spelling.
When a submitted turn uses persist:false, or its session's Chat entity has
persist=false, Chat may show its cards while that
one operation is active, then removes them when the operation settles; neither
the input nor response remains in the retained transcript or model context.
This cleanup also applies to failed, cancelled, detached, or replaced-session
requests. Temporary input is not restored into the composer, and a temporary
failure does not become an assistant history card. The request still rejects
normally and keeps its diagnostic/status reporting. Cleanup owns the exact
operation's nodes so a completion listener can start another turn safely.
Submission code passes those card references directly when it creates them;
reusing an operation identifier never selects earlier conversation cards for
cleanup or timestamp updates.
The session's terminal retained boolean reports its actual commit decision;
Chat uses that decision instead of retroactively interpreting a flag changed
for a later request. A completion listener cannot erase an earlier settled
turn by changing the next operation's retention setting.
Chat carries a submission's no-retention choice into its copied session request
before any rendering wait, so re-enabling the entity before dispatch cannot
retain that temporary input. Existing falsy entity settings retain their
no-retention meaning; a compatible custom session without a Chat entity keeps
its existing default behavior.
Persistent-turn recovery and existing saved history remain unchanged.
For streaming sessions, every provisional structural card and the terminal
result must preserve the same choice, ordered call position, exact ID, type,
function name, argument string, and extension fields. A changed or omitted
observed call fails with
AI_CHAT_STREAM_TOOL_CALL_MISMATCH; the provisional card is removed and the
prior pending-call state is restored instead of leaving a ghost card or a false
settlement.
setAIAvailability() remains a current LLM availability input, but selected
sticky AIRuntimeState LLM state wins over that boolean. STT and TTS readiness always
comes from sticky runtime role state; the method never forwards standalone
speech booleans or synthesizes ready speech roles without a selected, loaded
provider.
Before model selection is available, conversation surfaces remain hidden unless
the host supplies LLM availability through setAIAvailability(). For a selected
local LLM, the transcript, session status, composer, upload, speech panel
(including application-supplied controls), language selector, and timer stay
hidden until that exact sticky role is ready and loaded. The existing model
activation area remains available for Start, progress, cancellation, and retry.
At viewport widths up to 44rem, that pending local-model activation area sits
at the top of the chat area; wider layouts retain their existing placement.
A selected cloud route (localOnly:false) shows the conversation surfaces
immediately; Send still follows actual LLM availability. Later unload, failure,
or selection changes update visibility from the same runtime subscription
without starting model work or changing retained conversation content. A
completed conversation keeps its transcript visible and its controls hidden.
When a selected LLM route is unloaded or in error, the component exposes a
keyboard-operable Start/Try again control while Send stays disabled. During
loading, the control becomes Cancel loading and reflects sticky progress
inside the same activation area. Progress is indeterminate until a real finite
positive total exists. A complete provider-reported completed, total, and
unit measure is informational and remains visible without gating activation.
modelName supplies the application-owned display label without moving model
policy into the component.
The default requestAIActivation(intent) forwards mutable
{role:'llm',action:'load'|'unload',reason:'user'} to
requestAIRuntimeIntent(). A host may replace that callback.
Before the callback, the component dispatches the bubbles/composed/cancelable
chat-ai-activation-request event with mutable complete {intent,state} detail.
preventDefault() suppresses the callback. A callback failure dispatches the
bubbles/composed, noncancelable chat-ai-activation-error event with mutable complete
{request,error,message}. A recognized canceled load whose current route is
unloaded or unloading is not reported as an activation error.
On pagehide, a BFCache-persisted page retains the component and its session,
speech, listeners, and provider state. A matching persisted pageshow refreshes
the current availability UI without rebinding or duplicating listeners.
Nonpersisted pagehide remains terminal and calls destroy().
destroy() aborts the component's AI-runtime-state subscription, destroys the
activation controller, removes both page lifecycle listeners, calls the
optional speech controller's destroy(), sets ready to false, and returns
true; later calls return false. It does not initiate a provider load or
unload.
Chat listens for the bound (or current global) AI runtime's ai-tts-failure
event and forwards its complete Error and exact operation boundary to
speech.reportTTSError(). Playback-start or playback-resume failures can occur
after Chat's streamTTS() preparation promise has resolved.
SDK 0.5.12 adds a waitForPlayback:true mode for the
terminal result of the segments submitted by one invocation; Chat continues
to feed chunks without waiting for playback. Runtime mute, cancellation,
permission waiting, and stale generations remain non-errors.
Each visible model chunk, including the first chunk that creates its assistant
card, renders once in arrival order. When speech is ready and unmuted, each
chunk also reaches AI.streamTTS(text) once. Card creation is synchronous, so
consecutive chunks retain their original order without waiting for speech
preparation or playback. Thinking content remains outside speech forwarding.
The AI owner automatically removes repeated formatting marks from an outbound
speech-input copy before the configured segmentation, admits completed segments to bounded synthesis
immediately, and schedules the contiguous ready audio prefix on the audio
clock. Chat retains the original Markdown for display and storage and owns no
second speech queue. No app option selects or disables this cleanup. Single
punctuation, ordinary repeated punctuation, language, and voice retain their
existing behavior.
Events: chat-ready, chat-session-bound, chat-session-message,
chat-session-error, chat-send-message, chat-send-error,
chat-file-uploaded, chat-file-upload-error, chat-language-changed,
chat-language-change-error, chat-ai-activation-request,
chat-ai-activation-error, chat-speech-synthesis-error, and
conversation-timebox-error.
All chat operation ids have the form
<component-instance-id>:<kind>:<sequence>. The stable public reasons are
chat-ready, message-submission-requested,
message-submission-cancelled, caller-signal-aborted,
component-destroyed, host-message-submission-rejected,
file-storage-completed, file-storage-rejected,
language-change-requested, language-change-callback-rejected,
language-model-activation-requested,
language-model-activation-rejected, speech-synthesis-rejected, and
conversation-timebox-delivery-rejected.
The stable chat boundary codes are:
ARCANE_CHAT_MESSAGE_SUBMISSION_ABORTEDfor the owned submission signal;ARCANE_CHAT_LANGUAGE_MODEL_ACTIVATION_REQUEST_REJECTED;ARCANE_CHAT_HOST_MESSAGE_SUBMISSION_REJECTED;ARCANE_CHAT_FILE_STORAGE_REJECTED;ARCANE_CHAT_LANGUAGE_CHANGE_CALLBACK_REJECTED;ARCANE_CHAT_SPEECH_SYNTHESIS_REQUEST_REJECTED;ARCANE_CHAT_CONVERSATION_TIMEBOX_DELIVERY_REJECTED.
Error projections preserve the complete error detail, with the boundary code
and any distinct dependency causeCode. File projections preserve the complete
live File and its authored metadata. Language and LLM activation requests are
cancelable before their host callbacks. Every public detail remains mutable.
Shared dependencies: MD.js, File.js, ConversationTimebox.js, AIRuntimeState.js.
Availability and normalization
Browser and supported native WebViews. UI and provider-runtime state are normalized; AI/storage/media behavior remains mixed. The component emits no activation request on import or startup. After the user operates the visible control and the component event is not canceled, it publishes a capability-neutral user intent; a provider/runtime owner decides whether and how to execute the requested load or unload. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="chat.html"
href="/arcane/components/chat.html">
</html-import>
conversation-view.html
Overview
Provider-neutral conversation display, advisory actions, composer, busy state, and status.
Public surface
Methods/properties: setConversation(), setBusy(), setStatus(), clearComposer(), destroy().
Events: conversation-view-ready, communication-send, communication-advisory-action.
Availability and normalization
Browser and supported native WebViews. DOM-normalized. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="conversation-view.html"
href="/arcane/components/conversation-view.html">
</html-import>
dashboard-config.html
Overview
Selects which normalized chart definitions are visible on a dashboard.
Public surface
Methods/properties: configure(), setDefinitions(), setVisibility(), getChartOptions(), getEffectiveVisibility(), open(), close(), destroy().
Events: dashboard-config-ready, dashboard-config-opened, dashboard-config-closed, dashboard-config-change.
Shared dependencies: ComponentContracts.js, WaitForComponent.js.
Availability and normalization
Browser and supported native WebViews. Fully normalized definitions and visibility. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="dashboard-config.html"
href="/arcane/components/dashboard-config.html">
</html-import>
data-maintenance.html
Overview
Runs destructive cleanup of empty chats and memories inside the current app data scope.
Public surface
Methods/properties: open(), destroy().
Events: data-maintenance-ready, data-maintenance-complete.
Shared dependencies: DataMaintenance.js, WaitForComponent.js.
Availability and normalization
Browser and supported native WebViews. Normalized counts; DBOPFS failures mixed. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="data-maintenance.html"
href="/arcane/components/data-maintenance.html">
</html-import>
data-view.html
Overview
Opens a modal file view using the shared file manager. Applications supply their
own record mappings through the same preview callbacks as the standalone
file-manager.html.
Public surface
Methods/properties: beforeOpen(), open(), close(), printPreview(), destroy().
Assign previewDescriptor, previewTransform, and directoryFilter on the
host before opening. The component forwards those callbacks, comma-separated
data-hidden-prefixes, and the presence of data-show-hidden to its child
before the child's first load. Reopening refreshes those values before
loadAll(), so changed callbacks and hidden-directory choices take effect.
beforeOpen() is awaited before this configuration is consumed. data-dirs
selects the initial directories; data-layout defaults to files.
await close() invalidates pending opens, closes the child's dialogs before the
parent, and returns true only after closure. It returns false when destroyed
or a child/parent cannot close; complete errors reach shared diagnostics. It is
reusable: a later open() reloads the existing child. Repeated closes share the
pending closure. destroy() remains terminal.
An application that loads a history selection into an editor must synchronously
call preventDefault() on the existing cancelable file-manager-open event
before awaiting its own save/load work. That application owns record selection,
autosave, title, and editor focus; call close() after loading and restore focus
after it resolves true. No record-loading policy is added to the SDK.
printPreview() forwards to the currently open child preview and returns
false when no such preview is available.
Events: data-view-ready.
Shared dependencies: WaitForComponent.js.
Availability and normalization
Browser and supported native WebViews. DOM-native result. Preview records
and directory policy remain application-owned; the child owns rendering,
preview cancellation, and media cleanup. destroy() also destroys the child
file manager and modal. HTMLImport + DOM; native methods remain subject to the
bound app's capabilities. Deep protocol details.
Example
<html-import
id="data-view.html"
href="/arcane/components/data-view.html">
</html-import>
directory-picker.html
Overview
Presents the provider-owned OS directory chooser with change/cancel/error states.
Public surface
Methods/properties: configure(), focus(), select(), destroy().
Events: directory-picker-ready, directory-picker-change, directory-picker-cancel, directory-picker-error.
Shared dependencies: DirectoryPicker.js.
Availability and normalization
Browser and supported native WebViews. Complete directory paths and native selection/error content are preserved without trimming, character caps, or a generic control-character gate. The provider or operating system owns any platform-specific path failure. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="directory-picker.html"
href="/arcane/components/directory-picker.html">
</html-import>
document-inspector.html
Overview
Inspects PDF, text, or source documents and records review state.
Public surface
Methods/properties: loadDocument(), selectView(), markSaved(), destroy().
Events: document-inspector-ready, document-review-change.
Shared dependencies: MD.js.
Availability and normalization
Browser and supported native WebViews. Document state normalized; browser document APIs mixed. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="document-inspector.html"
href="/arcane/components/document-inspector.html">
</html-import>
file-drop.html
Overview
Acquires files by drag/drop or picker and presents busy, progress, error, and cleared state.
Public surface
Methods/properties: configure(), openPicker(), clear(), setBusy(), setError(), setProgress(), destroy().
Events: file-drop-ready, file-drop-selected, file-drop-progress, file-drop-state, file-drop-error.
Availability and normalization
Browser and supported native WebViews. Complete picker, drop, and API selections are preserved; multiple remains a picker hint and maxFiles remains compatible configuration rather than a rejection or discard gate. Browser File/drop errors are mixed. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="file-drop.html"
href="/arcane/components/file-drop.html">
</html-import>
file-inspector.html
Overview
Displays file metadata, preview, busy/error state, and caller-defined actions.
Public surface
Methods/properties: configure(), show(), clear(), setActions(), setBusy(), setError(), setPreview(), destroy().
Events: file-inspector-ready, file-inspector-action, file-inspector-change, file-inspector-cleared, file-inspector-error.
Slots: title, preview, metadata, actions.
Availability and normalization
Browser and supported native WebViews. State normalized; preview/provider behavior mixed. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="file-inspector.html"
href="/arcane/components/file-inspector.html">
</html-import>
file-manager.html
Overview
Browses, filters, selects, opens, and acts on app-scoped files. Optional neutral preview descriptors let an application display complete text, documents, conversations, and related media without adding its record schemas to the SDK.
The default tree provider is initialized before storage readiness starts the
first load. Already-ready DBOPFS loads immediately; otherwise the component
starts on dbopfs-ready. Both paths retain the same file-manager-ready event
and destroy() cleanup, without delaying unrelated component startup.
Public surface
Methods/properties: setProvider(), loadAll(), setFilter(),
setDirectoryFilter(), select(), clearSelection(), close(), printPreview(), destroy(),
previewDescriptor, previewTransform, directoryFilter.
Assign directoryFilter(entry, context) before the first load, or call
setDirectoryFilter(fn|null) to replace it and reload an initialized manager.
Returning exactly false excludes a directory. Context is
{directory,fileName,path,layout}; directory-level calls have an empty
fileName. The built-in DBOPFS paths apply this predicate before reading an
excluded directory's keys or file metadata. Tree-provider entries are also
filtered before display and expansion; an injected provider still owns the
reads inside its own list() implementation.
Comma-separated data-hidden-prefixes now applies to directory names as well
as the existing filename filtering. data-show-hidden disables the prefix
rule, while the explicit directory predicate remains active. Existing
setFilter(fn|null) and provider filter predicates retain their entry first
argument and false-only exclusion behavior; their optional second argument
is the same {directory,fileName,path,layout} context.
previewDescriptor(file, context) receives the original opened File, not a
serialized copy or a JSON-only projection. Context is
{directory,fileName,extension,path,mimeType,signal}. It may return a descriptor
or a promise for one. Returning null or undefined continues through the
existing preview path. Application record parsing and mapping belong in this
callback; the SDK supplies no conversation or media-storage schema.
Each descriptor accepts an optional title. Supported shapes are:
| Kind | Content |
|---|---|
text |
content: complete string, displayed as preformatted text |
markdown |
content: complete Markdown string, rendered by the shared Markdown owner |
html |
content: complete HTML string assigned unchanged to a titled iframe's srcdoc |
json |
content: value displayed as formatted JSON |
conversation |
messages: ordered {role,content,timestamp,name?,status?} records |
collection |
items: ordered descriptors, including nested collections |
image, audio, pdf, download |
content: a Blob or File, or a function receiving {signal} and resolving to one |
Conversation role and complete Markdown content are strings. Optional
assistant name is displayed exactly when it is a nonblank string; otherwise
the assistant label is AI, without a role suffix. User and other role labels
retain their supplied name alongside the role. User and assistant cards use
distinct shared-theme backgrounds, and each card retains its original
data-role. Optional status is displayed beside the time. Valid supplied
timestamps are displayed in local time with their real ISO datetime; absent
timestamps display Time unavailable, and an unrecognized supplied timestamp
is displayed as supplied. No timestamp is invented.
Images may supply alt; downloads require fileName. A media/download
function is lazy: only that item's explicit Load button invokes it, with
the preview's abort signal. A failed item shows Unable to load this item.
and makes the same button available for retry; sibling items remain visible.
The shared logger receives the original error. Immediate
Blobs render directly. Audio exposes native controls without autoplay. The
component does not automatically read every related media variant.
Closing the preview, opening another file, or destroying the manager aborts
the preview signal, ignores late descriptor/loader results, stops owned audio,
removes iframe srcdoc, and releases owned object URLs, including those in
nested collections. An active print snapshot retains its URLs until the
browser's afterprint event, even when the preview closes meanwhile.
Applications should observe the supplied signal in their asynchronous reads.
Descriptor and file-open failures show Unable to open this file. in the
current modal and send the original error to the shared logger.
When no descriptor is returned, the existing
previewTransform(parsed,{directory,extension,fileName}) callback remains
available for JSON-family files. Native image, audio, PDF, HTML, Markdown,
JSON, and text presentation remains available. HTML and Markdown also use
text/html and text/markdown MIME routing when a filename has no matching
extension. Routing compares the lowercase MIME essence without its parameters;
the callback's mimeType and the file content remain unchanged.
HTML uses its complete original string in srcdoc without an
added sandbox policy; Markdown reads the complete original text before
rendering. With no descriptor or previewTransform, JSON, JSONL, and NDJSON
files are read in full and recognized through
decodeMarkdownMediaRecord(). A complete
stored image record, including nested single-record arrays, opens as an image
when its decoded Blob has an image/ media type. Untyped/non-image records,
multiple records, and unrecognized content keep their ordinary JSON-family
presentation; malformed recognized image encoding follows the existing
file-open failure path.
This recognition leaves saved content unchanged and performs no migration.
Untransformed JSONL/NDJSON shows its complete original text,
including lines that are not JSON records. Other binary files offer a download
of the original File.
The larger file-preview dialog reuses --modal-width, --modal-max-height,
and --modal-padding; applications can override those existing modal values.
The preview's Print button and await printPreview() print its current
rendered content with the file title. Native browser Print selects the open
preview ahead of the editor. Printing uses the shared
PrintView.js owner; accessible HTML frames
are copied from their current rendered document, never substituted with source
text. Explicit printing waits for images/fonts and HTML frame readiness.
The shared print surface uses a light paper palette and 1in (25.4mm) page margins
while preserving image/SVG colors and leaving the screen theme unchanged.
Native PDF and inaccessible embedded viewers require their own print command.
true means the browser print dialog was requested, not that paper or a PDF
was produced. Closed, destroyed, or unavailable previews return false;
preparation failures reject and the visible control reports a concise failure.
Markdown previews resolve saved arcane-media: images through
MarkdownMedia.js before connecting IMG
nodes. Text appears while independent image reads finish; failures leave the
complete text and successful images visible with a concise recovery status.
Explicit printing waits for local reads and decoding. Native Print reports
pending media because it cannot await them. Closing or replacing a preview
cancels display readiness without waiting for storage; URLs already retained
by a requested print remain until afterprint. Original Markdown and ordinary
external image URLs remain unchanged.
Standalone IMG blocks with multiline quoted descriptions use the shared
MD.js tokenizer in both ordinary and source-mapped
rendering; the complete description and stored Markdown remain intact.
await close() cancels pending presentation work and closes delete, file, and
directory dialogs in that order. A settled preview keeps its rendered content,
media, and printing available until the file dialog actually closes; refusing
or failing to close leaves the still-visible preview usable. Actual file-dialog
closure releases its preview resources. The method returns false on
refused/failed closure or after destruction. The manager stays
reusable; a later opening can use it again. Already accepted upload/deletion
writes complete through the storage owner without reopening closed dialogs.
Events: file-manager-ready, file-manager-select, file-manager-open, file-manager-action.
Shared dependencies: DBOPFS.js, File.js, MD.js, MarkdownMedia.js, PrintView.js, WaitForComponent.js.
Availability and normalization
Browser and supported native WebViews. Selection/filter state, neutral preview descriptors, complete content delivery, cancellation, and media cleanup are normalized; storage/provider behavior remains mixed. HTMLImport and DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="file-manager.html"
href="/arcane/components/file-manager.html">
</html-import>
header.html
Overview
Shared title bar with history, reload, online marker, presentation labels, and 988 link.
The saved User skin adds its class tokens to the document body without replacing
application layout or other pre-existing classes. Repeated ready notifications
replace only skin classes previously added by that header. Skin application
keeps the existing already-ready check and user-entity-loaded subscription;
navigation and online-status behavior are unchanged.
Public surface
This fragment declares no public host method.
This fragment declares no component-specific readiness or action event; use the loader's html-import-ready only to know that import execution completed.
Availability and normalization
Browser and supported native WebViews. Browser/platform-native behavior; no component-ready contract. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="header.html"
href="/arcane/components/header.html">
</html-import>
integration-settings.html
Overview
Edits non-secret communication service configuration and service actions.
Public surface
Methods/properties: configure(), getValues(), setStatus(), destroy().
Events: integration-settings-ready, integration-settings-save, integration-settings-close, integration-action.
Availability and normalization
Browser and supported native WebViews. Normalized non-secret values. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="integration-settings.html"
href="/arcane/components/integration-settings.html">
</html-import>
local-ai-status.html
Overview
Presents local-AI standby, failure, recovery, guidance, retry, and dismissal states.
Public surface
Methods/properties: configure(), begin(), present(), destroy(), and the hidden property.
Events: local-ai-status-ready, local-ai-status-dismissed, local-ai-retry.
Shared dependencies: LocalAIReadiness.js.
Availability and normalization
Browser and supported native WebViews. Fully normalized LocalAIReadiness report. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="local-ai-status.html"
href="/arcane/components/local-ai-status.html">
</html-import>
markdown-document.html
Overview
Renders and navigates a complete Markdown document with focusable fragments.
Public surface
Methods/properties: configure(), load(), render(), clear(), fail(), focus(), focusFragment(), destroy().
Events: markdown-document-ready, markdown-document-state,
markdown-document-loading, markdown-document-rendered,
markdown-document-empty, markdown-document-error, and
markdown-document-navigate.
Saved local image references use
MarkdownMedia.js. Text rendering and
the existing rendered event do not wait for image reads. The optional
labels.mediaError supplies concise visible failure text while complete
diagnostics remain in the developer console; successful images and document
text remain visible. Replacing, clearing, failing, or destroying the document
releases its display resources without deleting stored media. Markdown source
and ordinary external image URLs remain unchanged.
Complete standalone IMG blocks with quoted multiline descriptions render
through the shared MD.js tokenizer without
rewriting saved Markdown.
Shared dependencies: MD.js, MarkdownMedia.js.
Availability and normalization
Browser and supported native WebViews. Complete Markdown and state are normalized; malformed input and Marked/DOM failures remain visible. HTMLImport
- DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="markdown-document.html"
href="/arcane/components/markdown-document.html">
</html-import>
markdown-editor.html
Overview
Configurable Markdown authoring, toolbar, preview, plain-text title, and save surface. The default editor retains its growing stacked layout and existing controls. Optional fit mode keeps the Markdown input and rendered preview inside an application-supplied bounded area.
Public surface
Methods/properties: configure(), focus(), clear(), insertMarkdown(text),
saveEntry(), print(), destroy(), value, entryTitle, options.
insertMarkdown(text) replaces the current source selection with the exact
supplied string, places the caret after it, and emits the ordinary change
event. It preserves the source viewport and normal preview/save lifecycle.
It returns false when read-only or destroyed and throws TypeError for a
non-string. The application owns the inserted Markdown and any related data.
The visible Print control and await print() print the complete rendered
Markdown with entryTitle, independently of saving. Native browser Print uses
that same registered view unless an open file preview takes precedence.
The SDK copies current rendered DOM/styles into a temporary print-only view,
leaving the editor's source, controls, and screen layout in place. Both explicit
and native print use the shared light paper palette and 1in (25.4mm) page margins;
image pixels and SVG artwork keep their colors. Explicit printing waits for
resource readiness; native beforeprint is synchronous
and uses the currently rendered content. print() returns false when the
view is unavailable, rejects preparation failures, and returns true only
when the browser dialog was requested. Completion of physical printing or PDF
saving is not observable through this method. See
PrintView.js.
Saved arcane-media: image references are hydrated through
MarkdownMedia.js in detached rendered
nodes. Source text, edit selection, source-map comments, ordinary image URLs,
and the existing save flow remain unchanged. Image status has its own
idle-hidden media-status part, separate from save status. Explicit printing
waits for the current image reads/decoding, follows a replacement preview, and
rechecks readiness before capture. Native Print reports still-pending media
synchronously; it cannot wait or cancel the native dialog. Print-owned URLs
outlive a changed or destroyed editor until afterprint.
The shared MD.js tokenizer preserves complete
standalone IMG blocks with quoted multiline descriptions in ordinary and
source-mapped rendering. Existing saved markup needs no rewriting.
configure({fit:true,followPreview:true}) opts into the two independent
behaviors. Both options default to false; omitted options retain their
previous values during reconfiguration, and explicit false disables either.
Initial markup can use data-fit="true" and data-follow-preview="true".
fit:true fills the host's available height. The application must supply a
bounded host height and allow its enclosing flex/grid item to shrink, for
example with min-height:0. Input and preview have independent scroll areas:
two columns when room permits and two bounded stacked panes on narrow widths.
Title, toolbar, status, and save remain outside those scrolling panes. Hiding
the preview leaves the input the available pane space. Fit mode does not
change the application's fixed shell or scroll the page.
followPreview:true follows the Markdown body's active edit position after
typing or applying a toolbar format. It scrolls the preview only as needed
to bring a short corresponding block into view; a block taller than the pane
uses the caret's approximate fraction within that block. Users can scroll the
preview independently, and rerendering retains that reading position; the next
body edit may reposition it. Title edits,
programmatic value replacement, and ordinary preview scrolling do not request
edit-position following. Moving the selection alone does not trigger following,
and following never scrolls the input pane or containing page. The title
remains a native plain-text input.
Preview rendering preserves the source pane's current horizontal and vertical
scroll offsets and selection. Value replacement and reconfiguration retain
those offsets and the selection positions that still fit the new text; layout
changes move only the preview, keeping the live textarea attached. Toolbar
formatting focuses the source without scrolling its ancestors, selects the
formatted text, and preserves the source viewport. Native typing, keyboard
selection, and manual source scrolling retain their ordinary behavior; there
is no scroll lock or deferred restoration of an earlier source position.
Following uses the shared Markdown block mapping;
lists, quotes, and tables follow their block, while invisible source positions
use a nearby available rendered block rather than exact glyph geometry.
Public CSS parts are editor, title, toolbar, input, preview,
actions, status, media-status, print-action, and save-action. Applications can make the title
borderless and compact through ::part(title) while retaining its native
editing behavior and visible keyboard focus. These parts are styling hooks,
not slots or replacement controls.
Existing showTitle, showToolbar, showSave, showPreview, readOnly,
clearOnSave, labels, formats, and callbacks keep their behavior. onSave
or the host's save receives complete {title,markdown} plus a second
{signal,operationId} context; layout and following add no fields to the
saved content. Edits, replacement, clear, and destruction retain the existing
save cancellation and late-result suppression. Destruction also cancels the
pending preview frame.
Events: markdown-editor-ready, markdown-editor-change, markdown-editor-saved.
Shared dependencies: MD.js, ComponentContracts.js.
Availability and normalization
Browser and supported native WebViews. Editor values, opt-in fit layout, and preview following are normalized; the injected save result remains application-owned. HTMLImport + DOM; native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="markdown-editor.html"
href="/arcane/components/markdown-editor.html">
</html-import>
For a bounded editor, choose the height in the application and style only the public title part:
<style>
#field-notes { display:block; height:32rem; min-height:0; }
#field-notes::part(title) {
border:0;
border-radius:0;
background:transparent;
padding:.35em 0;
}
</style>
<html-import
id="field-notes"
href="/arcane/components/markdown-editor.html"
data-fit="true"
data-follow-preview="true"
data-title-placeholder="Dragon field notes">
</html-import>
media-embed.html
Overview
Loads a parsed YouTube video or playlist embed and exposes an external-platform
action. Ordinary YouTube hosting is the default; configure({privacyEnhanced:true})
explicitly selects the privacy-enhanced host.
Public surface
Methods/properties: configure(), load(), destroy().
Events: media-embed-ready, media-load, media-error, media-open-platform.
Shared dependencies: YouTubeMedia.js.
Availability and normalization
Browser and supported native WebViews. URL/error normalized; iframe/platform behavior native. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="media-embed.html"
href="/arcane/components/media-embed.html">
</html-import>
modal.html
Overview
Generic modal with population, configurable user dismissal, actions, and concurrent task execution.
Public surface
Methods/properties: configure(), populate(), open(), close(), runTasks(),
destroy(), running, opened.
configure({dismissible}) synchronously returns the current {dismissible}
configuration, or false after destruction. dismissible starts as true;
omitting it preserves the current choice. A supplied value must be a boolean.
Setting it to false hides the close button and prevents user dismissal through
Escape, backdrop clicks and the close button. Setting it back to true restores
normal user dismissal. The choice persists across population, open/close cycles
and task completion. If the close button held focus when disabled, focus moves
to a content control or the focusable modal body.
This option does not prevent the owning application from calling close() or
destroy(). The existing running-task behavior remains: close() leaves a
running modal open unless called with its existing second force argument set
to true; destroy() releases the component. Product-specific conditions for
closing a modal belong to the application. Content, actions and task results
are preserved, and runTasks() continues to execute independent jobs concurrently.
runTasks(title, jobs) calls each job.task(reportProgress) concurrently.
The optional callback accepts complete plain-text status for that pending job
only and returns true when displayed. For example, a request can report its
retry delay without replacing another job's progress. Reports after that job
settles or the modal is destroyed return false and change no UI. A display
failure is logged without rejecting the task. Existing zero-argument task
functions remain supported, results retain Promise.allSettled order, and
destruction does not cancel the application-owned work. Progress is transient
display content, never a task result or conversation record.
Events: modal-ready, modal-opened, modal-closed, modal-action.
Slots: header, body, footer.
Availability and normalization
Browser and supported native WebViews. Modal state normalized; injected task results mixed. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="modal.html"
href="/arcane/components/modal.html">
</html-import>
output-panel.html
Overview
Presents status, output, body, coverage, actions, pending, error, and cleared states.
Public surface
Methods/properties: configure(), setOutput(), setBody(), setCoverage(), setActions(), setPending(), setStatus(), setError(), clear(), destroy().
Events: output-panel-ready, output-panel-state, output-panel-change, output-panel-action, output-panel-error, output-panel-cleared.
Slots: title, header-actions, body, coverage, actions.
Availability and normalization
Browser and supported native WebViews. DOM-normalized. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="output-panel.html"
href="/arcane/components/output-panel.html">
</html-import>
preferences-form.html
Overview
Builds a schema-driven preferences form with submit, reset, busy, and status behavior.
Public surface
Methods/properties: configure(), getValues(), setValues(), setBusy(), setStatus(), destroy().
Events: preferences-form-ready, preferences-change, preferences-submit, preferences-reset.
Availability and normalization
Browser and supported native WebViews. Normalized form values. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="preferences-form.html"
href="/arcane/components/preferences-form.html">
</html-import>
pwa-install.html
Overview
A compact installation and update suggestion using the shared PWA owner.
The default floating panel appears near the top right when the browser offers
installation or a completed resource refresh establishes an update. It has an
Install or Update action and an explicit close button, takes no
focus automatically, and has no dismissal timer. It uses the Arcane theme and
primitives, wraps complete labels and errors, and scrolls its own content when
the available height is limited. The parent page loads ThemeBootstrap.js to
apply the user's appearance preferences.
Public surface
configure({appName, installLabel, closeLabel, promptingLabel, description, updateTitle, updateLabel, updateDescription, updateCloseLabel, presentation})
updates display configuration and returns its current record.
Labels remain complete strings. appName initially uses data-app-name or
this app; the default button label is Install. presentation is floating
by default or inline, initially read from data-presentation. Inline placement
uses the parent's layout. Set description to an empty string when a compact
placement needs no supporting text; supplied descriptions remain visible.
install() calls the shared owner's native prompt synchronously and returns its
promise of the browser outcome or null when no prompt is available. Call it
directly from a user action. The component's Install button already does this.
An explicit request's complete failure message remains visible until dismissed;
the method rejects with the same error. The browser controls actual installation.
Acceptance hides the suggestion without claiming installation has completed.
When an update is available, the same panel shows Update available, Update,
Reload this page to use the updated app., and the close label Close update suggestion. Each string has its matching configuration key. This presentation
takes precedence over installation, including for installed/running apps and
previously dismissed installation suggestions.
update() calls the shared owner's ordinary location.reload() synchronously,
returning true when available and false when unavailable or destroyed. It leaves
availability intact if a native unload handler cancels navigation. Native reload
errors propagate; the button observes them through developer diagnostics. There
is no automatic reload, extra SDK confirmation, cache reset, or guarantee of
preserving transient application state. dismissUpdate() hides only the update
suggestion for this page owner and returns true, or false after destruction.
dismiss() closes the component. Floating dismissal also uses the owner's
session dismissal; an explicit inline component ignores that shared dismissal
and closes only its own instance. Closing retains any unused native prompt at
the shared owner. destroy() removes the component's listeners and subscription,
disposes its event source, hides its host, and marks ready false; it does not
dispose the shared owner or change browser installation state. Both methods
return true while active and false after destruction; destroy() is idempotent.
The readonly state property returns the shared owner's current install/update-state
record; ready becomes true after methods and the state subscription are attached.
pwa-install-ready carries {ready, state}; pwa-install-change carries
{state, visible} for each observed owner update; pwa-install-dismissed carries
{presentation, state}, with kind: 'update' for update dismissal. These follow
the canonical event projection contract.
Availability and normalization
The component requires HTMLImport and a DOM renderer. Native installation
availability comes from the browser's beforeinstallprompt event through
getPwaInstall(). Without an available event, the installation suggestion stays hidden;
absence does not identify why installation is unavailable. Installed-app events,
accepted prompts, and an already running installed display mode hide it.
The shared SDK owner persists browser-reported installation in app-scoped
DBOPFS. Both floating and inline controls stay hidden while that record is
loading and remain hidden on later visits when installation is remembered.
Those installation conditions do not hide an available update. Update state
comes from the existing page-scoped registration owner, including a current-state
read when the prompt is created after the refresh. A new page does not replay a
completed update from an earlier page. Update dismissal is independent of saved
installation state and performs no durable write.
Acceptance alone does not save installation. The component's ready means
its methods and subscription are attached; storage completion belongs to the
shared owner's ready promise and does not delay page rendering.
Example
<html-import
id="install-app"
href="/arcane/components/pwa-install.html"
data-app-name="Example Library"
data-presentation="inline"
hidden>
</html-import>
record-timeline.html
Overview
Displays chronological records/evidence and emits open actions.
Public surface
Methods/properties: setItems(), populate(), destroy().
Events: record-timeline-ready, record-timeline-open.
Availability and normalization
Browser and supported native WebViews. Complete item inventories and fields are preserved while missing identity/date records remain non-renderable. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="record-timeline.html"
href="/arcane/components/record-timeline.html">
</html-import>
relationship-board.html
Overview
Displays normalized relationship nodes/edges in graph and list forms.
Public surface
Methods/properties: setGraph(), populate(), destroy().
Events: relationship-board-ready, relationship-node-open, relationship-edge-open.
Availability and normalization
Browser and supported native WebViews. Complete node, edge, lane, label, and summary inventories are preserved; edges still require existing endpoints. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="relationship-board.html"
href="/arcane/components/relationship-board.html">
</html-import>
screen-capture.html
Overview
Presents image, video, or GIF display-capture workflow.
Public surface
Methods/properties: capture (the component-owned ScreenCapture instance) and destroy().
Events: screen-capture-ready, screen-capture-result.
Ready uses operation id screen-capture-ready-<component-instance-id>;
capture results use the current instance-owned generation. destroy()
invalidates that generation, aborts UI listeners, revokes the preview URL,
destroys the ScreenCapture instance, disposes the source, marks the host
unready, and returns true; repeated calls return false.
Shared dependencies: ScreenCapture.js.
Availability and normalization
Browser and supported native WebViews. State/result normalized; media permission/codec failures mixed. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="screen-capture.html"
href="/arcane/components/screen-capture.html">
</html-import>
source-code-viewer.html
Overview
Renders line-addressable source code with load, error, focus, and state behavior.
Public surface
Methods/properties: configure(), load(), render(), clear(), fail(), focus(), focusLine(), destroy().
Events: source-code-viewer-ready, source-code-viewer-state,
source-code-viewer-state-loading, source-code-viewer-state-ready,
source-code-viewer-state-empty, and source-code-viewer-state-error.
Availability and normalization
Browser and supported native WebViews. Complete mutable source/state is rendered without character or line caps; malformed control-character metadata still fails honestly. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="source-code-viewer.html"
href="/arcane/components/source-code-viewer.html">
</html-import>
source-explanation.html
Overview
Presents an evidence finding, source selection, explanation, and save state.
Public surface
Methods/properties: showFinding(), populate(), selectSource(), markSaved(), destroy().
Events: source-explanation-ready, source-explanation-save, source-explanation-source-selected.
Availability and normalization
Browser and supported native WebViews. DOM-normalized. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="source-explanation.html"
href="/arcane/components/source-explanation.html">
</html-import>
speech.html
An explicitly selected native Web Speech provider uses gesture-started live
capture instead of MediaRecorder. The shared control retains every final
result and emits its existing completion event once with the exact combined
text when native capture ends. The speech-transcription-progress event carries
cumulative complete final text and the current interim hypothesis, with the
capture's operationId. Final segments replace their interim hypothesis before
publishing; capture completion clears remaining interim text. The live display
retains both while displayTranscription is true (the default). Set it false
when a containing Chat owns the editable draft; status still reports listening,
loading, and errors. Interim hypotheses stay transient. Release/Stop
finishes native recognition; cancellation, replacement and destruction abort
it and suppress late submission. A persisted page hide stops live native capture
without restarting it when the page returns. Existing Whisper and TTS paths
remain unchanged.
On desktop native capture, an accessible editable BCP47 language control occupies
the feedback area instead of idle transcription/voice readiness boilerplate.
recognitionLanguage defaults to navigator.language, accepts an explicit
language tag without restricting it to the suggested choices, and is passed to
the capture owner at start. Opening or reopening the editable picker shows all
suggestions regardless of its saved/current value. Filtering begins only after
the user changes the input text; initialization, programmatic configuration,
and choosing a suggestion leave the full list available on the next opening.
Suggestions display their native language and region names alongside the exact
BCP47 tags; they are suggestions, not an exhaustive provider support inventory.
The selected or freely typed tag remains unchanged. Arrow keys navigate the
suggestions, Enter chooses the active suggestion, and Escape or Tab closes the
list. The picker is visible and enabled only for desktop live-transcription
mode, including before recording begins. It is disabled during active capture
so changes affect the next capture; leaving live-transcription mode closes and
disables it. File/model transcription and conversation-language configuration
remain separate. Native voice loading, errors, and speaking
remain visible. Model-based transcription retains its existing status, and
mobile speech retains its existing voice-output-only presentation.
Overview
Coordinates explicit speech-to-text activation, speech controls, transcription completion, mute state, and microphone availability.
Public surface
Methods/properties: configure(), setMuted(),
reportTTSError(error,boundary='synthesis'), requestSTTActivation(),
destroy(), availability, muted, initialMuted, recognitionLanguage,
displayTranscription, and componentReady. The two new properties may also
be supplied through configure().
Events: speech-ready, speech-transcription-progress, speech-transcription-complete,
speech-transcription-error, speech-transcription-cancelled,
speech-microphone-unavailable, speech-stt-activation-request,
speech-stt-activation-error, speech-tts-lifecycle-error, and
speech-synthesis-error.
Shared dependencies: AI.js,
AIRuntimeState.js,
ComponentContracts.js, and
DBLS.js.
On mobile browsers, including tablets, the shared browser-device classifier
selects a Speech interface for voice output. Transcription activation,
recording, sending recorded audio, and their status/progress are unavailable;
requestSTTActivation() returns false without requesting a provider action.
The keyboard remains the voice-input path. The existing TTS mute/unmute control
remains available alongside application-supplied controls such as End. Mobile
voice feedback participates in layout only while a voice load is requested or
the TTS role is loading; it collapses in other states, including unloaded, ready, and
speaking. Complete status text and error events remain maintained by the same
owner, and the voice control retains its state-specific labels and retry action.
Desktop speech and the dedicated voice-transcription.html component retain their
existing behavior.
An already accepted file transcription retains its exact owned runtime
operation through the same provider/model's unloaded, busy recovering state
or correlated pending error. This preserves the actual RPC result or failure;
it does not enable another recording. Unload, close, provider/model replacement,
transport loss and caller cancellation still invalidate owned work. Native Web
Speech microphone capture keeps its independent readiness and final/interim
cancellation lifetime. See native speech recovery.
On desktop, the Hold to talk control remains disabled unless sticky STT state
is ready, the role is not busy, and microphone capture is available. For an explicitly
selected STT route, a separate keyboard-operable control presents Start
transcription while unloaded, Cancel loading while loading, a disabled
Canceling state while unloading, and Try again with the sticky error while
error. Selected-unloaded, busy, and error states are shown as distinct facts;
none is treated as ready.
Only captured microphone input that completes the selected STT route emits
speech-transcription-complete. A transient capture rejection reports
speech-microphone-unavailable but remains locally retryable; an observed
permission-denied state disables capture until the browser reports that the
permission is available again, at which point the microphone-owned status is
cleared.
The default requestSTTActivation(intent) forwards the mutable
{role:'stt',action:'load'|'unload',reason:'user'} record to
requestAIRuntimeIntent(). Before calling it, the component emits a bubbling,
composed, cancelable speech-stt-activation-request event with mutable complete
{intent,state} detail. preventDefault() suppresses the callback and intent.
Callback failure emits speech-stt-activation-error with mutable complete
{request,error,message} detail. Cancel loading publishes an unload intent;
only subsequent sticky unloading or unloaded state confirms lifecycle
progress, and callback return never proves provider work stopped.
Provider and runtime failures use generic visible speech status unless their
Error owner explicitly marks nonblank copy with userSafe:true. Complete
unknown diagnostics remain available through the developer console and error
events; they do not become control labels or status text by default. The same
boundary applies to STT activation, transcription, TTS lifecycle, synthesis,
and playback failures.
reportTTSError() recognizes synthesis, decode, playback-start, and
playback-resume. It preserves the user's mute choice, sticky provider
readiness, and accepted sibling speech jobs. The AI runtime owns settlement of
the failed job; reporting an error neither stops the queue nor retries it. The
component emits speech-synthesis-error with the exact boundary,
stable reason/code, generic user-safe status, and complete Error in the local
event detail.
synthesis:tts-synthesis-rejected/ARCANE_SPEECH_TTS_SYNTHESIS_REQUEST_REJECTED;decode:tts-decode-rejected/ARCANE_SPEECH_TTS_DECODE_REJECTED;playback-start:tts-playback-start-rejected/ARCANE_SPEECH_TTS_PLAYBACK_START_REJECTED;playback-resume:tts-playback-resume-rejected/ARCANE_SPEECH_TTS_PLAYBACK_RESUME_REJECTED.
The component emits no activation request on import or state observation.
Provider registration and selection remain inert, and default
startTranscription=false does not request STT during runtime startup. The
provider/runtime owner decides whether and how to execute a user intent; the
component never selects a runtime or model, downloads artifacts, reloads after
failure, or falls back to another provider.
Each transcription request owns an AbortController; its signal is passed as
the second argument to AI.fetchSTT(). Cancel, a newer capture, and destroy()
abort that controller and suppress late results. This proves request delivery
was canceled, not that an uncooperative provider stopped underlying work.
Each microphone attempt also owns one capture generation and one operation id
from the initial getUserMedia() request through transcription settlement. A
release while permission is still pending retires only that generation because
the browser request cannot be canceled synchronously. If that stale request
later resolves, the component stops its returned stream without clearing a
newer press, status, operation id, or retry. Active capture finalization checks
both the generation and operation id, and successful transcription retains the
same capture operation id rather than inventing a second correlation boundary.
User Unmute calls the shared AI.setSpeechMuted(false) lifecycle owner before
or with publishing the TTS load intent, so the runtime can legally load TTS.
Configured initialMuted:false records that same unmute intent even when the
TTS route is still unselected or loading. Public muted expresses the user's
choice; role availability and the AI runtime still prevent playback until the
selected role reaches ready, when the waiting intent is applied. A failed
load ends its activation attempt without changing that choice or starting
another attempt. Retry voice explicitly starts a new attempt, including when
the preserved choice is unmuted; an unloaded selected voice offers Load voice.
When a role returns to ready, permitted queued playback resumes through the
existing AI owner without repeating activation or replaying failed jobs.
Synthesis, decode, and playback failures also
preserve that choice and do not automatically replay failed speech.
Mute calls AI.setSpeechMuted(true), stops playback, cancels active TTS work,
and unloads the selected TTS role. Lifecycle failures remain visible through
speech-tts-lifecycle-error and sticky role state.
A BFCache-persisted pagehide retains the component, active provider state,
microphone permission observation, and listeners. On persisted pageshow, the
component resynchronizes the current AI mute state and rerenders its controls
and status without duplicating activation or provider work. Nonpersisted
pagehide remains terminal and destroys the component.
Speech operation ids are
<component-instance-id>:<kind>:<sequence>. Canonical cancellation reasons are
stt-role-unready, stt-provider-transcription-cancelled, stt-role-busy,
microphone-unavailable, component-destroyed, and
stt-transcription-cancelled. Microphone capture-failure reasons are
microphone-input-missing, microphone-input-unavailable,
microphone-capture-denied, and microphone-capture-rejected. Component
boundary codes are ARCANE_SPEECH_MICROPHONE_CAPTURE_REJECTED,
ARCANE_SPEECH_STT_TRANSCRIPTION_REQUEST_REJECTED,
ARCANE_SPEECH_TTS_LOAD_REJECTED, ARCANE_SPEECH_TTS_UNLOAD_REJECTED,
ARCANE_SPEECH_TTS_SYNTHESIS_REQUEST_REJECTED,
ARCANE_SPEECH_TTS_DECODE_REJECTED,
ARCANE_SPEECH_TTS_PLAYBACK_START_REJECTED, and
ARCANE_SPEECH_TTS_PLAYBACK_RESUME_REJECTED. Each of those component-boundary
public projections keeps the exact boundary in code and preserves a distinct
string code from the browser, runtime, or provider additively as causeCode.
A missing STT method therefore uses boundary
ARCANE_SPEECH_STT_TRANSCRIPTION_REQUEST_REJECTED with
causeCode:'ARCANE_SPEECH_STT_RUNTIME_METHOD_UNAVAILABLE'.
Stable rejection reasons are stt-transcription-rejected,
tts-load-rejected, tts-unload-rejected, tts-synthesis-rejected,
tts-decode-rejected, tts-playback-start-rejected, and
tts-playback-resume-rejected. Shared activation rejection uses
ARCANE_STT_ACTIVATION_REQUEST_REJECTED and activation-request-rejected.
Availability and normalization
Browser and supported native WebViews. UI/runtime state and explicit user STT activation intent are normalized; provider/model authority and media behavior remain external. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="speech.html"
href="/arcane/components/speech.html">
</html-import>
summary-strip.html
Overview
Displays compact selectable KPI or summary items.
Public surface
Methods/properties: configure(), setItems(), updateItem(), clear(), destroy().
Events: summary-strip-ready, summary-strip-change, summary-strip-select.
Availability and normalization
Browser and supported native WebViews. DOM-normalized. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="summary-strip.html"
href="/arcane/components/summary-strip.html">
</html-import>
table.html
Overview
Builds and updates a simple header/body table.
Public surface
Methods/properties: buildHeader(), buildTable(), destroy().
Events: table-ready, header-update, body-update.
Availability and normalization
Browser and supported native WebViews. DOM-normalized. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="table.html"
href="/arcane/components/table.html">
</html-import>
task-progress.html
Overview
Runs and displays a task list with started/change/complete/error state.
Public surface
Methods/properties: configure(), setTasks(), updateTask(), runTasks(), clear(), destroy().
Events: task-progress-ready, task-progress-started, task-progress-change, task-progress-complete, task-progress-error.
Availability and normalization
Browser and supported native WebViews. Task state normalized; injected task results mixed. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="task-progress.html"
href="/arcane/components/task-progress.html">
</html-import>
terminal-workspace.html
Overview
Presents multiple terminal sessions, output, active selection, theme, and terminal actions.
Public surface
Methods/properties: configure(), addSession(), removeSession(), activateSession(), append(), clear(), setState(), setTheme(), focus(), destroy().
Events: terminal-workspace-ready, terminal-submit, terminal-interrupt, terminal-clear, terminal-session-new, terminal-session-close, terminal-session-select, terminal-settings.
Shared dependencies: AnsiText.js.
Availability and normalization
Browser and supported native WebViews. UI/session state normalized; native command results supplied externally. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="terminal-workspace.html"
href="/arcane/components/terminal-workspace.html">
</html-import>
theme-editor.html
Overview
Edits, previews, saves, and resets semantic custom theme tokens.
Public surface
Methods/properties: configure(), getTheme(), setTheme(), setBusy(), setStatus(), destroy().
Events: theme-editor-ready, theme-preview, theme-save, theme-reset.
Shared dependencies: Theme.js.
Availability and normalization
Browser and supported native WebViews. Fully normalized Theme values. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="theme-editor.html"
href="/arcane/components/theme-editor.html">
</html-import>
theme-switcher.html
Overview
Selects and refreshes system, light, dark, or custom theme mode. Native buttons
retain complete readable labels and wrap when their component runs out of room,
independently of viewport width. Each button has a 2.75rem minimum target in
both dimensions. Selected buttons retain aria-pressed, their selected colors
and an inset outline while hovered; ordinary hover fill applies only to
unselected, enabled choices. Disabled choices and keyboard focus have distinct
presentation.
Public surface
Methods/properties: configure(options), setMode(mode='system'), refresh().
configure({modes,labels}) changes only this component's presentation:
modesis an ordered array of the available identifierssystem,light,dark, andcustom. It selects both visible choices and DOM/keyboard order. Omittedmodesretains the current presentation; an empty array displays no choices. Unknown or repeated identifiers throwTypeErrorbefore changing the presentation.labelsis a partial record of complete string labels keyed by those mode identifiers. Omitted labels keep their current text. Text is assigned throughtextContent, never interpreted as markup or reduced to initials. A label for a built-in mode that is not a string throwsTypeError.- The return value is
{modes,labels}containing independent mutable copies of the current presentation. Later changes to supplied/returned records do not reconfigure the component.
Label-only and unchanged-order configuration retain the existing buttons in place. An actual reorder restores keyboard focus to the previously focused button when that choice remains visible and enabled, without scrolling.
The default remains Auto / Light / Dark / Skin, using identifiers
system, light, dark, and custom. A caller may omit Skin or change Auto's
label to System without removing custom-theme support from other instances.
Configuration never changes preferences, activates a theme, or replaces the
current selected mode. If the active mode is omitted, no visible button claims
to be selected. Restoring that choice restores its existing pressed and disabled
state. Skin remains disabled until the manager has a saved custom theme.
For the initial presentation, data-modes accepts whitespace-separated mode
identifiers and data-system-label supplies the complete system-mode label.
These attributes are read once before the asynchronous ThemeManager import and
preference refresh, so initial choices do not wait for html-import-ready.
Use configure() after that event for subsequent presentation changes;
changing these attributes later does not reconfigure an existing instance.
setMode() updates pressed state and the host's data-mode only. refresh()
loads the existing ThemeManager state, updates selection and Skin availability,
and resolves with the complete manager state. Clicking a choice uses the same
manager persistence/activation operation. While it is pending, choices expose
aria-disabled="true" and ignore repeated activation while remaining in the
keyboard focus flow. Native disabling remains for an unavailable Skin choice.
Selection does not move focus when it completes or fails, so the initiating
button retains focus unless the user moves elsewhere. Presentation configuration
preserves that pending state; an actual reorder retains its focus behavior above.
The host inherits text color. Existing --app-bar-border (falling back to
--border-color), --app-bar-accent (then --secondary-color),
--app-bar-active-text (then --primary-color), and --focus-color overrides
remain supported. Applications own their palette and surrounding placement;
the component adds no application-specific palette or settings section.
Set these public CSS custom properties on the html-import host or an ancestor
to style one instance through the ordinary cascade. Omitting them preserves the
existing presentation:
| Property | Controls | Default |
|---|---|---|
--theme-switcher-radius |
Outer group border radius | 1.6rem |
--theme-switcher-option-radius |
Each option's border radius | 1.4rem |
--theme-switcher-font |
Complete option font shorthand |
700 .875rem/1.25 system-ui,sans-serif |
--theme-switcher-background |
Group background, independent of option state | color-mix(in srgb,currentColor 8%,transparent) |
The font value includes its size and family, plus any weight and line height.
Use an application-owned complete font token or value, rather than the
CSS-wide keyword inherit as the custom-property value. The host still inherits
text color. These properties do not alter the 2.75rem minimum targets,
full-label wrapping, selected/hover/focus/disabled states, or theme persistence.
Applications retain responsibility for readable font and color choices.
This fragment declares no component-specific readiness or action event; use the loader's html-import-ready only to know that import execution completed.
Shared dependencies: ThemeManager.js.
Availability and normalization
Browser and supported native WebViews. Preference/native appearance behavior mixed; no component-ready contract. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="theme-switcher"
href="/node_modules/arcane-os/runtime/arcane/components/theme-switcher.html"
data-modes="light dark system"
data-system-label="System">
</html-import>
This instance displays Light / Dark / System in that order. An instance without the two configuration attributes retains all four default choices. Both use the existing shared preference owner; presentation does not create a new store or migrate saved themes.
An application can give that instance modest rounded corners and its own ordinary label font without accessing the shadow root:
#theme-switcher {
--theme-switcher-radius: .65rem;
--theme-switcher-option-radius: .5rem;
--theme-switcher-font: 400 1rem/1.25 var(--app-font-family, system-ui, sans-serif);
--theme-switcher-background: transparent;
--app-bar-border: var(--border-color);
}
These are example application values, not new component defaults. Other instances retain the defaults unless the application cascades overrides to them.
unified-inbox.html
Overview
Displays provider-neutral communication threads with active/loading state.
Public surface
Methods/properties: configure(), setThreads(), setActive(), setLoading(), destroy().
Events: unified-inbox-ready, inbox-refresh, thread-select.
Availability and normalization
Browser and supported native WebViews. DOM-normalized. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="unified-inbox.html"
href="/arcane/components/unified-inbox.html">
</html-import>
voice-transcription.html
Overview
Records manual clips by default, with optional continuous capture that cuts segments after quiet periods or at a periodic boundary. Transcription and application saves run in capture order while microphone capture continues. The component exposes explicit selected-STT activation, cancellation, retry, and completion of the combined transcript.
Public surface
Methods/properties: configure(), requestSTTActivation(), startRecording(),
stopRecording(), retryTranscription(), cancelRecording(), save(),
completeTranscription()/complete(), clear(), reset(), destroy().
Events: voice-transcription-ready, voice-transcription-state,
voice-transcription-segment, voice-transcription-empty,
voice-transcription-error, voice-transcription-change,
voice-transcription-complete, speech-transcription-complete,
speech-transcription-cancelled, speech-stt-activation-request, and
speech-stt-activation-error.
Shared dependencies: MD.js,
ComponentContracts.js,
AIRuntimeState.js,
ContinuousVoiceCapture.js, and
AI.js.
Availability and normalization
Browser and supported native WebViews. The component subscribes
synchronously to sticky AIRuntimeState.roles.stt; its recording Start button
and public startRecording() both remain unavailable unless that role is exactly
ready and not busy. Once continuous capture starts, a busy STT lane does not
interrupt the microphone session.
A configured transcribe(file,context) callback remains
request plumbing rather than readiness authority. Its context now includes the
owned signal additively, and continuous clips also include their sequence.
The default route calls AI.fetchSTT(file,signal) so
readiness loss or destruction can abort delivery.
For a selected unloaded, loading, unloading, or error role, the component
keeps recording Start disabled and presents the same keyboard-operable Start
transcription/Try again or Cancel loading control as speech.html. Both use the
shared createSTTActivationController() contract. User operation emits the
cancelable speech-stt-activation-request event with mutable complete {intent,state}.
During loading, both controls show a native progress bar and the current
preparation, download, or initialization message with the current file and
reported elapsed time. Unknown totals remain indeterminate. In speech.html,
prior local status stays visible alongside the loading status. The activation event's
preventDefault() suppresses the callback. The default
requestSTTActivation(intent) publishes the mutable
{role:'stt',action:'load'|'unload',reason:'user'} intent. Callback failure emits
speech-stt-activation-error with mutable complete {request,error,message}. Import and
state observation emit no activation request and never begin a model download.
Unknown provider/runtime diagnostics remain complete in the developer console
and error events, while controls use generic visible outcomes unless the Error
owner explicitly marks nonblank copy with userSafe:true.
An already accepted file transcription can continue through the exact same provider/model/runtime operation's unloaded, busy recovery or pending-error state. This uses the real runtime operation ID rather than the component's local counter; another request supplies no continuation authority. New recording and transcription remain readiness-gated, and actual unload, close, replacement, transport loss or cancellation still ends the owned request. The same shared rule applies to an active continuous file-transcription job. Native Web Speech capture retains its separate readiness, stop/final-drain and interim ownership.
Outside that exact continuing request, if sticky readiness is lost during microphone acquisition, capture, or the STT
request, the component invalidates the session, aborts the owned request signal,
releases media, discards late completion, and emits
speech-transcription-cancelled. Its source-local reason is
runtime-unready, while its canonical/public reason is stt-role-unready. A
busy role uses stt-role-busy in both views. A current provider cancellation
returns the component workflow to idle with local
stt-provider-request-cancelled and canonical/public
stt-provider-transcription-cancelled; destruction uses
component-destroyed in both views. Replacing configuration without an
initialValue during active work uses configuration-replaced in both views.
Stale teardown results remain suppressed. A
current save failure, including AbortError, enters the visible error state.
Readiness loss after transcription has finished does not invalidate an already
pending application save or completion callback: its settlement remains
observable, while any new recording remains gated by current sticky readiness.
Assigning value or calling configure({initialValue}) explicitly supersedes
an in-flight microphone start, STT request, save, or completion. The component
advances its generation, aborts owned STT delivery, releases owned media, emits
speech-transcription-cancelled with
reason:'transcript-replaced', and suppresses
late settlement before publishing the assigned transcript. Assigning transcript
text during active manual recording preserves that recording and changes the transcript
to which the captured segment will be appended.
On a BFCache-persisted pagehide, the component and its owned state remain
live. An active continuous microphone session requests its final stop and
flush; the manual recording lifecycle is unchanged. A persisted pageshow
rerenders the retained authoritative state without
restarting capture, transcription, or activation. Nonpersisted pagehide
retains terminal destruction.
destroy() aborts the state subscription, cancels active work, removes the
activation listener, sets component ready to false, and returns true;
repeated destruction is
idempotent. Destruction is terminal: Start, activation, and Complete remain
disabled and status remains unavailable. voice-transcription-state detail is
the mutable complete {message,state,stt} record, extended during a continuous
session with {capture,processing,queued,errorPhase,error}, where state remains the component
workflow and stt is the authoritative mutable role record. Transcript
completion stays available when STT is unavailable before destruction.
State/text, explicit activation, and request cancellation are normalized;
provider/model authority and media behavior remain external. HTMLImport + DOM;
injected Arcane/provider modules where listed.
Native methods remain subject to the bound app's capabilities. Deep protocol details.
Continuous capture and controls
An explicitly selected native Web Speech provider uses the same ordered
transcript/save queue in either capture mode. Each complete final text segment
skips file transcription and enters the existing append/save stages. The existing
transcript output immediately displays canonical text, queued final segments,
and the current interim hypothesis in order. There is no separate interim pane.
Interim text never reaches value, a save, or a success event. Moving an accepted
final segment into canonical text does not display it twice; saved text and
retry payloads remain owned by the ordered queue. Native stopRecording() returns the drain promise, including final
results emitted during native stop. Browser end stops capture without an
automatic restart. Provider replacement stops native capture while already
accepted final segments retain their ordered saves. Explicit Cancel, transcript
replacement and destruction retain the existing supersession behavior.
This path does not require AudioWorklet or MediaRecorder. A supplied custom
transcribe(file,context) callback keeps the existing audio-clip route.
configure({capture:{mode:'continuous'}}) opts into the SDK's
ContinuousVoiceCapture owner.
The default capture settings are preRollMs:1500, quietMs:2000,
chunkMs:30000, and activityThreshold:0.02. These are audio amplitude and
timing settings: the detector observes sound activity, including background
noise, and does not perform semantic voice-activity recognition. The worklet
keeps a rolling pre-roll, emits no clips containing only inactivity, and does
not repeat samples across periodic segments. If preRollMs exceeds chunkMs,
the first active clip preserves all that pre-roll and may exceed the periodic
duration. Each emitted clip contains a
complete mono Float32 WAV and a session-local sequence starting at one.
The component runs one clip's transcription and save before the next clip's
transcription. Captured clips wait in memory while STT is busy. With the
default persist:true, onSave({transcript,segment,sequence,signal}) or the
existing host.save callback must resolve before that segment's success event
and before the next clip proceeds. Returning false from a continuous save or
completion callback reports that the application did not accept the operation.
Text is preserved completely; the
configured separator joins successful segments. An STT failure retains its
audio. A save failure retains the successful text and exact save payload so
retryTranscription() repeats only that save and does not retranscribe or
append the segment again. Retry resumes the ordered queue after the retained
stage succeeds. Waiting clips remain available if the selected STT role becomes
unready. An in-flight STT request is aborted if its selected provider/model
changes or becomes unready; its clip remains at the failed stage for explicit
retry. A provider result with no text emits
voice-transcription-empty and advances the queue without appending text.
Continuous stopRecording() releases the microphone immediately, flushes the
final active segment, and returns a promise that resolves true after the
queue drains or false while a failure remains. Default manual
stopRecording() keeps its synchronous boolean return. Complete waits for
the continuous flush and all saves before calling
onComplete({transcript,signal}) or the existing host.complete callback.
After a capture interruption, explicit completion can use the retained
transcript once every queued clip has settled. A pending clip failure still
prevents completion. Overlapping completion requests invoke the application
callback once.
cancelRecording() explicitly discards outstanding clips, aborts active
callbacks, and suppresses late text, save, and completion delivery. Callbacks
must observe the supplied signal to cancel their own external effects; an
already accepted external save is not undone. Replacing configuration or the
transcript explicitly cancels a continuous session and its outstanding clips.
clear() refuses a retained queue; use the explicit Cancel action before
discarding it.
voice-transcription-segment and speech-transcription-complete retain their
complete {text,transcript} detail and add sequence for continuous clips.
State events distinguish capture, processing, queued clips, errorPhase,
and the complete error from the existing workflow state and selected stt
role. Errors remain visible and retryable without implicitly discarding audio.
controls:'simple' uses one large primary Start/Stop button, and
showComplete:false hides the secondary Complete action. Standard controls
and the Complete action remain the defaults. labels can supply start,
stop, complete, retry, and cancel strings. Applications can style the
exposed parts primary-action, stop-action, complete-action,
retry-action, cancel-action, transcript, status, controls, and
description without reaching into the component's markup.
Example
<html-import
id="voice-transcription.html"
href="/arcane/components/voice-transcription.html">
</html-import>
After the component is ready, configure the selected capture mode and the application's real persistence callback:
voice.configure({
capture:{mode:'continuous',preRollMs:1500,quietMs:2000,chunkMs:30000},
controls:'simple',
labels:{start:'Start recording',stop:'Stop recording'},
onSave:saveTranscript,
onComplete:completeTranscript
});
weather-widget.html
Overview
Displays normalized current and daily weather with refresh intent.
Public surface
Methods/properties: setWeather(), clear(), destroy().
Events: weather-widget-ready, weather-refresh.
Availability and normalization
Browser and supported native WebViews. Display normalized; provider supplied externally. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="weather-widget.html"
href="/arcane/components/weather-widget.html">
</html-import>
web-navigator.html
Overview
Guards embedded/external navigation and surfaces allow/block/open intents.
Public surface
Methods/properties: configure(), navigate(), currentUrl(), destroy().
Events: web-navigator-ready, web-navigate, web-navigation-blocked, web-open-external.
Availability and normalization
Browser and supported native WebViews. Navigation intent/decision normalized; browser navigation result platform-native. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. Deep protocol details.
Example
<html-import
id="web-navigator.html"
href="/arcane/components/web-navigator.html">
</html-import>
Readiness caveats
header.html and theme-switcher.html do not currently publish a component-specific ready event/property. Consumers can observe html-import-ready for completed fragment execution and then feature-detect their methods. Other fragments publish the exact ready event listed above.