@noodleseed/assistant 1.25.1 → 1.26.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.
Files changed (44) hide show
  1. package/README.md +54 -20
  2. package/dist/{app-view-element-BNkQab1B.d.ts → app-view-element-C_ATXseu.d.ts} +1 -1
  3. package/dist/{app-view-element-DhuiNW_x.d.cts → app-view-element-CiFVNIke.d.cts} +1 -1
  4. package/dist/app-view.cjs +5 -5
  5. package/dist/app-view.cjs.map +1 -1
  6. package/dist/app-view.d.cts +3 -3
  7. package/dist/app-view.d.ts +3 -3
  8. package/dist/app-view.js +2 -2
  9. package/dist/{appearance-B6vSg8Ub.d.cts → appearance-C24W6BRj.d.cts} +7 -3
  10. package/dist/{appearance-B6vSg8Ub.d.ts → appearance-C24W6BRj.d.ts} +7 -3
  11. package/dist/{chunk-5TYS2Q6S.js → chunk-5NBHHNI3.js} +2 -2
  12. package/dist/{chunk-FJYPE4GC.js → chunk-5PW6PXCI.js} +702 -122
  13. package/dist/chunk-5PW6PXCI.js.map +1 -0
  14. package/dist/{chunk-7BQHW37I.js → chunk-FNXAVRL5.js} +7 -1
  15. package/dist/{chunk-7BQHW37I.js.map → chunk-FNXAVRL5.js.map} +1 -1
  16. package/dist/{chunk-CF2SCDLF.js → chunk-XKTUXFGX.js} +6 -6
  17. package/dist/chunk-XKTUXFGX.js.map +1 -0
  18. package/dist/{client-BkogON2A.d.ts → client-BheCOERq.d.ts} +51 -2
  19. package/dist/{client-C07ppTU_.d.cts → client-BiMRVxjs.d.cts} +51 -2
  20. package/dist/client.cjs.map +1 -1
  21. package/dist/client.d.cts +2 -2
  22. package/dist/client.d.ts +2 -2
  23. package/dist/client.js +1 -1
  24. package/dist/embed.global.js +171 -89
  25. package/dist/index.cjs +709 -124
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +6 -53
  28. package/dist/index.d.ts +6 -53
  29. package/dist/index.js +3 -3
  30. package/dist/react/client.cjs.map +1 -1
  31. package/dist/react/client.d.cts +2 -2
  32. package/dist/react/client.d.ts +2 -2
  33. package/dist/react/client.js +1 -1
  34. package/dist/react.cjs +709 -124
  35. package/dist/react.cjs.map +1 -1
  36. package/dist/react.d.cts +4 -4
  37. package/dist/react.d.ts +4 -4
  38. package/dist/react.js +4 -4
  39. package/dist/server.d.cts +1 -1
  40. package/dist/server.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/dist/chunk-CF2SCDLF.js.map +0 -1
  43. package/dist/chunk-FJYPE4GC.js.map +0 -1
  44. /package/dist/{chunk-5TYS2Q6S.js.map → chunk-5NBHHNI3.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -15197,7 +15197,7 @@ __export(src_exports, {
15197
15197
  });
15198
15198
  module.exports = __toCommonJS(src_exports);
15199
15199
 
15200
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
15200
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
15201
15201
  init_v4();
15202
15202
  var RELATED_TASK_META_KEY = "io.modelcontextprotocol/related-task";
15203
15203
  var JSONRPC_VERSION = "2.0";
@@ -20594,7 +20594,7 @@ var pipelineType = ZodPipeline.create;
20594
20594
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/mini/parse.js
20595
20595
  init_core2();
20596
20596
 
20597
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
20597
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
20598
20598
  function isZ4Schema(s2) {
20599
20599
  const schema = s2;
20600
20600
  return !!schema._zod;
@@ -20657,7 +20657,7 @@ function getLiteralValue(schema) {
20657
20657
  return void 0;
20658
20658
  }
20659
20659
 
20660
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
20660
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
20661
20661
  function isTerminal(status) {
20662
20662
  return status === "completed" || status === "failed" || status === "cancelled";
20663
20663
  }
@@ -20665,7 +20665,7 @@ function isTerminal(status) {
20665
20665
  // ../../node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@4.4.3/node_modules/zod-to-json-schema/dist/esm/parsers/string.js
20666
20666
  var ALPHA_NUMERIC = new Set("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789");
20667
20667
 
20668
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
20668
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
20669
20669
  function getMethodLiteral(schema) {
20670
20670
  const shape = getObjectShape(schema);
20671
20671
  const methodSchema = shape?.method;
@@ -20686,7 +20686,7 @@ function parseWithCompat(schema, data) {
20686
20686
  return result.data;
20687
20687
  }
20688
20688
 
20689
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_supports-color@7.2.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
20689
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
20690
20690
  var DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
20691
20691
  var Protocol = class {
20692
20692
  constructor(_options) {
@@ -22343,7 +22343,7 @@ function updateAssistantAppTheme(card, theme) {
22343
22343
 
22344
22344
  // src/appearance.ts
22345
22345
  var common = {
22346
- fontFamily: "inherit",
22346
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
22347
22347
  monoFontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
22348
22348
  baseFontSize: 15,
22349
22349
  messageFontSize: 15,
@@ -22354,7 +22354,7 @@ var common = {
22354
22354
  buttonRadius: 999,
22355
22355
  launcherRadius: 999,
22356
22356
  spacing: 8,
22357
- backdropBlur: 18,
22357
+ backdropBlur: 6,
22358
22358
  motionScale: 1
22359
22359
  };
22360
22360
  var DEFAULT_APPEARANCE = {
@@ -22374,7 +22374,7 @@ var DEFAULT_APPEARANCE = {
22374
22374
  accent: "#C2410C",
22375
22375
  accentText: "#FFFFFF",
22376
22376
  link: "#9A3412",
22377
- divider: "#E4E4E7",
22377
+ divider: "rgba(0, 0, 0, 0.1)",
22378
22378
  focus: "#C2410C",
22379
22379
  success: "#16835D",
22380
22380
  warning: "#A45B00",
@@ -22382,7 +22382,7 @@ var DEFAULT_APPEARANCE = {
22382
22382
  overlay: "#18181B66",
22383
22383
  code: "#F1F1F3",
22384
22384
  widgetFrame: "#E4E4E7",
22385
- shadow: "0 4px 16px rgba(0, 0, 0, 0.06), 0 24px 70px rgba(0, 0, 0, 0.10)"
22385
+ shadow: "0 4px 16px rgba(0, 0, 0, 0.06)"
22386
22386
  },
22387
22387
  dark: {
22388
22388
  ...common,
@@ -22397,7 +22397,7 @@ var DEFAULT_APPEARANCE = {
22397
22397
  accent: "#FB923C",
22398
22398
  accentText: "#1C0A02",
22399
22399
  link: "#FDBA74",
22400
- divider: "#292524",
22400
+ divider: "rgba(255, 255, 255, 0.1)",
22401
22401
  focus: "#FB923C",
22402
22402
  success: "#58C69A",
22403
22403
  warning: "#F2B45F",
@@ -22405,15 +22405,15 @@ var DEFAULT_APPEARANCE = {
22405
22405
  overlay: "#00000099",
22406
22406
  code: "#26262C",
22407
22407
  widgetFrame: "#34343B",
22408
- shadow: "0 8px 32px rgba(0, 0, 0, 0.48)"
22408
+ shadow: "0 8px 32px rgba(0, 0, 0, 0.4)"
22409
22409
  }
22410
22410
  },
22411
22411
  layout: {
22412
22412
  mode: "floating",
22413
- position: "bottom-right",
22414
- panelWidth: 520,
22415
- panelMinHeight: 540,
22416
- panelMaxHeight: 820,
22413
+ position: "bottom-center",
22414
+ panelWidth: 970,
22415
+ panelMinHeight: 0,
22416
+ panelMaxHeight: 1025,
22417
22417
  edgeOffset: 20,
22418
22418
  zIndex: 2147483e3,
22419
22419
  density: "comfortable",
@@ -22426,11 +22426,13 @@ var DEFAULT_APPEARANCE = {
22426
22426
  showLauncher: true,
22427
22427
  showHeader: true,
22428
22428
  showAvatars: true,
22429
- showTimestamps: false
22429
+ showTimestamps: false,
22430
+ showPoweredBy: true
22430
22431
  },
22431
22432
  labels: {
22432
- welcomeHeading: "How can I help?",
22433
+ welcomeHeading: "",
22433
22434
  welcomeMessage: "",
22435
+ launcherPlaceholder: "Chat with us",
22434
22436
  composerPlaceholder: "Ask a question\u2026",
22435
22437
  thinking: "Thinking",
22436
22438
  send: "Send",
@@ -22464,11 +22466,12 @@ var DEFAULT_APPEARANCE = {
22464
22466
  },
22465
22467
  presentation: {
22466
22468
  panel: {
22467
- surface: "glass",
22469
+ surface: "solid",
22468
22470
  elevation: "soft",
22469
22471
  border: "subtle"
22470
22472
  },
22471
22473
  launcher: {
22474
+ style: "pill",
22472
22475
  icon: "brand-mark",
22473
22476
  size: "md",
22474
22477
  status: "none",
@@ -22478,7 +22481,11 @@ var DEFAULT_APPEARANCE = {
22478
22481
  composer: { leadingIcon: "none", sendIcon: "arrow-up", shape: "pill" },
22479
22482
  messages: { userStyle: "bubble", assistantStyle: "plain" }
22480
22483
  },
22481
- suggestedPrompts: [],
22484
+ suggestedPrompts: [
22485
+ "What products do you have?",
22486
+ "Tell me about your business",
22487
+ "How can I get in touch?"
22488
+ ],
22482
22489
  locale: "en",
22483
22490
  direction: "auto"
22484
22491
  };
@@ -22494,7 +22501,7 @@ function resolveAppearance(input = {}) {
22494
22501
  mark: themedAsset(branding?.mark)
22495
22502
  },
22496
22503
  theme: {
22497
- defaultMode: branding?.colorScheme ?? DEFAULT_APPEARANCE.theme.defaultMode,
22504
+ defaultMode: assistant?.theme ?? branding?.colorScheme ?? DEFAULT_APPEARANCE.theme.defaultMode,
22498
22505
  light: resolveTheme("light", branding),
22499
22506
  dark: resolveTheme("dark", branding)
22500
22507
  },
@@ -22505,9 +22512,17 @@ function resolveAppearance(input = {}) {
22505
22512
  ...assistant?.layout?.edgeOffset === void 0 ? {} : { edgeOffset: boundedNumber(assistant.layout.edgeOffset, 0, 96) }
22506
22513
  },
22507
22514
  behavior: { ...DEFAULT_APPEARANCE.behavior, ...assistant?.behavior },
22508
- labels: { ...DEFAULT_APPEARANCE.labels, ...assistant?.labels },
22515
+ labels: {
22516
+ ...DEFAULT_APPEARANCE.labels,
22517
+ ...branding?.name ? { launcherPlaceholder: `Chat with ${branding.name}` } : {},
22518
+ ...assistant?.labels
22519
+ },
22509
22520
  presentation: resolvePresentation(assistant?.presentation),
22510
- suggestedPrompts: assistant?.suggestedPrompts ?? DEFAULT_APPEARANCE.suggestedPrompts,
22521
+ suggestedPrompts: assistant?.suggestedPrompts ?? (branding?.name ? [
22522
+ "What products do you have?",
22523
+ `Tell me about ${branding.name}`,
22524
+ "How can I get in touch?"
22525
+ ] : DEFAULT_APPEARANCE.suggestedPrompts),
22511
22526
  ...assistant?.privacyUrl ? { privacyUrl: assistant.privacyUrl } : {},
22512
22527
  ...assistant?.termsUrl ? { termsUrl: assistant.termsUrl } : {},
22513
22528
  locale: assistant?.locale ?? DEFAULT_APPEARANCE.locale,
@@ -24778,6 +24793,10 @@ async function resolve(value) {
24778
24793
  return Promise.resolve(value);
24779
24794
  }
24780
24795
 
24796
+ // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js
24797
+ init_external();
24798
+ init_external();
24799
+
24781
24800
  // ../../node_modules/.pnpm/ai@6.0.201_zod@4.4.3/node_modules/ai/dist/index.mjs
24782
24801
  init_v4();
24783
24802
  init_v4();
@@ -27520,6 +27539,11 @@ function isRecord3(value) {
27520
27539
  // src/session-source.ts
27521
27540
  var NOODLE_CLOUD_URL = "https://cloud.noodleseed.dev";
27522
27541
  var PUBLIC_SESSION_PATH = "/v1/assistant/public-sessions";
27542
+ var PUBLIC_CONFIGURATION_PATH = "/v1/assistant/public-configurations";
27543
+ function publicConfigurationUrl(serviceUrl, embedId) {
27544
+ const base = (serviceUrl || NOODLE_CLOUD_URL).replace(/\/+$/, "");
27545
+ return `${base}${PUBLIC_CONFIGURATION_PATH}/${encodeURIComponent(embedId)}`;
27546
+ }
27523
27547
  function resolveSessionSource(options) {
27524
27548
  const { sessionEndpoint, embedId, serviceUrl } = options;
27525
27549
  if (Boolean(embedId) === Boolean(sessionEndpoint)) {
@@ -29031,11 +29055,11 @@ function createDOMPurify() {
29031
29055
  const originalDocument = document2;
29032
29056
  const currentScript = originalDocument.currentScript;
29033
29057
  window2.DocumentFragment;
29034
- const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
29058
+ const HTMLTemplateElement = window2.HTMLTemplateElement, Node = window2.Node, Element2 = window2.Element, NodeFilter = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
29035
29059
  _window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap;
29036
29060
  window2.HTMLFormElement;
29037
29061
  const DOMParser = window2.DOMParser, trustedTypes = window2.trustedTypes;
29038
- const ElementPrototype = Element.prototype;
29062
+ const ElementPrototype = Element2.prototype;
29039
29063
  const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
29040
29064
  const remove = lookupGetter(ElementPrototype, "remove");
29041
29065
  const getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
@@ -31685,19 +31709,40 @@ function queryRequired(root, selector) {
31685
31709
  if (!element) throw new Error(`assistant renderer is missing ${selector}`);
31686
31710
  return element;
31687
31711
  }
31688
- function assistantElementMarkup(appearance, open, styles) {
31712
+ function assistantElementMarkup(appearance, styles) {
31689
31713
  return `${styles}
31690
- <button class="launcher" type="button" aria-label="${escapeAttribute(appearance.labels.open)}" aria-controls="assistant-panel" aria-expanded="${String(open)}"><slot name="launcher-icon"></slot><span class="visually-hidden" data-session-status aria-live="polite" hidden></span></button>
31714
+ <div class="launcher">
31715
+ <slot name="launcher-icon"></slot>
31716
+ <span class="launcher-loader" aria-hidden="true"></span>
31717
+ <button class="launcher-trigger" type="button" aria-label="${escapeAttribute(appearance.labels.open)}" aria-controls="assistant-launcher-form" aria-expanded="false">
31718
+ <span class="launcher-label">${escapeAttribute(appearance.labels.launcherPlaceholder)}</span>
31719
+ <span class="launcher-arrow" aria-hidden="true"></span>
31720
+ </button>
31721
+ <form class="launcher-form" id="assistant-launcher-form" aria-hidden="true" autocomplete="off">
31722
+ <input class="launcher-input" type="text" aria-label="${escapeAttribute(appearance.labels.launcherPlaceholder)}" placeholder="${escapeAttribute(appearance.labels.launcherPlaceholder)}" tabindex="-1">
31723
+ <button class="launcher-send" type="submit" aria-label="${escapeAttribute(appearance.labels.send)}"></button>
31724
+ </form>
31725
+ <span class="visually-hidden" data-session-status aria-live="polite" hidden></span>
31726
+ </div>
31691
31727
  <section class="panel" id="assistant-panel" role="dialog" aria-label="${escapeAttribute(appearance.brand.name)}">
31692
31728
  <header><slot name="header-leading"></slot><img class="brand-logo" alt=""><strong></strong><slot name="header-actions"></slot><button class="close" type="button" aria-label="${escapeAttribute(appearance.labels.close)}"></button></header>
31693
31729
  <div class="welcome"><slot name="empty-state"></slot></div>
31694
- <div class="suggested-prompts"></div>
31695
31730
  <div class="messages-region">
31696
31731
  <div class="messages" aria-live="polite"></div>
31697
31732
  <button class="new-messages" type="button" aria-label="${escapeAttribute(appearance.labels.newMessages)}" hidden></button>
31698
31733
  </div>
31699
- <form><slot name="composer-leading"></slot><textarea rows="1"></textarea><button class="send" type="submit"></button><slot name="composer-trailing"></slot></form>
31734
+ <div class="input-section">
31735
+ <div class="suggested-prompts"></div>
31736
+ <form class="composer"><slot name="composer-leading"></slot><textarea rows="1"></textarea><button class="send" type="submit"></button><slot name="composer-trailing"></slot></form>
31737
+ </div>
31700
31738
  <nav class="legal" aria-label="Legal"></nav>
31739
+ <div class="powered-by-row">
31740
+ <a class="powered-by" href="https://noodleseed.com" target="_blank" rel="noopener noreferrer">
31741
+ <span>Powered by</span>
31742
+ <span class="powered-by-icon" aria-hidden="true"><svg width="14" height="14" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="16" height="16" rx="8" fill="currentColor" fill-opacity="0.12"></rect><path d="M8.58023 12.8485C6.27833 12.8463 4.41315 11.0141 4.42117 8.75681L4.43588 4.61714L8.66254 4.62118C10.9644 4.62339 12.8296 6.45561 12.8216 8.71287C12.8135 10.9975 10.9128 12.8507 8.58023 12.8485Z" fill="currentColor"></path><path d="M8.82627 4.76869C11.1282 4.7709 12.9933 6.60312 12.9853 8.86038L12.9706 13L8.74395 12.996C6.44206 12.9938 4.57687 11.1616 4.5849 8.90432C4.59302 6.6197 6.49364 4.76646 8.82627 4.76869Z" fill="currentColor"></path><ellipse cx="3.69536" cy="3.68106" rx="0.695363" ry="0.681056" fill="currentColor"></ellipse></svg></span>
31743
+ <span class="powered-by-name">Noodle Seed</span>
31744
+ </a>
31745
+ </div>
31701
31746
  <slot name="conversation-footer"></slot>
31702
31747
  </section>`;
31703
31748
  }
@@ -31716,6 +31761,230 @@ function appendLegalLinks(legal, appearance) {
31716
31761
  }
31717
31762
  }
31718
31763
 
31764
+ // src/element-theme-resolution.ts
31765
+ function resolveAssistantTheme(input) {
31766
+ if (input.configured === "light" || input.configured === "dark") return input.configured;
31767
+ const hostMode = resolveHostTheme(input.host, input.media);
31768
+ return input.configured === "invert" ? opposite(hostMode) : hostMode;
31769
+ }
31770
+ function resolveHostTheme(host, media) {
31771
+ const view = host.ownerDocument.defaultView;
31772
+ for (let node = host.parentElement; node; node = node.parentElement) {
31773
+ const declared = declaredTheme(node);
31774
+ if (declared) return declared;
31775
+ const computed = computedTheme(view?.getComputedStyle(node).colorScheme);
31776
+ if (computed) return computed;
31777
+ }
31778
+ return media?.matches ? "dark" : "light";
31779
+ }
31780
+ function computedTheme(colorScheme) {
31781
+ const modes = colorScheme?.split(/\s+/) ?? [];
31782
+ if (modes.includes("dark") && !modes.includes("light")) return "dark";
31783
+ if (modes.includes("light") && !modes.includes("dark")) return "light";
31784
+ return void 0;
31785
+ }
31786
+ function declaredTheme(element) {
31787
+ const value = element.getAttribute("data-theme") ?? element.getAttribute("data-color-scheme") ?? element.getAttribute("data-mode");
31788
+ if (value === "dark" || value === "light") return value;
31789
+ if (element.classList.contains("dark")) return "dark";
31790
+ if (element.classList.contains("light")) return "light";
31791
+ return void 0;
31792
+ }
31793
+ function opposite(mode) {
31794
+ return mode === "dark" ? "light" : "dark";
31795
+ }
31796
+
31797
+ // src/element-host-environment-controller.ts
31798
+ var AssistantElementHostEnvironmentController = class {
31799
+ #host;
31800
+ #appearance;
31801
+ #applyTheme;
31802
+ #close;
31803
+ #media;
31804
+ #themeObserver;
31805
+ constructor(options) {
31806
+ this.#host = options.host;
31807
+ this.#appearance = options.appearance;
31808
+ this.#applyTheme = options.applyTheme;
31809
+ this.#close = options.close;
31810
+ }
31811
+ get media() {
31812
+ return this.#media;
31813
+ }
31814
+ resolvedTheme() {
31815
+ return resolveAssistantTheme({
31816
+ host: this.#host,
31817
+ configured: this.#host.getAttribute("theme") ?? this.#appearance().theme.defaultMode,
31818
+ ...this.#media ? { media: this.#media } : {}
31819
+ });
31820
+ }
31821
+ connect() {
31822
+ this.disconnect();
31823
+ this.#media = globalThis.matchMedia?.("(prefers-color-scheme: dark)");
31824
+ this.#media?.addEventListener("change", this.#applyTheme);
31825
+ this.#themeObserver = new MutationObserver(this.#applyTheme);
31826
+ for (let node = this.#host.parentElement; node; node = node.parentElement) {
31827
+ this.#themeObserver.observe(node, {
31828
+ attributes: true,
31829
+ attributeFilter: ["class", "data-theme", "data-color-scheme", "data-mode", "style"]
31830
+ });
31831
+ }
31832
+ document.addEventListener("keydown", this.#handleDocumentKeydown);
31833
+ document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
31834
+ }
31835
+ disconnect() {
31836
+ this.#media?.removeEventListener("change", this.#applyTheme);
31837
+ this.#media = void 0;
31838
+ this.#themeObserver?.disconnect();
31839
+ this.#themeObserver = void 0;
31840
+ document.removeEventListener("keydown", this.#handleDocumentKeydown);
31841
+ document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
31842
+ }
31843
+ #handleDocumentKeydown = (event) => {
31844
+ if (event.key === "Escape" && this.#host.hasAttribute("open") && this.#appearance().behavior.closeOnEscape) {
31845
+ this.#close();
31846
+ }
31847
+ };
31848
+ #handleDocumentPointerDown = (event) => {
31849
+ if (this.#host.hasAttribute("open") && this.#appearance().behavior.closeOnOutsideClick && !event.composedPath().includes(this.#host)) {
31850
+ this.#close();
31851
+ }
31852
+ };
31853
+ };
31854
+
31855
+ // src/element-launcher-controller.ts
31856
+ var AssistantElementLauncherController = class {
31857
+ #host;
31858
+ #appearance;
31859
+ #openPanel;
31860
+ #sendMessage;
31861
+ #root;
31862
+ constructor(options) {
31863
+ this.#host = options.host;
31864
+ this.#appearance = options.appearance;
31865
+ this.#openPanel = options.openPanel;
31866
+ this.#sendMessage = options.sendMessage;
31867
+ }
31868
+ connect(root) {
31869
+ this.disconnect();
31870
+ this.#root = root;
31871
+ queryRequired(root, ".launcher").addEventListener(
31872
+ "click",
31873
+ this.#handleLauncherClick
31874
+ );
31875
+ queryRequired(root, ".launcher-trigger").addEventListener(
31876
+ "click",
31877
+ this.#handleTrigger
31878
+ );
31879
+ queryRequired(root, ".launcher-form").addEventListener(
31880
+ "submit",
31881
+ this.#handleSubmit
31882
+ );
31883
+ queryRequired(root, ".launcher-input").addEventListener(
31884
+ "keydown",
31885
+ this.#handleInputKeydown
31886
+ );
31887
+ document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
31888
+ this.sync();
31889
+ }
31890
+ disconnect() {
31891
+ document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
31892
+ this.#root = void 0;
31893
+ }
31894
+ sync() {
31895
+ const root = this.#root;
31896
+ if (!root) return;
31897
+ const appearance = this.#appearance();
31898
+ const style = appearance.presentation.launcher.style;
31899
+ this.#host.dataset.launcherStyle = style;
31900
+ const trigger = queryRequired(root, ".launcher-trigger");
31901
+ const label = queryRequired(root, ".launcher-label");
31902
+ const input = queryRequired(root, ".launcher-input");
31903
+ label.textContent = appearance.labels.launcherPlaceholder;
31904
+ input.placeholder = appearance.labels.launcherPlaceholder;
31905
+ input.setAttribute("aria-label", appearance.labels.launcherPlaceholder);
31906
+ trigger.setAttribute("aria-label", appearance.labels.open);
31907
+ queryRequired(root, ".launcher-send").setAttribute(
31908
+ "aria-label",
31909
+ appearance.labels.send
31910
+ );
31911
+ queryRequired(root, ".launcher").hidden = !appearance.behavior.showLauncher;
31912
+ queryRequired(root, ".powered-by-row").hidden = !appearance.behavior.showPoweredBy;
31913
+ if (style === "bubble" || this.#host.hasAttribute("open")) this.collapse(true);
31914
+ }
31915
+ collapse(force = false) {
31916
+ const root = this.#root;
31917
+ if (!root) return;
31918
+ const input = queryRequired(root, ".launcher-input");
31919
+ if (!force && input.value.trim()) return;
31920
+ this.#host.removeAttribute("launcher-expanded");
31921
+ const form = queryRequired(root, ".launcher-form");
31922
+ const trigger = queryRequired(root, ".launcher-trigger");
31923
+ form.setAttribute("aria-hidden", "true");
31924
+ trigger.setAttribute("aria-expanded", "false");
31925
+ input.tabIndex = -1;
31926
+ input.blur();
31927
+ }
31928
+ focusTrigger() {
31929
+ this.#root?.querySelector(".launcher-trigger")?.focus();
31930
+ }
31931
+ #expand() {
31932
+ const root = this.#root;
31933
+ if (!root || this.#appearance().presentation.launcher.style === "bubble") return;
31934
+ this.#host.setAttribute("launcher-expanded", "");
31935
+ const form = queryRequired(root, ".launcher-form");
31936
+ const trigger = queryRequired(root, ".launcher-trigger");
31937
+ const input = queryRequired(root, ".launcher-input");
31938
+ form.setAttribute("aria-hidden", "false");
31939
+ trigger.setAttribute("aria-expanded", "true");
31940
+ input.tabIndex = 0;
31941
+ requestAnimationFrame(() => {
31942
+ if (this.#host.hasAttribute("launcher-expanded")) input.focus();
31943
+ });
31944
+ }
31945
+ #handleTrigger = () => {
31946
+ if (this.#appearance().presentation.launcher.style === "bubble") {
31947
+ this.#openPanel();
31948
+ return;
31949
+ }
31950
+ this.#expand();
31951
+ };
31952
+ #handleLauncherClick = (event) => {
31953
+ if (event.composedPath().some(
31954
+ (target) => target instanceof Element && target.matches(".launcher-trigger, .launcher-form")
31955
+ )) {
31956
+ return;
31957
+ }
31958
+ this.#handleTrigger();
31959
+ };
31960
+ #handleSubmit = (event) => {
31961
+ event.preventDefault();
31962
+ const input = this.#root?.querySelector(".launcher-input");
31963
+ const message = input?.value.trim() ?? "";
31964
+ if (input) input.value = "";
31965
+ this.#openPanel();
31966
+ if (message) this.#sendMessage(message);
31967
+ };
31968
+ #handleInputKeydown = (event) => {
31969
+ if (event.key === "Enter" && !event.isComposing) {
31970
+ event.preventDefault();
31971
+ this.#root?.querySelector(".launcher-form")?.requestSubmit();
31972
+ return;
31973
+ }
31974
+ if (event.key !== "Escape") return;
31975
+ event.preventDefault();
31976
+ event.stopPropagation();
31977
+ const input = this.#root?.querySelector(".launcher-input");
31978
+ if (input) input.value = "";
31979
+ this.collapse(true);
31980
+ this.focusTrigger();
31981
+ };
31982
+ #handleDocumentPointerDown = (event) => {
31983
+ if (event.composedPath().includes(this.#host)) return;
31984
+ this.collapse();
31985
+ };
31986
+ };
31987
+
31719
31988
  // src/element-page-context-controller.ts
31720
31989
  var AssistantElementPageContextController = class {
31721
31990
  #snapshot;
@@ -31769,10 +32038,12 @@ var AssistantElementPresentationGate = class {
31769
32038
  syncOpenState() {
31770
32039
  const open = this.#host.hasAttribute("open");
31771
32040
  const presentationReady = this.#host.hasAttribute("data-presentation-ready");
31772
- const launcher = this.#host.shadowRoot?.querySelector(".launcher");
31773
- launcher?.setAttribute("aria-expanded", String(open && presentationReady));
31774
- launcher?.setAttribute("aria-busy", String(open && !presentationReady));
31775
- if (launcher) launcher.disabled = open && !presentationReady;
32041
+ const publicConfigurationLoading = this.#host.hasAttribute("data-public-configuration-loading");
32042
+ const presentationBlocked = !presentationReady && (open || publicConfigurationLoading);
32043
+ const launcher = this.#host.shadowRoot?.querySelector(".launcher-trigger");
32044
+ launcher?.setAttribute("aria-busy", String(presentationBlocked));
32045
+ if (launcher) launcher.disabled = presentationBlocked;
32046
+ this.#host.shadowRoot?.querySelector(".panel")?.setAttribute("aria-hidden", String(!(open && presentationReady)));
31776
32047
  if (open && this.#host.isConnected) this.#primeSession();
31777
32048
  }
31778
32049
  reveal() {
@@ -31783,6 +32054,233 @@ var AssistantElementPresentationGate = class {
31783
32054
  }
31784
32055
  };
31785
32056
 
32057
+ // src/assistant-configuration-schema.ts
32058
+ var hexColorSchema = external_exports.string().regex(/^#[0-9A-Fa-f]{6}$/);
32059
+ var browserAssetUrlSchema = external_exports.string().trim().url().refine(isSecureBrowserAssetUrl, "must use https (http is allowed only for loopback testing)");
32060
+ var httpsUrlSchema = external_exports.string().trim().url().refine(isHttpsUrl2, "must use https");
32061
+ var brandAssetSchema = external_exports.object({
32062
+ uri: browserAssetUrlSchema,
32063
+ darkUri: browserAssetUrlSchema.optional(),
32064
+ alt: external_exports.string().trim().min(1).max(240)
32065
+ }).strict();
32066
+ var brandThemeSchema = external_exports.object({
32067
+ surface: hexColorSchema.optional(),
32068
+ surfaceRaised: hexColorSchema.optional(),
32069
+ surfaceMuted: hexColorSchema.optional(),
32070
+ text: hexColorSchema.optional(),
32071
+ textMuted: hexColorSchema.optional(),
32072
+ accent: hexColorSchema.optional(),
32073
+ accentText: hexColorSchema.optional(),
32074
+ link: hexColorSchema.optional(),
32075
+ border: hexColorSchema.optional(),
32076
+ borderStrong: hexColorSchema.optional(),
32077
+ focus: hexColorSchema.optional(),
32078
+ success: hexColorSchema.optional(),
32079
+ warning: hexColorSchema.optional(),
32080
+ danger: hexColorSchema.optional(),
32081
+ code: hexColorSchema.optional()
32082
+ }).strict();
32083
+ var brandingSchema = external_exports.object({
32084
+ name: external_exports.string().trim().min(1).max(160).optional(),
32085
+ accent: hexColorSchema.optional(),
32086
+ surface: hexColorSchema.optional(),
32087
+ surfaceDark: hexColorSchema.optional(),
32088
+ logo: brandAssetSchema.optional(),
32089
+ mark: brandAssetSchema.optional(),
32090
+ avatar: brandAssetSchema.optional(),
32091
+ theme: external_exports.object({ light: brandThemeSchema.optional(), dark: brandThemeSchema.optional() }).strict().optional(),
32092
+ radius: external_exports.enum(["none", "sm", "md", "lg"]).optional(),
32093
+ density: external_exports.enum(["compact", "comfortable"]).optional(),
32094
+ typography: external_exports.enum(["system", "serif", "mono"]).optional(),
32095
+ colorScheme: external_exports.enum(["auto", "light", "dark"]).optional()
32096
+ }).strict();
32097
+ var labelsSchema = external_exports.object({
32098
+ welcomeHeading: external_exports.string().trim().min(1).max(160).optional(),
32099
+ welcomeMessage: external_exports.string().max(1e3).optional(),
32100
+ launcherPlaceholder: external_exports.string().trim().min(1).max(160).optional(),
32101
+ composerPlaceholder: external_exports.string().trim().min(1).max(160).optional(),
32102
+ thinking: external_exports.string().trim().min(1).max(80).optional(),
32103
+ send: external_exports.string().trim().min(1).max(80).optional(),
32104
+ stop: external_exports.string().trim().min(1).max(80).optional(),
32105
+ close: external_exports.string().trim().min(1).max(80).optional(),
32106
+ open: external_exports.string().trim().min(1).max(80).optional(),
32107
+ confirm: external_exports.string().trim().min(1).max(80).optional(),
32108
+ decline: external_exports.string().trim().min(1).max(80).optional(),
32109
+ cancel: external_exports.string().trim().min(1).max(80).optional(),
32110
+ confirmationHeading: external_exports.string().trim().min(1).max(120).optional(),
32111
+ additionalDetails: external_exports.string().trim().min(1).max(120).optional(),
32112
+ redacted: external_exports.string().trim().min(1).max(120).optional(),
32113
+ completed: external_exports.string().trim().min(1).max(80).optional(),
32114
+ stopped: external_exports.string().trim().min(1).max(80).optional(),
32115
+ copy: external_exports.string().trim().min(1).max(80).optional(),
32116
+ newMessages: external_exports.string().trim().min(1).max(80).optional(),
32117
+ reconnect: external_exports.string().trim().min(1).max(80).optional(),
32118
+ newConversation: external_exports.string().trim().min(1).max(80).optional(),
32119
+ retry: external_exports.string().trim().min(1).max(80).optional(),
32120
+ unavailable: external_exports.string().trim().min(1).max(240).optional(),
32121
+ sessionExpired: external_exports.string().trim().min(1).max(240).optional(),
32122
+ sessionIdle: external_exports.string().trim().min(1).max(120).optional(),
32123
+ sessionLoading: external_exports.string().trim().min(1).max(120).optional(),
32124
+ sessionReady: external_exports.string().trim().min(1).max(120).optional(),
32125
+ sessionError: external_exports.string().trim().min(1).max(120).optional(),
32126
+ signInHeading: external_exports.string().trim().min(1).max(120).optional(),
32127
+ signInBody: external_exports.string().max(240).optional(),
32128
+ signInAction: external_exports.string().trim().min(1).max(80).optional(),
32129
+ signUpAction: external_exports.string().trim().min(1).max(80).optional()
32130
+ }).strict();
32131
+ var presentationSchema = external_exports.object({
32132
+ panel: external_exports.object({
32133
+ surface: external_exports.enum(["solid", "glass"]).optional(),
32134
+ elevation: external_exports.enum(["soft", "dramatic"]).optional(),
32135
+ border: external_exports.enum(["subtle", "strong"]).optional(),
32136
+ radius: external_exports.number().int().min(0).max(64).optional()
32137
+ }).strict().optional(),
32138
+ launcher: external_exports.object({
32139
+ style: external_exports.enum(["pill", "bubble"]).optional(),
32140
+ icon: external_exports.enum(["brand-mark", "chat", "none"]).optional(),
32141
+ size: external_exports.enum(["md", "lg"]).optional(),
32142
+ status: external_exports.enum(["none", "session"]).optional(),
32143
+ effect: external_exports.enum(["none", "pulse"]).optional()
32144
+ }).strict().optional(),
32145
+ header: external_exports.object({
32146
+ mark: external_exports.enum(["none", "brand-mark", "status"]).optional(),
32147
+ badge: external_exports.object({
32148
+ text: external_exports.string().trim().min(1).max(80),
32149
+ tone: external_exports.enum(["neutral", "success", "warning", "danger"]).optional(),
32150
+ indicator: external_exports.boolean().optional()
32151
+ }).strict().optional()
32152
+ }).strict().optional(),
32153
+ composer: external_exports.object({
32154
+ leadingIcon: external_exports.enum(["none", "brand-mark"]).optional(),
32155
+ sendIcon: external_exports.enum(["arrow-up", "paper-plane"]).optional(),
32156
+ shape: external_exports.enum(["rounded", "pill"]).optional()
32157
+ }).strict().optional(),
32158
+ messages: external_exports.object({
32159
+ userStyle: external_exports.enum(["bubble", "accent"]).optional(),
32160
+ assistantStyle: external_exports.enum(["plain", "bubble"]).optional()
32161
+ }).strict().optional()
32162
+ }).strict();
32163
+ var assistantUiSchema = external_exports.object({
32164
+ theme: external_exports.enum(["auto", "light", "dark", "invert"]).optional(),
32165
+ layout: external_exports.object({
32166
+ mode: external_exports.enum(["floating", "inline", "drawer"]).optional(),
32167
+ position: external_exports.enum(["bottom-left", "bottom-center", "bottom-right"]).optional(),
32168
+ panelWidth: external_exports.number().int().min(280).max(1200).optional(),
32169
+ panelMinHeight: external_exports.number().int().min(240).max(1600).optional(),
32170
+ panelMaxHeight: external_exports.number().int().min(320).max(2400).optional(),
32171
+ edgeOffset: external_exports.number().int().min(0).max(96).optional(),
32172
+ zIndex: external_exports.number().int().min(0).max(2147483647).optional(),
32173
+ density: external_exports.enum(["compact", "comfortable"]).optional(),
32174
+ mobileFullscreen: external_exports.boolean().optional()
32175
+ }).strict().optional(),
32176
+ behavior: external_exports.object({
32177
+ startOpen: external_exports.boolean().optional(),
32178
+ closeOnEscape: external_exports.boolean().optional(),
32179
+ closeOnOutsideClick: external_exports.boolean().optional(),
32180
+ showLauncher: external_exports.boolean().optional(),
32181
+ showHeader: external_exports.boolean().optional(),
32182
+ showAvatars: external_exports.boolean().optional(),
32183
+ showTimestamps: external_exports.boolean().optional(),
32184
+ showPoweredBy: external_exports.boolean().optional()
32185
+ }).strict().optional(),
32186
+ labels: labelsSchema.optional(),
32187
+ presentation: presentationSchema.optional(),
32188
+ suggestedPrompts: external_exports.array(external_exports.string().trim().min(1).max(240)).max(8).optional(),
32189
+ privacyUrl: httpsUrlSchema.optional(),
32190
+ termsUrl: httpsUrlSchema.optional(),
32191
+ locale: external_exports.string().trim().min(2).max(35).optional(),
32192
+ direction: external_exports.enum(["ltr", "rtl", "auto"]).optional()
32193
+ }).strict();
32194
+ var assistantConfigurationSchema = external_exports.object({ branding: brandingSchema.optional(), assistant: assistantUiSchema.optional() }).strict();
32195
+ function parseAssistantConfiguration(value) {
32196
+ const parsed = assistantConfigurationSchema.safeParse(value);
32197
+ return parsed.success ? parsed.data : void 0;
32198
+ }
32199
+ function isHttpsUrl2(value) {
32200
+ try {
32201
+ return new URL(value).protocol === "https:";
32202
+ } catch {
32203
+ return false;
32204
+ }
32205
+ }
32206
+ function isSecureBrowserAssetUrl(value) {
32207
+ try {
32208
+ const url2 = new URL(value);
32209
+ if (url2.protocol === "https:") return true;
32210
+ if (url2.protocol !== "http:") return false;
32211
+ return url2.hostname === "localhost" || url2.hostname === "127.0.0.1" || url2.hostname === "[::1]";
32212
+ } catch {
32213
+ return false;
32214
+ }
32215
+ }
32216
+
32217
+ // src/element-public-configuration-controller.ts
32218
+ var AssistantElementPublicConfigurationController = class {
32219
+ #source;
32220
+ #apply;
32221
+ #loadingChanged;
32222
+ #generation = 0;
32223
+ #bootstrap;
32224
+ #abort;
32225
+ constructor(source, apply2, loadingChanged) {
32226
+ this.#source = source;
32227
+ this.#apply = apply2;
32228
+ this.#loadingChanged = loadingChanged;
32229
+ }
32230
+ connect() {
32231
+ this.#restart();
32232
+ }
32233
+ refresh() {
32234
+ this.#restart();
32235
+ }
32236
+ disconnect() {
32237
+ this.#generation += 1;
32238
+ this.#abort?.abort();
32239
+ this.#abort = void 0;
32240
+ this.#bootstrap = void 0;
32241
+ }
32242
+ #restart() {
32243
+ this.disconnect();
32244
+ this.#prime();
32245
+ }
32246
+ #prime() {
32247
+ const source = this.#source();
32248
+ if (!source.embedId || this.#bootstrap) return;
32249
+ const generation = this.#generation;
32250
+ const abort = new AbortController();
32251
+ this.#abort = abort;
32252
+ const fetcher = source.fetch ?? ((input, init) => globalThis.fetch(input, init));
32253
+ this.#loadingChanged(true);
32254
+ const bootstrap = Promise.resolve().then(
32255
+ () => fetcher(publicConfigurationUrl(source.serviceUrl, source.embedId), {
32256
+ method: "GET",
32257
+ headers: { accept: "application/json" },
32258
+ credentials: "omit",
32259
+ cache: "no-cache",
32260
+ signal: abort.signal
32261
+ })
32262
+ ).then(async (response) => {
32263
+ if (!response.ok) return;
32264
+ const value = await response.json();
32265
+ if (generation !== this.#generation || !isRecord6(value)) {
32266
+ return;
32267
+ }
32268
+ const configuration = parseAssistantConfiguration(value.configuration);
32269
+ if (configuration !== void 0) this.#apply(configuration);
32270
+ }).catch(() => void 0).finally(() => {
32271
+ if (generation === this.#generation) this.#loadingChanged(false);
32272
+ if (this.#bootstrap === bootstrap) {
32273
+ this.#bootstrap = void 0;
32274
+ this.#abort = void 0;
32275
+ }
32276
+ });
32277
+ this.#bootstrap = bootstrap;
32278
+ }
32279
+ };
32280
+ function isRecord6(value) {
32281
+ return typeof value === "object" && value !== null && !Array.isArray(value);
32282
+ }
32283
+
31786
32284
  // src/element-scroll-controller.ts
31787
32285
  var AssistantElementScrollController = class {
31788
32286
  #region;
@@ -31912,44 +32410,69 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
31912
32410
  *, *::before, *::after { box-sizing: border-box; }
31913
32411
  .visually-hidden { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; }
31914
32412
  .visually-hidden[hidden] { display: none !important; }
31915
- :host { color-scheme: light dark; font-family: var(--ns-assistant-font-family, var(--ns-assistant-default-font-family)); font-size: var(--ns-assistant-base-font-size, var(--ns-assistant-default-base-font-size)); line-height: var(--ns-assistant-line-height, var(--ns-assistant-default-line-height)); z-index: var(--ns-assistant-z-index, var(--ns-assistant-default-z-index)); -webkit-font-smoothing: antialiased; }
31916
- :host([data-mode="floating"]) { position: fixed; bottom: 20px; right: 20px; }
31917
- :host([data-mode="floating"][data-position="bottom-left"]) { right: auto; left: 20px; }
32413
+ :host { --ns-assistant-halo-launcher-action: #f4f4f5; --ns-assistant-halo-launcher-action-hover: #e4e4e7; --ns-assistant-halo-launcher-border: rgba(0,0,0,.04); --ns-assistant-halo-launcher-shadow: 0 1px 8px rgba(0,0,0,.04); --ns-assistant-halo-launcher-shadow-hover: 0 2px 12px rgba(0,0,0,.06); --ns-assistant-halo-send-button: #e4e4e7; --ns-assistant-halo-send-button-text: #09090b; box-sizing: border-box; color-scheme: light dark; font-family: var(--ns-assistant-font-family, var(--ns-assistant-default-font-family)); font-size: var(--ns-assistant-base-font-size, var(--ns-assistant-default-base-font-size)); line-height: var(--ns-assistant-line-height, var(--ns-assistant-default-line-height)); z-index: var(--ns-assistant-z-index, var(--ns-assistant-default-z-index)); -webkit-font-smoothing: antialiased; }
32414
+ :host([data-theme="dark"]) { --ns-assistant-halo-launcher-action: #3f3f46; --ns-assistant-halo-launcher-action-hover: #52525b; --ns-assistant-halo-launcher-border: rgba(255,255,255,.1); --ns-assistant-halo-launcher-shadow: 0 4px 20px rgba(0,0,0,.3); --ns-assistant-halo-launcher-shadow-hover: 0 6px 24px rgba(0,0,0,.4); --ns-assistant-halo-send-button: #3f3f46; --ns-assistant-halo-send-button-text: #fff; }
32415
+ :host([data-mode="floating"]) { position: fixed; }
32416
+ :host([data-mode="floating"][open]) { width: min(var(--ns-assistant-panel-width, var(--ns-assistant-default-panel-width)), 100vw); }
31918
32417
  button { font: inherit; }
31919
32418
  button, textarea, input, select { -webkit-tap-highlight-color: transparent; }
31920
- .launcher { display: grid; place-items: center; width: 48px; height: 48px; border: 1px solid var(--ns-assistant-launcher-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 999px; color: var(--ns-assistant-launcher-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-launcher, var(--ns-assistant-panel, var(--ns-assistant-default-panel))); box-shadow: 0 8px 28px rgba(0,0,0,.14); cursor: pointer; transition: transform .24s cubic-bezier(.25,1,.5,1), box-shadow .2s ease; }
31921
- .launcher:hover { transform: translateY(-2px) scale(1.03); box-shadow: 0 8px 26px rgba(0,0,0,.16); }
31922
- .launcher img { width: 28px; height: 28px; border-radius: 50%; object-fit: contain; }
31923
- .panel { display: none; flex-direction: column; width: min(var(--ns-assistant-panel-width, var(--ns-assistant-default-panel-width)), calc(100vw - 40px)); min-height: var(--ns-assistant-min-height, var(--ns-assistant-default-min-height)); max-height: min(var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100vh - 40px)); overflow: hidden; color: var(--ns-assistant-panel-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-panel, var(--ns-assistant-default-panel)); border: 1px solid var(--ns-assistant-panel-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-panel-radius, var(--ns-assistant-default-panel-radius)); box-shadow: var(--ns-assistant-shadow, var(--ns-assistant-default-shadow)); transform-origin: bottom right; isolation: isolate; animation: halo-panel-in .28s cubic-bezier(.23,1,.32,1) both; }
32419
+ .launcher { display: flex; align-items: center; justify-content: center; gap: 12px; width: max-content; min-height: 44px; padding: 10px 14px; color: var(--ns-assistant-launcher-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-launcher, color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 50%, transparent)); border: 1px solid var(--ns-assistant-launcher-border, var(--ns-assistant-halo-launcher-border)); border-radius: 999px; box-shadow: var(--ns-assistant-halo-launcher-shadow), -6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent), 6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent), 0 0 40px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 10%, transparent); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); transition: width .5s cubic-bezier(.25,1,.5,1), height .5s cubic-bezier(.25,1,.5,1), padding .5s cubic-bezier(.25,1,.5,1), gap .35s cubic-bezier(.25,1,.5,1), transform .6s cubic-bezier(.25,1,.5,1), background-color .3s ease, box-shadow .3s ease; }
32420
+ :host([data-presentation-ready]) .launcher { padding: 10px 12px; }
32421
+ .launcher[hidden] { display: none; }
32422
+ .launcher:hover { transform: scale(1.02); box-shadow: var(--ns-assistant-halo-launcher-shadow-hover), -6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent), 6px 0 18px color-mix(in srgb, var(--ns-assistant-accent, var(--ns-assistant-default-accent)) 20%, transparent); }
32423
+ .launcher-trigger, .launcher-form { min-width: 0; margin: 0; padding: 0; border: 0; background: transparent; font: inherit; }
32424
+ .launcher-trigger { display: flex; align-items: center; gap: 12px; min-height: 28px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); cursor: text; }
32425
+ .launcher-label { padding-left: 6px; white-space: nowrap; font-size: 15px; line-height: 20px; }
32426
+ .launcher-arrow, .launcher-send { position: relative; display: grid; width: 28px; height: 28px; flex: 0 0 28px; place-items: center; border: 0; border-radius: 50%; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-launcher-action, var(--ns-assistant-halo-launcher-action)); cursor: pointer; }
32427
+ .launcher-arrow:hover, .launcher-send:hover { background: var(--ns-assistant-launcher-action-hover, var(--ns-assistant-halo-launcher-action-hover)); }
32428
+ .launcher-arrow::before, .launcher-send::before { content: ''; width: 16px; height: 16px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32429
+ .launcher-form { display: none; flex: 1; align-items: center; gap: 12px; opacity: 0; pointer-events: none; }
32430
+ .launcher-input { width: 100%; min-width: 0; height: 28px; padding: 0 0 0 6px; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: transparent; border: 0; outline: 0; box-shadow: none; appearance: none; font: inherit; font-size: 16px; line-height: 20px; }
32431
+ .launcher-input::placeholder { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
32432
+ :host([launcher-expanded]) .launcher { width: min(400px, calc(100vw - 40px)); justify-content: flex-start; }
32433
+ :host([launcher-expanded]) .launcher-trigger { display: none; }
32434
+ :host([launcher-expanded]) .launcher-form { display: flex; opacity: 1; pointer-events: auto; }
32435
+ :host([data-launcher-style="bubble"]) .launcher { gap: 0; min-height: 0; padding: 6px; cursor: pointer; }
32436
+ :host([data-launcher-style="bubble"]) .launcher-trigger { position: absolute; inset: 0; display: block; width: 100%; height: 100%; cursor: pointer; }
32437
+ :host([data-launcher-style="bubble"]) .launcher-label, :host([data-launcher-style="bubble"]) .launcher-arrow, :host([data-launcher-style="bubble"]) .launcher-form { display: none; }
32438
+ :host([data-launcher-style="bubble"]) .launcher-visual { width: 32px; height: 32px; flex-basis: 32px; }
32439
+ .launcher-loader { display: none; width: 16px; height: 16px; flex: 0 0 16px; border: 2px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-top-color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); border-radius: 50%; animation: halo-spin .8s linear infinite; }
32440
+ :host([data-session-state="loading"]:not([data-presentation-ready])) .launcher-loader, :host([data-public-configuration-loading]:not([data-presentation-ready])) .launcher-loader { display: block; }
32441
+ :host([data-session-state="loading"]:not([data-presentation-ready])) .launcher > :not(.launcher-loader):not([data-session-status]), :host([data-public-configuration-loading]:not([data-presentation-ready])) .launcher > :not(.launcher-loader):not([data-session-status]) { display: none; }
32442
+ .panel { display: none; flex-direction: column; width: 100%; max-width: 970px; height: min(85dvh, var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100dvh - 40px)); min-height: min(var(--ns-assistant-min-height, var(--ns-assistant-default-min-height)), calc(100dvh - 40px)); max-height: min(var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100dvh - 40px)); overflow: hidden; color: var(--ns-assistant-panel-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-panel, var(--ns-assistant-default-panel)); border: 1px solid var(--ns-assistant-panel-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-panel-radius, var(--ns-assistant-default-panel-radius)); box-shadow: var(--ns-assistant-shadow, var(--ns-assistant-default-shadow)); transform-origin: bottom center; isolation: isolate; animation: halo-panel-in .3s ease both; }
32443
+ :host([data-mode="floating"][open]) .panel { width: calc(100% - 40px); margin-inline: 20px; }
31924
32444
  :host([open][data-presentation-ready]) .panel { display: flex; }
31925
32445
  .panel { position: relative; }
31926
32446
  :host([open][data-presentation-ready]) .launcher { display: none; }
31927
32447
  :host([open]:not([data-presentation-ready])) .launcher { cursor: progress; opacity: .72; transform: none; }
31928
- header { display: flex; flex: 0 0 auto; gap: 10px; align-items: center; min-height: 64px; padding: 12px 18px; color: var(--ns-assistant-header-text, inherit); background: var(--ns-assistant-header, transparent); border-bottom: 1px solid color-mix(in srgb, var(--ns-assistant-header-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))) 78%, transparent); }
32448
+ header { display: flex; flex: 0 0 auto; gap: 10px; align-items: center; min-height: 64px; padding: 16px 20px; color: var(--ns-assistant-header-text, inherit); background: var(--ns-assistant-header, transparent); border-bottom: 1px solid var(--ns-assistant-header-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); }
31929
32449
  header strong { flex: 1; font-size: 16px; font-weight: 600; letter-spacing: 0; }
31930
32450
  .brand-logo { display: block; max-width: 120px; max-height: 28px; object-fit: contain; }
31931
32451
  .close, .send { display: grid; place-items: center; border: 0; border-radius: var(--ns-assistant-button-radius, var(--ns-assistant-default-button-radius)); cursor: pointer; }
31932
- .close { position: relative; width: 44px; height: 44px; padding: 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); background: transparent; transition: background .15s ease, color .15s ease, transform .15s ease; }
31933
- .close::before { content: ''; width: 18px; height: 18px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32452
+ .close { position: relative; width: 44px; height: 44px; margin: -6px; padding: 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); background: transparent; transition: background .15s ease, color .15s ease, transform .15s ease; }
32453
+ .close::before { content: ''; width: 20px; height: 20px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 6 12 12M18 6 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; }
31934
32454
  .close:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); }
31935
32455
  .close:active { transform: scale(.96); }
31936
- .welcome { flex: 0 0 auto; padding: 30px 22px 18px; }
32456
+ .welcome { flex: 0 0 auto; padding: 24px 20px 8px; }
31937
32457
  .welcome h2 { margin: 0; font-size: 1.35em; line-height: 1.25; letter-spacing: 0; }
31938
32458
  .welcome p { max-width: 42ch; margin: 7px 0 0; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
31939
- :host([has-messages]) .welcome, :host([has-messages]) .suggested-prompts { display: none; }
31940
- .suggested-prompts { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: 8px; padding: 0 20px 16px; }
32459
+ .welcome:has(.empty-state[hidden]) { display: none; }
32460
+ :host([has-messages]) .welcome { display: none; }
32461
+ .input-section { flex: 0 0 auto; padding: 8px 16px 16px; }
32462
+ .suggested-prompts { display: flex; flex: 0 0 auto; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
31941
32463
  .suggested-prompts:empty { display: none; }
31942
- .suggested-prompts button { min-height: 44px; padding: 8px 14px; color: var(--ns-assistant-suggestion-text, var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text))); background: var(--ns-assistant-suggestion, color-mix(in srgb, var(--ns-assistant-input, var(--ns-assistant-default-input)) 58%, transparent)); border: 1px solid var(--ns-assistant-suggestion-border, color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 82%, transparent)); border-radius: 999px; cursor: pointer; font-size: .86em; transition: background .2s ease, color .2s ease, border-color .2s ease, transform .2s ease; }
31943
- .suggested-prompts button:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); transform: translateY(-1px); }
32464
+ .suggested-prompts button { position: relative; display: inline-flex; align-items: center; padding: 6px 12px; color: var(--ns-assistant-suggestion-text, var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text))); background: var(--ns-assistant-suggestion, transparent); border: 1px solid var(--ns-assistant-suggestion-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: 999px; cursor: pointer; font-size: 12px; white-space: nowrap; transition: background .2s ease, color .2s ease; }
32465
+ .suggested-prompts button::before { content: ''; position: absolute; inset: -6px -2px; }
32466
+ .suggested-prompts button:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: var(--ns-assistant-elevated, var(--ns-assistant-default-elevated)); }
31944
32467
  .messages-region { position: relative; display: flex; flex: 1 1 auto; min-height: 0; overflow: hidden; }
31945
32468
  .messages-region::before, .messages-region::after { content: ''; position: absolute; right: 0; left: 0; z-index: 1; height: 18px; pointer-events: none; opacity: 0; transition: opacity .18s ease; }
31946
32469
  .messages-region::before { top: 0; background: linear-gradient(to bottom, color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 92%, transparent), transparent); }
31947
32470
  .messages-region::after { bottom: 0; background: linear-gradient(to top, color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 92%, transparent), transparent); }
31948
32471
  .messages-region[data-can-scroll-up]::before, .messages-region[data-can-scroll-down]::after { opacity: 1; }
31949
- .messages { flex: 1 1 auto; width: 100%; min-height: 0; padding: 18px 20px 24px; overflow-y: auto; background: var(--ns-assistant-canvas, transparent); overscroll-behavior: contain; scroll-behavior: smooth; }
32472
+ .messages { flex: 1 1 auto; width: 100%; min-height: 0; padding: 16px 20px; overflow-y: auto; background: var(--ns-assistant-canvas, transparent); overscroll-behavior: contain; scroll-behavior: smooth; }
31950
32473
  .messages::-webkit-scrollbar { width: 6px; }
31951
32474
  .messages::-webkit-scrollbar-thumb { background: var(--ns-assistant-divider, var(--ns-assistant-default-divider)); border-radius: 999px; }
31952
- .message { width: fit-content; max-width: 88%; margin: 0 0 14px; padding: 0; border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); background: transparent; white-space: pre-wrap; animation: halo-message-in .2s ease both; }
32475
+ .message { width: fit-content; max-width: 88%; margin: 0 0 12px; padding: 0; border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); background: transparent; white-space: pre-wrap; animation: halo-message-in .2s ease both; }
31953
32476
  .message > span, .message > .markdown { overflow-wrap: anywhere; }
