@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.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"chat.js","names":["_Fragment","_Fragment","_Fragment","useToast","Icon","Modal","Markdown","useOutside","useKitT","UIKIT_NS","intlLocale","lng","markTime","language","iso","visibleSteps","open","steps","STEP","MessageView","useTranslation","setOpen","useState","m","mark","i18n","atts","a","Fragment","t","waiting","v","s","onRetry","busy","useRecorder","supported","recording","setRecording","seconds","setSeconds","error","setError","rec","useRef","chunks","timer","stopped","cleanup","useCallback","tr","start","stream","r","blob","began","stop","resolve","useEffect","Chat","toast","text","setText","pending","setPending","uploading","setUploading","transcript","setTranscript","listRef","fileRef","recorder","props","first","messages","tail","last","tailText","tailSteps","lastLayout","el","was","send","msg","body","f","voice","attach","files","x","stopAndTranscribe","voiceKey","placeholder","c","y","ConversationList","creating","setCreating","onKey","onClose","item","currentId","onPick","inGroup","conversations","g","topics","archive","onCreate","NewTopicModal","ChatLayout","narrow","title","setTitle","create","AgentButton","small","label","expanded","icon","AgentMenu","draft","setDraft","name","ref","next","onRename","optionsLabel","options","value","o","hint"],"sources":["../src/chat/MessageView.tsx","../src/chat/useRecorder.ts","../src/chat/Chat.tsx","../src/chat/ConversationList.tsx","../src/chat/AgentMenu.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Icon } from \"../components/Icon\";\nimport { Markdown } from \"../components/Markdown\";\nimport { UIKIT_NS } from \"../i18n\";\nimport type { ChatMessage, ChatStep } from \"./types\";\n\n/** The locale of Intl formatting for a language code of the products. */\nconst intlLocale = (lng: string) => (lng === \"zh\" ? \"zh-CN\" : lng);\n\n/** The time of a caption: hours and minutes in the language of the interface. */\nexport function markTime(iso: string, language: string): string {\n return new Intl.DateTimeFormat(intlLocale(language), { hour: \"2-digit\", minute: \"2-digit\" }).format(new Date(iso));\n}\n\n/** More than three steps are folded to the last two (design §6.4). */\nexport function visibleSteps(steps: ChatStep[], open: boolean): ChatStep[] {\n return open || steps.length <= 3 ? steps : steps.slice(-2);\n}\n\n/** The icon of a step and its colour class by the state of the step. */\nconst STEP = {\n done: { icon: \"check\", cls: \"ok\" },\n error: { icon: \"alert\", cls: \"er\" },\n running: { icon: \"clock\", cls: \"run\" },\n} as const;\n\n/** One message of the conversation (design §6.4). */\nexport function MessageView({ m, busy, onRetry }: { m: ChatMessage; busy: boolean; onRetry?: () => void }) {\n const { t, i18n } = useTranslation(UIKIT_NS);\n const [open, setOpen] = useState(false);\n if (m.role === \"note\") return <div className=\"sysnote\">{m.text}</div>;\n const mark = m.mark && <div className=\"chan\"><Icon name={m.mark.icon} size={12} /> {m.mark.text} · {markTime(m.createdAt, i18n.language)}</div>;\n const atts = m.attachments && m.attachments.length > 0 && (\n <div className=\"atts\">\n {m.attachments.map((a) => <a key={a.id} href={a.href}><Icon name=\"clip\" size={12} /> {a.fileName}</a>)}\n </div>\n );\n if (m.role === \"user\") {\n return (\n <div className=\"m u\">\n {mark}\n {m.content}\n {m.text && <div className=\"bub\">{m.text}</div>}\n {atts}\n {m.wait && (\n <div className={`turnstate${m.wait.state === \"queued\" ? \" q\" : \"\"}`} role=\"status\">\n {m.wait.state === \"queued\"\n ? <><Icon name=\"clock\" size={12} />{t(\"chat.wait.queued\", { count: m.wait.position })}</>\n : <><span className=\"spin\" aria-hidden=\"true\" />{t(\"chat.wait.starting\")}</>}\n </div>\n )}\n </div>\n );\n }\n const steps = m.steps ?? [];\n const waiting = (m.status === \"streaming\" || m.status === \"pending\") && !m.text && !m.content;\n return (\n <div className=\"m a\">\n {mark}\n {steps.length > 3 && (\n <button className=\"tools-fold\" onClick={() => setOpen((v) => !v)} aria-expanded={open}>\n {open ? t(\"chat.hideSteps\") : t(\"chat.moreSteps\", { count: steps.length - 2 })}\n </button>\n )}\n {visibleSteps(steps, open).map((s) => (\n <div key={s.id} className=\"tool\" title={s.title}>\n <Icon name={STEP[s.status].icon} size={14} className={STEP[s.status].cls} />\n <span className=\"tx\">{s.text}</span>\n </div>\n ))}\n {waiting && <div className=\"bub\"><span className=\"typing\" aria-label={t(\"chat.typing\")}><i /><i /><i /></span></div>}\n {m.content ?? (m.text && <div className=\"bub\"><Markdown text={m.text} /></div>)}\n {atts}\n {m.error && (\n <div className={`llmerr${m.error.transient ? \" amber\" : \"\"}`} role=\"alert\" style={{ marginTop: 6 }}>\n <span>{m.error.text}</span>\n {onRetry && (\n <div className=\"row\">\n <button className=\"btn sm\" disabled={busy} onClick={onRetry}><Icon name=\"refresh\" size={14} />{t(\"chat.retry\")}</button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\n/** Push-to-talk recording with MediaRecorder. */\nexport function useRecorder() {\n const supported = typeof window !== \"undefined\" && \"MediaRecorder\" in window && !!navigator.mediaDevices?.getUserMedia;\n const [recording, setRecording] = useState(false);\n const [seconds, setSeconds] = useState(0);\n const [error, setError] = useState(false);\n const rec = useRef<MediaRecorder | null>(null);\n const chunks = useRef<Blob[]>([]);\n const timer = useRef<number | undefined>(undefined);\n const stopped = useRef<((b: Blob | null) => void) | null>(null);\n\n const cleanup = useCallback(() => {\n window.clearInterval(timer.current);\n rec.current?.stream.getTracks().forEach((tr) => tr.stop());\n rec.current = null;\n setRecording(false);\n }, []);\n\n const start = useCallback(async () => {\n if (!supported || rec.current) return;\n setError(false);\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n const r = new MediaRecorder(stream);\n chunks.current = [];\n r.ondataavailable = (e) => e.data.size > 0 && chunks.current.push(e.data);\n r.onstop = () => {\n const blob = chunks.current.length ? new Blob(chunks.current, { type: r.mimeType || \"audio/webm\" }) : null;\n cleanup();\n stopped.current?.(blob);\n stopped.current = null;\n };\n rec.current = r;\n r.start();\n setSeconds(0);\n setRecording(true);\n const began = Date.now();\n timer.current = window.setInterval(() => setSeconds(Math.floor((Date.now() - began) / 1000)), 250);\n } catch {\n setError(true);\n cleanup();\n }\n }, [supported, cleanup]);\n\n const stop = useCallback(() => new Promise<Blob | null>((resolve) => {\n const r = rec.current;\n if (!r || r.state === \"inactive\") return resolve(null);\n stopped.current = resolve;\n r.stop();\n }), []);\n\n useEffect(() => () => cleanup(), [cleanup]);\n\n const mm = Math.floor(seconds / 60);\n const ss = String(seconds % 60).padStart(2, \"0\");\n return { supported, recording, seconds: `${mm}:${ss}`, error, start, stop };\n}\n","import { useLayoutEffect, useRef, useState, type KeyboardEvent } from \"react\";\nimport { Icon } from \"../components/Icon\";\nimport { useToast } from \"../components/ui\";\nimport { useKitT } from \"../i18n\";\nimport { MessageView } from \"./MessageView\";\nimport type { ChatProps, ChatUpload } from \"./types\";\nimport { useRecorder } from \"./useRecorder\";\n\n/** The conversation: the messages and the composer (FTR.NAB.CMN-0005 R11–R13,\n * design §6). The behaviour is the one of the chat of Nabu. A control exists\n * only when the product gave its handler: no `onCancel` — no cancel button. */\nexport function Chat(props: ChatProps) {\n const t = useKitT();\n const toast = useToast();\n const [text, setText] = useState(\"\");\n const [pending, setPending] = useState<ChatUpload[]>([]);\n const [uploading, setUploading] = useState(false);\n const [transcript, setTranscript] = useState<string | null>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const recorder = useRecorder();\n const { messages, busy = false } = props;\n\n const first = messages[0]?.id;\n const tail = messages[messages.length - 1];\n const last = tail?.id;\n const tailText = tail?.text.length;\n const tailSteps = tail?.steps?.length;\n // The ends and the height of the list at the last layout: earlier messages\n // loaded above it keep the place of the list.\n const lastLayout = useRef<{ first?: string; last?: string; height: number }>({ height: 0 });\n // The list follows new messages and the growth of the last one: the dependencies are the trigger.\n useLayoutEffect(() => {\n const el = listRef.current;\n if (!el) return;\n const was = lastLayout.current;\n // history is prepended when the start of the list changed and its end did not;\n // another conversation changes both\n const prepended = was.first !== undefined && first !== was.first && last === was.last;\n el.scrollTop = prepended ? el.scrollTop + (el.scrollHeight - was.height) : el.scrollHeight;\n lastLayout.current = { first, last, height: el.scrollHeight };\n // oxlint-disable-next-line react/exhaustive-effect-dependencies -- the length and the growth of the tail only trigger\n }, [messages.length, first, last, tailText, tailSteps]);\n\n const send = async (body: string, voice: boolean) => {\n const msg = body.trim();\n if ((!msg && pending.length === 0) || busy || props.readOnly) return;\n try {\n await props.onSend(msg, pending.map((f) => f.id), voice);\n setText(\"\");\n setPending([]);\n setTranscript(null);\n } catch {\n // the product has told the user; the text stays in the composer\n }\n };\n\n const attach = async (files: FileList | null) => {\n if (!files?.length || !props.onUpload) return;\n setUploading(true);\n for (const f of Array.from(files)) {\n if (props.upload && f.size > props.upload.maxBytes) {\n toast({ kind: \"error\", title: t(\"chat.tooLarge\"), text: f.name });\n continue;\n }\n const a = await props.onUpload(f).catch(() => null);\n if (a) setPending((x) => [...x, a]);\n }\n setUploading(false);\n if (fileRef.current) fileRef.current.value = \"\";\n };\n\n const stopAndTranscribe = async () => {\n const blob = await recorder.stop();\n if (!blob || !props.onTranscribe) return;\n const r = await props.onTranscribe(blob).catch(() => null);\n if (r === null) return;\n if (!r) toast({ kind: \"error\", title: t(\"chat.voice.notRecognized\") });\n else setTranscript(r);\n };\n // Without a pointer the same button starts and stops the recording (R18).\n const voiceKey = (e: KeyboardEvent) => {\n if (e.key !== \" \" && e.key !== \"Enter\") return;\n e.preventDefault();\n if (e.repeat) return;\n if (recorder.recording) void stopAndTranscribe();\n else void recorder.start();\n };\n\n const placeholder = t(\"chat.placeholder\", { name: props.agentName });\n return (\n <section className=\"nb-chat\" aria-label={t(\"chat.title\")}>\n {props.header}\n <div className=\"msgs\" ref={listRef} aria-live=\"polite\">\n {props.hasOlder && props.onLoadOlder && (\n <button className=\"btn ghost sm\" style={{ alignSelf: \"center\" }} disabled={props.loadingOlder} onClick={props.onLoadOlder}>\n {t(\"chat.loadOlder\")}\n </button>\n )}\n {props.historyError && <div className=\"err-text\">{props.historyError}</div>}\n {messages.length === 0 && !props.loading && !props.historyError && (\n <div className=\"empty\"><div className=\"ic\"><Icon name=\"spark\" /></div><b>{t(\"chat.emptyTitle\", { name: props.agentName })}</b>{props.emptyHint}</div>\n )}\n {messages.map((m) => <MessageView key={m.id} m={m} busy={busy} onRetry={props.onRetry && (() => props.onRetry?.(m.id))} />)}\n {props.onConfirm && (props.confirmations ?? []).map((c) => (\n <div className=\"confirm\" key={c.id} role=\"group\" aria-label={t(\"chat.confirm.title\")}>\n <div className=\"h\"><Icon name=\"alert\" size={16} />{t(\"chat.confirm.title\")}</div>\n <div>{t(\"chat.confirm.text\", { action: c.summary })}</div>\n {c.preview !== undefined && <pre>{c.preview}</pre>}\n <div className=\"acts\">\n {/* never tied to `busy`: the agent asks in the middle of its turn */}\n <button className=\"btn sm primary\" onClick={() => props.onConfirm?.(c.id, true)}>{t(\"chat.confirm.approve\")}</button>\n <button className=\"btn sm\" onClick={() => props.onConfirm?.(c.id, false)}>{t(\"chat.confirm.reject\")}</button>\n </div>\n </div>\n ))}\n </div>\n\n {props.readOnly ? (\n <div className=\"composer\" style={{ justifyContent: \"space-between\", alignItems: \"center\" }}>{props.readOnly}</div>\n ) : transcript !== null ? (\n <div className=\"transcript\" style={{ margin: 10 }}>\n <div className=\"small muted\" style={{ marginBottom: 4 }}>{t(\"chat.voice.review\")}</div>\n <textarea className=\"inp\" rows={3} value={transcript} onChange={(e) => setTranscript(e.target.value)} aria-label={t(\"chat.voice.review\")} />\n <div className=\"row2\" style={{ marginTop: 8 }}>\n <button className=\"btn ghost sm\" onClick={() => setTranscript(null)}>{t(\"delete\")}</button>\n <button className=\"btn primary sm\" disabled={!transcript.trim() || busy} onClick={() => send(transcript, true)}>{t(\"chat.send\")}</button>\n </div>\n </div>\n ) : (\n <>\n {props.aboveComposer}\n {pending.length > 0 && (\n <div className=\"pending-files\">\n {pending.map((f) => (\n <span key={f.id} className=\"chip\">\n <Icon name=\"clip\" size={12} />{f.fileName}\n <button className=\"iconbtn\" style={{ width: 18, height: 18 }} aria-label={t(\"remove\")}\n onClick={() => setPending((x) => x.filter((y) => y.id !== f.id))}><Icon name=\"x\" size={12} /></button>\n </span>\n ))}\n </div>\n )}\n <div className=\"composer\">\n {props.onUpload && (\n <>\n <button className=\"iconbtn\" aria-label={t(\"chat.attach\")} disabled={uploading} onClick={() => fileRef.current?.click()}><Icon name=\"clip\" /></button>\n <input ref={fileRef} type=\"file\" multiple hidden accept={props.upload?.accept} onChange={(e) => attach(e.target.files)} />\n </>\n )}\n {recorder.recording ? (\n <div className=\"rec-box\">{t(\"chat.voice.recording\", { seconds: recorder.seconds })}</div>\n ) : (\n <textarea rows={1} value={text} placeholder={placeholder} aria-label={placeholder} onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault();\n void send(text, false);\n }\n }} />\n )}\n {props.onTranscribe && (\n <button className={`iconbtn${recorder.recording ? \" rec\" : \"\"}`} disabled={!recorder.supported}\n aria-label={recorder.recording ? t(\"chat.voice.stop\") : t(\"chat.voice.hold\")}\n title={recorder.supported ? t(\"chat.voice.hold\") : t(\"chat.voice.unsupported\")}\n onPointerDown={(e) => { e.preventDefault(); if (!recorder.recording) void recorder.start(); }}\n onPointerUp={() => recorder.recording && stopAndTranscribe()}\n onPointerLeave={() => recorder.recording && stopAndTranscribe()}\n onKeyDown={voiceKey}>\n <Icon name=\"mic\" />\n </button>\n )}\n {props.onCancel && busy ? (\n <button className=\"iconbtn fill\" aria-label={t(\"chat.stop\")} onClick={props.onCancel}><Icon name=\"stop\" /></button>\n ) : (\n <button className=\"iconbtn fill\" aria-label={t(\"chat.send\")} disabled={(!text.trim() && pending.length === 0) || busy} onClick={() => send(text, false)}>\n <Icon name=\"send\" />\n </button>\n )}\n </div>\n {recorder.error && <div className=\"err-text\" style={{ padding: \"0 12px 8px\" }}>{t(\"chat.voice.micDenied\")}</div>}\n </>\n )}\n </section>\n );\n}\n","import { useEffect, useState, type ReactNode } from \"react\";\nimport { Icon } from \"../components/Icon\";\nimport { Modal } from \"../components/ui\";\nimport { useKitT } from \"../i18n\";\nimport type { ChatConversation, ConversationListProps } from \"./types\";\n\n/** The conversations of the user: the main one, the topics, the archive (design\n * §6.2). In a wide place the list stands left of the messages; on a phone and in\n * a narrow place it lies over them while open and closes by a pick, a tap\n * beside it or Escape. */\nexport function ConversationList({ conversations, currentId, open, onPick, onClose, onCreate }: ConversationListProps) {\n const t = useKitT();\n const [creating, setCreating] = useState(false);\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => e.key === \"Escape\" && onClose();\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, onClose]);\n\n const item = (c: ChatConversation) => (\n <button key={c.id} className={`it${c.id === currentId ? \" on\" : \"\"}${c.group === \"archive\" ? \" arch\" : \"\"}`}\n onClick={() => onPick(c.id)} aria-current={c.id === currentId}>\n <Icon name={c.icon ?? \"msg2\"} size={16} />\n <span className=\"nm\">{c.title}</span>\n {!!c.unread && <span className=\"unread\" aria-label={t(\"chat.unread\", { count: c.unread })}>{c.unread}</span>}\n <span className=\"sub\">{c.when}</span>\n </button>\n );\n const inGroup = (g: ChatConversation[\"group\"]) => conversations.filter((c) => c.group === g);\n const topics = inGroup(\"topic\");\n const archive = inGroup(\"archive\");\n return (\n <>\n <nav className={`nb-side${open ? \" open\" : \"\"}`} aria-label={t(\"chat.conversations\")}>\n {onCreate && (\n <button className=\"btn sm\" style={{ width: \"100%\", justifyContent: \"center\" }} onClick={() => setCreating(true)}>\n <Icon name=\"plus\" size={15} />{t(\"chat.newTopic\")}\n </button>\n )}\n <div className=\"h\">{t(\"chat.conversation\")}</div>\n {inGroup(\"main\").map(item)}\n <div className=\"h\">{t(\"chat.topics\")}</div>\n {topics.length === 0 && <div className=\"small muted\" style={{ padding: \"0 10px\" }}>{t(\"chat.noTopics\")}</div>}\n {topics.map(item)}\n {archive.length > 0 && <div className=\"h\">{t(\"chat.archive\")}</div>}\n {archive.map(item)}\n </nav>\n {/* over the messages: a tap beside the list closes it */}\n {open && <button type=\"button\" className=\"nb-scrim\" aria-label={t(\"close\")} onClick={onClose} />}\n {creating && onCreate && <NewTopicModal onClose={() => setCreating(false)} onCreate={onCreate} />}\n </>\n );\n}\n\n/** The place of a chat: the list of conversations, the conversation and what the\n * product puts beside them. `narrow` is for a side panel: the list lies over the\n * messages as on a phone, whatever the width of the window. */\nexport function ChatLayout({ narrow, children }: { narrow?: boolean; children: ReactNode }) {\n return <div className={`nb-app${narrow ? \" narrow\" : \"\"}`}>{children}</div>;\n}\n\n/** The dialog of a new topic: one field, Enter creates. */\nexport function NewTopicModal({ onClose, onCreate }: { onClose: () => void; onCreate: (title: string) => Promise<void> }) {\n const t = useKitT();\n const [title, setTitle] = useState(\"\");\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const create = async () => {\n if (!title.trim() || pending) return;\n setPending(true);\n setError(null);\n try {\n await onCreate(title.trim());\n onClose();\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setPending(false);\n }\n };\n return (\n <Modal title={t(\"chat.newTopic\")} onClose={onClose} footer={<>\n <button className=\"btn ghost\" onClick={onClose}>{t(\"cancel\")}</button>\n <button className=\"btn primary\" disabled={!title.trim() || pending} onClick={create}>{t(\"create\")}</button>\n </>}>\n <div className=\"field\">\n <label htmlFor=\"topic-title\">{t(\"chat.topicTitle\")}</label>\n <input id=\"topic-title\" className=\"inp\" value={title} maxLength={120} onChange={(e) => setTitle(e.target.value)}\n onKeyDown={(e) => e.key === \"Enter\" && create()} />\n <div className=\"hint\">{t(\"chat.topicHint\")}</div>\n </div>\n {error && <div className=\"err-text\">{error}</div>}\n </Modal>\n );\n}\n","import { useState, type ReactNode } from \"react\";\nimport { Icon, type IconName } from \"../components/Icon\";\nimport { useOutside } from \"../components/ui\";\nimport { useKitT } from \"../i18n\";\n\n/** One of the ways an agent can look and talk; what it means only the product knows (R7). */\nexport interface AgentOption { key: string; label: string; icon: IconName }\n\n/** The round button of the agent: its icon, and the menu behind it. */\nexport function AgentButton({ icon, label, title, expanded, small, disabled, onClick }: {\n icon: IconName; label: string; title?: string; expanded?: boolean; small?: boolean; disabled?: boolean; onClick?: () => void;\n}) {\n return (\n <button type=\"button\" className={`agentbtn${small ? \" s\" : \"\"}`} disabled={disabled} aria-label={label} aria-expanded={expanded} title={title}\n // the menu closes on an outside mousedown; keep this click a toggle\n onMouseDown={(e) => expanded && e.stopPropagation()} onClick={onClick}>\n <Icon name={icon} size={small ? 15 : 18} />\n </button>\n );\n}\n\n/** The menu of the agent (FTR.NAB.CMN-0005 R15, design §6.6): its name and a\n * choice among the options of the product, as tiles with icons. The name is\n * saved on Enter and on leaving the field; a pick is saved at once. */\nexport function AgentMenu({ label, name, options, value, optionsLabel, hint, narrow, onRename, onPick, onClose }: {\n /** The name of the dialog for a screen reader. */\n label: string;\n name: string;\n options: AgentOption[];\n value: string;\n optionsLabel: ReactNode;\n hint?: ReactNode;\n /** A narrow place — a side panel: the options go in one column. */\n narrow?: boolean;\n onRename: (name: string) => void;\n onPick: (key: string) => void;\n /** Must keep its identity between renders. */\n onClose: () => void;\n}) {\n const t = useKitT();\n const [draft, setDraft] = useState(name);\n const ref = useOutside<HTMLDivElement>(true, onClose);\n const save = () => {\n const next = draft.trim();\n if (next && next !== name) onRename(next);\n };\n return (\n <div className={`agentmenu${narrow ? \" narrow\" : \"\"}`} ref={ref} role=\"dialog\" aria-label={label}>\n <div className=\"lab\">{t(\"agentName\")}</div>\n <input className=\"inp\" value={draft} maxLength={40} autoFocus aria-label={t(\"agentName\")}\n onChange={(e) => setDraft(e.target.value)} onBlur={save}\n onKeyDown={(e) => e.key === \"Enter\" && (e.target as HTMLInputElement).blur()} />\n <div className=\"lab\" style={{ marginTop: 14 }}>{optionsLabel}</div>\n <div className=\"agentoptions\">\n {options.map((o) => (\n <button key={o.key} type=\"button\" className={`agentoption${value === o.key ? \" on\" : \"\"}`} aria-pressed={value === o.key} onClick={() => onPick(o.key)}>\n <span className=\"ic\"><Icon name={o.icon} size={15} /></span>\n {o.label}\n </button>\n ))}\n </div>\n {hint && <div className=\"hint\" style={{ marginTop: 10 }}>{hint}</div>}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"chat.js","names":["_Fragment","_Fragment","_Fragment","_Fragment","useToast","Icon","Modal","Markdown","useOutside","useKitT","UIKIT_NS","matchCommands","q","query","commands","c","CommandPalette","t","items","skills","row","i","active","e","onPick","onHover","tokens","lng","n","ContextMeter","useTranslation","open","setOpen","useState","ref","share","context","pct","level","i18n","v","onCompact","onReset","intlLocale","markTime","language","iso","visibleSteps","steps","STEP","MessageView","m","EventDivider","mark","atts","a","Fragment","waiting","s","onRetry","busy","ev","transcribe","recognize","recording","on","useRecorder","supported","setRecording","seconds","setSeconds","setLevel","error","setError","rec","useRef","chunks","timer","audio","stopped","discard","limit","onLimit","cleanup","useCallback","tr","start","stream","r","blob","analyser","Ctx","samples","began","limited","peak","maxSeconds","stop","resolve","cancel","useEffect","clock","Chat","toast","text","setText","pending","setPending","uploading","setUploading","skill","setSkill","setActive","paletteClosed","setPaletteClosed","unknown","setUnknown","recognizing","setRecognizing","voice","listRef","fileRef","fieldRef","props","recorder","stopAndTranscribe","onPendingChange","first","messages","tail","last","tailText","tailSteps","lastLayout","el","was","paletteOpen","clear","runCommand","name","rest","send","msg","body","asText","word","cmd","f","pick","keys","d","attach","files","x","reason","retry","voiceKey","placeholder","left","y","ConversationList","creating","setCreating","onKey","onClose","item","currentId","inGroup","conversations","g","topics","archive","onCreate","NewTopicModal","ChatLayout","narrow","title","setTitle","create","AgentButton","small","label","expanded","icon","AgentMenu","draft","setDraft","next","onRename","optionsLabel","options","value","o","models","single","b","hint"],"sources":["../src/chat/CommandPalette.tsx","../src/chat/ContextMeter.tsx","../src/chat/MessageView.tsx","../src/chat/transcription.ts","../src/chat/useRecorder.ts","../src/chat/Chat.tsx","../src/chat/ConversationList.tsx","../src/chat/AgentMenu.tsx"],"sourcesContent":["import { Icon } from \"../components/Icon\";\nimport { useKitT } from \"../i18n\";\nimport type { ChatCommand } from \"./types\";\n\n/** The items of the palette that match what is typed after \"/\". */\nexport function matchCommands(commands: ChatCommand[], query: string): ChatCommand[] {\n const q = query.toLowerCase();\n return commands.filter((c) => c.name.toLowerCase().includes(q) || (c.description ?? \"\").toLowerCase().includes(q));\n}\n\n/** The palette of commands and skills over the composer (FTR.NAB.CHAT-0001 R4,\n * design §3.1). The composer owns the keys: arrows move `active`, Enter and Tab\n * pick it, Esc closes. */\nexport function CommandPalette({ items, active, onPick, onHover }: {\n items: ChatCommand[];\n active: number;\n onPick: (c: ChatCommand) => void;\n onHover: (i: number) => void;\n}) {\n const t = useKitT();\n const commands = items.filter((c) => c.kind === \"command\");\n const skills = items.filter((c) => c.kind === \"skill\");\n const row = (c: ChatCommand, i: number) => (\n <button key={c.kind + c.name} type=\"button\" role=\"option\" aria-selected={i === active} className={`palette-row${i === active ? \" on\" : \"\"}`}\n // the field keeps the focus: the pick happens before the blur\n onMouseDown={(e) => { e.preventDefault(); onPick(c); }} onMouseEnter={() => onHover(i)}>\n {/* the name of a command starts with «/» itself: its column stays empty, the names line up with the skills */}\n {c.kind === \"skill\" ? <Icon name=\"spark\" size={14} /> : <span className=\"slash\" aria-hidden=\"true\" />}\n <span className=\"nm\">{c.kind === \"command\" ? \"/\" + c.name : c.name}</span>\n <span className=\"ds\">{c.description}</span>\n {c.source && <span className=\"src\">{c.source}</span>}\n </button>\n );\n return (\n <div className=\"palette\" role=\"listbox\" aria-label={t(\"chat.palette.title\")}>\n {items.length === 0 && <div className=\"palette-empty\">{t(\"chat.palette.empty\")}</div>}\n {commands.length > 0 && <div className=\"palette-h\">{t(\"chat.palette.commands\")}</div>}\n {commands.map((c) => row(c, items.indexOf(c)))}\n {items.length > 0 && <div className=\"palette-h\">{t(\"chat.palette.skills\")}</div>}\n {skills.length === 0 && items.length > 0 && <div className=\"palette-empty\">{t(\"chat.palette.noSkills\")}</div>}\n {skills.map((c) => row(c, items.indexOf(c)))}\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Icon } from \"../components/Icon\";\nimport { useOutside } from \"../components/ui\";\nimport { UIKIT_NS, useKitT } from \"../i18n\";\nimport type { ChatContext } from \"./types\";\n\n/** A number of tokens shortly: 42K, 1.2M in the language of the interface. */\nexport function tokens(n: number, lng: string): string {\n return new Intl.NumberFormat(lng === \"zh\" ? \"zh-CN\" : lng, { notation: \"compact\", maximumFractionDigits: 1 }).format(n);\n}\n\n/** The fill of the context window by a ring next to the send button\n * (FTR.NAB.CHAT-0001 R3, design §3.1): grey, amber from 70 %, red from 90 %.\n * A click shows the numbers; a full context offers to compact or to reset. */\nexport function ContextMeter({ context, onCompact, onReset }: { context: ChatContext; onCompact?: () => void; onReset?: () => void }) {\n const t = useKitT();\n const { i18n } = useTranslation(UIKIT_NS);\n const [open, setOpen] = useState(false);\n const ref = useOutside<HTMLDivElement>(open, () => setOpen(false));\n const share = context.window > 0 ? Math.min(1, context.tokens / context.window) : 0;\n const pct = Math.round(share * 100);\n const level = share >= 0.9 ? \"full\" : share >= 0.7 ? \"warn\" : \"\";\n const r = 7;\n const c = 2 * Math.PI * r;\n const lng = i18n.language;\n return (\n <div className=\"ctxmeter\" ref={ref}>\n <button type=\"button\" className={`ctxring ${level}`} aria-expanded={open} onClick={() => setOpen((v) => !v)}\n aria-label={t(\"chat.context.meter\", { used: tokens(context.tokens, lng), total: tokens(context.window, lng), pct })}\n title={t(\"chat.context.meter\", { used: tokens(context.tokens, lng), total: tokens(context.window, lng), pct })}>\n <svg viewBox=\"0 0 18 18\" aria-hidden=\"true\">\n <circle className=\"bg\" cx=\"9\" cy=\"9\" r={r} />\n <circle className=\"fg\" cx=\"9\" cy=\"9\" r={r} strokeDasharray={`${(c * share).toFixed(1)} ${c.toFixed(1)}`} transform=\"rotate(-90 9 9)\" />\n </svg>\n </button>\n {open && (\n <div className=\"ctxtip\" role=\"dialog\">\n <div>{t(\"chat.context.meter\", { used: tokens(context.tokens, lng), total: tokens(context.window, lng), pct })}</div>\n {level === \"full\" && <div className=\"small muted\" style={{ marginTop: 4 }}>{t(\"chat.context.full\")}</div>}\n {level === \"full\" && (onCompact || onReset) && (\n <div className=\"row\" style={{ marginTop: 8, gap: 6 }}>\n {onCompact && <button type=\"button\" className=\"btn sm\" onClick={() => { setOpen(false); onCompact(); }}><Icon name=\"compress\" size={14} />{t(\"chat.context.compact\")}</button>}\n {onReset && <button type=\"button\" className=\"btn sm ghost\" onClick={() => { setOpen(false); onReset(); }}><Icon name=\"undo\" size={14} />{t(\"chat.context.reset\")}</button>}\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Icon } from \"../components/Icon\";\nimport { Markdown } from \"../components/Markdown\";\nimport { UIKIT_NS } from \"../i18n\";\nimport type { ChatMessage, ChatStep } from \"./types\";\n\n/** The locale of Intl formatting for a language code of the products. */\nconst intlLocale = (lng: string) => (lng === \"zh\" ? \"zh-CN\" : lng);\n\n/** The time of a caption: hours and minutes in the language of the interface. */\nexport function markTime(iso: string, language: string): string {\n return new Intl.DateTimeFormat(intlLocale(language), { hour: \"2-digit\", minute: \"2-digit\" }).format(new Date(iso));\n}\n\n/** More than three steps are folded to the last two (design §6.4). */\nexport function visibleSteps(steps: ChatStep[], open: boolean): ChatStep[] {\n return open || steps.length <= 3 ? steps : steps.slice(-2);\n}\n\n/** The icon of a step and its colour class by the state of the step. */\nconst STEP = {\n done: { icon: \"check\", cls: \"ok\" },\n error: { icon: \"alert\", cls: \"er\" },\n running: { icon: \"clock\", cls: \"run\" },\n} as const;\n\n/** One message of the conversation (design §6.4). */\nexport function MessageView({ m, busy, onRetry }: { m: ChatMessage; busy: boolean; onRetry?: () => void }) {\n const { t, i18n } = useTranslation(UIKIT_NS);\n const [open, setOpen] = useState(false);\n if (m.role === \"note\") return <div className=\"sysnote\">{m.text}</div>;\n if (m.role === \"event\" && m.event) return <EventDivider m={m} />;\n const mark = m.mark && <div className=\"chan\"><Icon name={m.mark.icon} size={12} /> {m.mark.text} · {markTime(m.createdAt, i18n.language)}</div>;\n const atts = m.attachments && m.attachments.length > 0 && (\n <div className=\"atts\">\n {m.attachments.map((a) => <a key={a.id} href={a.href}><Icon name=\"clip\" size={12} /> {a.fileName}</a>)}\n </div>\n );\n if (m.role === \"user\") {\n return (\n <div className=\"m u\">\n {mark}\n {m.content}\n {m.text && <div className=\"bub\">{m.text}</div>}\n {atts}\n {m.wait && (\n <div className={`turnstate${m.wait.state === \"queued\" ? \" q\" : \"\"}`} role=\"status\">\n {m.wait.state === \"queued\"\n ? <><Icon name=\"clock\" size={12} />{t(\"chat.wait.queued\", { count: m.wait.position })}</>\n : <><span className=\"spin\" aria-hidden=\"true\" />{t(\"chat.wait.starting\")}</>}\n </div>\n )}\n </div>\n );\n }\n const steps = m.steps ?? [];\n const waiting = (m.status === \"streaming\" || m.status === \"pending\") && !m.text && !m.content;\n return (\n <div className=\"m a\">\n {mark}\n {steps.length > 3 && (\n <button className=\"tools-fold\" onClick={() => setOpen((v) => !v)} aria-expanded={open}>\n {open ? t(\"chat.hideSteps\") : t(\"chat.moreSteps\", { count: steps.length - 2 })}\n </button>\n )}\n {visibleSteps(steps, open).map((s) => (\n <div key={s.id} className=\"tool\" title={s.title}>\n <Icon name={STEP[s.status].icon} size={14} className={STEP[s.status].cls} />\n <span className=\"tx\">{s.text}</span>\n </div>\n ))}\n {waiting && <div className=\"bub\"><span className=\"typing\" aria-label={t(\"chat.typing\")}><i /><i /><i /></span></div>}\n {m.content ?? (m.text && <div className=\"bub\" title={m.hint}><Markdown text={m.text} /></div>)}\n {atts}\n {m.error && (\n <div className={`llmerr${m.error.transient ? \" amber\" : \"\"}`} role=\"alert\" style={{ marginTop: 6 }}>\n <span>{m.error.text}</span>\n {onRetry && (\n <div className=\"row\">\n <button className=\"btn sm\" disabled={busy} onClick={onRetry}><Icon name=\"refresh\" size={14} />{t(\"chat.retry\")}</button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n\n/** An event of the conversation: a line with a chip; the details unfold\n * (FTR.NAB.CHAT-0001 design §3.2). */\nfunction EventDivider({ m }: { m: ChatMessage }) {\n const { t, i18n } = useTranslation(UIKIT_NS);\n const [open, setOpen] = useState(false);\n const ev = m.event!;\n return (\n <div className=\"evdiv\">\n <div className=\"evline\" role=\"separator\">\n <span className=\"evchip\">\n <Icon name={ev.icon} size={12} />\n {ev.text} · {markTime(m.createdAt, i18n.language)}\n {ev.details && (\n <button type=\"button\" className=\"textbtn\" aria-expanded={open} onClick={() => setOpen((v) => !v)}>\n {t(\"chat.event.details\")} {open ? \"▴\" : \"▾\"}\n </button>\n )}\n </span>\n </div>\n {open && ev.details && <div className=\"evdetails\">{ev.details}</div>}\n </div>\n );\n}\n","/** What the composer does with the outcome of a recognition. */\nexport interface TranscriptionHandlers {\n busy(on: boolean): void;\n /** The recognized text goes into the composer. */\n text(text: string): void;\n /** Nothing was recognized. */\n empty(): void;\n /** The recognition failed: the reason and a way to try the same recording again. */\n failed(reason: string | undefined, retry: () => void): void;\n}\n\n/** Recognizes a recording (FTR.NAB.CHAT-0001 R20, design §3.1). A rejection of the\n * product is a failure the user may retry: the recording stays with the retry until\n * the toast is closed. `null` means the product has told the user itself. */\nexport async function transcribe(recording: Blob, recognize: (b: Blob) => Promise<string | null>, on: TranscriptionHandlers): Promise<void> {\n on.busy(true);\n let r: string | null;\n try {\n r = await recognize(recording);\n } catch (e) {\n on.busy(false);\n on.failed(e instanceof Error && e.message ? e.message : undefined, () => void transcribe(recording, recognize, on));\n return;\n }\n on.busy(false);\n if (r === null) return;\n if (!r) on.empty();\n else on.text(r);\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\n/** Recording with MediaRecorder (FTR.NAB.CHAT-0001 R20): started and stopped\n * by the user, stopped by itself at `maxSeconds`; the level of the voice is\n * sampled for the bar of the recording. */\nexport function useRecorder(maxSeconds = 300, onLimit?: () => void) {\n const supported = typeof window !== \"undefined\" && \"MediaRecorder\" in window && !!navigator.mediaDevices?.getUserMedia;\n const [recording, setRecording] = useState(false);\n const [seconds, setSeconds] = useState(0);\n const [level, setLevel] = useState(0);\n const [error, setError] = useState(false);\n const rec = useRef<MediaRecorder | null>(null);\n const chunks = useRef<Blob[]>([]);\n const timer = useRef<number | undefined>(undefined);\n const audio = useRef<AudioContext | null>(null);\n const stopped = useRef<((b: Blob | null) => void) | null>(null);\n const discard = useRef(false);\n const limit = useRef(onLimit);\n useEffect(() => {\n limit.current = onLimit;\n });\n\n const cleanup = useCallback(() => {\n window.clearInterval(timer.current);\n rec.current?.stream.getTracks().forEach((tr) => tr.stop());\n rec.current = null;\n void audio.current?.close().catch(() => undefined);\n audio.current = null;\n setRecording(false);\n setLevel(0);\n }, []);\n\n const start = useCallback(async () => {\n if (!supported || rec.current) return;\n setError(false);\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n const r = new MediaRecorder(stream);\n chunks.current = [];\n discard.current = false;\n r.ondataavailable = (e) => e.data.size > 0 && chunks.current.push(e.data);\n r.onstop = () => {\n const blob = !discard.current && chunks.current.length ? new Blob(chunks.current, { type: r.mimeType || \"audio/webm\" }) : null;\n cleanup();\n stopped.current?.(blob);\n stopped.current = null;\n };\n let analyser: AnalyserNode | null = null;\n try {\n const Ctx = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (Ctx) {\n audio.current = new Ctx();\n analyser = audio.current.createAnalyser();\n analyser.fftSize = 256;\n audio.current.createMediaStreamSource(stream).connect(analyser);\n }\n } catch {\n analyser = null; // the bar stays flat without Web Audio\n }\n const samples = analyser ? new Uint8Array(analyser.fftSize) : null;\n rec.current = r;\n r.start();\n setSeconds(0);\n setRecording(true);\n const began = Date.now();\n let limited = false;\n timer.current = window.setInterval(() => {\n const s = Math.floor((Date.now() - began) / 1000);\n setSeconds(s);\n if (analyser && samples) {\n analyser.getByteTimeDomainData(samples);\n let peak = 0;\n for (const v of samples) peak = Math.max(peak, Math.abs(v - 128));\n setLevel(Math.min(1, peak / 64));\n }\n if (s >= maxSeconds && !limited) {\n limited = true;\n limit.current?.();\n }\n }, 100);\n } catch {\n setError(true);\n cleanup();\n }\n }, [supported, cleanup, maxSeconds]);\n\n const stop = useCallback(() => new Promise<Blob | null>((resolve) => {\n const r = rec.current;\n if (!r || r.state === \"inactive\") return resolve(null);\n stopped.current = resolve;\n r.stop();\n }), []);\n\n /** Ends the recording and drops it. */\n const cancel = useCallback(() => {\n discard.current = true;\n void stop();\n }, [stop]);\n\n useEffect(() => () => cleanup(), [cleanup]);\n\n return { supported, recording, seconds, level, error, start, stop, cancel };\n}\n\n/** m:ss of a number of seconds. */\nexport function clock(seconds: number): string {\n return `${Math.floor(seconds / 60)}:${String(seconds % 60).padStart(2, \"0\")}`;\n}\n","import { useEffect, useLayoutEffect, useRef, useState, type KeyboardEvent } from \"react\";\nimport { Icon } from \"../components/Icon\";\nimport { useToast } from \"../components/ui\";\nimport { useKitT } from \"../i18n\";\nimport { CommandPalette, matchCommands } from \"./CommandPalette\";\nimport { ContextMeter } from \"./ContextMeter\";\nimport { MessageView } from \"./MessageView\";\nimport { transcribe } from \"./transcription\";\nimport type { ChatCommand, ChatProps, ChatUpload } from \"./types\";\nimport { clock, useRecorder } from \"./useRecorder\";\n\n/** The conversation: the messages and the composer (FTR.NAB.CMN-0005 R11–R13,\n * design §6; FTR.NAB.CHAT-0001 design §3.1). The behaviour is the one of the\n * chat of Nabu. A control exists only when the product gave its handler: no\n * `onCancel` — no cancel button, no `commands` — no palette. */\nexport function Chat(props: ChatProps) {\n const t = useKitT();\n const toast = useToast();\n const [text, setText] = useState(\"\");\n const [pending, setPending] = useState<ChatUpload[]>([]);\n const [uploading, setUploading] = useState(false);\n const [skill, setSkill] = useState<string | null>(null);\n const [active, setActive] = useState(0);\n const [paletteClosed, setPaletteClosed] = useState(false);\n const [unknown, setUnknown] = useState<string | null>(null);\n const [recognizing, setRecognizing] = useState(false);\n const voice = useRef(false);\n const listRef = useRef<HTMLDivElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const fieldRef = useRef<HTMLTextAreaElement>(null);\n const maxSeconds = props.voiceMaxSeconds ?? 300;\n const recorder = useRecorder(maxSeconds, () => void stopAndTranscribe());\n const { messages, busy = false } = props;\n const onPendingChange = props.onPendingChange;\n useEffect(() => onPendingChange?.(pending), [pending, onPendingChange]);\n\n const first = messages[0]?.id;\n const tail = messages[messages.length - 1];\n const last = tail?.id;\n const tailText = tail?.text.length;\n const tailSteps = tail?.steps?.length;\n // The ends and the height of the list at the last layout: earlier messages\n // loaded above it keep the place of the list.\n const lastLayout = useRef<{ first?: string; last?: string; height: number }>({ height: 0 });\n // The list follows new messages and the growth of the last one: the dependencies are the trigger.\n useLayoutEffect(() => {\n const el = listRef.current;\n if (!el) return;\n const was = lastLayout.current;\n // history is prepended when the start of the list changed and its end did not;\n // another conversation changes both\n const prepended = was.first !== undefined && first !== was.first && last === was.last;\n el.scrollTop = prepended ? el.scrollTop + (el.scrollHeight - was.height) : el.scrollHeight;\n lastLayout.current = { first, last, height: el.scrollHeight };\n // oxlint-disable-next-line react/exhaustive-effect-dependencies -- the length and the growth of the tail only trigger\n }, [messages.length, first, last, tailText, tailSteps]);\n\n // R4: \"/\" at the start of the field without a space opens the palette\n const query = props.commands && !skill && text.startsWith(\"/\") && !/\\s/.test(text) ? text.slice(1) : null;\n const items = query !== null ? matchCommands(props.commands ?? [], query) : [];\n const paletteOpen = query !== null && !paletteClosed;\n\n const clear = () => {\n setText(\"\");\n setPending([]);\n setSkill(null);\n setUnknown(null);\n voice.current = false;\n };\n\n const runCommand = async (name: string, rest: string) => {\n if (!props.onCommand) return;\n try {\n await props.onCommand(name, rest);\n clear();\n } catch {\n // the product has told the user; the text stays\n }\n };\n\n const send = async (body: string, asText = false) => {\n const msg = body.trim();\n if ((!msg && pending.length === 0 && !skill) || busy || props.readOnly) return;\n // R4: a command typed in full runs; an unknown one waits for «Send as text»\n if (!asText && !skill && props.commands && msg.startsWith(\"/\")) {\n const [word, ...rest] = msg.slice(1).split(/\\s+/);\n const cmd = props.commands.find((c) => c.kind === \"command\" && c.name === word);\n if (cmd) return runCommand(cmd.name, rest.join(\" \"));\n if (word && !msg.includes(\"\\n\")) {\n setUnknown(\"/\" + word);\n return;\n }\n }\n try {\n await props.onSend(msg, pending.map((f) => f.id), voice.current, skill ?? undefined);\n clear();\n } catch {\n // the product has told the user; the text stays in the composer\n }\n };\n\n const pick = (c: ChatCommand) => {\n setActive(0);\n if (c.kind === \"skill\") {\n setSkill(c.name);\n setText(\"\");\n } else if (c.takesText) {\n setText(\"/\" + c.name + \" \");\n } else {\n void runCommand(c.name, \"\");\n }\n fieldRef.current?.focus();\n };\n\n const keys = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (paletteOpen && items.length > 0) {\n if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n const d = e.key === \"ArrowDown\" ? 1 : -1;\n setActive((a) => (a + d + items.length) % items.length);\n return;\n }\n if ((e.key === \"Enter\" && !e.shiftKey) || e.key === \"Tab\") {\n e.preventDefault();\n pick(items[Math.min(active, items.length - 1)]);\n return;\n }\n }\n if (paletteOpen && e.key === \"Escape\") {\n e.preventDefault();\n setPaletteClosed(true);\n return;\n }\n if (e.key === \"Backspace\" && skill && text === \"\") {\n setSkill(null); // design §3.1: Backspace in the empty field takes the skill off\n return;\n }\n if (e.key === \"Enter\" && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault();\n void send(text);\n }\n };\n\n const attach = async (files: FileList | null) => {\n if (!files?.length || !props.onUpload) return;\n setUploading(true);\n for (const f of Array.from(files)) {\n if (props.upload && f.size > props.upload.maxBytes) {\n toast({ kind: \"error\", title: t(\"chat.tooLarge\"), text: f.name });\n continue;\n }\n const a = await props.onUpload(f).catch(() => null);\n if (a) setPending((x) => [...x, a]);\n }\n setUploading(false);\n if (fileRef.current) fileRef.current.value = \"\";\n };\n\n // R20: the recognized text goes into the field; the user checks and sends it\n async function stopAndTranscribe() {\n const blob = await recorder.stop();\n if (!blob || !props.onTranscribe) return;\n await transcribe(blob, props.onTranscribe, {\n busy: setRecognizing,\n empty: () => toast({ kind: \"error\", title: t(\"chat.voice.notRecognized\") }),\n // design §3.1: the recording stays until the toast is closed\n failed: (reason, retry) => toast({ kind: \"error\", title: reason ?? t(\"chat.voice.failed\"), actions: [{ label: t(\"chat.voice.retry\"), primary: true, onClick: retry }] }),\n text: (r) => {\n voice.current = true;\n setText((x) => (x.trim() ? x.trimEnd() + \" \" + r : r));\n fieldRef.current?.focus();\n },\n });\n }\n\n const voiceKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && recorder.recording) {\n e.preventDefault();\n recorder.cancel();\n }\n };\n\n const placeholder = skill ? t(\"chat.skillPlaceholder\") : t(\"chat.placeholder\", { name: props.agentName });\n const left = maxSeconds - recorder.seconds;\n return (\n <section className=\"nb-chat\" aria-label={t(\"chat.title\")}>\n {props.header}\n <div className=\"msgs\" ref={listRef} aria-live=\"polite\">\n {props.hasOlder && props.onLoadOlder && (\n <button className=\"btn ghost sm\" style={{ alignSelf: \"center\" }} disabled={props.loadingOlder} onClick={props.onLoadOlder}>\n {t(\"chat.loadOlder\")}\n </button>\n )}\n {props.historyError && <div className=\"err-text\">{props.historyError}</div>}\n {messages.length === 0 && !props.loading && !props.historyError && (\n <div className=\"empty\"><div className=\"ic\"><Icon name=\"spark\" /></div><b>{t(\"chat.emptyTitle\", { name: props.agentName })}</b>{props.emptyHint}</div>\n )}\n {messages.map((m) => <MessageView key={m.id} m={m} busy={busy} onRetry={props.onRetry && (() => props.onRetry?.(m.id))} />)}\n {props.onConfirm && (props.confirmations ?? []).map((c) => (\n <div className=\"confirm\" key={c.id} role=\"group\" aria-label={t(\"chat.confirm.title\")}>\n <div className=\"h\"><Icon name=\"alert\" size={16} />{t(\"chat.confirm.title\")}</div>\n <div>{t(\"chat.confirm.text\", { action: c.summary })}</div>\n {c.preview !== undefined && <pre>{c.preview}</pre>}\n <div className=\"acts\">\n {/* never tied to `busy`: the agent asks in the middle of its turn */}\n <button className=\"btn sm primary\" onClick={() => props.onConfirm?.(c.id, true)}>{t(\"chat.confirm.approve\")}</button>\n <button className=\"btn sm\" onClick={() => props.onConfirm?.(c.id, false)}>{t(\"chat.confirm.reject\")}</button>\n </div>\n </div>\n ))}\n </div>\n\n {props.readOnly ? (\n <div className=\"composer\" style={{ justifyContent: \"space-between\", alignItems: \"center\" }}>{props.readOnly}</div>\n ) : (\n <div className=\"composer-wrap\">\n {paletteOpen && <CommandPalette items={items} active={Math.min(active, Math.max(items.length - 1, 0))} onPick={pick} onHover={setActive} />}\n {props.aboveComposer}\n {pending.length > 0 && (\n <div className=\"pending-files\">\n {pending.map((f) => (\n <span key={f.id} className=\"chip\">\n <Icon name=\"clip\" size={12} />{f.fileName}\n <button className=\"iconbtn\" style={{ width: 18, height: 18 }} aria-label={t(\"remove\")}\n onClick={() => setPending((x) => x.filter((y) => y.id !== f.id))}><Icon name=\"x\" size={12} /></button>\n </span>\n ))}\n </div>\n )}\n {unknown && (\n <div className=\"cmd-unknown\" role=\"status\">\n {t(\"chat.unknownCommand\", { name: unknown })}\n <button type=\"button\" className=\"textbtn\" onClick={() => void send(text, true)}>{t(\"chat.sendAsText\")}</button>\n </div>\n )}\n <div className=\"composer\">\n {props.onUpload && !recorder.recording && (\n <>\n <button className=\"iconbtn\" aria-label={t(\"chat.attach\")} disabled={uploading} onClick={() => fileRef.current?.click()}><Icon name=\"clip\" /></button>\n <input ref={fileRef} type=\"file\" multiple hidden accept={props.upload?.accept} onChange={(e) => attach(e.target.files)} />\n </>\n )}\n {recorder.recording ? (\n <div className={`recbar${left <= 15 ? \" ending\" : \"\"}`} role=\"status\" aria-label={t(\"chat.voice.recordingNow\")}>\n <span className=\"dot\" aria-hidden=\"true\" />\n <span className=\"tm\">{clock(recorder.seconds)} / {clock(maxSeconds)}</span>\n <span className=\"lvl\" aria-hidden=\"true\"><i style={{ transform: `scaleX(${Math.max(0.04, recorder.level)})` }} /></span>\n <button type=\"button\" className=\"btn ghost sm\" onClick={recorder.cancel}>{t(\"cancel\")}</button>\n <button type=\"button\" className=\"btn primary sm\" onKeyDown={voiceKey} onClick={() => void stopAndTranscribe()}>{t(\"chat.voice.done\")}</button>\n </div>\n ) : (\n <div className={`field${skill ? \" with-skill\" : \"\"}`}>\n {skill && (\n <span className=\"chip skill-chip\">\n <Icon name=\"spark\" size={12} />{skill}\n <button className=\"iconbtn\" style={{ width: 18, height: 18 }} aria-label={t(\"remove\")} onClick={() => setSkill(null)}><Icon name=\"x\" size={12} /></button>\n </span>\n )}\n <textarea ref={fieldRef} rows={1} value={text} placeholder={recognizing ? t(\"chat.voice.recognizing\") : placeholder} aria-label={placeholder}\n disabled={recognizing} aria-expanded={paletteOpen} aria-autocomplete={props.commands ? \"list\" : undefined}\n onChange={(e) => { setText(e.target.value); setPaletteClosed(false); setActive(0); setUnknown(null); }}\n onKeyDown={keys} />\n </div>\n )}\n {props.context && !recorder.recording && <ContextMeter context={props.context} onCompact={props.onCompact} onReset={props.onReset} />}\n {props.onTranscribe && !recorder.recording && (\n <button className=\"iconbtn\" disabled={!recorder.supported || recognizing}\n aria-label={t(\"chat.voice.start\")} title={recorder.supported ? t(\"chat.voice.start\") : t(\"chat.voice.unsupported\")}\n onClick={() => void recorder.start()}>\n <Icon name=\"mic\" />\n </button>\n )}\n {!recorder.recording && (props.onCancel && busy ? (\n <button className=\"iconbtn fill\" aria-label={t(\"chat.stop\")} onClick={props.onCancel}><Icon name=\"stop\" /></button>\n ) : (\n <button className=\"iconbtn fill\" aria-label={t(\"chat.send\")} disabled={(!text.trim() && pending.length === 0 && !skill) || busy} onClick={() => send(text)}>\n <Icon name=\"send\" />\n </button>\n ))}\n </div>\n {recorder.error && <div className=\"err-text\" style={{ padding: \"0 12px 8px\" }}>{t(\"chat.voice.micDenied\")}</div>}\n </div>\n )}\n </section>\n );\n}\n","import { useEffect, useState, type ReactNode } from \"react\";\nimport { Icon } from \"../components/Icon\";\nimport { Modal } from \"../components/ui\";\nimport { useKitT } from \"../i18n\";\nimport type { ChatConversation, ConversationListProps } from \"./types\";\n\n/** The conversations of the user: the main one, the topics, the archive (design\n * §6.2). In a wide place the list stands left of the messages; on a phone and in\n * a narrow place it lies over them while open and closes by a pick, a tap\n * beside it or Escape. */\nexport function ConversationList({ conversations, currentId, open, onPick, onClose, onCreate }: ConversationListProps) {\n const t = useKitT();\n const [creating, setCreating] = useState(false);\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => e.key === \"Escape\" && onClose();\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, onClose]);\n\n const item = (c: ChatConversation) => (\n <button key={c.id} className={`it${c.id === currentId ? \" on\" : \"\"}${c.group === \"archive\" ? \" arch\" : \"\"}`}\n onClick={() => onPick(c.id)} aria-current={c.id === currentId}>\n <Icon name={c.icon ?? \"msg2\"} size={16} />\n <span className=\"nm\">{c.title}</span>\n {!!c.unread && <span className=\"unread\" aria-label={t(\"chat.unread\", { count: c.unread })}>{c.unread}</span>}\n <span className=\"sub\">{c.when}</span>\n </button>\n );\n const inGroup = (g: ChatConversation[\"group\"]) => conversations.filter((c) => c.group === g);\n const topics = inGroup(\"topic\");\n const archive = inGroup(\"archive\");\n return (\n <>\n <nav className={`nb-side${open ? \" open\" : \"\"}`} aria-label={t(\"chat.conversations\")}>\n {onCreate && (\n <button className=\"btn sm\" style={{ width: \"100%\", justifyContent: \"center\" }} onClick={() => setCreating(true)}>\n <Icon name=\"plus\" size={15} />{t(\"chat.newTopic\")}\n </button>\n )}\n <div className=\"h\">{t(\"chat.conversation\")}</div>\n {inGroup(\"main\").map(item)}\n <div className=\"h\">{t(\"chat.topics\")}</div>\n {topics.length === 0 && <div className=\"small muted\" style={{ padding: \"0 10px\" }}>{t(\"chat.noTopics\")}</div>}\n {topics.map(item)}\n {archive.length > 0 && <div className=\"h\">{t(\"chat.archive\")}</div>}\n {archive.map(item)}\n </nav>\n {/* over the messages: a tap beside the list closes it */}\n {open && <button type=\"button\" className=\"nb-scrim\" aria-label={t(\"close\")} onClick={onClose} />}\n {creating && onCreate && <NewTopicModal onClose={() => setCreating(false)} onCreate={onCreate} />}\n </>\n );\n}\n\n/** The place of a chat: the list of conversations, the conversation and what the\n * product puts beside them. `narrow` is for a side panel: the list lies over the\n * messages as on a phone, whatever the width of the window. */\nexport function ChatLayout({ narrow, children }: { narrow?: boolean; children: ReactNode }) {\n return <div className={`nb-app${narrow ? \" narrow\" : \"\"}`}>{children}</div>;\n}\n\n/** The dialog of a new topic: one field, Enter creates. */\nexport function NewTopicModal({ onClose, onCreate }: { onClose: () => void; onCreate: (title: string) => Promise<void> }) {\n const t = useKitT();\n const [title, setTitle] = useState(\"\");\n const [pending, setPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const create = async () => {\n if (!title.trim() || pending) return;\n setPending(true);\n setError(null);\n try {\n await onCreate(title.trim());\n onClose();\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setPending(false);\n }\n };\n return (\n <Modal title={t(\"chat.newTopic\")} onClose={onClose} footer={<>\n <button className=\"btn ghost\" onClick={onClose}>{t(\"cancel\")}</button>\n <button className=\"btn primary\" disabled={!title.trim() || pending} onClick={create}>{t(\"create\")}</button>\n </>}>\n <div className=\"field\">\n <label htmlFor=\"topic-title\">{t(\"chat.topicTitle\")}</label>\n <input id=\"topic-title\" className=\"inp\" value={title} maxLength={120} onChange={(e) => setTitle(e.target.value)}\n onKeyDown={(e) => e.key === \"Enter\" && create()} />\n <div className=\"hint\">{t(\"chat.topicHint\")}</div>\n </div>\n {error && <div className=\"err-text\">{error}</div>}\n </Modal>\n );\n}\n","import { useState, type ReactNode } from \"react\";\nimport { Icon, type IconName } from \"../components/Icon\";\nimport { useOutside } from \"../components/ui\";\nimport { useKitT } from \"../i18n\";\n\n/** One of the ways an agent can look and talk; what it means only the product knows (R7). */\nexport interface AgentOption { key: string; label: string; icon: IconName }\n\n/** A model the user may choose for the agent (FTR.NAB.CHAT-0001 R16, design §3.3). */\nexport interface AgentModelOption {\n key: string;\n label: string;\n /** The connection or the default model, grey under the name. */\n sub?: string;\n /** The capabilities: images, reasoning, the window. */\n badges?: { icon?: IconName; text: string }[];\n /** Under the row of the chosen model: the context will be compacted. */\n warn?: ReactNode;\n}\n\n/** The block «Model» of the menu: one model is shown without a choice; none — the text of the product. */\nexport interface AgentModels {\n label: ReactNode;\n options: AgentModelOption[];\n value: string;\n onPick: (key: string) => void;\n empty?: ReactNode;\n}\n\n/** The round button of the agent: its icon, and the menu behind it. */\nexport function AgentButton({ icon, label, title, expanded, small, disabled, onClick }: {\n icon: IconName; label: string; title?: string; expanded?: boolean; small?: boolean; disabled?: boolean; onClick?: () => void;\n}) {\n return (\n <button type=\"button\" className={`agentbtn${small ? \" s\" : \"\"}`} disabled={disabled} aria-label={label} aria-expanded={expanded} title={title}\n // the menu closes on an outside mousedown; keep this click a toggle\n onMouseDown={(e) => expanded && e.stopPropagation()} onClick={onClick}>\n <Icon name={icon} size={small ? 15 : 18} />\n </button>\n );\n}\n\n/** The menu of the agent (FTR.NAB.CMN-0005 R15, design §6.6): its name and a\n * choice among the options of the product, as tiles with icons. The name is\n * saved on Enter and on leaving the field; a pick is saved at once. */\nexport function AgentMenu({ label, name, options, value, optionsLabel, hint, narrow, models, onRename, onPick, onClose }: {\n /** The name of the dialog for a screen reader. */\n label: string;\n name: string;\n options: AgentOption[];\n value: string;\n optionsLabel: ReactNode;\n hint?: ReactNode;\n /** A narrow place — a side panel: the options go in one column. */\n narrow?: boolean;\n /** The choice of the model after the options. */\n models?: AgentModels;\n onRename: (name: string) => void;\n onPick: (key: string) => void;\n /** Must keep its identity between renders. */\n onClose: () => void;\n}) {\n const t = useKitT();\n const [draft, setDraft] = useState(name);\n const ref = useOutside<HTMLDivElement>(true, onClose);\n const save = () => {\n const next = draft.trim();\n if (next && next !== name) onRename(next);\n };\n return (\n <div className={`agentmenu${narrow ? \" narrow\" : \"\"}`} ref={ref} role=\"dialog\" aria-label={label}>\n <div className=\"lab\">{t(\"agentName\")}</div>\n <input className=\"inp\" value={draft} maxLength={40} autoFocus aria-label={t(\"agentName\")}\n onChange={(e) => setDraft(e.target.value)} onBlur={save}\n onKeyDown={(e) => e.key === \"Enter\" && (e.target as HTMLInputElement).blur()} />\n <div className=\"lab\" style={{ marginTop: 14 }}>{optionsLabel}</div>\n <div className=\"agentoptions\">\n {options.map((o) => (\n <button key={o.key} type=\"button\" className={`agentoption${value === o.key ? \" on\" : \"\"}`} aria-pressed={value === o.key} onClick={() => onPick(o.key)}>\n <span className=\"ic\"><Icon name={o.icon} size={15} /></span>\n {o.label}\n </button>\n ))}\n </div>\n {models && (\n <>\n <div className=\"lab\" style={{ marginTop: 14 }}>{models.label}</div>\n {models.options.length === 0 && <div className=\"hint\">{models.empty}</div>}\n <div className=\"agentmodels\" role=\"radiogroup\">\n {models.options.map((m) => {\n const single = models.options.length === 1;\n const on = single || models.value === m.key;\n return (\n <button key={m.key} type=\"button\" role=\"radio\" aria-checked={on} disabled={single} className={`agentmodel${on ? \" on\" : \"\"}`}\n onClick={() => !on && models.onPick(m.key)}>\n {!single && <span className={`radio${on ? \" on\" : \"\"}`} aria-hidden=\"true\" />}\n <span className=\"body\">\n <span className=\"nm\">{m.label}</span>\n {m.sub && <span className=\"sub\">{m.sub}</span>}\n {m.badges && m.badges.length > 0 && (\n <span className=\"badges\">\n {m.badges.map((b) => <span key={b.text} className=\"cap\">{b.icon && <Icon name={b.icon} size={11} />}{b.text}</span>)}\n </span>\n )}\n {on && m.warn && <span className=\"warn\">{m.warn}</span>}\n </span>\n </button>\n );\n })}\n </div>\n </>\n )}\n {hint && <div className=\"hint\" style={{ marginTop: 10 }}>{hint}</div>}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -70,6 +70,8 @@ declare const PATHS: {
70
70
  readonly download: '<path d="M12 4v12M7 11l5 5 5-5M5 20h14"/>';
71
71
  readonly pin: '<path d="M9 4h6l-1 6 4 4H6l4-4zM12 14v6"/>';
72
72
  readonly edit: '<path d="M4 20h4L19 9l-4-4L4 16zM14 6l4 4"/>';
73
+ readonly image: '<rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="9" cy="10" r="2"/><path d="m21 16-5-5-9 9"/>';
74
+ readonly compress: '<path d="M4 14h6v6M20 10h-6V4M14 10l7-7M3 21l7-7"/>';
73
75
  };
