@rubrion/agent-kit-react 0.0.0-stage → 0.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.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The full assistant screen: the same conversation as the chat box, with room,
3
+ * in the manner of a chat app. Conversations (new, search, earlier ones with any
4
+ * agent) sit on one side; the agent picker on top; the field centered on an empty
5
+ * conversation. On phones the conversation list is a drawer.
6
+ */
7
+ export declare function AssistantScreen({ className, panelSide, greeting, hint }: {
8
+ className?: string;
9
+ /** Put the conversations opposite the app's own sidebar. */
10
+ panelSide?: 'left' | 'right';
11
+ greeting?: string;
12
+ hint?: string;
13
+ }): import("react").JSX.Element;
14
+ /** The conversation's agent, on top: each conversation belongs to one agent, and switching opens a new one. */
15
+ export declare function AgentPicker(): import("react").JSX.Element | null;
16
+ /** The conversations: new, search by title, and earlier ones (with any agent). */
17
+ export declare function ConversationList({ onPick }: {
18
+ onPick?: () => void;
19
+ }): import("react").JSX.Element;
@@ -0,0 +1,81 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Check, ChevronDown, MessagesSquare, PanelRightClose, Search, SquarePen, X } from 'lucide-react';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { useAgent } from '../provider.js';
5
+ import { Availability, Composer, Suggestions, Thread } from './Conversation.js';
6
+ import { Avatar, IconButton, cn } from './ui.js';
7
+ /**
8
+ * The full assistant screen: the same conversation as the chat box, with room,
9
+ * in the manner of a chat app. Conversations (new, search, earlier ones with any
10
+ * agent) sit on one side; the agent picker on top; the field centered on an empty
11
+ * conversation. On phones the conversation list is a drawer.
12
+ */
13
+ export function AssistantScreen({ className, panelSide = 'right', greeting, hint }) {
14
+ const { turns, phase, newConversation, config, t } = useAgent();
15
+ const panelKey = `${config.storageKey}_panel`;
16
+ const [drawer, setDrawer] = useState(false);
17
+ // desktop: a column that collapses, remembered; phone: a drawer
18
+ const [panel, setPanel] = useState(() => { try {
19
+ return localStorage.getItem(panelKey) !== '0';
20
+ }
21
+ catch {
22
+ return true;
23
+ } });
24
+ const togglePanel = () => {
25
+ if (!matchMedia('(min-width: 1024px)').matches) {
26
+ setDrawer(true);
27
+ return;
28
+ }
29
+ setPanel((a) => {
30
+ try {
31
+ localStorage.setItem(panelKey, a ? '0' : '1');
32
+ }
33
+ catch { /* this tab only */ }
34
+ return !a;
35
+ });
36
+ };
37
+ const empty = !turns.length;
38
+ const firstName = (config.personName ?? '').split(' ')[0];
39
+ const aside = (_jsx("aside", { "aria-label": t.conversations, "aria-hidden": !panel, inert: !panel || undefined, className: cn('hidden shrink-0 flex-col overflow-hidden bg-muted/30 transition-[width,opacity] duration-300 lg:flex', panelSide === 'right' ? 'border-l' : 'border-r', panel ? 'w-72 opacity-100' : 'w-0 border-0 opacity-0'), children: _jsx("div", { className: "flex min-h-0 w-72 flex-1 flex-col", children: _jsx(ConversationList, {}) }) }));
40
+ return (_jsxs("div", { className: cn('flex h-full min-h-0', className), children: [_jsx("h1", { className: "sr-only", children: t.assistant }), panelSide === 'left' && aside, _jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsxs("div", { className: "flex items-center gap-2 px-3 py-2 sm:px-4", children: [_jsx(AgentPicker, {}), _jsxs("div", { className: "ml-auto flex items-center gap-1.5", children: [_jsx(IconButton, { label: t.newConversation, onClick: newConversation, children: _jsx(SquarePen, {}) }), _jsxs(IconButton, { label: panel ? t.collapse : t.conversations, onClick: togglePanel, "aria-expanded": panel, className: cn(panel && 'lg:bg-accent'), children: [panel ? _jsx(PanelRightClose, { className: "hidden lg:block" }) : null, _jsx(MessagesSquare, { className: cn(panel && 'lg:hidden') })] })] })] }), _jsx(Availability, { children: empty ? (_jsxs("div", { className: "grid flex-1 content-center justify-items-center gap-5 overflow-y-auto px-4 pb-10", children: [_jsx(Avatar, { size: 112, phase: phase, jumping: true }), _jsxs("div", { className: "ak-rise grid gap-1 text-center", children: [_jsx("p", { className: "text-2xl font-medium tracking-tight sm:text-3xl", children: greeting ?? t.greeting(firstName) }), _jsx("p", { className: "text-sm text-muted-foreground", children: hint ?? t.greetingHint })] }), _jsx(Composer, { className: "ak-rise w-full max-w-2xl [animation-delay:60ms]" }), _jsx(Suggestions, { className: "ak-rise max-w-2xl [animation-delay:120ms]" })] })) : (_jsxs(_Fragment, { children: [_jsx(Thread, { empty: null }), _jsxs("div", { className: "mx-auto w-full max-w-3xl px-4 pt-2 pb-3", children: [_jsx(Composer, {}), _jsx("p", { className: "mt-1.5 text-center text-[11px] text-muted-foreground", children: t.disclaimer })] })] })) })] }), panelSide === 'right' && aside, drawer && (_jsxs("div", { className: "fixed inset-0 z-50 lg:hidden", role: "dialog", "aria-modal": "true", "aria-label": t.conversations, "data-state": "open", onKeyDown: (e) => e.key === 'Escape' && setDrawer(false), children: [_jsx("button", { type: "button", "aria-label": t.close, className: "absolute inset-0 bg-black/40", onClick: () => setDrawer(false) }), _jsx("div", { className: cn('absolute inset-y-0 flex w-80 max-w-[85vw] flex-col bg-background shadow-xl', panelSide === 'right' ? 'right-0' : 'left-0'), children: _jsx(ConversationList, { onPick: () => setDrawer(false) }) })] }))] }));
41
+ }
42
+ /** The conversation's agent, on top: each conversation belongs to one agent, and switching opens a new one. */
43
+ export function AgentPicker() {
44
+ const { agents, agent, chooseAgent, busy, t } = useAgent();
45
+ const [open, setOpen] = useState(false);
46
+ const box = useRef(null);
47
+ useEffect(() => {
48
+ if (!open)
49
+ return;
50
+ const away = (e) => { if (!box.current?.contains(e.target))
51
+ setOpen(false); };
52
+ const esc = (e) => e.key === 'Escape' && setOpen(false);
53
+ document.addEventListener('mousedown', away);
54
+ document.addEventListener('keydown', esc);
55
+ return () => { document.removeEventListener('mousedown', away); document.removeEventListener('keydown', esc); };
56
+ }, [open]);
57
+ const current = agents.find((a) => a.id === agent);
58
+ if (!agents.length)
59
+ return null;
60
+ return (_jsxs("div", { ref: box, className: "relative", children: [_jsxs("button", { type: "button", disabled: busy || agents.length < 2, "aria-label": t.chooseAgent, "aria-expanded": open, onClick: () => setOpen((o) => !o), className: "inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-base font-medium hover:bg-accent disabled:hover:bg-transparent", children: [current?.name ?? t.assistant, " ", agents.length > 1 && _jsx(ChevronDown, { className: "size-4 text-muted-foreground" })] }), open && (_jsx("ul", { role: "menu", className: "ak-rise absolute top-full left-0 z-30 mt-1 grid w-72 gap-0.5 rounded-lg border bg-popover p-1 text-popover-foreground shadow-lg", children: agents.map((a) => (_jsx("li", { role: "none", children: _jsxs("button", { type: "button", role: "menuitem", onClick: () => { chooseAgent(a.id); setOpen(false); }, className: "flex w-full items-start gap-3 rounded-md px-2 py-2 text-left text-sm hover:bg-accent", children: [_jsx(Avatar, { size: 28 }), _jsxs("span", { className: "grid flex-1 gap-0.5", children: [_jsxs("span", { className: "flex items-center gap-1.5 font-medium", children: [a.name, a.thinking && _jsx("span", { className: "rounded-full bg-muted px-1.5 text-[10px] font-normal", children: t.thinks })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: a.tagline })] }), a.id === agent && _jsx(Check, { className: "mt-1 size-4 text-primary" })] }) }, a.id))) }))] }));
61
+ }
62
+ const relative = (iso, locale) => {
63
+ const day = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
64
+ const days = Math.round((day(new Date()) - day(new Date(iso))) / 864e5);
65
+ return days < 1
66
+ ? new Date(iso).toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit' })
67
+ : new Intl.RelativeTimeFormat(locale, { numeric: 'auto' }).format(-days, 'day');
68
+ };
69
+ /** The conversations: new, search by title, and earlier ones (with any agent). */
70
+ export function ConversationList({ onPick }) {
71
+ const { sessions, agents, thread, agent, busy, newConversation, open, remove, t } = useAgent();
72
+ const [term, setTerm] = useState('');
73
+ const q = term.trim().toLowerCase();
74
+ const nameOf = (id) => agents.find((a) => a.id === id)?.name ?? id;
75
+ const found = sessions.filter((s) => !q || s.title.toLowerCase().includes(q));
76
+ return (_jsxs("div", { className: "flex min-h-0 flex-1 flex-col gap-3 p-3", children: [_jsxs("button", { type: "button", onClick: () => { newConversation(); onPick?.(); }, className: "inline-flex h-9 items-center gap-2 rounded-md border bg-background px-3 text-sm font-medium shadow-xs hover:bg-accent [&_svg]:size-4", children: [_jsx(SquarePen, {}), " ", t.newConversation] }), _jsxs("div", { className: "relative", children: [_jsx(Search, { className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { value: term, onChange: (e) => setTerm(e.target.value), placeholder: t.searchConversations, "aria-label": t.searchConversations, className: "h-8 w-full rounded-md border bg-background pr-2 pl-8 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring/40" })] }), _jsx("p", { className: "px-1 text-[11px] font-medium tracking-wide text-muted-foreground uppercase", children: t.conversations }), !sessions.length ? (_jsx("p", { className: "px-1 text-xs text-muted-foreground", children: t.conversationsEmpty })) : !found.length ? (_jsx("p", { className: "px-1 text-xs text-muted-foreground", children: t.conversationsNoMatch })) : (_jsx("ul", { className: "-mx-1 grid min-h-0 flex-1 content-start gap-0.5 overflow-y-auto", children: found.map((s) => {
77
+ const current = s.id === thread && s.agent === agent;
78
+ return (_jsxs("li", { className: cn('group/session relative rounded-md', current ? 'bg-accent' : 'hover:bg-muted'), children: [_jsxs("button", { type: "button", disabled: busy, onClick: () => { open(s); onPick?.(); }, className: "grid w-full gap-0.5 px-2.5 py-2 pr-8 text-left", "aria-current": current || undefined, children: [_jsx("span", { className: "truncate text-sm", children: s.title }), _jsxs("span", { className: "text-[11px] text-muted-foreground", children: [nameOf(s.agent), " \u00B7 ", relative(s.updatedAt, t.locale)] })] }), _jsx(IconButton, { label: `${t.deleteConversation}: ${s.title}`, disabled: busy, onClick: () => remove(s), className: "absolute top-1/2 right-1 size-6 -translate-y-1/2 opacity-0 group-hover/session:opacity-100 hover:text-destructive focus-visible:opacity-100", children: _jsx(X, {}) })] }, `${s.agent}:${s.id}`));
79
+ }) }))] }));
80
+ }
81
+ //# sourceMappingURL=AssistantScreen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssistantScreen.js","sourceRoot":"","sources":["../../src/components/AssistantScreen.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The assistant in the corner of every screen. NOT modal: the point is reading
3
+ * the screen while asking about it. It shares the conversation of the full
4
+ * screen (AgentProvider sits above the router), so expanding carries it along,
5
+ * even with an answer on its way.
6
+ *
7
+ * Rendered in a portal on body: an ancestor with a transform would become the
8
+ * containing block of `fixed`. Hide it on the full assistant screen (`hidden`).
9
+ */
10
+ export declare function ChatBox({ onExpand, hidden, subtitle, emptyTitle, side }: {
11
+ /** Shows the expand button; typically navigates to the assistant screen. */
12
+ onExpand?: () => void;
13
+ hidden?: boolean;
14
+ subtitle?: string;
15
+ emptyTitle?: string;
16
+ side?: 'left' | 'right';
17
+ }): import("react").ReactPortal | null;
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Maximize2, MessageSquarePlus, X } from 'lucide-react';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { createPortal } from 'react-dom';
5
+ import { useAgent } from '../provider.js';
6
+ import { CompactConversation } from './Conversation.js';
7
+ import { Avatar, IconButton, cn } from './ui.js';
8
+ /**
9
+ * The assistant in the corner of every screen. NOT modal: the point is reading
10
+ * the screen while asking about it. It shares the conversation of the full
11
+ * screen (AgentProvider sits above the router), so expanding carries it along,
12
+ * even with an answer on its way.
13
+ *
14
+ * Rendered in a portal on body: an ancestor with a transform would become the
15
+ * containing block of `fixed`. Hide it on the full assistant screen (`hidden`).
16
+ */
17
+ export function ChatBox({ onExpand, hidden, subtitle, emptyTitle, side = 'right' }) {
18
+ const { t, busy, phase, newConversation, config } = useAgent();
19
+ const seenKey = `${config.storageKey}_seen`;
20
+ const [open, setOpen] = useState(false);
21
+ // The jump is an introduction: once per visit (sessionStorage), never twice in
22
+ // the same one, which makes it an invitation and not insistence.
23
+ const [seen, setSeen] = useState(() => { try {
24
+ return sessionStorage.getItem(seenKey) === '1';
25
+ }
26
+ catch {
27
+ return false;
28
+ } });
29
+ const button = useRef(null);
30
+ // Esc closes and gives focus back to the button; only bound while open
31
+ useEffect(() => {
32
+ if (!open)
33
+ return;
34
+ const onKey = (e) => {
35
+ if (e.key !== 'Escape' || e.defaultPrevented)
36
+ return;
37
+ // a popover or dialog of the screen on top handles its own Esc
38
+ if (document.querySelector('[role=dialog][data-state=open], [role=alertdialog]'))
39
+ return;
40
+ setOpen(false);
41
+ button.current?.focus();
42
+ };
43
+ document.addEventListener('keydown', onKey);
44
+ return () => document.removeEventListener('keydown', onKey);
45
+ }, [open]);
46
+ if (hidden || typeof document === 'undefined')
47
+ return null;
48
+ const jumping = !seen && phase === 'idle';
49
+ return createPortal(_jsxs("div", { className: cn('pointer-events-none fixed bottom-4 z-40 flex flex-col gap-3 print:hidden', side === 'right' ? 'right-4 items-end' : 'left-4 items-start'), children: [open && (_jsxs("section", { role: "region", "aria-label": t.assistant, className: "ak-rise pointer-events-auto flex h-[min(560px,calc(100dvh-6rem))] w-[min(400px,calc(100vw-2rem))] flex-col overflow-hidden rounded-xl border bg-card text-card-foreground shadow-2xl", children: [_jsxs("header", { className: "flex items-center gap-2 border-b px-3 py-2", children: [_jsx(Avatar, { size: 30, phase: phase }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h2", { className: "text-sm font-medium", children: t.assistant }), _jsx("p", { className: "truncate text-xs text-muted-foreground", children: subtitle ?? t.scope })] }), _jsx(IconButton, { label: t.newConversation, onClick: newConversation, children: _jsx(MessageSquarePlus, {}) }), onExpand && _jsx(IconButton, { label: t.expand, onClick: () => { setOpen(false); onExpand(); }, children: _jsx(Maximize2, {}) }), _jsx(IconButton, { label: t.close, onClick: () => setOpen(false), children: _jsx(X, {}) })] }), _jsx(CompactConversation, { emptyTitle: emptyTitle })] })), _jsx("button", { ref: button, type: "button", "aria-expanded": open, title: open ? t.close : t.open, "aria-label": open ? t.close : t.open, onClick: () => {
50
+ setSeen(true);
51
+ try {
52
+ sessionStorage.setItem(seenKey, '1');
53
+ }
54
+ catch { /* jumps again next load */ }
55
+ setOpen((o) => !o);
56
+ },
57
+ // the whole button jumps, not just the drawing: a still circle around a jumping face looks loose
58
+ className: cn('pointer-events-auto grid size-14 place-items-center rounded-full border bg-card text-foreground shadow-lg transition-transform hover:-translate-y-0.5', jumping && 'ak-jump', busy && !open && 'ring-2 ring-primary/50'), children: open ? _jsx(X, { className: "size-5" }) : _jsx(Avatar, { size: 40, phase: phase }) })] }), document.body);
59
+ }
60
+ //# sourceMappingURL=ChatBox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatBox.js","sourceRoot":"","sources":["../../src/components/ChatBox.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type ReactNode } from 'react';
2
+ /** Instead of the conversation: loading, offline, or blocked by the preflight (missing key, budget…). */
3
+ export declare function Availability({ children }: {
4
+ children: ReactNode;
5
+ }): import("react").JSX.Element;
6
+ /**
7
+ * The conversation thread. Follows the answer only while the person is at the
8
+ * bottom; scrolled up, an arrow brings them back. Scrolling the thread does by
9
+ * itself (following, or the arrow) never counts as the person leaving the end.
10
+ */
11
+ export declare function Thread({ compact, empty }: {
12
+ compact?: boolean;
13
+ empty: ReactNode;
14
+ }): import("react").JSX.Element;
15
+ /** The question field: grows with the text; Enter sends, Shift+Enter breaks the line; while answering, the button stops. */
16
+ export declare function Composer({ compact, placeholder, className }: {
17
+ compact?: boolean;
18
+ placeholder?: string;
19
+ className?: string;
20
+ }): import("react").JSX.Element;
21
+ /** Starter questions (only on an empty conversation). */
22
+ export declare function Suggestions({ questions, className }: {
23
+ questions?: string[];
24
+ className?: string;
25
+ }): import("react").JSX.Element | null;
26
+ /** The compact conversation of the chat box: the thread, and the field below. */
27
+ export declare function CompactConversation({ emptyTitle }: {
28
+ emptyTitle?: string;
29
+ }): import("react").JSX.Element;
@@ -0,0 +1,108 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { ArrowDown, ArrowUp, Square } from 'lucide-react';
3
+ import { useEffect, useLayoutEffect, useRef, useState } from 'react';
4
+ import { useAgent } from '../provider.js';
5
+ import { Markdown, ThinkStep, ToolStep } from './Steps.js';
6
+ import { Avatar, IconButton, cn } from './ui.js';
7
+ /** Instead of the conversation: loading, offline, or blocked by the preflight (missing key, budget…). */
8
+ export function Availability({ children }) {
9
+ const { available, status, error, activate, t, config } = useAgent();
10
+ useEffect(() => { activate(); }, [activate]);
11
+ if (available === null) {
12
+ return _jsxs("div", { className: "grid gap-2 p-4", children: [_jsx("div", { className: "h-16 animate-pulse rounded-md bg-muted" }), _jsx("div", { className: "h-10 w-2/3 animate-pulse rounded-md bg-muted" })] });
13
+ }
14
+ if (status && !status.ready) {
15
+ return config.renderBlocked ? _jsx(_Fragment, { children: config.renderBlocked(status) }) : (_jsxs("div", { className: "grid justify-items-center gap-3 p-6 text-center text-sm", role: "alert", children: [_jsx(Avatar, { size: 56 }), _jsx("p", { className: "font-medium", children: t.notReady }), status.message && _jsx("p", { className: "text-muted-foreground", children: status.message })] }));
16
+ }
17
+ if (!available) {
18
+ return (_jsxs("div", { className: "grid justify-items-center gap-2 p-6 text-center text-sm", children: [_jsx(Avatar, { size: 56 }), _jsx("p", { children: t.offline }), _jsx("p", { className: "text-muted-foreground", children: error && !/offline/i.test(error) ? error : t.tryAgainSoon })] }));
19
+ }
20
+ return _jsx(_Fragment, { children: children });
21
+ }
22
+ /**
23
+ * The conversation thread. Follows the answer only while the person is at the
24
+ * bottom; scrolled up, an arrow brings them back. Scrolling the thread does by
25
+ * itself (following, or the arrow) never counts as the person leaving the end.
26
+ */
27
+ export function Thread({ compact, empty }) {
28
+ const { turns, phase, agents, t } = useAgent();
29
+ const box = useRef(null);
30
+ const end = useRef(null);
31
+ const atEnd = useRef(true);
32
+ const own = useRef(false);
33
+ const [far, setFar] = useState(false);
34
+ const onScroll = () => {
35
+ const el = box.current;
36
+ if (!el)
37
+ return;
38
+ const bottom = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
39
+ if (own.current) {
40
+ if (bottom)
41
+ own.current = false;
42
+ return;
43
+ }
44
+ atEnd.current = bottom;
45
+ setFar(!bottom);
46
+ };
47
+ const down = () => {
48
+ atEnd.current = true;
49
+ own.current = true;
50
+ setFar(false);
51
+ end.current?.scrollIntoView({ block: 'end', behavior: 'smooth' });
52
+ };
53
+ useEffect(() => {
54
+ if (!atEnd.current)
55
+ return;
56
+ own.current = true;
57
+ end.current?.scrollIntoView({ block: 'end' });
58
+ }, [turns]);
59
+ const nameOf = (id) => agents.find((a) => a.id === id)?.name ?? t.assistant;
60
+ const last = turns[turns.length - 1];
61
+ return (_jsxs("div", { className: "relative min-h-0 flex-1", children: [_jsxs("div", { ref: box, onScroll: onScroll, className: "h-full overflow-y-auto", "aria-live": "polite", children: [!turns.length ? empty : (_jsx("ol", { className: cn('mx-auto grid gap-5', compact ? 'p-3' : 'max-w-3xl px-4 py-6'), children: turns.map((turn) => _jsx(Message, { turn: turn, name: turn.role === 'assistant' ? nameOf(turn.agent) : '', phase: turn === last ? phase : 'idle', compact: compact }, turn.id)) })), _jsx("div", { ref: end })] }), far && turns.length > 0 && (_jsx(IconButton, { label: t.jumpToEnd, onClick: down, className: "absolute bottom-3 left-1/2 -translate-x-1/2 rounded-full border bg-card text-foreground shadow-md", children: _jsx(ArrowDown, {}) }))] }));
62
+ }
63
+ function Message({ turn, name, phase, compact }) {
64
+ const { t } = useAgent();
65
+ if (turn.role === 'user') {
66
+ return (_jsx("li", { className: "ak-rise max-w-[85%] justify-self-end rounded-2xl rounded-br-sm bg-primary px-3.5 py-2 text-sm whitespace-pre-line text-primary-foreground", children: turn.text }));
67
+ }
68
+ return (_jsxs("li", { className: "ak-rise flex items-start gap-2.5", children: [_jsx(Avatar, { size: compact ? 26 : 32, phase: phase, className: "mt-0.5" }), _jsxs("div", { className: "grid min-w-0 flex-1 gap-2", children: [_jsx("p", { className: "text-xs font-medium text-muted-foreground", children: name }), !turn.steps.length && !turn.done && (_jsx("span", { className: "flex gap-1 py-1", "aria-label": t.writing, children: [0, 1, 2].map((i) => _jsx("i", { className: "size-1.5 animate-pulse rounded-full bg-muted-foreground/60", style: { animationDelay: `${i * 160}ms` } }, i)) })), turn.steps.map((s, i) => (s.kind === 'think' ? _jsx(ThinkStep, { step: s }, i)
69
+ : s.kind === 'tool' ? _jsx(ToolStep, { step: s }, s.id) : _jsx(Markdown, { text: s.text }, i))), turn.error && _jsx("p", { className: "text-sm text-destructive", role: "alert", children: turn.error })] })] }));
70
+ }
71
+ /** The question field: grows with the text; Enter sends, Shift+Enter breaks the line; while answering, the button stops. */
72
+ export function Composer({ compact, placeholder, className }) {
73
+ const { busy, send, stop, available, t } = useAgent();
74
+ const [text, setText] = useState('');
75
+ const field = useRef(null);
76
+ useLayoutEffect(() => {
77
+ const el = field.current;
78
+ if (!el)
79
+ return;
80
+ el.style.height = 'auto';
81
+ if (text)
82
+ el.style.height = `${Math.min(el.scrollHeight, 200)}px`;
83
+ }, [text]);
84
+ const submit = () => {
85
+ if (!text.trim() || busy || !available)
86
+ return;
87
+ send(text);
88
+ setText('');
89
+ };
90
+ return (_jsxs("form", { onSubmit: (e) => { e.preventDefault(); submit(); }, className: cn('flex items-end gap-2 rounded-2xl border bg-card p-1.5 pl-3 shadow-sm focus-within:ring-2 focus-within:ring-ring/40', className), children: [_jsx("textarea", { ref: field, autoFocus: true, rows: 1, value: text, maxLength: 4000, "aria-label": t.placeholder, placeholder: placeholder ?? t.placeholder, className: cn('max-h-[200px] min-h-9 flex-1 resize-none bg-transparent py-2 text-sm outline-none placeholder:text-muted-foreground', compact && 'min-h-8 py-1.5'), onChange: (e) => setText(e.target.value), onKeyDown: (e) => { if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {
91
+ e.preventDefault();
92
+ submit();
93
+ } } }), busy ? (_jsx(IconButton, { label: t.stop, onClick: stop, className: "rounded-full bg-secondary text-secondary-foreground", children: _jsx(Square, { className: "fill-current" }) })) : (_jsx("button", { type: "submit", disabled: !text.trim() || !available, title: t.ask, "aria-label": t.ask, className: "inline-flex size-8 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground transition-opacity disabled:opacity-40 [&_svg]:size-4", children: _jsx(ArrowUp, {}) }))] }));
94
+ }
95
+ /** Starter questions (only on an empty conversation). */
96
+ export function Suggestions({ questions, className }) {
97
+ const { send, busy, config } = useAgent();
98
+ const list = questions ?? config.suggestions ?? [];
99
+ if (!list.length)
100
+ return null;
101
+ return (_jsx("div", { className: cn('flex flex-wrap justify-center gap-2', className), children: list.map((q) => (_jsx("button", { type: "button", disabled: busy, onClick: () => send(q), className: "rounded-full border bg-card px-3 py-1.5 text-left text-xs transition-colors hover:border-primary/40 hover:bg-accent/50", children: q }, q))) }));
102
+ }
103
+ /** The compact conversation of the chat box: the thread, and the field below. */
104
+ export function CompactConversation({ emptyTitle }) {
105
+ const { t } = useAgent();
106
+ return (_jsx(Availability, { children: _jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [_jsx(Thread, { compact: true, empty: _jsxs("div", { className: "grid justify-items-center gap-3 px-3 py-6 text-center", children: [_jsx(Avatar, { size: 64 }), _jsx("p", { className: "text-base font-medium", children: emptyTitle ?? t.emptyTitle }), _jsx(Suggestions, {})] }) }), _jsx("div", { className: "border-t bg-card p-2", children: _jsx(Composer, { compact: true }) })] }) }));
107
+ }
108
+ //# sourceMappingURL=Conversation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Conversation.js","sourceRoot":"","sources":["../../src/components/Conversation.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Phase } from '../events.js';
2
+ /**
3
+ * The default mascot: growth rings around a core, no face. Idle, the rings
4
+ * breathe; thinking, they pulse outward in turn; using a tool, the outer ring
5
+ * turns; speaking, the core beats. Colors come from the theme (currentColor and
6
+ * --primary), so it reads on light and dark. Swap it with renderMascot.
7
+ */
8
+ export declare function Mascot({ phase, size, jumping, label, className }: {
9
+ phase?: Phase;
10
+ size?: number;
11
+ /** Jumps while idle: only where it is an invitation (the corner button before the first click). */
12
+ jumping?: boolean;
13
+ /** Set when it stands alone; next to text that already says "Assistant", leave it decorative. */
14
+ label?: string;
15
+ className?: string;
16
+ }): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useId } from 'react';
3
+ /**
4
+ * The default mascot: growth rings around a core, no face. Idle, the rings
5
+ * breathe; thinking, they pulse outward in turn; using a tool, the outer ring
6
+ * turns; speaking, the core beats. Colors come from the theme (currentColor and
7
+ * --primary), so it reads on light and dark. Swap it with renderMascot.
8
+ */
9
+ export function Mascot({ phase = 'idle', size = 28, jumping, label, className }) {
10
+ const id = useId().replace(/:/g, '');
11
+ return (_jsxs("svg", { viewBox: "0 0 64 64", width: size, height: size, focusable: "false", className: ['ak-mascot', `ak-mascot--${phase}`, jumping && phase === 'idle' && 'ak-jump', className].filter(Boolean).join(' '), ...(label ? { role: 'img', 'aria-label': label } : { 'aria-hidden': true }), children: [_jsx("defs", { children: _jsxs("radialGradient", { id: `${id}-g`, cx: "45%", cy: "40%", r: "65%", children: [_jsx("stop", { offset: "0%", stopColor: "var(--card, #fff)" }), _jsx("stop", { offset: "100%", stopColor: "var(--muted, #eee)" })] }) }), _jsx("circle", { cx: "32", cy: "32", r: "29", fill: `url(#${id}-g)`, className: "ak-mascot__edge", strokeWidth: "2" }), _jsxs("g", { fill: "none", strokeLinecap: "round", children: [_jsx("circle", { className: "ak-mascot__ring ak-mascot__ring--3", cx: "31", cy: "32.5", r: "22", strokeWidth: "1.8", strokeDasharray: "112 26" }), _jsx("circle", { className: "ak-mascot__ring ak-mascot__ring--2", cx: "32.5", cy: "32", r: "15", strokeWidth: "1.8" }), _jsx("circle", { className: "ak-mascot__ring ak-mascot__ring--1", cx: "32", cy: "32.5", r: "8.5", strokeWidth: "1.8" })] }), _jsx("circle", { className: "ak-mascot__core", cx: "32.5", cy: "32.5", r: "3.4" })] }));
12
+ }
13
+ //# sourceMappingURL=Mascot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Mascot.js","sourceRoot":"","sources":["../../src/components/Mascot.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAG9B;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAQ5E;IACA,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACrC,OAAO,CACN,eAAK,OAAO,EAAC,WAAW,EAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAC,OAAO,EACpE,SAAS,EAAE,CAAC,WAAW,EAAE,cAAc,KAAK,EAAE,EAAE,OAAO,IAAI,KAAK,KAAK,MAAM,IAAI,SAAS,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAC1H,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,aAC5E,yBACC,0BAAgB,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAC,KAAK,EAAC,EAAE,EAAC,KAAK,EAAC,CAAC,EAAC,KAAK,aACvD,eAAM,MAAM,EAAC,IAAI,EAAC,SAAS,EAAC,mBAAmB,GAAG,EAClD,eAAM,MAAM,EAAC,MAAM,EAAC,SAAS,EAAC,oBAAoB,GAAG,IACrC,GACX,EACP,iBAAQ,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,IAAI,EAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAC,iBAAiB,EAAC,WAAW,EAAC,GAAG,GAAG,EACpG,aAAG,IAAI,EAAC,MAAM,EAAC,aAAa,EAAC,OAAO,aACnC,iBAAQ,SAAS,EAAC,oCAAoC,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,MAAM,EAAC,CAAC,EAAC,IAAI,EAAC,WAAW,EAAC,KAAK,EAAC,eAAe,EAAC,QAAQ,GAAG,EAC7H,iBAAQ,SAAS,EAAC,oCAAoC,EAAC,EAAE,EAAC,MAAM,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,IAAI,EAAC,WAAW,EAAC,KAAK,GAAG,EACpG,iBAAQ,SAAS,EAAC,oCAAoC,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,MAAM,EAAC,CAAC,EAAC,KAAK,EAAC,WAAW,EAAC,KAAK,GAAG,IAClG,EACJ,iBAAQ,SAAS,EAAC,iBAAiB,EAAC,EAAE,EAAC,MAAM,EAAC,EAAE,EAAC,MAAM,EAAC,CAAC,EAAC,KAAK,GAAG,IAC7D,CACN,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Step } from '../events.js';
2
+ /** The answer's markdown, sanitized (DOMPurify) before it reaches the page; each code block gets a copy button. */
3
+ export declare function Markdown({ text }: {
4
+ text: string;
5
+ }): import("react").JSX.Element;
6
+ /** The thinking agent's reasoning: open while it thinks, folded after. */
7
+ export declare function ThinkStep({ step }: {
8
+ step: Extract<Step, {
9
+ kind: 'think';
10
+ }>;
11
+ }): import("react").JSX.Element;
12
+ /** One card per tool call: spins, settles, and opens to show what was asked and what came back. */
13
+ export declare function ToolStep({ step }: {
14
+ step: Extract<Step, {
15
+ kind: 'tool';
16
+ }>;
17
+ }): import("react").JSX.Element;
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import DOMPurify from 'dompurify';
3
+ import { marked } from 'marked';
4
+ import { Check, ChevronRight, X } from 'lucide-react';
5
+ import { useLayoutEffect, useMemo, useRef } from 'react';
6
+ import { useAgent } from '../provider.js';
7
+ import { cn } from './ui.js';
8
+ /** The answer's markdown, sanitized (DOMPurify) before it reaches the page; each code block gets a copy button. */
9
+ export function Markdown({ text }) {
10
+ const { t } = useAgent();
11
+ const ref = useRef(null);
12
+ const html = useMemo(() => DOMPurify.sanitize(marked.parse(text, { async: false, gfm: true, breaks: true })), [text]);
13
+ useLayoutEffect(() => {
14
+ ref.current?.querySelectorAll('pre').forEach((pre) => {
15
+ if (pre.querySelector('.ak-copy'))
16
+ return;
17
+ const b = document.createElement('button');
18
+ b.type = 'button';
19
+ b.className = 'ak-copy';
20
+ b.textContent = t.copy;
21
+ b.onclick = () => {
22
+ navigator.clipboard?.writeText(pre.querySelector('code')?.textContent ?? '');
23
+ b.textContent = t.copied;
24
+ setTimeout(() => { b.textContent = t.copy; }, 1500);
25
+ };
26
+ pre.appendChild(b);
27
+ });
28
+ }, [html, t]);
29
+ return _jsx("div", { ref: ref, className: "ak-md", dangerouslySetInnerHTML: { __html: html } });
30
+ }
31
+ const seconds = (a, b) => Math.max(1, Math.round(((b ?? Date.now()) - a) / 1000));
32
+ /** The thinking agent's reasoning: open while it thinks, folded after. */
33
+ export function ThinkStep({ step }) {
34
+ const { t } = useAgent();
35
+ const live = step.end === undefined;
36
+ return (_jsxs("details", { className: "group/step rounded-lg border border-dashed bg-muted/40 text-sm", open: live, children: [_jsxs("summary", { className: "flex cursor-pointer list-none items-center gap-2 px-3 py-1.5 text-muted-foreground", children: [_jsx("span", { className: "flex gap-0.5", "aria-hidden": true, children: [0, 1, 2].map((i) => _jsx("i", { className: cn('size-1.5 rounded-full bg-primary/70', live && 'animate-pulse'), style: { animationDelay: `${i * 160}ms` } }, i)) }), live ? t.thinking : step.start ? t.thoughtFor(seconds(step.start, step.end)) : t.thinking.replace(/…$/, ''), _jsx(ChevronRight, { className: "ml-auto size-3.5 transition-transform group-open/step:rotate-90" })] }), _jsx("p", { className: "border-t px-3 py-2 text-[13px] whitespace-pre-line text-muted-foreground", children: step.text })] }));
37
+ }
38
+ const firstString = (args) => {
39
+ const v = args && Object.values(args).find((x) => typeof x === 'string' || typeof x === 'number');
40
+ return v === undefined ? undefined : String(v);
41
+ };
42
+ /** One card per tool call: spins, settles, and opens to show what was asked and what came back. */
43
+ export function ToolStep({ step }) {
44
+ const { t, config } = useAgent();
45
+ const [running, done] = config.toolLabels?.[step.name] ?? [step.name, step.name];
46
+ const args = step.args;
47
+ const subject = (config.toolSubject ?? ((_n, a) => firstString(a)))(step.name, args);
48
+ return (_jsxs("details", { className: "group/step rounded-lg border bg-card text-sm shadow-xs", children: [_jsxs("summary", { className: "flex cursor-pointer list-none items-center gap-2 px-3 py-1.5", children: [_jsx("span", { className: cn('grid size-5 place-items-center rounded-full text-[11px]', step.state === 'running' ? 'bg-muted' : step.state === 'done' ? 'bg-primary/10 text-primary' : 'bg-destructive/10 text-destructive'), "aria-hidden": true, children: step.state === 'running' ? _jsx("span", { className: "size-3 animate-spin rounded-full border-2 border-primary/30 border-t-primary" })
49
+ : step.state === 'done' ? _jsx(Check, { className: "size-3" }) : _jsx(X, { className: "size-3" }) }), _jsxs("span", { className: "min-w-0 flex-1 truncate", children: [step.state === 'running' ? running : done, subject !== undefined && _jsxs("em", { className: "text-muted-foreground not-italic", children: [" \u00B7 ", subject] })] }), step.end ? _jsxs("span", { className: "text-xs text-muted-foreground tabular-nums", children: [seconds(step.start, step.end), "s"] }) : null, _jsx(ChevronRight, { className: "size-3.5 text-muted-foreground transition-transform group-open/step:rotate-90" })] }), _jsxs("div", { className: "border-t px-3 py-2", children: [_jsx("p", { className: "mb-1 text-[11px] font-medium tracking-wide text-muted-foreground uppercase", children: t.details }), _jsx("pre", { className: "max-h-64 overflow-auto rounded-md bg-muted p-2 font-mono text-[11px] leading-relaxed", children: JSON.stringify({ args: step.args, result: step.result }, null, 2) })] })] }));
50
+ }
51
+ //# sourceMappingURL=Steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Steps.js","sourceRoot":"","sources":["../../src/components/Steps.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type ButtonHTMLAttributes, type ReactNode } from 'react';
2
+ import type { Phase } from '../events.js';
3
+ export declare const cn: (...c: (string | false | null | undefined)[]) => string;
4
+ /** A square icon button; the label is both the tooltip and the accessible name. */
5
+ export declare const IconButton: import("react").ForwardRefExoticComponent<ButtonHTMLAttributes<HTMLButtonElement> & {
6
+ label: string;
7
+ children: ReactNode;
8
+ size?: "sm" | "md";
9
+ } & import("react").RefAttributes<HTMLButtonElement>>;
10
+ /** The app's mascot if it gave one (renderMascot), else the kit's. */
11
+ export declare function Avatar({ phase, size, jumping, className }: {
12
+ phase?: Phase;
13
+ size?: number;
14
+ jumping?: boolean;
15
+ className?: string;
16
+ }): import("react").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // The few primitives the kit needs, styled with the shadcn/ui tokens (bg-card,
3
+ // text-muted-foreground, ring-ring…), so they match any shadcn app without
4
+ // depending on its component files.
5
+ import { forwardRef } from 'react';
6
+ import { useAgent } from '../provider.js';
7
+ import { Mascot } from './Mascot.js';
8
+ export const cn = (...c) => c.filter(Boolean).join(' ');
9
+ /** A square icon button; the label is both the tooltip and the accessible name. */
10
+ export const IconButton = forwardRef(({ label, children, className, size = 'sm', ...rest }, ref) => (_jsx("button", { ref: ref, type: "button", title: label, "aria-label": label, ...rest, className: cn('inline-flex shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4', size === 'sm' ? 'size-8' : 'size-9', className), children: children })));
11
+ IconButton.displayName = 'IconButton';
12
+ /** The app's mascot if it gave one (renderMascot), else the kit's. */
13
+ export function Avatar({ phase = 'idle', size = 28, jumping, className }) {
14
+ const { config } = useAgent();
15
+ if (config.renderMascot)
16
+ return _jsx("span", { className: cn('inline-grid shrink-0 place-items-center', className), children: config.renderMascot({ phase, size, jumping }) });
17
+ return _jsx(Mascot, { phase: phase, size: size, jumping: jumping, className: className });
18
+ }
19
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/components/ui.tsx"],"names":[],"mappings":";AAAA,+EAA+E;AAC/E,2EAA2E;AAC3E,oCAAoC;AACpC,OAAO,EAAE,UAAU,EAA6C,MAAM,OAAO,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAwC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAI/F,mFAAmF;AACnF,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAyB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAC3H,iBAAQ,GAAG,EAAE,GAAG,EAAE,IAAI,EAAC,QAAQ,EAAC,KAAK,EAAE,KAAK,gBAAc,KAAK,KAAM,IAAI,EACxE,SAAS,EAAE,EAAE,CAAC,6RAA6R,EAC1S,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,YAC/C,QAAQ,GACD,CACT,CAAC,CAAC;AACH,UAAU,CAAC,WAAW,GAAG,YAAY,CAAC;AAEtC,sEAAsE;AACtE,MAAM,UAAU,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,SAAS,EAA2E;IAChJ,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC9B,IAAI,MAAM,CAAC,YAAY;QAAE,OAAO,eAAM,SAAS,EAAE,EAAE,CAAC,yCAAyC,EAAE,SAAS,CAAC,YAAG,MAAM,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,GAAQ,CAAC;IAClK,OAAO,KAAC,MAAM,IAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAI,CAAC;AACrF,CAAC"}