@agent-native/core-corpus 0.217.0 → 0.219.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.
Files changed (81) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/hubspot/SKILL.md +5 -3
  3. package/corpus/templates/analytics/CHANGELOG.md +2 -0
  4. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +38 -167
  5. package/corpus/templates/analytics/changelog/2026-10-16-owned-and-shared-chats-appear-in-separate-history-sections.md +6 -0
  6. package/corpus/templates/assets/CHANGELOG.md +6 -0
  7. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +51 -117
  8. package/corpus/templates/assets/changelog/2026-10-16-owned-and-shared-chats-appear-in-separate-history-sections.md +6 -0
  9. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +34 -101
  10. package/corpus/templates/brain/app/routes/sources.tsx +1 -1
  11. package/corpus/templates/brain/vitest.config.ts +7 -0
  12. package/corpus/templates/calendar/CHANGELOG.md +6 -0
  13. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +1 -1
  14. package/corpus/templates/calendar/changelog/2026-10-16-booking-links-show-localized-visibility-badges.md +6 -0
  15. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +62 -101
  16. package/corpus/templates/clips/CHANGELOG.md +7 -20
  17. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +20 -77
  18. package/corpus/templates/clips/app/components/player/share-dialog.tsx +63 -90
  19. package/corpus/templates/clips/app/components/sharing/share-test-support.tsx +180 -0
  20. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +5 -584
  21. package/corpus/templates/clips/changelog/2026-10-16-share-dialogs-make-it-easier-to-see-who-has-access-and-manag.md +6 -0
  22. package/corpus/templates/clips/changelog/2026-10-21-share-panels-describe-general-access-in-a-sentence.md +6 -0
  23. package/corpus/templates/community/qr/package.json +1 -1
  24. package/corpus/templates/content/CHANGELOG.md +7 -0
  25. package/corpus/templates/content/app/components/editor/CommentStack.tsx +301 -0
  26. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +770 -179
  27. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +75 -27
  28. package/corpus/templates/content/app/components/editor/SuggestionText.tsx +18 -3
  29. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +89 -22
  30. package/corpus/templates/content/app/components/editor/block-field-comment-threads.ts +15 -0
  31. package/corpus/templates/content/app/components/editor/block-field-comments.tsx +5 -9
  32. package/corpus/templates/content/app/components/editor/comment-stacks.ts +143 -0
  33. package/corpus/templates/content/app/components/editor/extensions/SuggestionHighlight.ts +383 -34
  34. package/corpus/templates/content/app/components/editor/suggestions/draft-session.ts +31 -0
  35. package/corpus/templates/content/app/components/editor/suggestions/presentation-rebase.ts +82 -4
  36. package/corpus/templates/content/app/global.css +31 -0
  37. package/corpus/templates/content/app/i18n-data.ts +8 -0
  38. package/corpus/templates/content/changelog/2026-10-16-accepting-a-suggestion-on-a-page-that-changed-since-it-was-s.md +6 -0
  39. package/corpus/templates/content/changelog/2026-10-20-suggested-edits-that-add-remove-split-or-merge-paragraphs-li.md +6 -0
  40. package/corpus/templates/content/changelog/2026-10-22-blocks-with-several-comment-threads-fold-into-one-stack-in-t.md +6 -0
  41. package/corpus/templates/content/changelog/2026-10-22-opening-a-page-no-longer-saves-an-edit-again-after-another-o.md +6 -0
  42. package/corpus/templates/content/docs/product/capabilities/content.comment.page-owned.md +8 -1
  43. package/corpus/templates/content/shared/suggestion-diff.ts +23 -6
  44. package/corpus/templates/content/shared/suggestion-formatting.ts +44 -14
  45. package/corpus/templates/content/shared/suggestion-text.ts +20 -5
  46. package/corpus/templates/design/.generated/bridge/interact-links.generated.ts +8 -8
  47. package/corpus/templates/design/CHANGELOG.md +8 -0
  48. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +18 -1
  49. package/corpus/templates/design/app/components/design/bridge/interact-links.bridge.ts +8 -8
  50. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +15 -13
  51. package/corpus/templates/design/app/i18n/en-US.ts +1 -1
  52. package/corpus/templates/design/app/pages/DesignSystems.tsx +1 -1
  53. package/corpus/templates/design/app/pages/Index.tsx +18 -64
  54. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-modes.ts +15 -6
  55. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-screen-rendering.tsx +29 -5
  56. package/corpus/templates/design/app/pages/design-editor/prototype-navigation-transition.ts +423 -0
  57. package/corpus/templates/design/app/pages/design-editor/view/single-screen-canvas.tsx +35 -9
  58. package/corpus/templates/design/changelog/2026-10-16-design-pages-use-localized-visibility-badges-and-a-shared-ow.md +6 -0
  59. package/corpus/templates/design/changelog/2026-10-20-the-design-full-app-toggle-on-the-home-page-no-longer-hides-.md +6 -0
  60. package/corpus/templates/design/changelog/2026-10-22-prototype-links-can-play-code-authored-screen-transitions.md +6 -0
  61. package/corpus/templates/design/shared/motion-authored-css-import.ts +938 -7
  62. package/corpus/templates/design/shared/motion-html-source.ts +1689 -135
  63. package/corpus/templates/design/shared/motion-prototype-transition.ts +329 -0
  64. package/corpus/templates/design/shared/motion-react-source.ts +2154 -126
  65. package/corpus/templates/design/shared/motion-text-runtime-v1.fixture.txt +221 -0
  66. package/corpus/templates/dispatch/CHANGELOG.md +4 -0
  67. package/corpus/templates/dispatch/app/i18n-data.ts +75 -0
  68. package/corpus/templates/dispatch/changelog/2026-10-21-owned-and-shared-chats-appear-in-separate-history-sections.md +6 -0
  69. package/corpus/templates/factory/app/components/layout/Sidebar.tsx +34 -100
  70. package/corpus/templates/forms/app/pages/FormsListPage.tsx +1 -1
  71. package/corpus/templates/plan/CHANGELOG.md +6 -0
  72. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +34 -109
  73. package/corpus/templates/plan/changelog/2026-10-16-owned-and-shared-chats-appear-in-separate-history-sections.md +6 -0
  74. package/corpus/templates/slides/CHANGELOG.md +1 -0
  75. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +1 -1
  76. package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +1 -1
  77. package/corpus/templates/slides/app/pages/Index.tsx +7 -2
  78. package/corpus/templates/slides/changelog/2026-10-16-deck-lists-use-the-shared-ownership-filter-and-visibility-ba.md +6 -0
  79. package/package.json +1 -1
  80. package/corpus/templates/chat/app/lib/sidebar-thread-state.ts +0 -29
  81. package/corpus/templates/slides/app/components/deck/DeckFilterMenu.tsx +0 -83
