@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.
Files changed (196) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +13 -0
  3. package/corpus/core/docs/content/integrations.mdx +597 -0
  4. package/corpus/core/docs/content/locales/ar-SA/mcp-clients.mdx +19 -1
  5. package/corpus/core/docs/content/locales/de-DE/mcp-clients.mdx +22 -1
  6. package/corpus/core/docs/content/locales/es-ES/mcp-clients.mdx +23 -1
  7. package/corpus/core/docs/content/locales/fr-FR/mcp-clients.mdx +23 -1
  8. package/corpus/core/docs/content/locales/hi-IN/mcp-clients.mdx +22 -1
  9. package/corpus/core/docs/content/locales/ja-JP/mcp-clients.mdx +21 -1
  10. package/corpus/core/docs/content/locales/ko-KR/mcp-clients.mdx +20 -1
  11. package/corpus/core/docs/content/locales/pt-BR/mcp-clients.mdx +22 -1
  12. package/corpus/core/docs/content/locales/zh-CN/mcp-clients.mdx +17 -1
  13. package/corpus/core/docs/content/locales/zh-TW/mcp-clients.mdx +17 -1
  14. package/corpus/core/docs/content/mcp-clients.mdx +51 -1
  15. package/corpus/core/docs/content/organizations-teams-permissions.mdx +413 -0
  16. package/corpus/core/package.json +1 -1
  17. package/corpus/core/src/client/AssistantChat.tsx +13 -1
  18. package/corpus/core/src/client/chat/message-components.tsx +41 -0
  19. package/corpus/core/src/client/composer/TiptapComposer.tsx +45 -8
  20. package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +30 -11
  21. package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +240 -0
  22. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +159 -40
  23. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +433 -4
  24. package/corpus/core/src/client/resources/mcp-integration-logos.ts +108 -0
  25. package/corpus/core/src/deploy/build.ts +32 -0
  26. package/corpus/core/src/extensions/html-shell.ts +33 -1
  27. package/corpus/core/src/ingestion/office.ts +1 -2
  28. package/corpus/core/src/ingestion/pptx.ts +2 -4
  29. package/corpus/core/src/localization/default-messages.ts +126 -1
  30. package/corpus/core/src/mcp/actions/call-mcp-tool.ts +1 -0
  31. package/corpus/core/src/server/index.ts +4 -0
  32. package/corpus/core/src/server/org-admin.ts +28 -0
  33. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
  34. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
  35. package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
  36. package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +64 -0
  37. package/corpus/templates/analytics/AGENTS.md +5 -0
  38. package/corpus/templates/analytics/actions/clone-creative-context-dashboard.ts +86 -0
  39. package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -0
  40. package/corpus/templates/analytics/app/i18n/zh-TW.ts +1 -0
  41. package/corpus/templates/analytics/app/i18n-data.ts +1 -0
  42. package/corpus/templates/analytics/app/pages/Ask.tsx +8 -4
  43. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +59 -0
  44. package/corpus/templates/analytics/app/routes/agent.tsx +7 -1
  45. package/corpus/templates/analytics/changelog/2026-07-17-library-now-flags-published-dashboards-with-newer-versions-a.md +6 -0
  46. package/corpus/templates/analytics/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
  47. package/corpus/templates/analytics/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
  48. package/corpus/templates/analytics/package.json +1 -0
  49. package/corpus/templates/analytics/server/lib/native-creative-context.ts +158 -0
  50. package/corpus/templates/analytics/server/plugins/creative-context.ts +10 -0
  51. package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +12 -3
  52. package/corpus/templates/assets/AGENTS.md +5 -0
  53. package/corpus/templates/assets/actions/clone-creative-context-asset.ts +74 -0
  54. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +2 -1
  55. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +308 -178
  56. package/corpus/templates/assets/app/routes/library.tsx +5 -11
  57. package/corpus/templates/assets/changelog/2026-07-17-library-now-flags-published-assets-with-newer-versions-and-l.md +6 -0
  58. package/corpus/templates/assets/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
  59. package/corpus/templates/assets/server/lib/native-creative-context.ts +198 -0
  60. package/corpus/templates/assets/server/plugins/creative-context.ts +4 -0
  61. package/corpus/templates/brain/actions/provider-api-request.ts +1 -0
  62. package/corpus/templates/calendar/actions/provider-api-request.ts +1 -0
  63. package/corpus/templates/clips/actions/get-recording-insights.ts +7 -4
  64. package/corpus/templates/clips/actions/list-recordings.ts +48 -0
  65. package/corpus/templates/clips/actions/list-viewers.ts +2 -1
  66. package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +3 -1
  67. package/corpus/templates/clips/app/components/player/share-dialog.tsx +1 -3
  68. package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +11 -6
  69. package/corpus/templates/clips/app/hooks/use-view-tracking.ts +6 -1
  70. package/corpus/templates/clips/app/lib/ffmpeg-export.ts +4 -2
  71. package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -3
  72. package/corpus/templates/clips/changelog/2026-07-17-dictation-keeps-sentence-spacing-and-no-longer-crashes-when-.md +6 -0
  73. package/corpus/templates/clips/changelog/2026-07-17-shared-clips-now-preserve-editor-access-and-show-editor-insi.md +6 -0
  74. package/corpus/templates/clips/changelog/2026-07-17-stitching-clips-no-longer-fails-when-editor-media-metadata-i.md +6 -0
  75. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +14 -8
  76. package/corpus/templates/clips/shared/view-analytics.ts +4 -0
  77. package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +12 -3
  78. package/corpus/templates/content/AGENTS.md +5 -0
  79. package/corpus/templates/content/actions/clone-creative-context-document.ts +61 -0
  80. package/corpus/templates/content/actions/provider-api-request.ts +1 -0
  81. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +21 -0
  82. package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +29 -0
  83. package/corpus/templates/content/changelog/2026-07-17-library-now-flags-published-documents-with-newer-versions-an.md +6 -0
  84. package/corpus/templates/content/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
  85. package/corpus/templates/content/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
  86. package/corpus/templates/content/parity/matrix.md +1 -1
  87. package/corpus/templates/content/parity/matrix.ts +1 -0
  88. package/corpus/templates/content/server/lib/native-creative-context.ts +191 -0
  89. package/corpus/templates/content/server/plugins/creative-context.ts +8 -1
  90. package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +11 -3
  91. package/corpus/templates/design/AGENTS.md +5 -0
  92. package/corpus/templates/design/actions/clone-creative-context-design-native.ts +111 -0
  93. package/corpus/templates/design/actions/provider-api-request.ts +1 -0
  94. package/corpus/templates/design/app/pages/Index.tsx +44 -0
  95. package/corpus/templates/design/app/pages/design-editor/types.ts +1 -0
  96. package/corpus/templates/design/changelog/2026-07-17-library-now-flags-published-designs-with-newer-versions-and-.md +6 -0
  97. package/corpus/templates/design/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
  98. package/corpus/templates/design/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
  99. package/corpus/templates/design/server/lib/native-creative-context.ts +265 -0
  100. package/corpus/templates/design/server/plugins/creative-context.ts +8 -1
  101. package/corpus/templates/dispatch/actions/provider-api-request.ts +1 -0
  102. package/corpus/templates/mail/actions/provider-api-request.ts +1 -0
  103. package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +11 -3
  104. package/corpus/templates/slides/AGENTS.md +5 -0
  105. package/corpus/templates/slides/actions/clone-creative-context-deck.ts +96 -0
  106. package/corpus/templates/slides/actions/extract-pdf.ts +3 -2
  107. package/corpus/templates/slides/actions/import-file.ts +3 -2
  108. package/corpus/templates/slides/actions/provider-api-request.ts +1 -0
  109. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +27 -0
  110. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +21 -0
  111. package/corpus/templates/slides/changelog/2026-07-17-library-now-flags-published-decks-with-newer-versions-and-le.md +6 -0
  112. package/corpus/templates/slides/changelog/2026-07-17-pdf-and-powerpoint-imports-now-work-reliably-in-hosted-decks.md +6 -0
  113. package/corpus/templates/slides/changelog/2026-07-17-resources-can-be-added-to-creative-context-from-their-action.md +6 -0
  114. package/corpus/templates/slides/changelog/2026-07-17-you-can-add-exact-approved-artifact-versions-to-governed-cre.md +6 -0
  115. package/corpus/templates/slides/server/lib/native-creative-context.ts +288 -0
  116. package/corpus/templates/slides/server/plugins/creative-context.ts +4 -0
  117. package/dist/client/AssistantChat.d.ts.map +1 -1
  118. package/dist/client/AssistantChat.js +8 -2
  119. package/dist/client/AssistantChat.js.map +1 -1
  120. package/dist/client/chat/message-components.d.ts.map +1 -1
  121. package/dist/client/chat/message-components.js +35 -1
  122. package/dist/client/chat/message-components.js.map +1 -1
  123. package/dist/client/composer/TiptapComposer.d.ts +7 -0
  124. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  125. package/dist/client/composer/TiptapComposer.js +37 -8
  126. package/dist/client/composer/TiptapComposer.js.map +1 -1
  127. package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
  128. package/dist/client/integrations/IntegrationsPanel.js +3 -2
  129. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  130. package/dist/client/resources/McpConnectionSuggestion.d.ts +9 -0
  131. package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -0
  132. package/dist/client/resources/McpConnectionSuggestion.js +115 -0
  133. package/dist/client/resources/McpConnectionSuggestion.js.map +1 -0
  134. package/dist/client/resources/McpIntegrationDialog.d.ts +2 -1
  135. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  136. package/dist/client/resources/McpIntegrationDialog.js +48 -20
  137. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  138. package/dist/client/resources/mcp-integration-catalog.d.ts +9 -0
  139. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  140. package/dist/client/resources/mcp-integration-catalog.js +387 -4
  141. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  142. package/dist/client/resources/mcp-integration-logos.d.ts +2 -0
  143. package/dist/client/resources/mcp-integration-logos.d.ts.map +1 -0
  144. package/dist/client/resources/mcp-integration-logos.js +109 -0
  145. package/dist/client/resources/mcp-integration-logos.js.map +1 -0
  146. package/dist/collab/awareness.d.ts +2 -2
  147. package/dist/collab/awareness.d.ts.map +1 -1
  148. package/dist/deploy/build.d.ts.map +1 -1
  149. package/dist/deploy/build.js +23 -0
  150. package/dist/deploy/build.js.map +1 -1
  151. package/dist/extensions/html-shell.d.ts.map +1 -1
  152. package/dist/extensions/html-shell.js +33 -1
  153. package/dist/extensions/html-shell.js.map +1 -1
  154. package/dist/ingestion/office.d.ts.map +1 -1
  155. package/dist/ingestion/office.js +1 -2
  156. package/dist/ingestion/office.js.map +1 -1
  157. package/dist/ingestion/pptx.js +2 -4
  158. package/dist/ingestion/pptx.js.map +1 -1
  159. package/dist/localization/default-messages.d.ts +98 -0
  160. package/dist/localization/default-messages.d.ts.map +1 -1
  161. package/dist/localization/default-messages.js +99 -1
  162. package/dist/localization/default-messages.js.map +1 -1
  163. package/dist/mcp/actions/call-mcp-tool.js +1 -0
  164. package/dist/mcp/actions/call-mcp-tool.js.map +1 -1
  165. package/dist/notifications/routes.d.ts +1 -1
  166. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  167. package/dist/resources/handlers.d.ts +1 -1
  168. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  169. package/dist/server/index.d.ts +1 -0
  170. package/dist/server/index.d.ts.map +1 -1
  171. package/dist/server/index.js +1 -0
  172. package/dist/server/index.js.map +1 -1
  173. package/dist/server/org-admin.d.ts +3 -0
  174. package/dist/server/org-admin.d.ts.map +1 -0
  175. package/dist/server/org-admin.js +24 -0
  176. package/dist/server/org-admin.js.map +1 -0
  177. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
  178. package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
  179. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
  180. package/docs/content/integrations.mdx +597 -0
  181. package/docs/content/locales/ar-SA/mcp-clients.mdx +19 -1
  182. package/docs/content/locales/de-DE/mcp-clients.mdx +22 -1
  183. package/docs/content/locales/es-ES/mcp-clients.mdx +23 -1
  184. package/docs/content/locales/fr-FR/mcp-clients.mdx +23 -1
  185. package/docs/content/locales/hi-IN/mcp-clients.mdx +22 -1
  186. package/docs/content/locales/ja-JP/mcp-clients.mdx +21 -1
  187. package/docs/content/locales/ko-KR/mcp-clients.mdx +20 -1
  188. package/docs/content/locales/pt-BR/mcp-clients.mdx +22 -1
  189. package/docs/content/locales/zh-CN/mcp-clients.mdx +17 -1
  190. package/docs/content/locales/zh-TW/mcp-clients.mdx +17 -1
  191. package/docs/content/mcp-clients.mdx +51 -1
  192. package/docs/content/organizations-teams-permissions.mdx +413 -0
  193. package/package.json +1 -1
  194. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +9 -0
  195. package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +31 -0
  196. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +9 -0
