@agent-native/core 0.101.6 → 0.101.10

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 (237) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +28 -0
  3. package/corpus/core/docs/content/deployment.mdx +9 -7
  4. package/corpus/core/docs/content/locales/ar-SA/deployment.mdx +9 -7
  5. package/corpus/core/docs/content/locales/de-DE/deployment.mdx +9 -7
  6. package/corpus/core/docs/content/locales/es-ES/deployment.mdx +9 -7
  7. package/corpus/core/docs/content/locales/fr-FR/deployment.mdx +9 -7
  8. package/corpus/core/docs/content/locales/hi-IN/deployment.mdx +9 -7
  9. package/corpus/core/docs/content/locales/ja-JP/deployment.mdx +9 -7
  10. package/corpus/core/docs/content/locales/ko-KR/deployment.mdx +9 -7
  11. package/corpus/core/docs/content/locales/pt-BR/deployment.mdx +9 -7
  12. package/corpus/core/docs/content/locales/zh-CN/deployment.mdx +9 -7
  13. package/corpus/core/docs/content/locales/zh-TW/deployment.mdx +9 -7
  14. package/corpus/core/package.json +1 -1
  15. package/corpus/core/src/a2a/artifact-response.ts +255 -12
  16. package/corpus/core/src/agent/thread-data-builder.ts +84 -11
  17. package/corpus/core/src/client/review/ReviewCommentComposer.tsx +9 -1
  18. package/corpus/core/src/client/review/ReviewThreadPanel.tsx +17 -2
  19. package/corpus/core/src/client/settings/SettingsPanel.tsx +41 -21
  20. package/corpus/core/src/client/settings/useBuilderStatus.ts +28 -9
  21. package/corpus/core/src/client/setup-connections/BuilderConnectCard.tsx +2 -7
  22. package/corpus/core/src/integrations/a2a-continuation-processor.ts +99 -7
  23. package/corpus/core/src/integrations/adapters/discord.ts +3 -1
  24. package/corpus/core/src/integrations/adapters/email.ts +4 -1
  25. package/corpus/core/src/integrations/adapters/google-docs.ts +4 -1
  26. package/corpus/core/src/integrations/adapters/microsoft-teams.ts +3 -1
  27. package/corpus/core/src/integrations/adapters/slack.ts +38 -9
  28. package/corpus/core/src/integrations/adapters/telegram.ts +32 -10
  29. package/corpus/core/src/integrations/adapters/whatsapp.ts +5 -1
  30. package/corpus/core/src/integrations/index.ts +1 -0
  31. package/corpus/core/src/integrations/types.ts +9 -2
  32. package/corpus/core/src/integrations/webhook-handler.ts +69 -45
  33. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +1 -0
  34. package/corpus/core/src/server/auth.ts +25 -1
  35. package/corpus/core/src/server/builder-browser.ts +353 -1
  36. package/corpus/core/src/server/core-routes-plugin.ts +601 -223
  37. package/corpus/templates/calendar/app/components/calendar/DayView.tsx +80 -1
  38. package/corpus/templates/calendar/app/components/calendar/EventCard.tsx +28 -3
  39. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +5 -1
  40. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +30 -3
  41. package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +196 -0
  42. package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +115 -1
  43. package/corpus/templates/calendar/app/lib/out-of-office.ts +45 -0
  44. package/corpus/templates/calendar/changelog/2026-07-14-out-of-office-blocks-now-sit-behind-meetings-and-event-stack.md +6 -0
  45. package/corpus/templates/content/.agents/skills/content/SKILL.md +31 -0
  46. package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +35 -21
  47. package/corpus/templates/content/AGENTS.md +32 -9
  48. package/corpus/templates/content/actions/_builder-cms-intent-lookup.ts +87 -0
  49. package/corpus/templates/content/actions/_builder-cms-read-client.ts +173 -25
  50. package/corpus/templates/content/actions/_builder-cms-source-adapter.ts +1 -0
  51. package/corpus/templates/content/actions/_builder-cms-write-adapter.ts +427 -18
  52. package/corpus/templates/content/actions/_builder-cms-write-client.ts +17 -73
  53. package/corpus/templates/content/actions/_builder-cms-write-settings.ts +27 -7
  54. package/corpus/templates/content/actions/_builder-source-execution-claim.ts +124 -0
  55. package/corpus/templates/content/actions/_builder-source-execution-preservation.ts +21 -0
  56. package/corpus/templates/content/actions/_builder-source-timings.ts +57 -0
  57. package/corpus/templates/content/actions/_database-source-utils.ts +1071 -170
  58. package/corpus/templates/content/actions/_database-utils.ts +104 -13
  59. package/corpus/templates/content/actions/_local-file-documents.ts +53 -1
  60. package/corpus/templates/content/actions/_preview-document-draft.ts +31 -0
  61. package/corpus/templates/content/actions/_property-utils.ts +7 -1
  62. package/corpus/templates/content/actions/cancel-prepared-builder-source-update.ts +309 -0
  63. package/corpus/templates/content/actions/configure-document-property.ts +11 -0
  64. package/corpus/templates/content/actions/create-content-database.ts +11 -0
  65. package/corpus/templates/content/actions/create-document.ts +9 -0
  66. package/corpus/templates/content/actions/create-inline-content-database.ts +3 -0
  67. package/corpus/templates/content/actions/execute-builder-source-batch.ts +120 -49
  68. package/corpus/templates/content/actions/execute-builder-source-execution.ts +608 -264
  69. package/corpus/templates/content/actions/export-content-source.ts +1 -0
  70. package/corpus/templates/content/actions/get-content-database.ts +13 -1
  71. package/corpus/templates/content/actions/get-document.ts +12 -2
  72. package/corpus/templates/content/actions/get-preview-document-draft.ts +26 -0
  73. package/corpus/templates/content/actions/import-content-source.ts +6 -0
  74. package/corpus/templates/content/actions/list-documents.ts +3 -0
  75. package/corpus/templates/content/actions/materialize-builder-required-fields.ts +550 -0
  76. package/corpus/templates/content/actions/prepare-builder-source-execution.ts +112 -65
  77. package/corpus/templates/content/actions/prepare-builder-source-review.ts +463 -170
  78. package/corpus/templates/content/actions/preview-builder-source-review.ts +99 -0
  79. package/corpus/templates/content/actions/pull-document.ts +2 -0
  80. package/corpus/templates/content/actions/search-documents.ts +5 -1
  81. package/corpus/templates/content/actions/set-content-database-source-write-mode.ts +2 -2
  82. package/corpus/templates/content/actions/update-document.ts +16 -1
  83. package/corpus/templates/content/actions/update-preview-document-draft.ts +153 -0
  84. package/corpus/templates/content/actions/view-screen.ts +15 -2
  85. package/corpus/templates/content/app/components/editor/DescriptionField.tsx +121 -0
  86. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +14 -0
  87. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +250 -49
  88. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +57 -5
  89. package/corpus/templates/content/app/components/editor/body-hydration.ts +27 -0
  90. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +2414 -589
  91. package/corpus/templates/content/app/components/editor/database/settings.tsx +13 -10
  92. package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +358 -75
  93. package/corpus/templates/content/app/components/editor/previewDocumentSaveController.ts +124 -29
  94. package/corpus/templates/content/app/components/editor/previewDocumentSaveRegistry.ts +2 -0
  95. package/corpus/templates/content/app/global.css +18 -1
  96. package/corpus/templates/content/app/hooks/use-content-database.ts +68 -0
  97. package/corpus/templates/content/app/hooks/use-documents.ts +53 -4
  98. package/corpus/templates/content/app/i18n/zh-TW.ts +30 -0
  99. package/corpus/templates/content/app/i18n-data.ts +339 -0
  100. package/corpus/templates/content/changelog/2026-07-10-builder-backed-preview-edits-are-preserved-when-article-bodi.md +6 -0
  101. package/corpus/templates/content/changelog/2026-07-10-builder-cms-sources-can-now-be-enabled-for-guarded-staged-or.md +6 -0
  102. package/corpus/templates/content/changelog/2026-07-13-builder-connection-setup-is-now-available-directly-from-conn.md +6 -0
  103. package/corpus/templates/content/changelog/2026-07-13-builder-reviews-now-hide-already-applied-writes-detect-nativ.md +6 -0
  104. package/corpus/templates/content/changelog/2026-07-13-required-builder-publishing-fields-can-now-be-added-directly.md +6 -0
  105. package/corpus/templates/content/changelog/2026-07-13-you-can-now-cancel-a-prepared-builder-update-safely-before-i.md +6 -0
  106. package/corpus/templates/content/changelog/2026-07-14-builder-account-connection-now-remains-available-when-branch.md +6 -0
  107. package/corpus/templates/content/changelog/2026-07-14-builder-backed-articles-now-preserve-fifth-and-sixth-level-h.md +6 -0
  108. package/corpus/templates/content/changelog/2026-07-14-builder-sources-now-review-and-publish-rich-article-updates-.md +6 -0
  109. package/corpus/templates/content/changelog/2026-07-14-builder-writes-now-stop-retries-when-reconciliation-is-needed.md +6 -0
  110. package/corpus/templates/content/changelog/2026-07-14-file-and-media-links-now-validate-before-saving.md +6 -0
  111. package/corpus/templates/content/changelog/2026-07-14-pages-and-databases-can-describe-themselves-with-guidance-fo.md +6 -0
  112. package/corpus/templates/content/changelog/2026-07-14-slack-follow-ups-now-retain-created-content-identity-and-per.md +6 -0
  113. package/corpus/templates/content/parity/matrix.md +27 -25
  114. package/corpus/templates/content/parity/matrix.ts +50 -2
  115. package/corpus/templates/content/server/db/schema.ts +51 -0
  116. package/corpus/templates/content/server/lib/document-context.ts +76 -0
  117. package/corpus/templates/content/server/lib/public-documents.ts +3 -0
  118. package/corpus/templates/content/server/plugins/auth.ts +1 -0
  119. package/corpus/templates/content/server/plugins/db.ts +59 -0
  120. package/corpus/templates/content/server/routes/api/document-agent-context.json.get.ts +5 -0
  121. package/corpus/templates/content/shared/api.ts +87 -1
  122. package/corpus/templates/content/shared/builder-mdx.ts +705 -15
  123. package/corpus/templates/content/shared/content-source.ts +7 -0
  124. package/corpus/templates/content/shared/nfm.ts +3 -3
  125. package/corpus/templates/content/shared/properties.ts +2 -0
  126. package/corpus/templates/design/app/components/design/ReadOnlyDesignBanner.tsx +52 -7
  127. package/corpus/templates/design/app/components/design/ReviewCommentsPanel.tsx +36 -4
  128. package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +4 -1
  129. package/corpus/templates/design/app/i18n/ar-SA.ts +1 -0
  130. package/corpus/templates/design/app/i18n/de-DE.ts +1 -0
  131. package/corpus/templates/design/app/i18n/en-US.ts +1 -0
  132. package/corpus/templates/design/app/i18n/es-ES.ts +1 -0
  133. package/corpus/templates/design/app/i18n/fr-FR.ts +1 -0
  134. package/corpus/templates/design/app/i18n/hi-IN.ts +1 -0
  135. package/corpus/templates/design/app/i18n/ja-JP.ts +1 -0
  136. package/corpus/templates/design/app/i18n/ko-KR.ts +1 -0
  137. package/corpus/templates/design/app/i18n/pt-BR.ts +1 -0
  138. package/corpus/templates/design/app/i18n/zh-CN.ts +1 -0
  139. package/corpus/templates/design/app/i18n/zh-TW.ts +1 -0
  140. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +8 -0
  141. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +11 -0
  142. package/corpus/templates/design/changelog/2026-07-14-reviewers-can-now-pin-comments-from-the-canvas-toolbar-targe.md +6 -0
  143. package/corpus/templates/design/changelog/2026-07-15-viewer-comment-controls-now-sit-inside-the-read-only-notice-.md +6 -0
  144. package/corpus/templates/design/shared/review-anchor.ts +48 -0
  145. package/corpus/templates/plan/server/plan-mdx.ts +53 -7
  146. package/dist/a2a/artifact-response.d.ts +15 -0
  147. package/dist/a2a/artifact-response.d.ts.map +1 -1
  148. package/dist/a2a/artifact-response.js +204 -5
  149. package/dist/a2a/artifact-response.js.map +1 -1
  150. package/dist/agent/thread-data-builder.d.ts +6 -0
  151. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  152. package/dist/agent/thread-data-builder.js +71 -8
  153. package/dist/agent/thread-data-builder.js.map +1 -1
  154. package/dist/client/review/ReviewCommentComposer.d.ts +2 -1
  155. package/dist/client/review/ReviewCommentComposer.d.ts.map +1 -1
  156. package/dist/client/review/ReviewCommentComposer.js +3 -3
  157. package/dist/client/review/ReviewCommentComposer.js.map +1 -1
  158. package/dist/client/review/ReviewThreadPanel.d.ts +9 -1
  159. package/dist/client/review/ReviewThreadPanel.d.ts.map +1 -1
  160. package/dist/client/review/ReviewThreadPanel.js +6 -4
  161. package/dist/client/review/ReviewThreadPanel.js.map +1 -1
  162. package/dist/client/settings/SettingsPanel.d.ts +3 -0
  163. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  164. package/dist/client/settings/SettingsPanel.js +11 -4
  165. package/dist/client/settings/SettingsPanel.js.map +1 -1
  166. package/dist/client/settings/useBuilderStatus.d.ts +8 -4
  167. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  168. package/dist/client/settings/useBuilderStatus.js +19 -6
  169. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  170. package/dist/client/setup-connections/BuilderConnectCard.d.ts.map +1 -1
  171. package/dist/client/setup-connections/BuilderConnectCard.js +2 -5
  172. package/dist/client/setup-connections/BuilderConnectCard.js.map +1 -1
  173. package/dist/collab/awareness.d.ts +2 -2
  174. package/dist/collab/awareness.d.ts.map +1 -1
  175. package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
  176. package/dist/integrations/a2a-continuation-processor.js +72 -6
  177. package/dist/integrations/a2a-continuation-processor.js.map +1 -1
  178. package/dist/integrations/adapters/discord.d.ts.map +1 -1
  179. package/dist/integrations/adapters/discord.js +1 -0
  180. package/dist/integrations/adapters/discord.js.map +1 -1
  181. package/dist/integrations/adapters/email.d.ts.map +1 -1
  182. package/dist/integrations/adapters/email.js +2 -0
  183. package/dist/integrations/adapters/email.js.map +1 -1
  184. package/dist/integrations/adapters/google-docs.d.ts.map +1 -1
  185. package/dist/integrations/adapters/google-docs.js +2 -0
  186. package/dist/integrations/adapters/google-docs.js.map +1 -1
  187. package/dist/integrations/adapters/microsoft-teams.d.ts.map +1 -1
  188. package/dist/integrations/adapters/microsoft-teams.js +1 -0
  189. package/dist/integrations/adapters/microsoft-teams.js.map +1 -1
  190. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  191. package/dist/integrations/adapters/slack.js +21 -6
  192. package/dist/integrations/adapters/slack.js.map +1 -1
  193. package/dist/integrations/adapters/telegram.d.ts.map +1 -1
  194. package/dist/integrations/adapters/telegram.js +11 -2
  195. package/dist/integrations/adapters/telegram.js.map +1 -1
  196. package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
  197. package/dist/integrations/adapters/whatsapp.js +3 -0
  198. package/dist/integrations/adapters/whatsapp.js.map +1 -1
  199. package/dist/integrations/index.d.ts +1 -1
  200. package/dist/integrations/index.d.ts.map +1 -1
  201. package/dist/integrations/index.js.map +1 -1
  202. package/dist/integrations/types.d.ts +8 -2
  203. package/dist/integrations/types.d.ts.map +1 -1
  204. package/dist/integrations/types.js.map +1 -1
  205. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  206. package/dist/integrations/webhook-handler.js +40 -43
  207. package/dist/integrations/webhook-handler.js.map +1 -1
  208. package/dist/observability/routes.d.ts +5 -5
  209. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  210. package/dist/secrets/routes.d.ts +9 -9
  211. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  212. package/dist/server/agent-chat/action-filters-a2a.js +1 -0
  213. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  214. package/dist/server/auth.d.ts +1 -0
  215. package/dist/server/auth.d.ts.map +1 -1
  216. package/dist/server/auth.js +19 -2
  217. package/dist/server/auth.js.map +1 -1
  218. package/dist/server/builder-browser.d.ts +78 -0
  219. package/dist/server/builder-browser.d.ts.map +1 -1
  220. package/dist/server/builder-browser.js +246 -1
  221. package/dist/server/builder-browser.js.map +1 -1
  222. package/dist/server/core-routes-plugin.d.ts +41 -0
  223. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  224. package/dist/server/core-routes-plugin.js +260 -14
  225. package/dist/server/core-routes-plugin.js.map +1 -1
  226. package/docs/content/deployment.mdx +9 -7
  227. package/docs/content/locales/ar-SA/deployment.mdx +9 -7
  228. package/docs/content/locales/de-DE/deployment.mdx +9 -7
  229. package/docs/content/locales/es-ES/deployment.mdx +9 -7
  230. package/docs/content/locales/fr-FR/deployment.mdx +9 -7
  231. package/docs/content/locales/hi-IN/deployment.mdx +9 -7
  232. package/docs/content/locales/ja-JP/deployment.mdx +9 -7
  233. package/docs/content/locales/ko-KR/deployment.mdx +9 -7
  234. package/docs/content/locales/pt-BR/deployment.mdx +9 -7
  235. package/docs/content/locales/zh-CN/deployment.mdx +9 -7
  236. package/docs/content/locales/zh-TW/deployment.mdx +9 -7
  237. package/package.json +2 -2
