@agent-native/core-corpus 0.201.0-nightly-20261005153421 → 0.201.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 (235) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +9 -2
  3. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +14 -4
  4. package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +12 -7
  5. package/corpus/templates/analytics/CHANGELOG.md +6 -0
  6. package/corpus/templates/analytics/README.md +2 -2
  7. package/corpus/templates/analytics/changelog/2026-10-02-events-with-a-very-long-name-app-or-page-path-no-longer-caus.md +6 -0
  8. package/corpus/templates/analytics/package.json +1 -0
  9. package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +9 -19
  10. package/corpus/templates/analytics/server/handlers/session-replay.ts +34 -47
  11. package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +9 -6
  12. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +57 -36
  13. package/corpus/templates/analytics/server/lib/indexed-text.ts +53 -0
  14. package/corpus/templates/analytics/server/lib/request-errors.ts +73 -0
  15. package/corpus/templates/analytics/server/lib/session-event-index.ts +6 -16
  16. package/corpus/templates/analytics/server/lib/session-replay.ts +12 -2
  17. package/corpus/templates/analytics/server/plugins/auth.ts +2 -1
  18. package/corpus/templates/analytics/server/plugins/otel.ts +6 -0
  19. package/corpus/templates/assets/.agents/skills/security/SKILL.md +9 -2
  20. package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +12 -7
  21. package/corpus/templates/assets/CHANGELOG.md +7 -0
  22. package/corpus/templates/assets/README.md +2 -2
  23. package/corpus/templates/assets/package.json +1 -0
  24. package/corpus/templates/assets/server/plugins/auth.ts +2 -1
  25. package/corpus/templates/assets/server/plugins/otel.ts +6 -0
  26. package/corpus/templates/brain/.agents/skills/brain/RUNBOOK.md +2 -1
  27. package/corpus/templates/brain/.agents/skills/brain/SKILL.md +5 -4
  28. package/corpus/templates/brain/.agents/skills/security/SKILL.md +9 -2
  29. package/corpus/templates/brain/.agents/skills/storing-data/SKILL.md +12 -7
  30. package/corpus/templates/brain/CHANGELOG.md +6 -0
  31. package/corpus/templates/brain/README.md +12 -8
  32. package/corpus/templates/brain/changelog/2026-10-05-private-slack-channels-are-searchable-org-wide.md +6 -0
  33. package/corpus/templates/brain/package.json +1 -0
  34. package/corpus/templates/brain/server/lib/audiences.ts +1 -98
  35. package/corpus/templates/brain/server/lib/connectors.ts +2 -166
  36. package/corpus/templates/brain/server/plugins/otel.ts +6 -0
  37. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +9 -2
  38. package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +12 -7
  39. package/corpus/templates/calendar/CHANGELOG.md +7 -0
  40. package/corpus/templates/calendar/README.md +2 -2
  41. package/corpus/templates/calendar/package.json +1 -0
  42. package/corpus/templates/calendar/server/plugins/auth.ts +2 -1
  43. package/corpus/templates/calendar/server/plugins/otel.ts +6 -0
  44. package/corpus/templates/chat/.agents/skills/security/SKILL.md +9 -2
  45. package/corpus/templates/chat/.agents/skills/storing-data/SKILL.md +12 -7
  46. package/corpus/templates/chat/README.md +2 -2
  47. package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +9 -0
  48. package/corpus/templates/clips/.agents/skills/security/SKILL.md +9 -2
  49. package/corpus/templates/clips/CHANGELOG.md +24 -0
  50. package/corpus/templates/clips/README.md +2 -2
  51. package/corpus/templates/clips/actions/lib/audio-chunk-list.ts +23 -0
  52. package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +187 -292
  53. package/corpus/templates/clips/actions/lib/chunked-transcription.ts +151 -0
  54. package/corpus/templates/clips/actions/lib/recording-audio-source.ts +191 -0
  55. package/corpus/templates/clips/actions/request-transcript.ts +81 -135
  56. package/corpus/templates/clips/actions/search-recordings.ts +19 -5
  57. package/corpus/templates/clips/app/components/clips-command-menu.tsx +5 -0
  58. package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -1
  59. package/corpus/templates/clips/app/components/library/search-bar.tsx +5 -0
  60. package/corpus/templates/clips/app/hooks/use-library.ts +1 -0
  61. package/corpus/templates/clips/app/lib/local-recording-upload.ts +13 -6
  62. package/corpus/templates/clips/app/lib/recording-section.ts +1 -1
  63. package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +7 -5
  64. package/corpus/templates/clips/app/routes/record.tsx +16 -6
  65. package/corpus/templates/clips/changelog/2026-10-02-long-uploads-an-hour-or-more-now-transcribe-reliably-instead.md +6 -0
  66. package/corpus/templates/clips/changelog/2026-10-05-confirming-discard-recording-now-returns-you-to-your-library.md +6 -0
  67. package/corpus/templates/clips/changelog/2026-10-05-discarding-a-recording-now-removes-its-failed-upload-card-fr.md +6 -0
  68. package/corpus/templates/clips/changelog/2026-10-05-discarding-a-recovered-recording-no-longer-warns-that-it-s-o.md +6 -0
  69. package/corpus/templates/clips/changelog/2026-10-05-search-results-identify-recordings-in-trash-and-open-them-wi.md +6 -0
  70. package/corpus/templates/clips/package.json +1 -0
  71. package/corpus/templates/clips/server/lib/builder-cdn.ts +5 -0
  72. package/corpus/templates/clips/server/lib/builder-media-compression.ts +2 -2
  73. package/corpus/templates/clips/server/plugins/auth.ts +2 -1
  74. package/corpus/templates/clips/server/plugins/otel.ts +6 -0
  75. package/corpus/templates/clips/shared/transcript-failure.ts +5 -0
  76. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +8 -2
  77. package/corpus/templates/content/.agents/skills/security/SKILL.md +9 -2
  78. package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +12 -7
  79. package/corpus/templates/content/CHANGELOG.md +41 -0
  80. package/corpus/templates/content/README.md +2 -2
  81. package/corpus/templates/content/actions/_database-navigation.ts +523 -344
  82. package/corpus/templates/content/actions/_database-row-mutation.ts +44 -10
  83. package/corpus/templates/content/actions/_database-setup-discovery.ts +9 -3
  84. package/corpus/templates/content/actions/_database-utils.ts +299 -271
  85. package/corpus/templates/content/actions/_property-utils.ts +293 -190
  86. package/corpus/templates/content/actions/_relation-values.ts +3 -1
  87. package/corpus/templates/content/actions/get-content-database.ts +1 -0
  88. package/corpus/templates/content/actions/query-content-database-items.ts +32 -5
  89. package/corpus/templates/content/actions/set-document-property.ts +17 -11
  90. package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +21 -6
  91. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +127 -43
  92. package/corpus/templates/content/app/components/editor/DocumentEditorSkeleton.tsx +159 -50
  93. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +12 -28
  94. package/corpus/templates/content/app/components/editor/PageDraftRecovery.tsx +6 -1
  95. package/corpus/templates/content/app/components/editor/TableHoverControls.tsx +139 -70
  96. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +16 -1
  97. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +180 -75
  98. package/corpus/templates/content/app/components/editor/database/DatabaseViewSkeleton.tsx +76 -0
  99. package/corpus/templates/content/app/components/editor/database/navigation-state.ts +60 -2
  100. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +41 -42
  101. package/corpus/templates/content/app/components/editor/document-editor-layout.ts +18 -0
  102. package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +11 -3
  103. package/corpus/templates/content/app/components/editor/suggestions/draft-session.ts +15 -7
  104. package/corpus/templates/content/app/components/editor/suggestions/model.ts +13 -0
  105. package/corpus/templates/content/app/components/editor/suggestions/read-only-blocks.ts +136 -0
  106. package/corpus/templates/content/app/components/editor/table-view.ts +73 -0
  107. package/corpus/templates/content/app/components/layout/ContentStartupShell.tsx +1 -1
  108. package/corpus/templates/content/app/components/layout/Layout.tsx +5 -1
  109. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +57 -16
  110. package/corpus/templates/content/app/components/sidebar/MovePageDialog.tsx +4 -4
  111. package/corpus/templates/content/app/components/sidebar/SidebarNavigationRow.tsx +34 -10
  112. package/corpus/templates/content/app/global.css +16 -8
  113. package/corpus/templates/content/app/hooks/content-action-refresh.ts +14 -13
  114. package/corpus/templates/content/app/hooks/use-content-database.ts +72 -9
  115. package/corpus/templates/content/app/hooks/use-content-personal-navigation.ts +7 -3
  116. package/corpus/templates/content/app/hooks/use-documents.ts +27 -0
  117. package/corpus/templates/content/app/i18n-data.ts +3 -2
  118. package/corpus/templates/content/app/lib/content-landing.ts +3 -31
  119. package/corpus/templates/content/app/lib/files-navigation.ts +182 -10
  120. package/corpus/templates/content/app/lib/files-root-hint.ts +20 -32
  121. package/corpus/templates/content/app/lib/page-startup-hints.ts +108 -0
  122. package/corpus/templates/content/app/lib/private-link-redirect.ts +25 -0
  123. package/corpus/templates/content/app/lib/sidebar-layout-hint.ts +34 -1
  124. package/corpus/templates/content/app/lib/startup-timing.ts +2 -0
  125. package/corpus/templates/content/app/root.tsx +3 -1
  126. package/corpus/templates/content/app/routes/_app.home.tsx +10 -19
  127. package/corpus/templates/content/app/routes/p.$id.tsx +23 -5
  128. package/corpus/templates/content/changelog/2026-10-02-a-page-link-you-cant-open-now-says-so-instead-of-opening-an.md +6 -0
  129. package/corpus/templates/content/changelog/2026-10-02-after-a-refresh-the-files-sidebar-shows-the-open-page-s-fold.md +6 -0
  130. package/corpus/templates/content/changelog/2026-10-02-large-collections-open-faster.md +6 -0
  131. package/corpus/templates/content/changelog/2026-10-02-pages-stay-inside-the-window-at-every-width-long-inline-code.md +6 -0
  132. package/corpus/templates/content/changelog/2026-10-02-pages-with-open-comments-and-collections-with-sorted-or-filt.md +6 -0
  133. package/corpus/templates/content/changelog/2026-10-02-suggest-edits-works-on-pages-written-by-agents-including-pag.md +6 -0
  134. package/corpus/templates/content/changelog/2026-10-02-while-you-suggest-edits-tables-and-other-blocks-that-suggest.md +6 -0
  135. package/corpus/templates/content/changelog/2026-10-05-collection-view-context-now-survives-quick-page-changes-when.md +6 -0
  136. package/corpus/templates/content/changelog/2026-10-05-collection-views-keep-their-saved-rows-accurate-during-refre.md +6 -0
  137. package/corpus/templates/content/changelog/2026-10-05-exact-saved-view-links-keep-collection-retry-available.md +6 -0
  138. package/corpus/templates/content/changelog/2026-10-05-expanding-a-files-folder-now-shares-one-navigation-read-acro.md +6 -0
  139. package/corpus/templates/content/changelog/2026-10-05-files-navigation-retries-temporary-failures-consistently.md +6 -0
  140. package/corpus/templates/content/changelog/2026-10-05-shared-page-owners-keep-edit-and-manage-controls-in-files-an.md +6 -0
  141. package/corpus/templates/content/changelog/2026-10-05-tagging-an-ai-in-a-comment-works-again-instead-of-failing-ri.md +6 -0
  142. package/corpus/templates/content/changelog/2026-10-05-the-home-loading-shell-keeps-the-layout-of-your-last-opened-.md +6 -0
  143. package/corpus/templates/content/changelog/2026-10-05-typing-and-a-space-or-inserting-a-toggle-or-callout-no-longe.md +6 -0
  144. package/corpus/templates/content/docs/product/capabilities/content.workspace.session-restore.md +4 -1
  145. package/corpus/templates/content/e2e/playwright.config.ts +1 -1
  146. package/corpus/templates/content/package.json +2 -1
  147. package/corpus/templates/content/scripts/seed-perf-database.mjs +600 -0
  148. package/corpus/templates/content/scripts/trace-startup.mjs +25 -3
  149. package/corpus/templates/content/server/db/index.ts +1 -1
  150. package/corpus/templates/content/server/lib/suggested-edits.ts +23 -26
  151. package/corpus/templates/content/server/plugins/auth.ts +2 -1
  152. package/corpus/templates/content/server/plugins/otel.ts +6 -0
  153. package/corpus/templates/content/shared/api.ts +17 -0
  154. package/corpus/templates/content/shared/suggestion-diff.ts +124 -38
  155. package/corpus/templates/content/shared/suggestion-formatting.ts +134 -3
  156. package/corpus/templates/crm/.agents/skills/security/SKILL.md +9 -2
  157. package/corpus/templates/crm/.agents/skills/storing-data/SKILL.md +12 -7
  158. package/corpus/templates/crm/package.json +1 -0
  159. package/corpus/templates/crm/server/plugins/otel.ts +6 -0
  160. package/corpus/templates/design/.agents/skills/security/SKILL.md +9 -2
  161. package/corpus/templates/design/.agents/skills/storing-data/SKILL.md +12 -7
  162. package/corpus/templates/design/CHANGELOG.md +41 -0
  163. package/corpus/templates/design/README.md +2 -2
  164. package/corpus/templates/design/actions/list-designs.ts +11 -4
  165. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +110 -32
  166. package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +28 -0
  167. package/corpus/templates/design/app/components/design/multi-screen/types.ts +1 -0
  168. package/corpus/templates/design/app/components/home/DesignHomeLibrary.tsx +79 -0
  169. package/corpus/templates/design/app/components/layout/Header.tsx +2 -4
  170. package/corpus/templates/design/app/components/ui/tabs.tsx +59 -1
  171. package/corpus/templates/design/app/global.css +1 -34
  172. package/corpus/templates/design/app/i18n/en-US.ts +4 -0
  173. package/corpus/templates/design/app/lib/design-filter.ts +4 -2
  174. package/corpus/templates/design/app/pages/Index.tsx +91 -59
  175. package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-element-drop.ts +58 -17
  176. package/corpus/templates/design/changelog/2026-10-01-filter-designs-by-owner.md +6 -0
  177. package/corpus/templates/design/changelog/2026-10-03-layers-dropped-into-visible-canvas-space-beyond-a-screen-now.md +6 -0
  178. package/corpus/templates/design/changelog/2026-10-03-visible-screen-overflow-no-longer-routes-drops-to-the-canvas.md +6 -0
  179. package/corpus/templates/design/changelog/2026-10-05-the-recent-tab-shows-loading-placeholders-until-your-designs.md +6 -0
  180. package/corpus/templates/design/package.json +1 -0
  181. package/corpus/templates/design/server/plugins/auth.ts +2 -1
  182. package/corpus/templates/design/server/plugins/otel.ts +6 -0
  183. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +9 -2
  184. package/corpus/templates/dispatch/.agents/skills/storing-data/SKILL.md +12 -7
  185. package/corpus/templates/dispatch/README.md +2 -2
  186. package/corpus/templates/dispatch/package.json +1 -0
  187. package/corpus/templates/dispatch/server/plugins/otel.ts +6 -0
  188. package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +2 -1
  189. package/corpus/templates/factory/.agents/skills/security/SKILL.md +9 -2
  190. package/corpus/templates/factory/.agents/skills/storing-data/SKILL.md +12 -7
  191. package/corpus/templates/factory/package.json +1 -0
  192. package/corpus/templates/factory/server/plugins/otel.ts +6 -0
  193. package/corpus/templates/forms/.agents/skills/security/SKILL.md +9 -2
  194. package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +12 -7
  195. package/corpus/templates/forms/README.md +2 -2
  196. package/corpus/templates/forms/package.json +1 -0
  197. package/corpus/templates/forms/server/plugins/auth.ts +2 -1
  198. package/corpus/templates/forms/server/plugins/otel.ts +6 -0
  199. package/corpus/templates/mail/.agents/skills/security/SKILL.md +9 -2
  200. package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +12 -7
  201. package/corpus/templates/mail/CHANGELOG.md +6 -0
  202. package/corpus/templates/mail/README.md +2 -2
  203. package/corpus/templates/mail/package.json +1 -0
  204. package/corpus/templates/mail/server/plugins/auth.ts +2 -1
  205. package/corpus/templates/mail/server/plugins/otel.ts +6 -0
  206. package/corpus/templates/plan/.agents/skills/security/SKILL.md +9 -2
  207. package/corpus/templates/plan/.agents/skills/storing-data/SKILL.md +12 -7
  208. package/corpus/templates/plan/CHANGELOG.md +1 -0
  209. package/corpus/templates/plan/README.md +2 -2
  210. package/corpus/templates/plan/package.json +1 -0
  211. package/corpus/templates/plan/server/plugins/auth.ts +2 -1
  212. package/corpus/templates/plan/server/plugins/otel.ts +6 -0
  213. package/corpus/templates/slides/.agents/skills/security/SKILL.md +9 -2
  214. package/corpus/templates/slides/.agents/skills/storing-data/SKILL.md +12 -7
  215. package/corpus/templates/slides/CHANGELOG.md +23 -0
  216. package/corpus/templates/slides/README.md +2 -2
  217. package/corpus/templates/slides/actions/list-decks.ts +11 -4
  218. package/corpus/templates/slides/app/components/deck/DeckFilterMenu.tsx +44 -36
  219. package/corpus/templates/slides/app/components/home/SlidesHomeLibrary.tsx +79 -0
  220. package/corpus/templates/slides/app/components/layout/Header.tsx +2 -15
  221. package/corpus/templates/slides/app/components/ui/tabs.tsx +59 -0
  222. package/corpus/templates/slides/app/global.css +3 -54
  223. package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
  224. package/corpus/templates/slides/app/lib/deck-filter.ts +5 -2
  225. package/corpus/templates/slides/app/pages/Index.tsx +102 -88
  226. package/corpus/templates/slides/changelog/2026-10-01-filter-decks-by-owner.md +6 -0
  227. package/corpus/templates/slides/changelog/2026-10-02-hide-recent-until-decks-available.md +6 -0
  228. package/corpus/templates/slides/changelog/2026-10-05-the-recent-tab-shows-loading-placeholders-until-your-decks-a.md +6 -0
  229. package/corpus/templates/slides/package.json +1 -0
  230. package/corpus/templates/slides/server/handlers/request-auth-context.ts +8 -0
  231. package/corpus/templates/slides/server/plugins/auth.ts +2 -1
  232. package/corpus/templates/slides/server/plugins/otel.ts +6 -0
  233. package/corpus/templates/tasks/.agents/skills/security/SKILL.md +9 -2
  234. package/corpus/templates/tasks/.agents/skills/storing-data/SKILL.md +12 -7
  235. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import { defineAction, embedApp } from "@agent-native/core";
