@adia-ai/web-modules 0.8.3 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/chat/chat-shell/chat-shell.js +28 -8
- package/dist/chat/chat-shell.min.js +25 -25
- package/dist/everything.min.js +64 -68
- package/dist/web-modules.min.css +1 -1
- package/dist/web-modules.sheet.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-modules
|
|
2
|
+
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **`chat-shell.appendMessage({ html: true })`** — assistant messages can carry trusted app-authored component markup (light-DOM upgrade in place); the `render` (markdown) path escapes inline HTML by design, which made gen-ui's error bubbles show raw `<col-ui …>` source text. The html mode persists on the message record and survives `stopStreaming()` and `conversation` getter/setter round-trips.
|
|
7
|
+
|
|
8
|
+
### Maintenance
|
|
9
|
+
- **`dist/` bundles rebuilt** (`chat/chat-shell.min.js`, `everything.min.js` — the chat-shell change plus the inlined @adia-ai/llm provider-routing fixes).
|
|
10
|
+
|
|
2
11
|
## [0.8.3] — 2026-07-16
|
|
3
12
|
|
|
4
13
|
### Maintenance
|
|
@@ -66,13 +66,15 @@ class ChatShell extends UIElement {
|
|
|
66
66
|
get conversation() {
|
|
67
67
|
return this.#messages
|
|
68
68
|
.filter(m => m.role === 'user' || m.role === 'assistant')
|
|
69
|
-
.map(m => ({ role: m.role, content: m.content }));
|
|
69
|
+
.map(m => (m.html ? { role: m.role, content: m.content, html: true } : { role: m.role, content: m.content }));
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
set conversation(msgs) {
|
|
73
73
|
this.clear();
|
|
74
74
|
for (const m of msgs) {
|
|
75
|
-
|
|
75
|
+
// Round-trip the html mode — re-rendering an html message through
|
|
76
|
+
// the markdown path would escape its component markup.
|
|
77
|
+
this.appendMessage({ role: m.role, content: m.content, render: !m.html, html: !!m.html });
|
|
76
78
|
}
|
|
77
79
|
}
|
|
78
80
|
|
|
@@ -122,9 +124,22 @@ class ChatShell extends UIElement {
|
|
|
122
124
|
|
|
123
125
|
// ── Message management ──
|
|
124
126
|
|
|
125
|
-
|
|
127
|
+
/**
|
|
128
|
+
* @param {object} msg
|
|
129
|
+
* @param {string} msg.role — 'user' | 'assistant' | 'error'
|
|
130
|
+
* @param {string} [msg.content]
|
|
131
|
+
* @param {boolean} [msg.render] — treat content as MARKDOWN (inline HTML
|
|
132
|
+
* is escaped — component markup shows as literal text under this flag)
|
|
133
|
+
* @param {boolean} [msg.html] — assistant only: insert content as raw
|
|
134
|
+
* HTML (light-DOM component markup upgrades in place). TRUSTED
|
|
135
|
+
* app-authored strings only — never LLM output or user input; the
|
|
136
|
+
* caller owns escaping of any interpolated values.
|
|
137
|
+
*/
|
|
138
|
+
appendMessage({ role, content = '', render: renderMd = false, html = false }) {
|
|
126
139
|
const id = `msg_${++msgId}`;
|
|
127
|
-
|
|
140
|
+
// html persists on the record: stopStreaming() and the conversation
|
|
141
|
+
// setter must never push an html message back through the markdown path.
|
|
142
|
+
this.#messages.push({ id, role, content, html });
|
|
128
143
|
|
|
129
144
|
const el = document.createElement('div');
|
|
130
145
|
el.setAttribute('data-role', role);
|
|
@@ -133,10 +148,13 @@ class ChatShell extends UIElement {
|
|
|
133
148
|
if (role === 'user') {
|
|
134
149
|
el.innerHTML = `<div data-bubble>${escapeHTML(content)}</div>`;
|
|
135
150
|
} else if (role === 'assistant') {
|
|
136
|
-
const
|
|
151
|
+
const done = renderMd || html;
|
|
152
|
+
const rendered = html ? content
|
|
153
|
+
: renderMd && content ? renderMarkdown(content)
|
|
154
|
+
: escapeHTML(content);
|
|
137
155
|
el.innerHTML = `
|
|
138
156
|
<span data-avatar>AI</span>
|
|
139
|
-
<div data-bubble><div data-content>${rendered}</div>${!
|
|
157
|
+
<div data-bubble><div data-content>${rendered}</div>${!done ? '<span data-cursor></span>' : ''}</div>
|
|
140
158
|
`;
|
|
141
159
|
} else if (role === 'error') {
|
|
142
160
|
el.innerHTML = `<icon-ui name="warning"></icon-ui><span>${escapeHTML(content)}</span>`;
|
|
@@ -202,9 +220,11 @@ class ChatShell extends UIElement {
|
|
|
202
220
|
// Remove cursor
|
|
203
221
|
this.#messagesEl?.querySelector('[data-role]:last-child [data-cursor]')?.remove();
|
|
204
222
|
|
|
205
|
-
// Render markdown in last assistant bubble
|
|
223
|
+
// Render markdown in last assistant bubble — never an html-mode
|
|
224
|
+
// message: its component markup is already live DOM, and the markdown
|
|
225
|
+
// path would re-escape it to source text.
|
|
206
226
|
const last = this.#messages[this.#messages.length - 1];
|
|
207
|
-
if (last?.role === 'assistant' && last.content) {
|
|
227
|
+
if (last?.role === 'assistant' && last.content && !last.html) {
|
|
208
228
|
const contentEl = this.#messagesEl?.querySelector('[data-role]:last-child [data-content]');
|
|
209
229
|
if (contentEl) {
|
|
210
230
|
contentEl.innerHTML = renderMarkdown(last.content);
|