@@ -0,0 +1,61 @@
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 { resolveNativeContextCloneReference } from "@agent-native/creative-context/server";
9
+ import { z } from "zod";
10
+
11
+ import createDocument from "./create-document.js";
12
+
13
+ export default defineAction({
14
+ description:
15
+ "Clone one exact governed Markdown document without returning its private source payload.",
16
+ schema: z.object({
17
+ contextId: z.string(),
18
+ artifactKey: z.string(),
19
+ resourceId: z.string(),
20
+ expectedUpdatedAt: z.string().optional(),
21
+ title: z.string().optional(),
22
+ parentId: z.string().optional(),
23
+ }),
24
+ publicAgent: { expose: true, readOnly: false, requiresAuth: true },
25
+ run: async (args) => {
26
+ const reference = await resolveNativeContextCloneReference({
27
+ appId: "content",
28
+ resourceType: "document",
29
+ resourceId: args.resourceId,
30
+ expectedUpdatedAt: args.expectedUpdatedAt,
31
+ contextId: args.contextId,
32
+ artifactKey: args.artifactKey,
33
+ });
34
+ const raw = await readPrivateBlob(
35
+ reference.cloneHandle as PrivateBlobHandle,
36
+ );
37
+ const content = Buffer.from(raw.data).toString("utf8");
38
+ const hash = createHash("sha256").update(content).digest("hex");
39
+ if (
40
+ raw.metadata?.appId !== "content" ||
41
+ raw.metadata?.resourceType !== "document" ||
42
+ raw.metadata?.resourceId !== args.resourceId ||
43
+ raw.metadata?.contentHash !== hash
44
+ )
45
+ throw new Error(
46
+ "Governed document clone payload failed integrity verification.",
47
+ );
48
+ const result = await createDocument.run({
49
+ title: args.title?.trim() || "Context document",
50
+ content,
51
+ ...(args.parentId ? { parentId: args.parentId } : {}),
52
+ });
53
+ if (!result?.id) throw new Error("Document clone did not persist.");
54
+ return {
55
+ id: result.id,
56
+ title: result.title,
57
+ urlPath: result.urlPath,
58
+ clonedExactVersion: reference.publishedItemVersionId,
59
+ };
60
+ },
61
+ });
@@ -202,6 +202,7 @@ export default defineAction({
202
202
  ),
203
203
  }),
