@noodleseed/assistant 1.9.0 → 1.11.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 CHANGED
@@ -247,6 +247,26 @@ interaction streams a continuation. `principalKey` is browser-local and never se
247
247
  whenever the authenticated user or tenant changes so the hook aborts and clears the previous session and
248
248
  transcript.
249
249
 
250
+ If the product deliberately sends a first turn on mount, make the effect cleanup-aware. React Strict Mode
251
+ discards the provisional effect, so a persistent "already sent" ref can suppress the stable remount:
252
+
253
+ ```tsx
254
+ import { useEffect } from "react";
255
+
256
+ useEffect(() => {
257
+ let active = true;
258
+ queueMicrotask(() => {
259
+ if (active) settle(client.sendMessage(initialMessage));
260
+ });
261
+ return () => {
262
+ active = false;
263
+ };
264
+ }, [client, initialMessage]);
265
+ ```
266
+
267
+ `settle` must await or catch the command promise as in the complete example; the same structured failure
268
+ also appears in the hook's `error` state.
269
+
250
270
  When the customer-owned transcript should render the linked MCP App itself, pass the typed `data-view`
251
271
  payload and the same client to the supported host component:
252
272
 
@@ -259,7 +279,7 @@ if (part.type === "data-view") {
259
279
  key={`${part.data.id}:${part.data.resourceUri}`}
260
280
  client={client}
261
281
  view={part.data}
262
- theme="dark"
282
+ theme={resolvedTheme}
263
283
  onError={(failure) => reportAssistantError(failure)}
264
284
  />
265
285
  );