74
76
  export type IconName = keyof typeof PATHS;
75
77
  export declare function Icon({ name, size, className }: {
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as e, c as t, d as n, i as r, l as i, n as a, o, r as s, s as c, t as l, u } from "./ui-CGgZtEVm.js";
1
+ import { a as e, c as t, d as n, i as r, l as i, n as a, o, r as s, s as c, t as l, u } from "./ui-joAvYmUH.js";
2
2
  import { n as d, t as f } from "./i18n-BJ8rsBp6.js";
3
3
  import { jsx as p, jsxs as m } from "react/jsx-runtime";
4
4
  import { useCallback as h, useEffect as g, useRef as _, useState as v } from "react";
@@ -43,6 +43,12 @@ export declare const resources: {
43
43
  notRecognized: string;
44
44
  micDenied: string;
45
45
  unsupported: string;
46
+ start: string;
47
+ done: string;
48
+ recognizing: string;
49
+ recordingNow: string;
50
+ failed: string;
51
+ retry: string;
46
52
  };
47
53
  confirm: {
48
54
  title: string;
@@ -54,6 +60,25 @@ export declare const resources: {
54
60
  starting: string;
55
61
  queued: string;
56
62
  };
63
+ palette: {
64
+ title: string;
65
+ commands: string;
66
+ skills: string;
67
+ noSkills: string;
68
+ empty: string;
69
+ };
70
+ unknownCommand: string;
71
+ sendAsText: string;
72
+ skillPlaceholder: string;
73
+ context: {
74
+ meter: string;
75
+ full: string;
76
+ compact: string;
77
+ reset: string;
78
+ };
79
+ event: {
80
+ details: string;
81
+ };
57
82
  };
58
83
  };