204
204
  http: false,
205
+ toolCallable: false,
205
206
  run: async (args) => {
206
207
  if (args.stageAs) {
207
208
  const ctx = getCredentialContext();
@@ -7,6 +7,7 @@ import {
7
7
  type CollabUser,
8
8
  } from "@agent-native/core/client";
9
9
  import { ShareButton } from "@agent-native/core/client";
10
+ import { CreativeContextShareTab } from "@agent-native/creative-context/client";
10
11
  import type { DocumentSourceInfo } from "@shared/api";
11
12
  import {
12
13
  IconArrowBarDown,
@@ -711,6 +712,26 @@ export function DocumentToolbar({
711
712
  onCheckedChange: handleHideFromSearchChange,
712
713
  }}
713
714
  variant="compact"
715
+ shareTabs={{
716
+ tabs: [
717
+ {
718
+ value: "context",
719
+ label: "Context",
720
+ content: (
721
+ <CreativeContextShareTab
722
+ resource={{
723
+ appId: "content",
724
+ resourceType: "document",
725
+ resourceId: documentId,
726
+ title: documentTitle || "Untitled",
727
+ updatedAt: documentUpdatedAt ?? undefined,
728
+ preview: { kind: "document", label: "Document" },
729
+ }}
730
+ />
731
+ ),
732
+ },
733
+ ],
734
+ }}
714
735
  />
715
736
 
716
737
  <VersionHistoryPanel
@@ -1,4 +1,5 @@
1
1
  import { useT } from "@agent-native/core/client";
2
+ import { CreativeContextShareSheet } from "@agent-native/creative-context/client";
2
3
  import {
3
4
  SortableContext,
4
5
  useSortable,
@@ -114,6 +115,7 @@ export function DocumentTreeItem({
114
115
  const hasMenuActions = canEdit || canManage;
115
116
  const canCreateChild = canEdit && !isLocalFileNode;
116
117
  const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
118
+ const [contextSheetOpen, setContextSheetOpen] = useState(false);
117
119
  const indent = depth * 12 + 12;
118
120
  const rowWidth =
119
121
  sidebarWidth === undefined ? undefined : Math.max(0, sidebarWidth - 8);
@@ -250,6 +252,18 @@ export function DocumentTreeItem({
250
252
  </DropdownMenuItem>
251
253
  )}
252
254
  {canEdit && canManage && <DropdownMenuSeparator />}
255
+ {canEdit && !isLocalFileNode && (
256
+ <DropdownMenuItem
257
+ onSelect={(event) => {
258
+ event.preventDefault();
259
+ event.stopPropagation();
260
+ setContextSheetOpen(true);
261
+ }}
262
+ >
263
+ <IconPlus size={14} className="me-2" />
264
+ {t("creativeContext.addToContext" /* i18n-key-ignore */)}
265
+ </DropdownMenuItem>
266
+ )}
253
267
  {canManage && (
254
268
  <DropdownMenuItem
255
269
  className="text-destructive"
@@ -310,6 +324,21 @@ export function DocumentTreeItem({
310
324
  </div>
311
325
  </div>
312
326
 
327
+ <CreativeContextShareSheet
328
+ open={contextSheetOpen}
329
+ onOpenChange={setContextSheetOpen}
330
+ resource={{
331
+ appId: "content",
332
+ resourceType: "document",
333
+ resourceId: node.id,
334
+ title: node.title || "Untitled",
335
+ updatedAt: node.updatedAt,
336
+ visibility: node.visibility,
337
+ preview: { kind: "document", label: "Document" },
338
+ }}
339
+ canManage={canManage}
340
+ />
341
+
313
342
  {hasChildren && expanded && (
314
343
  <SortableContext
315
344
  items={node.children.map((child) => child.id)}
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-17
4
+ ---
5
+
6
+ Library now flags published documents with newer versions and lets you submit the update in place.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-17
4
+ ---
5
+
6
+ Resources can be added to Creative Context from their action menus.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-17
4
+ ---
5
+
6
+ You can add exact, approved artifact versions to governed Creative Contexts for safe reuse.
@@ -20,7 +20,7 @@ This generated matrix tracks whether high-value Content UI operations use the sa
20
20
  | sharing.document-discoverability-and-export | sharing | Share, hide from search, export, and reveal documents | action-backed | `export-document`, `reveal-local-source-file`, `set-document-discoverability`, `share-local-file-document` | `app/components/editor/DocumentToolbar.tsx`, `app/hooks/use-documents.ts` | Search discoverability, shareable copies, exports, and OS reveal requests are managed through Content actions. | - | - | P0 | covered | `actions/_local-file-documents.test.ts` | `local-file-source-truth` | - |
21
21
  | sharing.os-reveal-local-source | sharing | Reveal a local source file in the system file manager | host-only | `reveal-local-source-file` | `app/components/editor/DocumentToolbar.tsx`, `actions/reveal-local-source-file.ts` | - | OS reveal depends on trusted local host capabilities and should not spend agent tool surface or imply portable hosted behavior. | - | P2 | seeded | - | - | Local folder exception/docs PR |
22
22
  | sidebar.chrome-state | sidebar | Collapse sections and resize the sidebar | client-only-ephemeral | - | `app/components/sidebar/DocumentSidebar.tsx`, `app/components/layout/Layout.tsx` | - | - | - | P2 | none | - | - | - |
23
- | sidebar.document-tree-crud | sidebar | Create, delete, move, favorite, list, search, and open pages | action-backed | `create-document`, `delete-document`, `get-document`, `list-documents`, `move-document`, `search-documents`, `update-document` | `app/components/sidebar/DocumentSidebar.tsx`, `app/components/sidebar/DocumentTreeItem.tsx`, `app/hooks/use-documents.ts` | Document tree rows and document metadata are created, updated, deleted, moved, searched, or read. | - | - | P0 | covered | `actions/content-database-lifecycle.db.test.ts`, `actions/_local-file-documents.test.ts` | `document-search-edit` | - |
23
+ | sidebar.document-tree-crud | sidebar | Create, delete, move, favorite, list, search, and open pages | action-backed | `create-document`, `clone-creative-context-document`, `delete-document`, `get-document`, `list-documents`, `move-document`, `search-documents`, `update-document` | `app/components/sidebar/DocumentSidebar.tsx`, `app/components/sidebar/DocumentTreeItem.tsx`, `app/hooks/use-documents.ts` | Document tree rows and document metadata are created, updated, deleted, moved, searched, or read. | - | - | P0 | covered | `actions/content-database-lifecycle.db.test.ts`, `actions/_local-file-documents.test.ts` | `document-search-edit` | - |
24
24
  | sidebar.navigation-and-screen-context | sidebar | Navigate between documents and expose current screen context | action-equivalent | `navigate`, `view-screen` | `app/components/sidebar/DocumentSidebar.tsx`, `actions/navigate.ts`, `actions/view-screen.ts` | Application navigation state is updated or read so the agent can reason about the user's current page/view. | Human navigation is router-local, while agent navigation/screen inspection uses application-state actions to produce the same workspace orientation effect. | - | P1 | seeded | - | - | - |
25
25
  | source-sync.builder-body-hydration-worker | source-sync | Process queued Builder CMS body hydration work | action-backed | `process-builder-body-hydration` | `app/components/editor/DocumentEditor.tsx`, `app/components/editor/database/DatabaseView.tsx`, `app/hooks/use-content-database.ts` | Queued Builder body hydration entries are processed into readable Content document/database body state. | This action is intentionally hidden from the model with agentTool: false because it is an internal bounded queue worker; agents should use source refresh, review, and execution actions rather than manually driving hydration internals. | - | P0 | covered | `actions/_database-source-utils.test.ts` | - | - |
26
26
  | source-sync.builder-cms-review-and-write-gates | source-sync | Review, stage, validate, cancel, and execute Builder CMS source writes | action-backed | `cancel-prepared-builder-source-update`, `execute-builder-source-batch`, `execute-builder-source-execution`, `prepare-builder-source-execution`, `prepare-builder-source-review`, `preview-builder-source-review`, `review-content-database-source-change-set`, `set-content-database-source-write-mode`, `stage-builder-source-bulk-update`, `stage-builder-revision`, `validate-builder-source-execution` | `app/components/editor/DocumentDatabase.tsx`, `app/components/editor/database/DatabaseView.tsx`, `app/components/editor/database-sources/BuilderSourceReviewDialog.tsx` | Builder source write mode, staged reviews, pre-dispatch cancellations, validation records, and bounded execution records are created through guarded actions. | - | - | P0 | covered | `actions/builder-source-review-gates.db.test.ts`, `actions/cancel-prepared-builder-source-update.db.test.ts`, `actions/execute-builder-source-execution.test.ts`, `actions/stage-builder-source-bulk-update.db.test.ts` | `builder-source-review-readonly` | - |
@@ -17,6 +17,7 @@ export const parityMatrix: ParityRow[] = [
17
17
  status: "action-backed",
18
18
  actions: [
19
19
  "create-document",
20
+ "clone-creative-context-document",
20
21
  "delete-document",
21
22
  "get-document",
22
23
  "list-documents",
@@ -0,0 +1,191 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+
3
+ import { putPrivateBlob } from "@agent-native/core/private-blob";
4
+ import { accessFilter, resolveAccess } from "@agent-native/core/sharing";
5
+ import type { NativeResourceCaptureAdapter } from "@agent-native/creative-context/server";
6
+ import { and, inArray } from "drizzle-orm";
7
+
8
+ import { flushOpenDocumentEditorToSql } from "../../actions/_document-flush.js";
9
+ import { getDb, schema } from "../db/index.js";
10
+
11
+ interface DocumentPreviewBlock {
12
+ kind: "heading" | "paragraph" | "bullet" | "quote" | "code";
13
+ text: string;
14
+ level?: number;
15
+ }
16
+
17
+ function documentPreview(markdown: string) {
18
+ const lines = markdown.replace(/\r\n/g, "\n").split("\n");
19
+ const headings = lines
20
+ .filter((line) => /^#{1,6}\s+/.test(line))
21
+ .map((line) =>
22
+ line
23
+ .replace(/^#{1,6}\s+/, "")
24
+ .trim()
25
+ .slice(0, 160),
26
+ )
27
+ .filter(Boolean)
28
+ .slice(0, 8);
29
+ const excerpt = lines
30
+ .filter((line) => !/^\s*(?:```|#{1,6}\s+)/.test(line))
31
+ .join(" ")
32
+ .replace(/\s+/g, " ")
33
+ .trim()
34
+ .slice(0, 1_500);
35
+ let inCode = false;
36
+ const blocks = lines
37
+ .slice(0, 240)
38
+ .flatMap<DocumentPreviewBlock>((rawLine) => {
39
+ const line = rawLine.trim();
40
+ if (/^```/.test(line)) {
41
+ inCode = !inCode;
42
+ return [];
43
+ }
44
+ if (!line) return [];
45
+ if (inCode) {
46
+ return [{ kind: "code" as const, text: rawLine.slice(0, 600) }];
47
+ }
48
+ const heading = /^(#{1,6})\s+(.+)$/.exec(line);
49
+ if (heading) {
50
+ return [
51
+ {
52
+ kind: "heading" as const,
53
+ text: (heading[2] ?? "").slice(0, 300),
54
+ level: heading[1]?.length ?? 1,
55
+ },
56
+ ];
57
+ }
58
+ const bullet = /^(?:[-*+] |\d+[.)] )(.+)$/.exec(line);
59
+ if (bullet) {
60
+ return [
61
+ { kind: "bullet" as const, text: (bullet[1] ?? "").slice(0, 600) },
62
+ ];
63
+ }
64
+ if (line.startsWith(">")) {
65
+ return [
66
+ { kind: "quote" as const, text: line.slice(1).trim().slice(0, 600) },
67
+ ];
68
+ }
69
+ return [{ kind: "paragraph" as const, text: line.slice(0, 600) }];
70
+ });
71
+ return {
72
+ type: "document" as const,
73
+ headings,
74
+ excerpt,
75
+ blocks: blocks.slice(0, 40),
76
+ };
77
+ }
78
+
79
+ export const nativeDocumentCreativeContextAdapter: NativeResourceCaptureAdapter =
80
+ {
81
+ appId: "content",
82
+ resourceType: "document",
83
+ async listResourceVersions(resourceIds) {
84
+ if (!resourceIds.length) return [];
85
+ return getDb()
86
+ .select({
87
+ resourceId: schema.documents.id,
88
+ sourceModifiedAt: schema.documents.updatedAt,
89
+ })
90
+ .from(schema.documents)
91
+ .where(
92
+ and(
93
+ inArray(schema.documents.id, [...resourceIds]),
94
+ accessFilter(schema.documents, schema.documentShares),
95
+ ),
96
+ );
97
+ },
98
+ async capture(reference) {
99
+ const access = await resolveAccess("document", reference.resourceId);
100
+ if (!access) throw new Error("Document not found");
101
+ const initial = access.resource as typeof schema.documents.$inferSelect;
102
+ if (
103
+ reference.expectedUpdatedAt &&
104
+ reference.expectedUpdatedAt !== initial.updatedAt
105
+ )
106
+ throw new Error(
107
+ "Document changed before it could be submitted to Context.",
108
+ );
109
+ await flushOpenDocumentEditorToSql({
110
+ documentId: initial.id,
111
+ ownerEmail: initial.ownerEmail ?? null,
112
+ });
113
+ const refreshed = await resolveAccess("document", initial.id);
114
+ if (!refreshed) throw new Error("Document not found");
115
+ const document =
116
+ refreshed.resource as typeof schema.documents.$inferSelect;
117
+ const contentHash = createHash("sha256")
118
+ .update(document.content)
119
+ .digest("hex");
120
+ const versionId = randomUUID();
121
+ await getDb().insert(schema.documentVersions).values({
122
+ id: versionId,
123
+ ownerEmail: document.ownerEmail,
124
+ documentId: document.id,
125
+ title: document.title,
126
+ content: document.content,
127
+ createdAt: new Date().toISOString(),
128
+ });
129
+ const handle = await putPrivateBlob({
130
+ data: Buffer.from(document.content),
131
+ filename: `${document.id}.md`,
132
+ mimeType: "text/markdown",
133
+ ownerEmail: document.ownerEmail,
134
+ key: `creative-context/content/${document.id}/${contentHash}.md`,
135
+ metadata: {
136
+ appId: "content",
137
+ resourceType: "document",
138
+ resourceId: document.id,
139
+ contentHash,
140
+ },
141
+ });
142
+ if (!handle)
143
+ throw new Error(
144
+ "Private blob storage is required to submit a document to Context.",
145
+ );
146
+ return {
147
+ artifactKey: `content:document:${document.id}`,
148
+ source: {
149
+ name: "Content",
150
+ kind: "native-app",
151
+ externalRef: document.id,
152
+ access: {
153
+ visibility: document.visibility ?? "private",
154
+ canManage: refreshed.role === "owner" || refreshed.role === "admin",
155
+ },
156
+ },
157
+ items: [
158
+ {
159
+ externalId: `native:content:document:${document.id}`,
160
+ kind: "document",
161
+ title: document.title,
162
+ canonicalUrl: `/page/${document.id}`,
163
+ mimeType: "text/markdown",
164
+ content: document.content.slice(0, 40_000),
165
+ summary: document.description ?? "Immutable Markdown document.",
166
+ contentHash,
167
+ sourceModifiedAt: document.updatedAt,
168
+ sourceVersion: versionId,
169
+ metadata: { preview: documentPreview(document.content) },
170
+ },
171
+ ],
172
+ privateMetadata: {
173
+ nativeResource: {
174
+ appId: "content",
175
+ resourceType: "document",
176
+ resourceId: document.id,
177
+ expectedUpdatedAt: reference.expectedUpdatedAt,
178
+ },
179
+ clone: {
180
+ handle,
181
+ appId: "content",
182
+ resourceType: "document",
183
+ resourceId: document.id,
184
+ contentHash,
185
+ sourceVersion: versionId,
186
+ updatedAt: document.updatedAt,
187
+ },
188
+ },
189
+ };
190
+ },
191
+ };
@@ -1,7 +1,12 @@
1
1
  import { registerOnboardingStep } from "@agent-native/core/onboarding";
2
- import { setupCreativeContext } from "@agent-native/creative-context/server";
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 { nativeDocumentCreativeContextAdapter } 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(nativeDocumentCreativeContextAdapter);
37
+
31
38
  export default setupCreativeContext({ appId: "content" });
@@ -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
- `pinnedPackId` is set, prefer that immutable pack. Otherwise use
40
- `currentPackId` when it records context already selected for this session.
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
  }
@@ -114,3 +117,8 @@ If `nativeCode.content` is `null` and `oversized` is true, use the named
114
117
  `get-context-item`, but the inline content is only the validated manifest shell.
115
118
  Never concatenate a truncated fragment or use delimited `version.content` as
116
119
  HTML.
120
+
121
+ For an app-created Design snapshot, use
122
+ `clone-creative-context-design-native` instead. That typed action resolves the
123
+ exact approved private file/Yjs payload and duplicates it through Design's
124
+ native path. Generic context actions must never receive or return that payload.
@@ -178,6 +178,11 @@ patterns live in `.agents/skills/`.
178
178
  `.agents/skills/creative-context/SKILL.md`: explicit request and current
179
179
  design first, then a pinned/current pack, then narrow library search. Respect
180
180
  `creative-context.contextMode: "off"` without silently restoring a pack.
181
+ - To submit a design to a governed Creative Context, use the Context tab or
182
+ `manage-context-membership`; it captures one immutable live design snapshot.
183
+ Reuse only a returned opaque native clone reference through the Design clone action.
184
+ Use `operation="submit-latest"` with a Library membership id when its native
185
+ update status reports `update-available`.
181
186
  - For reusable design-system setup from Figma, connected code/GitHub, local
182
187
  code/design files, or optional `design.md`, use Builder-backed DSI indexing
183
188
  through `index-design-system-with-builder` or the Design System Setup `.fig`
@@ -0,0 +1,111 @@
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 { resolveNativeContextCloneReference } from "@agent-native/creative-context/server";
9
+ import { z } from "zod";
10
+
11
+ import { mutateDesignData } from "../server/lib/design-data-mutation.js";
12
+ import { saveImportedDesignFiles } from "../server/lib/import-design-files.js";
13
+ import createDesign from "./create-design.js";
14
+
15
+ const payloadSchema = z.object({
16
+ designId: z.string(),
17
+ designData: z.string(),
18
+ files: z.array(
19
+ z.object({
20
+ filename: z.string(),
21
+ fileType: z.enum(["html", "css", "jsx", "asset"]),
22
+ content: z.string(),
23
+ }),
24
+ ),
25
+ tweaks: z.unknown().optional(),
26
+ appliedTweaks: z.unknown().optional(),
27
+ resolvedCssVars: z.unknown().optional(),
28
+ });
29
+
30
+ export default defineAction({
31
+ description:
32
+ "Clone an exact governed Design snapshot into a new editable Design project without exposing the source payload.",
33
+ schema: z.object({
34
+ contextId: z.string(),
35
+ artifactKey: z.string(),
36
+ resourceId: z.string(),
37
+ expectedUpdatedAt: z.string().optional(),
38
+ title: z.string().optional(),
39
+ }),
40
+ publicAgent: { expose: true, readOnly: false, requiresAuth: true },
41
+ run: async (args) => {
42
+ const reference = await resolveNativeContextCloneReference({
43
+ appId: "design",
44
+ resourceType: "design",
45
+ resourceId: args.resourceId,
46
+ expectedUpdatedAt: args.expectedUpdatedAt,
47
+ contextId: args.contextId,
48
+ artifactKey: args.artifactKey,
49
+ });
50
+ const raw = await readPrivateBlob(
51
+ reference.cloneHandle as PrivateBlobHandle,
52
+ );
53
+ const body = Buffer.from(raw.data).toString("utf8");
54
+ const hash = createHash("sha256").update(body).digest("hex");
55
+ if (
56
+ raw.metadata?.appId !== "design" ||
57
+ raw.metadata?.resourceType !== "design" ||
58
+ raw.metadata?.resourceId !== args.resourceId ||
59
+ raw.metadata?.contentHash !== hash
60
+ )
61
+ throw new Error(
62
+ "Governed design clone payload failed integrity verification.",
63
+ );
64
+ const payload = payloadSchema.parse(JSON.parse(body));
65
+ const created = await createDesign.run({
66
+ title: args.title?.trim() || "Context design",
67
+ projectType: "prototype",
68
+ });
69
+ const saved = await saveImportedDesignFiles({
70
+ designId: created.id,
71
+ sourceType: "creative-context-native-clone",
72
+ preserveExactContent: true,
73
+ files: payload.files.map((file) => ({
74
+ ...file,
75
+ source: {
76
+ creativeContextItemVersionId: reference.publishedItemVersionId,
77
+ },
78
+ })),
79
+ });
80
+ if (saved.files.length !== payload.files.length)
81
+ throw new Error("Design clone did not persist every saved file.");
82
+ const capturedData = z
83
+ .record(z.string(), z.unknown())
84
+ .parse(JSON.parse(payload.designData));
85
+ const {
86
+ canvasFrames: _capturedFrames,
87
+ screenMetadata: _capturedMetadata,
88
+ ...capturedState
89
+ } = capturedData;
90
+ await mutateDesignData({
91
+ designId: created.id,
92
+ mutate: (current) => ({
93
+ ...capturedState,
94
+ canvasFrames: current.canvasFrames,
95
+ screenMetadata: current.screenMetadata,
96
+ }),
97
+ isApplied: (persisted) =>
98
+ Object.entries(capturedState).every(
99
+ ([key, value]) =>
100
+ JSON.stringify(persisted[key]) === JSON.stringify(value),
101
+ ),
102
+ });
103
+ return {
104
+ designId: saved.designId,
105
+ title: created.title,
106
+ fileCount: saved.files.length,
107
+ urlPath: saved.urlPath,
108
+ clonedExactVersion: reference.publishedItemVersionId,
109
+ };
110
+ },
111
+ });
@@ -204,6 +204,7 @@ export default defineAction({
204
204
  ),
205
205
  }),
206
206
  http: false,
207
+ toolCallable: false,
207
208
  needsApproval: requiresProviderApiApproval,
208
209
  run: async (args) => {
209
210
  if (args.stageAs) {