@green-on-grey/ui-kit 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/chat.js CHANGED
@@ -1,20 +1,175 @@
1
- import { c as e, d as t, i as n, l as r, s as i } from "./ui-CGgZtEVm.js";
1
+ import { c as e, d as t, i as n, l as r, s as i } from "./ui-joAvYmUH.js";
2
2
  import { n as a, t as o } from "./i18n-BJ8rsBp6.js";
3
3
  import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
4
4
  import { useCallback as u, useEffect as d, useLayoutEffect as f, useRef as p, useState as m } from "react";
5
5
  import { useTranslation as h } from "react-i18next";
6
+ //#region src/chat/CommandPalette.tsx
7
+ function g(e, t) {
8
+ let n = t.toLowerCase();
9
+ return e.filter((e) => e.name.toLowerCase().includes(n) || (e.description ?? "").toLowerCase().includes(n));
10
+ }
11
+ function _({ items: e, active: n, onPick: r, onHover: i }) {
12
+ let o = a(), s = e.filter((e) => e.kind === "command"), u = e.filter((e) => e.kind === "skill"), d = (e, a) => /* @__PURE__ */ l("button", {
13
+ type: "button",
14
+ role: "option",
15
+ "aria-selected": a === n,
16
+ className: `palette-row${a === n ? " on" : ""}`,
17
+ onMouseDown: (t) => {
18
+ t.preventDefault(), r(e);
19
+ },
20
+ onMouseEnter: () => i(a),
21
+ children: [
22
+ e.kind === "skill" ? /* @__PURE__ */ c(t, {
23
+ name: "spark",
24
+ size: 14
25
+ }) : /* @__PURE__ */ c("span", {
26
+ className: "slash",
27
+ "aria-hidden": "true"
28
+ }),
29
+ /* @__PURE__ */ c("span", {
30
+ className: "nm",
31
+ children: e.kind === "command" ? "/" + e.name : e.name
32
+ }),
33
+ /* @__PURE__ */ c("span", {
34
+ className: "ds",
35
+ children: e.description
36
+ }),
37
+ e.source && /* @__PURE__ */ c("span", {
38
+ className: "src",
39
+ children: e.source
40
+ })
41
+ ]
42
+ }, e.kind + e.name);
43
+ return /* @__PURE__ */ l("div", {
44
+ className: "palette",
45
+ role: "listbox",
46
+ "aria-label": o("chat.palette.title"),
47
+ children: [
48
+ e.length === 0 && /* @__PURE__ */ c("div", {
49
+ className: "palette-empty",
50
+ children: o("chat.palette.empty")
51
+ }),
52
+ s.length > 0 && /* @__PURE__ */ c("div", {
53
+ className: "palette-h",
54
+ children: o("chat.palette.commands")
55
+ }),
56
+ s.map((t) => d(t, e.indexOf(t))),
57
+ e.length > 0 && /* @__PURE__ */ c("div", {
58
+ className: "palette-h",
59
+ children: o("chat.palette.skills")
60
+ }),
61
+ u.length === 0 && e.length > 0 && /* @__PURE__ */ c("div", {
62
+ className: "palette-empty",
63
+ children: o("chat.palette.noSkills")
64
+ }),
65
+ u.map((t) => d(t, e.indexOf(t)))
66
+ ]
67
+ });
68
+ }
69
+ //#endregion
70
+ //#region src/chat/ContextMeter.tsx
71
+ function v(e, t) {
72
+ return new Intl.NumberFormat(t === "zh" ? "zh-CN" : t, {
73
+ notation: "compact",
74
+ maximumFractionDigits: 1
75
+ }).format(e);
76
+ }
77
+ function y({ context: e, onCompact: n, onReset: r }) {
78
+ let s = a(), { i18n: u } = h(o), [d, f] = m(!1), p = i(d, () => f(!1)), g = e.window > 0 ? Math.min(1, e.tokens / e.window) : 0, _ = Math.round(g * 100), y = g >= .9 ? "full" : g >= .7 ? "warn" : "", b = 2 * Math.PI * 7, x = u.language;
79
+ return /* @__PURE__ */ l("div", {
80
+ className: "ctxmeter",
81
+ ref: p,
82
+ children: [/* @__PURE__ */ c("button", {
83
+ type: "button",
84
+ className: `ctxring ${y}`,
85
+ "aria-expanded": d,
86
+ onClick: () => f((e) => !e),
87
+ "aria-label": s("chat.context.meter", {
88
+ used: v(e.tokens, x),
89
+ total: v(e.window, x),
90
+ pct: _
91
+ }),
92
+ title: s("chat.context.meter", {
93
+ used: v(e.tokens, x),
94
+ total: v(e.window, x),
95
+ pct: _
96
+ }),
97
+ children: /* @__PURE__ */ l("svg", {
98
+ viewBox: "0 0 18 18",
99
+ "aria-hidden": "true",
100
+ children: [/* @__PURE__ */ c("circle", {
101
+ className: "bg",
102
+ cx: "9",
103
+ cy: "9",
104
+ r: 7
105
+ }), /* @__PURE__ */ c("circle", {
106
+ className: "fg",
107
+ cx: "9",
108
+ cy: "9",
109
+ r: 7,
110
+ strokeDasharray: `${(b * g).toFixed(1)} ${b.toFixed(1)}`,
111
+ transform: "rotate(-90 9 9)"
112
+ })]
113
+ })
114
+ }), d && /* @__PURE__ */ l("div", {
115
+ className: "ctxtip",
116
+ role: "dialog",
117
+ children: [
118
+ /* @__PURE__ */ c("div", { children: s("chat.context.meter", {
119
+ used: v(e.tokens, x),
120
+ total: v(e.window, x),
121
+ pct: _
122
+ }) }),
123
+ y === "full" && /* @__PURE__ */ c("div", {
124
+ className: "small muted",
125
+ style: { marginTop: 4 },
126
+ children: s("chat.context.full")
127
+ }),
128
+ y === "full" && (n || r) && /* @__PURE__ */ l("div", {
129
+ className: "row",
130
+ style: {
131
+ marginTop: 8,
132
+ gap: 6
133
+ },
134
+ children: [n && /* @__PURE__ */ l("button", {
135
+ type: "button",
136
+ className: "btn sm",
137
+ onClick: () => {
138
+ f(!1), n();
139
+ },
140
+ children: [/* @__PURE__ */ c(t, {
141
+ name: "compress",
142
+ size: 14
143
+ }), s("chat.context.compact")]
144
+ }), r && /* @__PURE__ */ l("button", {
145
+ type: "button",
146
+ className: "btn sm ghost",
147
+ onClick: () => {
148
+ f(!1), r();
149
+ },
150
+ children: [/* @__PURE__ */ c(t, {
151
+ name: "undo",
152
+ size: 14
153
+ }), s("chat.context.reset")]
154
+ })]
155
+ })
156
+ ]
157
+ })]
158
+ });
159
+ }
160
+ //#endregion
6
161
  //#region src/chat/MessageView.tsx