31954
32477
  .message .avatar { float: left; width: 24px; height: 24px; margin-right: 9px; border-radius: 50%; object-fit: cover; }
31955
32478
  .message time { display: block; margin-top: 4px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: .75em; line-height: 1.2; }
@@ -31962,7 +32485,7 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
31962
32485
  .new-messages { position: absolute; left: 50%; bottom: 14px; z-index: 2; width: 44px; height: 44px; padding: 0; color: var(--ns-assistant-secondary-button-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-secondary-button, color-mix(in srgb, var(--ns-assistant-input, var(--ns-assistant-default-input)) 92%, transparent)); border: 1px solid var(--ns-assistant-secondary-button-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-button-radius, var(--ns-assistant-default-button-radius)); box-shadow: 0 8px 24px rgba(0,0,0,.12); transform: translateX(-50%); cursor: pointer; }
31963
32486
  .new-messages::before { content: ''; display: block; width: 18px; height: 18px; margin: auto; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
31964
32487
  .message.assistant { max-width: 100%; color: var(--ns-assistant-assistant-message-text, inherit); background: var(--ns-assistant-assistant-message, transparent); border: 1px solid var(--ns-assistant-assistant-message-border, transparent); }
31965
- .message.user { display: grid; max-width: 85%; justify-items: start; gap: 3px; margin-left: auto; padding: 10px 16px 8px; color: var(--ns-assistant-user-message-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-user-message, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); border: 1px solid var(--ns-assistant-user-message-border, transparent); border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); font-size: .94em; }
32488
+ .message.user { display: grid; max-width: 85%; justify-items: start; gap: 3px; margin-left: auto; padding: 10px 16px; color: var(--ns-assistant-user-message-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-user-message, var(--ns-assistant-elevated, var(--ns-assistant-default-elevated))); border: 1px solid var(--ns-assistant-user-message-border, transparent); border-radius: var(--ns-assistant-card-radius, var(--ns-assistant-default-card-radius)); font-size: 14px; }
31966
32489
  .message.user time { margin-top: 0; }