@@ -269,7 +289,9 @@ if (part.type === "data-view") {
269
289
  `NoodleAppView` owns the double iframe and AppBridge. Its lifecycle identity is the supplied client plus
270
290
  `view.id` plus `view.resourceUri`: ordinary parent rerenders and fresh view/callback objects retain the
271
291
  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.
292
+ Do not also key an ancestor by the whole view object or a callback. Pass the embedding application's
293
+ resolved `"light"` or `"dark"` theme; later changes are published through MCP Apps host context without
294
+ replacing the iframe.
273
295
 
274
296
  Outside React, subscribe to the DOM-free AI SDK `UIMessage` state without registering a custom element or
275
297
  touching browser storage:
@@ -318,6 +340,24 @@ Use the lower-level `subscribe(...)` event stream only for transport and session
318
340
  do not belong in the transcript. The package uses the headless `ai` runtime only; React remains an optional
319
341
  peer isolated to the `/react` and `/react/client` entries.
320
342
 
343
+ For a custom progress surface, raw `tool_started` carries the direct invocation's call `id` and technical
344
+ `tool` name before execution. Map known tools through a finite application-owned label table and use a
345
+ neutral fallback such as "Working"; never turn an internal identifier into customer copy mechanically.
346
+ Keep one reserved region with `role="status"` and `aria-live="polite"` from submitted/thinking through tool
347
+ activity and the linked-view skeleton. `view_available` makes that view ready; a raw `error` event or chat
348
+ `error` state replaces the skeleton with `role="alert"`. Keep the skeleton's dimensions stable, mark its
349
+ decorative shapes `aria-hidden="true"`, and disable shimmer/transition animation under
350
+ `@media (prefers-reduced-motion: reduce)`.
351
+
352
+ The transport identity of a view is exactly `view.id + view.resourceUri`; different call IDs are distinct
353
+ invocations and must not be collapsed automatically. If the product intentionally owns one current panel
354
+ for a known resource, define an explicit application-owned slot map and replace only that slot:
355
+
356
+ ```ts
357
+ const viewSlots = new Map([["ui://workspace/current", "current-workspace"]]);
358
+ const renderKey = viewSlots.get(view.resourceUri) ?? `${view.id}:${view.resourceUri}`;
359
+ ```
360
+
321
361
  `clientContext` contains untrusted locale/timezone presentation hints and is evaluated for every turn.
322
362
  The client resolves a turn or interaction only after exactly one valid terminal `done` event followed by
323
363
  stream EOF. A truncated or malformed stream, duplicate `done`, or any frame after `done` is
@@ -393,10 +433,19 @@ exact control over assistant-specific roles:
393
433
  ```tsx
394
434
  <NoodleAssistant
395
435
  sessionEndpoint="/api/assistant/session"
436
+ theme={resolvedTheme}
396
437
  appearance={{
397
438
  light: {
398
- panel: { surface: "#FFFFFF", text: "#101828", border: "#E4E7EC" },
399
- composer: { surface: "#F9FAFB", text: "#101828", border: "#D0D5DD" },
439
+ panel: {
440
+ surface: "var(--app-surface)",
441
+ text: "var(--app-text)",
442
+ border: "var(--app-border)",
443
+ },
444
+ composer: {
445
+ surface: "var(--app-input)",
446
+ text: "var(--app-text)",
447
+ border: "var(--app-border)",
448
+ },
400
449
  confirmation: { surface: "#F8FAFC", text: "#101828", border: "#CBD5E1" },
401
450
  primaryButton: { surface: "#635BFF", text: "#FFFFFF" },
402
451
  },
@@ -405,11 +454,38 @@ exact control over assistant-specific roles:
405
454
  />
406
455
  ```
407
456
 
408
- The same object is available as `element.appearance`. It covers canvas, panel, header, assistant/user
409
- messages, composer, suggestions, confirmation, primary/secondary buttons, launcher, code, and MCP App frame
410
- roles in light and dark modes. Exact colors are preserved; insufficient contrast emits the typed
411
- `assistant-appearance-warning` event. Stable public CSS variables remain available for stylesheet-based
412
- integration:
457
+ The same object is available as `element.appearance`. CSS custom properties inherit through the assistant
458
+ host into its shadow tree, so `var(--app-token)` references reuse the embedding application's existing
459
+ tokens without copying literal colors. Exact parseable literal colors are preserved and checked;
460
+ insufficient contrast emits the typed `assistant-appearance-warning` event. Contrast for unresolved CSS
461
+ references remains the host application's responsibility.
462
+
463
+ The complete typed appearance role map is:
464
+
465
+ | Appearance role | Public CSS custom properties |
466
+ | --- | --- |
467
+ | `canvas` | `--ns-assistant-canvas` |
468
+ | `text` | `--ns-assistant-text` |
469
+ | `mutedText` | `--ns-assistant-muted-text` |
470
+ | `link` | `--ns-assistant-link` |
471
+ | `focus` | `--ns-assistant-focus` |
472
+ | `success` | `--ns-assistant-success` |
473
+ | `warning` | `--ns-assistant-warning` |
474
+ | `danger` | `--ns-assistant-danger` |
475
+ | `panel` | `--ns-assistant-panel`, `--ns-assistant-panel-text`, `--ns-assistant-panel-border` |
476
+ | `header` | `--ns-assistant-header`, `--ns-assistant-header-text`, `--ns-assistant-header-border` |
477
+ | `assistantMessage` | `--ns-assistant-assistant-message`, `--ns-assistant-assistant-message-text`, `--ns-assistant-assistant-message-border` |
478
+ | `userMessage` | `--ns-assistant-user-message`, `--ns-assistant-user-message-text`, `--ns-assistant-user-message-border` |
479
+ | `composer` | `--ns-assistant-composer`, `--ns-assistant-composer-text`, `--ns-assistant-composer-border` |
480
+ | `suggestion` | `--ns-assistant-suggestion`, `--ns-assistant-suggestion-text`, `--ns-assistant-suggestion-border` |
481
+ | `confirmation` | `--ns-assistant-confirmation`, `--ns-assistant-confirmation-text`, `--ns-assistant-confirmation-border` |
482
+ | `primaryButton` | `--ns-assistant-primary-button`, `--ns-assistant-primary-button-text`, `--ns-assistant-primary-button-border` |
483
+ | `secondaryButton` | `--ns-assistant-secondary-button`, `--ns-assistant-secondary-button-text`, `--ns-assistant-secondary-button-border` |
484
+ | `launcher` | `--ns-assistant-launcher`, `--ns-assistant-launcher-text`, `--ns-assistant-launcher-border` |
485
+ | `code` | `--ns-assistant-code`, `--ns-assistant-code-text`, `--ns-assistant-code-border` |
486
+ | `app` | `--ns-assistant-app`, `--ns-assistant-app-text`, `--ns-assistant-app-border` |
487
+
488
+ Stable public CSS variables also remain available directly for stylesheet-based integration:
413
489
 
414
490
  ```css
415
491
  noodle-assistant {
@@ -427,6 +503,11 @@ defaults. The public slots are `launcher-icon`,
427
503
  embedding-page integration API, not a way to put HTML or callbacks in deployment configuration. Internal
428
504
  shadow-DOM selectors and classes are not public API.
429
505
 
506
+ `theme="auto"` follows the browser's operating-system color preference. When the embedding application has
507
+ its own theme toggle, pass its resolved `"light"` or `"dark"` value to `NoodleAssistant` and every
508
+ `NoodleAppView`. Updates change the assistant in place and notify mounted MCP Apps through standard host
509
+ context.
510
+
430
511
  Server branding controls customer name, themed logo/mark/avatar assets, semantic light/dark colors, density,
431
512
  radius, typography, and automatic theme. `embeddedAssistant(...)` controls floating/inline/drawer layout,
432
513
  position and dimensions, mobile and launcher/header/avatar/timestamp behavior, visible labels, suggested
@@ -8360,6 +8360,11 @@ function toAssistantClientEvent(event) {
8360
8360
  return event;
8361
8361
  }
8362
8362
  break;
8363
+ case "tool_started":
8364
+ if (hasString(value, "id") && hasString(value, "tool") && hasOptionalTurnId(value)) {
8365
+ return event;
8366
+ }
8367
+ break;
8363
8368
  case "tool_proposed":
8364
8369
  if (hasString(value, "id") && hasString(value, "tool") && hasOptionalString(value.title) && hasOptionalString(value.description) && hasOptionalJson(value.arguments) && (value.reviewSchema === void 0 || isRecord2(value.reviewSchema)) && hasOptionalString(value.expiresAt) && (value.requiresConfirmation === void 0 || value.requiresConfirmation === true) && hasOptionalTurnId(value)) {
8365
8370
  return event;
@@ -9086,4 +9091,4 @@ export {
9086
9091
  AssistantClientError,
9087
9092
  createAssistantClient
9088
9093
  };
9089
- //# sourceMappingURL=chunk-RYQBXTLR.js.map
9094
+ //# sourceMappingURL=chunk-KRB2SXFD.js.map