@agent-native/core-corpus 0.222.1 → 0.222.2-nightly-20261029152548
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/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/assets/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/brain/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/brain/server/plugins/auth.ts +1 -1
- package/corpus/templates/brain/server/routes/api/brain/queue/run.post.ts +1 -7
- package/corpus/templates/calendar/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/chat/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/clips/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/clips/app/components/clips-command-menu.tsx +12 -7
- package/corpus/templates/clips/app/components/import-menu.tsx +4 -1
- package/corpus/templates/clips/app/components/library/library-grid.tsx +15 -8
- package/corpus/templates/clips/app/components/library/library-layout.tsx +10 -2
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +4 -7
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +1 -1
- package/corpus/templates/clips/app/routes/_app.screenshots.tsx +16 -0
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +12 -1
- package/corpus/templates/clips/changelog/2026-10-28-fixed-the-share-advanced-popover-so-the-save-buttons-fit-and.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-29-screenshots-are-available-when-enabled-in-labs.md +6 -0
- package/corpus/templates/clips/shared/labs.ts +9 -0
- package/corpus/templates/content/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/content/actions/execute-builder-source-execution.ts +91 -4
- package/corpus/templates/content/changelog/2026-10-27-two-collections-connected-to-the-same-builder-model-can-no-l.md +6 -0
- package/corpus/templates/crm/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/design/.agents/skills/hubspot-email/SKILL.md +2 -2
- package/corpus/templates/design/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/design/.generated/bridge/native-builtin-metadata.generated.ts +326 -0
- package/corpus/templates/design/.generated/bridge/native-worker-source.generated.ts +6 -0
- package/corpus/templates/design/actions/generate-design.ts +19 -16
- package/corpus/templates/dispatch/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/forms/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/mail/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/plan/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/slides/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/corpus/templates/slides-2/.deploy-tmp/agent-native-provided-plugins.mjs +10 -0
- package/package.json +1 -1
package/corpus/README.md
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","analytics-alert-jobs","analytics-rollup-backfill-jobs","auth","collab","config","content-metrics-collection-jobs","core-routes","creative-context","dashboard-report-jobs","db","feature-flags","labs","onboarding","otel","session-replay-retention-jobs","transactional-emails","uptime-monitor-jobs"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","creative-context","db","labs","onboarding","otel"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","brain-jobs","core-routes","db","otel"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -13,12 +13,6 @@ declare global {
|
|
|
13
13
|
export const BRAIN_QUEUE_SWEEP_LIMIT = 25;
|
|
14
14
|
export const BRAIN_MAX_DISTILLATIONS_PER_SWEEP = 2;
|
|
15
15
|
|
|
16
|
-
function productionLike() {
|
|
17
|
-
return (
|
|
18
|
-
process.env.NODE_ENV === "production" || process.env.NETLIFY === "true"
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
16
|
function scheduledFunctionRuntime() {
|
|
23
17
|
return globalThis.__AGENT_NATIVE_BRAIN_SCHEDULED_RUNTIME__ === true;
|
|
24
18
|
}
|
|
@@ -35,7 +29,7 @@ function headerMatchesSecret(header: string | undefined, secret: string) {
|
|
|
35
29
|
export default defineEventHandler(async (event) => {
|
|
36
30
|
const secret = process.env.BRAIN_JOBS_SECRET?.trim(); // guard:allow-env-credential — deployment-level scheduler route secret
|
|
37
31
|
const scheduled = scheduledFunctionRuntime();
|
|
38
|
-
if (!secret &&
|
|
32
|
+
if (!secret && !scheduled) {
|
|
39
33
|
throw createError({
|
|
40
34
|
statusCode: 503,
|
|
41
35
|
statusMessage: "BRAIN_JOBS_SECRET is required",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","core-routes","db","event-rules","oauth-refresh","otel","transactional-emails"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","otel"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","calendar-jobs","config","core-routes","db","feature-flags","labs","onboarding","onboarding-calendar","otel","transactional-email-catalog"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import { useLab } from "@agent-native/core/client/labs";
|
|
2
3
|
import { useOrgRole } from "@agent-native/core/client/org";
|
|
3
4
|
import { docsUrl } from "@agent-native/core/shared";
|
|
4
5
|
import { useCommandMenuShortcut } from "@agent-native/toolkit/app/shared";
|
|
5
6
|
import { CommandMenu } from "@agent-native/toolkit/app/shared";
|
|
7
|
+
import { CLIPS_SCREENSHOTS } from "@shared/labs";
|
|
6
8
|
import {
|
|
7
9
|
IconArchive,
|
|
8
10
|
IconPhoto,
|
|
@@ -393,6 +395,7 @@ export function ClipsCommandMenu({
|
|
|
393
395
|
const location = useLocation();
|
|
394
396
|
const navigate = useNavigate();
|
|
395
397
|
const t = useT();
|
|
398
|
+
const screenshotsEnabled = useLab(CLIPS_SCREENSHOTS);
|
|
396
399
|
const { canManageOrg } = useOrgRole();
|
|
397
400
|
const context = useMemo(
|
|
398
401
|
() => commandRouteContext(location.pathname),
|
|
@@ -614,13 +617,15 @@ export function ClipsCommandMenu({
|
|
|
614
617
|
{t("navigation.dictate")}
|
|
615
618
|
<CommandMenu.Shortcut>G D</CommandMenu.Shortcut>
|
|
616
619
|
</CommandMenu.Item>
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
620
|
+
{screenshotsEnabled && (
|
|
621
|
+
<CommandMenu.Item
|
|
622
|
+
onSelect={() => void navigate("/screenshots")}
|
|
623
|
+
keywords={["screenshots", "screenshot", "images", "stills"]}
|
|
624
|
+
>
|
|
625
|
+
<IconPhoto size={16} />
|
|
626
|
+
{t("navigation.screenshots")}
|
|
627
|
+
</CommandMenu.Item>
|
|
628
|
+
)}
|
|
624
629
|
<CommandMenu.Item
|
|
625
630
|
onSelect={() => void navigate("/archive")}
|
|
626
631
|
keywords={["archive"]}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import { useLab } from "@agent-native/core/client/labs";
|
|
3
|
+
import { CLIPS_SCREENSHOTS } from "@shared/labs";
|
|
2
4
|
import { IconChevronDown, IconUpload } from "@tabler/icons-react";
|
|
3
5
|
import { useState } from "react";
|
|
4
6
|
|
|
@@ -63,6 +65,7 @@ export function ImportMenu({
|
|
|
63
65
|
variant = "outline",
|
|
64
66
|
}: ImportMenuProps) {
|
|
65
67
|
const t = useT();
|
|
68
|
+
const screenshotsEnabled = useLab(CLIPS_SCREENSHOTS);
|
|
66
69
|
const { input, openUploadPicker } = useUploadVideoPicker();
|
|
67
70
|
const [loomDialogOpen, setLoomDialogOpen] = useState(false);
|
|
68
71
|
|
|
@@ -118,7 +121,7 @@ export function ImportMenu({
|
|
|
118
121
|
{t("preRecord.uploadVideo")}
|
|
119
122
|
</DropdownMenuItem>
|
|
120
123
|
) : null}
|
|
121
|
-
{onScreenshot ? (
|
|
124
|
+
{onScreenshot && screenshotsEnabled ? (
|
|
122
125
|
<DropdownMenuItem
|
|
123
126
|
disabled={screenshotPending}
|
|
124
127
|
onSelect={(event) => {
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import { useT } from "@agent-native/core/client/i18n";
|
|
7
7
|
import { normalizeDocumentTitle } from "@agent-native/core/shared";
|
|
8
8
|
import { FileStorageSetupPopover } from "@agent-native/toolkit/app/chat/FileStorageSetupPopover";
|
|
9
|
-
import { IconAlertTriangle } from "@tabler/icons-react";
|
|
9
|
+
import { IconAlertTriangle, IconPhoto } from "@tabler/icons-react";
|
|
10
10
|
import {
|
|
11
11
|
type DragEvent,
|
|
12
12
|
type ReactElement,
|
|
@@ -59,7 +59,7 @@ import { resolveVideoMimeType } from "@/lib/video-metadata";
|
|
|
59
59
|
|
|
60
60
|
import { BulkActionToolbar, type BulkMoveTarget } from "./bulk-action-toolbar";
|
|
61
61
|
import { DroppedUploadCard } from "./dropped-upload-card";
|
|
62
|
-
import { EmptyState } from "./empty-state";
|
|
62
|
+
import { AppEmptyState, EmptyState } from "./empty-state";
|
|
63
63
|
import { FilterChips, type FilterChip } from "./filter-chips";
|
|
64
64
|
import { FolderCard } from "./folder-card";
|
|
65
65
|
import { buildLibraryActionHrefs } from "./library-action-hrefs";
|
|
@@ -757,7 +757,7 @@ export function LibraryGrid({
|
|
|
757
757
|
/>
|
|
758
758
|
)}
|
|
759
759
|
<div className="ms-auto flex shrink-0 items-center gap-2 lg:col-start-3 lg:ms-0 lg:justify-self-end">
|
|
760
|
-
{!isEmptyState && extraActions}
|
|
760
|
+
{(!isEmptyState || kind === "image") && extraActions}
|
|
761
761
|
{!isEmptyState && (
|
|
762
762
|
<SortMenu value={sort} onChange={handleSortChange} />
|
|
763
763
|
)}
|
|
@@ -834,11 +834,18 @@ export function LibraryGrid({
|
|
|
834
834
|
) : recordings.length === 0 &&
|
|
835
835
|
visibleFolders.length === 0 &&
|
|
836
836
|
uploads.length === 0 ? (
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
837
|
+
kind === "image" ? (
|
|
838
|
+
<AppEmptyState
|
|
839
|
+
icon={IconPhoto}
|
|
840
|
+
title={t("navigation.screenshots")}
|
|
841
|
+
/>
|
|
842
|
+
) : (
|
|
843
|
+
<EmptyState
|
|
844
|
+
kind={resolvedEmptyKind}
|
|
845
|
+
spaceId={spaceId}
|
|
846
|
+
folderId={folderId}
|
|
847
|
+
/>
|
|
848
|
+
)
|
|
842
849
|
) : (
|
|
843
850
|
<div className="flex flex-col gap-8">
|
|
844
851
|
{visibleFolders.length > 0 && (
|
|
@@ -12,7 +12,11 @@ import {
|
|
|
12
12
|
AppSidebarFooter,
|
|
13
13
|
AppSidebarHeader,
|
|
14
14
|
} from "@agent-native/toolkit/app/shared";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
CLIPS_MEETINGS,
|
|
17
|
+
CLIPS_SCREENSHOTS,
|
|
18
|
+
CLIPS_VOICE_DICTATION,
|
|
19
|
+
} from "@shared/labs";
|
|
16
20
|
import {
|
|
17
21
|
IconInbox,
|
|
18
22
|
IconPhoto,
|
|
@@ -195,6 +199,7 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
|
|
|
195
199
|
const t = useT();
|
|
196
200
|
const isRecordingRoute = location.pathname.startsWith("/r/");
|
|
197
201
|
const meetingsLabEnabled = useLab(CLIPS_MEETINGS);
|
|
202
|
+
const screenshotsLabEnabled = useLab(CLIPS_SCREENSHOTS);
|
|
198
203
|
const voiceDictationLabEnabled = useLab(CLIPS_VOICE_DICTATION);
|
|
199
204
|
const recordingScope = useMemo(() => {
|
|
200
205
|
const match = location.pathname.match(/^\/(?:r|share)\/([^/]+)/);
|
|
@@ -564,7 +569,10 @@ export function LibraryLayout({ children }: LibraryLayoutProps) {
|
|
|
564
569
|
];
|
|
565
570
|
|
|
566
571
|
const primaryNavItems = navItems.filter(
|
|
567
|
-
({ to }) =>
|
|
572
|
+
({ to }) =>
|
|
573
|
+
to !== "/archive" &&
|
|
574
|
+
to !== "/trash" &&
|
|
575
|
+
(to !== "/screenshots" || screenshotsLabEnabled),
|
|
568
576
|
);
|
|
569
577
|
const lifecycleNavItems = navItems.filter(
|
|
570
578
|
({ to }) => to === "/archive" || to === "/trash",
|
|
@@ -64,6 +64,7 @@ import {
|
|
|
64
64
|
PopoverTrigger,
|
|
65
65
|
PopoverContent,
|
|
66
66
|
} from "@/components/ui/popover";
|
|
67
|
+
import { Switch } from "@/components/ui/switch";
|
|
67
68
|
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
68
69
|
import { cn } from "@/lib/utils";
|
|
69
70
|
|
|
@@ -755,7 +756,7 @@ function RecordingAdvancedAccess({
|
|
|
755
756
|
>
|
|
756
757
|
{t("embedRoute.passwordRequired")}
|
|
757
758
|
</Label>
|
|
758
|
-
<
|
|
759
|
+
<Switch
|
|
759
760
|
id="share-password-required"
|
|
760
761
|
checked={passwordEnabled}
|
|
761
762
|
disabled={!canEdit || updateRecording.isPending}
|
|
@@ -765,7 +766,7 @@ function RecordingAdvancedAccess({
|
|
|
765
766
|
|
|
766
767
|
{passwordEnabled ? (
|
|
767
768
|
<>
|
|
768
|
-
<div className="
|
|
769
|
+
<div className="grid grid-cols-[minmax(0,1fr)_auto] gap-2">
|
|
769
770
|
<Input
|
|
770
771
|
size="sm"
|
|
771
772
|
type="text"
|
|
@@ -778,12 +779,10 @@ function RecordingAdvancedAccess({
|
|
|
778
779
|
? t("playerSettings.passwordSetPlaceholder")
|
|
779
780
|
: t("playerSettings.passwordInputPlaceholder")
|
|
780
781
|
}
|
|
781
|
-
className="min-w-0"
|
|
782
782
|
/>
|
|
783
783
|
<Button
|
|
784
784
|
type="button"
|
|
785
785
|
size="sm"
|
|
786
|
-
className="shrink-0"
|
|
787
786
|
disabled={
|
|
788
787
|
!canEdit || updateRecording.isPending || !password.trim()
|
|
789
788
|
}
|
|
@@ -815,7 +814,7 @@ function RecordingAdvancedAccess({
|
|
|
815
814
|
<Label htmlFor="share-expiry" className="text-sm font-normal">
|
|
816
815
|
{t("shareDialog.linkExpires")}
|
|
817
816
|
</Label>
|
|
818
|
-
<div className="
|
|
817
|
+
<div className="grid grid-cols-[minmax(0,1fr)_auto] gap-2">
|
|
819
818
|
<Input
|
|
820
819
|
id="share-expiry"
|
|
821
820
|
size="sm"
|
|
@@ -825,12 +824,10 @@ function RecordingAdvancedAccess({
|
|
|
825
824
|
onChange={(event) =>
|
|
826
825
|
setExpiryDraft(fromDatetimeLocal(event.target.value))
|
|
827
826
|
}
|
|
828
|
-
className="min-w-0"
|
|
829
827
|
/>
|
|
830
828
|
<Button
|
|
831
829
|
type="button"
|
|
832
830
|
size="sm"
|
|
833
|
-
className="shrink-0"
|
|
834
831
|
disabled={!canEdit || updateRecording.isPending}
|
|
835
832
|
onClick={() => {
|
|
836
833
|
const nextExpiry = expiryDraft || null;
|
|
@@ -92,7 +92,7 @@ export function ShareAdvancedPopover({
|
|
|
92
92
|
align="start"
|
|
93
93
|
sideOffset={6}
|
|
94
94
|
onOpenAutoFocus={(event) => event.preventDefault()}
|
|
95
|
-
className="w-
|
|
95
|
+
className="w-80 max-w-[calc(100vw-2rem)] space-y-3 p-3"
|
|
96
96
|
>
|
|
97
97
|
{children}
|
|
98
98
|
</PopoverContent>
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import { useLabState } from "@agent-native/core/client/labs";
|
|
3
|
+
import { CLIPS_SCREENSHOTS } from "@shared/labs";
|
|
4
|
+
import { Navigate } from "react-router";
|
|
2
5
|
|
|
3
6
|
import { LibraryGrid } from "@/components/library/library-grid";
|
|
4
7
|
import { ScreenshotPrimaryAction } from "@/components/library/library-primary-actions";
|
|
8
|
+
import { Button } from "@/components/ui/button";
|
|
5
9
|
import enMessages from "@/i18n/en-US";
|
|
6
10
|
|
|
7
11
|
export function meta() {
|
|
@@ -16,6 +20,18 @@ export function meta() {
|
|
|
16
20
|
*/
|
|
17
21
|
export default function ScreenshotsRoute() {
|
|
18
22
|
const t = useT();
|
|
23
|
+
const lab = useLabState(CLIPS_SCREENSHOTS.key);
|
|
24
|
+
if (lab.isLoading) return null;
|
|
25
|
+
if (lab.isError) {
|
|
26
|
+
return (
|
|
27
|
+
<div role="alert" className="flex flex-col items-center gap-4 py-20">
|
|
28
|
+
<p>{t("sharePage.somethingWentWrong")}</p>
|
|
29
|
+
<Button onClick={lab.refetch}>{t("libraryGrid.retry")}</Button>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
if (!lab.isSuccess) return null;
|
|
34
|
+
if (!lab.enabled) return <Navigate replace to="/library" />;
|
|
19
35
|
return (
|
|
20
36
|
<LibraryGrid
|
|
21
37
|
view="library"
|
|
@@ -4,7 +4,11 @@ import {
|
|
|
4
4
|
SettingsTabsPage,
|
|
5
5
|
useAgentSettingsTabs,
|
|
6
6
|
} from "@agent-native/toolkit/app/settings";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
CLIPS_LABS,
|
|
9
|
+
CLIPS_SCREENSHOTS,
|
|
10
|
+
CLIPS_VOICE_DICTATION,
|
|
11
|
+
} from "@shared/labs";
|
|
8
12
|
import { useMemo } from "react";
|
|
9
13
|
|
|
10
14
|
import { useClipsSettingsRedesign } from "@/components/settings/clips-settings-redesign";
|
|
@@ -54,6 +58,13 @@ export default function SettingsIndexRoute() {
|
|
|
54
58
|
description: t("settings.labLookbackContextDescription"),
|
|
55
59
|
};
|
|
56
60
|
}
|
|
61
|
+
if (lab.key === CLIPS_SCREENSHOTS.key) {
|
|
62
|
+
return {
|
|
63
|
+
...lab,
|
|
64
|
+
displayName: t("navigation.screenshots"),
|
|
65
|
+
description: t("preRecord.takeScreenshot"),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
57
68
|
if (lab.key === CLIPS_VOICE_DICTATION.key) {
|
|
58
69
|
return {
|
|
59
70
|
...lab,
|
|
@@ -62,10 +62,19 @@ export const CLIPS_LOOKBACK_CONTEXT = defineLab({
|
|
|
62
62
|
keywords: "rewind lookback context history earlier screen before recording",
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
+
export const CLIPS_SCREENSHOTS = defineLab({
|
|
66
|
+
key: "clips.screenshots",
|
|
67
|
+
displayName: "Screenshots",
|
|
68
|
+
description: "Take screenshots.",
|
|
69
|
+
defaultEnabled: false,
|
|
70
|
+
keywords: "screenshots screenshot capture image",
|
|
71
|
+
});
|
|
72
|
+
|
|
65
73
|
export const CLIPS_LABS = defineLabs([
|
|
66
74
|
CLIPS_VIDEO_EDITING,
|
|
67
75
|
CLIPS_MEETINGS,
|
|
68
76
|
CLIPS_VOICE_DICTATION,
|
|
69
77
|
CLIPS_RESILIENT_RECORDING,
|
|
70
78
|
CLIPS_LOOKBACK_CONTEXT,
|
|
79
|
+
CLIPS_SCREENSHOTS,
|
|
71
80
|
]);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","builder-private-payload-cleanup","collab","content-webhooks","core-routes","creative-context","db","feature-flags","github-source-sync","labs","live-body-backfill","onboarding","otel","suggested-edits","transactional-emails"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -4,7 +4,19 @@ import {
|
|
|
4
4
|
isActionContractError,
|
|
5
5
|
} from "@agent-native/core/action";
|
|
6
6
|
import { assertAccess } from "@agent-native/core/sharing";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
and,
|
|
9
|
+
eq,
|
|
10
|
+
exists,
|
|
11
|
+
gte,
|
|
12
|
+
inArray,
|
|
13
|
+
isNull,
|
|
14
|
+
lt,
|
|
15
|
+
ne,
|
|
16
|
+
notInArray,
|
|
17
|
+
or,
|
|
18
|
+
sql,
|
|
19
|
+
} from "drizzle-orm";
|
|
8
20
|
import { z } from "zod";
|
|
9
21
|
|
|
10
22
|
import { getDb, schema } from "../server/db/index.js";
|
|
@@ -148,6 +160,11 @@ export interface ExecuteBuilderSourceExecutionDeps {
|
|
|
148
160
|
now: string;
|
|
149
161
|
staleBefore: string;
|
|
150
162
|
attemptToken: string;
|
|
163
|
+
/**
|
|
164
|
+
* The existing entry this execution overwrites. Its claim is refused while
|
|
165
|
+
* another source's push to the same entry holds a live claim.
|
|
166
|
+
*/
|
|
167
|
+
builderEntry?: { model: string; entryId: string } | null;
|
|
151
168
|
}) => Promise<boolean>;
|
|
152
169
|
renewExecutionClaim: (args: {
|
|
153
170
|
executionId: string;
|
|
@@ -313,6 +330,55 @@ export function builderExecutionConflict(message: string) {
|
|
|
313
330
|
return Object.assign(new Error(message), { statusCode: 409 });
|
|
314
331
|
}
|
|
315
332
|
|
|
333
|
+
// Collections are separate sources, so the database lock a claim takes does not
|
|
334
|
+
// keep two collections bound to the same Builder model apart. The live preflight
|
|
335
|
+
// only protects a push if no other Content push to the entry can land between
|
|
336
|
+
// its read and its write, so a push holds the entry from claim to write. A
|
|
337
|
+
// write whose outcome is unknown may still land, so it holds the entry too,
|
|
338
|
+
// until the claim lease outlasts any request still in flight.
|
|
339
|
+
async function builderEntryHasOtherLiveClaim(
|
|
340
|
+
tx: ReturnType<typeof getDb>,
|
|
341
|
+
args: {
|
|
342
|
+
model: string;
|
|
343
|
+
entryId: string;
|
|
344
|
+
executionId: string;
|
|
345
|
+
staleBefore: string;
|
|
346
|
+
},
|
|
347
|
+
) {
|
|
348
|
+
await tx.execute(
|
|
349
|
+
sql`SELECT pg_advisory_xact_lock(hashtextextended(${`content-builder-entry-write:${args.model}:${args.entryId}`}, 0::bigint))`,
|
|
350
|
+
);
|
|
351
|
+
const executions = schema.contentDatabaseSourceExecutions;
|
|
352
|
+
const changeSets = schema.contentDatabaseSourceChangeSets;
|
|
353
|
+
const rows = schema.contentDatabaseSourceRows;
|
|
354
|
+
const sources = schema.contentDatabaseSources;
|
|
355
|
+
const claims = await tx
|
|
356
|
+
.select({ id: executions.id })
|
|
357
|
+
.from(sources)
|
|
358
|
+
.innerJoin(rows, eq(rows.sourceId, sources.id))
|
|
359
|
+
.innerJoin(
|
|
360
|
+
changeSets,
|
|
361
|
+
and(
|
|
362
|
+
eq(changeSets.sourceId, sources.id),
|
|
363
|
+
eq(changeSets.databaseItemId, rows.databaseItemId),
|
|
364
|
+
),
|
|
365
|
+
)
|
|
366
|
+
.innerJoin(executions, eq(executions.changeSetId, changeSets.id))
|
|
367
|
+
.where(
|
|
368
|
+
and(
|
|
369
|
+
eq(sources.sourceType, "builder-cms"),
|
|
370
|
+
eq(sources.sourceTable, args.model),
|
|
371
|
+
eq(rows.sourceRowId, args.entryId),
|
|
372
|
+
eq(executions.sourceId, sources.id),
|
|
373
|
+
ne(executions.id, args.executionId),
|
|
374
|
+
inArray(executions.state, ["running", "reconciliation_required"]),
|
|
375
|
+
gte(executions.updatedAt, args.staleBefore),
|
|
376
|
+
),
|
|
377
|
+
)
|
|
378
|
+
.limit(1);
|
|
379
|
+
return claims.length > 0;
|
|
380
|
+
}
|
|
381
|
+
|
|
316
382
|
function isReclaimableRunningExecution(
|
|
317
383
|
execution: BuilderSourceExecutionRecord,
|
|
318
384
|
now: string,
|
|
@@ -1286,6 +1352,16 @@ export function realExecutionDeps(
|
|
|
1286
1352
|
)
|
|
1287
1353
|
.limit(1);
|
|
1288
1354
|
if (!scope) return null;
|
|
1355
|
+
if (
|
|
1356
|
+
args.builderEntry &&
|
|
1357
|
+
(await builderEntryHasOtherLiveClaim(transactionDb, {
|
|
1358
|
+
...args.builderEntry,
|
|
1359
|
+
executionId: args.executionId,
|
|
1360
|
+
staleBefore: args.staleBefore,
|
|
1361
|
+
}))
|
|
1362
|
+
) {
|
|
1363
|
+
return "entry_busy" as const;
|
|
1364
|
+
}
|
|
1289
1365
|
await lockContentDatabaseMutation(transactionDb, scope.databaseId);
|
|
1290
1366
|
const updated = await tx
|
|
1291
1367
|
.update(schema.contentDatabaseSourceExecutions)
|
|
@@ -1373,6 +1449,13 @@ export function realExecutionDeps(
|
|
|
1373
1449
|
}
|
|
1374
1450
|
throw error;
|
|
1375
1451
|
}
|
|
1452
|
+
if (result === "entry_busy") {
|
|
1453
|
+
await discardUncommittedPayload(prepared);
|
|
1454
|
+
fail(
|
|
1455
|
+
"Another Content collection is pushing to this Builder entry. Try again in a moment.",
|
|
1456
|
+
{ errorCode: "builder_entry_write_in_progress", statusCode: 409 },
|
|
1457
|
+
);
|
|
1458
|
+
}
|
|
1376
1459
|
if (builderExecutionAffectedRows(result) === 0) {
|
|
1377
1460
|
await discardUncommittedPayload(prepared);
|
|
1378
1461
|
}
|
|
@@ -2161,6 +2244,9 @@ export async function executeBuilderSourceExecutionWithDeps(
|
|
|
2161
2244
|
now,
|
|
2162
2245
|
staleBefore: staleRunningCutoff(now),
|
|
2163
2246
|
attemptToken,
|
|
2247
|
+
builderEntry: preflightEntryId
|
|
2248
|
+
? { model: plan.payload.target.model, entryId: preflightEntryId }
|
|
2249
|
+
: null,
|
|
2164
2250
|
});
|
|
2165
2251
|
if (!claimed) {
|
|
2166
2252
|
throw builderExecutionConflict("Builder execution is already running.");
|
|
@@ -2191,9 +2277,10 @@ export async function executeBuilderSourceExecutionWithDeps(
|
|
|
2191
2277
|
let writePayload: BuilderCmsExecutionPayload = validatedPayload;
|
|
2192
2278
|
if (preflightEntryId) {
|
|
2193
2279
|
// This check runs after the claim so it sits as close to the write as
|
|
2194
|
-
// possible.
|
|
2195
|
-
//
|
|
2196
|
-
//
|
|
2280
|
+
// possible. The claim keeps other Content pushes to this entry out, but a
|
|
2281
|
+
// save made in Builder that lands after this read and before the write
|
|
2282
|
+
// below is still overwritten: closing that needs a conditional write on
|
|
2283
|
+
// Builder's side.
|
|
2197
2284
|
let liveState: BuilderCmsEntryLiveState;
|
|
2198
2285
|
try {
|
|
2199
2286
|
liveState = await deps.readLiveEntry({
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","auth","core-routes","db","otel"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -26,8 +26,8 @@ only when the available context leaves materially different choices.
|
|
|
26
26
|
|
|
27
27
|
- Create the design if needed, then author complete email HTML with
|
|
28
28
|
`create-file` (`fileType: "html"`) or `generate-design` (`devices: []`, a
|
|
29
|
-
600px-wide `canvasFrames` placement).
|
|
30
|
-
|
|
29
|
+
600px-wide `canvasFrames` placement). Put
|
|
30
|
+
`<meta name="agent-native:frame-type" content="hubspot-email">` in the
|
|
31
31
|
head to retain email authoring defaults on future edits. Include the leading
|
|
32
32
|
HubSpot header comment containing `templateType: email` and
|
|
33
33
|
`isAvailableForNewContent: true` so new emails are selectable. The leading
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// AUTO-GENERATED by @agent-native/core deploy build
|
|
2
|
+
import { markDefaultPluginProvided } from "@agent-native/core/server/edge";
|
|
3
|
+
|
|
4
|
+
const pluginStems = ["agent-chat","assets-mcp","auth","builder-host-embed-headers","collab","config","core-routes","creative-context","db","e2e-attachment-storage","feature-flags","getting-started","journey-canvas-stage-cleanup","labs","local-import-asset-upload","otel","review"];
|
|
5
|
+
|
|
6
|
+
export default function markBuildDiscoveredPlugins(nitroApp) {
|
|
7
|
+
for (const stem of pluginStems) {
|
|
8
|
+
markDefaultPluginProvided(nitroApp, stem);
|
|
9
|
+
}
|
|
10
|
+
}
|