@agent-native/core 0.171.1 → 0.171.3
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/corpus/README.md +1 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +4 -5
- package/corpus/templates/calendar/actions/create-event.ts +11 -3
- package/corpus/templates/calendar/app/components/calendar/AddCalendarDialog.tsx +56 -51
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +3 -0
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +1 -1
- package/corpus/templates/calendar/app/components/calendar/PeopleSearchDialog.tsx +54 -51
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +1 -1
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +4 -1
- package/corpus/templates/calendar/app/hooks/use-people.ts +23 -13
- package/corpus/templates/calendar/app/lib/event-layout.ts +21 -6
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +3 -0
- package/corpus/templates/calendar/changelog/2026-08-24-overlapping-events-use-space-better.md +5 -0
- package/corpus/templates/calendar/server/lib/google-api.ts +9 -0
- package/corpus/templates/calendar/server/lib/google-calendar.ts +59 -2
- package/corpus/templates/calendar/server/lib/people-search.ts +43 -28
- package/corpus/templates/calendar/shared/api.ts +2 -0
- package/corpus/templates/clips/app/components/player/playback-comment-overlay.tsx +3 -3
- package/corpus/templates/mail/app/root.tsx +29 -0
- package/dist/client/DefaultSpinner.d.ts +3 -1
- package/dist/client/DefaultSpinner.js +2 -2
- package/dist/client/chat-first/apps-rail.d.ts +1 -1
- package/dist/client/chat-first/apps-rail.js +11 -8
- package/dist/client/chat-first/copy.js +1 -0
- package/dist/client/chat-first/types.d.ts +1 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/package.json +1 -1
package/corpus/README.md
CHANGED
|
@@ -2450,17 +2450,15 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
|
|
|
2450
2450
|
: "text-muted-foreground hover:bg-sidebar-accent/50",
|
|
2451
2451
|
)}
|
|
2452
2452
|
>
|
|
2453
|
-
<
|
|
2454
|
-
|
|
2455
|
-
onClick={toggleDashOpen}
|
|
2453
|
+
<Link
|
|
2454
|
+
to="/dashboards"
|
|
2456
2455
|
className="flex min-w-0 flex-1 items-center gap-3 px-3 py-2 text-start"
|
|
2457
|
-
aria-expanded={dashOpen}
|
|
2458
2456
|
>
|
|
2459
2457
|
<IconChartBar className="h-4 w-4 shrink-0" />
|
|
2460
2458
|
<span className="min-w-0 flex-1 truncate">
|
|
2461
2459
|
{t("navigation.dashboards")}
|
|
2462
2460
|
</span>
|
|
2463
|
-
</
|
|
2461
|
+
</Link>
|
|
2464
2462
|
<SidebarSectionSettingsPopover
|
|
2465
2463
|
label={t("navigation.dashboards")}
|
|
2466
2464
|
sortMode={dashboardSortMode}
|
|
@@ -2477,6 +2475,7 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
|
|
|
2477
2475
|
? t("sidebar.collapseDashboards")
|
|
2478
2476
|
: t("sidebar.expandDashboards")
|
|
2479
2477
|
}
|
|
2478
|
+
aria-expanded={dashOpen}
|
|
2480
2479
|
>
|
|
2481
2480
|
<IconChevronDown
|
|
2482
2481
|
className={cn(
|
|
@@ -216,10 +216,16 @@ export default defineAction({
|
|
|
216
216
|
};
|
|
217
217
|
|
|
218
218
|
let zoomMeetingLink: string | undefined;
|
|
219
|
+
let videoConferenceError: CalendarEvent["videoConferenceError"];
|
|
219
220
|
if (args.addZoom) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
try {
|
|
222
|
+
const zoom = await prepareZoomMeetingPatch(email, calEvent);
|
|
223
|
+
zoomMeetingLink = zoom.meetingLink;
|
|
224
|
+
Object.assign(calEvent, zoom.patch);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
videoConferenceError = "zoom";
|
|
227
|
+
console.error("[create-event] Zoom meeting provisioning failed", error);
|
|
228
|
+
}
|
|
223
229
|
}
|
|
224
230
|
|
|
225
231
|
const result = await googleCalendar.createEvent(calEvent, {
|
|
@@ -238,6 +244,8 @@ export default defineAction({
|
|
|
238
244
|
if (result.meetLink) calEvent.hangoutLink = result.meetLink;
|
|
239
245
|
if (result.conferenceData) calEvent.conferenceData = result.conferenceData;
|
|
240
246
|
if (zoomMeetingLink) calEvent.meetingLink = zoomMeetingLink;
|
|
247
|
+
if (videoConferenceError)
|
|
248
|
+
calEvent.videoConferenceError = videoConferenceError;
|
|
241
249
|
|
|
242
250
|
try {
|
|
243
251
|
emit(
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { callAction } from "@agent-native/core/client/hooks";
|
|
2
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
3
2
|
import {
|
|
4
3
|
IconSearch,
|
|
@@ -8,7 +7,7 @@ import {
|
|
|
8
7
|
IconLink,
|
|
9
8
|
IconCalendarPlus,
|
|
10
9
|
} from "@tabler/icons-react";
|
|
11
|
-
import { useState, useEffect,
|
|
10
|
+
import { useState, useEffect, useMemo, useRef } from "react";
|
|
12
11
|
import { toast } from "sonner";
|
|
13
12
|
|
|
14
13
|
import { Button } from "@/components/ui/button";
|
|
@@ -31,17 +30,12 @@ import {
|
|
|
31
30
|
useAddOverlayPerson,
|
|
32
31
|
useRemoveOverlayPerson,
|
|
33
32
|
} from "@/hooks/use-overlay-people";
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
interface SearchResponse {
|
|
42
|
-
results: SearchResult[];
|
|
43
|
-
scopeRequired?: boolean;
|
|
44
|
-
}
|
|
33
|
+
import {
|
|
34
|
+
filterPeopleResults,
|
|
35
|
+
mergePeopleResults,
|
|
36
|
+
usePeopleContacts,
|
|
37
|
+
usePeopleSearch,
|
|
38
|
+
} from "@/hooks/use-people";
|
|
45
39
|
|
|
46
40
|
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
47
41
|
const URL_REGEX = /^(https?|webcal):\/\/.+/i;
|
|
@@ -67,7 +61,7 @@ export function AddCalendarDialog({
|
|
|
67
61
|
|
|
68
62
|
return (
|
|
69
63
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
70
|
-
<DialogContent className="sm:max-w-[440px] gap-0 p-0 top-[
|
|
64
|
+
<DialogContent className="sm:max-w-[440px] max-h-[calc(85vh-1rem)] gap-0 overflow-y-auto p-0 top-[15vh] !translate-y-0">
|
|
71
65
|
<DialogHeader className="px-4 pt-4 pb-0">
|
|
72
66
|
<DialogTitle className="text-base">
|
|
73
67
|
{t("eventForm.addCalendar")}
|
|
@@ -89,7 +83,7 @@ export function AddCalendarDialog({
|
|
|
89
83
|
</TabsList>
|
|
90
84
|
|
|
91
85
|
<TabsContent value="people" className="mt-0">
|
|
92
|
-
<PeopleTab
|
|
86
|
+
<PeopleTab open={open} />
|
|
93
87
|
</TabsContent>
|
|
94
88
|
|
|
95
89
|
<TabsContent value="url" className="mt-0 px-4 pb-4 pt-3">
|
|
@@ -103,15 +97,12 @@ export function AddCalendarDialog({
|
|
|
103
97
|
|
|
104
98
|
// ─── People tab ──────────────────────────────────────────────────────────────
|
|
105
99
|
|
|
106
|
-
function PeopleTab({
|
|
100
|
+
function PeopleTab({ open }: { open: boolean }) {
|
|
107
101
|
const t = useT();
|
|
108
102
|
const [query, setQuery] = useState("");
|
|
109
|
-
const [
|
|
110
|
-
const [scopeRequired, setScopeRequired] = useState(false);
|
|
111
|
-
const [searching, setSearching] = useState(false);
|
|
103
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
112
104
|
const [activeIndex, setActiveIndex] = useState(-1);
|
|
113
105
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
114
|
-
const debounceRef = useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
115
106
|
const listRef = useRef<HTMLDivElement>(null);
|
|
116
107
|
const shouldScrollActiveResultRef = useRef(false);
|
|
117
108
|
|
|
@@ -119,46 +110,57 @@ function PeopleTab({ onClose: _ }: { onClose: () => void }) {
|
|
|
119
110
|
const overlayPeople = Array.isArray(rawOverlayPeople) ? rawOverlayPeople : [];
|
|
120
111
|
const addPerson = useAddOverlayPerson();
|
|
121
112
|
const removePerson = useRemoveOverlayPerson();
|
|
113
|
+
const contacts = usePeopleContacts("directory", open);
|
|
114
|
+
const directorySearch = usePeopleSearch(searchQuery, open, "directory");
|
|
122
115
|
|
|
123
|
-
const overlayEmails =
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
116
|
+
const overlayEmails = useMemo(
|
|
117
|
+
() => new Set(overlayPeople.map((p) => p.email.toLowerCase())),
|
|
118
|
+
[overlayPeople],
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const results = useMemo(
|
|
122
|
+
() =>
|
|
123
|
+
filterPeopleResults(
|
|
124
|
+
mergePeopleResults(
|
|
125
|
+
contacts.data?.results,
|
|
126
|
+
directorySearch.data?.results,
|
|
127
|
+
),
|
|
128
|
+
query,
|
|
129
|
+
new Set(),
|
|
130
|
+
),
|
|
131
|
+
[contacts.data?.results, directorySearch.data?.results, query],
|
|
132
|
+
);
|
|
133
|
+
const selectableResults = results.filter(
|
|
134
|
+
(r) => !overlayEmails.has(r.email.toLowerCase()),
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const searching =
|
|
138
|
+
contacts.isLoading ||
|
|
139
|
+
contacts.isFetching ||
|
|
140
|
+
directorySearch.isLoading ||
|
|
141
|
+
directorySearch.isFetching;
|
|
142
|
+
const scopeRequired = Boolean(
|
|
143
|
+
contacts.data?.scopeRequired || directorySearch.data?.scopeRequired,
|
|
144
|
+
);
|
|
142
145
|
|
|
143
146
|
useEffect(() => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}, [query
|
|
147
|
+
const timeout = window.setTimeout(
|
|
148
|
+
() => setSearchQuery(query),
|
|
149
|
+
query.trim() ? 300 : 0,
|
|
150
|
+
);
|
|
151
|
+
return () => window.clearTimeout(timeout);
|
|
152
|
+
}, [query]);
|
|
150
153
|
|
|
151
154
|
useEffect(() => {
|
|
152
155
|
setActiveIndex(results.length > 0 ? 0 : -1);
|
|
153
156
|
}, [results]);
|
|
154
157
|
|
|
155
158
|
useEffect(() => {
|
|
159
|
+
if (!open) return;
|
|
156
160
|
setQuery("");
|
|
157
|
-
|
|
158
|
-
setScopeRequired(false);
|
|
161
|
+
setSearchQuery("");
|
|
159
162
|
setActiveIndex(-1);
|
|
160
|
-
|
|
161
|
-
}, [search]);
|
|
163
|
+
}, [open]);
|
|
162
164
|
|
|
163
165
|
useEffect(() => {
|
|
164
166
|
if (
|
|
@@ -198,7 +200,10 @@ function PeopleTab({ onClose: _ }: { onClose: () => void }) {
|
|
|
198
200
|
return;
|
|
199
201
|
}
|
|
200
202
|
const trimmed = query.trim();
|
|
201
|
-
if (
|
|
203
|
+
if (
|
|
204
|
+
EMAIL_REGEX.test(trimmed) &&
|
|
205
|
+
!overlayEmails.has(trimmed.toLowerCase())
|
|
206
|
+
) {
|
|
202
207
|
handleAdd(trimmed);
|
|
203
208
|
setQuery("");
|
|
204
209
|
}
|
|
@@ -229,7 +234,7 @@ function PeopleTab({ onClose: _ }: { onClose: () => void }) {
|
|
|
229
234
|
className="max-h-48 overflow-y-auto border-t border-border"
|
|
230
235
|
>
|
|
231
236
|
{results.map((person) => {
|
|
232
|
-
const alreadyAdded = overlayEmails.has(person.email);
|
|
237
|
+
const alreadyAdded = overlayEmails.has(person.email.toLowerCase());
|
|
233
238
|
const selectableIdx = selectableResults.indexOf(person);
|
|
234
239
|
const isActive = !alreadyAdded && selectableIdx === activeIndex;
|
|
235
240
|
return (
|
|
@@ -856,6 +856,9 @@ export function CreateEventPopover({
|
|
|
856
856
|
deletePersistedDraft(activeDraftId);
|
|
857
857
|
onDraftCreated?.(activeDraftId);
|
|
858
858
|
}
|
|
859
|
+
if (result?.videoConferenceError === "zoom") {
|
|
860
|
+
toast.error(t("eventForm.zoomAddFailed"));
|
|
861
|
+
}
|
|
859
862
|
const eventId = result?.id;
|
|
860
863
|
const undo = eventId
|
|
861
864
|
? () => {
|
|
@@ -297,7 +297,7 @@ const DayEventCard = memo(function DayEventCard({
|
|
|
297
297
|
style={{
|
|
298
298
|
...posStyle,
|
|
299
299
|
left: `calc(${li.left}% + ${li.indent}px)`,
|
|
300
|
-
width: `calc(${li.width}% - ${li.indent
|
|
300
|
+
width: `calc(${li.width}% - ${li.indent + 2}px)`,
|
|
301
301
|
zIndex:
|
|
302
302
|
isBeingDragged && isDragging
|
|
303
303
|
? 100
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { callAction } from "@agent-native/core/client/hooks";
|
|
2
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
3
2
|
import {
|
|
4
3
|
IconSearch,
|
|
@@ -6,7 +5,7 @@ import {
|
|
|
6
5
|
IconUserPlus,
|
|
7
6
|
IconLoader2,
|
|
8
7
|
} from "@tabler/icons-react";
|
|
9
|
-
import { useState, useEffect,
|
|
8
|
+
import { useState, useEffect, useMemo, useRef } from "react";
|
|
10
9
|
|
|
11
10
|
import {
|
|
12
11
|
Dialog,
|
|
@@ -19,17 +18,12 @@ import {
|
|
|
19
18
|
useAddOverlayPerson,
|
|
20
19
|
useRemoveOverlayPerson,
|
|
21
20
|
} from "@/hooks/use-overlay-people";
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface SearchResponse {
|
|
30
|
-
results: SearchResult[];
|
|
31
|
-
scopeRequired?: boolean;
|
|
32
|
-
}
|
|
21
|
+
import {
|
|
22
|
+
filterPeopleResults,
|
|
23
|
+
mergePeopleResults,
|
|
24
|
+
usePeopleContacts,
|
|
25
|
+
usePeopleSearch,
|
|
26
|
+
} from "@/hooks/use-people";
|
|
33
27
|
|
|
34
28
|
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
35
29
|
|
|
@@ -44,12 +38,8 @@ export function PeopleSearchDialog({
|
|
|
44
38
|
}: PeopleSearchDialogProps) {
|
|
45
39
|
const t = useT();
|
|
46
40
|
const [query, setQuery] = useState("");
|
|
47
|
-
const [
|
|
48
|
-
const [scopeRequired, setScopeRequired] = useState(false);
|
|
49
|
-
const [searching, setSearching] = useState(false);
|
|
41
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
50
42
|
const [activeIndex, setActiveIndex] = useState(-1);
|
|
51
|
-
const inputRef = useRef<HTMLInputElement>(null);
|
|
52
|
-
const debounceRef = useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
53
43
|
const listRef = useRef<HTMLDivElement>(null);
|
|
54
44
|
const shouldScrollActiveResultRef = useRef(false);
|
|
55
45
|
|
|
@@ -57,52 +47,61 @@ export function PeopleSearchDialog({
|
|
|
57
47
|
const overlayPeople = Array.isArray(rawOverlayPeople) ? rawOverlayPeople : [];
|
|
58
48
|
const addPerson = useAddOverlayPerson();
|
|
59
49
|
const removePerson = useRemoveOverlayPerson();
|
|
50
|
+
const contacts = usePeopleContacts("directory", open);
|
|
51
|
+
const directorySearch = usePeopleSearch(searchQuery, open, "directory");
|
|
52
|
+
|
|
53
|
+
const overlayEmails = useMemo(
|
|
54
|
+
() => new Set(overlayPeople.map((p) => p.email.toLowerCase())),
|
|
55
|
+
[overlayPeople],
|
|
56
|
+
);
|
|
60
57
|
|
|
61
|
-
const
|
|
58
|
+
const results = useMemo(
|
|
59
|
+
() =>
|
|
60
|
+
filterPeopleResults(
|
|
61
|
+
mergePeopleResults(
|
|
62
|
+
contacts.data?.results,
|
|
63
|
+
directorySearch.data?.results,
|
|
64
|
+
),
|
|
65
|
+
query,
|
|
66
|
+
new Set(),
|
|
67
|
+
),
|
|
68
|
+
[contacts.data?.results, directorySearch.data?.results, query],
|
|
69
|
+
);
|
|
62
70
|
|
|
63
71
|
// Selectable results (exclude already-added)
|
|
64
|
-
const selectableResults = results.filter(
|
|
72
|
+
const selectableResults = results.filter(
|
|
73
|
+
(r) => !overlayEmails.has(r.email.toLowerCase()),
|
|
74
|
+
);
|
|
65
75
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
setResults(data.results ?? []);
|
|
75
|
-
setScopeRequired(data.scopeRequired ?? false);
|
|
76
|
-
} catch {
|
|
77
|
-
// ignore
|
|
78
|
-
} finally {
|
|
79
|
-
setSearching(false);
|
|
80
|
-
}
|
|
81
|
-
}, []);
|
|
76
|
+
const searching =
|
|
77
|
+
contacts.isLoading ||
|
|
78
|
+
contacts.isFetching ||
|
|
79
|
+
directorySearch.isLoading ||
|
|
80
|
+
directorySearch.isFetching;
|
|
81
|
+
const scopeRequired = Boolean(
|
|
82
|
+
contacts.data?.scopeRequired || directorySearch.data?.scopeRequired,
|
|
83
|
+
);
|
|
82
84
|
|
|
83
85
|
useEffect(() => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}, [query
|
|
86
|
+
const timeout = window.setTimeout(
|
|
87
|
+
() => setSearchQuery(query),
|
|
88
|
+
query.trim() ? 300 : 0,
|
|
89
|
+
);
|
|
90
|
+
return () => window.clearTimeout(timeout);
|
|
91
|
+
}, [query]);
|
|
90
92
|
|
|
91
93
|
// Reset active index when results change
|
|
92
94
|
useEffect(() => {
|
|
93
95
|
setActiveIndex(results.length > 0 ? 0 : -1);
|
|
94
96
|
}, [results]);
|
|
95
97
|
|
|
96
|
-
// Load org contacts when dialog opens
|
|
97
98
|
useEffect(() => {
|
|
98
99
|
if (open) {
|
|
99
100
|
setQuery("");
|
|
100
|
-
|
|
101
|
-
setScopeRequired(false);
|
|
101
|
+
setSearchQuery("");
|
|
102
102
|
setActiveIndex(-1);
|
|
103
|
-
search("");
|
|
104
103
|
}
|
|
105
|
-
}, [open
|
|
104
|
+
}, [open]);
|
|
106
105
|
|
|
107
106
|
function handleAdd(email: string, name?: string) {
|
|
108
107
|
addPerson.mutate({ email, name });
|
|
@@ -145,7 +144,10 @@ export function PeopleSearchDialog({
|
|
|
145
144
|
}
|
|
146
145
|
// Otherwise, try adding as a typed email
|
|
147
146
|
const trimmed = query.trim();
|
|
148
|
-
if (
|
|
147
|
+
if (
|
|
148
|
+
EMAIL_REGEX.test(trimmed) &&
|
|
149
|
+
!overlayEmails.has(trimmed.toLowerCase())
|
|
150
|
+
) {
|
|
149
151
|
handleAdd(trimmed);
|
|
150
152
|
setQuery("");
|
|
151
153
|
}
|
|
@@ -154,7 +156,7 @@ export function PeopleSearchDialog({
|
|
|
154
156
|
|
|
155
157
|
return (
|
|
156
158
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
157
|
-
<DialogContent className="sm:max-w-[440px] gap-0 p-0">
|
|
159
|
+
<DialogContent className="sm:max-w-[440px] max-h-[calc(85vh-1rem)] gap-0 overflow-y-auto p-0 top-[15vh] !translate-y-0">
|
|
158
160
|
<DialogHeader className="px-4 pt-4 pb-0">
|
|
159
161
|
<DialogTitle className="text-base">
|
|
160
162
|
{t("eventForm.people")}
|
|
@@ -165,7 +167,6 @@ export function PeopleSearchDialog({
|
|
|
165
167
|
<div className="relative px-4 pt-3 pb-2">
|
|
166
168
|
<IconSearch className="absolute left-7 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
|
|
167
169
|
<input
|
|
168
|
-
ref={inputRef}
|
|
169
170
|
value={query}
|
|
170
171
|
onChange={(e) => setQuery(e.target.value)}
|
|
171
172
|
onKeyDown={handleKeyDown}
|
|
@@ -185,7 +186,9 @@ export function PeopleSearchDialog({
|
|
|
185
186
|
className="max-h-48 overflow-y-auto border-t border-border"
|
|
186
187
|
>
|
|
187
188
|
{results.map((person) => {
|
|
188
|
-
const alreadyAdded = overlayEmails.has(
|
|
189
|
+
const alreadyAdded = overlayEmails.has(
|
|
190
|
+
person.email.toLowerCase(),
|
|
191
|
+
);
|
|
189
192
|
const selectableIdx = selectableResults.indexOf(person);
|
|
190
193
|
const isActive = !alreadyAdded && selectableIdx === activeIndex;
|
|
191
194
|
return (
|
|
@@ -367,7 +367,7 @@ const WeekEventCard = memo(function WeekEventCard({
|
|
|
367
367
|
style={{
|
|
368
368
|
...style,
|
|
369
369
|
left: `calc(${li.left}% + ${li.indent}px)`,
|
|
370
|
-
width: `calc(${li.width}% - ${li.indent
|
|
370
|
+
width: `calc(${li.width}% - ${li.indent + 2}px)`,
|
|
371
371
|
zIndex:
|
|
372
372
|
isBeingDragged && isDragging
|
|
373
373
|
? 100
|
|
@@ -272,7 +272,10 @@ export function AppLayout({ children }: AppLayoutProps) {
|
|
|
272
272
|
|
|
273
273
|
useEffect(() => {
|
|
274
274
|
if (!hasAccounts) return;
|
|
275
|
-
void
|
|
275
|
+
void Promise.all([
|
|
276
|
+
prefetchPeopleContacts(queryClient),
|
|
277
|
+
prefetchPeopleContacts(queryClient, "directory"),
|
|
278
|
+
]);
|
|
276
279
|
}, [hasAccounts, queryClient]);
|
|
277
280
|
|
|
278
281
|
useEffect(() => {
|
|
@@ -13,16 +13,18 @@ export interface PeopleSearchResponse {
|
|
|
13
13
|
scopeRequired?: boolean;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export type PeopleSearchScope = "all" | "directory";
|
|
17
|
+
|
|
16
18
|
const PEOPLE_CONTACTS_STALE_TIME = 10 * 60_000;
|
|
17
19
|
const PEOPLE_CONTACTS_GC_TIME = 30 * 60_000;
|
|
18
20
|
const PEOPLE_SEARCH_STALE_TIME = 60_000;
|
|
19
21
|
const PEOPLE_SEARCH_GC_TIME = 5 * 60_000;
|
|
20
22
|
|
|
21
|
-
export
|
|
22
|
-
"action",
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
export function peopleContactsQueryKey(scope: PeopleSearchScope = "all") {
|
|
24
|
+
return ["action", "search-people", { scope }] as const;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const PEOPLE_CONTACTS_QUERY_KEY = peopleContactsQueryKey();
|
|
26
28
|
|
|
27
29
|
function sourceRank(source?: PeopleSearchResult["source"]) {
|
|
28
30
|
switch (source) {
|
|
@@ -115,13 +117,14 @@ export function filterPeopleResults(
|
|
|
115
117
|
|
|
116
118
|
export function prefetchPeopleContacts(
|
|
117
119
|
queryClient: ReturnType<typeof useQueryClient>,
|
|
120
|
+
scope: PeopleSearchScope = "all",
|
|
118
121
|
) {
|
|
119
122
|
return queryClient.prefetchQuery({
|
|
120
|
-
queryKey:
|
|
123
|
+
queryKey: peopleContactsQueryKey(scope),
|
|
121
124
|
queryFn: () =>
|
|
122
125
|
callAction<PeopleSearchResponse>(
|
|
123
126
|
"search-people",
|
|
124
|
-
{ scope
|
|
127
|
+
{ scope },
|
|
125
128
|
{ method: "GET" },
|
|
126
129
|
),
|
|
127
130
|
staleTime: PEOPLE_CONTACTS_STALE_TIME,
|
|
@@ -129,13 +132,16 @@ export function prefetchPeopleContacts(
|
|
|
129
132
|
});
|
|
130
133
|
}
|
|
131
134
|
|
|
132
|
-
export function usePeopleContacts(
|
|
135
|
+
export function usePeopleContacts(
|
|
136
|
+
scope: PeopleSearchScope = "all",
|
|
137
|
+
enabled = true,
|
|
138
|
+
) {
|
|
133
139
|
return useQuery({
|
|
134
|
-
queryKey:
|
|
140
|
+
queryKey: peopleContactsQueryKey(scope),
|
|
135
141
|
queryFn: () =>
|
|
136
142
|
callAction<PeopleSearchResponse>(
|
|
137
143
|
"search-people",
|
|
138
|
-
{ scope
|
|
144
|
+
{ scope },
|
|
139
145
|
{ method: "GET" },
|
|
140
146
|
),
|
|
141
147
|
enabled,
|
|
@@ -145,14 +151,18 @@ export function usePeopleContacts(enabled = true) {
|
|
|
145
151
|
});
|
|
146
152
|
}
|
|
147
153
|
|
|
148
|
-
export function usePeopleSearch(
|
|
154
|
+
export function usePeopleSearch(
|
|
155
|
+
query: string,
|
|
156
|
+
enabled = true,
|
|
157
|
+
scope: PeopleSearchScope = "all",
|
|
158
|
+
) {
|
|
149
159
|
const q = query.trim();
|
|
150
160
|
return useQuery({
|
|
151
|
-
queryKey: ["action", "search-people", { q, scope
|
|
161
|
+
queryKey: ["action", "search-people", { q, scope }],
|
|
152
162
|
queryFn: () =>
|
|
153
163
|
callAction<PeopleSearchResponse>(
|
|
154
164
|
"search-people",
|
|
155
|
-
{ q, scope
|
|
165
|
+
{ q, scope },
|
|
156
166
|
{ method: "GET" },
|
|
157
167
|
),
|
|
158
168
|
enabled: enabled && q.length > 0,
|
|
@@ -112,18 +112,33 @@ export function computeTimedEventLayout(
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
const totalCols = overlapLayers.length;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
const sameStartGroups = new Map<number, EventEntry[]>();
|
|
116
|
+
const sameStartIndexes = new Map<EventEntry, number>();
|
|
117
|
+
for (const entry of group) {
|
|
118
|
+
const entries = sameStartGroups.get(entry.bounds.start) ?? [];
|
|
119
|
+
sameStartIndexes.set(entry, entries.length);
|
|
120
|
+
entries.push(entry);
|
|
121
|
+
sameStartGroups.set(entry.bounds.start, entries);
|
|
122
|
+
}
|
|
119
123
|
|
|
120
124
|
for (const entry of group) {
|
|
121
125
|
const col = eventColumns.get(entry.event)!;
|
|
126
|
+
const sameStartEntries = sameStartGroups.get(entry.bounds.start)!;
|
|
127
|
+
const sameStartIndex = sameStartIndexes.get(entry)!;
|
|
128
|
+
const sameStartWidth = 100 / sameStartEntries.length;
|
|
129
|
+
const isGroupStart = entry.bounds.start === group[0].bounds.start;
|
|
130
|
+
const useStartLanes = sameStartEntries.length > 1;
|
|
131
|
+
|
|
132
|
+
// Later events sit over the earlier event instead of forcing both cards
|
|
133
|
+
// into equal columns. Events with the same start time still get lanes so
|
|
134
|
+
// their titles remain independently readable.
|
|
135
|
+
const left = useStartLanes ? sameStartIndex * sameStartWidth : 0;
|
|
136
|
+
const width = 100 - left;
|
|
122
137
|
|
|
123
138
|
result.set(entry.event.id, {
|
|
124
|
-
left
|
|
139
|
+
left,
|
|
125
140
|
width,
|
|
126
|
-
indent:
|
|
141
|
+
indent: isGroupStart && sameStartIndex === 0 ? 0 : OVERLAP_INDENT_PX,
|
|
127
142
|
col,
|
|
128
143
|
totalCols,
|
|
129
144
|
stackOrder: stackOrder++,
|
|
@@ -896,6 +896,9 @@ export default function CalendarView() {
|
|
|
896
896
|
createEvent.mutate(payload, {
|
|
897
897
|
onSuccess: (result) => {
|
|
898
898
|
discardedCommittingDraftsRef.current.delete(draftId);
|
|
899
|
+
if (result?.videoConferenceError === "zoom") {
|
|
900
|
+
toast.error(t("eventForm.zoomAddFailed"));
|
|
901
|
+
}
|
|
899
902
|
const createdEventId = result?.id;
|
|
900
903
|
if (createdEventId) {
|
|
901
904
|
const undo = () => {
|
|
@@ -130,6 +130,14 @@ export function isGoogleNotFoundError(error: unknown): boolean {
|
|
|
130
130
|
);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
export function isGoogleEventAbsentError(error: unknown): boolean {
|
|
134
|
+
return (
|
|
135
|
+
isGoogleNotFoundError(error) ||
|
|
136
|
+
(error instanceof GoogleApiError && error.status === 410) ||
|
|
137
|
+
(error instanceof Error && /^Google API error \(410\):/.test(error.message))
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
133
141
|
export async function googleFetch(
|
|
134
142
|
url: string,
|
|
135
143
|
accessToken: string,
|
|
@@ -364,6 +372,7 @@ export function calendarListEvents(
|
|
|
364
372
|
timeMax?: string;
|
|
365
373
|
q?: string;
|
|
366
374
|
singleEvents?: boolean;
|
|
375
|
+
showDeleted?: boolean;
|
|
367
376
|
orderBy?: string;
|
|
368
377
|
maxResults?: number;
|
|
369
378
|
pageToken?: string;
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
calendarDeleteEvent,
|
|
31
31
|
calendarPatchEvent,
|
|
32
32
|
calendarUpdateEvent,
|
|
33
|
+
isGoogleEventAbsentError,
|
|
33
34
|
peopleGetProfile,
|
|
34
35
|
} from "./google-api.js";
|
|
35
36
|
import { getCalendarProviderApiRuntime } from "./provider-api.js";
|
|
@@ -1707,8 +1708,14 @@ export async function deleteEvent(
|
|
|
1707
1708
|
return;
|
|
1708
1709
|
}
|
|
1709
1710
|
|
|
1710
|
-
const instanceStart =
|
|
1711
|
-
|
|
1711
|
+
const instanceStart =
|
|
1712
|
+
instance.originalStartTime?.dateTime ||
|
|
1713
|
+
instance.originalStartTime?.date ||
|
|
1714
|
+
instance.start?.dateTime ||
|
|
1715
|
+
instance.start?.date ||
|
|
1716
|
+
"";
|
|
1717
|
+
const isAllDay =
|
|
1718
|
+
!instance.originalStartTime?.dateTime && !instance.start?.dateTime;
|
|
1712
1719
|
|
|
1713
1720
|
// Compute UNTIL value (day before this instance)
|
|
1714
1721
|
const cutoff = new Date(instanceStart);
|
|
@@ -1748,6 +1755,56 @@ export async function deleteEvent(
|
|
|
1748
1755
|
{ recurrence: updatedRecurrence },
|
|
1749
1756
|
{ sendUpdates },
|
|
1750
1757
|
);
|
|
1758
|
+
|
|
1759
|
+
// Truncating the master does not remove materialized exceptions after the
|
|
1760
|
+
// cutoff, so remove those exceptions as well.
|
|
1761
|
+
const instanceStartMs = Date.parse(instanceStart);
|
|
1762
|
+
const exceptionIds = new Set<string>([googleEventId]);
|
|
1763
|
+
let pageToken: string | undefined;
|
|
1764
|
+
do {
|
|
1765
|
+
const response = await calendarListEvents(client.accessToken, "primary", {
|
|
1766
|
+
singleEvents: false,
|
|
1767
|
+
showDeleted: true,
|
|
1768
|
+
maxResults: 2500,
|
|
1769
|
+
pageToken,
|
|
1770
|
+
});
|
|
1771
|
+
for (const event of response?.items || []) {
|
|
1772
|
+
if (event.recurringEventId !== recurringEventId) continue;
|
|
1773
|
+
const originalStart =
|
|
1774
|
+
event.originalStartTime?.dateTime ||
|
|
1775
|
+
event.originalStartTime?.date ||
|
|
1776
|
+
event.start?.dateTime ||
|
|
1777
|
+
event.start?.date;
|
|
1778
|
+
const originalStartMs =
|
|
1779
|
+
typeof originalStart === "string" ? Date.parse(originalStart) : NaN;
|
|
1780
|
+
if (
|
|
1781
|
+
event.id &&
|
|
1782
|
+
Number.isFinite(instanceStartMs) &&
|
|
1783
|
+
Number.isFinite(originalStartMs) &&
|
|
1784
|
+
originalStartMs >= instanceStartMs
|
|
1785
|
+
) {
|
|
1786
|
+
exceptionIds.add(event.id);
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
pageToken =
|
|
1790
|
+
typeof response?.nextPageToken === "string"
|
|
1791
|
+
? response.nextPageToken
|
|
1792
|
+
: undefined;
|
|
1793
|
+
} while (pageToken);
|
|
1794
|
+
|
|
1795
|
+
for (const eventId of exceptionIds) {
|
|
1796
|
+
try {
|
|
1797
|
+
await calendarDeleteEvent(
|
|
1798
|
+
client.accessToken,
|
|
1799
|
+
"primary",
|
|
1800
|
+
eventId,
|
|
1801
|
+
sendUpdates,
|
|
1802
|
+
);
|
|
1803
|
+
} catch (error) {
|
|
1804
|
+
// A generated occurrence may already be gone once the master is trimmed.
|
|
1805
|
+
if (!isGoogleEventAbsentError(error)) throw error;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1751
1808
|
}
|
|
1752
1809
|
|
|
1753
1810
|
/**
|
|
@@ -36,6 +36,7 @@ interface ContactCacheEntry {
|
|
|
36
36
|
|
|
37
37
|
const CONTACT_CACHE_TTL = 10 * 60 * 1000;
|
|
38
38
|
const contactCache = new Map<string, ContactCacheEntry>();
|
|
39
|
+
const contactCacheLoads = new Map<string, Promise<ContactCacheEntry>>();
|
|
39
40
|
|
|
40
41
|
const GENERIC_EMAIL_DOMAINS = new Set([
|
|
41
42
|
"gmail.com",
|
|
@@ -255,36 +256,50 @@ async function loadCachedContactPeople(
|
|
|
255
256
|
return cached;
|
|
256
257
|
}
|
|
257
258
|
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
259
|
+
const pending = contactCacheLoads.get(cacheKey);
|
|
260
|
+
if (pending) return pending;
|
|
261
|
+
|
|
262
|
+
const load = (async () => {
|
|
263
|
+
const people = new Map<string, PersonResult>();
|
|
264
|
+
let contactsLimited = false;
|
|
265
|
+
|
|
266
|
+
await Promise.all(
|
|
267
|
+
clients.map(async (client) => {
|
|
268
|
+
try {
|
|
269
|
+
const [connections, otherContacts] = await Promise.all([
|
|
270
|
+
listConnectionPages(client.accessToken, "connections"),
|
|
271
|
+
listConnectionPages(client.accessToken, "otherContacts"),
|
|
272
|
+
]);
|
|
273
|
+
|
|
274
|
+
for (const person of extractPeople(connections, "contact")) {
|
|
275
|
+
mergeCachedContact(people, person);
|
|
276
|
+
}
|
|
277
|
+
for (const person of extractPeople(otherContacts, "otherContact")) {
|
|
278
|
+
mergeCachedContact(people, person);
|
|
279
|
+
}
|
|
280
|
+
} catch (error) {
|
|
281
|
+
if (permissionLimited(error)) contactsLimited = true;
|
|
274
282
|
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
}),
|
|
279
|
-
);
|
|
283
|
+
}),
|
|
284
|
+
);
|
|
280
285
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
286
|
+
const entry: ContactCacheEntry = {
|
|
287
|
+
people: Array.from(people.values()),
|
|
288
|
+
contactsLimited,
|
|
289
|
+
expiresAt: Date.now() + CONTACT_CACHE_TTL,
|
|
290
|
+
};
|
|
291
|
+
contactCache.set(cacheKey, entry);
|
|
292
|
+
return entry;
|
|
293
|
+
})();
|
|
294
|
+
|
|
295
|
+
contactCacheLoads.set(cacheKey, load);
|
|
296
|
+
try {
|
|
297
|
+
return await load;
|
|
298
|
+
} finally {
|
|
299
|
+
if (contactCacheLoads.get(cacheKey) === load) {
|
|
300
|
+
contactCacheLoads.delete(cacheKey);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
288
303
|
}
|
|
289
304
|
|
|
290
305
|
export async function searchPeopleForUser(
|
|
@@ -66,6 +66,8 @@ export interface CalendarEvent {
|
|
|
66
66
|
hangoutLink?: string; // Google Meet link
|
|
67
67
|
/** Meeting URL stored in location/description for non-Google providers such as Zoom */
|
|
68
68
|
meetingLink?: string;
|
|
69
|
+
/** Action-result warning when optional video conferencing could not be provisioned. */
|
|
70
|
+
videoConferenceError?: "zoom";
|
|
69
71
|
conferenceData?: {
|
|
70
72
|
entryPoints?: Array<{
|
|
71
73
|
entryPointType: string;
|
|
@@ -103,9 +103,9 @@ export function PlaybackCommentOverlay({
|
|
|
103
103
|
</p>
|
|
104
104
|
<InlineMarkdown
|
|
105
105
|
content={comment.content}
|
|
106
|
-
className="line-clamp-3 text-sm leading-5 text-
|
|
107
|
-
linkClassName="text-
|
|
108
|
-
codeClassName="bg-
|
|
106
|
+
className="line-clamp-3 text-sm leading-5 text-background dark:text-foreground"
|
|
107
|
+
linkClassName="text-background underline decoration-background/60 hover:decoration-background dark:text-foreground dark:decoration-foreground/60 dark:hover:decoration-foreground"
|
|
108
|
+
codeClassName="bg-background/15 text-background dark:bg-foreground/15 dark:text-foreground"
|
|
109
109
|
/>
|
|
110
110
|
</div>
|
|
111
111
|
</div>
|
|
@@ -14,6 +14,11 @@ import {
|
|
|
14
14
|
type LocaleCode,
|
|
15
15
|
} from "@agent-native/core/client/i18n";
|
|
16
16
|
import {
|
|
17
|
+
isDynamicImportFailureMessage,
|
|
18
|
+
recoverFromStaleChunkError,
|
|
19
|
+
} from "@agent-native/core/client/route-chunk-recovery";
|
|
20
|
+
import {
|
|
21
|
+
DefaultSpinner,
|
|
17
22
|
ErrorReportActions,
|
|
18
23
|
getThemeInitScript,
|
|
19
24
|
} from "@agent-native/core/client/ui";
|
|
@@ -90,6 +95,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
90
95
|
fallback: string;
|
|
91
96
|
back: string;
|
|
92
97
|
reload: string;
|
|
98
|
+
loading: string;
|
|
93
99
|
sendFeedback: string;
|
|
94
100
|
feedbackPlaceholder: string;
|
|
95
101
|
openGitHubIssue: string;
|
|
@@ -100,6 +106,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
100
106
|
fallback: "Something went wrong while loading Mail.",
|
|
101
107
|
back: "Back",
|
|
102
108
|
reload: "Reload",
|
|
109
|
+
loading: "Reloading Mail...",
|
|
103
110
|
sendFeedback: "Send feedback",
|
|
104
111
|
feedbackPlaceholder:
|
|
105
112
|
"Describe what happened before this Mail error appeared.",
|
|
@@ -110,6 +117,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
110
117
|
fallback: "加载 Mail 时出现问题。",
|
|
111
118
|
back: "返回",
|
|
112
119
|
reload: "重新加载",
|
|
120
|
+
loading: "正在重新加载 Mail...",
|
|
113
121
|
sendFeedback: "发送反馈",
|
|
114
122
|
feedbackPlaceholder: "描述此 Mail 错误出现前发生了什么。",
|
|
115
123
|
openGitHubIssue: "打开 GitHub issue",
|
|
@@ -119,6 +127,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
119
127
|
fallback: "載入 Mail 時發生問題。",
|
|
120
128
|
back: "返回",
|
|
121
129
|
reload: "重新載入",
|
|
130
|
+
loading: "正在重新載入 Mail...",
|
|
122
131
|
sendFeedback: "傳送意見回饋",
|
|
123
132
|
feedbackPlaceholder: "描述此 Mail 錯誤出現前發生了什麼。",
|
|
124
133
|
openGitHubIssue: "開啟 GitHub issue",
|
|
@@ -128,6 +137,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
128
137
|
fallback: "Algo salió mal al cargar Mail.",
|
|
129
138
|
back: "Atrás",
|
|
130
139
|
reload: "Recargar",
|
|
140
|
+
loading: "Recargando Mail...",
|
|
131
141
|
sendFeedback: "Enviar comentarios",
|
|
132
142
|
feedbackPlaceholder:
|
|
133
143
|
"Describe qué pasó antes de que apareciera este error de Mail.",
|
|
@@ -138,6 +148,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
138
148
|
fallback: "Un problème est survenu lors du chargement de Mail.",
|
|
139
149
|
back: "Retour",
|
|
140
150
|
reload: "Recharger",
|
|
151
|
+
loading: "Rechargement de Mail...",
|
|
141
152
|
sendFeedback: "Envoyer un retour",
|
|
142
153
|
feedbackPlaceholder:
|
|
143
154
|
"Décrivez ce qui s'est passé avant cette erreur de Mail.",
|
|
@@ -148,6 +159,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
148
159
|
fallback: "Beim Laden von Mail ist ein Fehler aufgetreten.",
|
|
149
160
|
back: "Zurück",
|
|
150
161
|
reload: "Neu laden",
|
|
162
|
+
loading: "Mail wird neu geladen...",
|
|
151
163
|
sendFeedback: "Feedback senden",
|
|
152
164
|
feedbackPlaceholder:
|
|
153
165
|
"Beschreiben Sie, was vor diesem Mail-Fehler passiert ist.",
|
|
@@ -158,6 +170,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
158
170
|
fallback: "Mail の読み込み中に問題が発生しました。",
|
|
159
171
|
back: "戻る",
|
|
160
172
|
reload: "再読み込み",
|
|
173
|
+
loading: "Mail を再読み込み中...",
|
|
161
174
|
sendFeedback: "フィードバックを送信",
|
|
162
175
|
feedbackPlaceholder:
|
|
163
176
|
"この Mail エラーの直前に起きたことを説明してください。",
|
|
@@ -168,6 +181,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
168
181
|
fallback: "Mail을 불러오는 중 문제가 발생했습니다.",
|
|
169
182
|
back: "뒤로",
|
|
170
183
|
reload: "새로고침",
|
|
184
|
+
loading: "Mail 새로고침 중...",
|
|
171
185
|
sendFeedback: "피드백 보내기",
|
|
172
186
|
feedbackPlaceholder:
|
|
173
187
|
"이 Mail 오류가 나타나기 전에 무슨 일이 있었는지 적어 주세요.",
|
|
@@ -178,6 +192,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
178
192
|
fallback: "Algo deu errado ao carregar o Mail.",
|
|
179
193
|
back: "Voltar",
|
|
180
194
|
reload: "Recarregar",
|
|
195
|
+
loading: "Recarregando o Mail...",
|
|
181
196
|
sendFeedback: "Enviar feedback",
|
|
182
197
|
feedbackPlaceholder:
|
|
183
198
|
"Descreva o que aconteceu antes deste erro do Mail aparecer.",
|
|
@@ -188,6 +203,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
188
203
|
fallback: "Mail लोड करते समय कुछ गलत हुआ।",
|
|
189
204
|
back: "वापस",
|
|
190
205
|
reload: "रीलोड",
|
|
206
|
+
loading: "Mail रीलोड हो रहा है...",
|
|
191
207
|
sendFeedback: "फ़ीडबैक भेजें",
|
|
192
208
|
feedbackPlaceholder: "इस Mail त्रुटि से पहले क्या हुआ, उसका वर्णन करें।",
|
|
193
209
|
openGitHubIssue: "GitHub issue खोलें",
|
|
@@ -197,6 +213,7 @@ const MAIL_ERROR_COPY: Record<
|
|
|
197
213
|
fallback: "حدث خطأ أثناء تحميل Mail.",
|
|
198
214
|
back: "رجوع",
|
|
199
215
|
reload: "إعادة التحميل",
|
|
216
|
+
loading: "جارٍ إعادة تحميل Mail...",
|
|
200
217
|
sendFeedback: "إرسال الملاحظات",
|
|
201
218
|
feedbackPlaceholder: "صف ما حدث قبل ظهور خطأ Mail هذا.",
|
|
202
219
|
openGitHubIssue: "فتح مشكلة في GitHub",
|
|
@@ -469,6 +486,18 @@ export function ErrorBoundary() {
|
|
|
469
486
|
const copy =
|
|
470
487
|
MAIL_ERROR_COPY[activeErrorLocale()] ?? MAIL_ERROR_COPY[DEFAULT_LOCALE];
|
|
471
488
|
const message = routeErrorMessage(error, copy.fallback);
|
|
489
|
+
const staleChunk = isDynamicImportFailureMessage(message);
|
|
490
|
+
const [recovering, setRecovering] = useState(staleChunk);
|
|
491
|
+
|
|
492
|
+
useEffect(() => {
|
|
493
|
+
if (!staleChunk) {
|
|
494
|
+
setRecovering(false);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
if (!recoverFromStaleChunkError(error)) setRecovering(false);
|
|
498
|
+
}, [error, staleChunk]);
|
|
499
|
+
|
|
500
|
+
if (recovering) return <DefaultSpinner ariaLabel={copy.loading} />;
|
|
472
501
|
|
|
473
502
|
return (
|
|
474
503
|
<div className="flex min-h-screen items-center justify-center bg-background px-6 text-foreground">
|
|
@@ -23,7 +23,7 @@ function isDevelopmentBuild() {
|
|
|
23
23
|
return false;
|
|
24
24
|
return viteEnv?.DEV === true;
|
|
25
25
|
}
|
|
26
|
-
export function DefaultSpinner() {
|
|
26
|
+
export function DefaultSpinner({ ariaLabel = "Loading", }) {
|
|
27
27
|
const [showStallHint, setShowStallHint] = useState(false);
|
|
28
28
|
useEffect(() => {
|
|
29
29
|
setShowStallHint(isDevelopmentBuild());
|
|
@@ -36,7 +36,7 @@ export function DefaultSpinner() {
|
|
|
36
36
|
gap: 16,
|
|
37
37
|
height: "100vh",
|
|
38
38
|
width: "100%",
|
|
39
|
-
}, children: [_jsx("svg", { role: "status", "aria-label":
|
|
39
|
+
}, children: [_jsx("svg", { role: "status", "aria-label": ariaLabel, width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", style: { animation: "an-spin 1s linear infinite", opacity: 0.7 }, children: _jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) }), showStallHint && (_jsx("p", { className: "an-stall-hint", children: "Still loading. A first run compiles dependencies and can take a minute \u2014 if it does not finish, check the terminal running the dev server for errors." })), _jsx("style", { children: `
|
|
40
40
|
@keyframes an-spin { to { transform: rotate(360deg) } }
|
|
41
41
|
${showStallHint
|
|
42
42
|
? `
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ChatFirstAppRailProps } from "./types.js";
|
|
2
2
|
export declare const CHAT_FIRST_APP_RAIL_SHOW_ALL_STORAGE_KEY = "agent-native:chat-first-app-rail-show-all:v1";
|
|
3
|
-
export declare const ChatFirstAppsRail: import("react").MemoExoticComponent<({ apps, defaultAppIds, activeAppId, loading, error, collapsed, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onRemoveApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy, }: ChatFirstAppRailProps) => import("react").JSX.Element>;
|
|
3
|
+
export declare const ChatFirstAppsRail: import("react").MemoExoticComponent<({ apps, defaultAppIds, activeAppId, loading, error, collapsed, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onReloadApp, onRemoveApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy, }: ChatFirstAppRailProps) => import("react").JSX.Element>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger, Skeleton, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@agent-native/toolkit/ui";
|
|
3
|
-
import { IconApps, IconChevronDown, IconChevronUp, IconPin, IconPlus, IconTrash, } from "@tabler/icons-react";
|
|
3
|
+
import { IconApps, IconChevronDown, IconChevronUp, IconPin, IconPlus, IconRefresh, IconTrash, } from "@tabler/icons-react";
|
|
4
4
|
import { memo, useEffect, useMemo, useState } from "react";
|
|
5
5
|
import { CHAT_FIRST_DEFAULT_APP_IDS, orderChatFirstAppIds, readChatFirstAppLayout, writeChatFirstAppLayout, } from "../chat-first.js";
|
|
6
6
|
import { cn } from "../utils.js";
|
|
@@ -33,7 +33,10 @@ function ChatFirstRailAppIcon({ app, activeAppId, renderIcon, }) {
|
|
|
33
33
|
const isInactive = activeAppId !== undefined && !isActive;
|
|
34
34
|
return (_jsx("span", { "data-chat-first-app-icon": true, className: cn("transition-[filter]", isInactive && "grayscale"), children: renderIcon(app, { isActive, isInactive }) }));
|
|
35
35
|
}
|
|
36
|
-
function
|
|
36
|
+
function AppContextMenuContent({ app, copy, index, onMove, onReloadApp, onRemoveApp, onTogglePinned, pinned, total, }) {
|
|
37
|
+
return (_jsxs(ContextMenuContent, { children: [_jsxs(ContextMenuItem, { onSelect: () => onTogglePinned(app.id), children: [_jsx(IconPin, { size: 14, "aria-hidden": "true" }), pinned ? copy("removePinned") : copy("pinTop")] }), onReloadApp ? (_jsxs(ContextMenuItem, { onSelect: () => onReloadApp(app), children: [_jsx(IconRefresh, { size: 14, "aria-hidden": "true" }), copy("reloadApp")] })) : null, _jsx(ContextMenuSeparator, {}), _jsxs(ContextMenuItem, { disabled: index === 0, onSelect: () => onMove(app.id, -1), children: [_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" }), copy("moveUp")] }), _jsxs(ContextMenuItem, { disabled: index === total - 1, onSelect: () => onMove(app.id, 1), children: [_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" }), copy("moveDown")] }), onRemoveApp ? (_jsxs(_Fragment, { children: [_jsx(ContextMenuSeparator, {}), _jsxs(ContextMenuItem, { onSelect: () => onRemoveApp(app), className: "text-destructive focus:text-destructive", children: [_jsx(IconTrash, { size: 14, "aria-hidden": "true" }), copy("removeApp")] })] })) : null] }));
|
|
38
|
+
}
|
|
39
|
+
function AppRows({ apps, defaultAppIds, activeAppId, layout, onDragStart, onDrop, onDragEnd, onOpenApp, onReloadApp, onRemoveApp, onTogglePinned, onMove, renderIcon, copy, }) {
|
|
37
40
|
const orderedIds = orderChatFirstAppIds(apps.map((app) => app.id), layout, defaultAppIds);
|
|
38
41
|
const appsById = new Map(apps.map((app) => [app.id, app]));
|
|
39
42
|
const orderedApps = orderedIds
|
|
@@ -61,10 +64,10 @@ function AppRows({ apps, defaultAppIds, activeAppId, layout, onDragStart, onDrop
|
|
|
61
64
|
}
|
|
62
65
|
}, "aria-keyshortcuts": "Alt+ArrowUp Alt+ArrowDown", "aria-label": copy("openApp", { name: app.name }), children: [_jsx(ChatFirstRailAppIcon, { app: app, activeAppId: activeAppId, renderIcon: renderIcon }), _jsx("span", { className: "truncate", children: app.name })] }), _jsx("button", { type: "button", className: cn("flex size-6 shrink-0 items-center justify-center rounded text-sidebar-foreground/45 opacity-0 hover:bg-sidebar-accent hover:text-sidebar-foreground group-hover:opacity-100 focus-visible:opacity-100", pinned && "text-sidebar-foreground/70 opacity-100"), "aria-label": copy(pinned ? "unpinApp" : "pinApp", {
|
|
63
66
|
name: app.name,
|
|
64
|
-
}), "aria-pressed": pinned, onClick: () => onTogglePinned(app.id), children: _jsx(IconPin, { size: 13, strokeWidth: pinned ? 2.2 : 1.6, "aria-hidden": "true" }) }), _jsx("span", { className: "sr-only", children: `${index + 1} of ${orderedApps.length}` })] }) }),
|
|
67
|
+
}), "aria-pressed": pinned, onClick: () => onTogglePinned(app.id), children: _jsx(IconPin, { size: 13, strokeWidth: pinned ? 2.2 : 1.6, "aria-hidden": "true" }) }), _jsx("span", { className: "sr-only", children: `${index + 1} of ${orderedApps.length}` })] }) }), _jsx(AppContextMenuContent, { app: app, copy: copy, index: index, onMove: onMove, onReloadApp: onReloadApp, onRemoveApp: onRemoveApp, onTogglePinned: onTogglePinned, pinned: pinned, total: orderedApps.length })] }, app.id));
|
|
65
68
|
}) }));
|
|
66
69
|
}
|
|
67
|
-
export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, defaultAppIds, activeAppId, loading = false, error, collapsed = false, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onRemoveApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy = defaultChatFirstCopy, }) {
|
|
70
|
+
export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, defaultAppIds, activeAppId, loading = false, error, collapsed = false, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onReloadApp, onRemoveApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy = defaultChatFirstCopy, }) {
|
|
68
71
|
const [localLayout, setLocalLayout] = useState(() => readChatFirstAppLayout());
|
|
69
72
|
const layout = controlledLayout ?? localLayout;
|
|
70
73
|
const [draggedAppId, setDraggedAppId] = useState(null);
|
|
@@ -135,9 +138,9 @@ export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, default
|
|
|
135
138
|
if (collapsed) {
|
|
136
139
|
return (_jsx(TooltipProvider, { children: _jsxs("section", { "data-chat-first-apps-rail": true, className: "flex flex-col items-center gap-1 px-1.5 pt-2", "aria-label": copy("workspaceApps"), children: [loading && apps.length === 0
|
|
137
140
|
? [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "size-9 rounded-md" }, index)))
|
|
138
|
-
: visibleApps.map((app) => (_jsxs(Tooltip, { delayDuration: 0, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "data-chat-first-app": true, "data-app-id": app.id, className: cn("flex size-9 items-center justify-center rounded-md", activeAppId === app.id
|
|
139
|
-
|
|
140
|
-
|
|
141
|
+
: visibleApps.map((app) => (_jsxs(ContextMenu, { children: [_jsxs(Tooltip, { delayDuration: 0, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(ContextMenuTrigger, { asChild: true, children: _jsx("button", { type: "button", "data-chat-first-app": true, "data-app-id": app.id, className: cn("flex size-9 items-center justify-center rounded-md", activeAppId === app.id
|
|
142
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
143
|
+
: "text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"), onClick: () => onOpenApp(app), "aria-label": copy("openApp", { name: app.name }), children: _jsx(ChatFirstRailAppIcon, { app: app, activeAppId: activeAppId, renderIcon: renderIcon }) }) }) }), _jsx(TooltipContent, { side: "right", children: app.name })] }), _jsx(AppContextMenuContent, { app: app, copy: copy, index: orderedApps.indexOf(app), onMove: moveApp, onReloadApp: onReloadApp, onRemoveApp: onRemoveApp, onTogglePinned: togglePinned, pinned: layout.pinnedIds.includes(app.id), total: orderedApps.length })] }, app.id))), onOpenAllApps ? (_jsxs(Tooltip, { delayDuration: 0, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "data-chat-first-all-apps": true, className: "flex size-9 items-center justify-center rounded-md text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", onClick: onOpenAllApps, "aria-label": copy("allApps"), children: _jsx(IconApps, { size: 16, "aria-hidden": "true" }) }) }), _jsx(TooltipContent, { side: "right", children: copy("allApps") })] })) : null, error ? (_jsx("span", { className: "size-1.5 rounded-full bg-destructive", title: error, "aria-label": error })) : null] }) }));
|
|
141
144
|
}
|
|
142
|
-
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "mt-3 px-2 pb-2 pt-2", "aria-label": copy("workspaceApps"), children: [_jsxs("div", { className: "mb-1 flex items-center gap-1.5 px-2 text-[11px] font-medium text-sidebar-foreground/50", children: [_jsx("span", { children: copy("workspaceApps") }), _jsx("span", { className: "ml-auto", children: createTrigger })] }), loading && apps.length === 0 ? (_jsx("div", { className: "space-y-0.5 px-2", children: [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "h-8 w-full rounded-md" }, index))) })) : apps.length === 0 ? (_jsxs("div", { className: "px-2", children: [_jsx("p", { className: "text-xs text-sidebar-foreground/55", children: copy("noWorkspaceApps") }), createAppTrigger ? (createTrigger) : onCreateApp ? (_jsxs("button", { type: "button", className: "mt-1 inline-flex h-6 items-center gap-1.5 rounded-md border border-sidebar-border px-2 text-xs text-sidebar-foreground/75 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onCreateApp, children: [_jsx(IconPlus, { size: 13, "aria-hidden": "true" }), copy("createApp")] })) : (createTrigger)] })) : (_jsx(AppRows, { apps: visibleApps, defaultAppIds: defaultAppIds, activeAppId: activeAppId, layout: layout, onDragStart: setDraggedAppId, onDrop: reorderApps, onDragEnd: () => setDraggedAppId(null), onOpenApp: onOpenApp, onRemoveApp: onRemoveApp, onTogglePinned: togglePinned, onMove: moveApp, renderIcon: renderIcon, copy: copy })), hasMoreApps || showAllApps ? (_jsxs("button", { type: "button", className: "mt-0.5 flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: () => setShowAllApps((value) => !value), children: [showAllApps ? (_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" })) : (_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" })), showAllApps ? copy("showLess") : copy("showMore")] })) : null, onOpenAllApps ? (_jsx("div", { className: "mt-1 border-t border-sidebar-border/60 pt-1", children: _jsxs("button", { type: "button", "data-chat-first-all-apps": true, className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/55 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onOpenAllApps, children: [_jsx(IconApps, { size: 14, "aria-hidden": "true" }), _jsx("span", { children: copy("allApps") })] }) })) : null, error ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "mt-1 flex items-center gap-1 px-2 text-[10px] text-destructive/80", onClick: onRetry, "aria-label": error, children: [_jsx("span", { className: "size-1.5 rounded-full bg-destructive" }), onRetry ? copy("retry") : copy("appsLoadError")] }) }), _jsx(TooltipContent, { side: "right", children: error })] })) : null] }));
|
|
145
|
+
return (_jsxs("section", { "data-chat-first-apps-rail": true, className: "mt-3 px-2 pb-2 pt-2", "aria-label": copy("workspaceApps"), children: [_jsxs("div", { className: "mb-1 flex items-center gap-1.5 px-2 text-[11px] font-medium text-sidebar-foreground/50", children: [_jsx("span", { children: copy("workspaceApps") }), _jsx("span", { className: "ml-auto", children: createTrigger })] }), loading && apps.length === 0 ? (_jsx("div", { className: "space-y-0.5 px-2", children: [0, 1, 2].map((index) => (_jsx(Skeleton, { className: "h-8 w-full rounded-md" }, index))) })) : apps.length === 0 ? (_jsxs("div", { className: "px-2", children: [_jsx("p", { className: "text-xs text-sidebar-foreground/55", children: copy("noWorkspaceApps") }), createAppTrigger ? (createTrigger) : onCreateApp ? (_jsxs("button", { type: "button", className: "mt-1 inline-flex h-6 items-center gap-1.5 rounded-md border border-sidebar-border px-2 text-xs text-sidebar-foreground/75 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onCreateApp, children: [_jsx(IconPlus, { size: 13, "aria-hidden": "true" }), copy("createApp")] })) : (createTrigger)] })) : (_jsx(AppRows, { apps: visibleApps, defaultAppIds: defaultAppIds, activeAppId: activeAppId, layout: layout, onDragStart: setDraggedAppId, onDrop: reorderApps, onDragEnd: () => setDraggedAppId(null), onOpenApp: onOpenApp, onReloadApp: onReloadApp, onRemoveApp: onRemoveApp, onTogglePinned: togglePinned, onMove: moveApp, renderIcon: renderIcon, copy: copy })), hasMoreApps || showAllApps ? (_jsxs("button", { type: "button", className: "mt-0.5 flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/50 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: () => setShowAllApps((value) => !value), children: [showAllApps ? (_jsx(IconChevronUp, { size: 14, "aria-hidden": "true" })) : (_jsx(IconChevronDown, { size: 14, "aria-hidden": "true" })), showAllApps ? copy("showLess") : copy("showMore")] })) : null, onOpenAllApps ? (_jsx("div", { className: "mt-1 border-t border-sidebar-border/60 pt-1", children: _jsxs("button", { type: "button", "data-chat-first-all-apps": true, className: "flex h-8 w-full items-center gap-2 rounded-md px-2 text-xs text-sidebar-foreground/55 hover:bg-sidebar-accent hover:text-sidebar-foreground", onClick: onOpenAllApps, children: [_jsx(IconApps, { size: 14, "aria-hidden": "true" }), _jsx("span", { children: copy("allApps") })] }) })) : null, error ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "mt-1 flex items-center gap-1 px-2 text-[10px] text-destructive/80", onClick: onRetry, "aria-label": error, children: [_jsx("span", { className: "size-1.5 rounded-full bg-destructive" }), onRetry ? copy("retry") : copy("appsLoadError")] }) }), _jsx(TooltipContent, { side: "right", children: error })] })) : null] }));
|
|
143
146
|
});
|
|
@@ -56,6 +56,7 @@ export interface ChatFirstAppRailProps {
|
|
|
56
56
|
onLayoutError?: (reason: "unavailable" | "write-failed") => void;
|
|
57
57
|
onRetry?: () => void;
|
|
58
58
|
onOpenApp: (app: ChatFirstAppItem) => void;
|
|
59
|
+
onReloadApp?: (app: ChatFirstAppItem) => void;
|
|
59
60
|
onRemoveApp?: (app: ChatFirstAppItem) => void;
|
|
60
61
|
onOpenAllApps?: () => void;
|
|
61
62
|
onCreateApp?: () => void;
|
|
@@ -48,8 +48,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
|
|
|
48
48
|
}>;
|
|
49
49
|
/** DELETE /_agent-native/resources/:id — delete a resource */
|
|
50
50
|
export declare function handleDeleteResource(event: any): Promise<{
|
|
51
|
-
error: string;
|
|
52
51
|
ok?: undefined;
|
|
52
|
+
error: string;
|
|
53
53
|
} | {
|
|
54
54
|
error?: undefined;
|
|
55
55
|
ok: boolean;
|
package/dist/secrets/routes.d.ts
CHANGED
|
@@ -37,17 +37,17 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
|
|
|
37
37
|
ok?: undefined;
|
|
38
38
|
status?: undefined;
|
|
39
39
|
} | {
|
|
40
|
+
error?: undefined;
|
|
40
41
|
ok: boolean;
|
|
41
42
|
status: string;
|
|
42
|
-
error?: undefined;
|
|
43
43
|
} | {
|
|
44
44
|
ok?: undefined;
|
|
45
45
|
error: string;
|
|
46
46
|
removed?: undefined;
|
|
47
47
|
} | {
|
|
48
|
+
error?: undefined;
|
|
48
49
|
ok: boolean;
|
|
49
50
|
removed: boolean;
|
|
50
|
-
error?: undefined;
|
|
51
51
|
}>>;
|
|
52
52
|
/**
|
|
53
53
|
* POST /_agent-native/secrets/:key/test — validate an optional candidate value
|
|
@@ -58,13 +58,13 @@ export declare function createTestSecretHandler(): import("h3").EventHandlerWith
|
|
|
58
58
|
error: string;
|
|
59
59
|
note?: undefined;
|
|
60
60
|
} | {
|
|
61
|
+
error?: undefined;
|
|
61
62
|
ok: boolean;
|
|
62
63
|
note?: undefined;
|
|
63
|
-
error?: undefined;
|
|
64
64
|
} | {
|
|
65
|
+
error?: undefined;
|
|
65
66
|
ok: boolean;
|
|
66
67
|
note: string;
|
|
67
|
-
error?: undefined;
|
|
68
68
|
} | {
|
|
69
69
|
note?: undefined;
|
|
70
70
|
ok: boolean;
|
|
@@ -95,11 +95,11 @@ export interface AdHocSecretPayload {
|
|
|
95
95
|
export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
|
|
96
96
|
error: string;
|
|
97
97
|
} | {
|
|
98
|
+
error?: undefined;
|
|
98
99
|
ok: boolean;
|
|
99
100
|
key: string;
|
|
100
|
-
error?: undefined;
|
|
101
101
|
} | {
|
|
102
|
+
error?: undefined;
|
|
102
103
|
ok: boolean;
|
|
103
104
|
removed: boolean;
|
|
104
|
-
error?: undefined;
|
|
105
105
|
}>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.171.
|
|
3
|
+
"version": "0.171.3",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|