@adecore/agents-react 0.25.0 → 0.25.2
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/node-text.js +4 -2
- package/dist/chat/ui/intelligent-ui/renderers/map-view.js +15 -8
- package/dist/chat/ui/intelligent-ui/renderers/text.d.ts +1 -1
- package/dist/chat/ui/intelligent-ui/renderers/text.js +2 -1
- package/dist/host.d.ts +1 -0
- package/package.json +8 -8
- package/src/chat/ui/intelligent-ui/node-text.ts +4 -2
- package/src/chat/ui/intelligent-ui/renderers/map-view.tsx +15 -8
- package/src/chat/ui/intelligent-ui/renderers/text.tsx +9 -4
- package/src/host.ts +5 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseUiEventTime } from '@adecore/intelligent-ui';
|
|
2
|
-
import { formatClock, formatDay, formatDayClock, formatDayClockWithYear, formatDayWithYear } from '@adecore/ui/format';
|
|
2
|
+
import { formatClock, formatDateTime, formatDay, formatDayClock, formatDayClockWithYear, formatDayWithYear } from '@adecore/ui/format';
|
|
3
3
|
/* The text a node holds, every `$text` below it joined as written, such as the code of a CodeBlock. */
|
|
4
4
|
export function uiNodeText(node) {
|
|
5
5
|
return node.children.map((child) => (child.type === '$text' ? String(child.props.text ?? '') : uiNodeText(child))).join('');
|
|
@@ -129,7 +129,9 @@ export function uiEventTime(at, now = Date.now()) {
|
|
|
129
129
|
const year = moment.written ? moment.date.getUTCFullYear() : moment.date.getFullYear();
|
|
130
130
|
const withYear = year !== new Date(now).getFullYear();
|
|
131
131
|
if (moment.kind === 'time') {
|
|
132
|
-
return
|
|
132
|
+
return moment.seconds
|
|
133
|
+
? formatDateTime(moment.date, { hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'UTC' })
|
|
134
|
+
: formatClock(moment.date, zone);
|
|
133
135
|
}
|
|
134
136
|
if (moment.kind === 'date') {
|
|
135
137
|
return withYear ? formatDayWithYear(moment.date, zone) : formatDay(moment.date, zone);
|
|
@@ -11,12 +11,17 @@ const MARKER = 'flex size-5 items-center justify-center rounded-full bg-map-mark
|
|
|
11
11
|
const PICKED = 'z-1 bg-accent text-accent-text outline-2 outline-surface';
|
|
12
12
|
// A tile that fails this many times with none loading in between leaves the map empty, so the outline stands in.
|
|
13
13
|
const TILE_ERRORS_IN_A_ROW = 4;
|
|
14
|
-
let
|
|
15
|
-
/*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
let workerUrlSet = null;
|
|
15
|
+
/*
|
|
16
|
+
* The worker is a file of the package, so the bundler of the app has to serve it: the default address beside the chunk
|
|
17
|
+
* would not exist. A dev server that pre-bundles this package rewrites the fallback to a folder that is gone, so the
|
|
18
|
+
* host hands the address from its own source.
|
|
19
|
+
*/
|
|
20
|
+
function ensureBundledWorker(hosted) {
|
|
21
|
+
const url = hosted ?? new URL('maplibre-gl/dist/maplibre-gl-worker.mjs', import.meta.url).href;
|
|
22
|
+
if (url !== workerUrlSet) {
|
|
23
|
+
setWorkerUrl(url);
|
|
24
|
+
workerUrlSet = url;
|
|
20
25
|
}
|
|
21
26
|
}
|
|
22
27
|
/* The grounds of the built-in map are theme tokens, which the page resolves; the style needs plain colors. */
|
|
@@ -31,7 +36,9 @@ function readColors(element) {
|
|
|
31
36
|
*/
|
|
32
37
|
export function MapView({ markers, source, selected, onPick, onStatus }) {
|
|
33
38
|
const { t, i18n } = useTranslation('agent-chat');
|
|
34
|
-
const
|
|
39
|
+
const host = useChatHost();
|
|
40
|
+
const mode = host.code.useMode();
|
|
41
|
+
const workerUrl = host.maps?.workerUrl;
|
|
35
42
|
const element = useRef(null);
|
|
36
43
|
const [map, setMap] = useState(null);
|
|
37
44
|
const [outline, setOutline] = useState(false);
|
|
@@ -53,7 +60,7 @@ export function MapView({ markers, source, selected, onPick, onStatus }) {
|
|
|
53
60
|
const tiles = current.state === 'tiles' && !offline;
|
|
54
61
|
let created;
|
|
55
62
|
try {
|
|
56
|
-
ensureBundledWorker();
|
|
63
|
+
ensureBundledWorker(workerUrl);
|
|
57
64
|
created = new MapLibreMap({
|
|
58
65
|
container,
|
|
59
66
|
style: current.state === 'tiles' && tiles ? current.styleUrl(mode) : baseMapStyle(colors),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type UiProps } from '@adecore/intelligent-ui';
|
|
2
2
|
import { type UiRendererProps } from '../render-context.js';
|
|
3
3
|
export declare function SummaryRenderer({ node, children }: UiRendererProps<UiProps<'Summary'>>): import("react").JSX.Element;
|
|
4
4
|
export declare function CalloutRenderer({ node, children }: UiRendererProps<UiProps<'Callout'>>): import("react").JSX.Element;
|
|
@@ -3,6 +3,7 @@ import { useContext } from 'react';
|
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { Circle, CircleCheck, CircleDot, CircleMinus, CircleX } from 'lucide-react';
|
|
6
|
+
import { parseUiEventTime } from '@adecore/intelligent-ui';
|
|
6
7
|
import { Icon, Meter, Pill, Spinner } from '@adecore/ui';
|
|
7
8
|
import { formatNumber, formatPercent } from '@adecore/ui/format';
|
|
8
9
|
import { UiHeadContext } from '../render-context.js';
|
|
@@ -73,5 +74,5 @@ export function EventRenderer({ node, children }) {
|
|
|
73
74
|
const time = uiEventTime(at);
|
|
74
75
|
// A neutral dot says nothing the title does not, and a detail is part of what the row says.
|
|
75
76
|
const label = [time, uiNodeLabel(node), tone === 'neutral' ? '' : t(`blocks.event.tone.${tone}`), detail ?? ''].filter((part) => part !== '').join(', ');
|
|
76
|
-
return (_jsxs("li", { "aria-label": label, className: "group/event relative flex min-h-7 gap-3 pb-3 last:pb-0", children: [_jsx("span", { "aria-hidden": true, className: clsx('mt-1 size-2 shrink-0 rounded-full bg-current', UI_TONE_TEXT[tone]) }), _jsx("span", { "aria-hidden": true, className: "absolute top-3.5 bottom-0 left-0.75 w-px bg-border group-last/event:hidden" }), _jsxs("div", { className: "flex min-w-0 grow flex-col gap-0.5", children: [_jsx("time", { dateTime: at, className: "text-xs text-text-faint tabular-nums", children: time }), _jsx("div", { className: "text-sm wrap-break-word text-text", children: children }), detail !== undefined && detail !== '' && _jsx("div", { className: "text-xs wrap-anywhere text-text-faint", children: detail })] })] }));
|
|
77
|
+
return (_jsxs("li", { "aria-label": label, className: "group/event relative flex min-h-7 gap-3 pb-3 last:pb-0", children: [_jsx("span", { "aria-hidden": true, className: clsx('mt-1 size-2 shrink-0 rounded-full bg-current', UI_TONE_TEXT[tone]) }), _jsx("span", { "aria-hidden": true, className: "absolute top-3.5 bottom-0 left-0.75 w-px bg-border group-last/event:hidden" }), _jsxs("div", { className: "flex min-w-0 grow flex-col gap-0.5", children: [parseUiEventTime(at) === null ? (_jsx("span", { className: "text-xs wrap-anywhere text-text-faint tabular-nums", children: time })) : (_jsx("time", { dateTime: at, className: "text-xs text-text-faint tabular-nums", children: time })), _jsx("div", { className: "text-sm wrap-break-word text-text", children: children }), detail !== undefined && detail !== '' && _jsx("div", { className: "text-xs wrap-anywhere text-text-faint", children: detail })] })] }));
|
|
77
78
|
}
|
package/dist/host.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/agents-react",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.2",
|
|
4
4
|
"description": "React agent chat threads, composers, approvals, provider accounts and usage views.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -67,11 +67,11 @@
|
|
|
67
67
|
"test:visuals": "bun --config=integration.bunfig.toml --conditions=source test ./src/chat/visual-viewport.integration.test.ts"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@adecore/agent-contracts": "0.25.
|
|
71
|
-
"@adecore/editor": "0.25.
|
|
72
|
-
"@adecore/editor-react": "0.25.
|
|
73
|
-
"@adecore/intelligent-ui": "0.25.
|
|
74
|
-
"@adecore/merge": "0.25.
|
|
70
|
+
"@adecore/agent-contracts": "0.25.2",
|
|
71
|
+
"@adecore/editor": "0.25.2",
|
|
72
|
+
"@adecore/editor-react": "0.25.2",
|
|
73
|
+
"@adecore/intelligent-ui": "0.25.2",
|
|
74
|
+
"@adecore/merge": "0.25.2",
|
|
75
75
|
"@codemirror/commands": "^6.11.1",
|
|
76
76
|
"@codemirror/language": "^6.12.4",
|
|
77
77
|
"@codemirror/state": "^6.7.6",
|
|
@@ -94,14 +94,14 @@
|
|
|
94
94
|
"zustand": "^5.0.15"
|
|
95
95
|
},
|
|
96
96
|
"peerDependencies": {
|
|
97
|
-
"@adecore/ui": "^0.25.
|
|
97
|
+
"@adecore/ui": "^0.25.2",
|
|
98
98
|
"i18next": "^26.4.2",
|
|
99
99
|
"react": "^19.3.0",
|
|
100
100
|
"react-dom": "^19.3.0",
|
|
101
101
|
"react-i18next": "^17.0.15"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
|
-
"@adecore/ui": "0.25.
|
|
104
|
+
"@adecore/ui": "0.25.2",
|
|
105
105
|
"@types/bun": "^1.4.2",
|
|
106
106
|
"@types/react": "^19.3.0",
|
|
107
107
|
"@types/react-dom": "^19.3.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TFunction } from 'i18next';
|
|
2
2
|
import { parseUiEventTime, type UiComponentName, type UiProps, type UiViewNode } from '@adecore/intelligent-ui';
|
|
3
|
-
import { formatClock, formatDay, formatDayClock, formatDayClockWithYear, formatDayWithYear } from '@adecore/ui/format';
|
|
3
|
+
import { formatClock, formatDateTime, formatDay, formatDayClock, formatDayClockWithYear, formatDayWithYear } from '@adecore/ui/format';
|
|
4
4
|
import type { UiLiveStatus } from './render-context';
|
|
5
5
|
|
|
6
6
|
/* The text a node holds, every `$text` below it joined as written, such as the code of a CodeBlock. */
|
|
@@ -143,7 +143,9 @@ export function uiEventTime(at: string, now: Date | number = Date.now()): string
|
|
|
143
143
|
const year = moment.written ? moment.date.getUTCFullYear() : moment.date.getFullYear();
|
|
144
144
|
const withYear = year !== new Date(now).getFullYear();
|
|
145
145
|
if (moment.kind === 'time') {
|
|
146
|
-
return
|
|
146
|
+
return moment.seconds
|
|
147
|
+
? formatDateTime(moment.date, { hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: 'UTC' })
|
|
148
|
+
: formatClock(moment.date, zone);
|
|
147
149
|
}
|
|
148
150
|
if (moment.kind === 'date') {
|
|
149
151
|
return withYear ? formatDayWithYear(moment.date, zone) : formatDay(moment.date, zone);
|
|
@@ -33,13 +33,18 @@ const PICKED = 'z-1 bg-accent text-accent-text outline-2 outline-surface';
|
|
|
33
33
|
// A tile that fails this many times with none loading in between leaves the map empty, so the outline stands in.
|
|
34
34
|
const TILE_ERRORS_IN_A_ROW = 4;
|
|
35
35
|
|
|
36
|
-
let
|
|
36
|
+
let workerUrlSet: string | null = null;
|
|
37
37
|
|
|
38
|
-
/*
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
/*
|
|
39
|
+
* The worker is a file of the package, so the bundler of the app has to serve it: the default address beside the chunk
|
|
40
|
+
* would not exist. A dev server that pre-bundles this package rewrites the fallback to a folder that is gone, so the
|
|
41
|
+
* host hands the address from its own source.
|
|
42
|
+
*/
|
|
43
|
+
function ensureBundledWorker(hosted: string | undefined): void {
|
|
44
|
+
const url = hosted ?? new URL('maplibre-gl/dist/maplibre-gl-worker.mjs', import.meta.url).href;
|
|
45
|
+
if (url !== workerUrlSet) {
|
|
46
|
+
setWorkerUrl(url);
|
|
47
|
+
workerUrlSet = url;
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
50
|
|
|
@@ -56,7 +61,9 @@ function readColors(element: HTMLElement): MapColors {
|
|
|
56
61
|
*/
|
|
57
62
|
export function MapView({ markers, source, selected, onPick, onStatus }: MapViewProps) {
|
|
58
63
|
const { t, i18n } = useTranslation('agent-chat');
|
|
59
|
-
const
|
|
64
|
+
const host = useChatHost();
|
|
65
|
+
const mode = host.code.useMode();
|
|
66
|
+
const workerUrl = host.maps?.workerUrl;
|
|
60
67
|
const element = useRef<HTMLDivElement>(null);
|
|
61
68
|
const [map, setMap] = useState<MapLibreMap | null>(null);
|
|
62
69
|
const [outline, setOutline] = useState(false);
|
|
@@ -79,7 +86,7 @@ export function MapView({ markers, source, selected, onPick, onStatus }: MapView
|
|
|
79
86
|
const tiles = current.state === 'tiles' && !offline;
|
|
80
87
|
let created: MapLibreMap;
|
|
81
88
|
try {
|
|
82
|
-
ensureBundledWorker();
|
|
89
|
+
ensureBundledWorker(workerUrl);
|
|
83
90
|
created = new MapLibreMap({
|
|
84
91
|
container,
|
|
85
92
|
style: current.state === 'tiles' && tiles ? current.styleUrl(mode) : baseMapStyle(colors),
|
|
@@ -2,7 +2,7 @@ import { useContext } from 'react';
|
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import { Circle, CircleCheck, CircleDot, CircleMinus, CircleX, type LucideIcon } from 'lucide-react';
|
|
5
|
-
import type
|
|
5
|
+
import { parseUiEventTime, type UiProps } from '@adecore/intelligent-ui';
|
|
6
6
|
import { Icon, Meter, Pill, Spinner } from '@adecore/ui';
|
|
7
7
|
import { formatNumber, formatPercent } from '@adecore/ui/format';
|
|
8
8
|
import { UiHeadContext, type UiRenderContext, type UiRendererProps } from '../render-context';
|
|
@@ -150,9 +150,14 @@ export function EventRenderer({ node, children }: UiRendererProps<UiProps<'Event
|
|
|
150
150
|
<span aria-hidden className={clsx('mt-1 size-2 shrink-0 rounded-full bg-current', UI_TONE_TEXT[tone])} />
|
|
151
151
|
<span aria-hidden className="absolute top-3.5 bottom-0 left-0.75 w-px bg-border group-last/event:hidden" />
|
|
152
152
|
<div className="flex min-w-0 grow flex-col gap-0.5">
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
{/* A time nobody could read stays as written and is no `dateTime` for a machine to read. */}
|
|
154
|
+
{parseUiEventTime(at) === null ? (
|
|
155
|
+
<span className="text-xs wrap-anywhere text-text-faint tabular-nums">{time}</span>
|
|
156
|
+
) : (
|
|
157
|
+
<time dateTime={at} className="text-xs text-text-faint tabular-nums">
|
|
158
|
+
{time}
|
|
159
|
+
</time>
|
|
160
|
+
)}
|
|
156
161
|
<div className="text-sm wrap-break-word text-text">{children}</div>
|
|
157
162
|
{detail !== undefined && detail !== '' && <div className="text-xs wrap-anywhere text-text-faint">{detail}</div>}
|
|
158
163
|
</div>
|
package/src/host.ts
CHANGED
|
@@ -236,6 +236,11 @@ export interface ChatHost {
|
|
|
236
236
|
/* The map tiles of a Map block; left out, a map draws its outline and its list of places only. */
|
|
237
237
|
maps?: {
|
|
238
238
|
useSource(scopeId: string): UiMapSource;
|
|
239
|
+
/*
|
|
240
|
+
* The address of MapLibre's worker file (`maplibre-gl/dist/maplibre-gl-worker.mjs`) as the app's bundler serves it,
|
|
241
|
+
* for a bundler that moves this package and breaks the address the map would otherwise work out.
|
|
242
|
+
*/
|
|
243
|
+
workerUrl?: string;
|
|
239
244
|
};
|
|
240
245
|
/* The colors an account may wear in the order a picker offers them, the few it shows first, and their names. */
|
|
241
246
|
accents: {
|