7
- var g = (e) => e === "zh" ? "zh-CN" : e;
8
- function _(e, t) {
9
- return new Intl.DateTimeFormat(g(t), {
162
+ var b = (e) => e === "zh" ? "zh-CN" : e;
163
+ function x(e, t) {
164
+ return new Intl.DateTimeFormat(b(t), {
10
165
  hour: "2-digit",
11
166
  minute: "2-digit"
12
167
  }).format(new Date(e));
13
168
  }
14
- function v(e, t) {
169
+ function S(e, t) {
15
170
  return t || e.length <= 3 ? e : e.slice(-2);
16
171
  }
17
- var y = {
172
+ var C = {
18
173
  done: {
19
174
  icon: "check",
20
175
  cls: "ok"
@@ -28,12 +183,13 @@ var y = {
28
183
  cls: "run"
29
184
  }
30
185
  };
31
- function b({ m: e, busy: n, onRetry: i }) {
186
+ function w({ m: e, busy: n, onRetry: i }) {
32
187
  let { t: a, i18n: u } = h(o), [d, f] = m(!1);
33
188
  if (e.role === "note") return /* @__PURE__ */ c("div", {
34
189
  className: "sysnote",
35
190
  children: e.text
36
191
  });
192
+ if (e.role === "event" && e.event) return /* @__PURE__ */ c(T, { m: e });
37
193
  let p = e.mark && /* @__PURE__ */ l("div", {
38
194
  className: "chan",
39
195
  children: [
@@ -44,7 +200,7 @@ function b({ m: e, busy: n, onRetry: i }) {
44
200
  " ",
45
201
  e.mark.text,
46
202
  " · ",
47
- _(e.createdAt, u.language)
203
+ x(e.createdAt, u.language)
48
204
  ]
49
205
  }), g = e.attachments && e.attachments.length > 0 && /* @__PURE__ */ c("div", {
50
206
  className: "atts",
@@ -83,30 +239,30 @@ function b({ m: e, busy: n, onRetry: i }) {
83
239
  })
84
240
  ]
85
241
  });
86
- let b = e.steps ?? [], x = (e.status === "streaming" || e.status === "pending") && !e.text && !e.content;
242
+ let _ = e.steps ?? [], v = (e.status === "streaming" || e.status === "pending") && !e.text && !e.content;
87
243
  return /* @__PURE__ */ l("div", {
88
244
  className: "m a",
89
245
  children: [
90
246
  p,
91
- b.length > 3 && /* @__PURE__ */ c("button", {
247
+ _.length > 3 && /* @__PURE__ */ c("button", {
92
248
  className: "tools-fold",
93
249
  onClick: () => f((e) => !e),
94
250
  "aria-expanded": d,
95
- children: d ? a("chat.hideSteps") : a("chat.moreSteps", { count: b.length - 2 })
251
+ children: d ? a("chat.hideSteps") : a("chat.moreSteps", { count: _.length - 2 })
96
252
  }),
97
- v(b, d).map((e) => /* @__PURE__ */ l("div", {
253
+ S(_, d).map((e) => /* @__PURE__ */ l("div", {
98
254
  className: "tool",
99
255
  title: e.title,
100
256
  children: [/* @__PURE__ */ c(t, {
101
- name: y[e.status].icon,
257
+ name: C[e.status].icon,
102
258
  size: 14,
103
- className: y[e.status].cls
259
+ className: C[e.status].cls
104
260
  }), /* @__PURE__ */ c("span", {
105
261
  className: "tx",
106
262
  children: e.text
107
263
  })]
108
264
  }, e.id)),
109
- x && /* @__PURE__ */ c("div", {
265
+ v && /* @__PURE__ */ c("div", {
110
266
  className: "bub",
111
267
  children: /* @__PURE__ */ l("span", {
112
268
  className: "typing",
@@ -120,6 +276,7 @@ function b({ m: e, busy: n, onRetry: i }) {
120
276
  }),
121
277
  e.content ?? (e.text && /* @__PURE__ */ c("div", {
122
278
  className: "bub",
279
+ title: e.hint,
123
280
  children: /* @__PURE__ */ c(r, { text: e.text })
124
281
  })),
125
282
  g,
@@ -143,68 +300,184 @@ function b({ m: e, busy: n, onRetry: i }) {
143
300
  ]
144
301
  });
145
302
  }
303
+ function T({ m: e }) {
304
+ let { t: n, i18n: r } = h(o), [i, a] = m(!1), s = e.event;
305
+ return /* @__PURE__ */ l("div", {
306
+ className: "evdiv",
307
+ children: [/* @__PURE__ */ c("div", {
308
+ className: "evline",
309
+ role: "separator",
310
+ children: /* @__PURE__ */ l("span", {
311
+ className: "evchip",
312
+ children: [
313
+ /* @__PURE__ */ c(t, {
314
+ name: s.icon,
315
+ size: 12
316
+ }),
317
+ s.text,
318
+ " · ",
319
+ x(e.createdAt, r.language),
320
+ s.details && /* @__PURE__ */ l("button", {
321
+ type: "button",
322
+ className: "textbtn",
323
+ "aria-expanded": i,
324
+ onClick: () => a((e) => !e),
325
+ children: [
326
+ n("chat.event.details"),
327
+ " ",
328
+ i ? "▴" : "▾"
329
+ ]
330
+ })
331
+ ]
332
+ })
333
+ }), i && s.details && /* @__PURE__ */ c("div", {
334
+ className: "evdetails",
335
+ children: s.details
336
+ })]
337
+ });
338
+ }
339
+ //#endregion
340
+ //#region src/chat/transcription.ts
341
+ async function E(e, t, n) {
342
+ n.busy(!0);
343
+ let r;
344
+ try {
345
+ r = await t(e);
346
+ } catch (r) {
347
+ n.busy(!1), n.failed(r instanceof Error && r.message ? r.message : void 0, () => void E(e, t, n));
348
+ return;
349
+ }
350
+ n.busy(!1), r !== null && (r ? n.text(r) : n.empty());
351
+ }
146
352
  //#endregion
147
353
  //#region src/chat/useRecorder.ts
148
- function x() {
149
- let e = typeof window < "u" && "MediaRecorder" in window && !!navigator.mediaDevices?.getUserMedia, [t, n] = m(!1), [r, i] = m(0), [a, o] = m(!1), s = p(null), c = p([]), l = p(void 0), f = p(null), h = u(() => {
150
- window.clearInterval(l.current), s.current?.stream.getTracks().forEach((e) => e.stop()), s.current = null, n(!1);
151
- }, []), g = u(async () => {
152
- if (e && !s.current) {
153
- o(!1);
354
+ function D(e = 300, t) {
355
+ let n = typeof window < "u" && "MediaRecorder" in window && !!navigator.mediaDevices?.getUserMedia, [r, i] = m(!1), [a, o] = m(0), [s, c] = m(0), [l, f] = m(!1), h = p(null), g = p([]), _ = p(void 0), v = p(null), y = p(null), b = p(!1), x = p(t);
356
+ d(() => {
357
+ x.current = t;
358
+ });
359
+ let S = u(() => {
360
+ window.clearInterval(_.current), h.current?.stream.getTracks().forEach((e) => e.stop()), h.current = null, v.current?.close().catch(() => void 0), v.current = null, i(!1), c(0);
361
+ }, []), C = u(async () => {
362
+ if (n && !h.current) {
363
+ f(!1);
154
364
  try {
155
- let e = await navigator.mediaDevices.getUserMedia({ audio: !0 }), t = new MediaRecorder(e);
156
- c.current = [], t.ondataavailable = (e) => e.data.size > 0 && c.current.push(e.data), t.onstop = () => {
157
- let e = c.current.length ? new Blob(c.current, { type: t.mimeType || "audio/webm" }) : null;
158
- h(), f.current?.(e), f.current = null;
159
- }, s.current = t, t.start(), i(0), n(!0);
160
- let r = Date.now();
161
- l.current = window.setInterval(() => i(Math.floor((Date.now() - r) / 1e3)), 250);
365
+ let t = await navigator.mediaDevices.getUserMedia({ audio: !0 }), n = new MediaRecorder(t);
366
+ g.current = [], b.current = !1, n.ondataavailable = (e) => e.data.size > 0 && g.current.push(e.data), n.onstop = () => {
367
+ let e = !b.current && g.current.length ? new Blob(g.current, { type: n.mimeType || "audio/webm" }) : null;
368
+ S(), y.current?.(e), y.current = null;
369
+ };
370
+ let r = null;
371
+ try {
372
+ let e = window.AudioContext ?? window.webkitAudioContext;
373
+ e && (v.current = new e(), r = v.current.createAnalyser(), r.fftSize = 256, v.current.createMediaStreamSource(t).connect(r));
374
+ } catch {
375
+ r = null;
376
+ }
377
+ let a = r ? new Uint8Array(r.fftSize) : null;
378
+ h.current = n, n.start(), o(0), i(!0);
379
+ let s = Date.now(), l = !1;
380
+ _.current = window.setInterval(() => {
381
+ let t = Math.floor((Date.now() - s) / 1e3);
382
+ if (o(t), r && a) {
383
+ r.getByteTimeDomainData(a);
384
+ let e = 0;
385
+ for (let t of a) e = Math.max(e, Math.abs(t - 128));
386
+ c(Math.min(1, e / 64));
387
+ }
388
+ t >= e && !l && (l = !0, x.current?.());
389
+ }, 100);
162
390
  } catch {
163
- o(!0), h();
391
+ f(!0), S();
164
392
  }
165
393
  }
166
- }, [e, h]), _ = u(() => new Promise((e) => {
167
- let t = s.current;
394
+ }, [
395
+ n,
396
+ S,
397
+ e
398
+ ]), w = u(() => new Promise((e) => {
399
+ let t = h.current;
168
400
  if (!t || t.state === "inactive") return e(null);
169
- f.current = e, t.stop();
170
- }), []);
171
- return d(() => () => h(), [h]), {
172
- supported: e,
173
- recording: t,
174
- seconds: `${Math.floor(r / 60)}:${String(r % 60).padStart(2, "0")}`,
175
- error: a,
176
- start: g,
177
- stop: _
401
+ y.current = e, t.stop();
402
+ }), []), T = u(() => {
403
+ b.current = !0, w();
404
+ }, [w]);
405
+ return d(() => () => S(), [S]), {
406
+ supported: n,
407
+ recording: r,
408
+ seconds: a,
409
+ level: s,
410
+ error: l,
411
+ start: C,
412
+ stop: w,
413
+ cancel: T
178
414
  };
179
415
  }
416
+ function O(e) {
417
+ return `${Math.floor(e / 60)}:${String(e % 60).padStart(2, "0")}`;
418
+ }
180
419
  //#endregion
181
420
  //#region src/chat/Chat.tsx
182
- function S(n) {
183
- let r = a(), i = e(), [o, u] = m(""), [d, h] = m([]), [g, _] = m(!1), [v, y] = m(null), S = p(null), C = p(null), w = x(), { messages: T, busy: E = !1 } = n, D = T[0]?.id, O = T[T.length - 1], k = O?.id, A = O?.text.length, j = O?.steps?.length, M = p({ height: 0 });
421
+ function k(n) {
422
+ let r = a(), i = e(), [o, u] = m(""), [h, v] = m([]), [b, x] = m(!1), [S, C] = m(null), [T, k] = m(0), [A, j] = m(!1), [M, N] = m(null), [P, ee] = m(!1), F = p(!1), I = p(null), L = p(null), R = p(null), z = n.voiceMaxSeconds ?? 300, B = D(z, () => void oe()), { messages: V, busy: H = !1 } = n, U = n.onPendingChange;
423
+ d(() => U?.(h), [h, U]);
424
+ let W = V[0]?.id, G = V[V.length - 1], K = G?.id, te = G?.text.length, ne = G?.steps?.length, q = p({ height: 0 });
184
425
  f(() => {
185
- let e = S.current;
426
+ let e = I.current;
186
427
  if (!e) return;
187
- let t = M.current;
188
- e.scrollTop = t.first !== void 0 && D !== t.first && k === t.last ? e.scrollTop + (e.scrollHeight - t.height) : e.scrollHeight, M.current = {
189
- first: D,
190
- last: k,
428
+ let t = q.current;
429
+ e.scrollTop = t.first !== void 0 && W !== t.first && K === t.last ? e.scrollTop + (e.scrollHeight - t.height) : e.scrollHeight, q.current = {
430
+ first: W,
431
+ last: K,
191
432
  height: e.scrollHeight
192
433
  };
193
434
  }, [
194
- T.length,
195
- D,
196
- k,
197
- A,
198
- j
435
+ V.length,
436
+ W,
437
+ K,
438
+ te,
439
+ ne
199
440
  ]);
200
- let N = async (e, t) => {
201
- let r = e.trim();
202
- if (!(!r && d.length === 0 || E || n.readOnly)) try {
203
- await n.onSend(r, d.map((e) => e.id), t), u(""), h([]), y(null);
441
+ let J = n.commands && !S && o.startsWith("/") && !/\s/.test(o) ? o.slice(1) : null, Y = J === null ? [] : g(n.commands ?? [], J), X = J !== null && !A, Z = () => {
442
+ u(""), v([]), C(null), N(null), F.current = !1;
443
+ }, Q = async (e, t) => {
444
+ if (n.onCommand) try {
445
+ await n.onCommand(e, t), Z();
204
446
  } catch {}
205
- }, P = async (e) => {
447
+ }, $ = async (e, t = !1) => {
448
+ let r = e.trim();
449
+ if (!(!r && h.length === 0 && !S || H || n.readOnly)) {
450
+ if (!t && !S && n.commands && r.startsWith("/")) {
451
+ let [e, ...t] = r.slice(1).split(/\s+/), i = n.commands.find((t) => t.kind === "command" && t.name === e);
452
+ if (i) return Q(i.name, t.join(" "));
453
+ if (e && !r.includes("\n")) {
454
+ N("/" + e);
455
+ return;
456
+ }
457
+ }
458
+ try {
459
+ await n.onSend(r, h.map((e) => e.id), F.current, S ?? void 0), Z();
460
+ } catch {}
461
+ }
462
+ }, re = (e) => {
463
+ k(0), e.kind === "skill" ? (C(e.name), u("")) : e.takesText ? u("/" + e.name + " ") : Q(e.name, ""), R.current?.focus();
464
+ }, ie = (e) => {
465
+ if (X && Y.length > 0) {
466
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
467
+ e.preventDefault();
468
+ let t = e.key === "ArrowDown" ? 1 : -1;
469
+ k((e) => (e + t + Y.length) % Y.length);
470
+ return;
471
+ }
472
+ if (e.key === "Enter" && !e.shiftKey || e.key === "Tab") {
473
+ e.preventDefault(), re(Y[Math.min(T, Y.length - 1)]);
474
+ return;
475
+ }
476
+ }
477
+ X && e.key === "Escape" ? (e.preventDefault(), j(!0)) : e.key === "Backspace" && S && o === "" ? C(null) : e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing && (e.preventDefault(), $(o));
478
+ }, ae = async (e) => {
206
479
  if (e?.length && n.onUpload) {
207
- _(!0);
480
+ x(!0);
208
481
  for (let t of Array.from(e)) {
209
482
  if (n.upload && t.size > n.upload.maxBytes) {
210
483
  i({
@@ -215,21 +488,36 @@ function S(n) {
215
488
  continue;
216
489
  }
217
490
  let e = await n.onUpload(t).catch(() => null);
218
- e && h((t) => [...t, e]);
491
+ e && v((t) => [...t, e]);
219
492
  }
220
- _(!1), C.current && (C.current.value = "");
493
+ x(!1), L.current && (L.current.value = "");
221
494
  }
222
- }, F = async () => {
223
- let e = await w.stop();
224
- if (!e || !n.onTranscribe) return;
225
- let t = await n.onTranscribe(e).catch(() => null);
226
- t !== null && (t ? y(t) : i({
227
- kind: "error",
228
- title: r("chat.voice.notRecognized")
229
- }));
230
- }, I = (e) => {
231
- (e.key === " " || e.key === "Enter") && (e.preventDefault(), !e.repeat && (w.recording ? F() : w.start()));
232
- }, L = r("chat.placeholder", { name: n.agentName });
495
+ };
496
+ async function oe() {
497
+ let e = await B.stop();
498
+ e && n.onTranscribe && await E(e, n.onTranscribe, {
499
+ busy: ee,
500
+ empty: () => i({
501
+ kind: "error",
502
+ title: r("chat.voice.notRecognized")
503
+ }),
504
+ failed: (e, t) => i({
505
+ kind: "error",
506
+ title: e ?? r("chat.voice.failed"),
507
+ actions: [{
508
+ label: r("chat.voice.retry"),
509
+ primary: !0,
510
+ onClick: t
511
+ }]
512
+ }),
513
+ text: (e) => {
514
+ F.current = !0, u((t) => t.trim() ? t.trimEnd() + " " + e : e), R.current?.focus();
515
+ }
516
+ });
517
+ }
518
+ let se = (e) => {
519
+ e.key === "Escape" && B.recording && (e.preventDefault(), B.cancel());
520
+ }, ce = S ? r("chat.skillPlaceholder") : r("chat.placeholder", { name: n.agentName }), le = z - B.seconds;
233
521
  return /* @__PURE__ */ l("section", {
234
522
  className: "nb-chat",
235
523
  "aria-label": r("chat.title"),
@@ -237,7 +525,7 @@ function S(n) {
237
525
  n.header,
238
526
  /* @__PURE__ */ l("div", {
239
527
  className: "msgs",
240
- ref: S,
528
+ ref: I,
241
529
  "aria-live": "polite",
242
530
  children: [
243
531
  n.hasOlder && n.onLoadOlder && /* @__PURE__ */ c("button", {
@@ -251,7 +539,7 @@ function S(n) {
251
539
  className: "err-text",
252
540
  children: n.historyError
253
541
  }),
254
- T.length === 0 && !n.loading && !n.historyError && /* @__PURE__ */ l("div", {
542
+ V.length === 0 && !n.loading && !n.historyError && /* @__PURE__ */ l("div", {
255
543
  className: "empty",
256
544
  children: [
257
545
  /* @__PURE__ */ c("div", {
@@ -262,9 +550,9 @@ function S(n) {
262
550
  n.emptyHint
263
551
  ]
264
552
  }),
265
- T.map((e) => /* @__PURE__ */ c(b, {
553
+ V.map((e) => /* @__PURE__ */ c(w, {
266
554
  m: e,
267
- busy: E,
555
+ busy: H,
268
556
  onRetry: n.onRetry && (() => n.onRetry?.(e.id))
269
557
  }, e.id)),
270
558
  n.onConfirm && (n.confirmations ?? []).map((e) => /* @__PURE__ */ l("div", {
@@ -304,125 +592,175 @@ function S(n) {
304
592
  alignItems: "center"
305
593
  },
306
594
  children: n.readOnly
307
- }) : v === null ? /* @__PURE__ */ l(s, { children: [
308
- n.aboveComposer,
309
- d.length > 0 && /* @__PURE__ */ c("div", {
310
- className: "pending-files",
311
- children: d.map((e) => /* @__PURE__ */ l("span", {
312
- className: "chip",
313
- children: [
314
- /* @__PURE__ */ c(t, {
315
- name: "clip",
316
- size: 12
317
- }),
318
- e.fileName,
319
- /* @__PURE__ */ c("button", {
320
- className: "iconbtn",
321
- style: {
322
- width: 18,
323
- height: 18
324
- },
325
- "aria-label": r("remove"),
326
- onClick: () => h((t) => t.filter((t) => t.id !== e.id)),
327
- children: /* @__PURE__ */ c(t, {
328
- name: "x",
595
+ }) : /* @__PURE__ */ l("div", {
596
+ className: "composer-wrap",
597
+ children: [
598
+ X && /* @__PURE__ */ c(_, {
599
+ items: Y,
600
+ active: Math.min(T, Math.max(Y.length - 1, 0)),
601
+ onPick: re,
602
+ onHover: k
603
+ }),
604
+ n.aboveComposer,
605
+ h.length > 0 && /* @__PURE__ */ c("div", {
606
+ className: "pending-files",
607
+ children: h.map((e) => /* @__PURE__ */ l("span", {
608
+ className: "chip",
609
+ children: [
610
+ /* @__PURE__ */ c(t, {
611
+ name: "clip",
329
612
  size: 12
613
+ }),
614
+ e.fileName,
615
+ /* @__PURE__ */ c("button", {
616
+ className: "iconbtn",
617
+ style: {
618
+ width: 18,
619
+ height: 18
620
+ },
621
+ "aria-label": r("remove"),
622
+ onClick: () => v((t) => t.filter((t) => t.id !== e.id)),
623
+ children: /* @__PURE__ */ c(t, {
624
+ name: "x",
625
+ size: 12
626
+ })
330
627
  })
331
- })
332
- ]
333
- }, e.id))
334
- }),
335
- /* @__PURE__ */ l("div", {
336
- className: "composer",
337
- children: [
338
- n.onUpload && /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("button", {
339
- className: "iconbtn",
340
- "aria-label": r("chat.attach"),
341
- disabled: g,
342
- onClick: () => C.current?.click(),
343
- children: /* @__PURE__ */ c(t, { name: "clip" })
344
- }), /* @__PURE__ */ c("input", {
345
- ref: C,
346
- type: "file",
347
- multiple: !0,
348
- hidden: !0,
349
- accept: n.upload?.accept,
350
- onChange: (e) => P(e.target.files)
351
- })] }),
352
- w.recording ? /* @__PURE__ */ c("div", {
353
- className: "rec-box",
354
- children: r("chat.voice.recording", { seconds: w.seconds })
355
- }) : /* @__PURE__ */ c("textarea", {
356
- rows: 1,
357
- value: o,
358
- placeholder: L,
359
- "aria-label": L,
360
- onChange: (e) => u(e.target.value),
361
- onKeyDown: (e) => {
362
- e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing && (e.preventDefault(), N(o, !1));
363
- }
364
- }),
365
- n.onTranscribe && /* @__PURE__ */ c("button", {
366
- className: `iconbtn${w.recording ? " rec" : ""}`,
367
- disabled: !w.supported,
368
- "aria-label": w.recording ? r("chat.voice.stop") : r("chat.voice.hold"),
369
- title: w.supported ? r("chat.voice.hold") : r("chat.voice.unsupported"),
370
- onPointerDown: (e) => {
371
- e.preventDefault(), w.recording || w.start();
372
- },
373
- onPointerUp: () => w.recording && F(),
374
- onPointerLeave: () => w.recording && F(),
375
- onKeyDown: I,
376
- children: /* @__PURE__ */ c(t, { name: "mic" })
377
- }),
378
- n.onCancel && E ? /* @__PURE__ */ c("button", {
379
- className: "iconbtn fill",
380
- "aria-label": r("chat.stop"),
381
- onClick: n.onCancel,
382
- children: /* @__PURE__ */ c(t, { name: "stop" })
383
- }) : /* @__PURE__ */ c("button", {
384
- className: "iconbtn fill",
385
- "aria-label": r("chat.send"),
386
- disabled: !o.trim() && d.length === 0 || E,
387
- onClick: () => N(o, !1),
388
- children: /* @__PURE__ */ c(t, { name: "send" })
389
- })
390
- ]
391
- }),
392
- w.error && /* @__PURE__ */ c("div", {
393
- className: "err-text",
394
- style: { padding: "0 12px 8px" },
395
- children: r("chat.voice.micDenied")
396
- })
397
- ] }) : /* @__PURE__ */ l("div", {
398
- className: "transcript",
399
- style: { margin: 10 },
400
- children: [
401
- /* @__PURE__ */ c("div", {
402
- className: "small muted",
403
- style: { marginBottom: 4 },
404
- children: r("chat.voice.review")
628
+ ]
629
+ }, e.id))
405
630
  }),
406
- /* @__PURE__ */ c("textarea", {
407
- className: "inp",
408
- rows: 3,
409
- value: v,
410
- onChange: (e) => y(e.target.value),
411
- "aria-label": r("chat.voice.review")
631
+ M && /* @__PURE__ */ l("div", {
632
+ className: "cmd-unknown",
633
+ role: "status",
634
+ children: [r("chat.unknownCommand", { name: M }), /* @__PURE__ */ c("button", {
635
+ type: "button",
636
+ className: "textbtn",
637
+ onClick: () => void $(o, !0),
638
+ children: r("chat.sendAsText")
639
+ })]
412
640
  }),
413
641
  /* @__PURE__ */ l("div", {
414
- className: "row2",
415
- style: { marginTop: 8 },
416
- children: [/* @__PURE__ */ c("button", {
417
- className: "btn ghost sm",
418
- onClick: () => y(null),
419
- children: r("delete")
420
- }), /* @__PURE__ */ c("button", {
421
- className: "btn primary sm",
422
- disabled: !v.trim() || E,
423
- onClick: () => N(v, !0),
424
- children: r("chat.send")
425
- })]
642
+ className: "composer",
643
+ children: [
644
+ n.onUpload && !B.recording && /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("button", {
645
+ className: "iconbtn",
646
+ "aria-label": r("chat.attach"),
647
+ disabled: b,
648
+ onClick: () => L.current?.click(),
649
+ children: /* @__PURE__ */ c(t, { name: "clip" })
650
+ }), /* @__PURE__ */ c("input", {
651
+ ref: L,
652
+ type: "file",
653
+ multiple: !0,
654
+ hidden: !0,
655
+ accept: n.upload?.accept,
656
+ onChange: (e) => ae(e.target.files)
657
+ })] }),
658
+ B.recording ? /* @__PURE__ */ l("div", {
659
+ className: `recbar${le <= 15 ? " ending" : ""}`,
660
+ role: "status",
661
+ "aria-label": r("chat.voice.recordingNow"),
662
+ children: [
663
+ /* @__PURE__ */ c("span", {
664
+ className: "dot",
665
+ "aria-hidden": "true"
666
+ }),
667
+ /* @__PURE__ */ l("span", {
668
+ className: "tm",
669
+ children: [
670
+ O(B.seconds),
671
+ " / ",
672
+ O(z)
673
+ ]
674
+ }),
675
+ /* @__PURE__ */ c("span", {
676
+ className: "lvl",
677
+ "aria-hidden": "true",
678
+ children: /* @__PURE__ */ c("i", { style: { transform: `scaleX(${Math.max(.04, B.level)})` } })
679
+ }),
680
+ /* @__PURE__ */ c("button", {
681
+ type: "button",
682
+ className: "btn ghost sm",
683
+ onClick: B.cancel,
684
+ children: r("cancel")
685
+ }),
686
+ /* @__PURE__ */ c("button", {
687
+ type: "button",
688
+ className: "btn primary sm",
689
+ onKeyDown: se,
690
+ onClick: () => void oe(),
691
+ children: r("chat.voice.done")
692
+ })
693
+ ]
694
+ }) : /* @__PURE__ */ l("div", {
695
+ className: `field${S ? " with-skill" : ""}`,
696
+ children: [S && /* @__PURE__ */ l("span", {
697
+ className: "chip skill-chip",
698
+ children: [
699
+ /* @__PURE__ */ c(t, {
700
+ name: "spark",
701
+ size: 12
702
+ }),
703
+ S,
704
+ /* @__PURE__ */ c("button", {
705
+ className: "iconbtn",
706
+ style: {
707
+ width: 18,
708
+ height: 18
709
+ },
710
+ "aria-label": r("remove"),
711
+ onClick: () => C(null),
712
+ children: /* @__PURE__ */ c(t, {
713
+ name: "x",
714
+ size: 12
715
+ })
716
+ })
717
+ ]
718
+ }), /* @__PURE__ */ c("textarea", {
719
+ ref: R,
720
+ rows: 1,
721
+ value: o,
722
+ placeholder: P ? r("chat.voice.recognizing") : ce,
723
+ "aria-label": ce,
724
+ disabled: P,
725
+ "aria-expanded": X,
726
+ "aria-autocomplete": n.commands ? "list" : void 0,
727
+ onChange: (e) => {
728
+ u(e.target.value), j(!1), k(0), N(null);
729
+ },
730
+ onKeyDown: ie
731
+ })]
732
+ }),
733
+ n.context && !B.recording && /* @__PURE__ */ c(y, {
734
+ context: n.context,
735
+ onCompact: n.onCompact,
736
+ onReset: n.onReset
737
+ }),
738
+ n.onTranscribe && !B.recording && /* @__PURE__ */ c("button", {
739
+ className: "iconbtn",
740
+ disabled: !B.supported || P,
741
+ "aria-label": r("chat.voice.start"),
742
+ title: B.supported ? r("chat.voice.start") : r("chat.voice.unsupported"),
743
+ onClick: () => void B.start(),
744
+ children: /* @__PURE__ */ c(t, { name: "mic" })
745
+ }),
746
+ !B.recording && (n.onCancel && H ? /* @__PURE__ */ c("button", {
747
+ className: "iconbtn fill",
748
+ "aria-label": r("chat.stop"),
749
+ onClick: n.onCancel,
750
+ children: /* @__PURE__ */ c(t, { name: "stop" })
751
+ }) : /* @__PURE__ */ c("button", {
752
+ className: "iconbtn fill",
753
+ "aria-label": r("chat.send"),
754
+ disabled: !o.trim() && h.length === 0 && !S || H,
755
+ onClick: () => $(o),
756
+ children: /* @__PURE__ */ c(t, { name: "send" })
757
+ }))
758
+ ]
759
+ }),
760
+ B.error && /* @__PURE__ */ c("div", {
761
+ className: "err-text",
762
+ style: { padding: "0 12px 8px" },
763
+ children: r("chat.voice.micDenied")
426
764
  })
427
765
  ]
428
766
  })
@@ -431,7 +769,7 @@ function S(n) {
431
769
  }
432
770
  //#endregion
433
771
  //#region src/chat/ConversationList.tsx
434
- function C({ conversations: e, currentId: n, open: r, onPick: i, onClose: o, onCreate: u }) {
772
+ function A({ conversations: e, currentId: n, open: r, onPick: i, onClose: o, onCreate: u }) {
435
773
  let f = a(), [p, h] = m(!1);
436
774
  d(() => {
437
775
  if (!r) return;
@@ -507,19 +845,19 @@ function C({ conversations: e, currentId: n, open: r, onPick: i, onClose: o, onC
507
845
  "aria-label": f("close"),
508
846
  onClick: o
509
847
  }),
510
- p && u && /* @__PURE__ */ c(T, {
848
+ p && u && /* @__PURE__ */ c(M, {
511
849
  onClose: () => h(!1),
512
850
  onCreate: u
513
851
  })
514
852
  ] });
515
853
  }
516
- function w({ narrow: e, children: t }) {
854
+ function j({ narrow: e, children: t }) {
517
855
  return /* @__PURE__ */ c("div", {
518
856
  className: `nb-app${e ? " narrow" : ""}`,
519
857
  children: t
520
858
  });
521
859
  }
522
- function T({ onClose: e, onCreate: t }) {
860
+ function M({ onClose: e, onCreate: t }) {
523
861
  let r = a(), [i, o] = m(""), [u, d] = m(!1), [f, p] = m(null), h = async () => {
524
862
  if (i.trim() && !u) {
525
863
  d(!0), p(null);
@@ -571,7 +909,7 @@ function T({ onClose: e, onCreate: t }) {
571
909
  }
572
910
  //#endregion
573
911
  //#region src/chat/AgentMenu.tsx
574
- function E({ icon: e, label: n, title: r, expanded: i, small: a, disabled: o, onClick: s }) {
912
+ function N({ icon: e, label: n, title: r, expanded: i, small: a, disabled: o, onClick: s }) {
575
913
  return /* @__PURE__ */ c("button", {
576
914
  type: "button",
577
915
  className: `agentbtn${a ? " s" : ""}`,
@@ -587,35 +925,35 @@ function E({ icon: e, label: n, title: r, expanded: i, small: a, disabled: o, on
587
925
  })
588
926
  });
589
927
  }
590
- function D({ label: e, name: n, options: r, value: o, optionsLabel: s, hint: u, narrow: d, onRename: f, onPick: p, onClose: h }) {
591
- let g = a(), [_, v] = m(n), y = i(!0, h);
928
+ function P({ label: e, name: n, options: r, value: o, optionsLabel: u, hint: d, narrow: f, models: p, onRename: h, onPick: g, onClose: _ }) {
929
+ let v = a(), [y, b] = m(n), x = i(!0, _);
592
930
  return /* @__PURE__ */ l("div", {
593
- className: `agentmenu${d ? " narrow" : ""}`,
594
- ref: y,
931
+ className: `agentmenu${f ? " narrow" : ""}`,
932
+ ref: x,
595
933
  role: "dialog",
596
934
  "aria-label": e,
597
935
  children: [
598
936
  /* @__PURE__ */ c("div", {
599
937
  className: "lab",
600
- children: g("agentName")
938
+ children: v("agentName")
601
939
  }),
602
940
  /* @__PURE__ */ c("input", {
603
941
  className: "inp",
604
- value: _,
942
+ value: y,
605
943
  maxLength: 40,
606
944
  autoFocus: !0,
607
- "aria-label": g("agentName"),
608
- onChange: (e) => v(e.target.value),
945
+ "aria-label": v("agentName"),
946
+ onChange: (e) => b(e.target.value),
609
947
  onBlur: () => {
610
- let e = _.trim();
611
- e && e !== n && f(e);
948
+ let e = y.trim();
949
+ e && e !== n && h(e);
612
950
  },
613
951
  onKeyDown: (e) => e.key === "Enter" && e.target.blur()
614
952
  }),
615
953
  /* @__PURE__ */ c("div", {
616
954
  className: "lab",
617
955
  style: { marginTop: 14 },
618
- children: s
956
+ children: u
619
957
  }),
620
958
  /* @__PURE__ */ c("div", {
621
959
  className: "agentoptions",
@@ -623,7 +961,7 @@ function D({ label: e, name: n, options: r, value: o, optionsLabel: s, hint: u,
623
961
  type: "button",
624
962
  className: `agentoption${o === e.key ? " on" : ""}`,
625
963
  "aria-pressed": o === e.key,
626
- onClick: () => p(e.key),
964
+ onClick: () => g(e.key),
627
965
  children: [/* @__PURE__ */ c("span", {
628
966
  className: "ic",
629
967
  children: /* @__PURE__ */ c(t, {
@@ -633,15 +971,71 @@ function D({ label: e, name: n, options: r, value: o, optionsLabel: s, hint: u,
633
971
  }), e.label]
634
972
  }, e.key))
635
973
  }),
636
- u && /* @__PURE__ */ c("div", {
974
+ p && /* @__PURE__ */ l(s, { children: [
975
+ /* @__PURE__ */ c("div", {
976
+ className: "lab",
977
+ style: { marginTop: 14 },
978
+ children: p.label
979
+ }),
980
+ p.options.length === 0 && /* @__PURE__ */ c("div", {
981
+ className: "hint",
982
+ children: p.empty
983
+ }),
984
+ /* @__PURE__ */ c("div", {
985
+ className: "agentmodels",
986
+ role: "radiogroup",
987
+ children: p.options.map((e) => {
988
+ let n = p.options.length === 1, r = n || p.value === e.key;
989
+ return /* @__PURE__ */ l("button", {
990
+ type: "button",
991
+ role: "radio",
992
+ "aria-checked": r,
993
+ disabled: n,
994
+ className: `agentmodel${r ? " on" : ""}`,
995
+ onClick: () => !r && p.onPick(e.key),
996
+ children: [!n && /* @__PURE__ */ c("span", {
997
+ className: `radio${r ? " on" : ""}`,
998
+ "aria-hidden": "true"
999
+ }), /* @__PURE__ */ l("span", {
1000
+ className: "body",
1001
+ children: [
1002
+ /* @__PURE__ */ c("span", {
1003
+ className: "nm",
1004
+ children: e.label
1005
+ }),
1006
+ e.sub && /* @__PURE__ */ c("span", {
1007
+ className: "sub",
1008
+ children: e.sub
1009
+ }),
1010
+ e.badges && e.badges.length > 0 && /* @__PURE__ */ c("span", {
1011
+ className: "badges",
1012
+ children: e.badges.map((e) => /* @__PURE__ */ l("span", {
1013
+ className: "cap",
1014
+ children: [e.icon && /* @__PURE__ */ c(t, {
1015
+ name: e.icon,
1016
+ size: 11
1017
+ }), e.text]
1018
+ }, e.text))
1019
+ }),
1020
+ r && e.warn && /* @__PURE__ */ c("span", {
1021
+ className: "warn",
1022
+ children: e.warn
1023
+ })
1024
+ ]
1025
+ })]
1026
+ }, e.key);
1027
+ })
1028
+ })
1029
+ ] }),
1030
+ d && /* @__PURE__ */ c("div", {
637
1031
  className: "hint",
638
1032
  style: { marginTop: 10 },
639
- children: u
1033
+ children: d
640
1034
  })
641
1035
  ]
642
1036
  });
643
1037
  }
644
1038
  //#endregion
645
- export { E as AgentButton, D as AgentMenu, S as Chat, w as ChatLayout, C as ConversationList, T as NewTopicModal, x as useRecorder };
1039
+ export { N as AgentButton, P as AgentMenu, k as Chat, j as ChatLayout, _ as CommandPalette, y as ContextMeter, A as ConversationList, w as MessageView, M as NewTopicModal, v as tokens, D as useRecorder };
646
1040
 
647
1041
  //# sourceMappingURL=chat.js.map