@nonoun/native-chat 0.5.17 → 0.5.21

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.
@@ -1,8 +1,9 @@
1
- import { o as e, r as t, t as n, u as r } from "./adapter-mock-0s0RPkdx.js";
1
+ import { f as e, o as t, r as n, t as r } from "./adapter-mock-DQ_CxuNu.js";
2
2
  import { NativeElement as i, VirtualScrollController as a, createDisabledEffect as o, signal as s, uid as c } from "@nonoun/native-ui";
3
3
  /**
4
4
  * Chat message input with textarea, submit button, and Enter-to-send behavior.
5
5
  * @attr {boolean} disabled - Disables interaction
6
+ * @attr {string} value - Initial textarea value
6
7
  * @attr {boolean} busy - Disables submit but keeps textarea enabled
7
8
  * @attr {boolean} no-enter-submit - Disables Enter key submission
8
9
  * @attr {boolean} no-auto-clear - Prevents clearing the textarea after send
@@ -12,7 +13,11 @@ import { NativeElement as i, VirtualScrollController as a, createDisabledEffect
12
13
  * @fires native:composer-blur - Fired when the composer textarea loses focus
13
14
  */
14
15
  var l = class extends i {
15
- static observedAttributes = ["disabled", "busy"];
16
+ static observedAttributes = [
17
+ "disabled",
18
+ "busy",
19
+ "value"
20
+ ];
16
21
  #e;
17
22
  #t = s(!1);
18
23
  #n = s(!1);
@@ -56,13 +61,18 @@ var l = class extends i {
56
61
  case "busy":
57
62
  this.#n.value = n !== null;
58
63
  break;
64
+ case "value":
65
+ this.#r && (this.#r.value = n ?? "");
66
+ break;
59
67
  }
60
68
  super.attributeChangedCallback(e, t, n);
61
69
  }
62
70
  }
63
71
  setup() {
64
72
  super.setup(), this.addEffect(o(this, this.#t, this.#e)), this.deferChildren(() => {
65
- this.#a(), this.addEffect(() => {
73
+ this.#a();
74
+ let e = this.getAttribute("value");
75
+ e && this.#r && (this.#r.value = e), this.addEffect(() => {
66
76
  let e = this.#t.value;
67
77
  this.#r && this.#r.toggleAttribute("disabled", e), this.#i && (e ? this.#i.setAttribute("disabled", "") : this.#s());
68
78
  }), this.addEffect(() => {
@@ -133,15 +143,18 @@ var l = class extends i {
133
143
  }
134
144
  }
135
145
  }, u = class extends i {
146
+ static MAX_CONTEXT_MESSAGES = 50;
136
147
  static observedAttributes = [
137
148
  "show-stop",
138
149
  "show-restart",
139
150
  "auto-focus-policy",
140
151
  "open",
141
152
  "model",
153
+ "models",
142
154
  "gateway",
143
155
  "gateway-url",
144
- "gateway-config"
156
+ "gateway-config",
157
+ "gateway-urls"
145
158
  ];
146
159
  #e = s(!1);
147
160
  #t = s(!1);
@@ -152,10 +165,10 @@ var l = class extends i {
152
165
  #o = s(null);
153
166
  #s = s(null);
154
167
  #c = s(null);
155
- #l = s(!1);
156
- #u = null;
157
- #d = [];
158
- #f = null;
168
+ #l = s(null);
169
+ #u = s(!1);
170
+ #d = null;
171
+ #f = [];
159
172
  #p = null;
160
173
  #m = null;
161
174
  #h = null;
@@ -185,6 +198,12 @@ var l = class extends i {
185
198
  case "model":
186
199
  this.#a.value = n;
187
200
  break;
201
+ case "models":
202
+ n ? this.#i.value = n.split(",").map((e) => e.trim()).filter(Boolean).map((e) => ({
203
+ value: e,
204
+ label: e
205
+ })) : this.#i.value = [];
206
+ break;
188
207
  case "gateway":
189
208
  this.#o.value = n;
190
209
  break;
@@ -198,6 +217,13 @@ var l = class extends i {
198
217
  this.#c.value = null;
199
218
  }
200
219
  break;
220
+ case "gateway-urls":
221
+ try {
222
+ this.#l.value = n ? JSON.parse(n) : null;
223
+ } catch {
224
+ this.#l.value = null;
225
+ }
226
+ break;
201
227
  }
202
228
  super.attributeChangedCallback(e, t, n);
203
229
  }
@@ -225,7 +251,7 @@ var l = class extends i {
225
251
  return this.#i.value;
226
252
  }
227
253
  set models(e) {
228
- this.#i.value = e, e.length > 0 && this.#a.value === null && (this.#a.value = e[0].value, this.setAttribute("model", e[0].value));
254
+ this.#i.value = e, e.length > 0 ? this.setAttribute("models", e.map((e) => e.value).join(",")) : this.removeAttribute("models"), e.length > 0 && this.#a.value === null && (this.#a.value = e[0].value, this.setAttribute("model", e[0].value));
229
255
  }
230
256
  /** Currently selected model value. */