2
2
  import { buildDeepLink } from "@agent-native/core/server";
3
- import { and, eq, isNull, sql } from "drizzle-orm";
3
+ import { getRequestUserEmail } from "@agent-native/core/server/request-context";
4
+ import { and, eq, isNull, or, sql } from "drizzle-orm";
4
5
  import { z } from "zod";
5
6
 
6
7
  import { getDb, schema } from "../server/db/index.js";
@@ -9,6 +10,7 @@ import {
9
10
  isAgentRecordingCaller,
10
11
  } from "../server/lib/agent-recording-access.js";
11
12
  import { listingThumbnailUrl } from "../server/lib/player-thumbnail-url.js";
13
+ import { ownerEmailMatches } from "../server/lib/recordings.js";
12
14
  import { buildCaseInsensitiveSearchPattern } from "./search-recordings-utils.js";
13
15
 
14
16
  const SNIPPET_RADIUS = 80;
@@ -96,7 +98,7 @@ function transcriptMatch(
96
98
 
97
99
  export default defineAction({
98
100
  description:
99
- "Search recordings by title, description, transcript text, or comments. Transcript and comment matches include timestamps for jumping to the matching moment. Public/unlisted recordings are searchable only when owned by or previously viewed by the current user.",
101
+ "Search recordings by title, description, transcript text, or comments, including recordings in the caller's Trash. Transcript and comment matches include timestamps for jumping to the matching moment. Public/unlisted recordings are searchable only when owned by or previously viewed by the current user.",
100
102
  schema: z.object({
101
103
  query: z.string().min(1).describe("Search text"),
102
104
  limit: z.coerce.number().int().min(1).max(100).default(30),
@@ -119,6 +121,13 @@ export default defineAction({
119
121
  agentOnly: isAgentRecordingCaller(ctx?.caller),
120
122
  userEmail: ctx?.userEmail,
121
123
  };
124
+ const userEmail = ctx?.userEmail ?? getRequestUserEmail();
125
+ const lifecycleFilter = userEmail
126
+ ? or(
127
+ isNull(schema.recordings.trashedAt),
128
+ ownerEmailMatches(schema.recordings.ownerEmail, userEmail),
129
+ )
130
+ : isNull(schema.recordings.trashedAt);
122
131
 
123
132
  const recMatches = await db
124
133
  .select({
@@ -128,6 +137,7 @@ export default defineAction({
128
137
  thumbnailUrl: schema.recordings.thumbnailUrl,
129
138
  kind: schema.recordings.kind,
130
139
  mediaUpdatedAt: schema.recordings.mediaUpdatedAt,
140
+ trashedAt: schema.recordings.trashedAt,
131
141
  durationMs: schema.recordings.durationMs,
132
142
  ownerEmail: schema.recordings.ownerEmail,
133
143
  visibility: schema.recordings.visibility,
@@ -143,7 +153,7 @@ export default defineAction({
143
153
  schema.recordingViewers,
144
154
  recordingAccess,
145
155
  ),
146
- isNull(schema.recordings.trashedAt),
156
+ lifecycleFilter,
147
157
  sql`(lower(${schema.recordings.title}) LIKE ${pattern} ESCAPE '\\' OR lower(${schema.recordings.description}) LIKE ${pattern} ESCAPE '\\')`,
148
158
  ),
149
159
  )
@@ -160,6 +170,7 @@ export default defineAction({
160
170
  thumbnailUrl: schema.recordings.thumbnailUrl,
161
171
  kind: schema.recordings.kind,
162
172
  mediaUpdatedAt: schema.recordings.mediaUpdatedAt,
173
+ trashedAt: schema.recordings.trashedAt,
163
174
  durationMs: schema.recordings.durationMs,
164
175
  ownerEmail: schema.recordings.ownerEmail,
165
176
  visibility: schema.recordings.visibility,
@@ -179,7 +190,7 @@ export default defineAction({
179
190
  schema.recordingViewers,
180
191
  recordingAccess,
181
192
  ),
182
- isNull(schema.recordings.trashedAt),
193
+ lifecycleFilter,
183
194
  sql`lower(${schema.recordingTranscripts.fullText}) LIKE ${pattern} ESCAPE '\\'`,
184
195
  ),
185
196
  )
@@ -196,6 +207,7 @@ export default defineAction({
196
207
  thumbnailUrl: schema.recordings.thumbnailUrl,
197
208
  kind: schema.recordings.kind,
198
209
  mediaUpdatedAt: schema.recordings.mediaUpdatedAt,
210
+ trashedAt: schema.recordings.trashedAt,
199
211
  durationMs: schema.recordings.durationMs,
200
212
  ownerEmail: schema.recordings.ownerEmail,
201
213
  visibility: schema.recordings.visibility,
@@ -215,7 +227,7 @@ export default defineAction({
215
227
  schema.recordingViewers,
216
228
  recordingAccess,
217
229
  ),
218
- isNull(schema.recordings.trashedAt),
230
+ lifecycleFilter,
219
231
  sql`lower(${schema.recordingComments.content}) LIKE ${pattern} ESCAPE '\\'`,
220
232
  ),
221
233
  )
@@ -230,6 +242,7 @@ export default defineAction({
230
242
  title: r.title,
231
243
  description: r.description,
232
244
  thumbnailUrl: listingThumbnailUrl(r),
245
+ trashedAt: r.trashedAt,
233
246
  durationMs: r.durationMs,
234
247
  ownerEmail: r.ownerEmail,
235
248
  visibility: r.visibility,
@@ -241,6 +254,7 @@ export default defineAction({
241
254
  title: r.title,
242
255
  description: r.description,
243
256
  thumbnailUrl: listingThumbnailUrl(r),
257
+ trashedAt: r.trashedAt,
244
258
  durationMs: r.durationMs,
245
259
  ownerEmail: r.ownerEmail,
246
260
  visibility: r.visibility,
@@ -167,6 +167,11 @@ function RecordingSearchResults({
167
167
  {formatSearchSnippet(hit.snippet ?? hit.description)}
168
168
  </span>
169
169
  ) : null}
170
+ {hit.trashedAt ? (
171
+ <span className="mt-1 block text-xs text-muted-foreground">
172
+ {t("navigation.trash")}
173
+ </span>
174
+ ) : null}
170
175
  </span>
171
176
  {hit.matchPanel ? (
172
177
  <span className="shrink-0 text-xs text-muted-foreground">
@@ -497,7 +497,9 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
497
497
  to: "/trash",
498
498
  label: t("navigation.trash"),
499
499
  icon: IconTrash,
500
- match: (p) => p.startsWith("/trash"),
500
+ match: (p) =>
501
+ p.startsWith("/trash") ||
502
+ (p.startsWith("/r/") && recordingSection === "trash"),
501
503
  },
502
504
  ];
503
505
 
@@ -254,6 +254,11 @@ export function SearchBar({ className, side = "right" }: SearchBarProps) {
254
254
  <span className="uppercase tracking-wide">
255
255
  {matchLabel(hit, t)}
256
256
  </span>
257
+ {hit.trashedAt ? (
258
+ <span className="rounded-sm border border-border px-1 py-0.5 text-[9px] font-medium uppercase tracking-wide text-muted-foreground">
259
+ {t("navigation.trash")}
260
+ </span>
261
+ ) : null}
257
262
  {typeof hit.matchMs === "number" ? (
258
263
  <>
259
264
  <span aria-hidden="true">·</span>
@@ -110,6 +110,7 @@ export interface SearchHit {
110
110
  title: string;
111
111
  description: string;
112
112
  thumbnailUrl: string | null;
113
+ trashedAt: string | null;
113
114
  durationMs: number;
114
115
  matchType:
115
116
  | "title-description"
@@ -480,19 +480,26 @@ export async function uploadLocalRecording(
480
480
 
481
481
  /**
482
482
  * Discard a local copy this tab owns. Any in-flight upload of it settles
483
- * first, so its bookkeeping cannot race the delete, and the server row that
484
- * upload recorded is trashed unless it is already ready.
483
+ * first, so its bookkeeping cannot race the delete, and every server row the
484
+ * copy produced is trashed unless it is already ready.
485
485
  */
486
486
  export async function discardLocalRecording(
487
487
  localId: string,
488
488
  options: { afterUpload?: Promise<unknown> | null } = {},
489
489
  ): Promise<void> {
490
490
  await options.afterUpload;
491
- // coercion-ok: an unreadable copy is still deleted; its row times out on its own.
492
- const meta = await getRecordingBackupMeta(localId).catch(() => null);
493
- if (meta?.serverRecordingId) {
494
- await trashStaleServerRecordings([meta.serverRecordingId]);
491
+ const ids = new Set<string>();
492
+ try {
493
+ const meta = await getRecordingBackupMeta(localId);
494
+ if (meta?.serverRecordingId) ids.add(meta.serverRecordingId);
495
+ // The row created while recording; each retry uploads to a new id.
496
+ if (meta && !meta.localOnly) ids.add(meta.recordingId);
497
+ for (const id of meta?.staleServerRecordingIds ?? []) ids.add(id);
498
+ } catch {
499
+ // An unreadable copy is keyed by the id of the row its take created.
500
+ ids.add(localId);
495
501
  }
502
+ await trashStaleServerRecordings([...ids]);
496
503
  await deleteRecordingBackup(localId);
497
504
  }
498
505
 
@@ -9,7 +9,7 @@ import { useSyncExternalStore } from "react";
9
9
  * from the same facts — and says so here, so the highlighted section and the
10
10
  * breadcrumb always agree.
11
11
  */
12
- export type RecordingSection = "library" | "screenshots" | "spaces";
12
+ export type RecordingSection = "library" | "screenshots" | "spaces" | "trash";
13
13
 
14
14
  let current: RecordingSection | null = null;
15
15
  const listeners = new Set<() => void>();
@@ -1247,11 +1247,13 @@ export default function RecordingPage() {
1247
1247
  // a folder keeps that real home instead.
1248
1248
  const screenshotIsUnfiled = isImage && !recordingSpace && !recordingFolder;
1249
1249
  // The sidebar highlights the same section the breadcrumb starts with.
1250
- const recordingSection: RecordingSection = recordingSpace
1251
- ? "spaces"
1252
- : screenshotIsUnfiled
1253
- ? "screenshots"
1254
- : "library";
1250
+ const recordingSection: RecordingSection = recording?.trashedAt
1251
+ ? "trash"
1252
+ : recordingSpace
1253
+ ? "spaces"
1254
+ : screenshotIsUnfiled
1255
+ ? "screenshots"
1256
+ : "library";
1255
1257
  useEffect(() => {
1256
1258
  setRecordingSection(recordingSection);
1257
1259
  return () => setRecordingSection(null);
@@ -2758,13 +2758,14 @@ export default function RecordRoute() {
2758
2758
  // A copy left by another visit is taken only once this tab holds its lock;
2759
2759
  // one that another tab owns is never uploaded or deleted from here.
2760
2760
  const openRecoveredCopy = useCallback(
2761
- async (recordingId: string) => {
2761
+ async (recordingId: string): Promise<boolean> => {
2762
2762
  const status = await holdLocalCopy(recordingId);
2763
2763
  if (status === "busy") {
2764
2764
  toast.info(t("recordRoute.localRecordingOpenElsewhere"));
2765
- return;
2765
+ return false;
2766
2766
  }
2767
2767
  enterPendingUploadRef.current(recordingId);
2768
+ return true;
2768
2769
  },
2769
2770
  [holdLocalCopy, t],
2770
2771
  );
@@ -2778,8 +2779,11 @@ export default function RecordRoute() {
2778
2779
  [location.search],
2779
2780
  );
2780
2781
  const sessionEmail = authSession?.email ?? null;
2782
+ // A discarded copy stays locked until deleted; reopening it reads as "busy".
2783
+ const resumedLocalRecordingIdRef = useRef<string | null>(null);
2781
2784
  useEffect(() => {
2782
2785
  if (!resumeLocalRecordingId || !sessionEmail) return;
2786
+ if (resumedLocalRecordingIdRef.current === resumeLocalRecordingId) return;
2783
2787
  if (uiState !== "idle" || pendingLocalRef.current) return;
2784
2788
  let cancelled = false;
2785
2789
  void (async () => {
@@ -2805,7 +2809,9 @@ export default function RecordRoute() {
2805
2809
  void navigate("/record", { replace: true });
2806
2810
  return;
2807
2811
  }
2808
- await openRecoveredCopyRef.current(resumeLocalRecordingId);
2812
+ if (await openRecoveredCopyRef.current(resumeLocalRecordingId)) {
2813
+ resumedLocalRecordingIdRef.current = resumeLocalRecordingId;
2814
+ }
2809
2815
  })();
2810
2816
  return () => {
2811
2817
  cancelled = true;
@@ -3370,9 +3376,13 @@ export default function RecordRoute() {
3370
3376
  discardAutoPausedRef.current = false;
3371
3377
  const intent = discardPrompt;
3372
3378
  setDiscardPrompt(null);
3373
- if (intent === "restart") void restart();
3374
- else void doCancel();
3375
- }, [discardPrompt, doCancel, restart]);
3379
+ if (intent === "restart") {
3380
+ void restart();
3381
+ } else {
3382
+ void doCancel();
3383
+ void navigate("/library");
3384
+ }
3385
+ }, [discardPrompt, doCancel, navigate, restart]);
3376
3386
 
3377
3387
  // "Try again" after a failure never deletes a copy that may still exist:
3378
3388
  // a stored copy goes to the finish-upload step, a memory-only one asks.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-02
4
+ ---
5
+
6
+ Long uploads (an hour or more) now transcribe reliably instead of failing.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-05
4
+ ---
5
+
6
+ Confirming Discard recording now returns you to your library.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-05
4
+ ---
5
+
6
+ Discarding a recording now removes its failed upload card from your library.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-05
4
+ ---
5
+
6
+ Discarding a recovered recording no longer warns that it's open in another tab.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-05
4
+ ---
5
+
6
+ Search results identify recordings in Trash and open them with Trash navigation.
@@ -21,6 +21,7 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@agent-native/core": "workspace:*",
24
+ "@agent-native/otel": "workspace:*",
24
25
  "@agent-native/toolkit": "workspace:*",
25
26
  "@electric-sql/pglite": "^0.5.8",
26
27
  "@ffmpeg/ffmpeg": "^0.12.15",
@@ -0,0 +1,5 @@
1
+ const BUILDER_CDN_HOST_RE = /^cdn(?:-qa)?\.builder\.io$/i;
2
+
3
+ export function isBuilderCdnHost(hostname: string): boolean {
4
+ return BUILDER_CDN_HOST_RE.test(hostname);
5
+ }
@@ -14,6 +14,7 @@ import { and, eq, isNull } from "drizzle-orm";
14
14
 
15
15
  import type { MediaWorkerCallback } from "../../shared/media-worker-contract.js";
16
16
  import { getDb, schema } from "../db/index.js";
17
+ import { isBuilderCdnHost } from "./builder-cdn.js";
17
18
  import { enabledFlag } from "./env-flags.js";
18
19
  import {
19
20
  enqueueMediaWorkerJob,
@@ -24,7 +25,6 @@ import {
24
25
  } from "./media-worker.js";
25
26
  import { ownerEmailMatches } from "./recordings.js";
26
27
 
27
- const BUILDER_CDN_HOST_RE = /^cdn(?:-qa)?\.builder\.io$/i;
28
28
  const DEFAULT_TRIGGER_TIMEOUT_MS = 45_000;
29
29
  const DEFAULT_MAX_SOURCE_BYTES = 512 * 1024 * 1024;
30
30
  const MAX_TRIGGER_ATTEMPTS = 5;
@@ -294,7 +294,7 @@ export function extractBuilderMediaTarget(
294
294
  ): BuilderMediaTarget | null {
295
295
  try {
296
296
  const url = new URL(sourceUrl);
297
- if (!BUILDER_CDN_HOST_RE.test(url.hostname)) return null;
297
+ if (!isBuilderCdnHost(url.hostname)) return null;
298
298
  if (url.searchParams.get("optimized") === "true") return null;
299
299
 
300
300
  let objectPath: string | null = null;
@@ -8,7 +8,8 @@ export default createAuthPlugin({
8
8
  mountGoogleOAuthRoutes: false,
9
9
  marketing: {
10
10
  appName: "Clips",
11
- learnMoreUrl: "https://agent-native.com/apps/clips",
11
+ learnMoreUrl:
12
+ "https://agent-native.com/apps/clips?utm_source=app&utm_medium=product&utm_content=onboarding-learn-more",
12
13
  tagline:
13
14
  "Your AI agent transcribes, summarizes, and searches everything you record alongside you.",
14
15
  features: [
@@ -0,0 +1,6 @@
1
+ import { defineNitroPlugin } from "@agent-native/core/server";
2
+ import { startAgentNativeOtel } from "@agent-native/otel";
3
+
4
+ export default defineNitroPlugin(() => {
5
+ startAgentNativeOtel();
6
+ });
@@ -9,6 +9,8 @@ export type TranscriptFailureCode =
9
9
  | "NO_AUDIO_SAVED"
10
10
  /** Cloud transcription was attempted and threw. */
11
11
  | "CLOUD_FAILED"
12
+ /** A long recording was split and one of its parts could not be transcribed. */
13
+ | "CHUNK_FAILED"
12
14
  /** No cloud provider is connected for this owner. */
13
15
  | "CLOUD_UNCONFIGURED"
14
16
  /** Anything not yet classified. Prose is preserved; never retried blindly. */
@@ -18,6 +20,7 @@ const RETRYABLE: ReadonlySet<TranscriptFailureCode> = new Set([
18
20
  "TIMEOUT",
19
21
  "EXTRACTION_FAILED",
20
22
  "CLOUD_FAILED",
23
+ "CHUNK_FAILED",
21
24
  ]);
22
25
 
23
26
  export function isRetryableTranscriptFailure(
@@ -42,6 +45,8 @@ export function transcriptFailureMessage(code: TranscriptFailureCode): string {
42
45
  return "Transcription timed out before it finished. Retrying usually works.";
43
46
  case "CLOUD_FAILED":
44
47
  return "No transcript was captured locally, and cloud transcription could not finish. Retrying usually works; if it persists, check the recording's audio and the Builder connection.";
48
+ case "CHUNK_FAILED":
49
+ return "Part of this recording could not be transcribed, so no transcript was saved. Retrying usually works.";
45
50
  case "CLOUD_UNCONFIGURED":
46
51
  return "No transcript was captured locally, and no cloud transcription provider is connected. Use Builder.io in Settings to transcribe automatically.";
47
52
  case "UNKNOWN":
@@ -42,11 +42,17 @@ summaries for the visible rows, plus row count and total row count, so agents
42
42
  can tell whether the user is looking at the full collection or a constrained
43
43
  slice and can refer to the same rows and cells the user can currently scan;
44
44
  for calendar and timeline views this summary is limited to rows in the
45
- current visible date window plus rows shown in the "No date" section. When
45
+ current visible date window plus rows shown in the "No date" section. Each
46
+ cell summary carries display `text` (cut at 200 characters with
47
+ `textTruncated: true`) and carries `value` only when it differs from that
48
+ text; read the row with `get-content-database` for full values. The row cap
49
+ shrinks to keep the whole navigation state under 48 KB, and
50
+ `databaseVisibleItemLimit` reports the cap actually applied. When
46
51
  footer calculations are active, navigation state also includes
47
52
  `databaseCalculationResults` with the visible result text for each calculated
48
53
  column. When table rows are selected, navigation state also includes
49
- `databaseSelectedItemCount` and `databaseSelectedItems`, and
54
+ `databaseSelectedItemCount` and `databaseSelectedItems` (under the same
55
+ row cap), and
50
56
  `view-screen.databaseCurrentView` mirrors that selected row summary.
51
57
  `view-screen` exposes the same slice as `databaseCurrentView` alongside the
52
58
  full collection payload. Its row property summaries should mirror the active
@@ -290,9 +290,16 @@ export default defineEventHandler(async (event) => {
290
290
 
291
291
  ## Data Scoping
292
292
 
293
- In production, the framework automatically restricts all agent SQL queries to the current user's data using temporary views. This is enforced at the SQL level — the agent cannot bypass it.
293
+ In production, the framework automatically restricts all agent SQL queries to the current user's data using temporary views, and checks every statement before it runs so it can only reach those views.
294
294
 
295
- The `db-query` / `db-exec` tools (and the extension SQL bridge, which shares the same path) reject schema-qualified table references like `public.<table>` — a qualified name resolves to the base table and would skip the temp view. Use bare table names; scoping is applied automatically.
295
+ The `db-query` / `db-exec` / `db-patch` tools (and the extension SQL bridge, which shares the same path) read each statement the way Postgres does and refuse anything that could reach data around the temp views:
296
+
297
+ - schema- or database-qualified names like `public.<table>`, which resolve to the base table;
298
+ - names that resolve to anything other than the current user's temp views, such as materialized views or tables the scoping does not cover;
299
+ - app-defined SQL or PL/pgSQL functions and operators, whose bodies read tables without the views;
300
+ - built-ins that run SQL text, change session settings, or reach outside the database (`query_to_xml`, `set_config`, `dblink`, most `pg_*` functions).
301
+
302
+ `db-query` runs in a read-only transaction, and an `INSERT` must list its columns when the table has access-control columns. Use bare table names and plain expressions; scoping is applied automatically. When the agent needs data the views do not expose, add an app action with its own access checks.
296
303
 
297
304
  ### Per-User Scoping (`owner_email`)
298
305
 
@@ -75,10 +75,11 @@ state their PostgreSQL types directly.
75
75
 
76
76
  Member offboarding and email changes refuse to run while any column named
77
77
  `email`, `*_email`, `*scope_id`, `created_by`, `updated_by`, `invited_by`,
78
- `owner`, `principal_id`, `session_id`, or `user_id` has no policy. `owner_email`
79
- and `createSharesTable()` tables are handled for you. Declare every other one,
80
- including columns that are not member identities, from the app's database
81
- plugin graph (Clips does it in `server/db/index.ts`):
78
+ `owner`, `principal_id`, `session_id`, or `user_id` has no policy.
79
+ `createSharesTable()` tables are handled for you, and undeclared `owner_email`
80
+ columns transfer to the successor, which is right only for owned content.
81
+ Declare every other one, including columns that are not member identities, from
82
+ the app's database plugin graph (Clips does it in `server/db/index.ts`):
82
83
 
83
84
  ```ts
84
85
  import { registerIdentityColumns } from "@agent-native/core/org";
@@ -88,13 +89,17 @@ registerIdentityColumns([
88
89
  { table: "space_members", column: "email", emailChange: "rekey", offboard: "delete", orgScope: { column: "space_id", references: { table: "spaces", column: "id", orgColumn: "org_id" } }, reason: "Space membership grants access." },
89
90
  // Someone else's address: never rewritten.
90
91
  { table: "meeting_participants", column: "email", emailChange: "retain", offboard: "retain", reason: "Attendee address from the calendar provider." },
92
+ // A credential in an owner_email table: never handed to the successor.
93
+ { table: "api_keys", column: "owner_email", emailChange: "rekey", offboard: "revoke", reason: "Bearer keys act as their owner." },
91
94
  ]);
92
95
  ```
93
96
 
94
- Choose `delete` for grants, credentials, and pending tokens; `retain` for
97
+ Choose `delete` for grants, credentials, and pending tokens, or `revoke` (sets
98
+ `revoked_at`) when a reader treats a missing row as "not revoked"; `retain` for
95
99
  attribution, history, and third-party addresses; `transfer` only for owned
96
- data. A table without `org_id` needs `orgScope` or an organization-scoped
97
- removal leaves its rows alone.
100
+ data. Declare `owner_email` tables that hold credentials or grants, or
101
+ offboarding hands them to the successor. A table without `org_id` needs
102
+ `orgScope` or an organization-scoped removal leaves its rows alone.
98
103
 
99
104
  | Template | Tables |
100
105
  | ------------ | --------------------------------------------- |
@@ -3,10 +3,51 @@
3
3
  All notable user-facing changes to Agent-Native Content are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new").
5
5
 
6
+ ## 2026-10-05
7
+
8
+ ### Improved
9
+
10
+ - Collection pages keep selected rows visible through failed refreshes, and review space stays in place while comments refresh.
11
+
12
+ ### Fixed
13
+
14
+ - Collection view context now survives quick page changes when the saved summary fits.
15
+ - Exact saved-view links keep the collection retry available when rows fail to load
16
+ - Expanding a Files folder now shares one navigation read across open branches, and legacy owner shares retain their row controls.
17
+ - Files navigation retries temporary failures consistently
18
+ - Shared page owners keep edit and manage controls in Files, and newly opened folders populate faster.
19
+ - Tagging an AI in a comment works again instead of failing right away with "AI request failed".
20
+ - The home loading shell keeps the layout of your last opened page.
21
+ - Typing `>` and a space, or inserting a toggle or callout, no longer freezes and crashes the page on a Mac.
22
+
23
+ ## 2026-10-03
24
+
25
+ ### Fixed
26
+
27
+ - A malformed Lab preference no longer blocks unrelated editor commands.
28
+
29
+ ## 2026-10-02
30
+
31
+ ### Improved
32
+
33
+ - After a refresh, the Files sidebar shows the open page's folders in one load instead of one level at a time
34
+ - Builder.io setup instructions now use consistent action language across editor workflows.
35
+ - Large collections open faster
36
+ - Pages with open comments and collections with sorted or filtered views no longer jump while they load
37
+
38
+ ### Fixed
39
+
40
+ - A page link you can't open now says so, with the account you're signed in as, instead of opening another page. People who can open a private share link no longer see "This document is private" first.
41
+ - Comment edits and deletions now refresh collaborators with the document open.
42
+ - Pages stay inside the window at every width: long inline code and links wrap, and wide tables scroll inside their own frame instead of crushing their columns
43
+ - Suggest edits works on pages written by agents, including pages with Markdown tables, instead of refusing to start or rejecting each edit; suggestions inside a table cell are still not supported
44
+ - While you suggest edits, tables and other blocks that suggestions don't support yet are read-only, and an agent that tries to suggest a change inside one gets a clear message instead of "Internal server error".
45
+
6
46
  ## 2026-10-01
7
47
 
8
48
  ### Improved
9
49
 
50
+ - Home opens the page you were last on sooner
10
51
  - Pages and the sidebar load in place instead of jumping around
11
52
 
12
53
  ### Fixed
@@ -4,7 +4,7 @@ Open-source Obsidian for MDX — an agent-native, local-file document workspace
4
4
  a self-hostable alternative to Notion and Obsidian. Edit local Markdown/MDX files,
5
5
  build Notion-style collections, and write with an AI agent.
6
6
 
7
- **Live app: [content.agent-native.com](https://content.agent-native.com)**
7
+ **Live app: [content.agent-native.com](https://content.agent-native.com?utm_source=github&utm_medium=referral&utm_content=content-readme)**
8
8
 
9
9
  Open a doc and ask "rewrite this paragraph to be more concise" or "create a page
10
10
  called Q4 Planning with sub-pages for Goals, Metrics, and Risks" — the same result
@@ -31,4 +31,4 @@ pnpm install
31
31
  pnpm dev
32
32
  ```
33
33
 
34
- Full docs: [agent-native.com/docs/template-content](https://agent-native.com/docs/template-content).
34
+ Full docs: [agent-native.com/docs/template-content](https://agent-native.com/docs/template-content?utm_source=github&utm_medium=referral&utm_content=content-readme).