AparteConfig & core API
The Elements, CSS variables and
@aparte/engine pages are generated references for those surfaces.
This page is the companion for the single biggest surface that has none: the core JS
API — AparteConfig, AparteClient, and the transports. Every signature below is
copied from packages/core/src; where a type is complex it is simplified for
readability without changing its meaning — follow the source links for the full shape.
AparteConfig
Section titled “AparteConfig”AparteConfig is a global singleton instance of the AparteConfigClass
(packages/core/src/config/aparte-config.ts) — the “Invisible but Flexible” dependency-injection
hub. Everything below is a method on it, e.g. AparteConfig.registerAIProvider(...).
import { AparteConfig } from '@aparte/core';Most setters call an internal _notify(), which re-renders already-mounted components
(and dispatches a window aparte-config-change event) — so a live change (theme
switch, locale swap, new icon set) propagates without a reload.
Providers, keys & transport
Section titled “Providers, keys & transport”Registers the AI vendors the chat can talk to, how their API keys are resolved, and where the request is sent.
registerAIProvider(...providers: AparteAIProvider[]): void— register one or moreAparteAIProviderimplementations (e.g. from@aparte/provider-openai-compat).unregisterAIProvider(id: string): void— remove a provider by id.getAIProviders(): AparteAIProvider[]— all registered providers, filtered bymodelConfig.enabledProvidersif set.getAIProvider(id: string): AparteAIProvider | undefined— a single provider by id.refreshProviderModels(providerId: string): Promise<AparteAIModel[]>— resolve the key then call the provider’sfetchModels.setKeyProvider(provider: AparteKeyProvider): void— register a function that resolves an API key for a given provider id.getKey(providerId: string): Promise<string | undefined>— read the key for a provider via the registered key provider.setTransport(transport: AparteTransport): void— set where chat requests go and how auth is handled. Defaults toDirectTransport.getTransport(): AparteTransport— the active transport.
Renderers & render hooks
Section titled “Renderers & render hooks”Swap the markup of specific chat regions while keeping their built-in behavior (streaming,
show/hide, class hooks). Each accepts string | HTMLElement and null clears it.
setStatusRenderer(renderer: AparteStatusRenderer | null): void/getStatusRenderer(): AparteStatusRenderer | null— the typing indicator’s inner markup.setErrorRenderer(renderer: AparteErrorRenderer | null): void/getErrorRenderer(): AparteErrorRenderer | null— the content of an error bubble.setAttachmentRenderer(renderer: AparteAttachmentRenderer | null): void/getAttachmentRenderer(): AparteAttachmentRenderer | null— the chip for each user-message attachment.setSiblingNavRenderer(renderer: AparteSiblingNavRenderer | null): void/getSiblingNavRenderer(): AparteSiblingNavRenderer | null— the‹ N / M ›branch-position indicator.setBubbleShellRenderer(renderer: AparteBubbleShellRenderer | null): void/getBubbleShellRenderer(): AparteBubbleShellRenderer | null— the structural skeleton of<aparte-chat-bubble>(advanced; must honor the.aparte-messageclass-hook contract).setAvatarProvider(provider: AparteAvatarProvider | null): void/getAvatarProvider(): AparteAvatarProvider | null— fills the avatar host element with custom DOM (e.g. a mounted framework component).setArtifactPreviewBuilder(builder: AparteArtifactPreviewBuilder): void/getArtifactPreviewBuilder(): AparteArtifactPreviewBuilder | undefined— builds thesrcdocHTML for an artifact preview iframe.
Markdown, highlight & sanitizer
Section titled “Markdown, highlight & sanitizer”Controls how assistant text becomes HTML, and what scrubs that (untrusted, LLM-authored)
HTML before it is injected via innerHTML.
setMarkdownProvider(fn: AparteMarkdownProvider): void— a one-shot Markdown renderer ((raw: string) => string).renderMarkdown(raw: string): string— render Markdown via the registered provider (sanitized), falling back to HTML-escape +<br>.setStreamingMarkdownProvider(fn: AparteStreamingMarkdownProvider): void— an incremental renderer factory bound to a target element, used while a message is still streaming.createStreamingMarkdownRenderer(target: HTMLElement): AparteStreamingMarkdownRenderer | null— instantiate the streaming renderer fortarget, ornullif none is registered.setHighlightProvider(fn: AparteHighlightProvider): void— a syntax highlighter, sync or async:(code, lang) => string | Promise<string>.hasHighlightProvider(): boolean— whether a highlighter is registered.highlightCode(code: string, lang: string): Promise<string>— highlight via the registered provider (sanitized), falling back to a plain<pre><code>.setHtmlSanitizer(sanitizer: AparteSanitizer | null): void— replace the built-in allowlist sanitizer, or passnullto disable it (trusted content only).sanitizeHtml(html: string): string— run the active sanitizer over provider-produced HTML.
System prompt
Section titled “System prompt”setSystemPrompt(template: string | undefined): void— set the system-prompt template ({{key}}placeholders).getSystemPromptTemplate(): string | undefined— the raw template, unresolved.setSystemPromptVarsProvider(fn: AparteSystemPromptVarsProvider): void— a function returning the{{key}}→ value map, called at request time.resolveSystemPrompt(): string | null— the template with all placeholders substituted, ornullif none is set.
Locale
Section titled “Locale”Translatable UI strings (composer placeholder, Copy/Retry buttons, “thinking…”, etc.).
English ships in core as DEFAULT_LOCALE; other languages are injected.
setLocale(locale: AparteLocale): void— replace the active locale.getLocale(): AparteLocale— the active locale.extendLocale(translations: Partial<AparteLocale>): void— merge partial translations onto the current locale (e.g. for a plugin registering its own strings).t(key: keyof AparteLocale): string— look up a translated string, falling back toDEFAULT_LOCALE.
See the Localization guide.
Icons & skeleton
Section titled “Icons & skeleton”setIconProvider(provider: AparteIconProvider): void— a set of icon functions (() => stringHTML each), e.g. a FontAwesome bridge.getIconProvider(): AparteIconProvider— the registered provider, or a fallback built fromDEFAULT_ICON_FALLBACKS.getIcon(name: AparteIconName): string— HTML for one icon by name, falling back to the built-in default.setSkeletonProvider(provider: AparteSkeletonProvider): void— a custom loading-state generator (getSkeleton(type) => string).getSkeleton(type: AparteSkeletonType): string— skeleton HTML for a type (message/code/thinking/input/list/text), via the provider or a minimal built-in fallback.
Actions
Section titled “Actions”Custom buttons placed in the composer toolbar and/or the message (bubble) toolbar — one
merged registry, a zones parameter picks where each appears.
registerAction(action: AparteAction): void— register (or overwrite, byid) a custom action button.getActions(zone: AparteActionZone): AparteAction[]— actions for a zone ('composer' | 'bubble'), sorted byorder.unregisterAction(id: string): void— remove an action from every zone.setActionHidden(id: string, hidden: boolean): void— show/hide a composer action button at runtime.setBubbleActions(config: AparteBubbleActionsConfig): void— configure which built-in buttons (copy/retry/edit/feedback) appear in bubbles, or set explicit per-role ordered lists.getBubbleActions(): { copy, retry, edit, feedback, user?, assistant? }— the resolved bubble-actions config (defaults applied).
See the Customization guide.
Tools & tool renderers
Section titled “Tools & tool renderers”registerTool(tool: AparteTool, handler: AparteToolHandler): void— register a tool definition together with its handler.unregisterTool(name: string): void— remove a tool by name.getTools(): AparteTool[]— all registered tool definitions (passed in the chat request).getToolHandler(name: string): AparteToolHandler | undefined— the handler for a tool by name.registerToolRenderer(toolName: string, renderer: AparteToolRenderer): void— a per-tool segment renderer, controlling what appears in the bubble when that tool is called.unregisterToolRenderer(toolName: string): void— remove a per-tool renderer.getToolRenderer(toolName: string): AparteToolRenderer | undefined— the renderer for a tool name, if any.
See the Tools & human-in-the-loop guide.
Model preference
Section titled “Model preference”setModelConfig(config: AparteModelConfig): void— set model-selection config (enabledProviders,modelFilters,defaultProvider,defaultModel); auto-saves via the model-preference provider when both a default provider and model are set.getModelConfig(): AparteModelConfig— the current model configuration (a shallow copy).hasSelectedModel(): boolean—truewhen both a provider and a model are selected.setRequireModelSelection(required: boolean): void— opt-in: gate<aparte-composer>(block send + grey out) until a model is selected.getRequireModelSelection(): boolean— whether that gate is active.getCurrentModel(): AparteAIModel | undefined— the selected model object, when its provider’s model list is available synchronously.setModelPreferenceProvider(provider: AparteModelPreferenceProvider): void— register{ save, load }for host-app-agnostic persistence of the selected provider + model.restoreModelPreference(): AparteModelPreference | null— restore a previously saved preference via the registered provider (call once at startup).
Conversation manager
Section titled “Conversation manager”setConversationManager(manager: ConversationManager): void— register aConversationManagerso any UI controller can persist/load conversations without a framework coupling.getConversationManager(): ConversationManager | undefined— the registered manager, if any.
See the Conversation persistence guide.
Elicitation (human-in-the-loop)
Section titled “Elicitation (human-in-the-loop)”setElicitationPresenter(presenter: AparteElicitationPresenter | null): void— register the presenter that renders a typed input request (choice / confirmation / text field / form) and resolves with the user’s answer.<aparte-elicitation>registers itself here by default.getElicitationPresenter(): AparteElicitationPresenter | undefined— the registered presenter, if any.requestUserInput(request: AparteElicitationRequest): Promise<AparteElicitationResult>— ask the user for typed input mid-run; resolves{ action: 'accept' | 'decline' | 'cancel', ... }. Resolvescancelimmediately when no presenter is registered.
Subscribe & reset
Section titled “Subscribe & reset”subscribe(callback: () => void): () => void— subscribe to configuration changes; returns an unsubscribe function.reset(): void— reset all configuration back to defaults (providers, tools, tool renderers, model selection, actions, renderers, locale, sanitizer, bubble-actions config). Useful between SPA navigations / test cases so registries don’t leak.
AparteClient
Section titled “AparteClient”AparteClient (packages/core/src/client/aparte-client.ts) is “the automatic transmission for
aparté” — it listens for aparte-send (and aparte-retry/aparte-edit/aparte-abort/aparte-compact)
on window, resolves the provider + key, calls the transport, and streams the parsed segments
into the target element.
import { AparteClient } from '@aparte/core';
const client = new AparteClient({ keyResolver: (providerId) => process.env[providerId.toUpperCase() + '_KEY'],});client.start();AparteClientOptions
Section titled “AparteClientOptions”Constructor options (all optional):
| Option | Type | Purpose |
|---|---|---|
keyResolver | (providerId: string) => string | Record<string,string> | Promise<... | undefined | null> | undefined | null | Resolve the API key/config for a provider. |
approvalResolver | AparteToolApprovalResolver | Custom human-in-the-loop approval for needsApproval tools. Defaults to a global aparte-tool-decision DOM listener. |
compactionSelector | AparteCompactionSelector | Decide which messages compact() summarizes away vs. keeps verbatim. Default: drop everything. |
streamRunner | AparteStreamRunner | Delegate the agentic loop to a headless runner (e.g. @aparte/engine’s runStreamAgent) instead of the built-in inline loop. |
requestInterceptor | (request: AparteChatRequest) => AparteChatRequest | Promise<AparteChatRequest> | Modify the chat request before it is sent. |
autoRegister | boolean (default true) | Auto-register the default segment renderers. |
history | 'viewport' | 'none' | ((viewportMessages: AparteMessage[]) => AparteChatMessage[]) | Conversation-history strategy for new sends. |
targetResolver | () => HTMLElement | null | Resolve the render target when the default event-bubble walk / DOM scan can’t reach it. |
scopeToTargetId | string | Scope this client instance to one target id, for multiple independent conversations on one page. |
maxTurns | number (default 10) | Max agentic tool-call loop turns before the loop is forcibly stopped. |
rawFileInject | 'all' | 'images-only' | 'none' (default 'all') | Which attached files are injected as raw content parts vs. left to the app layer (e.g. a RAG pipeline). |
config | AparteConfigClass | The config instance this client reads. Defaults to the global AparteConfig. |
Public methods
Section titled “Public methods”constructor(options: AparteClientOptions = {})start(): void— attach theaparte-send/aparte-abort/aparte-compact/aparte-retry/aparte-editlisteners onwindow. Nothing streams before this is called.stop(): void— remove all listeners.abort(): void— abort the current streaming response and all active tool calls; dispatchesaparte-message-abortedon the target element.compact(): Promise<void>— summarize the conversation via the configured provider/model, clear the viewport, and inject the summary (dispatchesaparte-compact-start/aparte-compact-done/aparte-compact-erroronwindow).
Transports
Section titled “Transports”A transport decides where a chat request goes and how the API key is handled.
AparteConfig.setTransport(...) (default: DirectTransport) wires one in.
DirectTransport(packages/core/src/transport/direct-transport.ts) — calls the vendor endpoint straight from the browser. The default; only safe for BYOK or local models. Options:{ byok?: boolean }— settrueto silence the one-time insecure-keyconsole.warn.BackendTransport(packages/core/src/transport/backend-transport.ts) — POSTs{ providerId, request }to your own endpoint; the key never reaches the browser. Options:{ endpoint: string; headers?: Record<string,string>; buildBody?: (request, providerId) => unknown }.createAparteChatHandler(options)(packages/core/src/transport/backend-handler.ts) — builds the matching framework-free/api/chathandler ((req: Request) => Promise<Response>) forBackendTransport: same@aparte/provider-*adapters, run server-side, key never leaves the server.
See the Backend transport guide for the full walkthrough.