231
257
  get model() {
@@ -255,9 +281,16 @@ var l = class extends i {
255
281
  set gatewayConfig(e) {
256
282
  this.#c.value = e, e ? this.setAttribute("gateway-config", JSON.stringify(e)) : this.removeAttribute("gateway-config");
257
283
  }
284
+ /** Map of provider prefixes to gateway URLs. Enables auto-switching gateway based on model prefix. */
285
+ get gatewayUrls() {
286
+ return this.#l.value;
287
+ }
288
+ set gatewayUrls(e) {
289
+ this.#l.value = e, e ? this.setAttribute("gateway-urls", JSON.stringify(e)) : this.removeAttribute("gateway-urls");
290
+ }
258
291
  /** Whether the panel is currently streaming a response. Read-only. */
259
292
  get streaming() {
260
- return this.#l.value;
293
+ return this.#u.value;
261
294
  }
262
295
  /** Open the panel. Optionally focus the composer. */
263
296
  open(e) {
@@ -284,7 +317,7 @@ var l = class extends i {
284
317
  let o = document.createElement("span");
285
318
  o.setAttribute("slot", "label"), o.textContent = "Assistant", i.appendChild(o);
286
319
  let s = document.createElement("span");
287
- s.setAttribute("slot", "trailing"), s.style.display = "inline-flex", s.style.alignItems = "center", s.style.gap = "calc(var(--n-space) * 2)", i.appendChild(s), this.#v = s;
320
+ s.setAttribute("slot", "trailing"), s.className = "n-chat-panel-header-trailing", i.appendChild(s), this.#v = s;
288
321
  let c = document.createElement("n-body"), l = document.createElement("n-chat-content"), u = document.createElement("n-chat-feed");
289
322
  u.setAttribute("auto-scroll", ""), l.appendChild(u), this.#h = u, c.appendChild(l);
290
323
  let d = document.createElement("n-footer");
@@ -294,75 +327,94 @@ var l = class extends i {
294
327
  let m = document.createElement("n-chat-input-actions");
295
328
  this.#y = m;
296
329
  let h = document.createElement("n-button");
297
- h.setAttribute("variant", "ghost"), h.setAttribute("inline", ""), h.innerHTML = "<n-icon name=\"plus\"></n-icon>", m.appendChild(h);
298
- let g = document.createElement("n-button");
299
- g.setAttribute("variant", "ghost"), g.setAttribute("inline", ""), g.innerHTML = "<n-icon name=\"microphone\"></n-icon>", m.appendChild(g);
330
+ h.setAttribute("variant", "ghost"), h.setAttribute("inline", "");
331
+ let g = document.createElement("n-icon");
332
+ g.setAttribute("name", "plus"), h.appendChild(g), m.appendChild(h);
300
333
  let _ = document.createElement("n-button");
301
- _.setAttribute("variant", "primary"), _.setAttribute("intent", "accent"), _.setAttribute("radius", "round"), _.setAttribute("inline", ""), _.setAttribute("disabled", ""), _.dataset.submit = "", _.dataset.role = "submit", _.innerHTML = "<n-icon name=\"arrow-up\"></n-icon>", m.appendChild(_), f.appendChild(m), d.appendChild(f), this.append(i, c, d), this.addEffect(() => {
334
+ _.setAttribute("variant", "ghost"), _.setAttribute("inline", "");
335
+ let v = document.createElement("n-icon");
336
+ v.setAttribute("name", "microphone"), _.appendChild(v), m.appendChild(_);
337
+ let y = document.createElement("n-button");
338
+ y.setAttribute("variant", "primary"), y.setAttribute("intent", "accent"), y.setAttribute("radius", "round"), y.setAttribute("inline", ""), y.setAttribute("disabled", ""), y.dataset.submit = "", y.dataset.role = "submit";
339
+ let b = document.createElement("n-icon");
340
+ b.setAttribute("name", "arrow-up"), y.appendChild(b), m.appendChild(y), f.appendChild(m), d.appendChild(f), this.append(i, c, d), this.addEffect(() => {
302
341
  let e = this.#e.value;
303
342
  if (e && !this.#g) {
304
343
  let e = document.createElement("n-button");
305
- e.setAttribute("variant", "ghost"), e.setAttribute("inline", ""), e.setAttribute("aria-label", "Stop"), e.innerHTML = "<n-icon name=\"stop\"></n-icon>", e.addEventListener("native:press", this.#k), this.#g = e, this.#v?.prepend(e);
344
+ e.setAttribute("variant", "ghost"), e.setAttribute("inline", ""), e.setAttribute("aria-label", "Stop");
345
+ let t = document.createElement("n-icon");
346
+ t.setAttribute("name", "stop"), e.appendChild(t), e.addEventListener("native:press", this.#k), this.#g = e, this.#v?.prepend(e);
306
347
  } else !e && this.#g && (this.#g.removeEventListener("native:press", this.#k), this.#g.remove(), this.#g = null);
307
348
  }), this.addEffect(() => {
308
349
  let e = this.#t.value;
309
350
  if (e && !this.#_) {
310
351
  let e = document.createElement("n-button");
311
- e.setAttribute("variant", "ghost"), e.setAttribute("inline", ""), e.setAttribute("aria-label", "Restart"), e.innerHTML = "<n-icon name=\"arrow-counter-clockwise\"></n-icon>", e.addEventListener("native:press", this.#A), this.#_ = e;
312
- let t = this.#g?.nextSibling ?? this.#v?.firstChild ?? null;
313
- this.#v?.insertBefore(e, t);
352
+ e.setAttribute("variant", "ghost"), e.setAttribute("inline", ""), e.setAttribute("aria-label", "Restart");
353
+ let t = document.createElement("n-icon");
354
+ t.setAttribute("name", "arrow-counter-clockwise"), e.appendChild(t), e.addEventListener("native:press", this.#A), this.#_ = e;
355
+ let n = this.#g?.nextSibling ?? this.#v?.firstChild ?? null;
356
+ this.#v?.insertBefore(e, n);
314
357
  } else !e && this.#_ && (this.#_.removeEventListener("native:press", this.#A), this.#_.remove(), this.#_ = null);
315
358
  }), this.addEffect(() => {
316
359
  let e = this.#i.value;
317
360
  if (e.length > 0 && !this.#b) {
318
361
  let e = document.createElement("n-select");
319
- e.setAttribute("aria-label", "Select model"), e.setAttribute("data-role", "model-picker"), e.addEventListener("native:change", this.#j);
362
+ e.setAttribute("aria-label", "Select model"), e.setAttribute("data-role", "model-picker"), e.addEventListener("native:change", this.#M);
320
363
  let t = document.createElement("n-button");
321
- t.setAttribute("variant", "ghost"), t.setAttribute("inline", ""), t.innerHTML = "<n-icon name=\"dots-three-outline-fill\"></n-icon>";
322
- let n = document.createElement("n-listbox");
323
- n.setAttribute("popover", "manual"), e.append(t, n), this.#b = e, this.#x = n;
324
- let r = this.#y?.querySelector("[data-submit]");
325
- r ? this.#y?.insertBefore(e, r) : this.#y?.appendChild(e);
326
- } else e.length === 0 && this.#b && this.#z();
364
+ t.setAttribute("variant", "ghost"), t.setAttribute("inline", "");
365
+ let n = document.createElement("n-icon");
366
+ n.setAttribute("name", "dots-three-outline-fill"), t.appendChild(n);
367
+ let r = document.createElement("n-listbox");
368
+ r.setAttribute("popover", "manual"), e.append(t, r), this.#b = e, this.#x = r;
369
+ let i = this.#y?.querySelector("[data-submit]");
370
+ i ? this.#y?.insertBefore(e, i) : this.#y?.appendChild(e);
371
+ } else e.length === 0 && this.#b && this.#B();
327
372
  }), this.addEffect(() => {
328
373
  let e = this.#i.value, t = this.#a.value, n = this.#b, r = this.#x;
329
374
  if (!n || !r || e.length === 0) return;
330
375
  let i = t ?? e[0]?.value ?? null;
331
376
  if (i !== null) {
332
377
  r.innerHTML = "";
333
- for (let [t, n] of this.#R(e)) {
378
+ for (let [t, n] of this.#z(e)) {
334
379
  let e = document.createElement("n-option-group"), a = document.createElement("n-option-group-header");
335
380
  a.textContent = t, e.appendChild(a);
336
381
  for (let t of n) {
337
382
  let n = document.createElement("n-option"), r = t.value === i;
338
- n.setAttribute("value", t.value), n.setAttribute("aria-selected", String(r)), n.textContent = `${r ? "✓ " : ""}${t.label ?? t.value}`, e.appendChild(n);
383
+ n.setAttribute("value", t.value), n.setAttribute("aria-selected", String(r)), n.textContent = t.label ?? t.value, e.appendChild(n);
339
384
  }
340
385
  r.appendChild(e);
341
386
  }
342
387
  t === null && (this.#a.value = i, this.setAttribute("model", i)), n.value = i;
343
388
  }
389
+ }), this.addEffect(() => {
390
+ let e = this.#l.value, t = this.#a.value;
391
+ if (!e || !t) return;
392
+ let n = this.#o.value, r = this.#s.value;
393
+ if (n && r) return;
394
+ let i = this.#j(t);
395
+ i && (this.#o.value = i.gateway, this.setAttribute("gateway", i.gateway), this.#s.value = i.url, this.setAttribute("gateway-url", i.url));
344
396
  }), this.addEffect(() => {
345
397
  let i = this.#o.value, a = this.#s.value, o = this.#c.value;
346
398
  if (!i || !a) {
347
- this.#u = null;
399
+ this.#d = null;
348
400
  return;
349
401
  }
350
402
  let s = {
351
- clientId: this.#p ?? r(),
403
+ clientId: e(),
352
404
  baseUrl: a,
353
405
  gatewayConfig: o ?? {}
354
- };
355
- i === "openai" ? this.#u = e(s) : i === "claude" ? this.#u = t(s) : i === "mock" ? this.#u = n(s) : this.#u = null;
406
+ }, c = null;
407
+ i === "openai" ? c = t(s) : i === "claude" ? c = n(s) : i === "mock" && (c = r(s)), this.#d = c, c && c.bootstrapSession().catch(() => {});
356
408
  }), this.addEffect(() => {
357
- this.#o.value && (this.#e.value = this.#l.value);
358
- }), this.addEventListener("native:send", this.#M), this.addEventListener("native:chat-stop", this.#I), this.addEventListener("native:chat-restart", this.#L), this.deferChildren(() => {
409
+ this.#o.value && (this.#e.value = this.#u.value);
410
+ }), this.addEventListener("native:send", this.#N), this.addEventListener("native:chat-stop", this.#L), this.addEventListener("native:chat-restart", this.#R), this.deferChildren(() => {
359
411
  this.#S();
360
412
  }), this.#n.value === "ready" && queueMicrotask(() => {
361
413
  this.isConnected && this.focusComposer({ cursor: "end" }, "policy");
362
414
  });
363
415
  }
364
416
  teardown() {
365
- this.#f?.abort(), this.removeEventListener("native:send", this.#M), this.removeEventListener("native:chat-stop", this.#I), this.removeEventListener("native:chat-restart", this.#L), this.#g && this.#g.removeEventListener("native:press", this.#k), this.#_ && this.#_.removeEventListener("native:press", this.#A), this.#z(), this.#u = null, this.#d = [], this.#f = null, this.#m = null, this.#h = null, this.#g = null, this.#_ = null, this.#v = null, this.#y = null, this.#x = null, this.innerHTML = "", super.teardown();
417
+ this.#p?.abort(), this.removeEventListener("native:send", this.#N), this.removeEventListener("native:chat-stop", this.#L), this.removeEventListener("native:chat-restart", this.#R), this.#g && this.#g.removeEventListener("native:press", this.#k), this.#_ && this.#_.removeEventListener("native:press", this.#A), this.#B(), this.#d = null, this.#f = [], this.#p = null, this.#m = null, this.#h = null, this.#g = null, this.#_ = null, this.#v = null, this.#y = null, this.#x = null, this.innerHTML = "", super.teardown();
366
418
  }
367
419
  #S() {
368
420
  let e = this.querySelector(":scope > [slot=\"header-trailing\"]");
@@ -459,89 +511,134 @@ var l = class extends i {
459
511
  composed: !0
460
512
  }));
461
513
  };
462
- #j = (e) => {
514
+ /** Resolve gateway + URL from model prefix using the gateway-urls map. */
515
+ #j(e) {
516
+ let t = this.#l.value;
517
+ if (!t) return null;
518
+ let n = e.toLowerCase();
519
+ if (n.startsWith("claude") || n.startsWith("anthropic")) {
520
+ let e = t.claude;
521
+ if (e) return {
522
+ gateway: "claude",
523
+ url: e
524
+ };
525
+ }
526
+ if (n.startsWith("gpt") || n.startsWith("chatgpt") || n.startsWith("openai")) {
527
+ let e = t.openai;
528
+ if (e) return {
529
+ gateway: "openai",
530
+ url: e
531
+ };
532
+ }
533
+ for (let e of Object.keys(t)) if (n.startsWith(e.toLowerCase())) return {
534
+ gateway: e,
535
+ url: t[e]
536
+ };
537
+ return null;
538
+ }
539
+ #M = (e) => {
463
540
  let t = e.detail?.value ?? null;
464
541
  if (t === null) return;
465
542
  let n = this.#a.value;
466
- t !== n && (this.#a.value = t, this.setAttribute("model", t), this.dispatchEvent(new CustomEvent("native:model-change", {
543
+ if (t === n) return;
544
+ this.#a.value = t, this.setAttribute("model", t);
545
+ let r = this.#j(t);
546
+ r && (this.#o.value = r.gateway, this.setAttribute("gateway", r.gateway), this.#s.value = r.url, this.setAttribute("gateway-url", r.url)), this.dispatchEvent(new CustomEvent("native:model-change", {
467
547
  bubbles: !0,
468
548
  composed: !0,
469
549
  detail: {
470
550
  value: t,
471
551
  previousValue: n
472
552
  }
473
- })));
553
+ }));
474
554
  };
