@agent-native/core 0.180.0-nightly-20260915184036 → 0.180.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/CHANGELOG.md +10 -0
- package/corpus/templates/calendar/CHANGELOG.md +39 -0
- package/corpus/templates/calendar/INTERACTION-MATRIX.md +19 -17
- package/corpus/templates/calendar/actions/update-calendar-visual-preferences.ts +21 -0
- package/corpus/templates/calendar/actions/view-screen.ts +10 -2
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +11 -0
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +174 -145
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +20 -16
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +1 -0
- package/corpus/templates/calendar/app/hooks/use-events.ts +16 -0
- package/corpus/templates/calendar/app/hooks/use-view-preferences.ts +126 -14
- package/corpus/templates/calendar/app/i18n-data.ts +90 -0
- package/corpus/templates/calendar/app/lib/calendar-navigation.ts +29 -9
- package/corpus/templates/calendar/app/lib/calendar-timezone.ts +2 -0
- package/corpus/templates/calendar/app/lib/event-time-range.ts +34 -0
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +245 -35
- package/corpus/templates/calendar/changelog/2026-09-13-calendar-sidebar-overflow-is-easier-to-discover.md +6 -0
- package/corpus/templates/calendar/changelog/2026-09-15-calendar-mirrors-notion-calendar-s-customizable-day-ranges-a.md +6 -0
- package/corpus/templates/calendar/shared/calendar-view-preferences.ts +36 -0
- package/corpus/templates/calendar/shared/timezone.ts +9 -2
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +2 -0
- package/corpus/templates/clips/CHANGELOG.md +19 -0
- package/corpus/templates/clips/actions/save-browser-diagnostics.ts +43 -4
- package/corpus/templates/clips/app/components/player/browser-diagnostics-panel.tsx +114 -1
- package/corpus/templates/clips/app/i18n/en-US.ts +7 -0
- package/corpus/templates/clips/app/lib/browser-diagnostics-capture.ts +108 -0
- package/corpus/templates/clips/app/routes/record.tsx +1 -0
- package/corpus/templates/clips/changelog/2026-09-15-recordings-include-a-structured-timeline-of-browser-interact.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +7 -0
- package/corpus/templates/clips/chrome-extension/src/background.ts +235 -9
- package/corpus/templates/clips/chrome-extension/src/content-history-bridge.ts +80 -0
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +166 -5
- package/corpus/templates/clips/chrome-extension/vite.config.ts +4 -0
- package/corpus/templates/clips/server/db/schema.ts +3 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +40 -2
- package/corpus/templates/clips/server/plugins/db.ts +5 -0
- package/corpus/templates/clips/shared/browser-diagnostics.ts +171 -0
- package/corpus/templates/content/.agents/skills/content/SKILL.md +4 -2
- package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +8 -1
- package/corpus/templates/content/AGENTS.md +5 -6
- package/corpus/templates/content/CHANGELOG.md +24 -0
- package/corpus/templates/content/actions/_content-database-row-migration.ts +67 -36
- package/corpus/templates/content/actions/_document-edit-mutation.ts +74 -23
- package/corpus/templates/content/actions/edit-document.ts +48 -8
- package/corpus/templates/content/actions/migrate-content-database-rows.ts +69 -28
- package/corpus/templates/content/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/design/CHANGELOG.md +22 -0
- package/corpus/templates/factory/CHANGELOG.md +11 -0
- package/corpus/templates/forms/CHANGELOG.md +6 -0
- package/corpus/templates/mail/.agents/skills/mail-interaction-parity/references/interaction-matrix.md +24 -4
- package/corpus/templates/mail/CHANGELOG.md +68 -0
- package/corpus/templates/mail/app/components/email/ComposeBubbleToolbar.tsx +8 -0
- package/corpus/templates/mail/app/components/email/ComposeModal.tsx +33 -13
- package/corpus/templates/mail/app/components/email/EmailListItem.tsx +23 -4
- package/corpus/templates/mail/app/components/email/EmailThread.tsx +56 -13
- package/corpus/templates/mail/app/components/email/InlineReplyComposer.tsx +23 -4
- package/corpus/templates/mail/app/components/email/RecipientInput.tsx +9 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +8 -1
- package/corpus/templates/mail/app/i18n/en-US.ts +31 -0
- package/corpus/templates/mail/changelog/2026-09-15-mail-labels-recipient-and-account-controls-for-keyboard-and-.md +6 -0
- package/corpus/templates/slides/CHANGELOG.md +32 -0
- package/dist/client/CommandMenu.js +14 -2
- package/dist/client/settings/AccountSettingsCard.js +3 -2
- package/dist/client/settings/SettingsTabsPage.js +9 -1
- package/dist/client/settings/agent-settings-search.js +5 -1
- package/dist/client/sign-out.d.ts +1 -0
- package/dist/client/sign-out.js +8 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/handlers.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +4 -4
|
@@ -21,7 +21,6 @@ import { useQueryClient } from "@tanstack/react-query";
|
|
|
21
21
|
import {
|
|
22
22
|
format,
|
|
23
23
|
startOfWeek,
|
|
24
|
-
endOfWeek,
|
|
25
24
|
addMonths,
|
|
26
25
|
subMonths,
|
|
27
26
|
addWeeks,
|
|
@@ -51,14 +50,25 @@ import { WeekView } from "@/components/calendar/WeekView";
|
|
|
51
50
|
import { useCalendarContext } from "@/components/layout/AppLayout";
|
|
52
51
|
import type { ViewMode } from "@/components/layout/AppLayout";
|
|
53
52
|
import { Button } from "@/components/ui/button";
|
|
53
|
+
import {
|
|
54
|
+
Dialog,
|
|
55
|
+
DialogContent,
|
|
56
|
+
DialogFooter,
|
|
57
|
+
DialogHeader,
|
|
58
|
+
DialogTitle,
|
|
59
|
+
} from "@/components/ui/dialog";
|
|
54
60
|
import {
|
|
55
61
|
DropdownMenu,
|
|
62
|
+
DropdownMenuCheckboxItem,
|
|
56
63
|
DropdownMenuContent,
|
|
57
64
|
DropdownMenuItem,
|
|
58
|
-
DropdownMenuLabel,
|
|
59
65
|
DropdownMenuSeparator,
|
|
66
|
+
DropdownMenuSub,
|
|
67
|
+
DropdownMenuSubContent,
|
|
68
|
+
DropdownMenuSubTrigger,
|
|
60
69
|
DropdownMenuTrigger,
|
|
61
70
|
} from "@/components/ui/dropdown-menu";
|
|
71
|
+
import { Input } from "@/components/ui/input";
|
|
62
72
|
import { Spinner } from "@/components/ui/spinner";
|
|
63
73
|
import {
|
|
64
74
|
Tooltip,
|
|
@@ -73,6 +83,7 @@ import {
|
|
|
73
83
|
useDeleteEvent,
|
|
74
84
|
useRsvpEvent,
|
|
75
85
|
findEventByCurrentOrReplacedId,
|
|
86
|
+
findVisibleSelectedEvent,
|
|
76
87
|
prefetchEvents,
|
|
77
88
|
shouldShowEventsSkeleton,
|
|
78
89
|
} from "@/hooks/use-events";
|
|
@@ -106,6 +117,13 @@ import {
|
|
|
106
117
|
moveEventToCalendarDate,
|
|
107
118
|
normalizeTimezone,
|
|
108
119
|
} from "@/lib/calendar-timezone";
|
|
120
|
+
import {
|
|
121
|
+
DEFAULT_CALENDAR_DAYS,
|
|
122
|
+
isEventVisibleForDeclinedPreference,
|
|
123
|
+
MAX_CALENDAR_DAYS,
|
|
124
|
+
MIN_CALENDAR_DAYS,
|
|
125
|
+
normalizeNumberOfDays,
|
|
126
|
+
} from "@/lib/calendar-view-preferences";
|
|
109
127
|
import { resolveEventAccountEmail } from "@/lib/event-account-selection";
|
|
110
128
|
import { getGoogleEventColorHex } from "@/lib/event-colors";
|
|
111
129
|
import {
|
|
@@ -443,6 +461,10 @@ export default function CalendarView() {
|
|
|
443
461
|
new Map(),
|
|
444
462
|
);
|
|
445
463
|
const [commandPaletteOpen, setCommandPaletteOpen] = useState(false);
|
|
464
|
+
const [customDaysOpen, setCustomDaysOpen] = useState(false);
|
|
465
|
+
const [customDaysInput, setCustomDaysInput] = useState(
|
|
466
|
+
String(DEFAULT_CALENDAR_DAYS),
|
|
467
|
+
);
|
|
446
468
|
const openCommandPalette = useCallback(() => {
|
|
447
469
|
if (commandPaletteOpen) return;
|
|
448
470
|
trackEvent("calendar_search_opened", {
|
|
@@ -586,8 +608,20 @@ export default function CalendarView() {
|
|
|
586
608
|
// timezone is only a temporary fallback while settings are loading.
|
|
587
609
|
const { from, to } = useMemo(
|
|
588
610
|
() =>
|
|
589
|
-
getViewDateRange(
|
|
590
|
-
|
|
611
|
+
getViewDateRange(
|
|
612
|
+
viewMode,
|
|
613
|
+
selectedDate,
|
|
614
|
+
displayTimezone,
|
|
615
|
+
weekStartsOn,
|
|
616
|
+
viewPrefs.numberOfDays,
|
|
617
|
+
),
|
|
618
|
+
[
|
|
619
|
+
displayTimezone,
|
|
620
|
+
selectedDate,
|
|
621
|
+
viewMode,
|
|
622
|
+
viewPrefs.numberOfDays,
|
|
623
|
+
weekStartsOn,
|
|
624
|
+
],
|
|
591
625
|
);
|
|
592
626
|
|
|
593
627
|
const {
|
|
@@ -646,12 +680,28 @@ export default function CalendarView() {
|
|
|
646
680
|
);
|
|
647
681
|
}
|
|
648
682
|
case "week": {
|
|
649
|
-
//
|
|
650
|
-
|
|
651
|
-
const
|
|
652
|
-
const
|
|
683
|
+
// Warm two displayed periods so rapid `j j` stays instant, plus one
|
|
684
|
+
// period back. A custom day count advances by that same count.
|
|
685
|
+
const step = normalizeNumberOfDays(viewPrefs.numberOfDays);
|
|
686
|
+
const currentPeriodStart =
|
|
687
|
+
step === 7
|
|
688
|
+
? dateKeyToDate(
|
|
689
|
+
dateToCalendarDateKey(
|
|
690
|
+
startOfWeek(selectedDate, { weekStartsOn }),
|
|
691
|
+
),
|
|
692
|
+
)
|
|
693
|
+
: selectedDate;
|
|
694
|
+
const next = addDays(currentPeriodStart, step);
|
|
695
|
+
const next2 = addDays(currentPeriodStart, step * 2);
|
|
696
|
+
const prev = subDays(currentPeriodStart, step);
|
|
653
697
|
return [next, next2, prev].map((date) =>
|
|
654
|
-
getViewDateRange(
|
|
698
|
+
getViewDateRange(
|
|
699
|
+
"week",
|
|
700
|
+
date,
|
|
701
|
+
displayTimezone,
|
|
702
|
+
weekStartsOn,
|
|
703
|
+
viewPrefs.numberOfDays,
|
|
704
|
+
),
|
|
655
705
|
);
|
|
656
706
|
}
|
|
657
707
|
case "day": {
|
|
@@ -680,6 +730,7 @@ export default function CalendarView() {
|
|
|
680
730
|
queryClient,
|
|
681
731
|
selectedDate,
|
|
682
732
|
viewMode,
|
|
733
|
+
viewPrefs.numberOfDays,
|
|
683
734
|
weekStartsOn,
|
|
684
735
|
]);
|
|
685
736
|
|
|
@@ -740,6 +791,14 @@ export default function CalendarView() {
|
|
|
740
791
|
) {
|
|
741
792
|
return false;
|
|
742
793
|
}
|
|
794
|
+
if (
|
|
795
|
+
!isEventVisibleForDeclinedPreference(
|
|
796
|
+
e.responseStatus,
|
|
797
|
+
viewPrefs.showDeclinedEvents,
|
|
798
|
+
)
|
|
799
|
+
) {
|
|
800
|
+
return false;
|
|
801
|
+
}
|
|
743
802
|
// Hide events from hidden external calendars
|
|
744
803
|
if (e.source === "ical") {
|
|
745
804
|
const hiddenMatch = hiddenCalendars.external.some((calId) =>
|
|
@@ -755,6 +814,7 @@ export default function CalendarView() {
|
|
|
755
814
|
overlayPeople,
|
|
756
815
|
hiddenCalendars,
|
|
757
816
|
quickEditTempIds,
|
|
817
|
+
viewPrefs.showDeclinedEvents,
|
|
758
818
|
viewPrefs.googleCalendarVisibility,
|
|
759
819
|
]);
|
|
760
820
|
|
|
@@ -1055,25 +1115,54 @@ export default function CalendarView() {
|
|
|
1055
1115
|
|
|
1056
1116
|
useEffect(() => {
|
|
1057
1117
|
if (sidebarEvent) {
|
|
1058
|
-
const rebound =
|
|
1059
|
-
|
|
1118
|
+
const rebound = findVisibleSelectedEvent(
|
|
1119
|
+
events,
|
|
1120
|
+
sidebarEvent,
|
|
1121
|
+
viewPrefs.showDeclinedEvents,
|
|
1122
|
+
);
|
|
1123
|
+
if (!rebound) setSidebarEvent(null);
|
|
1124
|
+
else if (rebound.id !== sidebarEvent.id) setSidebarEvent(rebound);
|
|
1060
1125
|
}
|
|
1061
1126
|
if (focusedEvent) {
|
|
1062
|
-
const rebound =
|
|
1063
|
-
|
|
1127
|
+
const rebound = findVisibleSelectedEvent(
|
|
1128
|
+
events,
|
|
1129
|
+
focusedEvent,
|
|
1130
|
+
viewPrefs.showDeclinedEvents,
|
|
1131
|
+
);
|
|
1132
|
+
if (!rebound) setFocusedEvent(null);
|
|
1133
|
+
else if (rebound.id !== focusedEvent.id) setFocusedEvent(rebound);
|
|
1064
1134
|
}
|
|
1065
|
-
}, [
|
|
1135
|
+
}, [
|
|
1136
|
+
events,
|
|
1137
|
+
focusedEvent,
|
|
1138
|
+
setFocusedEvent,
|
|
1139
|
+
setSidebarEvent,
|
|
1140
|
+
sidebarEvent,
|
|
1141
|
+
viewPrefs.showDeclinedEvents,
|
|
1142
|
+
]);
|
|
1066
1143
|
|
|
1067
1144
|
const selectedEvent = useMemo(() => {
|
|
1068
1145
|
const candidate = sidebarEvent ?? focusedEvent;
|
|
1069
1146
|
if (!candidate) return null;
|
|
1070
|
-
return
|
|
1071
|
-
|
|
1147
|
+
return (
|
|
1148
|
+
findVisibleSelectedEvent(
|
|
1149
|
+
events,
|
|
1150
|
+
candidate,
|
|
1151
|
+
viewPrefs.showDeclinedEvents,
|
|
1152
|
+
) ?? null
|
|
1153
|
+
);
|
|
1154
|
+
}, [events, sidebarEvent, focusedEvent, viewPrefs.showDeclinedEvents]);
|
|
1072
1155
|
|
|
1073
1156
|
const refreshedSidebarEvent = useMemo(() => {
|
|
1074
1157
|
if (!sidebarEvent) return null;
|
|
1075
|
-
return
|
|
1076
|
-
|
|
1158
|
+
return (
|
|
1159
|
+
findVisibleSelectedEvent(
|
|
1160
|
+
events,
|
|
1161
|
+
sidebarEvent,
|
|
1162
|
+
viewPrefs.showDeclinedEvents,
|
|
1163
|
+
) ?? null
|
|
1164
|
+
);
|
|
1165
|
+
}, [events, sidebarEvent, viewPrefs.showDeclinedEvents]);
|
|
1077
1166
|
|
|
1078
1167
|
function handleNavigate(direction: "prev" | "next") {
|
|
1079
1168
|
trackEvent("calendar_date_navigated", {
|
|
@@ -1083,7 +1172,13 @@ export default function CalendarView() {
|
|
|
1083
1172
|
view_type: viewMode,
|
|
1084
1173
|
});
|
|
1085
1174
|
setSelectedDate(
|
|
1086
|
-
navigateCalendarDate(
|
|
1175
|
+
navigateCalendarDate(
|
|
1176
|
+
viewMode,
|
|
1177
|
+
selectedDate,
|
|
1178
|
+
direction,
|
|
1179
|
+
weekStartsOn,
|
|
1180
|
+
viewPrefs.numberOfDays,
|
|
1181
|
+
),
|
|
1087
1182
|
);
|
|
1088
1183
|
}
|
|
1089
1184
|
|
|
@@ -1883,8 +1978,12 @@ export default function CalendarView() {
|
|
|
1883
1978
|
? format(selectedDate, "MMM yyyy")
|
|
1884
1979
|
: format(selectedDate, "MMMM yyyy");
|
|
1885
1980
|
case "week": {
|
|
1886
|
-
const
|
|
1887
|
-
const
|
|
1981
|
+
const displayedDays = normalizeNumberOfDays(viewPrefs.numberOfDays);
|
|
1982
|
+
const ws =
|
|
1983
|
+
displayedDays === 7
|
|
1984
|
+
? startOfWeek(selectedDate, { weekStartsOn })
|
|
1985
|
+
: selectedDate;
|
|
1986
|
+
const we = addDays(ws, displayedDays - 1);
|
|
1888
1987
|
return isMobile
|
|
1889
1988
|
? `${format(ws, "MMM d")} – ${format(we, "d")}`
|
|
1890
1989
|
: `${format(ws, "MMM d")} – ${format(we, "d, yyyy")}`;
|
|
@@ -1896,6 +1995,18 @@ export default function CalendarView() {
|
|
|
1896
1995
|
}
|
|
1897
1996
|
})();
|
|
1898
1997
|
|
|
1998
|
+
function applyCustomDays() {
|
|
1999
|
+
const value = Number(customDaysInput);
|
|
2000
|
+
if (!Number.isInteger(value)) return;
|
|
2001
|
+
setViewPrefs({
|
|
2002
|
+
numberOfDays: Math.min(
|
|
2003
|
+
MAX_CALENDAR_DAYS,
|
|
2004
|
+
Math.max(MIN_CALENDAR_DAYS, value),
|
|
2005
|
+
),
|
|
2006
|
+
});
|
|
2007
|
+
setCustomDaysOpen(false);
|
|
2008
|
+
}
|
|
2009
|
+
|
|
1899
2010
|
return (
|
|
1900
2011
|
<TooltipProvider delayDuration={500}>
|
|
1901
2012
|
<div className="flex h-full min-w-0">
|
|
@@ -1962,20 +2073,83 @@ export default function CalendarView() {
|
|
|
1962
2073
|
</kbd>
|
|
1963
2074
|
</DropdownMenuItem>
|
|
1964
2075
|
<DropdownMenuSeparator />
|
|
1965
|
-
<
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
2076
|
+
<DropdownMenuSub>
|
|
2077
|
+
<DropdownMenuSubTrigger>
|
|
2078
|
+
{t("calendarView.numberOfDays")}
|
|
2079
|
+
</DropdownMenuSubTrigger>
|
|
2080
|
+
<DropdownMenuSubContent>
|
|
2081
|
+
{Array.from({ length: 8 }, (_, index) => index + 2).map(
|
|
2082
|
+
(count) => (
|
|
2083
|
+
<DropdownMenuItem
|
|
2084
|
+
key={count}
|
|
2085
|
+
onSelect={() =>
|
|
2086
|
+
setViewPrefs({ numberOfDays: count })
|
|
2087
|
+
}
|
|
2088
|
+
>
|
|
2089
|
+
{t("calendarView.daysCount", { count })}
|
|
2090
|
+
{viewPrefs.numberOfDays === count && (
|
|
2091
|
+
<IconCheck className="ml-auto h-3.5 w-3.5 text-muted-foreground" />
|
|
2092
|
+
)}
|
|
2093
|
+
</DropdownMenuItem>
|
|
2094
|
+
),
|
|
2095
|
+
)}
|
|
2096
|
+
<DropdownMenuSeparator />
|
|
2097
|
+
<DropdownMenuItem
|
|
2098
|
+
onSelect={() => {
|
|
2099
|
+
setCustomDaysInput(String(viewPrefs.numberOfDays));
|
|
2100
|
+
setCustomDaysOpen(true);
|
|
2101
|
+
}}
|
|
2102
|
+
>
|
|
2103
|
+
{t("calendarView.other")}
|
|
2104
|
+
{!Array.from(
|
|
2105
|
+
{ length: 8 },
|
|
2106
|
+
(_, index) => index + 2,
|
|
2107
|
+
).includes(viewPrefs.numberOfDays) && (
|
|
2108
|
+
<IconCheck className="ml-auto h-3.5 w-3.5 text-muted-foreground" />
|
|
2109
|
+
)}
|
|
2110
|
+
</DropdownMenuItem>
|
|
2111
|
+
</DropdownMenuSubContent>
|
|
2112
|
+
</DropdownMenuSub>
|
|
2113
|
+
<DropdownMenuSub>
|
|
2114
|
+
<DropdownMenuSubTrigger>
|
|
2115
|
+
{t("calendarView.viewSettings")}
|
|
2116
|
+
</DropdownMenuSubTrigger>
|
|
2117
|
+
<DropdownMenuSubContent>
|
|
2118
|
+
<DropdownMenuCheckboxItem
|
|
2119
|
+
checked={!viewPrefs.hideWeekends}
|
|
2120
|
+
onCheckedChange={(checked) =>
|
|
2121
|
+
setViewPrefs({ hideWeekends: !checked })
|
|
2122
|
+
}
|
|
2123
|
+
>
|
|
2124
|
+
{t("calendarView.weekends")}
|
|
2125
|
+
</DropdownMenuCheckboxItem>
|
|
2126
|
+
<DropdownMenuCheckboxItem
|
|
2127
|
+
checked={viewPrefs.showDeclinedEvents}
|
|
2128
|
+
onCheckedChange={(checked) =>
|
|
2129
|
+
setViewPrefs({ showDeclinedEvents: checked })
|
|
2130
|
+
}
|
|
2131
|
+
>
|
|
2132
|
+
{t("calendarView.declinedEvents")}
|
|
2133
|
+
</DropdownMenuCheckboxItem>
|
|
2134
|
+
<DropdownMenuCheckboxItem
|
|
2135
|
+
checked={viewPrefs.showWeekNumbers}
|
|
2136
|
+
onCheckedChange={(checked) =>
|
|
2137
|
+
setViewPrefs({ showWeekNumbers: checked })
|
|
2138
|
+
}
|
|
2139
|
+
>
|
|
2140
|
+
{t("calendarView.weekNumbers")}
|
|
2141
|
+
</DropdownMenuCheckboxItem>
|
|
2142
|
+
<DropdownMenuSeparator />
|
|
2143
|
+
<DropdownMenuItem asChild>
|
|
2144
|
+
<Link
|
|
2145
|
+
to="/settings"
|
|
2146
|
+
className="flex w-full items-center"
|
|
2147
|
+
>
|
|
2148
|
+
{t("calendarView.generalSettings")}
|
|
2149
|
+
</Link>
|
|
2150
|
+
</DropdownMenuItem>
|
|
2151
|
+
</DropdownMenuSubContent>
|
|
2152
|
+
</DropdownMenuSub>
|
|
1979
2153
|
</DropdownMenuContent>
|
|
1980
2154
|
</DropdownMenu>
|
|
1981
2155
|
</div>
|
|
@@ -2116,6 +2290,7 @@ export default function CalendarView() {
|
|
|
2116
2290
|
onDraftDiscard={discardDraftEvent}
|
|
2117
2291
|
isLoading={eventsLoading}
|
|
2118
2292
|
weekStartsOn={weekStartsOn}
|
|
2293
|
+
numberOfDays={viewPrefs.numberOfDays}
|
|
2119
2294
|
/>
|
|
2120
2295
|
)}
|
|
2121
2296
|
{viewMode === "day" && (
|
|
@@ -2265,6 +2440,41 @@ export default function CalendarView() {
|
|
|
2265
2440
|
}}
|
|
2266
2441
|
/>
|
|
2267
2442
|
{guestNotificationDialog}
|
|
2443
|
+
<Dialog open={customDaysOpen} onOpenChange={setCustomDaysOpen}>
|
|
2444
|
+
<DialogContent className="sm:max-w-[320px]">
|
|
2445
|
+
<DialogHeader>
|
|
2446
|
+
<DialogTitle>{t("calendarView.numberOfDays")}</DialogTitle>
|
|
2447
|
+
</DialogHeader>
|
|
2448
|
+
<form
|
|
2449
|
+
className="grid gap-4"
|
|
2450
|
+
onSubmit={(event) => {
|
|
2451
|
+
event.preventDefault();
|
|
2452
|
+
applyCustomDays();
|
|
2453
|
+
}}
|
|
2454
|
+
>
|
|
2455
|
+
<Input
|
|
2456
|
+
type="number"
|
|
2457
|
+
min={MIN_CALENDAR_DAYS}
|
|
2458
|
+
max={MAX_CALENDAR_DAYS}
|
|
2459
|
+
step={1}
|
|
2460
|
+
value={customDaysInput}
|
|
2461
|
+
onChange={(event) => setCustomDaysInput(event.target.value)}
|
|
2462
|
+
autoFocus
|
|
2463
|
+
aria-label={t("calendarView.numberOfDays")}
|
|
2464
|
+
/>
|
|
2465
|
+
<DialogFooter>
|
|
2466
|
+
<Button
|
|
2467
|
+
type="button"
|
|
2468
|
+
variant="outline"
|
|
2469
|
+
onClick={() => setCustomDaysOpen(false)}
|
|
2470
|
+
>
|
|
2471
|
+
{t("eventForm.cancel")}
|
|
2472
|
+
</Button>
|
|
2473
|
+
<Button type="submit">{t("eventForm.save")}</Button>
|
|
2474
|
+
</DialogFooter>
|
|
2475
|
+
</form>
|
|
2476
|
+
</DialogContent>
|
|
2477
|
+
</Dialog>
|
|
2268
2478
|
</div>
|
|
2269
2479
|
</TooltipProvider>
|
|
2270
2480
|
);
|
|
@@ -16,11 +16,21 @@ export const CALENDAR_COLORS = [
|
|
|
16
16
|
|
|
17
17
|
export type CalendarColorMode = "multi" | "single";
|
|
18
18
|
|
|
19
|
+
export const MIN_CALENDAR_DAYS = 1;
|
|
20
|
+
export const MAX_CALENDAR_DAYS = 31;
|
|
21
|
+
export const DEFAULT_CALENDAR_DAYS = 7;
|
|
22
|
+
|
|
19
23
|
/** Account-scoped key: a Google account email, or `"ics:<externalCalendarId>"`. */
|
|
20
24
|
export type CalendarColorSourceKey = string;
|
|
21
25
|
|
|
22
26
|
export interface CalendarViewPreferences {
|
|
23
27
|
hideWeekends: boolean;
|
|
28
|
+
/** Number of days shown by the week-style calendar view. */
|
|
29
|
+
numberOfDays: number;
|
|
30
|
+
/** Whether events declined by the current account remain visible. */
|
|
31
|
+
showDeclinedEvents: boolean;
|
|
32
|
+
/** Whether month view reserves a leading column for week numbers. */
|
|
33
|
+
showWeekNumbers: boolean;
|
|
24
34
|
/** @deprecated kept for back-compat migration; use accountColorModes */
|
|
25
35
|
colorMode: CalendarColorMode;
|
|
26
36
|
/** @deprecated kept for back-compat migration; use accountColors */
|
|
@@ -37,6 +47,9 @@ export interface CalendarViewPreferences {
|
|
|
37
47
|
|
|
38
48
|
export const DEFAULT_CALENDAR_VIEW_PREFERENCES: CalendarViewPreferences = {
|
|
39
49
|
hideWeekends: false,
|
|
50
|
+
numberOfDays: DEFAULT_CALENDAR_DAYS,
|
|
51
|
+
showDeclinedEvents: true,
|
|
52
|
+
showWeekNumbers: false,
|
|
40
53
|
colorMode: "multi",
|
|
41
54
|
singleColor: CALENDAR_COLORS[0],
|
|
42
55
|
accountColorModes: {},
|
|
@@ -45,6 +58,19 @@ export const DEFAULT_CALENDAR_VIEW_PREFERENCES: CalendarViewPreferences = {
|
|
|
45
58
|
googleCalendarColors: {},
|
|
46
59
|
};
|
|
47
60
|
|
|
61
|
+
export function normalizeNumberOfDays(value: unknown): number {
|
|
62
|
+
return typeof value === "number" && Number.isInteger(value)
|
|
63
|
+
? Math.min(MAX_CALENDAR_DAYS, Math.max(MIN_CALENDAR_DAYS, value))
|
|
64
|
+
: DEFAULT_CALENDAR_DAYS;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function isEventVisibleForDeclinedPreference(
|
|
68
|
+
responseStatus: string | undefined,
|
|
69
|
+
showDeclinedEvents: boolean,
|
|
70
|
+
): boolean {
|
|
71
|
+
return showDeclinedEvents || responseStatus !== "declined";
|
|
72
|
+
}
|
|
73
|
+
|
|
48
74
|
export function isValidCalendarColorMode(
|
|
49
75
|
value: unknown,
|
|
50
76
|
): value is CalendarColorMode {
|
|
@@ -114,6 +140,13 @@ export function normalizeCalendarViewPreferences(
|
|
|
114
140
|
if (typeof input.hideWeekends === "boolean") {
|
|
115
141
|
next.hideWeekends = input.hideWeekends;
|
|
116
142
|
}
|
|
143
|
+
next.numberOfDays = normalizeNumberOfDays(input.numberOfDays);
|
|
144
|
+
if (typeof input.showDeclinedEvents === "boolean") {
|
|
145
|
+
next.showDeclinedEvents = input.showDeclinedEvents;
|
|
146
|
+
}
|
|
147
|
+
if (typeof input.showWeekNumbers === "boolean") {
|
|
148
|
+
next.showWeekNumbers = input.showWeekNumbers;
|
|
149
|
+
}
|
|
117
150
|
if (isValidCalendarColorMode(input.colorMode)) {
|
|
118
151
|
next.colorMode = input.colorMode;
|
|
119
152
|
}
|
|
@@ -135,6 +168,9 @@ export function calendarViewPreferencesEqual(
|
|
|
135
168
|
): boolean {
|
|
136
169
|
return (
|
|
137
170
|
a.hideWeekends === b.hideWeekends &&
|
|
171
|
+
a.numberOfDays === b.numberOfDays &&
|
|
172
|
+
a.showDeclinedEvents === b.showDeclinedEvents &&
|
|
173
|
+
a.showWeekNumbers === b.showWeekNumbers &&
|
|
138
174
|
a.colorMode === b.colorMode &&
|
|
139
175
|
a.singleColor === b.singleColor &&
|
|
140
176
|
recordsEqual(a.accountColorModes, b.accountColorModes) &&
|
|
@@ -138,6 +138,7 @@ export function getCalendarViewDateRange(
|
|
|
138
138
|
selectedDate: string,
|
|
139
139
|
timezone: string,
|
|
140
140
|
weekStartsOn: 0 | 1 = 0,
|
|
141
|
+
numberOfDays = 7,
|
|
141
142
|
): { from: string; to: string } {
|
|
142
143
|
const selectedMonthStart = `${selectedDate.slice(0, 7)}-01`;
|
|
143
144
|
const [year, month] = selectedMonthStart.split("-").map(Number);
|
|
@@ -148,8 +149,14 @@ export function getCalendarViewDateRange(
|
|
|
148
149
|
let rangeStart = selectedDate;
|
|
149
150
|
let rangeEndExclusive = addDaysToDateKey(selectedDate, 1);
|
|
150
151
|
if (viewMode === "week") {
|
|
151
|
-
|
|
152
|
-
|
|
152
|
+
const displayedDays = Number.isInteger(numberOfDays)
|
|
153
|
+
? Math.min(31, Math.max(1, numberOfDays))
|
|
154
|
+
: 7;
|
|
155
|
+
rangeStart =
|
|
156
|
+
displayedDays === 7
|
|
157
|
+
? startOfCalendarWeek(selectedDate, weekStartsOn)
|
|
158
|
+
: selectedDate;
|
|
159
|
+
rangeEndExclusive = addDaysToDateKey(rangeStart, displayedDays);
|
|
153
160
|
} else if (viewMode === "month") {
|
|
154
161
|
const monthEnd = addDaysToDateKey(nextMonthStart, -1);
|
|
155
162
|
rangeStart = startOfCalendarWeek(selectedMonthStart, weekStartsOn);
|
|
@@ -228,6 +228,8 @@ temporary agent-link path:
|
|
|
228
228
|
raw provider URLs.
|
|
229
229
|
|
|
230
230
|
Public agent context also exposes the recording's redacted browser diagnostics:
|
|
231
|
+
the bounded relative event sequence as `browserDiagnostics.timeline`, including
|
|
232
|
+
navigation, click/input targets, console events, and request/response markers;
|
|
231
233
|
the console stream (all levels) as `browserDiagnostics.consoleLogs` and the
|
|
232
234
|
fetch/XHR stream as `browserDiagnostics.networkRequests` (method, sanitized URL
|
|
233
235
|
with query values redacted, status, duration), plus `consoleIssues` and
|
|
@@ -3,6 +3,25 @@
|
|
|
3
3
|
All notable user-facing changes to Clips are documented here. Open it any time
|
|
4
4
|
from the command menu (Cmd+K → "What's new") or from Settings.
|
|
5
5
|
|
|
6
|
+
## 2026-09-15
|
|
7
|
+
|
|
8
|
+
### Improved
|
|
9
|
+
|
|
10
|
+
- Trash now supports paging through more than 100 deleted recordings
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Fixed the volume slider knob alignment in shared recordings
|
|
15
|
+
- Shared Clips now focus the agent when asked, show clear viewer-safe transcript states, and keep workspace branding visible.
|
|
16
|
+
|
|
17
|
+
## 2026-09-14
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Comment edits and reactions stay consistent during rapid updates.
|
|
22
|
+
- Comment threads keep overlapping replies, reactions, and deletions consistent.
|
|
23
|
+
- Selected recording checkboxes remain visible while selecting multiple clips
|
|
24
|
+
|
|
6
25
|
## 2026-09-13
|
|
7
26
|
|
|
8
27
|
### Improved
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Save redacted browser diagnostics captured during a recording session.
|
|
3
3
|
*
|
|
4
4
|
* Called by the recorder UI after stop/finalize. Diagnostics are intentionally
|
|
5
|
-
* bounded and body/header-free: console text plus
|
|
6
|
-
* for fetch/XHR requests.
|
|
5
|
+
* bounded and body/header-free: interaction markers, console text, plus
|
|
6
|
+
* method/path/status/duration for fetch/XHR requests.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { defineAction } from "@agent-native/core/action";
|
|
@@ -16,15 +16,18 @@ import { getDb, schema } from "../server/db/index.js";
|
|
|
16
16
|
import { nanoid } from "../server/lib/recordings.js";
|
|
17
17
|
import {
|
|
18
18
|
MAX_BROWSER_DIAGNOSTIC_CONSOLE_LOGS,
|
|
19
|
+
MAX_BROWSER_DIAGNOSTIC_INTERACTION_EVENTS,
|
|
19
20
|
MAX_BROWSER_DIAGNOSTIC_MESSAGE_LENGTH,
|
|
20
21
|
MAX_BROWSER_DIAGNOSTIC_NETWORK_REQUESTS,
|
|
22
|
+
MAX_BROWSER_DIAGNOSTIC_TARGET_LENGTH,
|
|
21
23
|
MAX_BROWSER_DIAGNOSTIC_URL_LENGTH,
|
|
22
24
|
redactBrowserDiagnosticString,
|
|
25
|
+
sanitizeBrowserDiagnosticNavigationUrl,
|
|
23
26
|
summarizeBrowserDiagnostics,
|
|
24
27
|
type BrowserDiagnosticConsoleLevel,
|
|
25
28
|
} from "../shared/browser-diagnostics.js";
|
|
26
29
|
|
|
27
|
-
const REDACTION_VERSION =
|
|
30
|
+
const REDACTION_VERSION = 3;
|
|
28
31
|
|
|
29
32
|
const consoleLevelSchema = z.enum(["debug", "log", "info", "warn", "error"]);
|
|
30
33
|
|
|
@@ -49,6 +52,14 @@ const networkRequestSchema = z.object({
|
|
|
49
52
|
error: z.string().max(20_000).optional(),
|
|
50
53
|
});
|
|
51
54
|
|
|
55
|
+
const interactionEventSchema = z.object({
|
|
56
|
+
timestampMs: z.number().finite().nonnegative(),
|
|
57
|
+
elapsedMs: z.number().finite().nonnegative(),
|
|
58
|
+
kind: z.enum(["navigation", "click", "input", "scroll"]),
|
|
59
|
+
target: z.string().max(MAX_BROWSER_DIAGNOSTIC_TARGET_LENGTH).optional(),
|
|
60
|
+
url: z.string().max(8_000).optional(),
|
|
61
|
+
});
|
|
62
|
+
|
|
52
63
|
function truncate(value: string, maxLength: number): string {
|
|
53
64
|
return value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
|
|
54
65
|
}
|
|
@@ -141,9 +152,29 @@ function sanitizeNetworkRequest(entry: z.infer<typeof networkRequestSchema>) {
|
|
|
141
152
|
};
|
|
142
153
|
}
|
|
143
154
|
|
|
155
|
+
function sanitizeInteractionEvent(
|
|
156
|
+
entry: z.infer<typeof interactionEventSchema>,
|
|
157
|
+
) {
|
|
158
|
+
const target = entry.target
|
|
159
|
+
? truncate(
|
|
160
|
+
redactString(entry.target, { redactQueryValues: true }),
|
|
161
|
+
MAX_BROWSER_DIAGNOSTIC_TARGET_LENGTH,
|
|
162
|
+
)
|
|
163
|
+
: "";
|
|
164
|
+
return {
|
|
165
|
+
timestampMs: Math.round(entry.timestampMs),
|
|
166
|
+
elapsedMs: Math.round(entry.elapsedMs),
|
|
167
|
+
kind: entry.kind,
|
|
168
|
+
...(target ? { target } : {}),
|
|
169
|
+
...(entry.url
|
|
170
|
+
? { url: sanitizeBrowserDiagnosticNavigationUrl(entry.url) }
|
|
171
|
+
: {}),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
144
175
|
export default defineAction({
|
|
145
176
|
description:
|
|
146
|
-
"Save redacted console and network diagnostics captured during a Clips recording session. UI/internal use only.",
|
|
177
|
+
"Save redacted browser timeline, console, and network diagnostics captured during a Clips recording session. UI/internal use only.",
|
|
147
178
|
agentTool: false,
|
|
148
179
|
schema: z.object({
|
|
149
180
|
recordingId: z.string().describe("Recording ID"),
|
|
@@ -164,6 +195,10 @@ export default defineAction({
|
|
|
164
195
|
.array(networkRequestSchema)
|
|
165
196
|
.max(MAX_BROWSER_DIAGNOSTIC_NETWORK_REQUESTS)
|
|
166
197
|
.default([]),
|
|
198
|
+
interactionEvents: z
|
|
199
|
+
.array(interactionEventSchema)
|
|
200
|
+
.max(MAX_BROWSER_DIAGNOSTIC_INTERACTION_EVENTS)
|
|
201
|
+
.default([]),
|
|
167
202
|
}),
|
|
168
203
|
run: async (args) => {
|
|
169
204
|
const access = await assertAccess("recording", args.recordingId, "editor");
|
|
@@ -178,6 +213,9 @@ export default defineAction({
|
|
|
178
213
|
const networkRequests = args.networkRequests
|
|
179
214
|
.slice(-MAX_BROWSER_DIAGNOSTIC_NETWORK_REQUESTS)
|
|
180
215
|
.map(sanitizeNetworkRequest);
|
|
216
|
+
const interactionEvents = args.interactionEvents
|
|
217
|
+
.slice(-MAX_BROWSER_DIAGNOSTIC_INTERACTION_EVENTS)
|
|
218
|
+
.map(sanitizeInteractionEvent);
|
|
181
219
|
const summary = summarizeBrowserDiagnostics({
|
|
182
220
|
consoleLogs,
|
|
183
221
|
networkRequests,
|
|
@@ -199,6 +237,7 @@ export default defineAction({
|
|
|
199
237
|
endedAt,
|
|
200
238
|
consoleLogsJson: JSON.stringify(consoleLogs),
|
|
201
239
|
networkRequestsJson: JSON.stringify(networkRequests),
|
|
240
|
+
interactionEventsJson: JSON.stringify(interactionEvents),
|
|
202
241
|
redactionVersion: REDACTION_VERSION,
|
|
203
242
|
updatedAt: now,
|
|
204
243
|
};
|