@@ -1,9 +1,14 @@
1
1
  import {
2
2
  navigateWithAgentChatViewTransition,
3
3
  useChatThreads,
4
- type ChatThreadSummary,
5
4
  } from "@agent-native/core/client/agent-chat";
5
+ import { appPath } from "@agent-native/core/client/api-path";
6
6
  import { useT } from "@agent-native/core/client/i18n";
7
+ import {
8
+ OwnershipChatHistoryRail,
9
+ useOwnershipChatHistory,
10
+ ownDraftRows,
11
+ } from "@agent-native/toolkit/app/chat/ownership-history";
7
12
  import { DevDatabaseLink } from "@agent-native/toolkit/app/db-admin";
8
13
  import { FeedbackButton } from "@agent-native/toolkit/app/feedback";
9
14
  import { OrgSwitcher } from "@agent-native/toolkit/app/org";
@@ -12,12 +17,7 @@ import {
12
17
  AppSidebar,
13
18
  AppSidebarNavItem,
14
19
  } from "@agent-native/toolkit/app/shared";
15
- import {
16
- ChatHistoryRail,
17
- type ChatHistoryItem,
18
- } from "@agent-native/toolkit/chat-history";
19
20
  import { IconSearch } from "@tabler/icons-react";
20
- import { useEffect, useMemo } from "react";
21
21
  import { useLocation, useNavigate } from "react-router";