31967
32490
  .markdown { white-space: normal; }
31968
32491
  .markdown p { margin: 0 0 8px; }
@@ -32012,31 +32535,39 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
32012
32535
  .input-request input:focus-visible, .input-request select:focus-visible { border-color: var(--ns-assistant-focus, var(--ns-assistant-default-focus)); box-shadow: 0 0 0 2px var(--ns-assistant-focus, var(--ns-assistant-default-focus)); }
32013
32536
  .input-request .proposal-actions { margin-top: 2px; }
32014
32537
  ${ASSISTANT_APP_VIEW_CSS}
32015
- form { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; min-height: 56px; margin: 8px 16px 16px; padding: 6px 6px 6px 16px; color: var(--ns-assistant-composer-text, inherit); border: 1px solid var(--ns-assistant-composer-border, color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 86%, transparent)); border-radius: var(--ns-assistant-input-radius, var(--ns-assistant-default-input-radius)); background: var(--ns-assistant-composer, color-mix(in srgb, var(--ns-assistant-input, var(--ns-assistant-default-input)) 92%, transparent)); box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 8px 24px rgba(0,0,0,.035); transition: border-color .15s ease, box-shadow .15s ease; }
32016
- form:focus-within { box-shadow: inset 0 0 0 1px var(--ns-assistant-focus, var(--ns-assistant-default-focus)), 0 0 0 2px var(--ns-assistant-focus, var(--ns-assistant-default-focus)); }
32538
+ .composer { display: flex; flex: 0 0 auto; gap: 8px; align-items: center; min-height: 44px; margin: 0; padding: 8px 8px 8px 16px; color: var(--ns-assistant-composer-text, inherit); border: 1px solid var(--ns-assistant-composer-border, transparent); border-radius: var(--ns-assistant-input-radius, var(--ns-assistant-default-input-radius)); background: var(--ns-assistant-composer, var(--ns-assistant-input, var(--ns-assistant-default-input))); transition: border-color .15s ease, box-shadow .15s ease; }
32539
+ .composer:focus-within { border-color: var(--ns-assistant-focus, var(--ns-assistant-default-focus)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ns-assistant-focus, var(--ns-assistant-default-focus)) 32%, transparent); }
32017
32540
  textarea { flex: 1; min-height: 24px; max-height: 120px; resize: none; padding: 0; color: var(--ns-assistant-text, var(--ns-assistant-default-text)); background: transparent; border: 0; border-radius: 0; outline: 0; box-shadow: none; appearance: none; -webkit-appearance: none; font: inherit; font-size: 16px; line-height: 24px; }
32018
32541
  textarea::placeholder { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); }
32019
32542
  textarea:focus, textarea:focus-visible { outline: none; box-shadow: none; }
32020
32543
  button:focus-visible { outline: 3px solid var(--ns-assistant-focus, var(--ns-assistant-default-focus)); outline-offset: 2px; }
32021
- .send { position: relative; display: block; width: 44px; height: 44px; flex: 0 0 44px; padding: 0; overflow: hidden; color: transparent; border-radius: 999px; background: var(--ns-assistant-primary-button, var(--ns-assistant-accent, var(--ns-assistant-default-accent))); font-size: 0; line-height: 0; transition: transform .15s ease, background .15s ease; }
32022
- .send::before { content: ''; position: absolute; top: 50%; left: 50%; width: 17px; height: 17px; background: var(--ns-assistant-primary-button-text, var(--ns-assistant-accent-text, var(--ns-assistant-default-accent-text))); transform: translate(-50%, -50%); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32023
- .send:hover { transform: scale(1.05); background: var(--ns-assistant-hover, color-mix(in srgb, var(--ns-assistant-primary-button, var(--ns-assistant-accent, var(--ns-assistant-default-accent))) 88%, var(--ns-assistant-primary-button-text, var(--ns-assistant-accent-text, var(--ns-assistant-default-accent-text))) 12%)); }
32544
+ .send { position: relative; display: block; width: 44px; height: 44px; flex: 0 0 44px; margin: -8px; padding: 0; overflow: visible; color: var(--ns-assistant-primary-button-text, var(--ns-assistant-halo-send-button-text)); border-radius: 999px; background: transparent; font-size: 0; line-height: 0; }
32545
+ .send::after { content: ''; position: absolute; top: 50%; left: 50%; z-index: 0; width: 28px; height: 28px; border-radius: 50%; background: var(--ns-assistant-primary-button, var(--ns-assistant-halo-send-button)); transform: translate(-50%, -50%); }
32546
+ .send::before { content: ''; position: absolute; top: 50%; left: 50%; z-index: 1; width: 16px; height: 16px; background: currentColor; transform: translate(-50%, -50%); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 19V5M5 12l7-7 7 7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat; }
32547
+ .send:hover::after { background: var(--ns-assistant-hover, var(--ns-assistant-default-hover)); }
32024
32548
  :host([busy]) .send::before { width: 13px; height: 13px; border-radius: 3px; -webkit-mask: none; mask: none; }
32025
32549
  .send:disabled, textarea:disabled { opacity: .55; cursor: not-allowed; }
32026
- .legal { display: flex; gap: 12px; justify-content: center; padding: 0 12px 9px; font-size: .75em; }
32550
+ .legal { display: flex; gap: 12px; justify-content: center; padding: 0 12px 8px; font-size: .75em; }
32027
32551
  .legal:empty { display: none; }
32028
32552
  .legal a { color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); text-underline-offset: 2px; }
32553
+ .powered-by-row { display: flex; flex: 0 0 auto; justify-content: center; padding-bottom: 12px; }
32554
+ .powered-by-row[hidden] { display: none; }
32555
+ .powered-by { display: inline-flex; align-items: center; gap: 6px; margin: 0 auto 12px; padding: 0 16px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: 11px; line-height: 1; text-decoration: none; opacity: .7; transition: opacity .12s ease, color .12s ease; }
32556
+ .powered-by:hover { color: var(--ns-assistant-text, var(--ns-assistant-default-text)); opacity: 1; }
32557
+ .powered-by-icon { display: inline-flex; width: 14px; height: 14px; }
32558
+ .powered-by-name { font-weight: 500; }
32029
32559
  ::slotted([slot="conversation-footer"]) { display: block; padding: 0 16px 12px; color: var(--ns-assistant-muted-text, var(--ns-assistant-default-muted-text)); font-size: 11px; text-align: center; }
32030
- @keyframes halo-panel-in { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }
32560
+ @keyframes halo-panel-in { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
32031
32561
  @keyframes halo-message-in { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
32032
32562
  @keyframes halo-shimmer { from { background-position: 100% center; } to { background-position: 0 center; } }
32033
32563
  @keyframes halo-caret-blink { 50% { opacity: 0; } }
32564
+ @keyframes halo-spin { to { transform: rotate(360deg); } }
32034
32565
  :host([data-density="compact"]) .welcome { padding: 20px 18px 12px; }
32035
- @media (max-width: 640px) { :host([mobile-fullscreen][open]) { inset: 0; } :host([mobile-fullscreen][open]) .panel { width: 100vw; min-height: 100vh; max-height: 100vh; border: 0; border-radius: 0; } :host([mobile-fullscreen]) header { padding-top: max(12px, env(safe-area-inset-top)); padding-right: max(18px, env(safe-area-inset-right)); padding-left: max(18px, env(safe-area-inset-left)); } :host([mobile-fullscreen]) form { margin-right: max(16px, env(safe-area-inset-right)); margin-bottom: max(16px, env(safe-area-inset-bottom)); margin-left: max(16px, env(safe-area-inset-left)); } :host([mobile-fullscreen]) .legal, :host([mobile-fullscreen]) ::slotted([slot="conversation-footer"]) { padding-bottom: max(10px, env(safe-area-inset-bottom)); } }
32566
+ @media (max-width: 640px) { :host([mobile-fullscreen][open]) { inset: 0; width: 100vw; transform: none; } :host([mobile-fullscreen][open]) .panel { width: 100vw; max-width: none; height: 100dvh; min-height: 100dvh; max-height: 100dvh; margin: 0; border: 0; border-radius: 0; } :host([mobile-fullscreen]) header { padding-top: calc(16px + env(safe-area-inset-top)); padding-right: calc(20px + env(safe-area-inset-right)); padding-left: calc(20px + env(safe-area-inset-left)); } :host([mobile-fullscreen]) .messages { padding-right: calc(20px + env(safe-area-inset-right)); padding-left: calc(20px + env(safe-area-inset-left)); } :host([mobile-fullscreen]) .input-section { padding-right: calc(16px + env(safe-area-inset-right)); padding-bottom: calc(16px + env(safe-area-inset-bottom)); padding-left: calc(16px + env(safe-area-inset-left)); } :host([mobile-fullscreen]) .legal, :host([mobile-fullscreen]) ::slotted([slot="conversation-footer"]) { padding-bottom: max(10px, env(safe-area-inset-bottom)); } }
32036
32567
  @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; } .messages { scroll-behavior: auto; } .message.assistant.streaming .markdown::after { animation: none; } }
