0.19.3 Latest
Every @aparte/* package ships at this version (they are released in lockstep).
Patch Changes
-
d898de8: Per-chat theming now works on the React, Vue and Svelte chat root, and your own token overrides on
aparte-chatwin whatever order the stylesheets load in.The derived layer (the inks, the scales, the bubble colours) is worked out again on
[data-aparte-chat], the root the three wrappers render, so a chat given its own--aparte-primarythere gets its own user bubble and inks. Every anchor of that layer but:hostnow weighs nothing (:where()), like the palette:aparte-chat { --aparte-primary-ink: … }no longer loses when core’s sheet loads after yours, or on a chat that carriesdata-aparte-theme.If you theme a React, Vue or Svelte chat by setting a DERIVED token (a surface step, a radius or size step,
--aparte-link-color, a scale) on:rootor an element around the chat, list[data-aparte-chat]besideaparte-chatin that rule: the root now works those tokens out again, asaparte-chatalways did, so a value set above it no longer reaches inside. Masters such as--aparte-primaryor--aparte-radius-unitset on:rootare unaffected.@aparte/core -
866e468: The action bar no longer overlaps the branch picker’s next arrow, which is back to a full 24px target.
The bar pulls itself 6px toward the start of the line so its first icon lines up with the text above; after a visible branch picker that ran it 1.5px over the picker’s last arrow (axe target-size: 22.5px instead of 24px). The pull now applies only when the bar opens the row.
@aparte/core -
e57013a: Chrome 111, Safari 16.2, Firefox 121 and Samsung Internet 22 are supported again: the accent inks and the composer’s padding now fall back where relative colour syntax or the
lhunit is missing.Each
--aparte-*-inkis declared first as its accent mixed 40 / 60 with the text colour (on the default palette the worst case, a pressed soft wash on surface-3, measures 4.75:1 in light, and 6.58:1 on the page background), then, under@supports (color: oklch(from red l c h)), as the accent at the set lightness it was before. The editor padding reads the line height asembefore@supports (height: 1lh)takes over, to the same pixel. Browsers with both features draw exactly what they drew.@aparte/core -
3e3a7ef: The conversation list now has an accessible name, “Conversations” by default, taken from the new
conversationListlocale key.<aparte-conversation-list>is a navigation landmark, and a page with a second one (a site’s own nav) had two unnamed landmarks (axe landmark-unique). The name follows the locale; anaria-labeloraria-labelledbythe app sets, before or after the list connects, keeps priority. French: « Conversations ».@aparte/core,@aparte/locale-fr -
ae56657:
AparteCodeSegment.showLineNumbersandAparteErrorSegment.stackare deprecated: nothing reads them, and they will be removed in a later minor.No renderer or stylesheet draws line numbers, and the error renderer draws
contentanddetailsonly, so setting either field changed nothing. Put a stack trace indetailsto show it. Code that sets them keeps compiling until the removal, which a later changeset will announce.@aparte/core -
4a4cad8: Opening a tool row, a reasoning block or any
<details>in the transcript no longer leaves a blank under the reply.The bottom spacer, which lets the person’s message rise to the top, is now recomputed when a disclosure opens or closes. It used to keep its closed-row size, so opening a tool row lengthened the transcript by the row’s height (176px on the examples). Closes #105.
@aparte/core -
ddfaaae: A question or approval panel no longer steals the focus from a reader writing elsewhere, no longer lands on “Approve” while you type, and always announces itself.
- From a field outside the chat, an iframe or another chat, the focus stays where it is, and a polite status in the composer says the question.
- From the chat’s own editor (typing the next message while a reply streams), the focus goes to the panel itself, named by the question, not to its first option: Enter no longer approves a tool call by accident.
- From a button (the chat’s own or one of yours beside it) or from nowhere (a click in Safari, a screen reader’s activation), the focus goes to the first control, without scrolling the page when it came from nowhere.
- The focus is followed through open shadow roots, so a field inside a web component counts as a field.
- On close it goes back to whoever had it, or to the composer when that is gone or was
<body>. - An approval’s options are described by the question (
aria-describedby).@aparte/core
-
2f69e76: Eight types a public type already named are now exported: six element attribute interfaces,
AparteRequestMetaandAparteConversationsListener.AparteContextAttributes,AparteIconAttributes,AparteScrollRailAttributes,AparteSidebarAttributes,AparteSplitAttributesandAparteSuggestionsAttributeswere generated but missing from the package entry;AparteRequestMetais the type ofAparteChatRequest._meta;AparteConversationsListeneris whatAparteConversationManager.subscribetakes. A consumer can now name all of them. Types only: nothing changes at run time.@aparte/core -
3e474c5: A framework chat streaming with
injectTokenStreamnow shows Stop, stops on it, and saves the reply: the turn sends its own lifecycle events.injectTokenStream(React, Vue, Svelte, Angular) dispatchesaparte-message-startwhen it begins andaparte-message-done,-abortedor-errorwhen it ends, on the chat, stamped with its id, asAparteClientdoes. The composer’s Stop (aparte-abortfor this chat) stops the stream; another chat’s Stop does not. Code that sent these events by hand aroundinjectTokenStreamcan drop them; left in place, the composer and the conversation manager see each event twice, which they tolerate.@aparte/core -
04180a3: Four doc comments now say what the code does: the auto-compact rule, the titler’s default word count, the bubble’s
timestamp, and the composer’s internal bus.<aparte-context auto-compact>asks for a compaction on each turn that ends indanger, one request at a time, not once per crossing.setupTitler’sbudget, omitted, does not mean six words: the model keeps, among its six best-scored words, those it is at least half sure of, never fewer than three, and every word of a message of four words or fewer.- The bubble’s
timestampattribute no longer names a private method. - The composer’s
_on/_emitare marked@internaland leave the generated reference; from outside, listen foraparte-composer-change.@aparte/core,@aparte/plugin-titler
-
778202f: Neutral and secondary buttons draw their label in a darker ink on the ghost, outline and soft fills, so they meet AA contrast.
They were the two intents without an ink of their own, so their label read the fill colour: 4.19:1 for the neutral soft button, and 2.71:1 for secondary text on the page, against the 4.5:1 AA asks. They now derive
--aparte-neutral-inkand--aparte-secondary-inkthe way the five accents derive theirs; the neutral soft button measures 6.99:1 in light and 9.1:1 in dark. A button that sets only--aparte-btn-intentis unchanged.@aparte/core -
44aaee4: A button with no intent class now inks like a neutral one: an intent-less
--solidbutton and the selected segment of an intent-less or--surfacegroup meet AA contrast.Such a button is neutral, but it kept the dark constant ink instead of the ink derived from its fill, so its label read dark on the neutral fill at 3.38:1 in light. It now measures 5.50:1 in light (white on the fill) and 7.27:1 in dark. If you set
--aparte-btn-inkto change that label, set--aparte-on-neutralinstead: where relative colour syntax exists, the intent-less button no longer reads--aparte-btn-ink. Browsers without it keep the previous ink.@aparte/core -
0320655: The status line and a live reasoning block now speak the chat’s locale: no more English “Typing” or “Thinking” under a French locale.
<aparte-chat-status>withouttextnames itself, and tells a screen reader, from thetypingkey instead of an English literal, and follows a locale change. A reasoning block streamed from a model no longer carries a hard-codedlabel: 'Thinking', so the renderer names it from thethinkingkey and relabels it on a locale change, like a block restored from history. The English defaults lose their ellipsis, because they also name a block that is over:thinkingis “Thinking”,typingis “Typing”; in French,thinkingis « Réflexion ». Alabelyou set on a segment still wins. If you readsegment.labelon a streamed reasoning segment, it is nowundefined: fall back to the locale’sthinking, as the renderer does. A test matching “Thinking…” or “Typing…” (or « Réflexion en cours… ») reads the new words.@aparte/core,@aparte/locale-fr -
34160c3: A suggestion chip that sends now hands the focus to the composer, instead of dropping it to the page when its row hides.
With
empty-only, the row hides as soon as the message is on its way, and the chip a keyboard user had pressed went with it: the focus fell to<body>. When the chip held the focus, the composer now takes it after the send. A click that did not focus the chip changes nothing.@aparte/core -
5c777d5: Models now run on the graphics card by default when the browser has a WebGPU adapter, as documented; before,
'auto'fell back to WASM everywhere. To keep them on the processor, callsetComputeDevice('wasm').The worker resolves
'auto'itself, once:'webgpu'whennavigator.gpu.requestAdapter()answers,'wasm'otherwise. It is not passed on to Transformers.js, which would try WebNN first. A runner now receives the resolved device inctx.device. If a model then fails to load on WebGPU (a blocklisted driver, an operator the backend lacks), it is loaded again on WASM and the console says so; a forcedsetComputeDevice('webgpu')fails as asked.setComputeDevice('webgpu' | 'wasm')still forces one; there is no need to call it to turn the graphics card on.@aparte/provider-transformers -
6231952: The question on an answered receipt is drawn in the neutral ink, so it meets AA contrast on its success tint.
It used the muted text colour, which measured 4.29:1 on the success mark against the 4.5:1 AA asks. It now reads
--aparte-neutral-ink, which measures 7.17:1 in light and 8.56:1 in dark, and keeps the muted colour with a core that does not declare that token.@aparte/plugin-ask-user
Version-only bumps (no changes of their own): @aparte/engine, @aparte/runner-ag-ui, @aparte/provider-ai-sdk, @aparte/provider-openai-compat, @aparte/provider-scenario, @aparte/plugin-approval, @aparte/plugin-artifacts, @aparte/plugin-compaction, @aparte/plugin-marked, @aparte/plugin-model-selector, @aparte/plugin-shiki, @aparte/plugin-streaming-markdown, @aparte/angular, @aparte/react, @aparte/svelte, @aparte/vue, @aparte/docs-mcp.