22
22
  import { toast } from "sonner";
23
23
 
@@ -43,40 +43,6 @@ interface SidebarProps {
43
43
  onCollapsedChange?: (collapsed: boolean) => void;
44
44
  }
45
45
 
46
- function formatThreadAge(updatedAt: number) {
47
- const diffMs = Math.max(0, Date.now() - updatedAt);
48
- const minutes = Math.floor(diffMs / 60_000);
49
- if (minutes < 1) return "now";
50
- if (minutes < 60) return `${minutes}m`;
51
- const hours = Math.floor(minutes / 60);
52
- if (hours < 24) return `${hours}h`;
53
- const days = Math.floor(hours / 24);
54
- if (days < 7) return `${days}d`;
55
- return new Date(updatedAt).toLocaleDateString([], {
56
- month: "short",
57
- day: "numeric",
58
- });
59
- }
60
-
61
- function threadTitle(thread: ChatThreadSummary) {
62
- return thread.title || thread.preview || "Untitled chat";
63
- }
64
-
65
- function threadUpdatedAt(thread: ChatThreadSummary) {
66
- return Number.isFinite(thread.updatedAt)
67
- ? thread.updatedAt
68
- : Number.isFinite(thread.createdAt)
69
- ? thread.createdAt
70
- : 0;
71
- }
72
-
73
- function compareThreads(a: ChatThreadSummary, b: ChatThreadSummary) {
74
- const aPinned = a.pinnedAt ?? 0;
75
- const bPinned = b.pinnedAt ?? 0;
76
- if (aPinned || bPinned) return bPinned - aPinned;
77
- return threadUpdatedAt(b) - threadUpdatedAt(a);
78
- }
79
-
80
46
  function persistedActiveThreadId() {
81
47
  try {
82
48
  return localStorage.getItem(BRAIN_ACTIVE_THREAD_KEY);
@@ -94,8 +60,9 @@ function BrainChatsSection({ open }: { open: boolean }) {
94
60
  pinThread,
95
61
  archiveThread,
96
62
  renameThread,
97
- refreshThreads,
63
+ isNewThread,
98
64
  } = useChatThreads(undefined, BRAIN_CHAT_STORAGE_KEY, undefined, {
65
+ ownership: "mine",
99
66
  autoCreate: false,
100
67
  restoreActiveThread: false,
101
68
  });
@@ -104,46 +71,27 @@ function BrainChatsSection({ open }: { open: boolean }) {
104
71
  const location = useLocation();
105
72
  const activeThreadId = brainAskThreadIdFromPath(location.pathname);
106
73
 
107
- const visibleThreads = useMemo(
108
- () =>
109
- threads
110
- .filter((thread) => thread.messageCount > 0 && !thread.archivedAt)
111
- .sort(compareThreads),
112
- [threads],
113
- );
114
- const chatItems = useMemo<ChatHistoryItem[]>(
115
- () =>
116
- visibleThreads.map((thread) => ({
117
- id: thread.id,
118
- title: threadTitle(thread),
119
- titleText: threadTitle(thread),
120
- timestamp:
121
- thread.id === activeThreadId
122
- ? undefined
123
- : formatThreadAge(threadUpdatedAt(thread)),
124
- pinned: Boolean(thread.pinnedAt),
125
- })),
126
- [activeThreadId, visibleThreads],
127
- );
128
-
129
- useEffect(() => {
130
- const refresh = () => refreshThreads();
131
- const handleRunning = (event: Event) => {
132
- const detail = (event as CustomEvent).detail as
133
- | { isRunning?: unknown }
134
- | undefined;
135
- if (typeof detail?.isRunning === "boolean") refreshThreads();
136
- };
137
-
138
- window.addEventListener("agent-chat:threads-updated", refresh);
139
- window.addEventListener("agentNative.chatRunning", handleRunning);
140
- window.addEventListener("focus", refresh);
141
- return () => {
142
- window.removeEventListener("agent-chat:threads-updated", refresh);
143
- window.removeEventListener("agentNative.chatRunning", handleRunning);
144
- window.removeEventListener("focus", refresh);
145
- };
146
- }, [refreshThreads]);
74
+ const history = useOwnershipChatHistory({
75
+ getThreadUrl: (threadId) => appPath(brainAskThreadPath(threadId)),
76
+ activeId: activeThreadId,
77
+ localMineRows: ownDraftRows({ threads, isNewThread }),
78
+ mutations: {
79
+ pin: pinThread,
80
+ rename: renameThread,
81
+ archive: archiveThread,
82
+ },
83
+ onMutationFailed: (kind) => {
84
+ toast.error(
85
+ t(
86
+ kind === "archive"
87
+ ? "chat.archiveFailed"
88
+ : kind === "rename"
89
+ ? "chat.renameFailed"
90
+ : "agentChat.common.saveFailed",
91
+ ),
92
+ );
93
+ },
94
+ });
147
95
 
148
96
  function openThread(threadId: string) {
149
97
  switchThread(threadId);
@@ -165,20 +113,12 @@ function BrainChatsSection({ open }: { open: boolean }) {
165
113
  async function handleArchiveThread(threadId: string) {
166
114
  const wasActive =
167
115
  threadId === activeThreadId || threadId === persistedActiveThreadId();
168
- const archived = await archiveThread(threadId);
169
- if (!archived) {
170
- toast.error(t("chat.archiveFailed"));
171
- return;
172
- }
116
+ const archived = await history.listProps.onDelete!(threadId);
117
+ if (!archived) return false;
173
118
  if (wasActive) {
174
119
  handleNewChat();
175
120
  }
176
- }
177
-
178
- function handleRenameThread(threadId: string, title: string) {
179
- void renameThread(threadId, title).then((renamed) => {
180
- if (!renamed) toast.error(t("chat.renameFailed"));
181
- });
121
+ return true;
182
122
  }
183
123
 
184
124
  return (
@@ -188,8 +128,8 @@ function BrainChatsSection({ open }: { open: boolean }) {
188
128
  aria-hidden={!open}
189
129
  >
190
130
  <div className="ms-4">
191
- <ChatHistoryRail
192
- items={chatItems}
131
+ <OwnershipChatHistoryRail
132
+ {...history}
193
133
  activeId={activeThreadId}
194
134
  onSelect={openThread}
195
135
  onNewChat={handleNewChat}
@@ -198,13 +138,6 @@ function BrainChatsSection({ open }: { open: boolean }) {
198
138
  showMore: t("chat.chats"),
199
139
  showLess: t("chat.chats"),
200
140
  }}
201
- previewCount={5}
202
- expandedCount={15}
203
- onTogglePin={(threadId) => {
204
- const thread = visibleThreads.find((item) => item.id === threadId);
205
- if (thread) void pinThread(threadId, !thread.pinnedAt);
206
- }}
207
- onRename={handleRenameThread}
208
141
  renameMaxLength={160}
209
142
  onDelete={(threadId) => void handleArchiveThread(threadId)}
210
143
  labels={{
@@ -4,7 +4,7 @@ import {
4
4
  } from "@agent-native/core/client/hooks";
5
5
  import { useT } from "@agent-native/core/client/i18n";
6
6
  import { ShareButton } from "@agent-native/toolkit/app/sharing";
7
- import { VisibilityBadge } from "@agent-native/toolkit/sharing";
7
+ import { VisibilityBadge } from "@agent-native/toolkit/app/sharing/VisibilityBadge";
8
8
  import {
9
9
  IconAlertTriangle,
10
10
  IconArchive,
@@ -1,9 +1,16 @@
1
+ import path from "node:path";
2
+
1
3
  import baseConfig from "@agent-native/core/vitest-config";
2
4
  import { defineConfig, mergeConfig } from "vitest/config";
3
5
 
4
6
  export default mergeConfig(
5
7
  baseConfig,
6
8
  defineConfig({
9
+ resolve: {
10
+ alias: {
11
+ "@": path.resolve(__dirname, "./app"),
12
+ },
13
+ },
7
14
  test: {
8
15
  passWithNoTests: true,
9
16
  exclude: [
@@ -15,6 +15,12 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
15
15
 
16
16
  - Apps no longer keep server functions and databases warm by default; set `AGENT_NATIVE_ENABLE_KEEP_WARM=1` to opt in.
17
17
 
18
+ ## 2026-10-16
19
+
20
+ ### Improved
21
+
22
+ - Booking links show localized visibility badges.
23
+
18
24
  ## 2026-10-08
19
25
 
20
26
  ### Added
@@ -6,7 +6,7 @@ import {
6
6
  SlugEditor,
7
7
  } from "@agent-native/scheduling/react/components";
8
8
  import { ShareButton } from "@agent-native/toolkit/app/sharing";
9
- import { VisibilityBadge } from "@agent-native/toolkit/sharing";
9
+ import { VisibilityBadge } from "@agent-native/toolkit/app/sharing/VisibilityBadge";
10
10
  import type {
11
11
  AvailabilityConfig,
12
12
  BookingHost,
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-10-16
4
+ ---
5
+
6
+ Booking links show localized visibility badges.
@@ -1,3 +1,4 @@
1
+ import { appPath } from "@agent-native/core/client/api-path";
1
2
  import { useT } from "@agent-native/core/client/i18n";
2
3
  import {
3
4
  navigateWithAgentChatViewTransition,
@@ -5,14 +6,15 @@ import {
5
6
  useChatThreads,
6
7
  type ChatThreadSummary,
7
8
  } from "@agent-native/toolkit/app/chat/agentkit-chat/rail";
9
+ import {
10
+ ownDraftRows,
11
+ OwnershipChatHistoryRail,
12
+ useOwnershipChatHistory,
13
+ type OwnDraftRow,
14
+ } from "@agent-native/toolkit/app/chat/ownership-history";
8
15
  import { OrgSwitcher } from "@agent-native/toolkit/app/org";
9
16
  import { openCommandMenu } from "@agent-native/toolkit/app/shared";
10
17
  import { AgentNativeIcon } from "@agent-native/toolkit/app/shared/AgentNativeIcon";
11
- import {
12
- ChatHistoryList,
13
- type ChatHistoryItem,
14
- type ChatHistorySection,
15
- } from "@agent-native/toolkit/chat-history/ChatHistoryList";
16
18
  import {
17
19
  IconApps,
18
20
  IconClock,
@@ -25,7 +27,7 @@ import {
25
27
  IconPin,
26
28
  IconSearch,
27
29
  } from "@tabler/icons-react";
28
- import { useEffect, useMemo, useRef, useState } from "react";
30
+ import { useEffect, useRef, useState } from "react";
29
31
  import { Link, useLocation, useNavigate } from "react-router";
30
32
  import { toast } from "sonner";
31
33
 
@@ -41,7 +43,6 @@ import {
41
43
  } from "@/components/ui/tooltip";
42
44
  import { APP_TITLE } from "@/lib/app-config";
43
45
  import { chatThreadPath, HOME_PATH, threadIdFromPath } from "@/lib/chat-paths";
44
- import { visibleChatThreads } from "@/lib/sidebar-thread-state";
45
46
  import { cn } from "@/lib/utils";
46
47
 
47
48
  const CHAT_STORAGE_KEY = "chat";
@@ -53,11 +54,9 @@ interface SidebarProps {
53
54
  onCollapsedChange?: (collapsed: boolean) => void;
54
55
  }
55
56
 
56
- function threadTitle(thread: ChatThreadSummary, untitledLabel: string) {
57
- return thread.title || untitledLabel;
58
- }
59
-
60
- function threadUpdatedAt(thread: ChatThreadSummary) {
57
+ function threadUpdatedAt(
58
+ thread: Pick<ChatThreadSummary, "createdAt" | "updatedAt">,
59
+ ) {
61
60
  return Number.isFinite(thread.updatedAt)
62
61
  ? thread.updatedAt
63
62
  : Number.isFinite(thread.createdAt)
@@ -65,14 +64,6 @@ function threadUpdatedAt(thread: ChatThreadSummary) {
65
64
  : 0;
66
65
  }
67
66
 
68
- function compareRecentThreads(a: ChatThreadSummary, b: ChatThreadSummary) {
69
- return threadUpdatedAt(b) - threadUpdatedAt(a);
70
- }
71
-
72
- function comparePinnedThreads(a: ChatThreadSummary, b: ChatThreadSummary) {
73
- return (b.pinnedAt ?? 0) - (a.pinnedAt ?? 0);
74
- }
75
-
76
67
  function formatRelativeTime(timestamp: number) {
77
68
  const elapsed = timestamp - Date.now();
78
69
  const intervals = [
@@ -106,7 +97,10 @@ function ThreadHistoryTitle({
106
97
  title,
107
98
  running,
108
99
  }: {
109
- thread: ChatThreadSummary;
100
+ thread: OwnDraftRow &
101
+ Partial<
102
+ Pick<ChatThreadSummary, "preview" | "scope" | "source" | "pinnedAt">
103
+ >;
110
104
  title: string;
111
105
  running: boolean;
112
106
  }) {
@@ -287,7 +281,7 @@ function ChatThreadsSection({ collapsed }: { collapsed: boolean }) {
287
281
  pinThread,
288
282
  archiveThread,
289
283
  renameThread,
290
- refreshThreads,
284
+ isNewThread,
291
285
  } = useChatThreads(undefined, CHAT_STORAGE_KEY, undefined, {
292
286
  autoCreate: false,
293
287
  restoreActiveThread: false,
@@ -295,66 +289,46 @@ function ChatThreadsSection({ collapsed }: { collapsed: boolean }) {
295
289
  const { workingThreadIds, observedThreadStarts } =
296
290
  useAgentChatRunningThreads();
297
291
 
298
- const visibleThreads = useMemo(
299
- () => visibleChatThreads(threads, observedThreadStarts),
300
- [observedThreadStarts, threads],
301
- );
302
- const displayedActiveThreadId =
303
- threadIdFromPath(location.pathname) ??
304
- activeThreadId ??
305
- persistedActiveThreadId();
306
-
307
- const historySections = useMemo<ChatHistorySection[]>(() => {
308
- const untitledLabel = t("chat.untitledChat");
309
- const toItem = (thread: ChatThreadSummary): ChatHistoryItem => {
310
- const title = threadTitle(thread, untitledLabel);
292
+ const localMineRows = ownDraftRows({
293
+ threads,
294
+ isNewThread,
295
+ observedThreadStarts,
296
+ });
297
+ const history = useOwnershipChatHistory({
298
+ getThreadUrl: (threadId) => appPath(chatThreadPath(threadId)),
299
+ activeId:
300
+ threadIdFromPath(location.pathname) ??
301
+ activeThreadId ??
302
+ persistedActiveThreadId(),
303
+ localMineRows,
304
+ pinned: { label: t("chat.pinned") },
305
+ mutations: {
306
+ pin: pinThread,
307
+ rename: renameThread,
308
+ archive: archiveThread,
309
+ },
310
+ onMutationFailed: (kind) => {
311
+ if (kind === "archive") toast.error(t("chat.archiveFailed"));
312
+ if (kind === "rename") toast.error(t("chat.renameFailed"));
313
+ },
314
+ decorateItem: (item, row) => {
315
+ const title = row.title || row.preview || t("chat.untitledChat");
311
316
  return {
312
- id: thread.id,
317
+ ...item,
313
318
  title: (
314
319
  <ThreadHistoryTitle
315
- thread={thread}
320
+ thread={row}
316
321
  title={title}
317
- running={workingThreadIds.has(thread.id)}
322
+ running={workingThreadIds.has(row.id)}
318
323
  />
319
324
  ),
320
- titleText: title,
321
- pinned: Boolean(thread.pinnedAt),
322
325
  };
323
- };
324
- const pinned = visibleThreads
325
- .filter((thread) => Boolean(thread.pinnedAt))
326
- .sort(comparePinnedThreads)
327
- .map(toItem);
328
- const recent = visibleThreads
329
- .filter((thread) => !thread.pinnedAt)
330
- .sort(compareRecentThreads)
331
- .slice(0, 30)
332
- .map(toItem);
333
-
334
- return [
335
- { id: "pinned", label: t("chat.pinned"), items: pinned },
336
- { id: "recents", label: t("chat.recents"), items: recent },
337
- ];
338
- }, [t, visibleThreads, workingThreadIds]);
339
-
340
- useEffect(() => {
341
- const refresh = () => refreshThreads();
342
- const handleRunning = (event: Event) => {
343
- const detail = (event as CustomEvent).detail as
344
- | { isRunning?: unknown }
345
- | undefined;
346
- if (typeof detail?.isRunning === "boolean") refreshThreads();
347
- };
348
-
349
- window.addEventListener("agent-chat:threads-updated", refresh);
350
- window.addEventListener("agentNative.chatRunning", handleRunning);
351
- window.addEventListener("focus", refresh);
352
- return () => {
353
- window.removeEventListener("agent-chat:threads-updated", refresh);
354
- window.removeEventListener("agentNative.chatRunning", handleRunning);
355
- window.removeEventListener("focus", refresh);
356
- };
357
- }, [refreshThreads]);
326
+ },
327
+ });
328
+ const displayedActiveThreadId =
329
+ threadIdFromPath(location.pathname) ??
330
+ activeThreadId ??
331
+ persistedActiveThreadId();
358
332
 
359
333
  function openThread(threadId: string, options?: { isNew?: boolean }) {
360
334
  switchThread(threadId);
@@ -382,23 +356,6 @@ function ChatThreadsSection({ collapsed }: { collapsed: boolean }) {
382
356
  if (threadId) openThread(threadId, { isNew: true });
383
357
  }
384
358
 
385
- async function handleArchiveThread(threadId: string) {
386
- const wasActive =
387
- threadId === activeThreadId || threadId === persistedActiveThreadId();
388
- const archived = await archiveThread(threadId);
389
- if (!archived) {
390
- toast.error(t("chat.archiveFailed"));
391
- return;
392
- }
393
- if (wasActive) await handleNewChat();
394
- }
395
-
396
- function handleRenameThread(threadId: string, title: string) {
397
- void renameThread(threadId, title).then((renamed) => {
398
- if (!renamed) toast.error(t("chat.renameFailed"));
399
- });
400
- }
401
-
402
359
  const newChatButton = (
403
360
  <button
404
361
  type="button"
@@ -430,17 +387,20 @@ function ChatThreadsSection({ collapsed }: { collapsed: boolean }) {
430
387
  return (
431
388
  <div className="flex min-h-0 flex-1 flex-col">
432
389
  <div className="px-2 pb-3">{newChatButton}</div>
433
- <ChatHistoryList
434
- sections={historySections}
390
+ <OwnershipChatHistoryRail
391
+ {...history}
392
+ onNewChat={() => void handleNewChat()}
393
+ showNewChat={false}
435
394
  activeId={displayedActiveThreadId}
436
395
  onSelect={openThread}
437
- onTogglePin={(threadId) => {
438
- const thread = visibleThreads.find((item) => item.id === threadId);
439
- if (thread) void pinThread(threadId, !thread.pinnedAt);
396
+ onDelete={async (threadId) => {
397
+ const wasActive =
398
+ threadId === activeThreadId ||
399
+ threadId === persistedActiveThreadId();
400
+ const archived = await history.listProps.onDelete?.(threadId);
401
+ if (archived && wasActive) await handleNewChat();
440
402
  }}
441
- onRename={handleRenameThread}
442
403
  renameMaxLength={160}
443
- onDelete={(threadId) => void handleArchiveThread(threadId)}
444
404
  labels={{
445
405
  options: (item) =>
446
406
  t("chat.optionsFor", { title: item.titleText ?? "" }),
@@ -451,8 +411,9 @@ function ChatThreadsSection({ collapsed }: { collapsed: boolean }) {
451
411
  unpin: t("chat.unpinChat"),
452
412
  delete: t("chat.archiveChat"),
453
413
  }}
454
- variant="rail"
455
- emptyLabel={null}
414
+ railLabels={{
415
+ newChat: t("chat.newChat"),
416
+ }}
456
417
  className="chat-sidebar-history min-h-0 flex-1"
457
418
  listClassName="pb-4"
458
419
  />
@@ -3,6 +3,12 @@
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-10-21
7
+
8
+ ### Improved
9
+
10
+ - Share panels describe general access in a sentence and no longer open an empty people list when you click into them.
11
+
6
12
  ## 2026-10-20
7
13
 
8
14
  ### Fixed
@@ -59,6 +65,7 @@ from the command menu (Cmd+K → "What's new") or from Settings.
59
65
 
60
66
  ### Improved
61
67
 
68
+ - Share dialogs make it easier to see who has access and manage common sharing changes.
62
69
  - Rewind settings now show whether Rewind is remembering screen only or screen + audio.
63
70
  - Clips detects browser meetings more reliably and keeps notes until the meeting stop and transcript save are confirmed.
64
71
  - Clips detects browser meetings sooner, asks before starting when the active tab is unclear, and retries failed stops.
@@ -1617,24 +1624,4 @@ from the command menu (Cmd+K → "What's new") or from Settings.
1617
1624
  - The agent sidebar now slides in smoothly without duplicate edge borders.
1618
1625
  - The clip details sidebar now collapses into a slide-out panel on smaller screens.
1619
1626
 
1620
- ## 2026-06-25
1621
-
1622
- ### Added
1623
-
1624
- - GitHub issue and pull request pages can now preview playable Clips links when the Chrome extension is installed.
1625
- - Recording pages now offer a download action for viewers with video download access.
1626
-
1627
- ### Improved
1628
-
1629
- - Clip titles are now edited only from a clip's detail view, not from the library grid
1630
- - Console diagnostics keep more useful non-secret details when clips are shared with agents.
1631
- - Recording cards now avoid duplicate rename controls in the overflow menu.
1632
-
1633
- ### Fixed
1634
-
1635
- - Chrome extension recordings now upload large capture bursts reliably and report extension errors to Sentry.
1636
- - Fixed owner recognition so Clips created from desktop and web sessions remain editable by the same signed-in user.
1637
- - Fixed the Mac menu bar popover so it opens reliably after launch at login.
1638
- - Localized Clips Settings changelog and extension sidebar labels in every supported interface language.
1639
-
1640
1627
  For the full list of updates, see the [changelog folder](./changelog/).