475
- #M = (e) => {
476
- if (!this.#u) return;
555
+ #N = (e) => {
556
+ if (!this.#d) return;
477
557
  let t = e.detail?.value;
478
- t?.trim() && this.#N(t);
558
+ t?.trim() && (e.stopImmediatePropagation(), this.#P(t));
479
559
  };
480
- async #N(e) {
481
- let t = this.#u;
482
- if (!t || this.#l.value) return;
483
- this.#f?.abort();
484
- let n = new AbortController();
485
- this.#f = n;
560
+ async #P(t) {
561
+ let n = this.#d;
562
+ if (!n || this.#u.value) return;
563
+ this.#p?.abort();
564
+ let r = new AbortController();
565
+ this.#p = r;
486
566
  let i = {
487
567
  role: "user",
488
- message: e,
568
+ message: t,
489
569
  datetime: Date.now()
490
570
  };
491
- this.#d.push(i), this.#P(i);
492
- let a = `msg-${Date.now()}-a`, o = this.#F(a), s = o?.querySelector("n-chat-message-text");
493
- this.#l.value = !0;
571
+ this.#f.push(i);
572
+ let a = this.constructor.MAX_CONTEXT_MESSAGES;
573
+ this.#f.length > a && (this.#f = this.#f.slice(-a)), this.#F(i);
574
+ let o = `msg-${e()}`, s = this.#I(o), c = s?.querySelector("n-chat-message-text");
575
+ s?.setAttribute("status", "typing"), this.#u.value = !0;
576
+ let l = this.#w();
577
+ l && (l.busy = !0);
494
578
  try {
495
- let i = await t.sendMessageStream({
496
- id: this.#p ?? r(),
497
- messages: this.#d,
498
- query: e,
579
+ let i = await n.sendMessageStream({
580
+ id: e(),
581
+ messages: this.#f,
582
+ query: t,
499
583
  model: this.#a.value ?? void 0,
500
- signal: n.signal,
584
+ signal: r.signal,
501
585
  onChunk: (e) => {
502
- s && (s.content = e.fullMessage), e.done && o?.setAttribute("status", e.partial ? "partial" : "sent");
586
+ s?.getAttribute("status") === "typing" && s.setAttribute("status", "streaming"), c && (c.content = e.fullMessage), e.done && s?.setAttribute("status", e.partial ? "partial" : "sent");
503
587
  }
504
588
  });
505
- this.#d.push({
589
+ this.#f.push({
506
590
  role: "assistant",
507
591
  message: i.message,
508
592
  datetime: i.datetime ?? Date.now(),
509
593
  partial: i.partial
510
594
  });
511
595
  } catch (e) {
512
- if (e.name === "AbortError") return;
513
- o?.setAttribute("status", "error"), s && (s.content = `Error: ${e.message}`);
596
+ if (e.name === "AbortError") {
597
+ s?.setAttribute("status", "partial");
598
+ return;
599
+ }
600
+ s?.setAttribute("status", "error");
601
+ let t = c ? c.content : "";
602
+ c && (t.trim() ? c.content = t + `\n\n---\n*Error: ${e.message}*` : c.content = `Error: ${e.message}`);
514
603
  } finally {
515
- this.#l.value = !1, this.#f = null;
604
+ this.#u.value = !1, this.#p = null;
605
+ let e = this.#w();
606
+ e && (e.busy = !1);
516
607
  }
517
608
  }
518
- #P(e) {
519
- let t = this.#h;
520
- if (!t) return;
521
- let n = document.createElement("n-chat-messages");
522
- n.setAttribute("role", e.role), n.setAttribute("sender", e.role === "user" ? "You" : "Assistant");
523
- let r = document.createElement("n-chat-message");
524
- r.setAttribute("role", e.role), r.setAttribute("message-id", `msg-${Date.now()}`), r.setAttribute("status", "sent");
525
- let i = document.createElement("n-chat-message-text");
526
- i.content = e.message, r.appendChild(i), n.appendChild(r), t.appendChild(n);
527
- }
528
- #F(e) {
609
+ #F(t) {
610
+ let n = this.#h;
611
+ if (!n) return;
612
+ let r = document.createElement("n-chat-messages");
613
+ r.setAttribute("data-role", t.role), r.setAttribute("sender", t.role === "user" ? "You" : "Assistant");
614
+ let i = document.createElement("n-chat-message");
615
+ i.setAttribute("data-role", t.role), i.setAttribute("message-id", `msg-${e()}`), i.setAttribute("status", "sent");
616
+ let a = document.createElement("n-chat-message-text");
617
+ a.content = t.message, i.appendChild(a), r.appendChild(i), n.appendChild(r);
618
+ }
619
+ #I(e) {
529
620
  let t = this.#h;
530
621
  if (!t) return null;
531
622
  let n = document.createElement("n-chat-messages");
532
- n.setAttribute("role", "assistant"), n.setAttribute("sender", "Assistant");
623
+ n.setAttribute("data-role", "assistant"), n.setAttribute("sender", "Assistant");
533
624
  let r = document.createElement("n-chat-message");
534
- r.setAttribute("role", "assistant"), r.setAttribute("message-id", e), r.setAttribute("status", "streaming");
625
+ r.setAttribute("data-role", "assistant"), r.setAttribute("message-id", e), r.setAttribute("status", "streaming");
535
626
  let i = document.createElement("n-chat-message-text");
536
627
  return r.appendChild(i), n.appendChild(r), t.appendChild(n), r;
537
628
  }
