Capability first · transport second

Arcane runtime component catalog

Arcane components are reusable HTML fragments loaded through the shared 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.

SDK 0.97.1Runtime 0.8.12Protocol arcane/1
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

html
<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-ready
assistant-opened
assistant-closed
assistant-send
assistant-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-ready
calculation-complete
calculation-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-ready
chart-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-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
conversation-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-ready
communication-send
communication-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-ready
dashboard-config-opened
dashboard-config-closed
dashboard-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-ready
data-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-ready
directory-picker-change
directory-picker-cancel
directory-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-ready
document-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-ready
file-drop-selected
file-drop-progress
file-drop-state
file-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-ready
file-inspector-action
file-inspector-change
file-inspector-cleared
file-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-ready
file-manager-select
file-manager-open
file-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-ready
integration-settings-save
integration-settings-close
integration-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-ready
local-ai-status-dismissed
local-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-ready
markdown-document-state
markdown-document-loading
markdown-document-rendered
markdown-document-empty
markdown-document-error
markdown-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-ready
markdown-editor-change
markdown-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-ready
media-load
media-error
media-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()
running
opened
modal-ready
modal-opened
modal-closed
modal-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-ready
output-panel-state
output-panel-change
output-panel-action
output-panel-error
output-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-ready
preferences-change
preferences-submit
preferences-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()
state
ready
pwa-install-ready
pwa-install-change
pwa-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-ready
record-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-ready
relationship-node-open
relationship-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-ready
screen-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-ready
source-code-viewer-state
source-code-viewer-state-loading
source-code-viewer-state-ready
source-code-viewer-state-empty
source-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-ready
source-explanation-save
source-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()
availability
muted
initialMuted
recognitionLanguage
displayTranscription
componentReady
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
speech-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-ready
summary-strip-change
summary-strip-select
DOM-normalized
table.html Builds and updates a simple header/body table. buildHeader()
buildTable()
destroy()
table-ready
header-update
body-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-ready
task-progress-started
task-progress-change
task-progress-complete
task-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-ready
terminal-submit
terminal-interrupt
terminal-clear
terminal-session-new
terminal-session-close
terminal-session-select
terminal-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-ready
theme-preview
theme-save
theme-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-ready
inbox-refresh
thread-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-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
speech-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-ready
weather-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-ready
web-navigate
web-navigation-blocked
web-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
<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
<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
<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
<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
<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_ABORTED for 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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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:

html
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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:

  • modes is an ordered array of the available identifiers system, light, dark, and custom. It selects both visible choices and DOM/keyboard order. Omitted modes retains the current presentation; an empty array displays no choices. Unknown or repeated identifiers throw TypeError before changing the presentation.
  • labels is a partial record of complete string labels keyed by those mode identifiers. Omitted labels keep their current text. Text is assigned through textContent, never interpreted as markup or reduced to initials. A label for a built-in mode that is not a string throws TypeError.
  • 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
<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:

css
#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
<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
<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:

javascript
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
<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
<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.