@green-on-grey/ui-kit 1.0.1 → 1.1.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
+ children: "/"
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,171 @@ 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
+ }
146
339
  //#endregion
147
340
  //#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);
341
+ function E(e = 300, t) {
342
+ 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);
343
+ d(() => {
344
+ x.current = t;
345
+ });
346
+ let S = u(() => {
347
+ 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);
348
+ }, []), C = u(async () => {
349
+ if (n && !h.current) {
350
+ f(!1);
154
351
  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);
352
+ let t = await navigator.mediaDevices.getUserMedia({ audio: !0 }), n = new MediaRecorder(t);
353
+ g.current = [], b.current = !1, n.ondataavailable = (e) => e.data.size > 0 && g.current.push(e.data), n.onstop = () => {
354
+ let e = !b.current && g.current.length ? new Blob(g.current, { type: n.mimeType || "audio/webm" }) : null;
355
+ S(), y.current?.(e), y.current = null;
356
+ };
357
+ let r = null;
358
+ try {
359
+ let e = window.AudioContext ?? window.webkitAudioContext;
360
+ e && (v.current = new e(), r = v.current.createAnalyser(), r.fftSize = 256, v.current.createMediaStreamSource(t).connect(r));
361
+ } catch {
362
+ r = null;
363
+ }
364
+ let a = r ? new Uint8Array(r.fftSize) : null;
365
+ h.current = n, n.start(), o(0), i(!0);
366
+ let s = Date.now(), l = !1;
367
+ _.current = window.setInterval(() => {
368
+ let t = Math.floor((Date.now() - s) / 1e3);
369
+ if (o(t), r && a) {
370
+ r.getByteTimeDomainData(a);
371
+ let e = 0;
372
+ for (let t of a) e = Math.max(e, Math.abs(t - 128));
373
+ c(Math.min(1, e / 64));
374
+ }
375
+ t >= e && !l && (l = !0, x.current?.());
376
+ }, 100);
162
377
  } catch {
163
- o(!0), h();
378
+ f(!0), S();
164
379
  }
165
380
  }
166
- }, [e, h]), _ = u(() => new Promise((e) => {
167
- let t = s.current;
381
+ }, [
382
+ n,
383
+ S,
384
+ e
385
+ ]), w = u(() => new Promise((e) => {
386
+ let t = h.current;
168
387
  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: _
388
+ y.current = e, t.stop();
389
+ }), []), T = u(() => {
390
+ b.current = !0, w();
391
+ }, [w]);
392
+ return d(() => () => S(), [S]), {
393
+ supported: n,
394
+ recording: r,
395
+ seconds: a,
396
+ level: s,
397
+ error: l,
398
+ start: C,
399
+ stop: w,
400
+ cancel: T
178
401
  };
179
402
  }
403
+ function D(e) {
404
+ return `${Math.floor(e / 60)}:${String(e % 60).padStart(2, "0")}`;
405
+ }
180
406
  //#endregion
181
407
  //#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 });
408
+ function O(n) {
409
+ let r = a(), i = e(), [o, u] = m(""), [h, v] = m([]), [b, x] = m(!1), [S, C] = m(null), [T, O] = m(0), [k, A] = m(!1), [j, M] = m(null), [N, P] = m(!1), F = p(!1), I = p(null), L = p(null), R = p(null), z = n.voiceMaxSeconds ?? 300, B = E(z, () => void ae()), { messages: V, busy: H = !1 } = n, U = n.onPendingChange;
410
+ d(() => U?.(h), [h, U]);
411
+ let W = V[0]?.id, G = V[V.length - 1], K = G?.id, ee = G?.text.length, te = G?.steps?.length, q = p({ height: 0 });
184
412
  f(() => {
185
- let e = S.current;
413
+ let e = I.current;
186
414
  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,
415
+ let t = q.current;
416
+ e.scrollTop = t.first !== void 0 && W !== t.first && K === t.last ? e.scrollTop + (e.scrollHeight - t.height) : e.scrollHeight, q.current = {
417
+ first: W,
418
+ last: K,
191
419
  height: e.scrollHeight
192
420
  };
193
421
  }, [
194
- T.length,
195
- D,
196
- k,
197
- A,
198
- j
422
+ V.length,
423
+ W,
424
+ K,
425
+ ee,
426
+ te
199
427
  ]);
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);
428
+ let J = n.commands && !S && o.startsWith("/") && !/\s/.test(o) ? o.slice(1) : null, Y = J === null ? [] : g(n.commands ?? [], J), X = J !== null && !k, Z = () => {
429
+ u(""), v([]), C(null), M(null), F.current = !1;
430
+ }, Q = async (e, t) => {
431
+ if (n.onCommand) try {
432
+ await n.onCommand(e, t), Z();
204
433
  } catch {}
205
- }, P = async (e) => {
434
+ }, $ = async (e, t = !1) => {
435
+ let r = e.trim();
436
+ if (!(!r && h.length === 0 && !S || H || n.readOnly)) {
437
+ if (!t && !S && n.commands && r.startsWith("/")) {
438
+ let [e, ...t] = r.slice(1).split(/\s+/), i = n.commands.find((t) => t.kind === "command" && t.name === e);
439
+ if (i) return Q(i.name, t.join(" "));
440
+ if (e && !r.includes("\n")) {
441
+ M("/" + e);
442
+ return;
443
+ }
444
+ }
445
+ try {
446
+ await n.onSend(r, h.map((e) => e.id), F.current, S ?? void 0), Z();
447
+ } catch {}
448
+ }
449
+ }, ne = (e) => {
450
+ O(0), e.kind === "skill" ? (C(e.name), u("")) : e.takesText ? u("/" + e.name + " ") : Q(e.name, ""), R.current?.focus();
451
+ }, re = (e) => {
452
+ if (X && Y.length > 0) {
453
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
454
+ e.preventDefault();
455
+ let t = e.key === "ArrowDown" ? 1 : -1;
456
+ O((e) => (e + t + Y.length) % Y.length);
457
+ return;
458
+ }
459
+ if (e.key === "Enter" && !e.shiftKey || e.key === "Tab") {
460
+ e.preventDefault(), ne(Y[Math.min(T, Y.length - 1)]);
461
+ return;
462
+ }
463
+ }
464
+ X && e.key === "Escape" ? (e.preventDefault(), A(!0)) : e.key === "Backspace" && S && o === "" ? C(null) : e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing && (e.preventDefault(), $(o));
465
+ }, ie = async (e) => {
206
466
  if (e?.length && n.onUpload) {
207
- _(!0);
467
+ x(!0);
208
468
  for (let t of Array.from(e)) {
209
469
  if (n.upload && t.size > n.upload.maxBytes) {
210
470
  i({
@@ -215,21 +475,24 @@ function S(n) {
215
475
  continue;
216
476
  }
217
477
  let e = await n.onUpload(t).catch(() => null);
218
- e && h((t) => [...t, e]);
478
+ e && v((t) => [...t, e]);
219
479
  }
220
- _(!1), C.current && (C.current.value = "");
480
+ x(!1), L.current && (L.current.value = "");
221
481
  }
222
- }, F = async () => {
223
- let e = await w.stop();
482
+ };
483
+ async function ae() {
484
+ let e = await B.stop();
224
485
  if (!e || !n.onTranscribe) return;
486
+ P(!0);
225
487
  let t = await n.onTranscribe(e).catch(() => null);
226
- t !== null && (t ? y(t) : i({
488
+ P(!1), t !== null && (t ? (F.current = !0, u((e) => e.trim() ? e.trimEnd() + " " + t : t), R.current?.focus()) : i({
227
489
  kind: "error",
228
490
  title: r("chat.voice.notRecognized")
229
491
  }));
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 });
492
+ }
493
+ let oe = (e) => {
494
+ e.key === "Escape" && B.recording && (e.preventDefault(), B.cancel());
495
+ }, se = S ? r("chat.skillPlaceholder") : r("chat.placeholder", { name: n.agentName }), ce = z - B.seconds;
233
496
  return /* @__PURE__ */ l("section", {
234
497
  className: "nb-chat",
235
498
  "aria-label": r("chat.title"),
@@ -237,7 +500,7 @@ function S(n) {
237
500
  n.header,
238
501
  /* @__PURE__ */ l("div", {
239
502
  className: "msgs",
240
- ref: S,
503
+ ref: I,
241
504
  "aria-live": "polite",
242
505
  children: [
243
506
  n.hasOlder && n.onLoadOlder && /* @__PURE__ */ c("button", {
@@ -251,7 +514,7 @@ function S(n) {
251
514
  className: "err-text",
252
515
  children: n.historyError
253
516
  }),
254
- T.length === 0 && !n.loading && !n.historyError && /* @__PURE__ */ l("div", {
517
+ V.length === 0 && !n.loading && !n.historyError && /* @__PURE__ */ l("div", {
255
518
  className: "empty",
256
519
  children: [
257
520
  /* @__PURE__ */ c("div", {
@@ -262,9 +525,9 @@ function S(n) {
262
525
  n.emptyHint
263
526
  ]
264
527
  }),
265
- T.map((e) => /* @__PURE__ */ c(b, {
528
+ V.map((e) => /* @__PURE__ */ c(w, {
266
529
  m: e,
267
- busy: E,
530
+ busy: H,
268
531
  onRetry: n.onRetry && (() => n.onRetry?.(e.id))
269
532
  }, e.id)),
270
533
  n.onConfirm && (n.confirmations ?? []).map((e) => /* @__PURE__ */ l("div", {
@@ -304,125 +567,175 @@ function S(n) {
304
567
  alignItems: "center"
305
568
  },
306
569
  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",
570
+ }) : /* @__PURE__ */ l("div", {
571
+ className: "composer-wrap",
572
+ children: [
573
+ X && /* @__PURE__ */ c(_, {
574
+ items: Y,
575
+ active: Math.min(T, Math.max(Y.length - 1, 0)),
576
+ onPick: ne,
577
+ onHover: O
578
+ }),
579
+ n.aboveComposer,
580
+ h.length > 0 && /* @__PURE__ */ c("div", {
581
+ className: "pending-files",
582
+ children: h.map((e) => /* @__PURE__ */ l("span", {
583
+ className: "chip",
584
+ children: [
585
+ /* @__PURE__ */ c(t, {
586
+ name: "clip",
329
587
  size: 12
588
+ }),
589
+ e.fileName,
590
+ /* @__PURE__ */ c("button", {
591
+ className: "iconbtn",
592
+ style: {
593
+ width: 18,
594
+ height: 18
595
+ },
596
+ "aria-label": r("remove"),
597
+ onClick: () => v((t) => t.filter((t) => t.id !== e.id)),
598
+ children: /* @__PURE__ */ c(t, {
599
+ name: "x",
600
+ size: 12
601
+ })
330
602
  })
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")
603
+ ]
604
+ }, e.id))
405
605
  }),
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")
606
+ j && /* @__PURE__ */ l("div", {
607
+ className: "cmd-unknown",
608
+ role: "status",
609
+ children: [r("chat.unknownCommand", { name: j }), /* @__PURE__ */ c("button", {
610
+ type: "button",
611
+ className: "textbtn",
612
+ onClick: () => void $(o, !0),
613
+ children: r("chat.sendAsText")
614
+ })]
412
615
  }),
413
616
  /* @__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
- })]
617
+ className: "composer",
618
+ children: [
619
+ n.onUpload && !B.recording && /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("button", {
620
+ className: "iconbtn",
621
+ "aria-label": r("chat.attach"),
622
+ disabled: b,
623
+ onClick: () => L.current?.click(),
624
+ children: /* @__PURE__ */ c(t, { name: "clip" })
625
+ }), /* @__PURE__ */ c("input", {
626
+ ref: L,
627
+ type: "file",
628
+ multiple: !0,
629
+ hidden: !0,
630
+ accept: n.upload?.accept,
631
+ onChange: (e) => ie(e.target.files)
632
+ })] }),
633
+ B.recording ? /* @__PURE__ */ l("div", {
634
+ className: `recbar${ce <= 15 ? " ending" : ""}`,
635
+ role: "status",
636
+ "aria-label": r("chat.voice.recordingNow"),
637
+ children: [
638
+ /* @__PURE__ */ c("span", {
639
+ className: "dot",
640
+ "aria-hidden": "true"
641
+ }),
642
+ /* @__PURE__ */ l("span", {
643
+ className: "tm",
644
+ children: [
645
+ D(B.seconds),
646
+ " / ",
647
+ D(z)
648
+ ]
649
+ }),
650
+ /* @__PURE__ */ c("span", {
651
+ className: "lvl",
652
+ "aria-hidden": "true",
653
+ children: /* @__PURE__ */ c("i", { style: { transform: `scaleX(${Math.max(.04, B.level)})` } })
654
+ }),
655
+ /* @__PURE__ */ c("button", {
656
+ type: "button",
657
+ className: "btn ghost sm",
658
+ onClick: B.cancel,
659
+ children: r("cancel")
660
+ }),
661
+ /* @__PURE__ */ c("button", {
662
+ type: "button",
663
+ className: "btn primary sm",
664
+ onKeyDown: oe,
665
+ onClick: () => void ae(),
666
+ children: r("chat.voice.done")
667
+ })
668
+ ]
669
+ }) : /* @__PURE__ */ l("div", {
670
+ className: `field${S ? " with-skill" : ""}`,
671
+ children: [S && /* @__PURE__ */ l("span", {
672
+ className: "chip skill-chip",
673
+ children: [
674
+ /* @__PURE__ */ c(t, {
675
+ name: "spark",
676
+ size: 12
677
+ }),
678
+ S,
679
+ /* @__PURE__ */ c("button", {
680
+ className: "iconbtn",
681
+ style: {
682
+ width: 18,
683
+ height: 18
684
+ },
685
+ "aria-label": r("remove"),
686
+ onClick: () => C(null),
687
+ children: /* @__PURE__ */ c(t, {
688
+ name: "x",
689
+ size: 12
690
+ })
691
+ })
692
+ ]
693
+ }), /* @__PURE__ */ c("textarea", {
694
+ ref: R,
695
+ rows: 1,
696
+ value: o,
697
+ placeholder: N ? r("chat.voice.recognizing") : se,
698
+ "aria-label": se,
699
+ disabled: N,
700
+ "aria-expanded": X,
701
+ "aria-autocomplete": n.commands ? "list" : void 0,
702
+ onChange: (e) => {
703
+ u(e.target.value), A(!1), O(0), M(null);
704
+ },
705
+ onKeyDown: re
706
+ })]
707
+ }),
708
+ n.context && !B.recording && /* @__PURE__ */ c(y, {
709
+ context: n.context,
710
+ onCompact: n.onCompact,
711
+ onReset: n.onReset
712
+ }),
713
+ n.onTranscribe && !B.recording && /* @__PURE__ */ c("button", {
714
+ className: "iconbtn",
715
+ disabled: !B.supported || N,
716
+ "aria-label": r("chat.voice.start"),
717
+ title: B.supported ? r("chat.voice.start") : r("chat.voice.unsupported"),
718
+ onClick: () => void B.start(),
719
+ children: /* @__PURE__ */ c(t, { name: "mic" })
720
+ }),
721
+ !B.recording && (n.onCancel && H ? /* @__PURE__ */ c("button", {
722
+ className: "iconbtn fill",
723
+ "aria-label": r("chat.stop"),
724
+ onClick: n.onCancel,
725
+ children: /* @__PURE__ */ c(t, { name: "stop" })
726
+ }) : /* @__PURE__ */ c("button", {
727
+ className: "iconbtn fill",
728
+ "aria-label": r("chat.send"),
729
+ disabled: !o.trim() && h.length === 0 && !S || H,
730
+ onClick: () => $(o),
731
+ children: /* @__PURE__ */ c(t, { name: "send" })
732
+ }))
733
+ ]
734
+ }),
735
+ B.error && /* @__PURE__ */ c("div", {
736
+ className: "err-text",
737
+ style: { padding: "0 12px 8px" },
738
+ children: r("chat.voice.micDenied")
426
739
  })
427
740
  ]
428
741
  })
@@ -431,7 +744,7 @@ function S(n) {
431
744
  }
432
745
  //#endregion
433
746
  //#region src/chat/ConversationList.tsx
434
- function C({ conversations: e, currentId: n, open: r, onPick: i, onClose: o, onCreate: u }) {
747
+ function k({ conversations: e, currentId: n, open: r, onPick: i, onClose: o, onCreate: u }) {
435
748
  let f = a(), [p, h] = m(!1);
436
749
  d(() => {
437
750
  if (!r) return;
@@ -507,19 +820,19 @@ function C({ conversations: e, currentId: n, open: r, onPick: i, onClose: o, onC
507
820
  "aria-label": f("close"),
508
821
  onClick: o
509
822
  }),
510
- p && u && /* @__PURE__ */ c(T, {
823
+ p && u && /* @__PURE__ */ c(j, {
511
824
  onClose: () => h(!1),
512
825
  onCreate: u
513
826
  })
514
827
  ] });
515
828
  }
516
- function w({ narrow: e, children: t }) {
829
+ function A({ narrow: e, children: t }) {
517
830
  return /* @__PURE__ */ c("div", {
518
831
  className: `nb-app${e ? " narrow" : ""}`,
519
832
  children: t
520
833
  });
521
834
  }
522
- function T({ onClose: e, onCreate: t }) {
835
+ function j({ onClose: e, onCreate: t }) {
523
836
  let r = a(), [i, o] = m(""), [u, d] = m(!1), [f, p] = m(null), h = async () => {
524
837
  if (i.trim() && !u) {
525
838
  d(!0), p(null);
@@ -571,7 +884,7 @@ function T({ onClose: e, onCreate: t }) {
571
884
  }
572
885
  //#endregion
573
886
  //#region src/chat/AgentMenu.tsx
574
- function E({ icon: e, label: n, title: r, expanded: i, small: a, disabled: o, onClick: s }) {
887
+ function M({ icon: e, label: n, title: r, expanded: i, small: a, disabled: o, onClick: s }) {
575
888
  return /* @__PURE__ */ c("button", {
576
889
  type: "button",
577
890
  className: `agentbtn${a ? " s" : ""}`,
@@ -587,35 +900,35 @@ function E({ icon: e, label: n, title: r, expanded: i, small: a, disabled: o, on
587
900
  })
588
901
  });
589
902
  }
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);
903
+ function N({ label: e, name: n, options: r, value: o, optionsLabel: u, hint: d, narrow: f, models: p, onRename: h, onPick: g, onClose: _ }) {
904
+ let v = a(), [y, b] = m(n), x = i(!0, _);
592
905
  return /* @__PURE__ */ l("div", {
593
- className: `agentmenu${d ? " narrow" : ""}`,
594
- ref: y,
906
+ className: `agentmenu${f ? " narrow" : ""}`,
907
+ ref: x,
595
908
  role: "dialog",
596
909
  "aria-label": e,
597
910
  children: [
598
911
  /* @__PURE__ */ c("div", {
599
912
  className: "lab",
600
- children: g("agentName")
913
+ children: v("agentName")
601
914
  }),
602
915
  /* @__PURE__ */ c("input", {
603
916
  className: "inp",
604
- value: _,
917
+ value: y,
605
918
  maxLength: 40,
606
919
  autoFocus: !0,
607
- "aria-label": g("agentName"),
608
- onChange: (e) => v(e.target.value),
920
+ "aria-label": v("agentName"),
921
+ onChange: (e) => b(e.target.value),
609
922
  onBlur: () => {
610
- let e = _.trim();
611
- e && e !== n && f(e);
923
+ let e = y.trim();
924
+ e && e !== n && h(e);
612
925
  },
613
926
  onKeyDown: (e) => e.key === "Enter" && e.target.blur()
614
927
  }),
615
928
  /* @__PURE__ */ c("div", {
616
929
  className: "lab",
617
930
  style: { marginTop: 14 },
618
- children: s
931
+ children: u
619
932
  }),
620
933
  /* @__PURE__ */ c("div", {
621
934
  className: "agentoptions",
@@ -623,7 +936,7 @@ function D({ label: e, name: n, options: r, value: o, optionsLabel: s, hint: u,
623
936
  type: "button",
624
937
  className: `agentoption${o === e.key ? " on" : ""}`,
625
938
  "aria-pressed": o === e.key,
626
- onClick: () => p(e.key),
939
+ onClick: () => g(e.key),
627
940
  children: [/* @__PURE__ */ c("span", {
628
941
  className: "ic",
629
942
  children: /* @__PURE__ */ c(t, {
@@ -633,15 +946,71 @@ function D({ label: e, name: n, options: r, value: o, optionsLabel: s, hint: u,
633
946
  }), e.label]
634
947
  }, e.key))
635
948
  }),
636
- u && /* @__PURE__ */ c("div", {
949
+ p && /* @__PURE__ */ l(s, { children: [
950
+ /* @__PURE__ */ c("div", {
951
+ className: "lab",
952
+ style: { marginTop: 14 },
953
+ children: p.label
954
+ }),
955
+ p.options.length === 0 && /* @__PURE__ */ c("div", {
956
+ className: "hint",
957
+ children: p.empty
958
+ }),
959
+ /* @__PURE__ */ c("div", {
960
+ className: "agentmodels",
961
+ role: "radiogroup",
962
+ children: p.options.map((e) => {
963
+ let n = p.options.length === 1, r = n || p.value === e.key;
964
+ return /* @__PURE__ */ l("button", {
965
+ type: "button",
966
+ role: "radio",
967
+ "aria-checked": r,
968
+ disabled: n,
969
+ className: `agentmodel${r ? " on" : ""}`,
970
+ onClick: () => !r && p.onPick(e.key),
971
+ children: [!n && /* @__PURE__ */ c("span", {
972
+ className: `radio${r ? " on" : ""}`,
973
+ "aria-hidden": "true"
974
+ }), /* @__PURE__ */ l("span", {
975
+ className: "body",
976
+ children: [
977
+ /* @__PURE__ */ c("span", {
978
+ className: "nm",
979
+ children: e.label
980
+ }),
981
+ e.sub && /* @__PURE__ */ c("span", {
982
+ className: "sub",
983
+ children: e.sub
984
+ }),
985
+ e.badges && e.badges.length > 0 && /* @__PURE__ */ c("span", {
986
+ className: "badges",
987
+ children: e.badges.map((e) => /* @__PURE__ */ l("span", {
988
+ className: "cap",
989
+ children: [e.icon && /* @__PURE__ */ c(t, {
990
+ name: e.icon,
991
+ size: 11
992
+ }), e.text]
993
+ }, e.text))
994
+ }),
995
+ r && e.warn && /* @__PURE__ */ c("span", {
996
+ className: "warn",
997
+ children: e.warn
998
+ })
999
+ ]
1000
+ })]
1001
+ }, e.key);
1002
+ })
1003
+ })
1004
+ ] }),
1005
+ d && /* @__PURE__ */ c("div", {
637
1006
  className: "hint",
638
1007
  style: { marginTop: 10 },
639
- children: u
1008
+ children: d
640
1009
  })
641
1010
  ]
642
1011
  });
643
1012
  }
644
1013
  //#endregion
645
- export { E as AgentButton, D as AgentMenu, S as Chat, w as ChatLayout, C as ConversationList, T as NewTopicModal, x as useRecorder };
1014
+ export { M as AgentButton, N as AgentMenu, O as Chat, A as ChatLayout, _ as CommandPalette, y as ContextMeter, k as ConversationList, w as MessageView, j as NewTopicModal, v as tokens, E as useRecorder };
646
1015
 
647
1016
  //# sourceMappingURL=chat.js.map