@agent-native/core 0.106.3 → 0.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +13 -0
- package/corpus/core/docs/content/integrations.mdx +597 -0
- package/corpus/core/docs/content/locales/ar-SA/mcp-clients.mdx +19 -1
- package/corpus/core/docs/content/locales/de-DE/mcp-clients.mdx +22 -1
- package/corpus/core/docs/content/locales/es-ES/mcp-clients.mdx +23 -1
- package/corpus/core/docs/content/locales/fr-FR/mcp-clients.mdx +23 -1
- package/corpus/core/docs/content/locales/hi-IN/mcp-clients.mdx +22 -1
- package/corpus/core/docs/content/locales/ja-JP/mcp-clients.mdx +21 -1
- package/corpus/core/docs/content/locales/ko-KR/mcp-clients.mdx +20 -1
- package/corpus/core/docs/content/locales/pt-BR/mcp-clients.mdx +22 -1
- package/corpus/core/docs/content/locales/zh-CN/mcp-clients.mdx +17 -1
- package/corpus/core/docs/content/locales/zh-TW/mcp-clients.mdx +17 -1
- package/corpus/core/docs/content/mcp-clients.mdx +51 -1
- package/corpus/core/docs/content/organizations-teams-permissions.mdx +413 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/AssistantChat.tsx +13 -1
- package/corpus/core/src/client/chat/message-components.tsx +41 -0
- package/corpus/core/src/client/composer/TiptapComposer.tsx +45 -8
- package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +30 -11
- package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +240 -0
- package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +159 -40
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +433 -4
- package/corpus/core/src/client/resources/mcp-integration-logos.ts +108 -0
- package/corpus/core/src/deploy/build.ts +32 -0
- package/corpus/core/src/extensions/html-shell.ts +33 -1
- package/corpus/core/src/ingestion/office.ts +1 -2
- package/corpus/core/src/ingestion/pptx.ts +2 -4
- package/corpus/core/src/localization/default-messages.ts +126 -1
- package/corpus/core/src/mcp/actions/call-mcp-tool.ts +1 -0
- package/corpus/core/src/server/index.ts +4 -0
- package/corpus/core/src/server/org-admin.ts +28 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
- package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +64 -0
- package/corpus/templates/analytics/AGENTS.md +5 -0
- package/corpus/templates/analytics/actions/clone-creative-context-dashboard.ts +86 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/analytics/app/i18n-data.ts +1 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +8 -4
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +59 -0
- package/corpus/templates/analytics/app/routes/agent.tsx +7 -1
- package/corpus/templates/analytics/changelog/2026-07-17-library-now-flags-published-dashboards-with-newer-versions-a.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/analytics/package.json +1 -0
- package/corpus/templates/analytics/server/lib/native-creative-context.ts +158 -0
- package/corpus/templates/analytics/server/plugins/creative-context.ts +10 -0
- package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +12 -3
- package/corpus/templates/assets/AGENTS.md +5 -0
- package/corpus/templates/assets/actions/clone-creative-context-asset.ts +74 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +2 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +308 -178
- package/corpus/templates/assets/app/routes/library.tsx +5 -11
- package/corpus/templates/assets/changelog/2026-07-17-library-now-flags-published-assets-with-newer-versions-and-l.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/assets/server/lib/native-creative-context.ts +198 -0
- package/corpus/templates/assets/server/plugins/creative-context.ts +4 -0
- package/corpus/templates/brain/actions/provider-api-request.ts +1 -0
- package/corpus/templates/calendar/actions/provider-api-request.ts +1 -0
- package/corpus/templates/clips/actions/get-recording-insights.ts +7 -4
- package/corpus/templates/clips/actions/list-recordings.ts +48 -0
- package/corpus/templates/clips/actions/list-viewers.ts +2 -1
- package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +3 -1
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +1 -3
- package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +11 -6
- package/corpus/templates/clips/app/hooks/use-view-tracking.ts +6 -1
- package/corpus/templates/clips/app/lib/ffmpeg-export.ts +4 -2
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -3
- package/corpus/templates/clips/changelog/2026-07-17-dictation-keeps-sentence-spacing-and-no-longer-crashes-when-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-17-shared-clips-now-preserve-editor-access-and-show-editor-insi.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-17-stitching-clips-no-longer-fails-when-editor-media-metadata-i.md +6 -0
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +14 -8
- package/corpus/templates/clips/shared/view-analytics.ts +4 -0
- package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +12 -3
- package/corpus/templates/content/AGENTS.md +5 -0
- package/corpus/templates/content/actions/clone-creative-context-document.ts +61 -0
- package/corpus/templates/content/actions/provider-api-request.ts +1 -0
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +21 -0
- package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +29 -0
- package/corpus/templates/content/changelog/2026-07-17-library-now-flags-published-documents-with-newer-versions-an.md +6 -0
- package/corpus/templates/content/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/content/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/content/parity/matrix.md +1 -1
- package/corpus/templates/content/parity/matrix.ts +1 -0
- package/corpus/templates/content/server/lib/native-creative-context.ts +191 -0
- package/corpus/templates/content/server/plugins/creative-context.ts +8 -1
- package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +11 -3
- package/corpus/templates/design/AGENTS.md +5 -0
- package/corpus/templates/design/actions/clone-creative-context-design-native.ts +111 -0
- package/corpus/templates/design/actions/provider-api-request.ts +1 -0
- package/corpus/templates/design/app/pages/Index.tsx +44 -0
- package/corpus/templates/design/app/pages/design-editor/types.ts +1 -0
- package/corpus/templates/design/changelog/2026-07-17-library-now-flags-published-designs-with-newer-versions-and-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/design/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/design/server/lib/native-creative-context.ts +265 -0
- package/corpus/templates/design/server/plugins/creative-context.ts +8 -1
- package/corpus/templates/dispatch/actions/provider-api-request.ts +1 -0
- package/corpus/templates/mail/actions/provider-api-request.ts +1 -0
- package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +11 -3
- package/corpus/templates/slides/AGENTS.md +5 -0
- package/corpus/templates/slides/actions/clone-creative-context-deck.ts +96 -0
- package/corpus/templates/slides/actions/extract-pdf.ts +3 -2
- package/corpus/templates/slides/actions/import-file.ts +3 -2
- package/corpus/templates/slides/actions/provider-api-request.ts +1 -0
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +27 -0
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +21 -0
- package/corpus/templates/slides/changelog/2026-07-17-library-now-flags-published-decks-with-newer-versions-and-le.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-17-pdf-and-powerpoint-imports-now-work-reliably-in-hosted-decks.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
- package/corpus/templates/slides/server/lib/native-creative-context.ts +288 -0
- package/corpus/templates/slides/server/plugins/creative-context.ts +4 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +8 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/chat/message-components.d.ts.map +1 -1
- package/dist/client/chat/message-components.js +35 -1
- package/dist/client/chat/message-components.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +7 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +37 -8
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
- package/dist/client/integrations/IntegrationsPanel.js +3 -2
- package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
- package/dist/client/resources/McpConnectionSuggestion.d.ts +9 -0
- package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -0
- package/dist/client/resources/McpConnectionSuggestion.js +115 -0
- package/dist/client/resources/McpConnectionSuggestion.js.map +1 -0
- package/dist/client/resources/McpIntegrationDialog.d.ts +2 -1
- package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
- package/dist/client/resources/McpIntegrationDialog.js +48 -20
- package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts +9 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +387 -4
- package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
- package/dist/client/resources/mcp-integration-logos.d.ts +2 -0
- package/dist/client/resources/mcp-integration-logos.d.ts.map +1 -0
- package/dist/client/resources/mcp-integration-logos.js +109 -0
- package/dist/client/resources/mcp-integration-logos.js.map +1 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +23 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js +33 -1
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/ingestion/office.d.ts.map +1 -1
- package/dist/ingestion/office.js +1 -2
- package/dist/ingestion/office.js.map +1 -1
- package/dist/ingestion/pptx.js +2 -4
- package/dist/ingestion/pptx.js.map +1 -1
- package/dist/localization/default-messages.d.ts +98 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +99 -1
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp/actions/call-mcp-tool.js +1 -0
- package/dist/mcp/actions/call-mcp-tool.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/org-admin.d.ts +3 -0
- package/dist/server/org-admin.d.ts.map +1 -0
- package/dist/server/org-admin.js +24 -0
- package/dist/server/org-admin.js.map +1 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
- package/docs/content/integrations.mdx +597 -0
- package/docs/content/locales/ar-SA/mcp-clients.mdx +19 -1
- package/docs/content/locales/de-DE/mcp-clients.mdx +22 -1
- package/docs/content/locales/es-ES/mcp-clients.mdx +23 -1
- package/docs/content/locales/fr-FR/mcp-clients.mdx +23 -1
- package/docs/content/locales/hi-IN/mcp-clients.mdx +22 -1
- package/docs/content/locales/ja-JP/mcp-clients.mdx +21 -1
- package/docs/content/locales/ko-KR/mcp-clients.mdx +20 -1
- package/docs/content/locales/pt-BR/mcp-clients.mdx +22 -1
- package/docs/content/locales/zh-CN/mcp-clients.mdx +17 -1
- package/docs/content/locales/zh-TW/mcp-clients.mdx +17 -1
- package/docs/content/mcp-clients.mdx +51 -1
- package/docs/content/organizations-teams-permissions.mdx +413 -0
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
- package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
injectSessionReplayIframeBootstrap,
|
|
9
9
|
SESSION_REPLAY_IFRAME_ATTRIBUTE,
|
|
10
10
|
} from "@agent-native/core/client";
|
|
11
|
+
import { CreativeContextShareSheet } from "@agent-native/creative-context/client";
|
|
11
12
|
import {
|
|
12
13
|
useSetHeaderActions,
|
|
13
14
|
useSetPageTitle,
|
|
@@ -109,6 +110,7 @@ export default function Index() {
|
|
|
109
110
|
);
|
|
110
111
|
const [renameId, setRenameId] = useState<string | null>(null);
|
|
111
112
|
const [renameDraft, setRenameDraft] = useState("");
|
|
113
|
+
const [contextDesigns, setContextDesigns] = useState<Design[]>([]);
|
|
112
114
|
|
|
113
115
|
const anchorElRef = useRef<HTMLElement | null>(null);
|
|
114
116
|
const anchorRef = useRef<HTMLElement | null>(null);
|
|
@@ -809,6 +811,21 @@ export default function Index() {
|
|
|
809
811
|
</TooltipTrigger>
|
|
810
812
|
<TooltipContent>{t("home.clearSelection")}</TooltipContent>
|
|
811
813
|
</Tooltip>
|
|
814
|
+
<Button
|
|
815
|
+
variant="outline"
|
|
816
|
+
size="sm"
|
|
817
|
+
onClick={() =>
|
|
818
|
+
setContextDesigns(
|
|
819
|
+
designs.filter((design) =>
|
|
820
|
+
selectedDesignIds.has(design.id),
|
|
821
|
+
),
|
|
822
|
+
)
|
|
823
|
+
}
|
|
824
|
+
className="cursor-pointer"
|
|
825
|
+
>
|
|
826
|
+
<IconPlus className="w-3.5 h-3.5" />
|
|
827
|
+
{t("creativeContext.addToContext" /* i18n-key-ignore */)}
|
|
828
|
+
</Button>
|
|
812
829
|
<Button
|
|
813
830
|
variant="destructive"
|
|
814
831
|
size="sm"
|
|
@@ -936,6 +953,18 @@ export default function Index() {
|
|
|
936
953
|
<IconCopy className="w-3.5 h-3.5 me-2" />
|
|
937
954
|
{t("home.duplicate")}
|
|
938
955
|
</DropdownMenuItem>
|
|
956
|
+
<DropdownMenuItem
|
|
957
|
+
onSelect={(event) => {
|
|
958
|
+
event.preventDefault();
|
|
959
|
+
setContextDesigns([design]);
|
|
960
|
+
}}
|
|
961
|
+
className="cursor-pointer"
|
|
962
|
+
>
|
|
963
|
+
<IconPlus className="w-3.5 h-3.5 me-2" />
|
|
964
|
+
{t(
|
|
965
|
+
"creativeContext.addToContext" /* i18n-key-ignore */,
|
|
966
|
+
)}
|
|
967
|
+
</DropdownMenuItem>
|
|
939
968
|
<DropdownMenuItem
|
|
940
969
|
onClick={() => setDeleteId(design.id)}
|
|
941
970
|
className="text-red-400 focus:text-red-400 cursor-pointer"
|
|
@@ -954,6 +983,21 @@ export default function Index() {
|
|
|
954
983
|
)}
|
|
955
984
|
</main>
|
|
956
985
|
|
|
986
|
+
<CreativeContextShareSheet
|
|
987
|
+
open={contextDesigns.length > 0}
|
|
988
|
+
onOpenChange={(open) => {
|
|
989
|
+
if (!open) setContextDesigns([]);
|
|
990
|
+
}}
|
|
991
|
+
resources={contextDesigns.map((design) => ({
|
|
992
|
+
appId: "design",
|
|
993
|
+
resourceType: "design",
|
|
994
|
+
resourceId: design.id,
|
|
995
|
+
title: design.title,
|
|
996
|
+
updatedAt: design.updatedAt ?? design.createdAt,
|
|
997
|
+
preview: { kind: "document", label: "Design" },
|
|
998
|
+
}))}
|
|
999
|
+
/>
|
|
1000
|
+
|
|
957
1001
|
<PromptPopover
|
|
958
1002
|
open={showNewPrompt}
|
|
959
1003
|
onOpenChange={handleNewPromptOpenChange}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import { putPrivateBlob } from "@agent-native/core/private-blob";
|
|
4
|
+
import { accessFilter, resolveAccess } from "@agent-native/core/sharing";
|
|
5
|
+
import {
|
|
6
|
+
renderSafeNativeHtmlPreviews,
|
|
7
|
+
serializePrivateBlobHandle,
|
|
8
|
+
type NativeResourceCaptureAdapter,
|
|
9
|
+
} from "@agent-native/creative-context/server";
|
|
10
|
+
import { and, inArray } from "drizzle-orm";
|
|
11
|
+
import { nanoid } from "nanoid";
|
|
12
|
+
|
|
13
|
+
import { getDb, schema } from "../db/index.js";
|
|
14
|
+
import { buildDesignSnapshot } from "./design-snapshot.js";
|
|
15
|
+
|
|
16
|
+
function previewText(value: string, limit = 280) {
|
|
17
|
+
return value
|
|
18
|
+
.replace(/<[^>]+>/g, " ")
|
|
19
|
+
.replace(/\s+/g, " ")
|
|
20
|
+
.trim()
|
|
21
|
+
.slice(0, limit);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function captureDesignPreviewMedia(input: {
|
|
25
|
+
designId: string;
|
|
26
|
+
ownerEmail: string;
|
|
27
|
+
files: Array<{
|
|
28
|
+
id: string;
|
|
29
|
+
filename: string;
|
|
30
|
+
fileType: string;
|
|
31
|
+
content: string;
|
|
32
|
+
}>;
|
|
33
|
+
}) {
|
|
34
|
+
const previewFiles = input.files
|
|
35
|
+
.filter((file) => file.fileType === "html")
|
|
36
|
+
.slice(0, 12);
|
|
37
|
+
const rendered = await renderSafeNativeHtmlPreviews(
|
|
38
|
+
previewFiles.map((file) => ({
|
|
39
|
+
id: file.id,
|
|
40
|
+
html: file.content,
|
|
41
|
+
width: 1_280,
|
|
42
|
+
height: 800,
|
|
43
|
+
})),
|
|
44
|
+
);
|
|
45
|
+
const media = new Map<
|
|
46
|
+
string,
|
|
47
|
+
{
|
|
48
|
+
kind: "image";
|
|
49
|
+
mimeType: "image/png";
|
|
50
|
+
accessMode: "private";
|
|
51
|
+
storageKey: string;
|
|
52
|
+
altText: string;
|
|
53
|
+
contentHash: string;
|
|
54
|
+
width: number;
|
|
55
|
+
height: number;
|
|
56
|
+
metadata: { role: "design-preview"; fileId: string };
|
|
57
|
+
}
|
|
58
|
+
>();
|
|
59
|
+
await Promise.all(
|
|
60
|
+
rendered.map(async (preview) => {
|
|
61
|
+
const contentHash = createHash("sha256")
|
|
62
|
+
.update(preview.data)
|
|
63
|
+
.digest("hex");
|
|
64
|
+
const handle = await putPrivateBlob({
|
|
65
|
+
data: preview.data,
|
|
66
|
+
filename: `${input.designId}-${preview.id}.preview.png`,
|
|
67
|
+
mimeType: "image/png",
|
|
68
|
+
ownerEmail: input.ownerEmail,
|
|
69
|
+
key: `creative-context/design/${input.designId}/previews/${contentHash}.png`,
|
|
70
|
+
metadata: {
|
|
71
|
+
appId: "design",
|
|
72
|
+
resourceType: "design-preview",
|
|
73
|
+
resourceId: input.designId,
|
|
74
|
+
contentHash,
|
|
75
|
+
},
|
|
76
|
+
}).catch(() => null);
|
|
77
|
+
if (!handle) return;
|
|
78
|
+
const file = previewFiles.find(
|
|
79
|
+
(candidate) => candidate.id === preview.id,
|
|
80
|
+
);
|
|
81
|
+
media.set(preview.id, {
|
|
82
|
+
kind: "image",
|
|
83
|
+
mimeType: "image/png",
|
|
84
|
+
accessMode: "private",
|
|
85
|
+
storageKey: serializePrivateBlobHandle(handle),
|
|
86
|
+
altText: file?.filename ?? "Design preview",
|
|
87
|
+
contentHash,
|
|
88
|
+
width: preview.width,
|
|
89
|
+
height: preview.height,
|
|
90
|
+
metadata: { role: "design-preview", fileId: preview.id },
|
|
91
|
+
});
|
|
92
|
+
}),
|
|
93
|
+
);
|
|
94
|
+
return media;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export const nativeDesignCreativeContextAdapter: NativeResourceCaptureAdapter =
|
|
98
|
+
{
|
|
99
|
+
appId: "design",
|
|
100
|
+
resourceType: "design",
|
|
101
|
+
async listResourceVersions(resourceIds) {
|
|
102
|
+
if (!resourceIds.length) return [];
|
|
103
|
+
return getDb()
|
|
104
|
+
.select({
|
|
105
|
+
resourceId: schema.designs.id,
|
|
106
|
+
sourceModifiedAt: schema.designs.updatedAt,
|
|
107
|
+
})
|
|
108
|
+
.from(schema.designs)
|
|
109
|
+
.where(
|
|
110
|
+
and(
|
|
111
|
+
inArray(schema.designs.id, [...resourceIds]),
|
|
112
|
+
accessFilter(schema.designs, schema.designShares),
|
|
113
|
+
),
|
|
114
|
+
);
|
|
115
|
+
},
|
|
116
|
+
async capture(reference) {
|
|
117
|
+
const access = await resolveAccess("design", reference.resourceId);
|
|
118
|
+
if (!access) throw new Error("Design not found");
|
|
119
|
+
const design = access.resource as typeof schema.designs.$inferSelect;
|
|
120
|
+
if (
|
|
121
|
+
reference.expectedUpdatedAt &&
|
|
122
|
+
reference.expectedUpdatedAt !== design.updatedAt
|
|
123
|
+
)
|
|
124
|
+
throw new Error(
|
|
125
|
+
"Design changed before it could be submitted to Context.",
|
|
126
|
+
);
|
|
127
|
+
const snapshot = await buildDesignSnapshot(design.id, design.data);
|
|
128
|
+
const payload = JSON.stringify({
|
|
129
|
+
designId: design.id,
|
|
130
|
+
designData: design.data,
|
|
131
|
+
files: snapshot.files,
|
|
132
|
+
tweaks: snapshot.tweaks,
|
|
133
|
+
appliedTweaks: snapshot.appliedTweaks,
|
|
134
|
+
resolvedCssVars: snapshot.resolvedCssVars,
|
|
135
|
+
});
|
|
136
|
+
const contentHash = createHash("sha256").update(payload).digest("hex");
|
|
137
|
+
const versionId = nanoid();
|
|
138
|
+
await getDb().insert(schema.designVersions).values({
|
|
139
|
+
id: versionId,
|
|
140
|
+
designId: design.id,
|
|
141
|
+
label: "Creative Context submission",
|
|
142
|
+
snapshot: payload,
|
|
143
|
+
createdAt: new Date().toISOString(),
|
|
144
|
+
});
|
|
145
|
+
const handle = await putPrivateBlob({
|
|
146
|
+
data: Buffer.from(payload),
|
|
147
|
+
filename: `${design.id}.design.json`,
|
|
148
|
+
mimeType: "application/json",
|
|
149
|
+
ownerEmail: design.ownerEmail,
|
|
150
|
+
key: `creative-context/design/${design.id}/${contentHash}.json`,
|
|
151
|
+
metadata: {
|
|
152
|
+
appId: "design",
|
|
153
|
+
resourceType: "design",
|
|
154
|
+
resourceId: design.id,
|
|
155
|
+
contentHash,
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
if (!handle)
|
|
159
|
+
throw new Error(
|
|
160
|
+
"Private blob storage is required to submit a design to Context.",
|
|
161
|
+
);
|
|
162
|
+
const previewMedia = await captureDesignPreviewMedia({
|
|
163
|
+
designId: design.id,
|
|
164
|
+
ownerEmail: design.ownerEmail,
|
|
165
|
+
files: snapshot.files,
|
|
166
|
+
});
|
|
167
|
+
const sourceModifiedAt = design.updatedAt ?? undefined;
|
|
168
|
+
return {
|
|
169
|
+
artifactKey: `design:design:${design.id}`,
|
|
170
|
+
source: {
|
|
171
|
+
name: "Design",
|
|
172
|
+
kind: "native-app",
|
|
173
|
+
externalRef: design.id,
|
|
174
|
+
access: {
|
|
175
|
+
visibility: design.visibility ?? "private",
|
|
176
|
+
canManage: access.role === "owner" || access.role === "admin",
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
items: [
|
|
180
|
+
{
|
|
181
|
+
externalId: `native:design:design:${design.id}`,
|
|
182
|
+
kind: "design-project",
|
|
183
|
+
title: design.title,
|
|
184
|
+
canonicalUrl: `/design/${design.id}`,
|
|
185
|
+
mimeType: "application/json",
|
|
186
|
+
content: snapshot.files
|
|
187
|
+
.map(
|
|
188
|
+
(file) =>
|
|
189
|
+
`${file.filename}\n${file.content.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ")}`,
|
|
190
|
+
)
|
|
191
|
+
.join("\n")
|
|
192
|
+
.slice(0, 40_000),
|
|
193
|
+
summary: `${snapshot.files.length} saved design files captured as an immutable version.`,
|
|
194
|
+
contentHash,
|
|
195
|
+
sourceModifiedAt,
|
|
196
|
+
sourceVersion: versionId,
|
|
197
|
+
metadata: {
|
|
198
|
+
preview: {
|
|
199
|
+
type: "design",
|
|
200
|
+
fileCount: snapshot.files.length,
|
|
201
|
+
frames: snapshot.files.slice(0, 24).map((file) => ({
|
|
202
|
+
title: file.filename.slice(0, 160),
|
|
203
|
+
fileType: file.fileType.slice(0, 80),
|
|
204
|
+
excerpt: previewText(file.content),
|
|
205
|
+
})),
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
media: [...previewMedia.values()],
|
|
209
|
+
edges: snapshot.files.map((file) => ({
|
|
210
|
+
relation: "contains",
|
|
211
|
+
toExternalId: `native:design:design:${design.id}:frame:${file.id}`,
|
|
212
|
+
})),
|
|
213
|
+
},
|
|
214
|
+
...snapshot.files.map((file) => {
|
|
215
|
+
const content = file.content
|
|
216
|
+
.replace(/<[^>]+>/g, " ")
|
|
217
|
+
.replace(/\s+/g, " ")
|
|
218
|
+
.trim();
|
|
219
|
+
return {
|
|
220
|
+
externalId: `native:design:design:${design.id}:frame:${file.id}`,
|
|
221
|
+
kind: "design-frame",
|
|
222
|
+
title: file.filename,
|
|
223
|
+
canonicalUrl: `/design/${design.id}`,
|
|
224
|
+
mimeType: "text/html",
|
|
225
|
+
content,
|
|
226
|
+
summary: content.slice(0, 500),
|
|
227
|
+
contentHash: createHash("sha256")
|
|
228
|
+
.update(file.content)
|
|
229
|
+
.digest("hex"),
|
|
230
|
+
sourceModifiedAt,
|
|
231
|
+
sourceVersion: versionId,
|
|
232
|
+
metadata: {
|
|
233
|
+
preview: {
|
|
234
|
+
type: "design-frame",
|
|
235
|
+
title: file.filename.slice(0, 160),
|
|
236
|
+
fileType: file.fileType.slice(0, 80),
|
|
237
|
+
excerpt: previewText(file.content),
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
media: previewMedia.has(file.id)
|
|
241
|
+
? [previewMedia.get(file.id)!]
|
|
242
|
+
: undefined,
|
|
243
|
+
};
|
|
244
|
+
}),
|
|
245
|
+
],
|
|
246
|
+
privateMetadata: {
|
|
247
|
+
nativeResource: {
|
|
248
|
+
appId: "design",
|
|
249
|
+
resourceType: "design",
|
|
250
|
+
resourceId: design.id,
|
|
251
|
+
expectedUpdatedAt: reference.expectedUpdatedAt,
|
|
252
|
+
},
|
|
253
|
+
clone: {
|
|
254
|
+
handle,
|
|
255
|
+
appId: "design",
|
|
256
|
+
resourceType: "design",
|
|
257
|
+
resourceId: design.id,
|
|
258
|
+
contentHash,
|
|
259
|
+
sourceVersion: versionId,
|
|
260
|
+
updatedAt: design.updatedAt,
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
},
|
|
265
|
+
};
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { registerOnboardingStep } from "@agent-native/core/onboarding";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
registerNativeResourceCaptureAdapter,
|
|
4
|
+
setupCreativeContext,
|
|
5
|
+
} from "@agent-native/creative-context/server";
|
|
3
6
|
import { listContextSources } from "@agent-native/creative-context/store";
|
|
4
7
|
|
|
8
|
+
import { nativeDesignCreativeContextAdapter } from "../lib/native-creative-context.js";
|
|
9
|
+
|
|
5
10
|
registerOnboardingStep({
|
|
6
11
|
id: "creative-context-library",
|
|
7
12
|
order: 18,
|
|
@@ -28,4 +33,6 @@ registerOnboardingStep({
|
|
|
28
33
|
},
|
|
29
34
|
});
|
|
30
35
|
|
|
36
|
+
registerNativeResourceCaptureAdapter(nativeDesignCreativeContextAdapter);
|
|
37
|
+
|
|
31
38
|
export default setupCreativeContext({ appId: "design" });
|
|
@@ -35,9 +35,11 @@ role cannot silently stand in for another:
|
|
|
35
35
|
|
|
36
36
|
1. Follow the user's explicit instructions and the object currently selected in
|
|
37
37
|
the app.
|
|
38
|
-
2. Read the `creative-context` application-state record. If
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
2. Read the `creative-context` application-state record. If `pinnedPackId` is
|
|
39
|
+
set, replay that immutable pack. Otherwise honor `selectedContextId`; when it
|
|
40
|
+
is unset, let retrieval use Default plus at most one app-bound or
|
|
41
|
+
semantically matching specialty context. `currentPackId` is the receipt from
|
|
42
|
+
the latest materialized generation, not a replacement for context selection.
|
|
41
43
|
3. Call `search-creative-context` with a narrow query for exact facts, visual
|
|
42
44
|
language, audience guidance, prior decisions, or reusable references.
|
|
43
45
|
4. Call `get-context-item` only for the specific search result versions
|
|
@@ -60,6 +62,7 @@ The single state key is `creative-context`:
|
|
|
60
62
|
```json
|
|
61
63
|
{
|
|
62
64
|
"contextMode": "auto",
|
|
65
|
+
"selectedContextId": null,
|
|
63
66
|
"currentPackId": null,
|
|
64
67
|
"pinnedPackId": null
|
|
65
68
|
}
|
|
@@ -120,3 +123,8 @@ If `nativeCode.content` is `null` and `oversized` is true, use the named
|
|
|
120
123
|
`get-context-item`, but the inline content is only the validated manifest shell.
|
|
121
124
|
Never concatenate a truncated fragment or use delimited `version.content` as
|
|
122
125
|
HTML.
|
|
126
|
+
|
|
127
|
+
For an app-created deck snapshot, use `clone-creative-context-deck` instead.
|
|
128
|
+
That typed action resolves the exact approved private deck payload and runs it
|
|
129
|
+
through Slides' normal deck creation and sanitization path. Generic context
|
|
130
|
+
actions must never receive or return that payload.
|
|
@@ -44,6 +44,11 @@ Detailed deck, slide-editing, image, design-system, and export workflows live in
|
|
|
44
44
|
`.agents/skills/creative-context/SKILL.md`: explicit request and current deck
|
|
45
45
|
first, then a pinned/current pack, then narrow library search. Respect
|
|
46
46
|
`creative-context.contextMode: "off"` without silently restoring a pack.
|
|
47
|
+
- To submit a deck to a governed Creative Context, use the Context tab or
|
|
48
|
+
`manage-context-membership`; it captures one immutable deck version. Reuse
|
|
49
|
+
only a returned opaque native clone reference through the Slides clone action.
|
|
50
|
+
Use `operation="submit-latest"` with a Library membership id when its native
|
|
51
|
+
update status reports `update-available`.
|
|
47
52
|
|
|
48
53
|
## Persistence Model
|
|
49
54
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import { defineAction } from "@agent-native/core";
|
|
4
|
+
import {
|
|
5
|
+
readPrivateBlob,
|
|
6
|
+
type PrivateBlobHandle,
|
|
7
|
+
} from "@agent-native/core/private-blob";
|
|
8
|
+
import {
|
|
9
|
+
getRequestOrgId,
|
|
10
|
+
getRequestUserEmail,
|
|
11
|
+
} from "@agent-native/core/server/request-context";
|
|
12
|
+
import { resolveNativeContextCloneReference } from "@agent-native/creative-context/server";
|
|
13
|
+
import { eq } from "drizzle-orm";
|
|
14
|
+
import { nanoid } from "nanoid";
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
|
|
17
|
+
import { getDb, schema } from "../server/db/index.js";
|
|
18
|
+
import { getDeckUrl } from "./_app-url.js";
|
|
19
|
+
|
|
20
|
+
export default defineAction({
|
|
21
|
+
description:
|
|
22
|
+
"Clone one exact governed Slides deck version without exposing its native payload.",
|
|
23
|
+
schema: z.object({
|
|
24
|
+
contextId: z.string(),
|
|
25
|
+
artifactKey: z.string(),
|
|
26
|
+
resourceId: z.string(),
|
|
27
|
+
expectedUpdatedAt: z.string().optional(),
|
|
28
|
+
title: z.string().optional(),
|
|
29
|
+
}),
|
|
30
|
+
publicAgent: { expose: true, readOnly: false, requiresAuth: true },
|
|
31
|
+
run: async (args) => {
|
|
32
|
+
const reference = await resolveNativeContextCloneReference({
|
|
33
|
+
appId: "slides",
|
|
34
|
+
resourceType: "deck",
|
|
35
|
+
resourceId: args.resourceId,
|
|
36
|
+
expectedUpdatedAt: args.expectedUpdatedAt,
|
|
37
|
+
contextId: args.contextId,
|
|
38
|
+
artifactKey: args.artifactKey,
|
|
39
|
+
});
|
|
40
|
+
const raw = await readPrivateBlob(
|
|
41
|
+
reference.cloneHandle as PrivateBlobHandle,
|
|
42
|
+
);
|
|
43
|
+
const data = Buffer.from(raw.data).toString("utf8");
|
|
44
|
+
const contentHash = createHash("sha256").update(data).digest("hex");
|
|
45
|
+
if (
|
|
46
|
+
raw.metadata?.appId !== "slides" ||
|
|
47
|
+
raw.metadata?.resourceType !== "deck" ||
|
|
48
|
+
raw.metadata?.resourceId !== args.resourceId ||
|
|
49
|
+
raw.metadata?.contentHash !== contentHash
|
|
50
|
+
)
|
|
51
|
+
throw new Error(
|
|
52
|
+
"Governed deck clone payload failed integrity verification.",
|
|
53
|
+
);
|
|
54
|
+
const deck = JSON.parse(data) as Record<string, unknown> & {
|
|
55
|
+
slides?: Array<Record<string, unknown>>;
|
|
56
|
+
title?: string;
|
|
57
|
+
designSystemId?: string;
|
|
58
|
+
};
|
|
59
|
+
const email = getRequestUserEmail();
|
|
60
|
+
if (!email) throw new Error("no authenticated user");
|
|
61
|
+
const id = `deck-${nanoid()}`;
|
|
62
|
+
const now = new Date().toISOString();
|
|
63
|
+
const title = args.title?.trim() || `Copy of ${deck.title ?? "deck"}`;
|
|
64
|
+
deck.title = title;
|
|
65
|
+
deck.createdAt = now;
|
|
66
|
+
deck.updatedAt = now;
|
|
67
|
+
deck.slides = (deck.slides ?? []).map((slide) => ({
|
|
68
|
+
...slide,
|
|
69
|
+
id: `slide-${nanoid(8)}`,
|
|
70
|
+
}));
|
|
71
|
+
await getDb()
|
|
72
|
+
.insert(schema.decks)
|
|
73
|
+
.values({
|
|
74
|
+
id,
|
|
75
|
+
title,
|
|
76
|
+
data: JSON.stringify(deck),
|
|
77
|
+
designSystemId: deck.designSystemId ?? null,
|
|
78
|
+
ownerEmail: email,
|
|
79
|
+
orgId: getRequestOrgId() ?? null,
|
|
80
|
+
createdAt: now,
|
|
81
|
+
updatedAt: now,
|
|
82
|
+
});
|
|
83
|
+
const [saved] = await getDb()
|
|
84
|
+
.select({ id: schema.decks.id, title: schema.decks.title })
|
|
85
|
+
.from(schema.decks)
|
|
86
|
+
.where(eq(schema.decks.id, id));
|
|
87
|
+
if (!saved) throw new Error("Deck clone did not persist.");
|
|
88
|
+
return {
|
|
89
|
+
id: saved.id,
|
|
90
|
+
title: saved.title,
|
|
91
|
+
slideCount: deck.slides.length,
|
|
92
|
+
url: getDeckUrl(id),
|
|
93
|
+
clonedExactVersion: reference.publishedItemVersionId,
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
});
|
|
@@ -10,13 +10,14 @@ export default async function (args: string[]) {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const buf = fs.readFileSync(pdfPath);
|
|
13
|
-
const { CanvasFactory } = await import("pdf-parse/worker");
|
|
13
|
+
const { CanvasFactory, getData } = await import("pdf-parse/worker");
|
|
14
14
|
const { PDFParse } = await import("pdf-parse");
|
|
15
|
+
PDFParse.setWorker(getData());
|
|
15
16
|
const pdf = new PDFParse({
|
|
16
17
|
data: new Uint8Array(buf),
|
|
17
18
|
CanvasFactory,
|
|
18
19
|
});
|
|
19
|
-
const result = await pdf.getText();
|
|
20
|
+
const result = await pdf.getText().finally(() => pdf.destroy());
|
|
20
21
|
const pages = result.pages || [];
|
|
21
22
|
console.log("Total pages:", pages.length);
|
|
22
23
|
pages.forEach((page: { num: number; text: string }) => {
|
|
@@ -211,15 +211,16 @@ export default defineAction({
|
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
if (detectedFormat === "pdf") {
|
|
214
|
-
const { CanvasFactory } = await import("pdf-parse/worker");
|
|
214
|
+
const { CanvasFactory, getData } = await import("pdf-parse/worker");
|
|
215
215
|
const { PDFParse } = await import("pdf-parse");
|
|
216
|
+
PDFParse.setWorker(getData());
|
|
216
217
|
const { convertSectionsToSlides } =
|
|
217
218
|
await import("../server/handlers/import/html-converter.js");
|
|
218
219
|
const pdf = new PDFParse({
|
|
219
220
|
data: new Uint8Array(fileBuffer),
|
|
220
221
|
CanvasFactory,
|
|
221
222
|
});
|
|
222
|
-
const result = await pdf.getText();
|
|
223
|
+
const result = await pdf.getText().finally(() => pdf.destroy());
|
|
223
224
|
const pages = normalizePdfPages(result);
|
|
224
225
|
const textPages = pages.filter((p) => p.text.trim());
|
|
225
226
|
const title = titleFromPath(filename);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { VisibilityBadge, useT } from "@agent-native/core/client";
|
|
2
|
+
import { CreativeContextShareSheet } from "@agent-native/creative-context/client";
|
|
2
3
|
import {
|
|
3
4
|
IconDots,
|
|
4
5
|
IconTrash,
|
|
5
6
|
IconCopy,
|
|
6
7
|
IconPencil,
|
|
7
8
|
IconPalette,
|
|
9
|
+
IconPlus,
|
|
8
10
|
} from "@tabler/icons-react";
|
|
9
11
|
import { useState, useRef, useEffect } from "react";
|
|
10
12
|
import { Link } from "react-router";
|
|
@@ -42,6 +44,7 @@ export default function DeckCard({
|
|
|
42
44
|
const [isRenaming, setIsRenaming] = useState(false);
|
|
43
45
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
44
46
|
const [renameValue, setRenameValue] = useState(deck.title);
|
|
47
|
+
const [contextOpen, setContextOpen] = useState(false);
|
|
45
48
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
46
49
|
const pendingRenameRef = useRef(false);
|
|
47
50
|
|
|
@@ -188,6 +191,16 @@ export default function DeckCard({
|
|
|
188
191
|
<IconCopy className="w-3.5 h-3.5 me-2" />
|
|
189
192
|
{isDuplicating ? "Duplicating..." : "Duplicate"}
|
|
190
193
|
</DropdownMenuItem>
|
|
194
|
+
<DropdownMenuItem
|
|
195
|
+
onSelect={(event) => {
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
setMenuOpen(false);
|
|
198
|
+
setContextOpen(true);
|
|
199
|
+
}}
|
|
200
|
+
>
|
|
201
|
+
<IconPlus className="w-3.5 h-3.5 me-2" />
|
|
202
|
+
{t("creativeContext.addToContext" /* i18n-key-ignore */)}
|
|
203
|
+
</DropdownMenuItem>
|
|
191
204
|
<DropdownMenuSeparator />
|
|
192
205
|
<DropdownMenuItem
|
|
193
206
|
onClick={(e) => {
|
|
@@ -203,6 +216,20 @@ export default function DeckCard({
|
|
|
203
216
|
</DropdownMenuContent>
|
|
204
217
|
</DropdownMenu>
|
|
205
218
|
</div>
|
|
219
|
+
<CreativeContextShareSheet
|
|
220
|
+
open={contextOpen}
|
|
221
|
+
onOpenChange={setContextOpen}
|
|
222
|
+
resource={{
|
|
223
|
+
appId: "slides",
|
|
224
|
+
resourceType: "deck",
|
|
225
|
+
resourceId: deck.id,
|
|
226
|
+
title: deck.title,
|
|
227
|
+
updatedAt: deck.updatedAt,
|
|
228
|
+
visibility: deck.visibility,
|
|
229
|
+
preview: { kind: "document", label: "Deck" },
|
|
230
|
+
}}
|
|
231
|
+
canManage={deck.createdByMe}
|
|
232
|
+
/>
|
|
206
233
|
</div>
|
|
207
234
|
);
|
|
208
235
|
}
|