32037
32568
  @media (forced-colors: active) { .message.thinking > span { color: CanvasText; background: none; } }
32038
32569
  @media (hover: none) { .message-copy { opacity: 1; } }
32039
- @media (max-width: 560px) { :host([data-mode="floating"]) { inset: auto 12px 12px; } :host([open]) .panel { width: calc(100vw - 24px); max-height: calc(100vh - 24px); } }
32570
+ @media (max-width: 560px) { :host([data-mode="floating"]:not([open])) { bottom: 20px; } :host([open]:not([mobile-fullscreen])) .panel { width: calc(100vw - 40px); max-height: calc(100dvh - 40px); } }
32040
32571
  </style>`;
32041
32572
 
32042
32573
  // src/host-appearance.ts
@@ -32145,6 +32676,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32145
32676
  host.dataset.panelSurface = presentation.panel.surface;
32146
32677
  host.dataset.panelElevation = presentation.panel.elevation;
32147
32678
  host.dataset.panelBorder = presentation.panel.border;
32679
+ host.dataset.launcherStyle = presentation.launcher.style;
32148
32680
  host.dataset.launcherEffect = presentation.launcher.effect;
32149
32681
  host.dataset.messageUserStyle = presentation.messages.userStyle;
32150
32682
  host.dataset.messageAssistantStyle = presentation.messages.assistantStyle;
@@ -32157,11 +32689,11 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32157
32689
  }
32158
32690
  host.style.setProperty(
32159
32691
  "--ns-assistant-presentation-launcher-size",
32160
- presentation.launcher.size === "lg" ? "56px" : "48px"
32692
+ presentation.launcher.size === "lg" ? "56px" : "44px"
32161
32693
  );
32162
32694
  host.style.setProperty(
32163
32695
  "--ns-assistant-presentation-panel-background",
32164
- presentation.panel.surface === "solid" ? "var(--ns-assistant-panel, var(--ns-assistant-default-panel))" : "color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 88%, transparent)"
32696
+ presentation.panel.surface === "solid" ? "var(--ns-assistant-panel, var(--ns-assistant-default-panel))" : "color-mix(in srgb, var(--ns-assistant-panel, var(--ns-assistant-default-panel)) 50%, transparent)"
32165
32697
  );
32166
32698
  host.style.setProperty(
32167
32699
  "--ns-assistant-presentation-shadow",
@@ -32169,7 +32701,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32169
32701
  );
32170
32702
  host.style.setProperty(
32171
32703
  "--ns-assistant-presentation-border",
32172
- panelBorder(presentation.panel.border)
32704
+ panelBorder(presentation.panel.border, mode)
32173
32705
  );
32174
32706
  replaceFallback(root, "launcher-icon", [launcherVisual(appearance, mode, sessionState)]);
32175
32707
  const accessibleStatus = root.querySelector("[data-session-status]");
@@ -32182,7 +32714,7 @@ function syncAssistantPresentation(host, root, appearance, mode, sessionState) {
32182
32714
  replaceFallback(root, "empty-state", [emptyState(appearance)]);
32183
32715
  replaceFallback(root, "composer-leading", composerLeading(appearance, mode));
32184
32716
  replaceFallback(root, "conversation-footer", []);
32185
- const form = root.querySelector("form");
32717
+ const form = root.querySelector(".composer");
32186
32718
  if (form) form.dataset.shape = presentation.composer.shape;
32187
32719
  const send = root.querySelector(".send");
32188
32720
  if (send) send.dataset.icon = presentation.composer.sendIcon;
@@ -32202,18 +32734,21 @@ function panelShadow(elevation) {
32202
32734
  }
32203
32735
  return "var(--ns-assistant-default-shadow)";
32204
32736
  }
32205
- function panelBorder(border) {
32737
+ function panelBorder(border, mode) {
32206
32738
  if (border === "strong") {
32207
32739
  return "1px solid var(--ns-assistant-divider, var(--ns-assistant-default-divider))";
32208
32740
  }
32209
- return "1px solid color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) 74%, transparent)";
32741
+ const opacity = mode === "light" ? 60 : 100;
32742
+ return `1px solid color-mix(in srgb, var(--ns-assistant-divider, var(--ns-assistant-default-divider)) ${opacity}%, transparent)`;
32210
32743
  }
32211
32744
  function launcherVisual(appearance, mode, sessionState) {
32212
32745
  const launcher = appearance.presentation.launcher;
32213
32746
  const visual = document.createElement("span");
32214
32747
  visual.className = "launcher-visual";
32215
32748
  visual.setAttribute("aria-hidden", "true");
32216
- visual.append(icon(launcher.icon, appearance, mode, "launcher-glyph"));
32749
+ const visualKind = launcher.icon === "brand-mark" && !(appearance.brand.mark[mode] ?? appearance.brand.logo[mode]) ? launcher.style === "bubble" ? "chat" : "none" : launcher.icon;
32750
+ visual.hidden = visualKind === "none";
32751
+ visual.append(icon(visualKind, appearance, mode, "launcher-glyph"));
32217
32752
  if (launcher.status === "session") {
32218
32753
  const status = document.createElement("span");
32219
32754
  status.className = "launcher-status";
@@ -32263,9 +32798,12 @@ function headerBadge(appearance) {
32263
32798
  function emptyState(appearance) {
32264
32799
  const section = document.createElement("section");
32265
32800
  section.className = "empty-state";
32266
- const heading = document.createElement("h2");
32267
- heading.textContent = appearance.labels.welcomeHeading;
32268
- section.append(heading);
32801
+ section.hidden = !appearance.labels.welcomeHeading && !appearance.labels.welcomeMessage;
32802
+ if (appearance.labels.welcomeHeading) {
32803
+ const heading = document.createElement("h2");
32804
+ heading.textContent = appearance.labels.welcomeHeading;
32805
+ section.append(heading);
32806
+ }
32269
32807
  const description = appearance.labels.welcomeMessage;
32270
32808
  if (description) {
32271
32809
  const paragraph = document.createElement("p");
@@ -32292,7 +32830,7 @@ function toneIndicator(tone) {
32292
32830
  return indicator;
32293
32831
  }
32294
32832
  function icon(kind, appearance, mode, className) {
32295
- const mark = appearance.brand.mark[mode];
32833
+ const mark = appearance.brand.mark[mode] ?? appearance.brand.logo[mode];
32296
32834
  if (kind === "brand-mark" && mark) {
32297
32835
  const image = document.createElement("img");
32298
32836
  image.className = className;
@@ -32344,11 +32882,17 @@ function applyAssistantElementTheme(input) {
32344
32882
  var presentationStyles = `<style>
