@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
@@ -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:
@@ -5,6 +5,7 @@ import {
5
5
  import { agentNativePath } from "@agent-native/core/client/api-path";
6
6
  import { appApiPath } from "@agent-native/core/client/api-path";
7
7
  import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
8
+ import { usePerAppChatOpen } from "@agent-native/core/client/hooks";
8
9
  import { useT } from "@agent-native/core/client/i18n";
9
10
  import { openCommandMenu } from "@agent-native/core/client/navigation";
10
11
  import { InvitationBanner, OrgSwitcher } from "@agent-native/core/client/org";
@@ -372,6 +373,7 @@ function AppLayoutInner({ children }: AppLayoutProps) {
372
373
  if (typeof window === "undefined") return false;
373
374
  return localStorage.getItem(SIDEBAR_COLLAPSE_KEY) === "true";
374
375
  });
376
+ const perAppChatOpen = usePerAppChatOpen();
375
377
  useEffect(() => {
376
378
  if (sidebarPinned) localStorage.setItem("mail-sidebar-pinned", "true");
377
379
  else localStorage.removeItem("mail-sidebar-pinned");
@@ -384,7 +386,10 @@ function AppLayoutInner({ children }: AppLayoutProps) {
384
386
  }
385
387
  }, [sidebarCollapsed]);
386
388
  const showSidebar = sidebarOpen || (sidebarPinned && !isMobile);
387
- const showCollapsedSidebar = sidebarPinned && sidebarCollapsed && !isMobile;
389
+ const showCollapsedSidebar =
390
+ !isMobile &&
391
+ showSidebar &&
392
+ (sidebarPinned ? sidebarCollapsed : perAppChatOpen);
388
393
  const closeSidebar = useCallback(() => {
389
394
  if (!sidebarPinned || isMobile) setSidebarOpen(false);
390
395
  }, [sidebarPinned, isMobile]);
@@ -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:
@@ -8,6 +8,7 @@ import {
8
8
  } from "@agent-native/core/client/agent-chat";
9
9
  import { track } from "@agent-native/core/client/analytics";
10
10
  import { appPath, agentNativePath } from "@agent-native/core/client/api-path";
11
+ import { writeClipboardText } from "@agent-native/core/client/clipboard";
11
12
  import { emailToColor, emailToName } from "@agent-native/core/client/collab";
12
13
  import { PromptComposer } from "@agent-native/core/client/composer";
13
14
  import { useActionQuery, useSession } from "@agent-native/core/client/hooks";
@@ -33,7 +34,7 @@ import {
33
34
  useSetPageTitle,
34
35
  } from "@agent-native/toolkit/app-shell";
35
36
  import { type RichMarkdownCollabUser } from "@agent-native/toolkit/editor";
36
- import { ShareTrigger } from "@agent-native/toolkit/sharing";
37
+ import { ShareCopyRow, ShareTrigger } from "@agent-native/toolkit/sharing";
37
38
  import {
38
39
  SOURCE_AUTHOR_COMMENT_MENTION_EMAIL,
39
40
  extractCommentMentions,
@@ -6192,11 +6193,18 @@ function PlanShareControl({
6192
6193
  }, []);
6193
6194
 
6194
6195
  const copyPublishedUrl = useCallback(
6195
- (url: string) => {
6196
- void navigator.clipboard.writeText(url).then(
6197
- () => toast.success(t("plansPage.share.linkCopied")),
6198
- () => toast.error(t("plansPage.share.copyFailed")),
6199
- );
6196
+ async (url: string) => {
6197
+ try {
6198
+ if (!(await writeClipboardText(url))) {
6199
+ toast.error(t("plansPage.share.copyFailed"));
6200
+ return false;
6201
+ }
6202
+ toast.success(t("plansPage.share.linkCopied"));
6203
+ return true;
6204
+ } catch {
6205
+ toast.error(t("plansPage.share.copyFailed"));
6206
+ return false;
6207
+ }
6200
6208
  },
6201
6209
  [t],
6202
6210
  );
@@ -6334,22 +6342,16 @@ function PlanShareControl({
6334
6342
  </div>
6335
6343
  ) : effectivePublishedUrl ? (
6336
6344
  <div className="space-y-3">
6337
- <div className="flex min-w-0 items-center gap-2 rounded-md border border-border bg-muted/35 px-2.5 py-2">
6338
- <IconLink className="size-4 shrink-0 text-muted-foreground" />
6339
- <span className="min-w-0 truncate text-xs text-muted-foreground">
6340
- {effectivePublishedUrl}
6341
- </span>
6342
- </div>
6345
+ <ShareCopyRow
6346
+ value={effectivePublishedUrl}
6347
+ label={t("plansPage.share.linkLabel", { noun: Noun })}
6348
+ description={t("plansPage.share.hostedCopy", { noun })}
6349
+ copyLabel={t("plansPage.loggedOut.copy")}
6350
+ copiedLabel={t("plansPage.loggedOut.copied")}
6351
+ onCopy={copyPublishedUrl}
6352
+ className="rounded-md border border-border bg-muted/35 px-2.5 py-2"
6353
+ />
6343
6354
  <div className="flex flex-wrap items-center justify-end gap-2">
6344
- <Button
6345
- type="button"
6346
- size="sm"
6347
- variant="ghost"
6348
- onClick={() => copyPublishedUrl(effectivePublishedUrl)}
6349
- >
6350
- <IconCopy className="size-3.5" />
6351
- {t("plansPage.loggedOut.copy")}
6352
- </Button>
6353
6355
  <Button
6354
6356
  type="button"
6355
6357
  size="sm"
@@ -6363,10 +6365,7 @@ function PlanShareControl({
6363
6365
  {t("plansPage.share.updating")}
6364
6366
  </>
6365
6367
  ) : (
6366
- <>
6367
- <IconRefresh className="size-3.5" />
6368
- {t("plansPage.share.updateLink")}
6369
- </>
6368
+ t("plansPage.share.updateLink")
6370
6369
  )}
6371
6370
  </Button>
6372
6371
  <Button type="button" size="sm" asChild>
@@ -6375,7 +6374,6 @@ function PlanShareControl({
6375
6374
  target="_blank"
6376
6375
  rel="noreferrer"
6377
6376
  >
6378
- <IconExternalLink className="size-3.5" />
6379
6377
  {t("plansPage.share.openHostedPlan")}
6380
6378
  </a>
6381
6379
  </Button>
@@ -6394,10 +6392,7 @@ function PlanShareControl({
6394
6392
  {t("plansPage.share.creatingLink")}
6395
6393
  </>
6396
6394
  ) : (
6397
- <>
6398
- <IconLink className="size-4" />
6399
- {t("plansPage.share.createShareableLink")}
6400
- </>
6395
+ t("plansPage.share.createShareableLink")
6401
6396
  )}
6402
6397
  </Button>
6403
6398
  )}
@@ -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:
@@ -816,7 +816,8 @@ export function SlideInner({
816
816
  </div>
817
817
  );
818
818
 
819
- // Slides with fmd-slide class use inline styles — render as raw HTML to avoid layout conflicts
819
+ // Slides with fmd-slide markup carry their layout in the raw HTML contract;
820
+ // render them as-is so supported semantic classes and inline styles survive.
820
821
  const content = typeof slide.content === "string" ? slide.content : "";
821
822
  const isRawHtml =
822
823
  content.includes('class="fmd-slide"') ||
@@ -1,211 +1,155 @@
1
- import { appBasePath } from "@agent-native/core/client/api-path";
1
+ import { appBasePath, appPath } from "@agent-native/core/client/api-path";
2
+ import { writeClipboardText } from "@agent-native/core/client/clipboard";
2
3
  import { useT } from "@agent-native/core/client/i18n";
4
+ import { ShareDialog as CoreShareDialog } from "@agent-native/core/client/sharing";
5
+ import { ShareCopyRow } from "@agent-native/toolkit/sharing";
3
6
  import {
4
- IconShare2,
5
- IconCopy,
6
- IconCheck,
7
- IconLoader2,
8
- IconExternalLink,
9
- IconChevronDown,
10
- } from "@tabler/icons-react";
11
- import { useState, type ReactNode } from "react";
7
+ cloneElement,
8
+ isValidElement,
9
+ useCallback,
10
+ useState,
11
+ type MouseEvent,
12
+ type ReactElement,
13
+ type ReactNode,
14
+ } from "react";
15
+ import { toast } from "sonner";
12
16
 
13
17
  import { CloudUpgrade } from "@/components/CloudUpgrade";
14
- import {
15
- Popover,
16
- PopoverTrigger,
17
- PopoverContent,
18
- } from "@/components/ui/popover";
19
- import {
20
- Tooltip,
21
- TooltipContent,
22
- TooltipTrigger,
23
- } from "@/components/ui/tooltip";
24
18
  import type { Deck } from "@/context/DeckContext";
25
19
  import { useDbStatus } from "@/hooks/use-db-status";
20
+ import { getDeckShareLinkOrder } from "@/lib/deck-share-links";
26
21
 
27
22
  interface ShareDialogProps {
28
23
  deck: Deck;
29
- /** Trigger element rendered as the popover anchor (usually the Share button). */
24
+ /** Trigger element rendered as the dialog anchor (usually the Share button). */
30
25
  children: ReactNode;
31
26
  }
32
27
 
28
+ function getShareUrls(deckId: string) {
29
+ const origin = typeof window === "undefined" ? "" : window.location.origin;
30
+
31
+ return {
32
+ editor:
33
+ typeof window === "undefined"
34
+ ? `/deck/${deckId}`
35
+ : `${origin}${appPath(`/deck/${deckId}`)}`,
36
+ presentation:
37
+ typeof window === "undefined"
38
+ ? `/p/${deckId}`
39
+ : `${origin}${appPath(`/p/${deckId}`)}`,
40
+ };
41
+ }
42
+
33
43
  export default function ShareDialog({ deck, children }: ShareDialogProps) {
34
44
  const t = useT();
35
- const [open, setOpen] = useState(false);
36
- const [shareUrl, setShareUrl] = useState<string | null>(null);
37
- const [loading, setLoading] = useState(false);
38
- const [copied, setCopied] = useState(false);
39
- const [error, setError] = useState("");
40
45
  const { isLocal } = useDbStatus();
41
- const [showCloudUpgrade, setShowCloudUpgrade] = useState(false);
46
+ const [open, setOpen] = useState(false);
47
+ const [shareLink, setShareLink] = useState<{
48
+ deckId: string;
49
+ token: string;
50
+ } | null>(null);
51
+ const [creatingLink, setCreatingLink] = useState(false);
52
+
53
+ const shareUrls = getShareUrls(deck.id);
54
+ const shareLinkOrder = getDeckShareLinkOrder(deck.visibility);
55
+ const shareToken =
56
+ shareLink?.deckId === deck.id ? shareLink.token : undefined;
57
+ const primaryShareLink = shareToken
58
+ ? `${typeof window === "undefined" ? "" : window.location.origin}${appPath(`/share/${shareToken}`)}`
59
+ : undefined;
60
+ const secondaryShareLink = shareUrls[shareLinkOrder.secondary];
42
61
 
43
- const handleShare = async () => {
44
- setLoading(true);
45
- setError("");
62
+ const openShareDialog = useCallback(async () => {
63
+ if (isLocal) {
64
+ setOpen(true);
65
+ return;
66
+ }
67
+ if (shareToken) {
68
+ setOpen(true);
69
+ return;
70
+ }
71
+ if (creatingLink) return;
46
72
 
73
+ setCreatingLink(true);
47
74
  try {
48
- const res = await fetch(`${appBasePath()}/api/share`, {
75
+ const response = await fetch(`${appBasePath()}/api/share`, {
49
76
  method: "POST",
50
77
  headers: { "Content-Type": "application/json" },
51
78
  body: JSON.stringify({ deck }),
52
79
  });
53
-
54
- if (!res.ok) {
55
- const err = await res.json();
56
- throw new Error(err.error || t("share.createFailed"));
80
+ let payload: { error?: unknown; shareToken?: unknown };
81
+ try {
82
+ payload = (await response.json()) as {
83
+ error?: unknown;
84
+ shareToken?: unknown;
85
+ };
86
+ } catch {
87
+ throw new Error(t("share.createFailed"));
57
88
  }
58
-
59
- const data = await res.json();
60
- const url = `${window.location.origin}${appBasePath()}/share/${data.shareToken}`;
61
- setShareUrl(url);
62
- } catch (err: any) {
63
- setError(err.message);
89
+ if (!response.ok) {
90
+ throw new Error(
91
+ typeof payload.error === "string"
92
+ ? payload.error
93
+ : t("share.createFailed"),
94
+ );
95
+ }
96
+ if (typeof payload.shareToken !== "string" || !payload.shareToken) {
97
+ throw new Error(t("share.createFailed"));
98
+ }
99
+ setShareLink({ deckId: deck.id, token: payload.shareToken });
100
+ setOpen(true);
101
+ } catch (error) {
102
+ toast.error(
103
+ error instanceof Error ? error.message : t("share.createFailed"),
104
+ );
64
105
  } finally {
65
- setLoading(false);
106
+ setCreatingLink(false);
66
107
  }
67
- };
108
+ }, [creatingLink, deck, isLocal, shareToken, t]);
68
109
 
69
- const handleCopy = async () => {
70
- if (!shareUrl) return;
71
- await navigator.clipboard.writeText(shareUrl);
72
- setCopied(true);
73
- setTimeout(() => setCopied(false), 2000);
74
- };
110
+ const trigger = isValidElement(children)
111
+ ? (() => {
112
+ const triggerElement = children as ReactElement<{
113
+ onClick?: (event: MouseEvent) => void;
114
+ }>;
115
+ return cloneElement(triggerElement, {
116
+ onClick: (event) => {
117
+ triggerElement.props.onClick?.(event);
118
+ if (!event.defaultPrevented) void openShareDialog();
119
+ },
120
+ });
121
+ })()
122
+ : children;
75
123
 
76
124
  return (
77
- <Popover
78
- open={open}
79
- onOpenChange={(v) => {
80
- setOpen(v);
81
- if (!v) {
82
- setShareUrl(null);
83
- setError("");
84
- }
85
- }}
86
- >
87
- <PopoverTrigger asChild>{children}</PopoverTrigger>
88
- <PopoverContent
89
- align="end"
90
- className="w-[min(420px,calc(100vw-2rem))] bg-card border-border p-4"
91
- >
92
- {showCloudUpgrade || isLocal ? (
93
- <CloudUpgrade
94
- title={t("share.title")}
95
- description={t("share.cloudUpgradeDescription")}
96
- onClose={() => {
97
- setShowCloudUpgrade(false);
98
- setOpen(false);
99
- }}
125
+ <>
126
+ {trigger}
127
+ {open && isLocal ? (
128
+ <CloudUpgrade
129
+ title={t("share.title")}
130
+ description={t("share.cloudUpgradeDescription")}
131
+ onClose={() => setOpen(false)}
132
+ />
133
+ ) : null}
134
+ <CoreShareDialog
135
+ open={open && !isLocal}
136
+ onClose={() => setOpen(false)}
137
+ resourceType="deck"
138
+ resourceId={deck.id}
139
+ resourceTitle={deck.title}
140
+ shareUrl={primaryShareLink}
141
+ linkTabExtras={
142
+ <ShareCopyRow
143
+ label={t("editorToolbar.presentationLink")}
144
+ description={t("editorToolbar.presentationLinkDescription")}
145
+ value={secondaryShareLink}
146
+ copyLabel={t("share.copyLink")}
147
+ copiedLabel={t("share.copied")}
148
+ onCopy={(value) => writeClipboardText(value)}
149
+ className="mt-3"
100
150
  />
101
- ) : (
102
- <>
103
- <div className="mb-3">
104
- <div className="text-foreground flex items-center gap-2 text-sm font-semibold">
105
- <IconShare2 className="w-4 h-4 text-[#609FF8]" />
106
- {t("share.title")}
107
- </div>
108
- </div>
109
-
110
- <div className="space-y-4">
111
- {!shareUrl ? (
112
- <>
113
- <details className="group rounded-md border border-border bg-muted/30">
114
- <summary className="flex cursor-pointer list-none items-center justify-between gap-3 px-3 py-2.5 text-sm font-medium [&::-webkit-details-marker]:hidden">
115
- {t("share.whatGetsShared")}
116
- <IconChevronDown className="size-4 shrink-0 text-muted-foreground transition-transform group-open:rotate-180" />
117
- </summary>
118
- <div className="space-y-3 border-t border-border px-3 py-3 text-xs text-muted-foreground">
119
- <ul className="space-y-1">
120
- <li>
121
- {t("share.slideContent", {
122
- count: deck.slides.length,
123
- })}
124
- </li>
125
- <li>{t("share.presentationView")}</li>
126
- </ul>
127
- <div>
128
- <h4 className="mb-1 font-medium text-foreground/90">
129
- {t("share.whatStaysPrivate")}
130
- </h4>
131
- <ul className="space-y-1">
132
- <li>{t("share.speakerNotes")}</li>
133
- <li>{t("share.otherPresentations")}</li>
134
- <li>{t("share.editingAccess")}</li>
135
- </ul>
136
- </div>
137
- </div>
138
- </details>
139
-
140
- {error && (
141
- <p className="text-xs text-red-400 bg-red-400/10 px-3 py-2 rounded-lg">
142
- {error}
143
- </p>
144
- )}
145
-
146
- <button
147
- onClick={handleShare}
148
- disabled={loading}
149
- className="w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg bg-[#609FF8] hover:bg-[#7AB2FA] disabled:opacity-50 text-black text-sm font-medium transition-colors"
150
- >
151
- {loading ? (
152
- <>
153
- <IconLoader2 className="w-4 h-4 animate-spin" />
154
- {t("share.creatingLink")}
155
- </>
156
- ) : (
157
- <>
158
- <IconShare2 className="w-4 h-4" />
159
- {t("share.createShareLink")}
160
- </>
161
- )}
162
- </button>
163
- </>
164
- ) : (
165
- <>
166
- <div className="flex items-center gap-2">
167
- <input
168
- readOnly
169
- value={shareUrl}
170
- className="flex-1 bg-accent/50 border border-border rounded-lg px-3 py-2 text-sm text-foreground/90 outline-none"
171
- />
172
- <Tooltip>
173
- <TooltipTrigger asChild>
174
- <button
175
- onClick={handleCopy}
176
- className="flex-shrink-0 p-2 rounded-lg bg-accent hover:bg-accent border border-border transition-colors"
177
- aria-label={t("share.copyLink")}
178
- >
179
- {copied ? (
180
- <IconCheck className="w-4 h-4 text-green-400" />
181
- ) : (
182
- <IconCopy className="w-4 h-4 text-muted-foreground" />
183
- )}
184
- </button>
185
- </TooltipTrigger>
186
- <TooltipContent>{t("share.copyLink")}</TooltipContent>
187
- </Tooltip>
188
- </div>
189
-
190
- <a
191
- href={shareUrl}
192
- target="_blank"
193
- rel="noopener noreferrer"
194
- className="flex items-center justify-center gap-2 w-full px-4 py-2 rounded-lg bg-accent hover:bg-accent border border-border text-foreground/70 text-sm transition-colors"
195
- >
196
- <IconExternalLink className="w-3.5 h-3.5" />
197
- {t("share.openSharedLink")}
198
- </a>
199
-
200
- <p className="sr-only text-[11px] text-muted-foreground/70 text-center">
201
- {t("share.anyoneWithLink")}
202
- </p>
203
- </>
204
- )}
205
- </div>
206
- </>
207
- )}
208
- </PopoverContent>
209
- </Popover>
151
+ }
152
+ />
153
+ </>
210
154
  );
211
155
  }
@@ -446,6 +446,7 @@ export function FirstDeckOnboardingFlow({
446
446
  className="mt-8"
447
447
  autoFocus
448
448
  attachmentsEnabled
449
+ voiceEnabled
449
450
  maxDocumentAttachmentBytes={MAX_REFERENCE_FILE_BYTES}
450
451
  documentAttachmentLimitLabel="Slides reference files"
451
452
  disabled={uploading}