@agent-native/core 0.159.1 → 0.159.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.
Files changed (38) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +11 -6
  3. package/corpus/templates/clips/AGENTS.md +1 -0
  4. package/corpus/templates/clips/actions/lib/meeting-content.ts +15 -4
  5. package/corpus/templates/clips/actions/list-meetings.ts +179 -42
  6. package/corpus/templates/clips/actions/search-meetings.ts +277 -0
  7. package/corpus/templates/clips/app/components/meetings/agenda-card.tsx +273 -0
  8. package/corpus/templates/clips/app/components/meetings/day-grouped-card.tsx +113 -0
  9. package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +117 -0
  10. package/corpus/templates/clips/app/hooks/use-navigation-state.ts +12 -2
  11. package/corpus/templates/clips/app/i18n/en-US.ts +7 -2
  12. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +263 -357
  13. package/corpus/templates/clips/changelog/2026-08-14-meetings-history-is-searchable-again.md +6 -0
  14. package/corpus/templates/clips/desktop/design-refs/granola-ux.md +17 -0
  15. package/corpus/templates/content/actions/_database-source-utils.ts +29 -2
  16. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +11 -11
  17. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +11 -50
  18. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +57 -20
  19. package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +30 -0
  20. package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +204 -51
  21. package/corpus/templates/content/app/global.css +4 -1
  22. package/corpus/templates/content/app/i18n-data.ts +30 -0
  23. package/corpus/templates/content/changelog/2026-08-12-toggle-blocks-now-follow-notion-style-enter-and-shift-tab-be.md +6 -0
  24. package/corpus/templates/content/docs/solutions/2026-08-12-toggle-summary-focus-persistence-shape.md +733 -0
  25. package/corpus/templates/content/shared/builder-mdx.ts +44 -4
  26. package/corpus/templates/slides/actions/get-layout-overflows.ts +65 -2
  27. package/dist/deploy/build.d.ts +6 -4
  28. package/dist/deploy/build.js +27 -11
  29. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  30. package/dist/notifications/routes.d.ts +3 -3
  31. package/dist/observability/routes.d.ts +6 -6
  32. package/dist/secrets/routes.d.ts +3 -3
  33. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  34. package/dist/server/embed-route.js +6 -1
  35. package/dist/server/embed-session.d.ts +4 -1
  36. package/dist/server/embed-session.js +40 -1
  37. package/package.json +2 -2
  38. package/corpus/templates/clips/app/components/meetings/meeting-card.tsx +0 -333
@@ -0,0 +1,117 @@
1
+ /**
2
+ * <MeetingHistoryRow /> — one past meeting, one line.
3
+ *
4
+ * Granola renders history as Apple-Notes-style rows: attendee avatars, title,
5
+ * who was on the call, time. No card border, no summary preview, no
6
+ * status pills — see `desktop/design-refs/granola-ux.md` §2. Status badges on
7
+ * every row read as noise at list scale; the meeting detail page is where
8
+ * transcript/notes state belongs.
9
+ *
10
+ * `snippet` replaces the attendee subtitle in search results, where the reason
11
+ * a row matched is the only thing worth reading.
12
+ */
13
+ import { useSession } from "@agent-native/core/client/hooks";
14
+ import { useT } from "@agent-native/core/client/i18n";
15
+ import { IconFileText } from "@tabler/icons-react";
16
+ import { NavLink } from "react-router";
17
+
18
+ import { AttendeeStack, type AttendeeStackParticipant } from "./attendee-stack";
19
+
20
+ export interface MeetingHistoryItem {
21
+ id: string;
22
+ title: string;
23
+ scheduledStart?: string | null;
24
+ scheduledEnd?: string | null;
25
+ actualStart?: string | null;
26
+ actualEnd?: string | null;
27
+ createdAt?: string | null;
28
+ participants?: AttendeeStackParticipant[];
29
+ }
30
+
31
+ function formatTime(iso?: string | null): string {
32
+ if (!iso) return "";
33
+ const d = new Date(iso);
34
+ if (Number.isNaN(d.getTime())) return "";
35
+ return d.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
36
+ }
37
+
38
+ /**
39
+ * "Elaine" · "Lisa, Cody & 2 others" — Granola's attendee subtitle.
40
+ *
41
+ * The viewer is dropped: the subtitle answers "who was I with", and repeating
42
+ * the reader's own name down every row of their own history says nothing. A
43
+ * solo note keeps an empty subtitle rather than rendering just the viewer.
44
+ */
45
+ export function formatParticipantNames(
46
+ participants: AttendeeStackParticipant[],
47
+ viewerEmail?: string | null,
48
+ ): string {
49
+ const viewer = viewerEmail?.trim().toLowerCase();
50
+ const names = participants
51
+ .filter((p) => !viewer || p.email?.trim().toLowerCase() !== viewer)
52
+ .map((p) => p.name?.trim() || p.email?.trim().replace(/@.*$/, "") || "")
53
+ .filter(Boolean);
54
+ if (names.length === 0) return "";
55
+ if (names.length <= 2) return names.join(", ");
56
+ return `${names.slice(0, 2).join(", ")} & ${names.length - 2} others`;
57
+ }
58
+
59
+ export function MeetingHistoryRow({
60
+ meeting,
61
+ snippet,
62
+ }: {
63
+ meeting: MeetingHistoryItem;
64
+ snippet?: string | null;
65
+ }) {
66
+ const t = useT();
67
+ const { session } = useSession();
68
+ const participants = meeting.participants ?? [];
69
+ const subtitle =
70
+ snippet?.trim() || formatParticipantNames(participants, session?.email);
71
+ const time = formatTime(
72
+ meeting.actualStart ?? meeting.scheduledStart ?? meeting.createdAt,
73
+ );
74
+
75
+ return (
76
+ <NavLink
77
+ to={`/meetings/${meeting.id}`}
78
+ className="group flex items-center gap-3 rounded-md px-2 py-2 transition-colors hover:bg-accent/40 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring"
79
+ >
80
+ {participants.length > 0 ? (
81
+ <AttendeeStack participants={participants} size="md" max={2} />
82
+ ) : (
83
+ <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground">
84
+ <IconFileText className="h-3.5 w-3.5" />
85
+ </span>
86
+ )}
87
+ <div className="min-w-0 flex-1">
88
+ <div className="truncate text-sm text-foreground">
89
+ {meeting.title || t("meetingDetail.untitledMeeting")}
90
+ </div>
91
+ {subtitle ? (
92
+ <div className="truncate text-xs text-muted-foreground">
93
+ {subtitle}
94
+ </div>
95
+ ) : null}
96
+ </div>
97
+ {time ? (
98
+ <span className="shrink-0 text-xs tabular-nums text-muted-foreground">
99
+ {time}
100
+ </span>
101
+ ) : null}
102
+ </NavLink>
103
+ );
104
+ }
105
+
106
+ export function MeetingHistoryRowSkeleton() {
107
+ return (
108
+ <div className="flex items-center gap-3 px-2 py-2">
109
+ <div className="h-7 w-7 shrink-0 animate-pulse rounded-md bg-muted" />
110
+ <div className="min-w-0 flex-1 space-y-1.5">
111
+ <div className="h-3.5 w-2/5 animate-pulse rounded bg-muted" />
112
+ <div className="h-3 w-24 animate-pulse rounded bg-muted/70" />
113
+ </div>
114
+ <div className="h-3 w-12 animate-pulse rounded bg-muted/70" />
115
+ </div>
116
+ );
117
+ }
@@ -30,6 +30,7 @@ export interface NavigationState {
30
30
  search?: string;
31
31
  path?: string;
32
32
  meetingId?: string;
33
+ meetingsTab?: "agenda" | "past";
33
34
  dictationId?: string;
34
35
  }