59
84
  ru: {
@@ -98,6 +123,12 @@ export declare const resources: {
98
123
  notRecognized: string;
99
124
  micDenied: string;
100
125
  unsupported: string;
126
+ start: string;
127
+ done: string;
128
+ recognizing: string;
129
+ recordingNow: string;
130
+ failed: string;
131
+ retry: string;
101
132
  };
102
133
  confirm: {
103
134
  title: string;
@@ -109,6 +140,25 @@ export declare const resources: {
109
140
  starting: string;
110
141
  queued: string;
111
142
  };
143
+ palette: {
144
+ title: string;
145
+ commands: string;
146
+ skills: string;
147
+ noSkills: string;
148
+ empty: string;
149
+ };
150
+ unknownCommand: string;
151
+ sendAsText: string;
152
+ skillPlaceholder: string;
153
+ context: {
154
+ meter: string;
155
+ full: string;
156
+ compact: string;
157
+ reset: string;
158
+ };
159
+ event: {
160
+ details: string;
161
+ };
112
162
  };
113
163
  };
114
164
  de: {
@@ -153,6 +203,12 @@ export declare const resources: {
153
203
  notRecognized: string;
154
204
  micDenied: string;
155
205
  unsupported: string;
206
+ start: string;
207
+ done: string;
208
+ recognizing: string;
209
+ recordingNow: string;
210
+ failed: string;
211
+ retry: string;
156
212
  };
157
213
  confirm: {
158
214
  title: string;
@@ -164,6 +220,25 @@ export declare const resources: {
164
220
  starting: string;
165
221
  queued: string;
166
222
  };
223
+ palette: {
224
+ title: string;
225
+ commands: string;
226
+ skills: string;
227
+ noSkills: string;
228
+ empty: string;
229
+ };
230
+ unknownCommand: string;
231
+ sendAsText: string;
232
+ skillPlaceholder: string;
233
+ context: {
234
+ meter: string;
235
+ full: string;
236
+ compact: string;
237
+ reset: string;
238
+ };
239
+ event: {
240
+ details: string;
241
+ };
167
242
  };
168
243
  };
169
244
  es: {
@@ -208,6 +283,12 @@ export declare const resources: {
208
283
  notRecognized: string;
209
284
  micDenied: string;
210
285
  unsupported: string;
286
+ start: string;
287
+ done: string;
288
+ recognizing: string;
289
+ recordingNow: string;
290
+ failed: string;
291
+ retry: string;
211
292
  };
212
293
  confirm: {
213
294
  title: string;
@@ -219,6 +300,25 @@ export declare const resources: {
219
300
  starting: string;
220
301
  queued: string;
221
302
  };
303
+ palette: {
304
+ title: string;
305
+ commands: string;
306
+ skills: string;
307
+ noSkills: string;
308
+ empty: string;
309
+ };
310
+ unknownCommand: string;
311
+ sendAsText: string;
312
+ skillPlaceholder: string;
313
+ context: {
314
+ meter: string;
315
+ full: string;
316
+ compact: string;
317
+ reset: string;
318
+ };
319
+ event: {
320
+ details: string;
321
+ };
222
322
  };
223
323
  };
224
324
  zh: {
@@ -263,6 +363,12 @@ export declare const resources: {
263
363
  notRecognized: string;
264
364
  micDenied: string;
265
365
  unsupported: string;
366
+ start: string;
367
+ done: string;
368
+ recognizing: string;
369
+ recordingNow: string;
370
+ failed: string;
371
+ retry: string;
266
372
  };
267
373
  confirm: {
268
374
  title: string;
@@ -274,6 +380,25 @@ export declare const resources: {
274
380
  starting: string;
275
381
  queued: string;
276
382
  };
383
+ palette: {
384
+ title: string;
385
+ commands: string;
386
+ skills: string;
387
+ noSkills: string;
388
+ empty: string;
389
+ };
390
+ unknownCommand: string;
391
+ sendAsText: string;
392
+ skillPlaceholder: string;
393
+ context: {
394
+ meter: string;
395
+ full: string;
396
+ compact: string;
397
+ reset: string;
398
+ };
399
+ event: {
400
+ details: string;
401
+ };
277
402
  };
278
403
  };
279
404
  };