32345
32883
  :host([data-mode="floating"]) {
32346
32884
  bottom: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32347
- right: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32885
+ left: 50%;
32886
+ transform: translateX(-50%);
32348
32887
  }
32349
32888
  :host([data-mode="floating"][data-position="bottom-left"]) {
32350
- right: auto;
32351
32889
  left: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32890
+ transform: none;
32891
+ }
32892
+ :host([data-mode="floating"][data-position="bottom-right"]) {
32893
+ right: var(--ns-assistant-edge-offset, var(--ns-assistant-default-edge-offset));
32894
+ left: auto;
32895
+ transform: none;
32352
32896
  }
32353
32897
  .panel {
32354
32898
  background: var(--ns-assistant-panel-background, var(--ns-assistant-presentation-panel-background));
@@ -32365,22 +32909,26 @@ var presentationStyles = `<style>
32365
32909
 
32366
32910
  .launcher {
32367
32911
  position: relative;
32368
- width: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32369
- height: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32370
32912
  border-radius: var(--ns-assistant-launcher-radius, var(--ns-assistant-default-launcher-radius));
32371
32913
  isolation: isolate;
32372
32914
  }
32915
+ :host([data-launcher-style="bubble"]) .launcher {
32916
+ width: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32917
+ height: var(--ns-assistant-launcher-size, var(--ns-assistant-presentation-launcher-size));
32918
+ }
32373
32919
  :host([data-launcher-effect="pulse"]) .launcher {
32374
32920
  animation: assistant-launcher-pulse 2s ease-in-out infinite;
32375
32921
  }
32376
32922
  .launcher-visual {
32377
32923
  position: relative;
32378
32924
  display: grid;
32379
- width: 100%;
32380
- height: 100%;
32925
+ width: 28px;
32926
+ height: 28px;
32927
+ flex: 0 0 28px;
32381
32928
  place-items: center;
32382
32929
  border-radius: inherit;
32383
32930
  }
32931
+ .launcher-visual[hidden] { display: none; }
32384
32932
  .launcher-glyph, .composer-leading-glyph {
32385
32933
  display: block;
32386
32934
  width: 18px;
@@ -32408,10 +32956,28 @@ var presentationStyles = `<style>
32408
32956
  -webkit-mask: none;
32409
32957
  mask: none;
32410
32958
  }
32959
+ .launcher-visual .launcher-glyph:is(img) {
32960
+ width: 28px;
32961
+ height: 28px;
32962
+ border-radius: 50%;
32963
+ filter: grayscale(100%);
32964
+ opacity: .6;
32965
+ transition: width .5s cubic-bezier(.25,1,.5,1), height .5s cubic-bezier(.25,1,.5,1), filter .5s cubic-bezier(.25,1,.5,1), opacity .5s cubic-bezier(.25,1,.5,1);
32966
+ }
32967
+ .launcher:hover .launcher-glyph:is(img), :host([launcher-expanded]) .launcher-glyph:is(img) {
32968
+ filter: none;
32969
+ opacity: 1;
32970
+ }
32971
+ :host([data-launcher-style="bubble"]) .launcher-glyph:is(img) {
32972
+ width: 32px;
32973
+ height: 32px;
32974
+ filter: none;
32975
+ opacity: 1;
32976
+ }
32411
32977
  .launcher-status {
32412
32978
  position: absolute;
32413
- right: 1px;
32414
- bottom: 1px;
32979
+ right: -1px;
32980
+ bottom: -1px;
32415
32981
  width: 10px;
32416
32982
  height: 10px;
32417
32983
  border: 2px solid var(--ns-assistant-panel, var(--ns-assistant-default-panel));
@@ -32540,7 +33106,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32540
33106
  #conversationGeneration = 0;
32541
33107
  #messages;
32542
33108
  #thinking;
32543
- #media;
32544
33109
  #context;
32545
33110
  #modelContext;
32546
33111
  #pageContext;
@@ -32552,11 +33117,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32552
33117
  () => this.#primeSession(),
32553
33118
  () => this.focusComposer()
32554
33119
  );
33120
+ #publicConfiguration = new AssistantElementPublicConfigurationController(
33121
+ () => ({ embedId: this.embedId, serviceUrl: this.serviceUrl, fetch: this.#fetch }),
33122
+ (configuration) => this.#applyConfiguration(configuration),
33123
+ (loading) => this.#setPublicConfigurationLoading(loading)
33124
+ );
32555
33125
  #pendingUserEcho;
32556
33126
  #sessionState = "idle";
32557
33127
  #startOpenApplied = false;
32558
33128
  #readyDispatched = false;
32559
33129
  #turnInFlight = false;
33130
+ #fetch;
32560
33131
  #hostAppearance;
32561
33132
  #appearanceWarningKeys = /* @__PURE__ */ new Set();
32562
33133
  #appearanceStyleSnapshot = /* @__PURE__ */ new Map();
@@ -32566,6 +33137,17 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32566
33137
  embedId = "";
32567
33138
  /** Only for a dev or self-hosted service; the published snippet needs no origin. */
32568
33139
  serviceUrl = "";
33140
+ get fetch() {
33141
+ return this.#fetch;
33142
+ }
33143
+ set fetch(value) {
33144
+ if (this.#fetch === value) return;
33145
+ this.#fetch = value;
33146
+ if (this.#client) this.resetSession();
33147
+ if (!this.isConnected) return;
33148
+ if (this.embedId) this.#publicConfiguration.refresh();
33149
+ else this.#primeSession();
33150
+ }
32569
33151
  get appearance() {
32570
33152
  return this.#hostAppearance;
32571
33153
  }
@@ -32584,11 +33166,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32584
33166
  }
32585
33167
  return this.#appendMessage(role, text3);
32586
33168
  },
32587
- applyConfiguration: (configuration) => {
32588
- this.#appearance = resolveAppearance(configuration);
32589
- this.#syncAppearance();
32590
- this.#applyStartOpenPolicy();
32591
- },
33169
+ applyConfiguration: (configuration) => this.#applyConfiguration(configuration),
32592
33170
  labels: () => this.#appearance.labels,
32593
33171
  respond: (id, response) => this.respond(id, response),
32594
33172
  dispatchError: (detail) => this.#dispatchError(detail),
@@ -32604,7 +33182,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32604
33182
  client,
32605
33183
  sendMessage: (message) => this.sendMessage(message),
32606
33184
  updateModelContext: (update) => this.updateModelContext(update),
32607
- theme: this.#resolvedMode()
33185
+ theme: this.#environment.resolvedTheme()
32608
33186
  },
32609
33187
  {
32610
33188
  ...sandboxUrl === void 0 ? {} : { sandboxUrl },
@@ -32617,18 +33195,28 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32617
33195
  this.#revealLatest();
32618
33196
  }
32619
33197
  });
33198
+ #launcher = new AssistantElementLauncherController({
33199
+ host: this,
33200
+ appearance: () => this.#appearance,
33201
+ openPanel: () => this.open(),
33202
+ sendMessage: (message) => this.#sendGuarded(message)
33203
+ });
33204
+ #environment = new AssistantElementHostEnvironmentController({
33205
+ host: this,
33206
+ appearance: () => this.#appearance,
33207
+ applyTheme: () => this.#applyTheme(),
33208
+ close: () => this.#closeAndRestoreFocus()
33209
+ });
32620
33210
  connectedCallback() {
32621
33211
  if (!this.shadowRoot) this.attachShadow({ mode: "open" });
32622
33212
  if (!this.sessionEndpoint) this.sessionEndpoint = this.getAttribute("session-endpoint") ?? "";
32623
33213
  if (!this.embedId) this.embedId = this.getAttribute("embed-id") ?? "";
32624
33214
  if (!this.serviceUrl) this.serviceUrl = this.getAttribute("service-url") ?? "";
32625
33215
  if (!this.sessionEndpoint && !this.embedId) this.#presentationGate.reveal();
32626
- this.#media = globalThis.matchMedia?.("(prefers-color-scheme: dark)");
32627
- this.#media?.addEventListener("change", this.#handleSystemTheme);
32628
- document.addEventListener("keydown", this.#handleDocumentKeydown);
32629
- document.addEventListener("pointerdown", this.#handleDocumentPointerDown);
33216
+ this.#environment.connect();
32630
33217
  if (this.#appearance.behavior.startOpen) this.#applyStartOpenPolicy();
32631
33218
  this.#render();
33219
+ if (this.embedId) this.#publicConfiguration.connect();
32632
33220
  if (!this.#readyDispatched) {
32633
33221
  this.#readyDispatched = true;
32634
33222
  this.dispatchEvent(new CustomEvent("assistant-ready"));
@@ -32649,22 +33237,25 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32649
33237
  this.#clientEndpoint = "";
32650
33238
  this.#unsubscribeClient = void 0;
32651
33239
  this.#sessionBootstrap = void 0;
33240
+ this.#publicConfiguration.disconnect();
32652
33241
  this.#scroll.disconnect();
33242
+ this.#launcher.disconnect();
32653
33243
  this.#setBusy(false);
32654
- this.#media?.removeEventListener("change", this.#handleSystemTheme);
32655
- document.removeEventListener("keydown", this.#handleDocumentKeydown);
32656
- document.removeEventListener("pointerdown", this.#handleDocumentPointerDown);
33244
+ this.#environment.disconnect();
32657
33245
  }
32658
33246
  attributeChangedCallback(name21) {
32659
33247
  if (name21 === "theme") this.#applyTheme();
32660
33248
  if (name21 === "open") this.#presentationGate.syncOpenState();
32661
33249
  }
32662
33250
  open() {
33251
+ this.#launcher.collapse(true);
32663
33252
  this.setAttribute("open", "");
33253
+ if (this.hasAttribute("data-presentation-ready")) queueMicrotask(() => this.focusComposer());
32664
33254
  this.dispatchEvent(new CustomEvent("assistant-open"));
32665
33255
  }
32666
33256
  close() {
32667
33257
  this.removeAttribute("open");
33258
+ this.#launcher.collapse(true);
32668
33259
  this.dispatchEvent(new CustomEvent("assistant-close"));
32669
33260
  }
32670
33261
  toggle() {
@@ -32801,17 +33392,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32801
33392
  if (generation === this.#conversationGeneration) this.#setBusy(false);
32802
33393
  }
32803
33394
  }
32804
- #handleSystemTheme = () => this.#applyTheme();
32805
- #handleDocumentKeydown = (event) => {
32806
- if (event.key === "Escape" && this.hasAttribute("open") && this.#appearance.behavior.closeOnEscape) {
32807
- this.#closeAndRestoreFocus();
32808
- }
32809
- };
32810
- #handleDocumentPointerDown = (event) => {
32811
- if (this.hasAttribute("open") && this.#appearance.behavior.closeOnOutsideClick && !event.composedPath().includes(this)) {
32812
- this.close();
32813
- }
32814
- };
32815
33395
  #ensureClient() {
32816
33396
  const key = sessionSourceKey(this);
32817
33397
  if (this.#client && this.#clientEndpoint === key) return this.#client;
@@ -32827,8 +33407,13 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32827
33407
  const client = this.embedId ? createAssistantClient({
32828
33408
  embedId: this.embedId,
32829
33409
  ...this.serviceUrl ? { serviceUrl: this.serviceUrl } : {},
33410
+ ...this.#fetch ? { fetch: this.#fetch } : {},
33411
+ ...behavior
33412
+ }) : createAssistantClient({
33413
+ sessionEndpoint: this.sessionEndpoint,
33414
+ ...this.#fetch ? { fetch: this.#fetch } : {},
32830
33415
  ...behavior
32831
- }) : createAssistantClient({ sessionEndpoint: this.sessionEndpoint, ...behavior });
33416
+ });
32832
33417
  this.#client = client;
32833
33418
  this.#clientEndpoint = key;
32834
33419
  this.#unsubscribeClient = client.subscribe((event) => {
@@ -32857,6 +33442,8 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32857
33442
  this.dispatchEvent(new CustomEvent("assistant-event", { detail: event }));
32858
33443
  this.#events.handle(event);
32859
33444
  if (event.event === "session_started") {
33445
+ this.#publicConfiguration.disconnect();
33446
+ this.removeAttribute("data-public-configuration-loading");
32860
33447
  this.#presentationGate.reveal();
32861
33448
  this.#setSessionState("ready");
32862
33449
  this.#messages?.querySelector(".conversation-error")?.remove();
@@ -32906,10 +33493,10 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32906
33493
  if (!this.#messages) return void 0;
32907
33494
  const message = document.createElement("div");
32908
33495
  message.className = `message ${role}`;
32909
- if (role === "assistant" && this.#appearance.behavior.showAvatars && this.#appearance.brand.avatar[this.#resolvedMode()]) {
33496
+ if (role === "assistant" && this.#appearance.behavior.showAvatars && this.#appearance.brand.avatar[this.#environment.resolvedTheme()]) {
32910
33497
  const avatar = document.createElement("img");
32911
33498
  avatar.className = "avatar";
32912
- avatar.src = this.#appearance.brand.avatar[this.#resolvedMode()] ?? "";
33499
+ avatar.src = this.#appearance.brand.avatar[this.#environment.resolvedTheme()] ?? "";
32913
33500
  avatar.alt = "";
32914
33501
  message.append(avatar);
32915
33502
  }
@@ -32990,12 +33577,8 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32990
33577
  this.#primeSession();
32991
33578
  this.dispatchEvent(new CustomEvent("assistant-new-conversation"));
32992
33579
  }
32993
- #resolvedMode() {
32994
- const configured = this.getAttribute("theme") ?? this.#appearance.theme.defaultMode;
32995
- return configured === "auto" ? this.#media?.matches ? "dark" : "light" : configured;
32996
- }
32997
33580
  #applyTheme() {
32998
- const mode = this.#resolvedMode();
33581
+ const mode = this.#environment.resolvedTheme();
32999
33582
  for (const warning of applyAssistantElementTheme({
33000
33583
  host: this,
33001
33584
  root: this.shadowRoot,
@@ -33018,13 +33601,23 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33018
33601
  updateAssistantAppTheme(app, mode);
33019
33602
  }
33020
33603
  }
33604
+ #applyConfiguration(configuration) {
33605
+ this.#appearance = resolveAppearance(configuration);
33606
+ this.#syncAppearance();
33607
+ this.#applyStartOpenPolicy();
33608
+ }
33609
+ #setPublicConfigurationLoading(loading) {
33610
+ this.toggleAttribute("data-public-configuration-loading", loading);
33611
+ if (loading) this.#presentationGate.syncOpenState();
33612
+ else this.#presentationGate.reveal();
33613
+ }
33021
33614
  #setSessionState(state) {
33022
33615
  this.#sessionState = state;
33023
33616
  syncAssistantSessionVisualState(this, this.shadowRoot, state, this.#appearance);
33024
33617
  }
33025
33618
  #closeAndRestoreFocus() {
33026
33619
  this.close();
33027
- this.shadowRoot?.querySelector(".launcher")?.focus();
33620
+ this.#launcher.focusTrigger();
33028
33621
  }
33029
33622
  #applyStartOpenPolicy() {
33030
33623
  if (this.#startOpenApplied) return;
@@ -33050,10 +33643,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33050
33643
  textarea.placeholder = appearance.labels.composerPlaceholder;
33051
33644
  textarea.setAttribute("aria-label", appearance.labels.composerPlaceholder);
33052
33645
  queryRequired(this.shadowRoot, ".send").textContent = appearance.labels.send;
33053
- queryRequired(this.shadowRoot, ".launcher").setAttribute(
33054
- "aria-label",
33055
- appearance.labels.open
33056
- );
33057
33646
  queryRequired(this.shadowRoot, ".close").setAttribute(
33058
33647
  "aria-label",
33059
33648
  appearance.labels.close
@@ -33067,11 +33656,11 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33067
33656
  button2.addEventListener("click", () => this.#sendGuarded(prompt));
33068
33657
  prompts.append(button2);
33069
33658
  }
33070
- queryRequired(this.shadowRoot, ".launcher").hidden = !appearance.behavior.showLauncher;
33071
33659
  queryRequired(this.shadowRoot, "header").hidden = !appearance.behavior.showHeader;
33072
33660
  const legal = queryRequired(this.shadowRoot, ".legal");
33073
33661
  legal.replaceChildren();
33074
33662
  appendLegalLinks(legal, this.#appearance);
33663
+ this.#launcher.sync();
33075
33664
  this.#applyTheme();
33076
33665
  }
33077
33666
  #render() {
@@ -33089,12 +33678,11 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33089
33678
  this.toggleAttribute("mobile-fullscreen", appearance.layout.mobileFullscreen);
33090
33679
  this.shadowRoot.innerHTML = assistantElementMarkup(
33091
33680
  appearance,
33092
- this.hasAttribute("open"),
33093
33681
  `${ASSISTANT_ELEMENT_STYLES}${presentationStyles}`
33094
33682
  );
33095
33683
  queryRequired(this.shadowRoot, "strong").textContent = appearance.brand.name;
33096
33684
  const logo = queryRequired(this.shadowRoot, ".brand-logo");
33097
- const logoUrl = appearance.brand.logo[this.#resolvedMode()];
33685
+ const logoUrl = appearance.brand.logo[this.#environment.resolvedTheme()];
33098
33686
  if (logoUrl) {
33099
33687
  logo.src = logoUrl;
33100
33688
  logo.alt = appearance.brand.name;
@@ -33122,12 +33710,9 @@ var NoodleAssistantElement = class extends HTMLElementBase {
33122
33710
  this.#messages = this.shadowRoot.querySelector(".messages") ?? void 0;
33123
33711
  this.#messages?.append(...conversation);
33124
33712
  this.#thinking = this.#messages?.querySelector(".thinking") ?? void 0;
33125
- this.shadowRoot.querySelector(".launcher")?.addEventListener("click", () => {
33126
- this.open();
33127
- this.focusComposer();
33128
- });
33713
+ this.#launcher.connect(this.shadowRoot);
33129
33714
  this.shadowRoot.querySelector(".close")?.addEventListener("click", () => this.#closeAndRestoreFocus());
33130
- const form = queryRequired(this.shadowRoot, "form");
33715
+ const form = queryRequired(this.shadowRoot, ".composer");
33131
33716
  form.addEventListener("submit", (event) => {
33132
33717
  event.preventDefault();
33133
33718
  if (this.hasAttribute("busy")) {