Events
Everything aparté does that your app might care about goes out as a DOM event. There are 46 of them, and they are grouped below by the node they are dispatched on — because that is the part a listener gets wrong: attach to the element an event never reaches and it simply never fires, with no error to say why.
@aparte/core augments HTMLElementEventMap, so once the package is in your TypeScript
program addEventListener types the detail for you, with no cast:
chat.addEventListener('aparte-send', (event) => { event.detail.content; // string — typed, with no cast});The four wrappers surface six of these as callbacks in their own idiom (Wrapper surface); everything else is listened for on the DOM, in every framework alike.
On the element
Section titled “On the element”Dispatched by the element itself and bubbling, so a listener on any ancestor — including document — receives them. This is where an intent lives: the user pressed something, and your app decides what it means.
| Event | Detail | Dispatched on | Fired by |
|---|---|---|---|
aparte-action | AparteActionEventDetail | element | <aparte-chat-bubble> |
aparte-action-click | AparteActionClickEventDetail | element | <aparte-composer-action> |
aparte-approval-mode-change | AparteApprovalModeChangeEventDetail | element | <aparte-approval-mode> |
aparte-archive-conversation | AparteConversationArchiveDetail | element | <aparte-conversation-list> |
aparte-attachment-preview | AparteAttachmentPreviewEventDetail | element | <aparte-chat-bubble>, <aparte-composer-attachments> |
aparte-branch-navigate | AparteBranchNavigateEventDetail | element | <aparte-chat-bubble> |
aparte-cancel | — | element | <aparte-composer> |
aparte-composer-change | AparteComposerChangeEventDetail | element | <aparte-composer> |
aparte-composer-submit | — | element | <aparte-composer-input> |
aparte-context-threshold | AparteContextThresholdEventDetail | element | <aparte-context> |
aparte-delete-conversation | AparteConversationDeleteDetail | element | <aparte-conversation-list> |
aparte-edit | AparteEditEventDetail | element | <aparte-chat-bubble> |
aparte-feedback | AparteFeedbackEventDetail | element | <aparte-chat-bubble> |
aparte-link-click | AparteLinkClickEventDetail | element | <aparte-chat-bubble> |
aparte-message-info | AparteMessageInfoEventDetail | element | <aparte-chat-bubble> |
aparte-model-change | AparteModelChangeEventDetail | element | <aparte-model-selector> |
aparte-optgroup-toggle | AparteOptgroupToggleEventDetail | element | <aparte-optgroup> |
aparte-path-changed | ApartePathChangedEventDetail | element | <aparte-chat-viewport> |
aparte-pin-conversation | AparteConversationPinDetail | element | <aparte-conversation-list> |
aparte-rename-conversation | AparteConversationRenameDetail | element | <aparte-conversation-list> |
aparte-reset-done | — | element | <aparte-chat-viewport> |
aparte-retry | AparteRetryEventDetail | element | <aparte-chat-bubble> |
aparte-scroll-rail-jump | AparteScrollRailJumpDetail | element | <aparte-scroll-rail> |
aparte-segment-update | AparteSegmentUpdateEventDetail | element | <aparte-chat-viewport> |
aparte-select-change | AparteSelectChangeDetail | element | <aparte-select> |
aparte-select-close | — | element | <aparte-select> |
aparte-select-conversation | AparteConversationSelectDetail | element | <aparte-conversation-list> |
aparte-select-open | — | element | <aparte-select> |
aparte-send | AparteSendEventDetail | element | <aparte-composer> |
aparte-sidebar-toggle | AparteSidebarToggleDetail | element | <aparte-sidebar> |
aparte-split-resize | AparteSplitResizeDetail | element | <aparte-split> |
aparte-suggestion | AparteSuggestionEventDetail | element | <aparte-suggestions> |
aparte-unarchive-conversation | AparteConversationArchiveDetail | element | <aparte-conversation-list> |
aparte-unpin-conversation | AparteConversationPinDetail | element | <aparte-conversation-list> |
aparte-action
Section titled “aparte-action”A custom action-bar button was pressed.
aparte-action-click
Section titled “aparte-action-click”Bubbles up when the button is clicked, carrying which button it was and the composer it belongs to. The type argument is not decoration: a BARE @fires records CustomEvent with no argument, and the bindings generator then emits EventEmitter<void> with a listener that drops $event — so an Angular consumer with two custom buttons could not tell which one fired. detail: { actionId: string, composer: AparteComposer | null }
aparte-approval-mode-change
Section titled “aparte-approval-mode-change”After a switch: { mode, previousMode }. Bubbles and crosses shadow roots.
aparte-archive-conversation
Section titled “aparte-archive-conversation”The archive item was chosen on a live conversation.
aparte-attachment-preview
Section titled “aparte-attachment-preview”An attached image was clicked, asking the app to open it full-size.
aparte-branch-navigate
Section titled “aparte-branch-navigate”The ‹1/2› picker moved between sibling versions.
aparte-cancel
Section titled “aparte-cancel”The stop button was pressed. No detail; the two window events below carry the target.
aparte-composer-change
Section titled “aparte-composer-change”Any of value / streaming / disabled / attachments / panel changed, folded into one event.
aparte-composer-submit
Section titled “aparte-composer-submit”A submitting Enter was pressed with no <aparte-composer> ancestor to submit to; with one it calls root.submit() and dispatches nothing. No detail — the host that placed this primitive reads getValue().
aparte-context-threshold
Section titled “aparte-context-threshold”The level changed. Bubbles.
aparte-delete-conversation
Section titled “aparte-delete-conversation”The delete was confirmed. Nothing is removed here.
aparte-edit
Section titled “aparte-edit”An edit was saved.
aparte-feedback
Section titled “aparte-feedback”Thumbs up or down.
aparte-link-click
Section titled “aparte-link-click”A link in the message body is about to be followed. Cancelable: preventDefault() keeps the browser from navigating, so a host can route the link itself.
aparte-message-info
Section titled “aparte-message-info”The info affordance was pressed.
aparte-model-change
Section titled “aparte-model-change”The provider or the model changed; carries both ids.
aparte-optgroup-toggle
Section titled “aparte-optgroup-toggle”The group was collapsed or expanded.
aparte-path-changed
Section titled “aparte-path-changed”The active branch path changed, after a retry fork or a navigation.
aparte-pin-conversation
Section titled “aparte-pin-conversation”The pin item was chosen on an unpinned row.
aparte-rename-conversation
Section titled “aparte-rename-conversation”A rename was committed with a new, non-empty title. Nothing is renamed here.
aparte-reset-done
Section titled “aparte-reset-done”clearAll() finished emptying the transcript. No detail.
aparte-retry
Section titled “aparte-retry”Retry was pressed; the host forks the turn.
aparte-scroll-rail-jump
Section titled “aparte-scroll-rail-jump”A tick was activated. Bubbles, cancelable: preventDefault() leaves the transcript where it is.
aparte-segment-update
Section titled “aparte-segment-update”A segment grew or settled during a stream.
aparte-select-change
Section titled “aparte-select-change”The selection changed; carries the new value, its label and the previous value.
aparte-select-close
Section titled “aparte-select-close”The dropdown closed. No detail.
aparte-select-conversation
Section titled “aparte-select-conversation”A row’s title was activated; the host loads that conversation.
aparte-select-open
Section titled “aparte-select-open”The dropdown opened. No detail.
aparte-send
Section titled “aparte-send”A message was submitted: the text, its attachments and the target.
aparte-sidebar-toggle
Section titled “aparte-sidebar-toggle”The sidebar opened or closed, by a toggle, by Escape, by a click on the scrim or by collapsed being set. Bubbles.
aparte-split-resize
Section titled “aparte-split-resize”The position settled: after a drag, a key, a double-click or a property set. Never during a drag — persist from here.
aparte-suggestion
Section titled “aparte-suggestion”A starter was clicked. Bubbles, and is cancelable: preventDefault() stops the composer from being filled or submitted.
aparte-unarchive-conversation
Section titled “aparte-unarchive-conversation”The same item on an already-archived one; same detail shape, opposite intent.
aparte-unpin-conversation
Section titled “aparte-unpin-conversation”The same item on a pinned row; same detail shape, opposite intent.
On the chat host
Section titled “On the chat host”The turn lifecycle, dispatched by AparteClient on the <aparte-chat> it drives — bubbling and composed, and stamped with targetId so two chats on one page stay apart. A composer treats an ABSENT targetId as “for me”, which is what lets a single-chat page work with no wiring at all.
| Event | Detail | Dispatched on | Fired by |
|---|---|---|---|
aparte-message-aborted | AparteMessageAbortedEventDetail | chat host + window | <aparte-composer> |
aparte-message-done | AparteMessageDoneEventDetail | chat host | AparteClient |
aparte-message-error | AparteMessageErrorEventDetail | chat host | AparteClient |
aparte-message-start | AparteMessageStartEventDetail | chat host | AparteClient |
aparte-tool-approval-request | AparteToolApprovalRequestDetail | chat host | AparteClient |
aparte-message-aborted
Section titled “aparte-message-aborted”The run for this target ended early — the user pressed Stop, or abort() was called. This element dispatches it on window; AparteClient also dispatches it on the chat host, so it is listenable on either.
aparte-message-done
Section titled “aparte-message-done”Detail payload for aparte-message-done. Dispatched when a turn finishes normally. Carries token usage when the provider reports it.
aparte-message-error
Section titled “aparte-message-error”Detail payload for aparte-message-error. Dispatched when a turn fails. Four core components listen for it, and it is the event guides/troubleshooting.md tells you to bind to surface a failure.
aparte-message-start
Section titled “aparte-message-start”Detail payload for aparte-message-start. Dispatched when a turn begins, before the first token. The composer and the conversation controller both use it to enter their streaming state.
aparte-tool-approval-request
Section titled “aparte-tool-approval-request”Detail for aparte-tool-approval-request — emitted by the loop when a tool marked needsApproval is about to run. Listen for it to present the decision yourself. Core’s own gate asks at the COMPOSER (<aparte-elicitation> renders the panel there), and the transcript row shows only a state — there is no Approve/Reject control in a bubble. This block used to say “the built-in renderer already shows Approve/Reject inline”, which stopped being true when the decision moved to the composer. A consumer trusting it shipped with no presenter and no approvalResolver, and every needsApproval call aborted with nothing clickable on screen. The sibling docblock on needsApproval records the same correction; this one was missed in the same file.
On window
Section titled “On window”Page-level operations, dispatched on window because they concern the whole document rather than one chat — by core, or by a plugin (the compaction events are @aparte/plugin-compaction’s; aparte-compact itself is the gauge’s). A listener on an element will never see these.
| Event | Detail | Dispatched on | Fired by |
|---|---|---|---|
aparte-abort | AparteAbortEventDetail | window | <aparte-composer> |
aparte-compact | AparteCompactEventDetail | window | <aparte-context> |
aparte-compact-done | AparteCompactDoneEventDetail | window | @aparte/plugin-compaction |
aparte-compact-error | AparteCompactErrorEventDetail | window | @aparte/plugin-compaction |
aparte-compact-start | AparteCompactStartEventDetail | window | @aparte/plugin-compaction |
aparte-config-change | AparteConfigChangeEventDetail | window | AparteClient |
aparte-abort
Section titled “aparte-abort”Dispatched on window: stop the run for this target.
aparte-compact
Section titled “aparte-compact”Dispatched on window when auto-compact is set and the gauge first reaches danger: compact this target’s transcript. Once per crossing, and only while the attribute is present. @aparte/plugin-compaction answers it; with no listener nothing happens.
aparte-compact-done
Section titled “aparte-compact-done”Detail payload for aparte-compact-done. A union flattened to optional fields, because the two outcomes carry different payloads and a consumer cannot guess which: nothing to compact sends { skipped: true, reason }, a real compaction sends { summary, kept, dropped }.
aparte-compact-error
Section titled “aparte-compact-error”Detail payload for aparte-compact-error. Note the asymmetry with aparte-message-error, which is deliberate rather than hidden: error here is a plain string, not an AparteError.
aparte-compact-start
Section titled “aparte-compact-start”Detail payload for aparte-compact-start — the summarisation began. The point for a host to show a spinner: summarising a long conversation is a model call and takes as long as one.
aparte-config-change
Section titled “aparte-config-change”Detail payload for aparte-config-change, dispatched on window whenever any provider, locale, action or model setting changes. Five core components listen for it — the widest listener footprint of any event that had no declared type. config is what makes per-instance config work: a component resolving to a different instance compares it and skips the rebuild instead of every chat on the page reacting to every config’s change.
The ones you dispatch
Section titled “The ones you dispatch”The ones that travel the other way: core listens for these and never sends them, so they are COMMANDS your app issues rather than news it receives. Dispatch them on window; a listener will never see anything come back on the same name — the answer, when there is one, has a name of its own (aparte-reset is answered by aparte-reset-done).
| Event | Detail | Dispatched on | Fired by |
|---|---|---|---|
aparte-reset | — | window | your app |
aparte-reset
Section titled “aparte-reset”Empty every mounted transcript on the page. A command, not a notification: this is one of the events that travel the other way, dispatched by YOUR app on window and listened for here. Every connected <aparte-chat-viewport> clears its repository and its DOM and answers with aparte-reset-done, so a “New chat” button in a shell that holds no reference to the transcript still empties it. Carries no detail — and therefore no target, so it clears every viewport, not one.
A detail-less event is not an oversight
Section titled “A detail-less event is not an oversight”aparte-cancel, aparte-composer-submit, aparte-reset, aparte-reset-done, aparte-select-close, aparte-select-open carry no detail,
and are deliberately absent from AparteEventMap: a map entry would type event.detail
as null and gain nothing. The name is the whole message.