@adecore/agents-react 0.21.0 → 0.21.1
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/ui/intelligent-ui/UiBlockFrame.d.ts +14 -1
- package/dist/chat/ui/intelligent-ui/UiBlockFrame.js +47 -5
- package/dist/chat/ui/intelligent-ui/UiReply.d.ts +3 -1
- package/dist/chat/ui/intelligent-ui/UiReply.js +34 -30
- package/dist/chat/ui/intelligent-ui/block-local.d.ts +9 -0
- package/dist/chat/ui/intelligent-ui/block-local.js +30 -1
- package/dist/chat/ui/intelligent-ui/node-text.d.ts +6 -0
- package/dist/chat/ui/intelligent-ui/node-text.js +54 -0
- package/dist/chat/ui/intelligent-ui/registry.js +2 -1
- package/dist/chat/ui/intelligent-ui/render-context.d.ts +3 -0
- package/dist/chat/ui/intelligent-ui/renderers/chart.js +5 -7
- package/dist/chat/ui/intelligent-ui/renderers/choices.js +6 -2
- package/dist/chat/ui/intelligent-ui/renderers/content.js +6 -13
- package/dist/chat/ui/intelligent-ui/renderers/data.js +8 -15
- package/dist/chat/ui/intelligent-ui/renderers/inputs.d.ts +1 -0
- package/dist/chat/ui/intelligent-ui/renderers/inputs.js +16 -4
- package/dist/chat/ui/intelligent-ui/renderers/links.js +2 -1
- package/dist/chat/ui/intelligent-ui/use-ui-links.d.ts +4 -4
- package/dist/chat/ui/intelligent-ui/use-ui-links.js +29 -10
- package/dist/chat/ui/intelligent-ui/use-ui-queries.d.ts +2 -1
- package/dist/chat/ui/intelligent-ui/use-ui-queries.js +34 -21
- package/dist/chat/ui/rows/MessageRows.js +1 -1
- package/dist/locales/en/agent-chat.json +23 -4
- package/dist/locales/nl/agent-chat.json +23 -4
- package/dist/state/chats.js +5 -1
- package/package.json +24 -29
- package/src/chat/ui/intelligent-ui/UiBlockFrame.tsx +135 -5
- package/src/chat/ui/intelligent-ui/UiReply.tsx +48 -38
- package/src/chat/ui/intelligent-ui/block-local.ts +36 -1
- package/src/chat/ui/intelligent-ui/node-text.ts +60 -0
- package/src/chat/ui/intelligent-ui/registry.ts +2 -1
- package/src/chat/ui/intelligent-ui/render-context.ts +6 -0
- package/src/chat/ui/intelligent-ui/renderers/chart.tsx +5 -7
- package/src/chat/ui/intelligent-ui/renderers/choices.tsx +6 -2
- package/src/chat/ui/intelligent-ui/renderers/content.tsx +9 -14
- package/src/chat/ui/intelligent-ui/renderers/data.tsx +13 -19
- package/src/chat/ui/intelligent-ui/renderers/inputs.tsx +28 -5
- package/src/chat/ui/intelligent-ui/renderers/links.tsx +2 -1
- package/src/chat/ui/intelligent-ui/use-ui-links.ts +31 -11
- package/src/chat/ui/intelligent-ui/use-ui-queries.ts +48 -22
- package/src/chat/ui/rows/MessageRows.tsx +1 -1
- package/src/locales/en/agent-chat.json +23 -4
- package/src/locales/nl/agent-chat.json +23 -4
- package/src/state/chats.ts +5 -1
- package/dist/chat/ui/intelligent-ui/UiBlockFooter.d.ts +0 -15
- package/dist/chat/ui/intelligent-ui/UiBlockFooter.js +0 -50
- package/src/chat/ui/intelligent-ui/UiBlockFooter.tsx +0 -139
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useId, useState } from 'react';
|
|
3
|
-
import { useTranslation } from 'react-i18next';
|
|
4
|
-
import { Lock, Radio, TriangleAlert, Wrench } from 'lucide-react';
|
|
5
|
-
import { Icon, Spinner, Tooltip, useTickingText } from '@adecore/ui';
|
|
6
|
-
import { formatAgo, formatMoment } from '@adecore/ui/format';
|
|
7
|
-
import { useLater } from './use-later.js';
|
|
8
|
-
const NO_FIXES = [];
|
|
9
|
-
const READING_SPINNER_MS = 1000;
|
|
10
|
-
/* The one sign of a live block: what it reads, and when it last read it. A reading spins only after a second. */
|
|
11
|
-
function LivePart({ live }) {
|
|
12
|
-
const { t } = useTranslation('agent-chat');
|
|
13
|
-
const slow = useLater(live.state === 'reading', READING_SPINNER_MS);
|
|
14
|
-
const { readAt } = live;
|
|
15
|
-
const fresh = live.state === 'fresh' || live.state === 'reading';
|
|
16
|
-
const ago = useTickingText(() => {
|
|
17
|
-
if (readAt === null) {
|
|
18
|
-
return '';
|
|
19
|
-
}
|
|
20
|
-
const time = formatAgo(Date.now() - readAt);
|
|
21
|
-
return fresh ? t('blocks.live.read', { time }) : time;
|
|
22
|
-
});
|
|
23
|
-
const source = live.source ?? live.sources[0] ?? '';
|
|
24
|
-
const icon = slow ? (_jsx(Spinner, { size: 12 })) : live.state === 'failed' ? (_jsx(Icon, { icon: TriangleAlert, size: 12, className: "text-status-needs-you" })) : live.state === 'refused' ? (_jsx(Icon, { icon: Lock, size: 12 })) : (_jsx(Icon, { icon: Radio, size: 12, className: "text-status-idle" }));
|
|
25
|
-
const words = live.state === 'failed'
|
|
26
|
-
? t('blocks.live.failed', { source })
|
|
27
|
-
: live.state === 'refused'
|
|
28
|
-
? t('blocks.live.refused', { source })
|
|
29
|
-
: t('blocks.live.label');
|
|
30
|
-
const hint = live.state === 'failed' && live.reason !== undefined
|
|
31
|
-
? live.reason
|
|
32
|
-
: live.sources.length > 0
|
|
33
|
-
? t('blocks.live.sources', { sources: live.sources.join(', ') })
|
|
34
|
-
: null;
|
|
35
|
-
const body = (_jsxs("span", { tabIndex: hint === null ? undefined : 0, className: "flex items-center gap-1.5", children: [icon, _jsx("span", { children: words }), readAt !== null && live.state !== 'refused' && (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": true, children: "\u00B7" }), _jsx("time", { dateTime: new Date(readAt).toISOString(), children: _jsx("span", { ref: ago, className: "tabular-nums" }) })] })), readAt === null && fresh && (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": true, children: "\u00B7" }), _jsx("span", { children: t('blocks.live.notRead') })] }))] }));
|
|
36
|
-
return hint === null ? body : _jsx(Tooltip, { label: hint, children: body });
|
|
37
|
-
}
|
|
38
|
-
/*
|
|
39
|
-
* The line under a block, only when it has something to say: live, answered, repaired or drawn as
|
|
40
|
-
* text, in that order. A hairline of the soft border runs the full width of the card over it.
|
|
41
|
-
*/
|
|
42
|
-
export function UiBlockFooter({ live = null, answered = null, fixes = NO_FIXES, shownAsText = null }) {
|
|
43
|
-
const { t } = useTranslation('agent-chat');
|
|
44
|
-
const [fixesOpen, setFixesOpen] = useState(false);
|
|
45
|
-
const listId = useId();
|
|
46
|
-
if (live === null && answered === null && fixes.length === 0 && shownAsText === null) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
return (_jsxs("div", { className: "-mx-2.25 mt-2.25 -mb-2.25 flex flex-col gap-1.5 border-t border-border-soft px-4.25 py-2 text-xs text-text-faint", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1", children: [live !== null && _jsx(LivePart, { live: live }), answered !== null && (_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx("span", { children: t('blocks.answered', { label: answered.label }) }), _jsx("span", { "aria-hidden": true, children: "\u00B7" }), _jsx("time", { dateTime: new Date(answered.at).toISOString(), children: formatMoment(answered.at) })] })), fixes.length > 0 && (_jsxs("button", { type: "button", "aria-expanded": fixesOpen, "aria-controls": listId, className: "flex items-center gap-1.5 rounded-sm hover:text-text-muted", onClick: () => setFixesOpen(!fixesOpen), children: [_jsx(Icon, { icon: Wrench, size: 12 }), t('blocks.fixes', { count: fixes.length })] })), shownAsText !== null && (_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx("span", { children: t('blocks.shownAsText') }), _jsx("span", { "aria-hidden": true, children: "\u00B7" }), _jsx("span", { children: shownAsText })] }))] }), fixes.length > 0 && (_jsx("ul", { id: listId, hidden: !fixesOpen, className: "flex flex-col gap-0.5 text-text-muted", children: fixes.map((fix, index) => (_jsxs("li", { className: "flex gap-2", children: [_jsx("span", { className: "shrink-0 font-mono", children: fix.code }), _jsx("span", { className: "min-w-0", children: fix.message })] }, index))) }))] }));
|
|
50
|
-
}
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { useId, useState } from 'react';
|
|
2
|
-
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import { Lock, Radio, TriangleAlert, Wrench } from 'lucide-react';
|
|
4
|
-
import { Icon, Spinner, Tooltip, useTickingText } from '@adecore/ui';
|
|
5
|
-
import { formatAgo, formatMoment } from '@adecore/ui/format';
|
|
6
|
-
import type { UiLiveStatus } from './render-context';
|
|
7
|
-
import { useLater } from './use-later';
|
|
8
|
-
|
|
9
|
-
/* Something the compiler repaired, such as a prop it dropped; never an error to a person. */
|
|
10
|
-
export interface UiBlockFix {
|
|
11
|
-
code: string;
|
|
12
|
-
message: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface UiBlockFooterProps {
|
|
16
|
-
live?: UiLiveStatus | null;
|
|
17
|
-
/* The label of the Choice that answered the block, and when, in milliseconds since the epoch. */
|
|
18
|
-
answered?: { label: string; at: number } | null;
|
|
19
|
-
fixes?: readonly UiBlockFix[];
|
|
20
|
-
/* Why the whole block is drawn as its text, such as that it is too large. */
|
|
21
|
-
shownAsText?: string | null;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const NO_FIXES: readonly UiBlockFix[] = [];
|
|
25
|
-
const READING_SPINNER_MS = 1000;
|
|
26
|
-
|
|
27
|
-
/* The one sign of a live block: what it reads, and when it last read it. A reading spins only after a second. */
|
|
28
|
-
function LivePart({ live }: { live: UiLiveStatus }) {
|
|
29
|
-
const { t } = useTranslation('agent-chat');
|
|
30
|
-
const slow = useLater(live.state === 'reading', READING_SPINNER_MS);
|
|
31
|
-
const { readAt } = live;
|
|
32
|
-
const fresh = live.state === 'fresh' || live.state === 'reading';
|
|
33
|
-
const ago = useTickingText(() => {
|
|
34
|
-
if (readAt === null) {
|
|
35
|
-
return '';
|
|
36
|
-
}
|
|
37
|
-
const time = formatAgo(Date.now() - readAt);
|
|
38
|
-
return fresh ? t('blocks.live.read', { time }) : time;
|
|
39
|
-
});
|
|
40
|
-
const source = live.source ?? live.sources[0] ?? '';
|
|
41
|
-
const icon = slow ? (
|
|
42
|
-
<Spinner size={12} />
|
|
43
|
-
) : live.state === 'failed' ? (
|
|
44
|
-
<Icon icon={TriangleAlert} size={12} className="text-status-needs-you" />
|
|
45
|
-
) : live.state === 'refused' ? (
|
|
46
|
-
<Icon icon={Lock} size={12} />
|
|
47
|
-
) : (
|
|
48
|
-
<Icon icon={Radio} size={12} className="text-status-idle" />
|
|
49
|
-
);
|
|
50
|
-
const words =
|
|
51
|
-
live.state === 'failed'
|
|
52
|
-
? t('blocks.live.failed', { source })
|
|
53
|
-
: live.state === 'refused'
|
|
54
|
-
? t('blocks.live.refused', { source })
|
|
55
|
-
: t('blocks.live.label');
|
|
56
|
-
const hint =
|
|
57
|
-
live.state === 'failed' && live.reason !== undefined
|
|
58
|
-
? live.reason
|
|
59
|
-
: live.sources.length > 0
|
|
60
|
-
? t('blocks.live.sources', { sources: live.sources.join(', ') })
|
|
61
|
-
: null;
|
|
62
|
-
const body = (
|
|
63
|
-
<span tabIndex={hint === null ? undefined : 0} className="flex items-center gap-1.5">
|
|
64
|
-
{icon}
|
|
65
|
-
<span>{words}</span>
|
|
66
|
-
{readAt !== null && live.state !== 'refused' && (
|
|
67
|
-
<>
|
|
68
|
-
<span aria-hidden>·</span>
|
|
69
|
-
<time dateTime={new Date(readAt).toISOString()}>
|
|
70
|
-
<span ref={ago} className="tabular-nums" />
|
|
71
|
-
</time>
|
|
72
|
-
</>
|
|
73
|
-
)}
|
|
74
|
-
{readAt === null && fresh && (
|
|
75
|
-
<>
|
|
76
|
-
<span aria-hidden>·</span>
|
|
77
|
-
<span>{t('blocks.live.notRead')}</span>
|
|
78
|
-
</>
|
|
79
|
-
)}
|
|
80
|
-
</span>
|
|
81
|
-
);
|
|
82
|
-
return hint === null ? body : <Tooltip label={hint}>{body}</Tooltip>;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/*
|
|
86
|
-
* The line under a block, only when it has something to say: live, answered, repaired or drawn as
|
|
87
|
-
* text, in that order. A hairline of the soft border runs the full width of the card over it.
|
|
88
|
-
*/
|
|
89
|
-
export function UiBlockFooter({ live = null, answered = null, fixes = NO_FIXES, shownAsText = null }: UiBlockFooterProps) {
|
|
90
|
-
const { t } = useTranslation('agent-chat');
|
|
91
|
-
const [fixesOpen, setFixesOpen] = useState(false);
|
|
92
|
-
const listId = useId();
|
|
93
|
-
if (live === null && answered === null && fixes.length === 0 && shownAsText === null) {
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
return (
|
|
97
|
-
<div className="-mx-2.25 mt-2.25 -mb-2.25 flex flex-col gap-1.5 border-t border-border-soft px-4.25 py-2 text-xs text-text-faint">
|
|
98
|
-
<div className="flex flex-wrap items-center gap-x-3 gap-y-1">
|
|
99
|
-
{live !== null && <LivePart live={live} />}
|
|
100
|
-
{answered !== null && (
|
|
101
|
-
<span className="flex items-center gap-1.5">
|
|
102
|
-
<span>{t('blocks.answered', { label: answered.label })}</span>
|
|
103
|
-
<span aria-hidden>·</span>
|
|
104
|
-
<time dateTime={new Date(answered.at).toISOString()}>{formatMoment(answered.at)}</time>
|
|
105
|
-
</span>
|
|
106
|
-
)}
|
|
107
|
-
{fixes.length > 0 && (
|
|
108
|
-
<button
|
|
109
|
-
type="button"
|
|
110
|
-
aria-expanded={fixesOpen}
|
|
111
|
-
aria-controls={listId}
|
|
112
|
-
className="flex items-center gap-1.5 rounded-sm hover:text-text-muted"
|
|
113
|
-
onClick={() => setFixesOpen(!fixesOpen)}
|
|
114
|
-
>
|
|
115
|
-
<Icon icon={Wrench} size={12} />
|
|
116
|
-
{t('blocks.fixes', { count: fixes.length })}
|
|
117
|
-
</button>
|
|
118
|
-
)}
|
|
119
|
-
{shownAsText !== null && (
|
|
120
|
-
<span className="flex items-center gap-1.5">
|
|
121
|
-
<span>{t('blocks.shownAsText')}</span>
|
|
122
|
-
<span aria-hidden>·</span>
|
|
123
|
-
<span>{shownAsText}</span>
|
|
124
|
-
</span>
|
|
125
|
-
)}
|
|
126
|
-
</div>
|
|
127
|
-
{fixes.length > 0 && (
|
|
128
|
-
<ul id={listId} hidden={!fixesOpen} className="flex flex-col gap-0.5 text-text-muted">
|
|
129
|
-
{fixes.map((fix, index) => (
|
|
130
|
-
<li key={index} className="flex gap-2">
|
|
131
|
-
<span className="shrink-0 font-mono">{fix.code}</span>
|
|
132
|
-
<span className="min-w-0">{fix.message}</span>
|
|
133
|
-
</li>
|
|
134
|
-
))}
|
|
135
|
-
</ul>
|
|
136
|
-
)}
|
|
137
|
-
</div>
|
|
138
|
-
);
|
|
139
|
-
}
|