@agent-native/core 0.157.2 → 0.157.4

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 (167) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  3. package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +21 -0
  4. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +40 -1
  5. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  6. package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +21 -0
  7. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  8. package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +21 -0
  9. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  10. package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +21 -0
  11. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +3 -1
  12. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  13. package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
  14. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  15. package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +7 -7
  16. package/corpus/templates/clips/actions/approve-recording-access-request.ts +147 -0
  17. package/corpus/templates/clips/actions/request-recording-access.ts +121 -23
  18. package/corpus/templates/clips/actions/view-screen.ts +1 -1
  19. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +34 -53
  20. package/corpus/templates/clips/app/components/player/request-access-dialog.tsx +104 -0
  21. package/corpus/templates/clips/app/components/player/share-dialog.tsx +36 -45
  22. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +3 -6
  23. package/corpus/templates/clips/app/i18n/en-US.ts +26 -1
  24. package/corpus/templates/clips/app/lib/public-meeting.ts +1 -1
  25. package/corpus/templates/clips/app/routes/access-request.approve.tsx +250 -0
  26. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +9 -32
  27. package/corpus/templates/clips/app/routes/share.$shareId.tsx +123 -37
  28. package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +41 -1
  29. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +1 -0
  30. package/corpus/templates/clips/server/lib/emails.ts +40 -11
  31. package/corpus/templates/clips/shared/recording-link.ts +32 -1
  32. package/corpus/templates/clips/shared/share-attribution.ts +13 -0
  33. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  34. package/corpus/templates/content/.agents/skills/sharing/SKILL.md +21 -0
  35. package/corpus/templates/content/actions/add-database-item.ts +9 -0
  36. package/corpus/templates/content/actions/describe-content-database.ts +92 -0
  37. package/corpus/templates/content/actions/list-content-databases.ts +213 -72
  38. package/corpus/templates/content/actions/set-document-property.ts +9 -0
  39. package/corpus/templates/content/actions/submit-content-database-form.ts +9 -0
  40. package/corpus/templates/content/actions/update-document.ts +9 -0
  41. package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +22 -10
  42. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +2 -1
  43. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +245 -9
  44. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +192 -134
  45. package/corpus/templates/content/app/components/editor/database/settings.tsx +7 -0
  46. package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +61 -45
  47. package/corpus/templates/content/app/components/editor/extensions/ImageNode.ts +6 -0
  48. package/corpus/templates/content/app/components/editor/image-upload.ts +137 -5
  49. package/corpus/templates/content/app/global.css +8 -0
  50. package/corpus/templates/content/app/hooks/use-content-database.ts +91 -11
  51. package/corpus/templates/content/changelog/2026-08-12-image-uploads-now-confirm-the-image-can-be-displayed-before-.md +6 -0
  52. package/corpus/templates/content/changelog/2026-08-14-images-fill-the-page-width-by-default-and-remain-visible-whe.md +6 -0
  53. package/corpus/templates/content/changelog/2026-08-14-images-inserted-from-the-slash-command-stay-saved-after-uplo.md +6 -0
  54. package/corpus/templates/content/changelog/2026-08-14-svg-files-can-be-selected-reliably-from-the-image-picker.md +6 -0
  55. package/corpus/templates/content/parity/matrix.md +1 -1
  56. package/corpus/templates/content/parity/matrix.ts +7 -1
  57. package/corpus/templates/content/server/plugins/agent-chat.ts +3 -0
  58. package/corpus/templates/content/shared/api.ts +9 -0
  59. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  60. package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +21 -0
  61. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  62. package/corpus/templates/design/.agents/skills/sharing/SKILL.md +21 -0
  63. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  64. package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +21 -0
  65. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  66. package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +21 -0
  67. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  68. package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +21 -0
  69. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  70. package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +21 -0
  71. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  72. package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +21 -0
  73. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +6 -1
  74. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  75. package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +21 -0
  76. package/corpus/templates/plan/app/pages/PlansPage.tsx +25 -30
  77. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  78. package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +21 -0
  79. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +2 -1
  80. package/corpus/templates/slides/app/components/editor/ShareDialog.tsx +124 -180
  81. package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +1 -0
  82. package/corpus/templates/slides/app/global.css +99 -3
  83. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  84. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  85. package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +21 -0
  86. package/dist/chat-threads/schema.d.ts +1 -1
  87. package/dist/cli/code-agent-executor.js +318 -0
  88. package/dist/client/AgentPanel.d.ts +13 -1
  89. package/dist/client/AgentPanel.js +41 -3
  90. package/dist/client/AssistantChat.d.ts +9 -1
  91. package/dist/client/AssistantChat.js +26 -13
  92. package/dist/client/MultiTabAssistantChat.js +18 -5
  93. package/dist/client/agent-chat.d.ts +8 -0
  94. package/dist/client/agent-chat.js +15 -0
  95. package/dist/client/app-chat-sidebar.d.ts +23 -0
  96. package/dist/client/app-chat-sidebar.js +53 -0
  97. package/dist/client/app-providers.js +31 -2
  98. package/dist/client/frame-protocol.d.ts +20 -2
  99. package/dist/client/hooks/index.d.ts +1 -0
  100. package/dist/client/hooks/index.js +1 -0
  101. package/dist/client/sharing/AgentShareSection.d.ts +8 -0
  102. package/dist/client/sharing/AgentShareSection.js +50 -0
  103. package/dist/client/sharing/ShareButton.js +2 -1
  104. package/dist/client/sharing/ShareDialog.d.ts +2 -2
  105. package/dist/client/sharing/ShareDialog.js +21 -29
  106. package/dist/client/sharing/index.d.ts +1 -0
  107. package/dist/client/sharing/index.js +1 -0
  108. package/dist/client/sharing/useShareButtonController.d.ts +1 -0
  109. package/dist/client/sharing/useShareDialogController.d.ts +3 -0
  110. package/dist/client/sharing/useShareDialogController.js +2 -1
  111. package/dist/client/theme.d.ts +21 -0
  112. package/dist/client/theme.js +60 -0
  113. package/dist/client/ui/index.d.ts +1 -1
  114. package/dist/client/ui/index.js +1 -1
  115. package/dist/client/use-session.js +23 -0
  116. package/dist/collab/awareness.d.ts +2 -2
  117. package/dist/collab/routes.d.ts +1 -1
  118. package/dist/collab/struct-routes.d.ts +1 -1
  119. package/dist/dashboard-storage/schema.d.ts +1 -1
  120. package/dist/data-programs/schema.d.ts +1 -1
  121. package/dist/extensions/schema.d.ts +1 -1
  122. package/dist/localization/core-messages/ar-SA.js +6 -0
  123. package/dist/localization/core-messages/de-DE.js +6 -0
  124. package/dist/localization/core-messages/en-US.d.ts +6 -0
  125. package/dist/localization/core-messages/en-US.js +6 -0
  126. package/dist/localization/core-messages/es-ES.js +6 -0
  127. package/dist/localization/core-messages/fr-FR.js +6 -0
  128. package/dist/localization/core-messages/hi-IN.js +6 -0
  129. package/dist/localization/core-messages/ja-JP.js +6 -0
  130. package/dist/localization/core-messages/ko-KR.js +6 -0
  131. package/dist/localization/core-messages/pt-BR.js +6 -0
  132. package/dist/localization/core-messages/zh-CN.js +6 -0
  133. package/dist/localization/core-messages/zh-TW.js +6 -0
  134. package/dist/localization/core-messages.d.ts +6 -0
  135. package/dist/localization/default-messages.d.ts +1 -0
  136. package/dist/localization/default-messages.js +1 -0
  137. package/dist/notifications/routes.d.ts +3 -3
  138. package/dist/observability/routes.d.ts +5 -5
  139. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  140. package/dist/provider-api/actions/provider-api.d.ts +14 -14
  141. package/dist/secrets/routes.d.ts +9 -9
  142. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  143. package/dist/server/auth.js +8 -5
  144. package/dist/server/identity-sso-store.d.ts +6 -1
  145. package/dist/server/identity-sso-store.js +57 -14
  146. package/dist/server/identity-sso.d.ts +7 -8
  147. package/dist/server/identity-sso.js +15 -12
  148. package/dist/sharing/actions/list-resource-shares.d.ts +2 -0
  149. package/dist/sharing/actions/list-resource-shares.js +1 -0
  150. package/dist/sharing/schema.d.ts +1 -1
  151. package/dist/sharing/schema.js +4 -1
  152. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  153. package/dist/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
  154. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  155. package/dist/templates/default/.agents/skills/sharing/SKILL.md +21 -0
  156. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  157. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  158. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +21 -0
  159. package/docs/content/cross-app-sso.mdx +24 -17
  160. package/package.json +3 -3
  161. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  162. package/src/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
  163. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  164. package/src/templates/default/.agents/skills/sharing/SKILL.md +21 -0
  165. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  166. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
  167. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +21 -0