538
- #I = () => {
539
- this.#u && (this.#f?.abort(), this.#l.value = !1);
540
- };
541
629
  #L = () => {
542
- this.#u && (this.#f?.abort(), this.#l.value = !1, this.#d = [], this.#h && (this.#h.innerHTML = ""));
630
+ if (!this.#d) return;
631
+ this.#p?.abort(), this.#u.value = !1;
632
+ let e = this.#w();
633
+ e && (e.busy = !1);
634
+ };
635
+ #R = () => {
636
+ if (!this.#d) return;
637
+ this.#p?.abort(), this.#u.value = !1;
638
+ let e = this.#w();
639
+ e && (e.busy = !1), this.#f = [], this.#h && (this.#h.innerHTML = "");
543
640
  };
544
- #R(e) {
641
+ #z(e) {
545
642
  let t = /* @__PURE__ */ new Map(), n = (e) => {
546
643
  let t = `${e.label ?? ""} ${e.value}`.toLowerCase();
547
644
  return t.includes("claude") ? "Claude" : t.includes("gpt") || t.includes("openai") ? "ChatGPT" : t.includes("gemini") ? "Gemini" : "Models";
@@ -561,8 +658,8 @@ var l = class extends i {
561
658
  return (n === -1 ? 999 : n) - (i === -1 ? 999 : i);
562
659
  });