35
36
 
@@ -60,6 +61,9 @@ interface NavigateCommand extends Partial<NavigationState> {
60
61
  * /embed/:shareId -> embed
61
62
  * /notifications -> notifications
62
63
  * /settings[/*] -> settings
64
+ * /meetings -> meetings (meetingsTab: agenda)
65
+ * /meetings?tab=past -> meetings (meetingsTab: past)
66
+ * /meetings/:meetingId -> meeting
63
67
  */
64
68
  export function stateFromLocation(
65
69
  pathname: string,
@@ -110,7 +114,13 @@ export function stateFromLocation(
110
114
  if (meetingMatch[1]) {
111
115
  return { view: "meeting", meetingId: meetingMatch[1] };
112
116
  }
113
- return { view: "meetings" };
117
+ // ?tab= is absent on the default Agenda tab, so report it explicitly
118
+ // rather than leaving the agent to infer which list the user is looking at.
119
+ return {
120
+ view: "meetings",
121
+ meetingsTab: params.get("tab") === "past" ? "past" : "agenda",
122
+ ...(searchTerm ? { search: searchTerm } : {}),
123
+ };
114
124
  }
115
125
 
116
126
  // /dictate (optionally /dictate/:dictationId in the future)
@@ -185,7 +195,7 @@ export function pathFromCommand(cmd: NavigateCommand): string {
185
195
  case "settings":
186
196
  return "/settings";
187
197
  case "meetings":
188
- return "/meetings";
198
+ return cmd.meetingsTab === "past" ? "/meetings?tab=past" : "/meetings";
189
199
  case "meeting":
190
200
  return cmd.meetingId ? `/meetings/${cmd.meetingId}` : "/meetings";
191
201
  case "dictate":
@@ -1580,7 +1580,6 @@ All notable user-facing changes to Clips are documented here. Open it any time f
1580
1580
  transcriptPending: "Transcript pending",
1581
1581
  notesPending: "Notes pending",
1582
1582
  pastRecordings: "Past recordings",
1583
- loadOlder: "Load older",
1584
1583
  calendarNeedsReconnect:
1585
1584
  "Google Calendar needs to be reconnected to keep showing your upcoming meetings.",
1586
1585
  connectGoogleCalendar: "Connect Google Calendar",
@@ -1607,7 +1606,13 @@ All notable user-facing changes to Clips are documented here. Open it any time f
1607
1606
  title: "Meetings",
1608
1607
  intro:
1609
1608
  "Upcoming calendar meetings and your recorded notes. Start live notes from Clips Desktop at meeting time.",
1610
- searchPlaceholder: "Search meetings...",
1609
+ agendaTab: "Agenda",
1610
+ pastTab: "Past",
1611
+ now: "Now",
1612
+ noPastMeetings: "No past meetings yet",
1613
+ loadOlder: "Load older",
1614
+ searchFailed: "Couldn't search meetings. Try again in a moment.",
1615
+ searchPlaceholder: "Search meetings, attendees, and transcripts...",
1611
1616
  clearSearch: "Clear search",
1612
1617
  noMeetingsYet: "No meetings yet",
1613
1618
  noMeetingsDescription: