@noodleseed/assistant 1.9.0 → 1.10.0
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/README.md +52 -9
- package/dist/{chunk-4B3XXGRP.js → chunk-RSNMY27B.js} +24 -7
- package/dist/chunk-RSNMY27B.js.map +1 -0
- package/dist/index.cjs +22 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/react.cjs +28 -6
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +9 -2
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-4B3XXGRP.js.map +0 -1
package/README.md
CHANGED
|
@@ -259,7 +259,7 @@ if (part.type === "data-view") {
|
|
|
259
259
|
key={`${part.data.id}:${part.data.resourceUri}`}
|
|
260
260
|
client={client}
|
|
261
261
|
view={part.data}
|
|
262
|
-
theme=
|
|
262
|
+
theme={resolvedTheme}
|
|
263
263
|
onError={(failure) => reportAssistantError(failure)}
|
|
264
264
|
/>
|
|
265
265
|
);
|
|
@@ -269,7 +269,9 @@ if (part.type === "data-view") {
|
|
|
269
269
|
`NoodleAppView` owns the double iframe and AppBridge. Its lifecycle identity is the supplied client plus
|
|
270
270
|
`view.id` plus `view.resourceUri`: ordinary parent rerenders and fresh view/callback objects retain the
|
|
271
271
|
iframe, while a semantic view replacement or unmount requests standard App teardown and closes the bridge.
|
|
272
|
-
Do not also key an ancestor by the whole view object or a callback.
|
|
272
|
+
Do not also key an ancestor by the whole view object or a callback. Pass the embedding application's
|
|
273
|
+
resolved `"light"` or `"dark"` theme; later changes are published through MCP Apps host context without
|
|
274
|
+
replacing the iframe.
|
|
273
275
|
|
|
274
276
|
Outside React, subscribe to the DOM-free AI SDK `UIMessage` state without registering a custom element or
|
|
275
277
|
touching browser storage:
|
|
@@ -393,10 +395,19 @@ exact control over assistant-specific roles:
|
|
|
393
395
|
```tsx
|
|
394
396
|
<NoodleAssistant
|
|
395
397
|
sessionEndpoint="/api/assistant/session"
|
|
398
|
+
theme={resolvedTheme}
|
|
396
399
|
appearance={{
|
|
397
400
|
light: {
|
|
398
|
-
panel: {
|
|
399
|
-
|
|
401
|
+
panel: {
|
|
402
|
+
surface: "var(--app-surface)",
|
|
403
|
+
text: "var(--app-text)",
|
|
404
|
+
border: "var(--app-border)",
|
|
405
|
+
},
|
|
406
|
+
composer: {
|
|
407
|
+
surface: "var(--app-input)",
|
|
408
|
+
text: "var(--app-text)",
|
|
409
|
+
border: "var(--app-border)",
|
|
410
|
+
},
|
|
400
411
|
confirmation: { surface: "#F8FAFC", text: "#101828", border: "#CBD5E1" },
|
|
401
412
|
primaryButton: { surface: "#635BFF", text: "#FFFFFF" },
|
|
402
413
|
},
|
|
@@ -405,11 +416,38 @@ exact control over assistant-specific roles:
|
|
|
405
416
|
/>
|
|
406
417
|
```
|
|
407
418
|
|
|
408
|
-
The same object is available as `element.appearance`.
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
`assistant-appearance-warning` event.
|
|
412
|
-
|
|
419
|
+
The same object is available as `element.appearance`. CSS custom properties inherit through the assistant
|
|
420
|
+
host into its shadow tree, so `var(--app-token)` references reuse the embedding application's existing
|
|
421
|
+
tokens without copying literal colors. Exact parseable literal colors are preserved and checked;
|
|
422
|
+
insufficient contrast emits the typed `assistant-appearance-warning` event. Contrast for unresolved CSS
|
|
423
|
+
references remains the host application's responsibility.
|
|
424
|
+
|
|
425
|
+
The complete typed appearance role map is:
|
|
426
|
+
|
|
427
|
+
| Appearance role | Public CSS custom properties |
|
|
428
|
+
| --- | --- |
|
|
429
|
+
| `canvas` | `--ns-assistant-canvas` |
|
|
430
|
+
| `text` | `--ns-assistant-text` |
|
|
431
|
+
| `mutedText` | `--ns-assistant-muted-text` |
|
|
432
|
+
| `link` | `--ns-assistant-link` |
|
|
433
|
+
| `focus` | `--ns-assistant-focus` |
|
|
434
|
+
| `success` | `--ns-assistant-success` |
|
|
435
|
+
| `warning` | `--ns-assistant-warning` |
|
|
436
|
+
| `danger` | `--ns-assistant-danger` |
|
|
437
|
+
| `panel` | `--ns-assistant-panel`, `--ns-assistant-panel-text`, `--ns-assistant-panel-border` |
|
|
438
|
+
| `header` | `--ns-assistant-header`, `--ns-assistant-header-text`, `--ns-assistant-header-border` |
|
|
439
|
+
| `assistantMessage` | `--ns-assistant-assistant-message`, `--ns-assistant-assistant-message-text`, `--ns-assistant-assistant-message-border` |
|
|
440
|
+
| `userMessage` | `--ns-assistant-user-message`, `--ns-assistant-user-message-text`, `--ns-assistant-user-message-border` |
|
|
441
|
+
| `composer` | `--ns-assistant-composer`, `--ns-assistant-composer-text`, `--ns-assistant-composer-border` |
|
|
442
|
+
| `suggestion` | `--ns-assistant-suggestion`, `--ns-assistant-suggestion-text`, `--ns-assistant-suggestion-border` |
|
|
443
|
+
| `confirmation` | `--ns-assistant-confirmation`, `--ns-assistant-confirmation-text`, `--ns-assistant-confirmation-border` |
|
|
444
|
+
| `primaryButton` | `--ns-assistant-primary-button`, `--ns-assistant-primary-button-text`, `--ns-assistant-primary-button-border` |
|
|
445
|
+
| `secondaryButton` | `--ns-assistant-secondary-button`, `--ns-assistant-secondary-button-text`, `--ns-assistant-secondary-button-border` |
|
|
446
|
+
| `launcher` | `--ns-assistant-launcher`, `--ns-assistant-launcher-text`, `--ns-assistant-launcher-border` |
|
|
447
|
+
| `code` | `--ns-assistant-code`, `--ns-assistant-code-text`, `--ns-assistant-code-border` |
|
|
448
|
+
| `app` | `--ns-assistant-app`, `--ns-assistant-app-text`, `--ns-assistant-app-border` |
|
|
449
|
+
|
|
450
|
+
Stable public CSS variables also remain available directly for stylesheet-based integration:
|
|
413
451
|
|
|
414
452
|
```css
|
|
415
453
|
noodle-assistant {
|
|
@@ -427,6 +465,11 @@ defaults. The public slots are `launcher-icon`,
|
|
|
427
465
|
embedding-page integration API, not a way to put HTML or callbacks in deployment configuration. Internal
|
|
428
466
|
shadow-DOM selectors and classes are not public API.
|
|
429
467
|
|
|
468
|
+
`theme="auto"` follows the browser's operating-system color preference. When the embedding application has
|
|
469
|
+
its own theme toggle, pass its resolved `"light"` or `"dark"` value to `NoodleAssistant` and every
|
|
470
|
+
`NoodleAppView`. Updates change the assistant in place and notify mounted MCP Apps through standard host
|
|
471
|
+
context.
|
|
472
|
+
|
|
430
473
|
Server branding controls customer name, themed logo/mark/avatar assets, semantic light/dark colors, density,
|
|
431
474
|
radius, typography, and automatic theme. `embeddedAssistant(...)` controls floating/inline/drawer layout,
|
|
432
475
|
position and dimensions, mobile and launcher/header/avatar/timestamp behavior, visible labels, suggested
|
|
@@ -3106,6 +3106,7 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3106
3106
|
let mountedTransport;
|
|
3107
3107
|
let destroyed = false;
|
|
3108
3108
|
let initialized = false;
|
|
3109
|
+
let hostContext = createAssistantAppHostContext(actions.theme);
|
|
3109
3110
|
let destroyPromise;
|
|
3110
3111
|
const renderTimer = setTimeout(() => {
|
|
3111
3112
|
if (initialized || !frame.isConnected) return;
|
|
@@ -3132,7 +3133,7 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3132
3133
|
message: { text: {} }
|
|
3133
3134
|
},
|
|
3134
3135
|
{
|
|
3135
|
-
hostContext
|
|
3136
|
+
hostContext
|
|
3136
3137
|
}
|
|
3137
3138
|
);
|
|
3138
3139
|
mountedBridge = bridge;
|
|
@@ -3207,6 +3208,7 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3207
3208
|
if (destroyed) return;
|
|
3208
3209
|
initialized = true;
|
|
3209
3210
|
clearTimeout(renderTimer);
|
|
3211
|
+
bridge.setHostContext(hostContext);
|
|
3210
3212
|
const current = options.getDetail?.() ?? detail;
|
|
3211
3213
|
void bridge.sendToolInput({ arguments: current.arguments ?? {} });
|
|
3212
3214
|
void bridge.sendToolResult({
|
|
@@ -3222,6 +3224,11 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3222
3224
|
},
|
|
3223
3225
|
{ once: true }
|
|
3224
3226
|
);
|
|
3227
|
+
const updateTheme = (theme) => {
|
|
3228
|
+
if (destroyed) return;
|
|
3229
|
+
hostContext = createAssistantAppHostContext(theme);
|
|
3230
|
+
if (initialized) mountedBridge?.setHostContext(hostContext);
|
|
3231
|
+
};
|
|
3225
3232
|
const destroy = () => {
|
|
3226
3233
|
if (destroyPromise) return destroyPromise;
|
|
3227
3234
|
destroyed = true;
|
|
@@ -3240,9 +3247,12 @@ function mountAssistantApp(detail, actions, options = {}) {
|
|
|
3240
3247
|
})();
|
|
3241
3248
|
return destroyPromise;
|
|
3242
3249
|
};
|
|
3243
|
-
mountedApps.set(card, { destroy });
|
|
3250
|
+
mountedApps.set(card, { destroy, updateTheme });
|
|
3244
3251
|
return card;
|
|
3245
3252
|
}
|
|
3253
|
+
function updateAssistantAppTheme(card, theme) {
|
|
3254
|
+
mountedApps.get(card)?.updateTheme(theme);
|
|
3255
|
+
}
|
|
3246
3256
|
function unmountAssistantApp(card) {
|
|
3247
3257
|
return mountedApps.get(card)?.destroy() ?? Promise.resolve();
|
|
3248
3258
|
}
|
|
@@ -7168,7 +7178,7 @@ function contrastWarnings(theme, mode) {
|
|
|
7168
7178
|
for (const [role, foreground, background] of pairs) {
|
|
7169
7179
|
if (!foreground || !background) continue;
|
|
7170
7180
|
const ratio = contrastRatio2(foreground, background);
|
|
7171
|
-
if (ratio >= 4.5) continue;
|
|
7181
|
+
if (ratio === void 0 || ratio >= 4.5) continue;
|
|
7172
7182
|
warnings.push({
|
|
7173
7183
|
code: "low_contrast",
|
|
7174
7184
|
theme: mode,
|
|
@@ -7182,13 +7192,16 @@ function contrastWarnings(theme, mode) {
|
|
|
7182
7192
|
return warnings;
|
|
7183
7193
|
}
|
|
7184
7194
|
function contrastRatio2(first, second) {
|
|
7185
|
-
const
|
|
7186
|
-
const
|
|
7195
|
+
const firstLuminance = luminance(first);
|
|
7196
|
+
const secondLuminance = luminance(second);
|
|
7197
|
+
if (firstLuminance === void 0 || secondLuminance === void 0) return void 0;
|
|
7198
|
+
const lighter = Math.max(firstLuminance, secondLuminance);
|
|
7199
|
+
const darker = Math.min(firstLuminance, secondLuminance);
|
|
7187
7200
|
return (lighter + 0.05) / (darker + 0.05);
|
|
7188
7201
|
}
|
|
7189
7202
|
function luminance(color) {
|
|
7190
7203
|
const match = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(color);
|
|
7191
|
-
if (!match) return
|
|
7204
|
+
if (!match) return void 0;
|
|
7192
7205
|
const values = match.slice(1).map((value) => {
|
|
7193
7206
|
const channel = Number.parseInt(value, 16) / 255;
|
|
7194
7207
|
return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;
|
|
@@ -8021,6 +8034,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
|
|
|
8021
8034
|
})
|
|
8022
8035
|
);
|
|
8023
8036
|
}
|
|
8037
|
+
for (const app of this.shadowRoot?.querySelectorAll(".noodle-app-card") ?? []) {
|
|
8038
|
+
updateAssistantAppTheme(app, mode);
|
|
8039
|
+
}
|
|
8024
8040
|
}
|
|
8025
8041
|
#setSessionState(state) {
|
|
8026
8042
|
this.#sessionState = state;
|
|
@@ -8196,6 +8212,7 @@ function registerNoodleAssistant() {
|
|
|
8196
8212
|
|
|
8197
8213
|
export {
|
|
8198
8214
|
mountAssistantApp,
|
|
8215
|
+
updateAssistantAppTheme,
|
|
8199
8216
|
unmountAssistantApp,
|
|
8200
8217
|
ASSISTANT_TAG_NAME,
|
|
8201
8218
|
NoodleAssistantElement,
|
|
@@ -8206,4 +8223,4 @@ export {
|
|
|
8206
8223
|
dompurify/dist/purify.es.mjs:
|
|
8207
8224
|
(*! @license DOMPurify 3.4.11 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.11/LICENSE *)
|
|
8208
8225
|
*/
|
|
8209
|
-
//# sourceMappingURL=chunk-
|
|
8226
|
+
//# sourceMappingURL=chunk-RSNMY27B.js.map
|