@@ -7,8 +7,19 @@ interface UploadResponse {
7
7
  statusMessage?: unknown;
8
8
  }
9
9
 
10
- function isImageFile(file: File): boolean {
11
- return file.type.startsWith("image/");
10
+ function normalizeImageFile(file: File): File | null {
11
+ const mimeType = file.type.split(";")[0]?.trim().toLowerCase() ?? "";
12
+ if (/\.svg$/i.test(file.name)) {
13
+ if (mimeType === "image/svg+xml") return file;
14
+ if (mimeType === "" || mimeType === "application/octet-stream") {
15
+ return new File([file], file.name, {
16
+ type: "image/svg+xml",
17
+ lastModified: file.lastModified,
18
+ });
19
+ }
20
+ return null;
21
+ }
22
+ return mimeType.startsWith("image/") ? file : null;
12
23
  }
13
24
 
14
25
  function isVideoFile(file: File): boolean {
@@ -21,6 +32,122 @@ function isAudioFile(file: File): boolean {
21
32
 
22
33
  type MediaUploadKind = "image" | "video" | "audio";
23
34
 
35
+ const IMAGE_LOAD_TIMEOUT_MS = 15_000;
36
+
37
+ export class ImageRenderError extends Error {
38
+ constructor() {
39
+ super("Image could not be loaded.");
40
+ this.name = "ImageRenderError";
41
+ }
42
+ }
43
+
44
+ export class ImagePersistenceError extends Error {
45
+ constructor() {
46
+ super("Image could not be saved.");
47
+ this.name = "ImagePersistenceError";
48
+ }
49
+ }
50
+
51
+ export function waitForRenderedImage(
52
+ findImage: () => HTMLImageElement | null,
53
+ ): Promise<void> {
54
+ return new Promise((resolve, reject) => {
55
+ let image: HTMLImageElement | null = null;
56
+ let frame = 0;
57
+ const timeout = window.setTimeout(
58
+ () => finish(false),
59
+ IMAGE_LOAD_TIMEOUT_MS,
60
+ );
61
+
62
+ function cleanup() {
63
+ window.clearTimeout(timeout);
64
+ window.cancelAnimationFrame(frame);
65
+ if (image) {
66
+ image.removeEventListener("load", handleLoad);
67
+ image.removeEventListener("error", handleError);
68
+ }
69
+ }
70
+
71
+ function finish(loaded: boolean) {
72
+ cleanup();
73
+ if (loaded) resolve();
74
+ else reject(new ImageRenderError());
75
+ }
76
+
77
+ function handleLoad() {
78
+ frame = window.requestAnimationFrame(observe);
79
+ }
80
+
81
+ function handleError() {
82
+ finish(false);
83
+ }
84
+
85
+ function observe() {
86
+ image = findImage();
87
+ if (!image) {
88
+ frame = window.requestAnimationFrame(observe);
89
+ return;
90
+ }
91
+ if (image.complete) {
92
+ if (image.naturalWidth <= 0) {
93
+ finish(false);
94
+ return;
95
+ }
96
+ const bounds = image.getBoundingClientRect();
97
+ if (bounds.width > 0 && bounds.height > 0) {
98
+ finish(true);
99
+ return;
100
+ }
101
+ frame = window.requestAnimationFrame(observe);
102
+ return;
103
+ }
104
+ image.addEventListener("load", handleLoad, { once: true });
105
+ image.addEventListener("error", handleError, { once: true });
106
+ }
107
+
108
+ observe();
109
+ });
110
+ }
111
+
112
+ export async function completeImageFileUpload({
113
+ file,
114
+ stageAttributes,
115
+ waitForRender,
116
+ commitAttributes,
117
+ persistCommittedImage,
118
+ upload = uploadImageFile,
119
+ }: {
120
+ file: File;
121
+ stageAttributes: (src: string) => void;
122
+ waitForRender: () => Promise<void>;
123
+ commitAttributes: (src: string) => void;
124
+ persistCommittedImage: () => boolean | Promise<boolean>;
125
+ upload?: (file: File) => Promise<string>;
126
+ }): Promise<string> {
127
+ const src = await upload(file);
128
+ stageAttributes(src);
129
+ await waitForRender();
130
+ commitAttributes(src);
131
+ if (!(await persistCommittedImage())) throw new ImagePersistenceError();
132
+ return src;
133
+ }
134
+
135
+ export function createMediaUploadId(kind: MediaUploadKind): string {
136
+ const random =
137
+ typeof crypto !== "undefined" && "randomUUID" in crypto
138
+ ? crypto.randomUUID()
139
+ : Math.random().toString(36).slice(2);
140
+ return `${kind}-upload-${random}`;
141
+ }
142
+
143
+ export function createImagePickerId(): string {
144
+ const random =
145
+ typeof crypto !== "undefined" && "randomUUID" in crypto
146
+ ? crypto.randomUUID()
147
+ : Math.random().toString(36).slice(2);
148
+ return `image-picker-${random}`;
149
+ }
150
+
24
151
  function mediaUploadLabel(kind: MediaUploadKind) {
25
152
  if (kind === "image") return "Image";
26
153
  if (kind === "video") return "Video";
@@ -31,7 +158,10 @@ export function getImageFiles(
31
158
  files: FileList | File[] | null | undefined,
32
159
  ): File[] {
33
160
  if (!files) return [];
34
- return Array.from(files).filter(isImageFile);
161
+ return Array.from(files).flatMap((file) => {
162
+ const normalized = normalizeImageFile(file);
163
+ return normalized ? [normalized] : [];
164
+ });
35
165
  }
36
166
 
37
167
  export function getVideoFiles(
@@ -107,7 +237,7 @@ async function uploadMediaFile(
107
237
  ): Promise<string> {
108
238
  const isValidFile =
109
239
  kind === "image"
110
- ? isImageFile(file)
240
+ ? normalizeImageFile(file) !== null
111
241
  : kind === "video"
112
242
  ? isVideoFile(file)
113
243
  : isAudioFile(file);
@@ -153,7 +283,9 @@ async function uploadMediaFile(
153
283
  }
154
284
 
155
285
  export async function uploadImageFile(file: File): Promise<string> {
156
- return uploadMediaFile(file, "image");
286
+ const normalized = normalizeImageFile(file);
287
+ if (!normalized) throw new Error("Only image files can be uploaded.");
288
+ return uploadMediaFile(normalized, "image");
157
289
  }
158
290
 
159
291
  export async function uploadVideoFile(file: File): Promise<string> {
@@ -1325,6 +1325,10 @@ div[data-notion-column] > :last-child {
1325
1325
  transition: box-shadow 0.15s ease;
1326
1326
  }
1327
1327
 
1328
+ .notion-editor .node-image .media-block {
1329
+ width: 100%;
1330
+ }
1331
+
1328
1332
  .media-empty-block {
1329
1333
  position: relative;
1330
1334
  width: 100%;
@@ -1439,6 +1443,10 @@ div[data-notion-column] > :last-child {
1439
1443
  user-select: none;
1440
1444
  }
1441
1445
 
1446
+ .notion-editor .node-image .media-block__content {
1447
+ width: 100%;
1448
+ }
1449
+
1442
1450
  .media-block__broken {
1443
1451
  display: flex;
1444
1452
  align-items: center;
@@ -1,4 +1,5 @@
1
1
  import {
2
+ callAction,
2
3
  useActionMutation,
3
4
  useActionQuery,
4
5
  } from "@agent-native/core/client/hooks";
@@ -56,7 +57,7 @@ import type {
56
57
  ValidateBuilderSourceExecutionRequest,
57
58
  } from "@shared/api";
58
59
  import type { Query, QueryClient } from "@tanstack/react-query";
59
- import { useQueryClient } from "@tanstack/react-query";
60
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
60
61
 
61
62
  import { documentQueryFilter } from "../lib/document-query";
62
63
 
@@ -1390,16 +1391,95 @@ export function useContentDatabases(args: {
1390
1391
  excludeDatabaseIds?: string[];
1391
1392
  enabled: boolean;
1392
1393
  }) {
1393
- return useActionQuery<ListContentDatabasesResponse>(
1394
- "list-content-databases",
1395
- args.enabled
1396
- ? {
1397
- excludeDatabaseId: args.excludeDatabaseId ?? undefined,
1398
- excludeDatabaseIds: args.excludeDatabaseIds ?? undefined,
1399
- }
1400
- : undefined,
1401
- { enabled: args.enabled, retry: false },
1402
- );
1394
+ const filters = {
1395
+ excludeDatabaseId: args.excludeDatabaseId ?? undefined,
1396
+ excludeDatabaseIds: args.excludeDatabaseIds ?? undefined,
1397
+ };
1398
+ return useQuery({
1399
+ queryKey: ["action", "list-content-databases", filters],
1400
+ queryFn: async ({ signal }) => ({
1401
+ databases: await fetchCompleteContentDatabaseList((offset, limit) =>
1402
+ callAction<ListContentDatabasesResponse>(
1403
+ "list-content-databases",
1404
+ { ...filters, offset, limit },
1405
+ { method: "GET", signal },
1406
+ ),
1407
+ ),
1408
+ }),
1409
+ enabled: args.enabled,
1410
+ retry: false,
1411
+ });
1412
+ }
1413
+
1414
+ const CONTENT_DATABASE_LIST_PAGE_SIZE = 50;
1415
+
1416
+ export async function fetchCompleteContentDatabaseList(
1417
+ fetchPage: (
1418
+ offset: number,
1419
+ limit: number,
1420
+ ) => Promise<ListContentDatabasesResponse>,
1421
+ ) {
1422
+ const databases: ListContentDatabasesResponse["databases"] = [];
1423
+ const databaseIds = new Set<string>();
1424
+ let offset = 0;
1425
+ let expectedTotal: number | null = null;
1426
+
1427
+ while (true) {
1428
+ const page = await fetchPage(offset, CONTENT_DATABASE_LIST_PAGE_SIZE);
1429
+ const { pagination } = page;
1430
+ if (!pagination) {
1431
+ throw new Error(
1432
+ "list-content-databases returned no pagination boundary; refusing to treat the result as complete.",
1433
+ );
1434
+ }
1435
+ if (
1436
+ pagination.offset !== offset ||
1437
+ pagination.limit !== CONTENT_DATABASE_LIST_PAGE_SIZE ||
1438
+ pagination.returnedItems !== page.databases.length
1439
+ ) {
1440
+ throw new Error(
1441
+ "list-content-databases returned inconsistent pagination metadata; retry the complete read.",
1442
+ );
1443
+ }
1444
+ if (expectedTotal === null) expectedTotal = pagination.totalItems;
1445
+ if (pagination.totalItems !== expectedTotal) {
1446
+ throw new Error(
1447
+ "Content databases changed during paginated discovery; retry the complete read.",
1448
+ );
1449
+ }
1450
+ for (const database of page.databases) {
1451
+ if (databaseIds.has(database.databaseId)) {
1452
+ throw new Error(
1453
+ `list-content-databases repeated database "${database.databaseId}" across pages; refusing an ambiguous result.`,
1454
+ );
1455
+ }
1456
+ databaseIds.add(database.databaseId);
1457
+ databases.push(database);
1458
+ }
1459
+
1460
+ const expectedNextOffset = offset + page.databases.length;
1461
+ if (!pagination.hasMore) {
1462
+ if (
1463
+ pagination.nextOffset !== null ||
1464
+ expectedNextOffset !== expectedTotal ||
1465
+ databases.length !== expectedTotal
1466
+ ) {
1467
+ throw new Error(
1468
+ "list-content-databases claimed exhaustion before every declared database was returned.",
1469
+ );
1470
+ }
1471
+ return databases;
1472
+ }
1473
+ if (
1474
+ pagination.nextOffset !== expectedNextOffset ||
1475
+ pagination.nextOffset <= offset
1476
+ ) {
1477
+ throw new Error(
1478
+ "list-content-databases returned a non-advancing continuation; refusing a clipped result.",
1479
+ );
1480
+ }
1481
+ offset = pagination.nextOffset;
1482
+ }
1403
1483
  }
1404
1484
 
1405
1485
  export function useSuggestSourceJoinKey(args: {
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-12
4
+ ---
5
+
6
+ Image uploads now confirm the image can be displayed before reporting success
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-14
4
+ ---
5
+
6
+ Images fill the page width by default and remain visible when more images are added
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-14
4
+ ---
5
+
6
+ Images inserted from the slash command stay saved after upload
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-14
4
+ ---
5
+
6
+ SVG files can be selected reliably from the image picker
@@ -6,7 +6,7 @@ This generated matrix tracks whether high-value Content UI operations use the sa
6
6
  | -------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- | -------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | ------------------------------ |
7
7
  | comments.threads | comments | List, add, reply, resolve, reopen, and delete comment threads | action-backed | `add-comment`, `delete-comment`, `list-comments`, `update-comment` | `app/components/editor/CommentsSidebar.tsx`, `app/hooks/use-comments.ts` | Comment threads, replies, anchors, mentions, resolution state, and deletion are stored through comment actions. | - | - | P0 | seeded | - | - | - |
8
8
  | database.form-submissions | database | Submit public database forms as new rows | action-backed | `submit-content-database-form` | `app/components/editor/database/FormView.tsx` | A validated form submission atomically creates a database row document and its editable property values. | - | - | P0 | covered | `actions/submit-content-database-form.db.test.ts` | - | - |
9
- | database.lifecycle-and-trash | database | Create, soft-delete, restore, list, and inspect content databases | action-backed | `create-content-database`, `create-inline-content-database`, `delete-content-database`, `get-content-database`, `list-content-databases`, `list-trashed-content-databases`, `restore-content-database` | `app/components/editor/SlashCommandMenu.tsx`, `app/hooks/use-content-database.ts`, `app/hooks/use-documents.ts` | Database pages and database records are created, read, soft-deleted, restored, and listed. | - | - | P0 | covered | `actions/content-database-lifecycle.db.test.ts` | `database-source-scope` | - |
9
+ | database.lifecycle-and-trash | database | Create, soft-delete, restore, list, and inspect content databases | action-backed | `create-content-database`, `create-inline-content-database`, `delete-content-database`, `describe-content-database`, `get-content-database`, `list-content-databases`, `list-trashed-content-databases`, `restore-content-database` | `app/components/editor/SlashCommandMenu.tsx`, `app/hooks/use-content-database.ts`, `app/hooks/use-documents.ts` | Database pages and database records are created, read, soft-deleted, restored, and listed. | - | - | P0 | covered | `actions/content-database-lifecycle.db.test.ts`, `actions/list-content-databases.db.test.ts`, `server/plugins/agent-chat.spec.ts`, `../../packages/core/src/server/agent-chat/content-a2a-capabilities.spec.ts` | `database-source-scope` | - |
10
10
  | database.private-preview-drafts | database | Persist and reconcile a user's private database-page preview draft | action-backed | `get-preview-document-draft`, `update-preview-document-draft` | `app/components/editor/database/DatabaseView.tsx`, `app/hooks/use-documents.ts` | A user's private preview draft is read, saved, conflict-checked, or deleted without changing the shared database page until the normal save flow applies it. | These per-user editor-state actions are intentionally hidden from agent tools because preview drafts are a private UI recovery mechanism. | - | P1 | covered | `actions/preview-document-draft.db.test.ts` | - | - |
11
11
  | database.properties-and-view-config | database | Configure properties, values, ordering, and saved views | action-backed | `configure-document-property`, `delete-document-property`, `duplicate-document-property`, `get-content-database-personal-view`, `list-document-properties`, `reorder-document-property`, `set-document-property`, `update-content-database-personal-view`, `update-content-database-view` | `app/components/editor/DocumentProperties.tsx`, `app/components/editor/DocumentDatabase.tsx`, `app/components/editor/database/DatabaseView.tsx`, `app/hooks/use-document-properties.ts` | Property schemas, property values, property order, filters, sorts, grouping, hidden columns, view type, and view settings are stored. | - | - | P0 | covered | `actions/bind-content-database-source-field.db.test.ts`, `actions/content-database-source-actions.test.ts`, `actions/resync-content-database-source.db.test.ts` | `database-source-scope` | - |
12
12
  | database.rows | database | Add, duplicate, move, open, edit, and remove database rows | action-backed | `add-database-item`, `update-database-item`, `upsert-database-item-by-key`, `remove-database-items`, `duplicate-database-items`, `duplicate-database-item`, `migrate-content-database-rows`, `move-database-item`, `set-document-property` | `app/components/editor/DocumentDatabase.tsx`, `app/components/editor/database/DatabaseView.tsx` | Database row memberships and ordering are created, duplicated, moved, edited, and removed without deleting the backing page; bounded migrations atomically update row bodies and properties through the same canonical data model. | - | - | P0 | covered | `actions/database-row-batch-actions.db.test.ts`, `actions/upsert-database-item-by-key.db.test.ts`, `actions/migrate-content-database-rows.db.test.ts`, `parity/__tests__/database-row-batch-reliability.test.ts` | `database-bulk-row-reliability` | - |
@@ -275,6 +275,7 @@ export const parityMatrix: ParityRow[] = [
275
275
  "create-content-database",
276
276
  "create-inline-content-database",
277
277
  "delete-content-database",
278
+ "describe-content-database",
278
279
  "get-content-database",
279
280
  "list-content-databases",
280
281
  "list-trashed-content-databases",
@@ -285,7 +286,12 @@ export const parityMatrix: ParityRow[] = [
285
286
  spinePriority: "P0",
286
287
  testCoverage: "covered",
287
288
  followUpPR: null,
288
- coverageRefs: ["actions/content-database-lifecycle.db.test.ts"],
289
+ coverageRefs: [
290
+ "actions/content-database-lifecycle.db.test.ts",
291
+ "actions/list-content-databases.db.test.ts",
292
+ "server/plugins/agent-chat.spec.ts",
293
+ "../../packages/core/src/server/agent-chat/content-a2a-capabilities.spec.ts",
294
+ ],
289
295
  evalScenarioIds: ["database-source-scope"],
290
296
  },
291
297
  {
@@ -34,6 +34,9 @@ export default createAgentChatPlugin({
34
34
  durableBackgroundRuns: true,
35
35
  actions: loadActionsFromStaticRegistry(actionsRegistry),
36
36
  initialToolNames: INITIAL_TOOL_NAMES,
37
+ mcp: {
38
+ connectorCatalog: ["list-content-databases", "describe-content-database"],
39
+ },
37
40
  anonymousOwner: resolvePublicViewerOwner,
38
41
  extraContext: publicDocumentExtraContext,
39
42
  // Enable sandboxed JavaScript execution so Content agents can fetch,
@@ -1077,11 +1077,20 @@ export interface ChangeContentDatabaseSourceRoleRequest {
1077
1077
  export interface ContentDatabaseSummary {
1078
1078
  databaseId: string;
1079
1079
  documentId: string;
1080
+ spaceId: string | null;
1080
1081
  title: string;
1082
+ description: string;
1083
+ }
1084
+
1085
+ export interface ContentDatabaseDescriptionResponse {
1086
+ database: ContentDatabase;
1087
+ contextPath: ContentContextPathEntry[];
1088
+ properties: DocumentProperty[];
1081
1089
  }
1082
1090
 
1083
1091
  export interface ListContentDatabasesResponse {
1084
1092
  databases: ContentDatabaseSummary[];
1093
+ pagination: DocumentDiscoveryPagination;
1085
1094
  }
1086
1095
 
1087
1096
  export interface TrashedContentDatabaseSummary {
@@ -182,6 +182,11 @@ in the moment of agent use.
182
182
  five-item sidebar preview and a footer row with New chat followed by an
183
183
  ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
184
184
  actions.
185
+ - **Data grid kit**: provider-agnostic spreadsheet mechanics belong in
186
+ `@agent-native/toolkit/data-grid`. Apps provide rows, typed columns, editor
187
+ slots, selection and width state, persistence callbacks, and product-level
188
+ row/body slots. Keep database models, access checks, grouping, drag/drop,
189
+ and domain actions in the app adapter.
185
190
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
186
191
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
187
192
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -184,6 +184,27 @@ import { ShareButton } from "@agent-native/core/client/sharing";
184
184
 
185
185
  For list views, show `<VisibilityBadge visibility={row.visibility} />` next to each resource.
186
186
 
187
+ ## Standard share surface
188
+
189
+ All app share popovers should use the same compact surface contract:
190
+
191
+ - Use the text-only `ShareTrigger` from `@agent-native/toolkit/sharing`.
192
+ - Render ordinary links with `ShareCopyRow`, which exposes a Copy action without
193
+ printing the raw URL.
194
+ - Keep general access and individual people access in the standard Core sharing
195
+ flow. The people flow supports email invites, roles, notifications, and
196
+ removal through the shared share actions.
197
+ - Add `ShareAgentsSection` only when the resource has a real agent-readable
198
+ link or prompt. Keep it collapsed by default and supply domain-specific
199
+ content through the shared section shell.
200
+ - App-specific tabs or controls may remain when they represent a real domain
201
+ action (for example, an embed-code editor), but they should retain the same
202
+ trigger, copy-row, access, and spacing language.
203
+
204
+ `ShareDisclosureSection` is the toolkit-owned shell for optional expandable
205
+ share details; use its `ShareAgentsSection` or `SharePeopleSection` wrappers
206
+ instead of creating another collapsible share panel in a template.
207
+
187
208
  ## Actions available everywhere
188
209
 
189
210
  The framework auto-mounts these actions in every template — no per-template boilerplate:
@@ -182,6 +182,11 @@ in the moment of agent use.
182
182
  five-item sidebar preview and a footer row with New chat followed by an
183
183
  ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
184
184
  actions.
185
+ - **Data grid kit**: provider-agnostic spreadsheet mechanics belong in
186
+ `@agent-native/toolkit/data-grid`. Apps provide rows, typed columns, editor
187
+ slots, selection and width state, persistence callbacks, and product-level
188
+ row/body slots. Keep database models, access checks, grouping, drag/drop,
189
+ and domain actions in the app adapter.
185
190
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
186
191
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
187
192
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -184,6 +184,27 @@ import { ShareButton } from "@agent-native/core/client/sharing";
184
184
 
185
185
  For list views, show `<VisibilityBadge visibility={row.visibility} />` next to each resource.
186
186
 
187
+ ## Standard share surface
188
+
189
+ All app share popovers should use the same compact surface contract:
190
+
191
+ - Use the text-only `ShareTrigger` from `@agent-native/toolkit/sharing`.
192
+ - Render ordinary links with `ShareCopyRow`, which exposes a Copy action without
193
+ printing the raw URL.
194
+ - Keep general access and individual people access in the standard Core sharing
195
+ flow. The people flow supports email invites, roles, notifications, and
196
+ removal through the shared share actions.
197
+ - Add `ShareAgentsSection` only when the resource has a real agent-readable
198
+ link or prompt. Keep it collapsed by default and supply domain-specific
199
+ content through the shared section shell.
200
+ - App-specific tabs or controls may remain when they represent a real domain
201
+ action (for example, an embed-code editor), but they should retain the same
202
+ trigger, copy-row, access, and spacing language.
203
+
204
+ `ShareDisclosureSection` is the toolkit-owned shell for optional expandable
205
+ share details; use its `ShareAgentsSection` or `SharePeopleSection` wrappers
206
+ instead of creating another collapsible share panel in a template.
207
+
187
208
  ## Actions available everywhere
188
209
 
189
210
  The framework auto-mounts these actions in every template — no per-template boilerplate:
@@ -182,6 +182,11 @@ in the moment of agent use.
182
182
  five-item sidebar preview and a footer row with New chat followed by an
183
183
  ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
184
184
  actions.
185
+ - **Data grid kit**: provider-agnostic spreadsheet mechanics belong in
186
+ `@agent-native/toolkit/data-grid`. Apps provide rows, typed columns, editor
187
+ slots, selection and width state, persistence callbacks, and product-level
188
+ row/body slots. Keep database models, access checks, grouping, drag/drop,
189
+ and domain actions in the app adapter.
185
190
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
186
191
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
187
192
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -184,6 +184,27 @@ import { ShareButton } from "@agent-native/core/client/sharing";
184
184
 
185
185
  For list views, show `<VisibilityBadge visibility={row.visibility} />` next to each resource.
186
186
 
187
+ ## Standard share surface
188
+
189
+ All app share popovers should use the same compact surface contract:
190
+
191
+ - Use the text-only `ShareTrigger` from `@agent-native/toolkit/sharing`.
192
+ - Render ordinary links with `ShareCopyRow`, which exposes a Copy action without
193
+ printing the raw URL.
194
+ - Keep general access and individual people access in the standard Core sharing
195
+ flow. The people flow supports email invites, roles, notifications, and
196
+ removal through the shared share actions.
197
+ - Add `ShareAgentsSection` only when the resource has a real agent-readable
198
+ link or prompt. Keep it collapsed by default and supply domain-specific
199
+ content through the shared section shell.
200
+ - App-specific tabs or controls may remain when they represent a real domain
201
+ action (for example, an embed-code editor), but they should retain the same
202
+ trigger, copy-row, access, and spacing language.
203
+
204
+ `ShareDisclosureSection` is the toolkit-owned shell for optional expandable
205
+ share details; use its `ShareAgentsSection` or `SharePeopleSection` wrappers
206
+ instead of creating another collapsible share panel in a template.
207
+
187
208
  ## Actions available everywhere
188
209
 
189
210
  The framework auto-mounts these actions in every template — no per-template boilerplate:
@@ -182,6 +182,11 @@ in the moment of agent use.
182
182
  five-item sidebar preview and a footer row with New chat followed by an
183
183
  ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
184
184
  actions.
185
+ - **Data grid kit**: provider-agnostic spreadsheet mechanics belong in
186
+ `@agent-native/toolkit/data-grid`. Apps provide rows, typed columns, editor
187
+ slots, selection and width state, persistence callbacks, and product-level
188
+ row/body slots. Keep database models, access checks, grouping, drag/drop,
189
+ and domain actions in the app adapter.
185
190
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
186
191
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
187
192
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -184,6 +184,27 @@ import { ShareButton } from "@agent-native/core/client/sharing";
184
184
 
185
185
  For list views, show `<VisibilityBadge visibility={row.visibility} />` next to each resource.
186
186
 
187
+ ## Standard share surface
188
+
189
+ All app share popovers should use the same compact surface contract:
190
+
191
+ - Use the text-only `ShareTrigger` from `@agent-native/toolkit/sharing`.
192
+ - Render ordinary links with `ShareCopyRow`, which exposes a Copy action without
193
+ printing the raw URL.
194
+ - Keep general access and individual people access in the standard Core sharing
195
+ flow. The people flow supports email invites, roles, notifications, and
196
+ removal through the shared share actions.
197
+ - Add `ShareAgentsSection` only when the resource has a real agent-readable
198
+ link or prompt. Keep it collapsed by default and supply domain-specific
199
+ content through the shared section shell.
200
+ - App-specific tabs or controls may remain when they represent a real domain
201
+ action (for example, an embed-code editor), but they should retain the same
202
+ trigger, copy-row, access, and spacing language.
203
+
204
+ `ShareDisclosureSection` is the toolkit-owned shell for optional expandable
205
+ share details; use its `ShareAgentsSection` or `SharePeopleSection` wrappers
206
+ instead of creating another collapsible share panel in a template.
207
+
187
208
  ## Actions available everywhere
188
209
 
189
210
  The framework auto-mounts these actions in every template — no per-template boilerplate:
@@ -182,6 +182,11 @@ in the moment of agent use.
182
182
  five-item sidebar preview and a footer row with New chat followed by an
183
183
  ellipsis disclosure up to fifteen. Apps inject routing, labels, and domain
184
184
  actions.
185
+ - **Data grid kit**: provider-agnostic spreadsheet mechanics belong in
186
+ `@agent-native/toolkit/data-grid`. Apps provide rows, typed columns, editor
187
+ slots, selection and width state, persistence callbacks, and product-level
188
+ row/body slots. Keep database models, access checks, grouping, drag/drop,
189
+ and domain actions in the app adapter.
185
190
  - **Agent page kit**: the full-page `/agent` surface (`AgentTabsPage` from
186
191
  `@agent-native/core/client`) with Context, Files, Connections, Jobs, and
187
192
  Access tabs plus a Personal/Organization scope toggle. The canonical home
@@ -184,6 +184,27 @@ import { ShareButton } from "@agent-native/core/client/sharing";
184
184
 
185
185
  For list views, show `<VisibilityBadge visibility={row.visibility} />` next to each resource.
186
186
 
187
+ ## Standard share surface
188
+
189
+ All app share popovers should use the same compact surface contract:
190
+
191
+ - Use the text-only `ShareTrigger` from `@agent-native/toolkit/sharing`.
192
+ - Render ordinary links with `ShareCopyRow`, which exposes a Copy action without
193
+ printing the raw URL.
194
+ - Keep general access and individual people access in the standard Core sharing
195
+ flow. The people flow supports email invites, roles, notifications, and
196
+ removal through the shared share actions.
197
+ - Add `ShareAgentsSection` only when the resource has a real agent-readable
198
+ link or prompt. Keep it collapsed by default and supply domain-specific
199
+ content through the shared section shell.
200
+ - App-specific tabs or controls may remain when they represent a real domain
201
+ action (for example, an embed-code editor), but they should retain the same
202
+ trigger, copy-row, access, and spacing language.
203
+
204
+ `ShareDisclosureSection` is the toolkit-owned shell for optional expandable
205
+ share details; use its `ShareAgentsSection` or `SharePeopleSection` wrappers
206
+ instead of creating another collapsible share panel in a template.
207
+
187
208
  ## Actions available everywhere
188
209
 
189
210
  The framework auto-mounts these actions in every template — no per-template boilerplate: