@agent-native/core 0.157.3 → 0.157.5
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.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +40 -1
- package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +3 -1
- package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +7 -7
- package/corpus/templates/clips/actions/approve-recording-access-request.ts +147 -0
- package/corpus/templates/clips/actions/request-recording-access.ts +121 -23
- package/corpus/templates/clips/actions/view-screen.ts +1 -1
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +34 -53
- package/corpus/templates/clips/app/components/player/request-access-dialog.tsx +104 -0
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +36 -45
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +3 -6
- package/corpus/templates/clips/app/i18n/en-US.ts +26 -1
- package/corpus/templates/clips/app/lib/public-meeting.ts +1 -1
- package/corpus/templates/clips/app/routes/access-request.approve.tsx +250 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +9 -32
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +123 -37
- package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +41 -1
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +1 -0
- package/corpus/templates/clips/server/lib/emails.ts +40 -11
- package/corpus/templates/clips/shared/recording-link.ts +32 -1
- package/corpus/templates/clips/shared/share-attribution.ts +13 -0
- package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/content/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +22 -10
- package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +2 -1
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +245 -9
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +185 -134
- package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +61 -45
- package/corpus/templates/content/app/components/editor/extensions/ImageNode.ts +6 -0
- package/corpus/templates/content/app/components/editor/image-upload.ts +137 -5
- package/corpus/templates/content/app/global.css +8 -0
- package/corpus/templates/content/changelog/2026-08-12-image-uploads-now-confirm-the-image-can-be-displayed-before-.md +6 -0
- package/corpus/templates/content/changelog/2026-08-14-images-fill-the-page-width-by-default-and-remain-visible-whe.md +6 -0
- package/corpus/templates/content/changelog/2026-08-14-images-inserted-from-the-slash-command-stay-saved-after-uplo.md +6 -0
- package/corpus/templates/content/changelog/2026-08-14-svg-files-can-be-selected-reliably-from-the-image-picker.md +6 -0
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/design/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +6 -1
- package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +25 -30
- package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +21 -0
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +2 -1
- package/corpus/templates/slides/app/components/editor/ShareDialog.tsx +124 -180
- package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +1 -0
- package/corpus/templates/slides/app/global.css +99 -3
- package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
- package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +21 -0
- package/dist/chat-threads/schema.d.ts +1 -1
- package/dist/cli/code-agent-executor.js +318 -0
- package/dist/client/AgentPanel.d.ts +13 -1
- package/dist/client/AgentPanel.js +41 -3
- package/dist/client/AssistantChat.d.ts +9 -1
- package/dist/client/AssistantChat.js +26 -13
- package/dist/client/MultiTabAssistantChat.js +18 -5
- package/dist/client/agent-chat.d.ts +8 -0
- package/dist/client/agent-chat.js +15 -0
- package/dist/client/app-chat-sidebar.d.ts +23 -0
- package/dist/client/app-chat-sidebar.js +53 -0
- package/dist/client/app-providers.js +31 -2
- package/dist/client/frame-protocol.d.ts +20 -2
- package/dist/client/hooks/index.d.ts +1 -0
- package/dist/client/hooks/index.js +1 -0
- package/dist/client/sharing/AgentShareSection.d.ts +8 -0
- package/dist/client/sharing/AgentShareSection.js +50 -0
- package/dist/client/sharing/ShareButton.js +2 -1
- package/dist/client/sharing/ShareDialog.d.ts +2 -2
- package/dist/client/sharing/ShareDialog.js +21 -29
- package/dist/client/sharing/index.d.ts +1 -0
- package/dist/client/sharing/index.js +1 -0
- package/dist/client/sharing/useShareButtonController.d.ts +1 -0
- package/dist/client/sharing/useShareDialogController.d.ts +3 -0
- package/dist/client/sharing/useShareDialogController.js +2 -1
- package/dist/client/theme.d.ts +21 -0
- package/dist/client/theme.js +60 -0
- package/dist/client/ui/index.d.ts +1 -1
- package/dist/client/ui/index.js +1 -1
- package/dist/client/use-session.js +23 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/dashboard-storage/schema.d.ts +1 -1
- package/dist/data-programs/schema.d.ts +1 -1
- package/dist/extensions/schema.d.ts +1 -1
- package/dist/localization/core-messages/ar-SA.js +6 -0
- package/dist/localization/core-messages/de-DE.js +6 -0
- package/dist/localization/core-messages/en-US.d.ts +6 -0
- package/dist/localization/core-messages/en-US.js +6 -0
- package/dist/localization/core-messages/es-ES.js +6 -0
- package/dist/localization/core-messages/fr-FR.js +6 -0
- package/dist/localization/core-messages/hi-IN.js +6 -0
- package/dist/localization/core-messages/ja-JP.js +6 -0
- package/dist/localization/core-messages/ko-KR.js +6 -0
- package/dist/localization/core-messages/pt-BR.js +6 -0
- package/dist/localization/core-messages/zh-CN.js +6 -0
- package/dist/localization/core-messages/zh-TW.js +6 -0
- package/dist/localization/core-messages.d.ts +6 -0
- package/dist/localization/default-messages.d.ts +1 -0
- package/dist/localization/default-messages.js +1 -0
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +14 -14
- package/dist/server/auth.js +8 -5
- package/dist/server/identity-sso-store.d.ts +6 -1
- package/dist/server/identity-sso-store.js +57 -14
- package/dist/server/identity-sso.d.ts +7 -8
- package/dist/server/identity-sso.js +15 -12
- package/dist/sharing/actions/list-resource-shares.d.ts +2 -0
- package/dist/sharing/actions/list-resource-shares.js +1 -0
- package/dist/sharing/schema.d.ts +1 -1
- package/dist/sharing/schema.js +4 -1
- package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
- package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/sharing/SKILL.md +21 -0
- package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +21 -0
- package/docs/content/actions-access-control.mdx +226 -0
- package/docs/content/actions-advanced.mdx +152 -0
- package/docs/content/actions-defining.mdx +275 -0
- package/docs/content/actions-other-surfaces.mdx +167 -0
- package/docs/content/actions-overview.mdx +214 -0
- package/docs/content/actions-run-context.mdx +180 -0
- package/docs/content/agent-surfaces.mdx +1 -1
- package/docs/content/agent-teams.mdx +1 -1
- package/docs/content/agent-web-surfaces.mdx +1 -1
- package/docs/content/audit-log.mdx +1 -1
- package/docs/content/automation-connectors.mdx +1 -1
- package/docs/content/automations.mdx +1 -1
- package/docs/content/blueprint-installer.mdx +1 -1
- package/docs/content/cli-adapters.mdx +1 -1
- package/docs/content/client-agent-chat.mdx +1 -1
- package/docs/content/client-data.mdx +2 -2
- package/docs/content/client-overview.mdx +2 -2
- package/docs/content/components.mdx +1 -1
- package/docs/content/cross-app-sso.mdx +24 -17
- package/docs/content/data-programs.mdx +2 -2
- package/docs/content/database.mdx +1 -1
- package/docs/content/deployment.mdx +1 -1
- package/docs/content/docs-components.mdx +14 -3
- package/docs/content/drop-in-agent.mdx +2 -2
- package/docs/content/durable-resume.mdx +1 -1
- package/docs/content/evals.mdx +1 -1
- package/docs/content/extensions.mdx +1 -1
- package/docs/content/external-agents-catalog.mdx +2 -2
- package/docs/content/external-agents.mdx +1 -1
- package/docs/content/generative-ui.mdx +1 -1
- package/docs/content/getting-started.mdx +1 -1
- package/docs/content/http-api.mdx +4 -4
- package/docs/content/human-approval.mdx +1 -1
- package/docs/content/key-concepts.mdx +1 -1
- package/docs/content/mcp-apps.mdx +1 -1
- package/docs/content/mcp-clients.mdx +1 -1
- package/docs/content/mcp-protocol.mdx +1 -1
- package/docs/content/native-chat-ui.mdx +1 -1
- package/docs/content/observability.mdx +1 -1
- package/docs/content/organizations-teams-permissions.mdx +1 -1
- package/docs/content/processors.mdx +1 -1
- package/docs/content/pure-agent-apps.mdx +1 -1
- package/docs/content/recurring-jobs.mdx +1 -1
- package/docs/content/server-database.mdx +1 -1
- package/docs/content/server-overview.mdx +3 -3
- package/docs/content/server-routes.mdx +2 -2
- package/docs/content/template-analytics-developers.mdx +1 -1
- package/docs/content/template-assets-developers.mdx +1 -1
- package/docs/content/template-brain-developers.mdx +1 -1
- package/docs/content/template-calendar-developers.mdx +1 -1
- package/docs/content/template-chat-first-edits.mdx +1 -1
- package/docs/content/template-chat.mdx +1 -1
- package/docs/content/template-content-developers.mdx +1 -1
- package/docs/content/template-forms-developers.mdx +1 -1
- package/docs/content/template-forms.mdx +1 -1
- package/docs/content/template-mail-developers.mdx +2 -2
- package/docs/content/toolkit-org-team.mdx +1 -1
- package/docs/content/tracking.mdx +1 -1
- package/docs/content/what-is-agent-native.mdx +1 -1
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/chat/.agents/skills/sharing/SKILL.md +21 -0
- package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/sharing/SKILL.md +21 -0
- package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +21 -0
- package/docs/content/actions.mdx +0 -750
|
@@ -7,8 +7,19 @@ interface UploadResponse {
|
|
|
7
7
|
statusMessage?: unknown;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
function
|
|
11
|
-
|
|
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).
|
|
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
|
-
?
|
|
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
|
-
|
|
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;
|
|
@@ -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:
|
|
@@ -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 =
|
|
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:
|