563
660
  }
564
- #z() {
565
- this.#b &&= (this.#b.removeEventListener("native:change", this.#j), this.#b.remove(), null), this.#x = null;
661
+ #B() {
662
+ this.#b &&= (this.#b.removeEventListener("native:change", this.#M), this.#b.remove(), null), this.#x = null;
566
663
  }
567
664
  }, d = 40, f = class extends i {
568
665
  static observedAttributes = [
@@ -630,10 +727,10 @@ var l = class extends i {
630
727
  super.setup(), this.#e.role = "log", this.setAttribute("aria-live", "polite"), this.setAttribute("aria-label", "Conversation"), this.hasAttribute("scrollable") || this.setAttribute("scrollable", ""), this.hasAttribute("auto-scroll") || (this.#t.value = !0), this.addEventListener("scroll", this.#f, { passive: !0 }), this.#r = new MutationObserver(this.#p), this.#r.observe(this, {
631
728
  childList: !0,
632
729
  subtree: !0
633
- }), this.addEventListener("native:message-action", this.#m), this.hasAttribute("virtual") && this.#c();
730
+ }), this.hasAttribute("virtual") && this.#c();
634
731
  }
635
732
  teardown() {
636
- this.removeEventListener("scroll", this.#f), this.removeEventListener("native:message-action", this.#m), this.#r?.disconnect(), this.#r = null, this.#l(), super.teardown();
733
+ this.removeEventListener("scroll", this.#f), this.#r?.disconnect(), this.#r = null, this.#l(), super.teardown();
637
734
  }
638
735
  #c() {
639
736
  if (this.#i) return;
@@ -691,7 +788,6 @@ var l = class extends i {
691
788
  });
692
789
  });
693
790
  };
694
- #m = (e) => {};
695
791
  }, p = class extends i {
696
792
  static observedAttributes = [
697
793
  "src",
@@ -799,7 +895,7 @@ const h = {
799
895
  */
800
896
  var _ = class extends i {
801
897
  static observedAttributes = [
802
- "role",
898
+ "data-role",
803
899
  "message-id",
804
900
  "timestamp",
805
901
  "status",
@@ -824,7 +920,7 @@ var _ = class extends i {
824
920
  return this.#t.value;
825
921
  }
826
922
  set role(e) {
827
- this.#t.value = e, this.setAttribute("role", e);
923
+ this.#t.value = e, this.setAttribute("data-role", e);
828
924
  }
829
925
  get messageId() {
830
926
  return this.getAttribute("message-id") ?? "";
@@ -859,7 +955,7 @@ var _ = class extends i {
859
955
  attributeChangedCallback(e, t, n) {
860
956
  if (t !== n) {
861
957
  switch (e) {
862
- case "role":
958
+ case "data-role":
863
959
  this.#t.value = n ?? "assistant";
864
960
  break;
865
961
  case "status":
@@ -993,7 +1089,7 @@ function v(e, t, n) {
993
1089
  */
994
1090
  var y = class extends i {
995
1091
  static observedAttributes = [
996
- "role",
1092
+ "data-role",
997
1093
  "sender",
998
1094
  "avatar-align"
999
1095
  ];
@@ -1010,7 +1106,7 @@ var y = class extends i {
1010
1106
  setup() {
1011
1107
  super.setup(), this.#e.role = "group";
1012
1108
  let e = this.getAttribute("sender");
1013
- e && (this.#e.ariaLabel = `Messages from ${e}`), this.#i(), this.#r = new MutationObserver((e) => {
1109
+ e && this.setAttribute("aria-label", `Messages from ${e}`), this.#i(), this.#r = new MutationObserver((e) => {
1014
1110
  for (let t of e) for (let e of t.addedNodes) e instanceof Element && e.localName !== "n-chat-avatar" && (e === this.#t || e === this.#n || (e.localName === "n-chat-message" ? this.#n?.appendChild(e) : this.#t?.appendChild(e)));
1015
1111
  }), this.#r.observe(this, { childList: !0 });
1016
1112
  }
@@ -1039,6 +1135,7 @@ var y = class extends i {
1039
1135
  #e = s("markdown");
1040
1136
  #t = s("");
1041
1137
  #n = null;
1138
+ #r = 0;
1042
1139
  get content() {
1043
1140
  return this.#t.value;
1044
1141
  }
@@ -1058,12 +1155,14 @@ var y = class extends i {
1058
1155
  super.setup(), this.deferChildren(() => {
1059
1156
  !this.#t.value && this.textContent?.trim() && (this.#t.value = this.textContent.trim()), this.#n = document.createElement("div"), this.#n.className = "n-chat-prose", this.textContent = "", this.appendChild(this.#n), this.addEffect(() => {
1060
1157
  let e = this.#t.value, t = this.#e.value;
1061
- this.#n && (t === "plain" ? this.#n.textContent = e : this.#n.innerHTML = w(e));
1158
+ this.#n && (t === "plain" ? this.#n.textContent = e : (cancelAnimationFrame(this.#r), this.#r = requestAnimationFrame(() => {
1159
+ this.#n && (this.#n.innerHTML = T(w(e)));
1160
+ })));
1062
1161
  });
1063
1162
  });
1064
1163
  }
1065
1164
  teardown() {
1066
- this.#n = null, super.teardown();
1165
+ cancelAnimationFrame(this.#r), this.#n = null, super.teardown();
1067
1166
  }
1068
1167
  }, x = new Set([
1069
1168
  "p",
@@ -1248,7 +1347,7 @@ var E = class extends i {
1248
1347
  n.className = "n-chat-activity-sep", n.textContent = "|", n.setAttribute("aria-hidden", "true"), this.#c = document.createElement("span"), this.#c.className = "n-chat-activity-label", this.#u = document.createElement("span"), this.#u.className = "n-chat-activity-dots", this.#u.setAttribute("aria-hidden", "true"), this.#u.innerHTML = "<i></i><i></i><i></i>", t.append(this.#l, n, this.#c, this.#u), this.#d = document.createElement("div"), this.#d.className = "n-chat-activity-content", this.#d.hidden = !0, this.#d.appendChild(e), this.append(t, this.#d);
1249
1348
  }
1250
1349
  #p() {
1251
- this.#o = performance.now(), this.#h();
1350
+ this.#m(), this.#o = performance.now(), this.#h();
1252
1351
  }
1253
1352
  #m() {
1254
1353
  this.#s &&= (cancelAnimationFrame(this.#s), 0);
@@ -1389,6 +1488,7 @@ var k = class extends i {
1389
1488
  #n = s("inline");
1390
1489
  #r = s(null);
1391
1490
  #i = null;
1491
+ #a = null;
1392
1492
  constructor() {
1393
1493
  super(), this.#e = this.attachInternals();
1394
1494
  }
@@ -1429,48 +1529,57 @@ var k = class extends i {
1429
1529
  if (!this.#i || (this.#i.textContent = "", !e)) return;
1430
1530
  let n = M(e);
1431
1531
  if (n.length > 0) {
1432
- this.#a(n), this.dispatchEvent(new CustomEvent("native:genui-error", {
1532
+ this.#o(n), this.dispatchEvent(new CustomEvent("native:genui-error", {
1433
1533
  bubbles: !0,
1434
1534
  composed: !0,
1435
1535
  detail: { errors: n }
1436
1536
  }));
1437
1537
  return;
1438
1538
  }
1439
- if (t === "lightbox") this.#o(e);
1539
+ if (t === "lightbox") this.#s(e);
1440
1540
  else {
1441
1541
  let t = N(e);
1442
1542
  t && this.#i.appendChild(t);
1443
1543
  }
1444
1544
  this.#e.states.add("rendered");
1445
- }), this.addEventListener("native:press", this.#c);
1545
+ }), this.addEventListener("native:press", this.#u);
1446
1546
  }
1447
1547
  teardown() {
1448
- this.removeEventListener("native:press", this.#c), this.#i = null, super.teardown();
1548
+ this.removeEventListener("native:press", this.#u), this.#l(), this.#i = null, super.teardown();
1449
1549
  }
1450
- #a(e) {
1550
+ #o(e) {
1451
1551
  if (!this.#i) return;
1452
1552
  let t = document.createElement("div");
1453
1553
  t.className = "n-chat-genui-error", t.textContent = `Schema validation failed: ${e.join(", ")}`, this.#i.appendChild(t);
1454
1554
  }
1455
- #o(e) {
1555
+ #s(e) {
1456
1556
  if (!this.#i) return;
1457
1557
  let t = document.createElement("n-card");
1458
1558
  t.dataset.role = "preview";
1459
1559
  let n = document.createElement("span");
1460
1560
  n.textContent = `Interactive UI (${e.tag})`, t.appendChild(n);
1461
1561
  let r = document.createElement("n-button");
1462
- r.setAttribute("variant", "outline"), r.setAttribute("size", "sm"), r.setAttribute("inline", ""), r.textContent = "Open", r.addEventListener("click", () => this.#s(e)), t.appendChild(r), this.#i.appendChild(t);
1562
+ r.setAttribute("variant", "outline"), r.setAttribute("size", "sm"), r.setAttribute("inline", ""), r.textContent = "Open", r.addEventListener("click", () => this.#c(e)), t.appendChild(r), this.#i.appendChild(t);
1463
1563
  }
1464
- #s(e) {
1564
+ #c(e) {
1565
+ this.#l();
1465
1566
  let t = document.createElement("n-dialog"), n = N(e);
1466
- n && t.appendChild(n), this.appendChild(t), requestAnimationFrame(() => {
1567
+ n && t.appendChild(n), this.appendChild(t), this.#a = t, requestAnimationFrame(() => {
1467
1568
  let e = t.querySelector("dialog");
1468
1569
  e && e.showModal();
1469
1570
  }), t.addEventListener("close", () => {
1470
- t.remove();
1571
+ t.remove(), this.#a === t && (this.#a = null);
1471
1572
  });
1472
1573
  }
1473
- #c = (e) => {
1574
+ #l() {
1575
+ if (!this.#a) return;
1576
+ let e = this.#a.querySelector("dialog");
1577
+ if (e?.open) try {
1578
+ e.close();
1579
+ } catch {}
1580
+ this.#a.remove(), this.#a = null;
1581
+ }
1582
+ #u = (e) => {
1474
1583
  this.#i?.contains(e.target) && this.dispatchEvent(new CustomEvent("native:genui-action", {
1475
1584
  bubbles: !0,
1476
1585
  composed: !0,
@@ -1588,36 +1697,45 @@ var P = class extends i {
1588
1697
  }
1589
1698
  setup() {
1590
1699
  super.setup(), this.addEffect(o(this, this.#a, this.#e)), this.addEffect(() => {
1591
- this.#s();
1700
+ this.#t.value, this.#r.value, this.#n.value, this.#s();
1701
+ }), this.addEffect(() => {
1702
+ let e = this.#o.value, t = this.querySelectorAll("[data-value]");
1703
+ for (let n of t) {
1704
+ let t = n.getAttribute("data-value") ?? "", r = e.has(t);
1705
+ n.setAttribute("variant", r ? "primary" : "outline"), n.setAttribute("aria-pressed", String(r));
1706
+ }
1707
+ let n = this.querySelector("[data-action=\"submit\"]");
1708
+ n && this.#i.value && n.toggleAttribute("disabled", e.size === 0);
1592
1709
  }), this.addEventListener("native:press", this.#c);
1593
1710
  }
1594
1711
  teardown() {
1595
1712
  this.removeEventListener("native:press", this.#c), super.teardown();
1596
1713
  }
1597
1714
  #s() {
1598
- let e = this.#t.value, t = this.#r.value, n = this.#o.value, r = this.#n.value;
1599
- if (this.textContent = "", e) {
1715
+ let e = this.#t.value, t = this.#r.value, n = this.#n.value;
1716
+ if (this.textContent = "", t.length === 0) return;
1717
+ if (e) {
1600
1718
  let t = document.createElement("div");
1601
1719
  t.className = "n-chat-structured-question", t.textContent = e, this.appendChild(t);
1602
1720
  }
1603
- let i = document.createElement("n-stack");
1604
- i.setAttribute("direction", "row"), i.setAttribute("wrap", ""), i.setAttribute("role", r === "multi" ? "group" : "radiogroup");
1721
+ let r = document.createElement("n-stack");
1722
+ r.setAttribute("direction", "row"), r.setAttribute("wrap", ""), r.setAttribute("role", n === "multi" ? "group" : "radiogroup");
1605
1723
  for (let e of t) {
1606
- let t = document.createElement("n-button"), r = n.has(e.value);
1607
- if (t.setAttribute("variant", r ? "primary" : "outline"), t.setAttribute("data-value", e.value), t.setAttribute("aria-pressed", String(r)), e.icon) {
1724
+ let t = document.createElement("n-button");
1725
+ if (t.setAttribute("variant", "outline"), t.setAttribute("data-value", e.value), t.setAttribute("aria-pressed", "false"), e.icon) {
1608
1726
  let n = document.createElement("n-icon");
1609
1727
  n.setAttribute("name", e.icon), n.setAttribute("slot", "leading"), t.appendChild(n);
1610
1728
  }
1611
- let a = document.createElement("span");
1612
- a.setAttribute("slot", "label"), a.textContent = e.label, t.appendChild(a), i.appendChild(t);
1729
+ let n = document.createElement("span");
1730
+ n.setAttribute("slot", "label"), n.textContent = e.label, t.appendChild(n), r.appendChild(t);
1613
1731
  }
1614
- this.appendChild(i);
1615
- let a = document.createElement("div");
1616
- a.className = "n-chat-structured-actions";
1732
+ this.appendChild(r);
1733
+ let i = document.createElement("div");
1734
+ i.className = "n-chat-structured-actions";
1735
+ let a = document.createElement("n-button");
1736
+ a.setAttribute("variant", "ghost"), a.setAttribute("size", "sm"), a.setAttribute("inline", ""), a.setAttribute("data-action", "cancel"), a.textContent = "Skip", i.appendChild(a);
1617
1737
  let o = document.createElement("n-button");
1618
- o.setAttribute("variant", "ghost"), o.setAttribute("size", "sm"), o.setAttribute("inline", ""), o.setAttribute("data-action", "cancel"), o.textContent = "Skip", a.appendChild(o);
1619
- let s = document.createElement("n-button");
1620
- s.setAttribute("variant", "primary"), s.setAttribute("size", "sm"), s.setAttribute("inline", ""), s.setAttribute("data-action", "submit"), s.textContent = "Submit", this.#i.value && n.size === 0 && s.setAttribute("disabled", ""), a.appendChild(s), this.appendChild(a);
1738
+ o.setAttribute("variant", "primary"), o.setAttribute("size", "sm"), o.setAttribute("inline", ""), o.setAttribute("data-action", "submit"), o.textContent = "Submit", this.#i.value && o.setAttribute("disabled", ""), i.appendChild(o), this.appendChild(i);
1621
1739
  }
1622
1740
  #c = (e) => {
1623
1741
  if (this.#a.value) return;