0.28.0
Every @aparte/* package ships at this version (they are released in lockstep).
Minor Changes
-
5839913: A reply now shows the sources it cites: a chip at the end of each cited passage, a card it opens, and the list of sources under the reply. Providers send them with a new
sourcesstream event; a text segment carries them in two new fields,sourcesandcitations.A chip shows the source’s domain, and
+2when two more back the same passage; it sits after the passage’s punctuation, after the bold, link or code the passage ends in, and takes the place of a[1]marker the model wrote. A passage that cannot be found again gets no chip, only its place in the list. It is a button whose label is drawn fromdata-label, so copying the passage copies its words only: its card, shown in the top layer, shows the title as a link, the domain and an excerpt, pages through several sources, and closes on Escape or Tab back to the chip. The bubble lists the reply’s sources under its segments, in a closed<details>. Nothing changes for a reply that cites nothing, and the sources are never sent back to the model.The
sourcesevent’s offsets are into the text the model call streamed; the stream adapter rebases each citation onto the text segment it falls in. The engine now emitsturn-startbefore a non-streamed string answer too, as it does before a streamed call, so nothing of the call before it carries over. A non-streamed answer carries them too: a format adapter’s optionalparseSources(json), and the backend handler addssourcesandcitationsto its JSON. A chip is placed by text in the rendered Markdown, so the same under every Markdown provider;renderCitations(contentEl, segment)places them for a renderer of one’s own. Seven locale keys (sourcesCount,sourcesOne,sourcesCard,sourcePrevious,sourceNext,sourcePosition,opensInNewTab), translated in the nine@aparte/localesbundles. No favicon is fetched.@aparte/core,@aparte/engine,@aparte/locales -
5b3ed37: Register a renderer for a code language with
config.registerCodeLanguageRenderer({ languages, render }), and that language is drawn wherever it appears in a reply, under any Markdown provider: this is the seam@aparte/plugin-katexand@aparte/plugin-mermaiduse.A Markdown provider marks a source with
<code class="language-X">(inside a<pre>for a block;math-display/math-inlinefor maths) and core matches it to the renderer registered for X. Every fence in a streamed reply is already a code segment, so a```mermaidblock is drawn with no Markdown provider at all; maths needs a provider that recognises it.renderCodeLanguages(root)runs the same engine over an element of your own.The drawing goes beside the source and never inside it, so copying, the history the model reads and an incremental provider still writing tokens all keep the source. While a reply streams, a source is drawn as it arrives and the last drawing stays while the next one cannot be made yet; once settled, everything is drawn in full, and drawings are cached, so a framework re-render or a rebuilt block costs nothing. What a renderer returns is inserted as it is, not through the HTML sanitizer, which would strip what a drawing is made of: it has the standing of a segment renderer’s output. A renderer marked
lazydraws only once its source comes near the screen, so reopening a long conversation does not draw every diagram in it at once.@aparte/core -
6ccaf41:
config.highlightCode(code, lang, { fallback: false })now rejects when the highlight provider fails, instead of answering the plain block; without the option nothing changes.Core’s own highlight passes use it. A settled block is no longer highlighted again when a framework re-syncs it, which made a failure permanent: a highlighter that failed once (Shiki still loading its grammars) left the block plain, and marked as done, for good. A failed block now stays plain and unmarked, and the next pass tries it again. Two cases that also kept a block plain are fixed: a code segment re-synced under another config (a wrapper attaches the chat’s config after the first draw) is highlighted again with that config’s highlighter, and a reply whose bubble left the page while its highlight ran gets its colours when it comes back.
@aparte/core -
c9120ab: A reply from a model that reports its sources now lists them under the reply, and from
ai7.0.138 a citation puts a chip after the passage it supports.Nothing to change in your code. The bridge reads
sourceparts fromfullStream(url→{ id, url, title },document→{ id, title }, the filename when there is no title) and ends the turn with onesourcesevent just beforedone; the same URL reported twice is one source. A model that reports none leaves the stream as it was.From
ai7.0.138 atext-endpart may carrycitations, with offsets relative to that text part. The bridge rebases them onto the text of the whole call, so the chip lands after the right sentence; a citation with no offsets supports its whole text part, and itscitedTextbecomes the source’s snippet. The field is read without being typed, so the installedai(^7) builds and runs the same with or without it.A non-streamed request (
stream: false) whose answer cites sources now returns the stream[text, sources, done]instead of a bare string, which cannot carry them; an answer that cites nothing still returns the string.@aparte/provider-ai-sdk -
c9120ab: A reply from an endpoint that cites its sources now shows them: OpenAI and OpenRouter annotations and Perplexity’s source list reach the bubble, and there is a
PERPLEXITYpreset.Nothing to change in your code. The stream parser reads
url_citationannotations (ondelta.annotations, ormessage.annotationsfor a server that streams the whole message shape) and Perplexity’s root-levelcitations/search_results, and ends the turn with onesourcesevent just beforedone. An endpoint that sends neither leaves the stream as it was.The offsets of an annotation are into the whole message text, so the event waits for the end of the stream and an offset past the end of the text is brought back into it. Perplexity sends no offsets and writes
[1],[2]into the text: each marker that names a source becomes a citation that the chip replaces, and a marker that names none stays text. The same URL cited for two passages is one source, two sources on one passage are one citation, and a URL is passed on as the endpoint sent it (core’s renderer refuses ajavascript:link, not the provider).presets.PERPLEXITYpoints athttps://api.perplexity.aiand declares the Sonar models; with the newlistsModels: false,fetchModelsserves them without asking aGET /modelsPerplexity does not have. A[1]inside code is not taken for a marker. A non-streamed answer (stream: false) is read too, through the adapter’s newparseSources.@aparte/provider-openai-compat -
c552926: The showcase answers two more requests: ask it for maths, or for a diagram.
mathreplies with inline and display formulas and a sentence of prices that must stay text;diagramreplies with a```mermaidflowchart. With@aparte/plugin-katexand@aparte/plugin-mermaidinstalled they are drawn; without, they show as TeX and as code. Both come beforecode, whosewhenwould otherwise take “a maths example”.@aparte/provider-scenario -
c9120ab: A scenario turn can now carry sources and citations: a new
{ sources, citations? }step, and a showcase answer that uses it (“why is the sky blue?”, or ask for “sources”).sourceslists the sources a reply draws on andcitationsplaces each one in the text, so a demo or a test can show the chips and the source card without a model that searches. The step goes after the text it cites: a citation’sstartandendare UTF-16 offsets into the text the turn has streamed so far (itstextsteps joined,endexclusive). Source ids are unique within the turn.The showcase gains a
citationsscenario: three paragraphs on Rayleigh scattering citing three sources (en.wikipedia.org, nasa.gov, britannica.com), one passage citing two of them so the chip shows “+1”. It is placed beforecode, so “cite an example” reaches it while “show me the source code” still reachescode; its offsets are found in the passages rather than counted. The showcase’s default message now lists it among the things to ask for.@aparte/provider-scenario -
8c4cd8f: New package:
@aparte/plugin-katexdraws the maths a model writes with KaTeX. CallsetupKatex()and importkatex/dist/katex.min.css.Every
$…$,$$…$$,\(…\)and\[…\]a Markdown provider recognises is drawn as a formula, while the reply streams:@aparte/plugin-markedand@aparte/plugin-streaming-markdownrecognise maths on their own once it is registered. A formula still arriving keeps the last drawing that parsed, so nothing flashes red mid-stream; a finished one that does not parse shows its TeX, quietly. KaTeX is loaded on the first formula, and@aparte/plugin-katex/coretakes a KaTeX you hand it (setupKatexWith). Whatever the options say,truststays off, sizes and macro expansion are capped, and each formula gets its own macros.@aparte/plugin-katex -
d2b6972: Install a maths renderer (
@aparte/plugin-katex) and marked hands it every formula,$…$,$$…$$,\(…\)and\[…\], instead of reading the TeX as Markdown; with none registered, nothing changes.marked read TeX as Markdown:
\,and\\were escapes to it, anda*b*corx_1 + y_2became emphasis. Maths is now claimed by the tokenizer first and written as the placeholder a code-language renderer draws. It turns on by itself when amathrenderer is registered on the config, so there is nothing to configure;math: trueormath: falsein the options forces it. A single$follows Pandoc’s rule, so a price stays a price:$5 and $10is text.A formula never crosses a blank line or a line that opens a block TeX does not start a line with (a fence, a heading, a quote, a rule, an HTML block; a list item after
$$ is the PID), code wins over it (a$$in a fence or a code span stays code), emphasis and strikethrough around a formula close outside it,\(x^*\)included, and escaped brackets such as\[1\]stay brackets. With maths on, rendering runs on a marked instance of the plugin’s own: an extension added to the globalmarkedwithmarked.use()no longer applies, so pass marked options tosetupMarkedProvider(options).While a reply streams, a formula is drawn as it arrives: an unclosed
$$,\[or\(in the block being written is read as one still arriving. A single$is read only once it closes, since until then it could be a price. Andremend, which completes the block being written, no longer sees the TeX: it used to turn\[ a+binto a link.@aparte/plugin-marked -
8c4cd8f: New package:
@aparte/plugin-mermaiddraws the```mermaidfences a model writes as diagrams. CallsetupMermaid().It works with any Markdown provider, or none: every fence in a streamed reply is already a block of its own. The diagram is redrawn as its fence arrives, at most every 300 ms, keeping the last version that parsed; once the fence closes, one that does not parse shows a note and its source. Each diagram is an
<img>of its SVG, so no script or style a model wrote into it can reach the page, and Mermaid runs withsecurityLevel: 'strict'and HTML labels off, which a diagram’s own%%{init}%%cannot change. Colours follow the chat’s theme. Mermaid is loaded on the first diagram, a diagram is drawn only once it comes near the screen, and@aparte/plugin-mermaid/coretakes a Mermaid you hand it (setupMermaidWith).@aparte/plugin-mermaid -
722c161: With a maths renderer registered (
@aparte/plugin-katex), streamed formulas are now drawn; with none registered,$and\(now stay in the text instead of disappearing.The plugin now depends on
@paulrichez/streaming-markdown0.3.2, which reads maths by Pandoc’s rules —$5 and $10is two prices, a formula ends at a blank line or a line that opens a block, and a one-line$$x$$no longer opens a block that swallows the rest of the reply — and takes a{ math }option. The plugin turns maths on when amathrenderer is registered, decided once per reply.Each formula is written as
<code class="language-math math-inline">ormath-display, the placeholder@aparte/plugin-markedwrites and core’s code-language engine draws, markeddata-aparte-openuntil its closer arrives. A display formula opened by$$or\[on its own line is drawn as it arrives; any other once its closer has come. A display block that a blank line ends before its closer, and a formula the reply ended in the middle of, go back to text, and one that holds only a number (\[1\], a reference) is written back in its brackets, as plugin-marked reads it. Without a maths renderer the parser reads no maths at all: 0.3.0 wrote$x$as an<equation-inline>element and dropped its dollars.@aparte/plugin-streaming-markdown
Patch Changes
-
5d531f2: A finished reply is no longer re-rendered or re-highlighted on every framework render, and
setHtmlSanitizernow redraws what is already on screen.A framework host re-sends
{ content, isStreaming: false }to the last message on every render. Under a one-shot Markdown provider each of those rebuilt the whole element from the same string, throwing away what had been drawn on top of it, a highlighted fence for one, only to draw it again; and a code block was highlighted again from the same source. The settle now remembers what it wrote, under which config, and leaves an identical render in place; a code block re-sent unchanged keeps its highlight; and a block a highlighter has replaced is marked, so a later pass does not highlight it a second time as a block with no language. Changed content, another config, or a provider changed since, still redraws.Changing the sanitizer used to apply only to what was rendered afterwards. It now counts as a rendering change, like setting a Markdown or highlight provider: messages already drawn go through the new one, and the config’s listeners are told, synchronously. Passing the sanitizer already set changes nothing and tells no one.
@aparte/core -
2f1ae3e: A fenced code block still arriving now carries
isStreaming: true, so it is coloured line by line as it streams; a customcoderenderer sees the flag too.The parser marked a registered block as streaming but never a fence, and the code renderer read the missing flag as finished: the whole-content highlight ran again on every token, and the progressive path built for a streaming fence never ran. With the flag set, two highlight passes can be in flight at once, so the settled one now takes precedence over a streaming one that lands late, and of two settled highlights the newer wins.
The copy button on a code block copies the block’s source, rather than the text the pane happens to show.
@aparte/core -
85c68c4: If you replaced the sanitizer with
DOMPurify.sanitize, chain it in front of the built-in one instead:setHtmlSanitizer((html) => defaultSanitizer(DOMPurify.sanitize(html))).The Markdown guide and the
setHtmlSanitizerexample used to show DOMPurify on its own, as the hardened option.setHtmlSanitizerreplaces the built-in sanitizer, though, and DOMPurify’s defaults are written for any page rather than for a chat. Measured on DOMPurify 3.4.17, they keep seven of nine things the built-in one refuses in a model’s HTML: inline layout styles (a full-screen overlay), core’saparte-classes (a forged approval button),--aparte-*properties (the theme repainted from inside a reply),<form>and<button>, a password<input>,id(DOM clobbering), and an external link left to navigate the chat’s own frame. Chained in front ofdefaultSanitizer, all nine are refused again.No behaviour changes in core:
defaultSanitizerwas already exported. The documentation changes, and so does the warningsetHtmlSanitizer(null)prints.@aparte/core
Version-only bumps (no changes of their own): @aparte/runner-ag-ui, @aparte/runner-n8n, @aparte/provider-transformers, @aparte/plugin-approval, @aparte/plugin-artifacts, @aparte/plugin-ask-user, @aparte/plugin-compaction, @aparte/plugin-model-selector, @aparte/plugin-shiki, @aparte/plugin-titler, @aparte/angular, @aparte/react, @aparte/svelte, @aparte/vue, @aparte/docs-mcp.
0.28.1
Every @aparte/* package ships at this version (they are released in lockstep).
Patch Changes
-
63a5a01: A transcript that got shorter just after the chat scrolled itself no longer switches auto-follow off; the view no longer stops short of the bottom at the end of a reply on a slow WebKit.
The viewport reads a
scrollTopdecrease on a shorter transcript, within a second of its own scroll and with no reader input, as the engine clamping to a smaller maximum — the rule its own comment states. The code only applied it within 100 ms of a transcript mutation it had observed. Measured on CI WebKit: a settling reply dipped (1201 → 1068 px at the event), WebKit clamped 666 → 419, and the scroll event came 104 ms after the last mutation — so it was read as the reader going up, and the view stayed 409 px short for good. A jump with no shrink behind it, a reader’s hand, a held pointer and a jump outside that second still disarm as before.@aparte/core -
d7f8fe0: An LM Studio server that cannot be reached no longer gets a second request to its older
/api/v0/modelsAPI when the context window is read.The fallback is for a server that answers without the v1 REST API (an HTTP error); a request that got no answer at all — the server is down, or the page is being left — now ends the probe with no window, as any other failed probe does. In WebKit the second request, sent while a page was being left, surfaced as a page error.
@aparte/provider-openai-compat -
9a2ce96: A diagram still arriving now shows a placeholder box instead of its source, then draws each node as soon as its line is complete; it no longer flashes an empty image.
Before, a fence streamed its Mermaid source as text, then the header alone (
flowchart LR, anaccTitle) drew an empty 16×16 image in its place, and nothing changed until the whole of a half-written line parsed: characters, then a blank, then the diagram. Now its first frame is the skeleton recipe, each later frame draws the source up to its last complete line, and a frame whose drawing would paint nothing keeps what is shown. A closed fence is drawn as before;progressive: falsestill waits for it.@aparte/plugin-mermaid
Version-only bumps (no changes of their own): @aparte/engine, @aparte/runner-ag-ui, @aparte/runner-n8n, @aparte/provider-ai-sdk, @aparte/provider-scenario, @aparte/provider-transformers, @aparte/plugin-approval, @aparte/plugin-artifacts, @aparte/plugin-ask-user, @aparte/plugin-compaction, @aparte/plugin-katex, @aparte/plugin-marked, @aparte/plugin-model-selector, @aparte/plugin-shiki, @aparte/plugin-streaming-markdown, @aparte/plugin-titler, @aparte/angular, @aparte/react, @aparte/svelte, @aparte/vue, @aparte/locales, @aparte/docs-mcp.
0.28.2
Every @aparte/* package ships at this version (they are released in lockstep).
Patch Changes
- 2d108c1: The npm page of each of these packages now links to its docs page; nine of them pointed at
/plugins/…addresses that only redirect since the docs moved, anddocs-mcppointed at the site’s home.@aparte/plugin-approval,@aparte/plugin-artifacts,@aparte/plugin-ask-user,@aparte/plugin-compaction,@aparte/plugin-marked,@aparte/plugin-model-selector,@aparte/plugin-shiki,@aparte/plugin-streaming-markdown,@aparte/plugin-titler,@aparte/docs-mcp
Version-only bumps (no changes of their own): @aparte/core, @aparte/engine, @aparte/runner-ag-ui, @aparte/runner-n8n, @aparte/provider-ai-sdk, @aparte/provider-openai-compat, @aparte/provider-scenario, @aparte/provider-transformers, @aparte/plugin-katex, @aparte/plugin-mermaid, @aparte/angular, @aparte/react, @aparte/svelte, @aparte/vue, @aparte/locales.
0.28.3
Every @aparte/* package ships at this version (they are released in lockstep).
Patch Changes
-
Nothing to change in your code: this version carries what 0.28.2 announced, which never reached npm.
0.28.2’s release stopped at its build step in CI, before anything was published, so the version after 0.28.1 on npm is this one. Its changes are 0.28.2’s: each package’s npm page links to its docs page.
@aparte/core
Version-only bumps (no changes of their own): @aparte/engine, @aparte/runner-ag-ui, @aparte/runner-n8n, @aparte/provider-ai-sdk, @aparte/provider-openai-compat, @aparte/provider-scenario, @aparte/provider-transformers, @aparte/plugin-approval, @aparte/plugin-artifacts, @aparte/plugin-ask-user, @aparte/plugin-compaction, @aparte/plugin-katex, @aparte/plugin-marked, @aparte/plugin-mermaid, @aparte/plugin-model-selector, @aparte/plugin-shiki, @aparte/plugin-streaming-markdown, @aparte/plugin-titler, @aparte/angular, @aparte/react, @aparte/svelte, @aparte/vue, @aparte/locales, @aparte/docs-mcp.
0.29.0
Every @aparte/* package ships at this version (they are released in lockstep).
Minor Changes
-
324d2ba: New package:
@aparte/plugin-cardsdraws a tool’s result as a rich card instead of a row. Import one card’s entry and call its setup, e.g.setupWeatherCard({ tool: 'get_weather', map }).Eleven cards, each its own entry so an app ships only the ones it imports:
weather,items(articles and search results),product,place,stats(key figures),order(orders and bookings),stock(a quote with its line or candlestick chart),plan(an agent’s task list, updated in place),score(matches),media(pictures, videos, sounds, with a lightbox) andlink(a page preview). Each has three or four variants, chosen by name or by a function of the data, and a reader that already takes the shapes the usual APIs return (Open-Meteo, Shopify, Stripe, Google Places, Yahoo Finance, API-Football, Open Graph…);mapturns your tool’s own fields into the card’s. While the call runs the card shows its skeleton; a call refused, stopped or failed is one line that says so, never a card. Every card is also acardsegment (weatherCard.segment(data)) with a fallback sentence for a text-only reader, and its words come in the ten languages of@aparte/locales, rewritten in place on a language switch.A card can answer back: with an
onChange, the stock card draws range buttons over its chart, and whatonChangereturns is drawn in place — the same element, the focus kept. Changes run one at a time, each from the data the one before left, and what they returned is kept while the page lives: a turn ending, the conversation saved or reopened, in every framework, draws the card as the person left it. A button the app declares (actions) can open a link, send a message or only report; a button read from a tool’s result can only be a web link or anid, never text sent as the person. Setting a card up twice stacks: the newer setup draws, and removing the older one leaves it in place. The root entry is the kit the cards are made with (defineCard,segmented,toggle,slider,carousel,sparkline, theIntlformatters), for a card of your own that behaves the same way.@aparte/plugin-cards -
324d2ba: New package:
@aparte/plugin-chartjsdraws the```chartjsfences a model writes, and a tool’s result, as Chart.js charts. CallsetupChartjs(); passtool(andmap) to draw a tool’s result in place of its row.The fence’s body is Chart.js’ own
{ type, data, options }as JSON (```chart.jsworks too), drawn while it streams. Each chart gets the chat’s look in its own config —Chart.defaultsis never touched — and is recoloured on a light/dark switch. It is afigurewith a hidden table of its numbers. A config from a model carries no code: its ownpluginslist is dropped, and so are strings where Chart.js would call a function and looping animations; its size is bounded — points, labels and datasets bymaxPoints(5000 by default), a scale to a hundred ticks, the hidden table to 10 000 cells (readChartConfigis the reader).chart.js/autois loaded on the first chart, and@aparte/plugin-chartjs/coretakes aChartyou registered yourself (setupChartjsWith).@aparte/plugin-chartjs -
324d2ba: New package:
@aparte/plugin-echartsdraws the```echartsfences a model writes, and a tool’s result, as Apache ECharts charts. CallsetupECharts(); passtool(andmap) to draw a tool’s result in place of its row.The fence’s body is ECharts’ own
optionas JSON, drawn while it streams from the part that has arrived, at most every 300 ms. The chart wears the chat’s tokens as an ECharts theme, recoloured in place on a light/dark switch, with series colours that stay apart for colour-blind readers. It is drawn as SVG, as afigurewith ECharts’ own description and a hidden table of its numbers. A model’s option cannot write HTML, load a picture, open a link or download a file: tooltips are forced to rich text; images, links,saveAsImage,dataView, a CSSurl()however it is spelled and a dataset filter’s regular expression are taken out; a colour key takes colour syntax only (sanitizeEChartsOption). ECharts is loaded on the first chart, and@aparte/plugin-echarts/coretakes an ECharts build you hand it (setupEChartsWith).@aparte/plugin-echarts
Version-only bumps (no changes of their own): @aparte/core, @aparte/engine, @aparte/runner-ag-ui, @aparte/runner-n8n, @aparte/provider-ai-sdk, @aparte/provider-openai-compat, @aparte/provider-scenario, @aparte/provider-transformers, @aparte/plugin-approval, @aparte/plugin-artifacts, @aparte/plugin-ask-user, @aparte/plugin-compaction, @aparte/plugin-katex, @aparte/plugin-marked, @aparte/plugin-mermaid, @aparte/plugin-model-selector, @aparte/plugin-shiki, @aparte/plugin-streaming-markdown, @aparte/plugin-titler, @aparte/angular, @aparte/react, @aparte/svelte, @aparte/vue, @aparte/locales, @aparte/docs-mcp.
0.29.1
Every @aparte/* package ships at this version (they are released in lockstep).
Patch Changes
-
Add
setupCardFences(): a```card-weathercode block of JSON in an answer is drawn as the weather card (every card has itscard-<name>language).For backends that send only text and keep their tool calls to themselves — a workflow engine, a server that streams its answer, a model with no tools.
loadmaps a card’s name to its entry (() => import('@aparte/plugin-cards/weather')), fetched the first time a block names it. While the block streams a placeholder holds its place; a block whose JSON does not parse, or whose card the page cannot draw, shows its source. Works with any Markdown provider, or none.@aparte/plugin-cards
Version-only bumps (no changes of their own): @aparte/core, @aparte/engine, @aparte/runner-ag-ui, @aparte/runner-n8n, @aparte/provider-ai-sdk, @aparte/provider-openai-compat, @aparte/provider-scenario, @aparte/provider-transformers, @aparte/plugin-approval, @aparte/plugin-artifacts, @aparte/plugin-ask-user, @aparte/plugin-chartjs, @aparte/plugin-compaction, @aparte/plugin-echarts, @aparte/plugin-katex, @aparte/plugin-marked, @aparte/plugin-mermaid, @aparte/plugin-model-selector, @aparte/plugin-shiki, @aparte/plugin-streaming-markdown, @aparte/plugin-titler, @aparte/angular, @aparte/react, @aparte/svelte, @aparte/vue, @aparte/locales, @aparte/docs-mcp.
0.29.2
Every @aparte/* package ships at this version (they are released in lockstep).
Patch Changes
-
df050ad: A card written as a
```card-<name>block is drawn on its own, without the code card’s header, language label and copy button around it.Core: a code-language renderer can say
bare: true— its drawing then stands for the whole fenced block, and the code card around it goes. Diagrams, charts and maths keep their card and the copy of their source.setupCardFences()sets it.A link in the person’s own bubble (an email or a URL they typed) now takes the bubble’s text colour, underlined: it was drawn in the link colour, which on a bubble filled with the primary was the bubble’s own colour.
@aparte/core,@aparte/plugin-cards
Version-only bumps (no changes of their own): @aparte/engine, @aparte/runner-ag-ui, @aparte/runner-n8n, @aparte/provider-ai-sdk, @aparte/provider-openai-compat, @aparte/provider-scenario, @aparte/provider-transformers, @aparte/plugin-approval, @aparte/plugin-artifacts, @aparte/plugin-ask-user, @aparte/plugin-chartjs, @aparte/plugin-compaction, @aparte/plugin-echarts, @aparte/plugin-katex, @aparte/plugin-marked, @aparte/plugin-mermaid, @aparte/plugin-model-selector, @aparte/plugin-shiki, @aparte/plugin-streaming-markdown, @aparte/plugin-titler, @aparte/angular, @aparte/react, @aparte/svelte, @aparte/vue, @aparte/locales, @aparte/docs-mcp.
0.29.3 Latest
Every @aparte/* package ships at this version (they are released in lockstep).
Patch Changes
-
89e03ee: A card of your own (
defineCard) is drawn from its```card-<name>block even when it is set up aftersetupCardFences(), and a block can pick the card’s layout with"variant"in its JSON.- plugin-cards:
setupCardFences()hears of each card set up on its config from then on and draws its blocks too; before, only the cards known when it started were, and a card defined later showed its source. - plugin-cards:
"variant": "<name>"in a block’s JSON picks that layout when it is one of the card’s; any other value is the card’s data as before. - plugin-cards: a product alone in its answer is drawn with a landscape picture, and with a low band when it has none. The square frame, the width of a chat column, made the card taller than the chat’s view, and empty when the product had no picture. In a row of products the tiles stay square.
- core, plugin-cards: a message with padding and a card with its border no longer run past their column. Both took
max-width: 100%and counted padding or border outside it, so a bubble clipped their right edge. - plugin-cards: a change a live card was still waiting on when the conversation was left and opened again lands on the card now shown. It was drawn on the element the person had left, and the card they came back to kept the old value until the next redraw.
@aparte/core,@aparte/plugin-cards
- plugin-cards:
Version-only bumps (no changes of their own): @aparte/engine, @aparte/runner-ag-ui, @aparte/runner-n8n, @aparte/provider-ai-sdk, @aparte/provider-openai-compat, @aparte/provider-scenario, @aparte/provider-transformers, @aparte/plugin-approval, @aparte/plugin-artifacts, @aparte/plugin-ask-user, @aparte/plugin-chartjs, @aparte/plugin-compaction, @aparte/plugin-echarts, @aparte/plugin-katex, @aparte/plugin-marked, @aparte/plugin-mermaid, @aparte/plugin-model-selector, @aparte/plugin-shiki, @aparte/plugin-streaming-markdown, @aparte/plugin-titler, @aparte/angular, @aparte/react, @aparte/svelte, @aparte/vue, @aparte/locales, @aparte/docs-mcp.