@@ -1,3 +1,5 @@
1
+ import { createHmac, timingSafeEqual } from "node:crypto";
2
+
1
3
  export interface A2AToolResultSummary {
2
4
  tool: string;
3
5
  result: string;
@@ -6,6 +8,121 @@ export interface A2AToolResultSummary {
6
8
  export interface A2AArtifactResponseOptions {
7
9
  baseUrl?: string;
8
10
  includeReferencedArtifacts?: boolean;
11
+ includePersistedArtifactMarker?: boolean;
12
+ }
13
+
14
+ export interface A2AArtifactIdentity {
15
+ resourceType:
16
+ | "document"
17
+ | "deck"
18
+ | "dashboard"
19
+ | "analysis"
20
+ | "image"
21
+ | "design"
22
+ | "monitor"
23
+ | "form";
24
+ id: string;
25
+ sourceAction: string;
26
+ titleAtAction?: string;
27
+ url?: string;
28
+ }
29
+
30
+ const ARTIFACT_IDENTITY_WRITE_TOOLS = new Set([
31
+ "save-monitor",
32
+ "create-form",
33
+ "submit-content-database-form",
34
+ "add-database-item",
35
+ "create-document",
36
+ "update-document",
37
+ "create-deck",
38
+ "duplicate-deck",
39
+ "add-slide",
40
+ "update-dashboard",
41
+ "rename-dashboard",
42
+ "save-analysis",
43
+ "generate-image",
44
+ "edit-image",
45
+ "refine-image",
46
+ "restyle-image",
47
+ "save-generated-image",
48
+ "save-generated-asset",
49
+ "export-image",
50
+ "export-asset",
51
+ "generate-image-batch",
52
+ "create-design",
53
+ "generate-design",
54
+ "create-file",
55
+ "duplicate-design",
56
+ ]);
57
+
58
+ const PERSISTED_ARTIFACT_MARKER = "agent-native:persisted-artifacts=";
59
+ const PERSISTED_ARTIFACT_MARKER_PATTERN =
60
+ /\s*<!--\s*agent-native:persisted-artifacts=[A-Za-z0-9_-]+\.[a-f0-9]{64}\s*-->/g;
61
+ const ARTIFACT_RESOURCE_TYPES = new Set<A2AArtifactIdentity["resourceType"]>([
62
+ "document",
63
+ "deck",
64
+ "dashboard",
65
+ "analysis",
66
+ "image",
67
+ "design",
68
+ "monitor",
69
+ "form",
70
+ ]);
71
+
72
+ function persistedArtifactIdentitiesFromMarker(
73
+ result: string,
74
+ ): A2AArtifactIdentity[] {
75
+ const secret = process.env.A2A_SECRET;
76
+ if (!secret) return [];
77
+ const match = result.match(
78
+ /<!--\s*agent-native:persisted-artifacts=([A-Za-z0-9_-]+)\.([a-f0-9]{64})\s*-->/,
79
+ );
80
+ if (!match) return [];
81
+ try {
82
+ const payload = match[1];
83
+ const expected = createHmac("sha256", secret).update(payload).digest();
84
+ const supplied = Buffer.from(match[2], "hex");
85
+ if (
86
+ supplied.length !== expected.length ||
87
+ !timingSafeEqual(supplied, expected)
88
+ ) {
89
+ return [];
90
+ }
91
+ const parsed = JSON.parse(Buffer.from(payload, "base64url").toString());
92
+ if (!Array.isArray(parsed)) return [];
93
+ return parsed
94
+ .slice(0, 12)
95
+ .filter((identity): identity is A2AArtifactIdentity => {
96
+ const item = asRecord(identity);
97
+ return (
98
+ !!item &&
99
+ ARTIFACT_RESOURCE_TYPES.has(
100
+ item.resourceType as A2AArtifactIdentity["resourceType"],
101
+ ) &&
102
+ typeof item.id === "string" &&
103
+ typeof item.sourceAction === "string"
104
+ );
105
+ });
106
+ } catch {
107
+ return [];
108
+ }
109
+ }
110
+
111
+ function withPersistedArtifactMarker(
112
+ text: string,
113
+ toolResults: A2AToolResultSummary[],
114
+ ): string {
115
+ const identities = extractA2AArtifactIdentities(toolResults).slice(0, 12);
116
+ const secret = process.env.A2A_SECRET;
117
+ if (identities.length === 0 || !secret) return text;
118
+ const payload = Buffer.from(JSON.stringify(identities)).toString("base64url");
119
+ const signature = createHmac("sha256", secret).update(payload).digest("hex");
120
+ const marker = `<!-- ${PERSISTED_ARTIFACT_MARKER}${payload}.${signature} -->`;
121
+ return text ? `${text}\n\n${marker}` : marker;
122
+ }
123
+
124
+ export function stripA2APersistedArtifactMarkers(text: string): string {
125
+ return text.replace(PERSISTED_ARTIFACT_MARKER_PATTERN, "").trim();
9
126
  }
10
127
 
11
128
  interface CreatedDocumentArtifact {
@@ -617,15 +734,25 @@ function collectArtifacts(results: A2AToolResultSummary[]): {
617
734
 
618
735
  if (
619
736
  toolResult.tool === "generate-image" ||
737
+ toolResult.tool === "edit-image" ||
620
738
  toolResult.tool === "refine-image" ||
739
+ toolResult.tool === "restyle-image" ||
621
740
  toolResult.tool === "get-asset" ||
622
741
  toolResult.tool === "save-generated-image" ||
742
+ toolResult.tool === "save-generated-asset" ||
623
743
  toolResult.tool === "export-image"
624
744
  ) {
625
745
  addImageArtifact(images, parsed);
626
746
  continue;
627
747
  }
628
748
 
749
+ if (toolResult.tool === "export-asset") {
750
+ if (stringValue(parsed.artifactType) === "image") {
751
+ addImageArtifact(images, parsed);
752
+ }
753
+ continue;
754
+ }
755
+
629
756
  if (toolResult.tool === "generate-image-batch") {
630
757
  if (Array.isArray(parsed.images)) {
631
758
  for (const item of parsed.images) {
@@ -730,6 +857,114 @@ function collectArtifacts(results: A2AToolResultSummary[]): {
730
857
  };
731
858
  }
732
859
 
860
+ /**
861
+ * Extract a compact, verified identity ledger from successful artifact tools.
862
+ * The ledger deliberately excludes raw tool results so it is safe to retain in
863
+ * long-lived thread context and stable even when a resource is later renamed.
864
+ */
865
+ export function extractA2AArtifactIdentities(
866
+ results: A2AToolResultSummary[],
867
+ ): A2AArtifactIdentity[] {
868
+ const identities = new Map<string, A2AArtifactIdentity>();
869
+
870
+ const remember = (identity: A2AArtifactIdentity) => {
871
+ identities.set(`${identity.resourceType}:${identity.id}`, identity);
872
+ };
873
+
874
+ for (const result of results) {
875
+ if (result.tool === "call-agent") {
876
+ for (const identity of persistedArtifactIdentitiesFromMarker(
877
+ result.result,
878
+ )) {
879
+ remember({ ...identity, sourceAction: "call-agent" });
880
+ }
881
+ continue;
882
+ }
883
+ if (!ARTIFACT_IDENTITY_WRITE_TOOLS.has(result.tool)) continue;
884
+ const artifacts = collectArtifacts([result]);
885
+ for (const document of artifacts.documents) {
886
+ remember({
887
+ resourceType: "document",
888
+ id: document.id,
889
+ sourceAction: result.tool,
890
+ titleAtAction: document.title,
891
+ url: document.url,
892
+ });
893
+ }
894
+ for (const deck of artifacts.decks) {
895
+ remember({
896
+ resourceType: "deck",
897
+ id: deck.id,
898
+ sourceAction: result.tool,
899
+ url: deck.url,
900
+ });
901
+ }
902
+ for (const dashboard of artifacts.dashboards) {
903
+ remember({
904
+ resourceType: "dashboard",
905
+ id: dashboard.id,
906
+ sourceAction: result.tool,
907
+ titleAtAction: dashboard.title,
908
+ url: dashboard.url,
909
+ });
910
+ }
911
+ for (const analysis of artifacts.analyses) {
912
+ remember({
913
+ resourceType: "analysis",
914
+ id: analysis.id,
915
+ sourceAction: result.tool,
916
+ titleAtAction: analysis.title,
917
+ url: analysis.url,
918
+ });
919
+ }
920
+ for (const image of artifacts.images) {
921
+ remember({
922
+ resourceType: "image",
923
+ id: image.id,
924
+ sourceAction: result.tool,
925
+ titleAtAction: image.title,
926
+ url: image.url,
927
+ });
928
+ }
929
+ for (const design of artifacts.designShells) {
930
+ remember({
931
+ resourceType: "design",
932
+ id: design.id,
933
+ sourceAction: result.tool,
934
+ titleAtAction: design.title,
935
+ });
936
+ }
937
+ for (const design of artifacts.generatedDesigns) {
938
+ remember({
939
+ resourceType: "design",
940
+ id: design.id,
941
+ sourceAction: result.tool,
942
+ url: design.url,
943
+ });
944
+ }
945
+ for (const monitor of artifacts.monitors) {
946
+ remember({
947
+ resourceType: "monitor",
948
+ id: monitor.id,
949
+ sourceAction: result.tool,
950
+ titleAtAction: monitor.name,
951
+ url: monitor.url,
952
+ });
953
+ }
954
+ for (const form of artifacts.forms) {
955
+ remember({
956
+ resourceType: "form",
957
+ id: form.id,
958
+ sourceAction: result.tool,
959
+ titleAtAction: form.title,
960
+ url: form.url,
961
+ });
962
+ }
963
+ }
964
+
965
+ return [...identities.values()];
966
+ }
967
+
733
968
  type DownstreamArtifact =
734
969
  | { kind: "deck"; id: string; url: string }
735
970
  | { kind: "document"; id: string; url: string; title?: string }
@@ -1131,6 +1366,10 @@ export function appendA2AArtifactLinks(
1131
1366
  const baseUrl = normalizeBaseUrl(options.baseUrl);
1132
1367
  const includeReferencedArtifacts =
1133
1368
  options.includeReferencedArtifacts ?? false;
1369
+ const finalize = (value: string) =>
1370
+ options.includePersistedArtifactMarker
1371
+ ? withPersistedArtifactMarker(value, toolResults)
1372
+ : value;
1134
1373
  const {
1135
1374
  documents,
1136
1375
  decks,
@@ -1160,7 +1399,7 @@ export function appendA2AArtifactLinks(
1160
1399
  ) ||
1161
1400
  /\b(?:done|created|ready|here(?:'s| is)|complete|finished)\b/i.test(text))
1162
1401
  ) {
1163
- return formatIncompleteDesignMessage(incompleteShells);
1402
+ return finalize(formatIncompleteDesignMessage(incompleteShells));
1164
1403
  }
1165
1404
 
1166
1405
  const unverifiedRefs = findUnverifiedArtifactReferences(
@@ -1174,15 +1413,17 @@ export function appendA2AArtifactLinks(
1174
1413
  generatedDesigns,
1175
1414
  );
1176
1415
  if (unverifiedRefs.length > 0) {
1177
- return formatUnverifiedArtifactMessage(
1178
- unverifiedRefs,
1179
- documents,
1180
- decks,
1181
- dashboards,
1182
- analyses,
1183
- images,
1184
- generatedDesigns,
1185
- baseUrl,
1416
+ return finalize(
1417
+ formatUnverifiedArtifactMessage(
1418
+ unverifiedRefs,
1419
+ documents,
1420
+ decks,
1421
+ dashboards,
1422
+ analyses,
1423
+ images,
1424
+ generatedDesigns,
1425
+ baseUrl,
1426
+ ),
1186
1427
  );
1187
1428
  }
1188
1429
 
@@ -1258,9 +1499,11 @@ export function appendA2AArtifactLinks(
1258
1499
  }
1259
1500
  }
1260
1501
 
1261
- if (missingLines.length === 0) return text;
1502
+ if (missingLines.length === 0) {
1503
+ return finalize(text);
1504
+ }
1262
1505
  const artifactBlock = `Artifacts:\n${missingLines.join("\n")}`;
1263
- return text ? `${text}\n\n${artifactBlock}` : artifactBlock;
1506
+ return finalize(text ? `${text}\n\n${artifactBlock}` : artifactBlock);
1264
1507
  }
1265
1508
 
1266
1509
  export function buildA2ARecoverableArtifactMessage(
@@ -637,23 +637,96 @@ export function threadDataToEngineMessages(
637
637
  for (const entry of data.messages) {
638
638
  const m = entry?.message ?? entry;
639
639
  if (!m || (m.role !== "user" && m.role !== "assistant")) continue;
640
- const text =
641
- typeof m.content === "string"
642
- ? m.content
643
- : Array.isArray(m.content)
644
- ? m.content
645
- .filter(
646
- (c: any) => c?.type === "text" && typeof c.text === "string",
647
- )
648
- .map((c: any) => c.text)
649
- .join("\n")
650
- : "";
640
+ const text = threadMessageTextForEngine(m);
651
641
  if (!text.trim()) continue;
652
642
  messages.push({ role: m.role, content: [{ type: "text", text }] });
653
643
  }
654
644
  return messages;
655
645
  }
656
646
 
647
+ const MAX_INTEGRATION_ARTIFACTS_IN_CONTEXT = 12;
648
+ const MAX_INTEGRATION_ARTIFACT_FIELD_CHARS = 500;
649
+
650
+ function boundedString(value: unknown): string | undefined {
651
+ if (typeof value !== "string") return undefined;
652
+ const trimmed = value.trim();
653
+ return trimmed
654
+ ? trimmed.slice(0, MAX_INTEGRATION_ARTIFACT_FIELD_CHARS)
655
+ : undefined;
656
+ }
657
+
658
+ function promptSafeJson(value: unknown): string {
659
+ return JSON.stringify(value)
660
+ .replaceAll("&", "\\u0026")
661
+ .replaceAll("<", "\\u003c")
662
+ .replaceAll(">", "\\u003e");
663
+ }
664
+
665
+ function messageTextContent(message: any): string {
666
+ if (typeof message?.content === "string") return message.content;
667
+ if (!Array.isArray(message?.content)) return "";
668
+ return message.content
669
+ .filter(
670
+ (part: any) => part?.type === "text" && typeof part.text === "string",
671
+ )
672
+ .map((part: any) => part.text)
673
+ .join("\n");
674
+ }
675
+
676
+ /**
677
+ * Select the participant-visible delivery for integration turns while keeping
678
+ * a compact, trusted resource ledger available to the agent. Raw tool results
679
+ * remain in thread_data for UI/audit use but are not replayed into the prompt.
680
+ */
681
+ export function threadMessageTextForEngine(message: any): string {
682
+ const delivery = message?.metadata?.integrationDelivery;
683
+ const deliveryAttempted =
684
+ message?.metadata?.integrationDeliveryAttempted === true;
685
+ const deliveredText =
686
+ message?.role === "assistant" &&
687
+ delivery?.status === "delivered" &&
688
+ typeof delivery.text === "string" &&
689
+ delivery.text.trim()
690
+ ? delivery.text
691
+ : undefined;
692
+ let text =
693
+ deliveredText ??
694
+ (message?.role === "assistant" && deliveryAttempted
695
+ ? ""
696
+ : messageTextContent(message));
697
+
698
+ if (message?.role !== "assistant") return text;
699
+ const storedArtifacts = message?.metadata?.integrationArtifacts;
700
+ if (!Array.isArray(storedArtifacts)) return text;
701
+
702
+ const artifacts = storedArtifacts
703
+ .slice(0, MAX_INTEGRATION_ARTIFACTS_IN_CONTEXT)
704
+ .map((artifact: any) => ({
705
+ resourceType: boundedString(artifact?.resourceType),
706
+ id: boundedString(artifact?.id),
707
+ sourceAction: boundedString(artifact?.sourceAction),
708
+ titleAtAction: boundedString(artifact?.titleAtAction),
709
+ url: boundedString(artifact?.url),
710
+ }))
711
+ .filter(
712
+ (artifact: {
713
+ resourceType?: string;
714
+ id?: string;
715
+ sourceAction?: string;
716
+ }) => artifact.resourceType && artifact.id && artifact.sourceAction,
717
+ );
718
+ if (artifacts.length === 0) return text;
719
+
720
+ const context = [
721
+ "<integration_artifact_context>",
722
+ "Trusted action history for this conversation. Resource IDs remain stable if participants rename the resource. Use these IDs when a follow-up refers to an earlier artifact, while still deciding from the request whether to update, add, supersede, or create.",
723
+ promptSafeJson(artifacts),
724
+ "</integration_artifact_context>",
725
+ ].join("\n");
726
+ text = text.trim() ? `${text.trim()}\n\n${context}` : context;
727
+ return text;
728
+ }
729
+
657
730
  export interface CodeAgentThreadTranscriptEvent {
658
731
  id: string;
659
732
  runId: string;
@@ -1,7 +1,7 @@
1
1
  import { Button } from "@agent-native/toolkit/ui/button";
2
2
  import { Spinner } from "@agent-native/toolkit/ui/spinner";
3
3
  import { Textarea } from "@agent-native/toolkit/ui/textarea";
4
- import { IconMessageCircle, IconSend } from "@tabler/icons-react";
4
+ import { IconFocus2, IconMessageCircle, IconSend } from "@tabler/icons-react";
5
5
 
6
6
  import type { ReviewResolutionTarget } from "../../review/types.js";
7
7
  import { cn } from "../utils.js";
@@ -16,6 +16,7 @@ export interface ReviewCommentComposerProps {
16
16
  placeholder?: string;
17
17
  commentLabel?: string;
18
18
  agentLabel?: string;
19
+ contextLabel?: string;
19
20
  autoFocus?: boolean;
20
21
  submitOnEnter?: boolean;
21
22
  onEscape?: () => void;
@@ -32,6 +33,7 @@ export function ReviewCommentComposer({
32
33
  placeholder = "Add a comment...",
33
34
  commentLabel = "Comment",
34
35
  agentLabel = "Send to agent",
36
+ contextLabel,
35
37
  autoFocus = false,
36
38
  submitOnEnter = false,
37
39
  onEscape,
@@ -51,6 +53,12 @@ export function ReviewCommentComposer({
51
53
  submit("human");
52
54
  }}
53
55
  >
56
+ {contextLabel ? (
57
+ <div className="mb-2 flex min-w-0 items-center gap-1.5 text-xs text-muted-foreground">
58
+ <IconFocus2 className="size-3.5 shrink-0" />
59
+ <span className="truncate">{contextLabel}</span>
60
+ </div>
61
+ ) : null}
54
62
  <Textarea
55
63
  autoFocus={autoFocus}
56
64
  value={value}
@@ -52,6 +52,14 @@ export interface ReviewThreadPanelProps {
52
52
  resourceType: string;
53
53
  resourceId: string;
54
54
  targetId?: string | null;
55
+ /** Persist new comments against this target while targetId continues to filter the list. */
56
+ composerTargetId?: string | null;
57
+ /** Optional element/point anchor attached to new comments from the composer. */
58
+ composerAnchor?: unknown | null;
59
+ /** Host metadata attached to new comments from the composer. */
60
+ composerMetadata?: Record<string, unknown>;
61
+ /** Visible label describing the element currently targeted by the composer. */
62
+ composerContextLabel?: string;
55
63
  title?: string;
56
64
  className?: string;
57
65
  includeResolved?: boolean;
@@ -89,6 +97,10 @@ export function ReviewThreadPanel({
89
97
  resourceType,
90
98
  resourceId,
91
99
  targetId,
100
+ composerTargetId,
101
+ composerAnchor,
102
+ composerMetadata,
103
+ composerContextLabel,
92
104
  title = "Review",
93
105
  className,
94
106
  includeResolved = true,
@@ -145,9 +157,11 @@ export function ReviewThreadPanel({
145
157
  {
146
158
  resourceType,
147
159
  resourceId,
148
- targetId,
160
+ targetId: composerTargetId === undefined ? targetId : composerTargetId,
161
+ ...(composerAnchor !== undefined ? { anchor: composerAnchor } : {}),
162
+ ...(composerMetadata ? { metadata: composerMetadata } : {}),
149
163
  body,
150
- ...(showComposerTargetPicker ? { resolutionTarget } : {}),
164
+ resolutionTarget: showComposerTargetPicker ? resolutionTarget : "human",
151
165
  },
152
166
  {
153
167
  onSuccess: (comment) => {
@@ -194,6 +208,7 @@ export function ReviewThreadPanel({
194
208
  placeholder={placeholder}
195
209
  commentLabel={composerCommentLabel}
196
210
  agentLabel={composerAgentLabel}
211
+ contextLabel={composerContextLabel}
197
212
  />
198
213
  ) : null}
199
214
 
@@ -45,6 +45,7 @@ import {
45
45
  TooltipTrigger,
46
46
  } from "../components/ui/tooltip.js";
47
47
  import { TeamPage } from "../org/TeamPage.js";
48
+ import { BuilderConnectCard } from "../setup-connections/BuilderConnectCard.js";
48
49
  import { callAction } from "../use-action.js";
49
50
  import { uploadAvatar, useAvatarUrl } from "../use-avatar.js";
50
51
  import { useDevMode } from "../use-dev-mode.js";
@@ -2578,6 +2579,7 @@ interface SettingsPanelContentProps extends SettingsPanelProps {
2578
2579
  showCapabilityStrip?: boolean;
2579
2580
  className?: string;
2580
2581
  surface?: SettingsSurface;
2582
+ builderConnectionOwnedExternally?: boolean;
2581
2583
  }
2582
2584
 
2583
2585
  function SettingsPanelContent({
@@ -2591,8 +2593,11 @@ function SettingsPanelContent({
2591
2593
  showCapabilityStrip = true,
2592
2594
  className,
2593
2595
  surface = "sidebar",
2596
+ builderConnectionOwnedExternally = false,
2594
2597
  }: SettingsPanelContentProps) {
2595
- const { status: builder, loading: builderLoading } = useBuilderStatus();
2598
+ const { status: builder, loading: builderLoading } = useBuilderStatus({
2599
+ enabled: !builderConnectionOwnedExternally,
2600
+ });
2596
2601
  const connected = builder?.configured ?? false;
2597
2602
  const connectUrl = builder?.cliAuthUrl ?? builder?.connectUrl;
2598
2603
  const orgName = builder?.orgName;
@@ -2600,6 +2605,7 @@ function SettingsPanelContent({
2600
2605
  const credentialSource = builder?.credentialSource;
2601
2606
  const builderBranchesAvailable = !!builder?.builderEnabled;
2602
2607
  const builderFlow = useBuilderConnectFlow({
2608
+ enabled: !builderConnectionOwnedExternally,
2603
2609
  popupUrl: connectUrl,
2604
2610
  trackingSource: "settings_panel_builder_card",
2605
2611
  });
@@ -2965,20 +2971,22 @@ function SettingsPanelContent({
2965
2971
  icon={<IconBrowser size={14} />}
2966
2972
  title="Browser Automation"
2967
2973
  subtitle="Let agents control a real browser for web tasks."
2968
- connected={connected}
2974
+ connected={builderConnectionOwnedExternally ? undefined : connected}
2969
2975
  open={openSection === "browser"}
2970
2976
  onToggle={() => toggle("browser")}
2971
2977
  >
2972
- <UseBuilderCard
2973
- builderFlow={builderFlow}
2974
- connectUrl={connectUrl}
2975
- connected={connected}
2976
- orgName={orgName}
2977
- envManaged={envManaged}
2978
- credentialSource={credentialSource}
2979
- trackingSource="browser_settings"
2980
- trackingFlow="browser_automation"
2981
- />
2978
+ {!builderConnectionOwnedExternally ? (
2979
+ <UseBuilderCard
2980
+ builderFlow={builderFlow}
2981
+ connectUrl={connectUrl}
2982
+ connected={connected}
2983
+ orgName={orgName}
2984
+ envManaged={envManaged}
2985
+ credentialSource={credentialSource}
2986
+ trackingSource="browser_settings"
2987
+ trackingFlow="browser_automation"
2988
+ />
2989
+ ) : null}
2982
2990
  </SettingsSection>
2983
2991
  )}
2984
2992
 
@@ -3057,6 +3065,26 @@ export function SettingsPanel(props: SettingsPanelProps) {
3057
3065
  return <SettingsPanelContent {...props} />;
3058
3066
  }
3059
3067
 
3068
+ export function ConnectionsSettingsContent({
3069
+ settingsPanelProps,
3070
+ }: {
3071
+ settingsPanelProps: SettingsPanelProps;
3072
+ }) {
3073
+ return (
3074
+ <div className="mx-auto w-full max-w-2xl space-y-4">
3075
+ <BuilderConnectCard trackingSource="settings_connections" />
3076
+ <SettingsPanelContent
3077
+ {...settingsPanelProps}
3078
+ surface="page"
3079
+ sections={CONNECTION_SETTINGS_SECTIONS}
3080
+ showCapabilityStrip={false}
3081
+ className="w-full"
3082
+ builderConnectionOwnedExternally
3083
+ />
3084
+ </div>
3085
+ );
3086
+ }
3087
+
3060
3088
  export function useAgentSettingsTabs(): SettingsTabItem[] {
3061
3089
  const { isDevMode, canToggle, setDevMode } = useDevMode();
3062
3090
  const baseProps = useMemo<SettingsPanelProps>(
@@ -3102,15 +3130,7 @@ export function useAgentSettingsTabs(): SettingsTabItem[] {
3102
3130
  ...connections,
3103
3131
  icon: IconPlugConnected,
3104
3132
  group: "agent",
3105
- content: (
3106
- <SettingsPanelContent
3107
- {...baseProps}
3108
- surface="page"
3109
- sections={CONNECTION_SETTINGS_SECTIONS}
3110
- showCapabilityStrip={false}
3111
- className="mx-auto w-full max-w-2xl"
3112
- />
3113
- ),
3133
+ content: <ConnectionsSettingsContent settingsPanelProps={baseProps} />,
3114
3134
  },
3115
3135
  {
3116
3136
  ...organization,