import type { Source, ProjectAction } from '../../types/widget'; import { EventEmitter } from '../../stencil-public-runtime'; import { AiIconType } from '../../utils/icon-types'; export declare class BielMessage { messageId?: string; sender: 'user' | 'ai'; text: string; sources?: Source[]; availableActions?: ProjectAction[]; feedback?: 0 | 1; hideFeedback: boolean; bielId: string; isPartial: boolean; partialId: number; sourcesText: string; aiIcon: AiIconType; hideAvatars: boolean; hideSources: boolean; hideInlineCitations: boolean; assistantLabel: string; smoothStreaming: boolean; renderMath: boolean; mathjaxUrl: string; renderDiagrams: boolean; mermaidTheme: string; content: string; rawContent: string; feedbackValue: 0 | 1; displaySources: Source[]; citationNumbers: { [urlKey: string]: number; }; showSources: boolean; copied: boolean; completed: boolean; el: HTMLElement; scrollToBottom: EventEmitter<{ bielId: string; }>; feedbackSent: EventEmitter<{ bielId: string; messageId: string; reaction: 0 | 1; }>; private copyTimers; private revealBacklog; private revealCarry; private revealRafId; private lastRevealTs; private pendingReveal; private lastMarkdownTs; private waitingForFade; private completionWaitVersion; private pendingCompletion; private get useSmoothStreaming(); handleTextUpdate(event: CustomEvent<{ text: string; id: number; bielId: string; }>): void; private startRevealLoop; private revealTick; private invalidateCompletionWait; private completeAfterReveal; private finishRevealNow; private applyCompletion; handlePartialMessageComplete(event: CustomEvent<{ partialId: number; bielId: string; msg: { text: string; sender: 'user' | 'ai'; messageId?: string; feedback?: 0 | 1; sources?: Source[]; isPartial: boolean; partialId?: number; }; }>): void; /** * Replace the streamed draft with the server's completed text, which is * authoritative: the payload may differ from the deltas (the server validates * citations only once the answer is whole, so the final text can drop markers * the draft still shows — leaving a chip pointing at a source that isn't in * the sources list), and it is the safest point to remount custom elements * that were updated repeatedly while Markdown was partial. An empty text is * treated as "nothing to replace with" and keeps the draft. */ replaceContent(text?: string): void; handleSettledTextChanged(text: string): void; handleSettledSourcesChanged(sources: Source[]): void; componentWillLoad(): void; disconnectedCallback(): void; private get isComplete(); private toggleSources; private hostnameFrom; private handleReaction; private copyAnswer; private execCommandCopy; componentDidLoad(): void; /** * Replace each inline ```` tag with an anchor styled as a * chip, resolving the name against the project's actions. Unknown/unresolved * tags are removed so no raw markup leaks. Runs before Markdown parsing so * the anchor survives marked + DOMPurify (which both keep plain elements). */ renderInlineActions(text: string): string; /** * Upgrade citation links into compact superscript chips as a DOM pass over the * already-parsed, already-sanitized message tree: any anchor whose visible * text is purely 1-2 digits and whose href is http(s) becomes a scholarly * ``[n]`` chip. The backend streams these as plain markdown links, e.g. * ``[1](https://docs.example.com/page)``. * * Running AFTER marked + DOMPurify (rather than a raw-text regex before them) * means: URLs with balanced parentheses are parsed correctly by marked; * citation-shaped text inside code spans/fences stays literal because it never * becomes an anchor; and DOMPurify has already stripped any dangerous href, so * only safe http(s) links remain to match. The pass is idempotent (an anchor * already carrying the chip class is skipped) and mutates in place, so the * upgraded anchor rides the same streaming diff as the action chips. Partial * links at a chunk boundary (``[1](https://doc``) aren't anchors yet, so no * chip appears until the link completes. * * With `hideInlineCitations` the same detection applies but matching anchors * are removed (with the space before them) instead of upgraded — the message * reads as if the backend had never cited. * * A chip shows its source's rank by first appearance in the message, not the * number the backend wrote: those are positions in the model's context list, * so a message can arrive citing 1, 5, 3. Numbering by appearance keeps the * sequence counting up from the very first streamed chunk — the backend * settles on the same numbering for the final message, so nothing shifts * when streaming ends. The href is the citation's real identity; the digit * is only a pointer to it. The same map (normalized href → number) badges * the footer's source cards, so a card always matches its chips. */ upgradeCitationAnchors(root: HTMLElement): void; /** * Remove a citation anchor along with the single space that precedes it, so * "blue [1](url)." collapses to "blue." — the same one-space cleanup the * backend applies when it strips an invalid marker. */ removeCitationAnchor(anchor: HTMLAnchorElement): void; /** Replace `citationNumbers` only when the collected map actually differs, * so the per-chunk streaming passes don't trigger a re-render each time. */ recordCitationNumbers(found: { [urlKey: string]: number; }): void; /** Citation number for a source card, or `undefined` when that source was * never cited inline (or citations are hidden). */ citationNumberFor(url: string): number | undefined; /** * Pull math out of the Markdown before anything else touches it. Runs ahead * of the action tags so the anchors injected for those can never be mistaken * for a formula, and returns the spans to be put back after sanitizing. */ private takeMathSpans; processMarkdown(fragment: string, replaceAll?: boolean): void; convertToElement(content: string): HTMLElement; private wrapStreamingText; private settleStreamingFragment; deepCompareAndReplace(element1: HTMLElement, element2: HTMLElement): void; private cloneMessageNode; areNodesEqual(node1: Node, node2: Node): boolean; /** * Copy the freshly parsed element's attributes onto the mounted one. * * `class` is excluded for custom elements only: Stencil writes their host * class itself (`hydrated`, scoping classes) and the detached tree never * carries it, so copying would strip it and leave the element invisible. On * a plain element the class comes solely from this component's own parse * pipeline and must be synced — a citation anchor is already mounted as the * autolink of a half-streamed URL by the time the chip pass claims it, and * the chip class is then the only thing that changes. */ synchronizeAttributes(element1: HTMLElement, element2: HTMLElement): void; private renderFooter; render(): any; }