@agent-native/core 0.165.3 → 0.167.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 (249) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +5 -1
  3. package/corpus/templates/analytics/.agents/skills/workspace-conventions/SKILL.md +4 -1
  4. package/corpus/templates/analytics/CHANGELOG.md +740 -2
  5. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +93 -56
  6. package/corpus/templates/analytics/app/i18n-data.ts +23 -20
  7. package/corpus/templates/analytics/app/pages/Settings.tsx +0 -1
  8. package/corpus/templates/analytics/app/pages/adhoc/explorer/index.tsx +0 -1
  9. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +1 -1
  10. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +2 -1
  11. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +0 -1
  12. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +0 -32
  13. package/corpus/templates/analytics/server/lib/session-replay.ts +1 -5
  14. package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +5 -1
  15. package/corpus/templates/assets/.agents/skills/workspace-conventions/SKILL.md +4 -1
  16. package/corpus/templates/assets/CHANGELOG.md +204 -2
  17. package/corpus/templates/assets/actions/navigate.ts +2 -2
  18. package/corpus/templates/assets/actions/save-generated-image.ts +0 -5
  19. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +2 -262
  20. package/corpus/templates/assets/app/routes/library.tsx +1 -1
  21. package/corpus/templates/assets/app/routes/settings.tsx +0 -3
  22. package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +5 -1
  23. package/corpus/templates/brain/.agents/skills/workspace-conventions/SKILL.md +4 -1
  24. package/corpus/templates/brain/CHANGELOG.md +145 -2
  25. package/corpus/templates/brain/actions/ask-brain.ts +0 -1
  26. package/corpus/templates/brain/actions/navigate.ts +2 -2
  27. package/corpus/templates/brain/app/routes/sources.tsx +0 -4
  28. package/corpus/templates/brain/server/lib/capture-sanitization.ts +0 -11
  29. package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +5 -1
  30. package/corpus/templates/calendar/.agents/skills/workspace-conventions/SKILL.md +4 -1
  31. package/corpus/templates/calendar/CHANGELOG.md +272 -2
  32. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +0 -20
  33. package/corpus/templates/calendar/app/pages/CalendarView.tsx +0 -1
  34. package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +5 -1
  35. package/corpus/templates/chat/.agents/skills/workspace-conventions/SKILL.md +4 -1
  36. package/corpus/templates/chat/CHANGELOG.md +89 -2
  37. package/corpus/templates/chat/actions/navigate.ts +2 -2
  38. package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +5 -1
  39. package/corpus/templates/clips/.agents/skills/workspace-conventions/SKILL.md +4 -1
  40. package/corpus/templates/clips/CHANGELOG.md +865 -2
  41. package/corpus/templates/clips/actions/import-loom-recording.ts +16 -4
  42. package/corpus/templates/clips/actions/navigate.ts +2 -2
  43. package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +0 -1
  44. package/corpus/templates/clips/app/components/library/space-dialogs.tsx +0 -1
  45. package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +0 -1
  46. package/corpus/templates/clips/app/components/player/clips-share-trigger.tsx +17 -0
  47. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +3 -3
  48. package/corpus/templates/clips/app/components/player/video-player.tsx +2 -2
  49. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +0 -1
  50. package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +0 -1
  51. package/corpus/templates/clips/app/global.css +31 -0
  52. package/corpus/templates/clips/app/hooks/use-playback-position.ts +0 -2
  53. package/corpus/templates/clips/app/lib/download-release-channel.ts +10 -0
  54. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +1 -3
  55. package/corpus/templates/clips/app/routes/download.tsx +67 -44
  56. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +7 -12
  57. package/corpus/templates/clips/app/routes/record.tsx +6 -6
  58. package/corpus/templates/clips/app/routes/share.$shareId.tsx +26 -29
  59. package/corpus/templates/clips/changelog/2026-08-20-clip-viewer-share-actions.md +6 -0
  60. package/corpus/templates/clips/changelog/2026-08-20-preparing-recording-countdown-overlay.md +6 -0
  61. package/corpus/templates/clips/chrome-extension/src/background.ts +0 -13
  62. package/corpus/templates/clips/chrome-extension/src/overlay.ts +0 -1
  63. package/corpus/templates/clips/chrome-extension/src/popup.ts +0 -20
  64. package/corpus/templates/clips/desktop/src/app.tsx +6 -18
  65. package/corpus/templates/clips/desktop/src/hooks/useMediaDevices.ts +0 -1
  66. package/corpus/templates/clips/desktop/src/lib/recorder.ts +0 -8
  67. package/corpus/templates/clips/desktop/src/overlays/preparing.tsx +4 -6
  68. package/corpus/templates/clips/desktop/src/styles.css +18 -20
  69. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +9 -17
  70. package/corpus/templates/content/.agents/skills/secrets/SKILL.md +5 -1
  71. package/corpus/templates/content/.agents/skills/workspace-conventions/SKILL.md +4 -1
  72. package/corpus/templates/content/CHANGELOG.md +503 -2
  73. package/corpus/templates/content/actions/_database-source-utils.ts +0 -3
  74. package/corpus/templates/content/actions/attach-content-database-source.ts +1 -4
  75. package/corpus/templates/content/actions/navigate.ts +2 -2
  76. package/corpus/templates/content/actions/prepare-builder-source-execution.ts +1 -1
  77. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +0 -6
  78. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +0 -580
  79. package/corpus/templates/content/app/components/editor/database/FormView.tsx +2 -2
  80. package/corpus/templates/content/app/components/editor/database/filter-sort.ts +1 -1
  81. package/corpus/templates/content/app/components/editor/database/settings.tsx +0 -23
  82. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +0 -1
  83. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +8 -304
  84. package/corpus/templates/content/app/hooks/use-documents.ts +0 -1
  85. package/corpus/templates/content/shared/api.ts +0 -1
  86. package/corpus/templates/content/shared/builder-mdx.ts +0 -1
  87. package/corpus/templates/content/shared/nfm.ts +1 -7
  88. package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +5 -1
  89. package/corpus/templates/crm/.agents/skills/workspace-conventions/SKILL.md +4 -1
  90. package/corpus/templates/crm/CHANGELOG.md +31 -2
  91. package/corpus/templates/crm/actions/merge-crm-records.ts +0 -4
  92. package/corpus/templates/crm/app/components/crm/record/RecordLists.tsx +0 -1
  93. package/corpus/templates/crm/server/crm/hubspot-adapter.ts +0 -1
  94. package/corpus/templates/crm/server/crm/salesforce-adapter.ts +0 -1
  95. package/corpus/templates/crm/server/db/crm-store.ts +1 -1
  96. package/corpus/templates/design/.agents/skills/secrets/SKILL.md +5 -1
  97. package/corpus/templates/design/.agents/skills/workspace-conventions/SKILL.md +4 -1
  98. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1 -14
  99. package/corpus/templates/design/AGENTS.md +2 -1
  100. package/corpus/templates/design/CHANGELOG.md +870 -2
  101. package/corpus/templates/design/actions/apply-component-prop-edit.ts +1 -5
  102. package/corpus/templates/design/actions/generate-design.ts +0 -1
  103. package/corpus/templates/design/actions/generate-screens.ts +5 -2
  104. package/corpus/templates/design/actions/go-to-main-component.ts +2 -2
  105. package/corpus/templates/design/actions/list-design-systems.ts +10 -0
  106. package/corpus/templates/design/actions/navigate.ts +2 -2
  107. package/corpus/templates/design/actions/open-component-source.ts +4 -4
  108. package/corpus/templates/design/actions/present-design-variants.ts +1 -2
  109. package/corpus/templates/design/actions/run-design-audit.ts +0 -22
  110. package/corpus/templates/design/actions/show-design-questions.ts +5 -2
  111. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +19 -8
  112. package/corpus/templates/design/app/components/design/EditPanel.tsx +11 -183
  113. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +21 -4
  114. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +1 -5
  115. package/corpus/templates/design/app/components/design/bridge/codegen.ts +1 -1
  116. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +10 -19
  117. package/corpus/templates/design/app/components/design/edit-panel/appearance-properties.tsx +1 -1
  118. package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +13 -3
  119. package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +38 -32
  120. package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +1 -4
  121. package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +0 -4
  122. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +15 -6
  123. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +2 -2
  124. package/corpus/templates/design/app/components/visual-editor/NodeRewriteProposal.tsx +0 -1
  125. package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +1 -1
  126. package/corpus/templates/design/app/i18n-data.ts +122 -0
  127. package/corpus/templates/design/app/lib/clipboard-content-lineage.ts +11 -1
  128. package/corpus/templates/design/app/pages/DesignEditor.tsx +50 -254
  129. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +163 -8
  130. package/corpus/templates/design/app/pages/Index.tsx +17 -0
  131. package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +44 -32
  132. package/corpus/templates/design/app/pages/design-editor/canvas-primitives.ts +10 -0
  133. package/corpus/templates/design/app/pages/design-editor/clone-and-pen-edit.ts +49 -3
  134. package/corpus/templates/design/app/pages/design-editor/clone-idrefs.ts +31 -0
  135. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +28 -0
  136. package/corpus/templates/design/app/pages/design-editor/commands/add-auto-layout.ts +3 -3
  137. package/corpus/templates/design/app/pages/design-editor/commands/align-selection.ts +44 -14
  138. package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +16 -5
  139. package/corpus/templates/design/app/pages/design-editor/commands/change-selected-z-index.ts +1 -1
  140. package/corpus/templates/design/app/pages/design-editor/commands/frame-selection.ts +1 -1
  141. package/corpus/templates/design/app/pages/design-editor/commands/group-selection.ts +1 -1
  142. package/corpus/templates/design/app/pages/design-editor/commands/nudge-selection.ts +1 -1
  143. package/corpus/templates/design/app/pages/design-editor/commands/paste-selection.ts +142 -17
  144. package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-duplicate-change.ts +1 -0
  145. package/corpus/templates/design/app/pages/design-editor/commands/ungroup-selection.ts +1 -1
  146. package/corpus/templates/design/app/pages/design-editor/commands/visual-duplicate-change.ts +1 -0
  147. package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +25 -9
  148. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +1 -0
  149. package/corpus/templates/design/app/pages/design-editor/measure-child-rects.ts +83 -0
  150. package/corpus/templates/design/app/pages/design-editor/paste-placement.ts +66 -0
  151. package/corpus/templates/design/server/routes/[...page].get.ts +0 -1
  152. package/corpus/templates/design/shared/code-layer.ts +120 -70
  153. package/corpus/templates/design/shared/design-surface-index.ts +0 -1
  154. package/corpus/templates/design/shared/pen-path.ts +0 -4
  155. package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +5 -1
  156. package/corpus/templates/dispatch/.agents/skills/workspace-conventions/SKILL.md +4 -1
  157. package/corpus/templates/dispatch/CHANGELOG.md +196 -2
  158. package/corpus/templates/dispatch/app/routes/integrations.tsx +0 -109
  159. package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +5 -1
  160. package/corpus/templates/factory/.agents/skills/workspace-conventions/SKILL.md +4 -1
  161. package/corpus/templates/factory/CHANGELOG.md +121 -2
  162. package/corpus/templates/factory/actions/navigate.ts +2 -2
  163. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +0 -13
  164. package/corpus/templates/factory/app/routes/factory.tsx +0 -1
  165. package/corpus/templates/factory/server/factory-graph/store.ts +0 -1
  166. package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +5 -1
  167. package/corpus/templates/forms/.agents/skills/workspace-conventions/SKILL.md +4 -1
  168. package/corpus/templates/forms/CHANGELOG.md +166 -2
  169. package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +5 -1
  170. package/corpus/templates/macros/.agents/skills/workspace-conventions/SKILL.md +4 -1
  171. package/corpus/templates/macros/CHANGELOG.md +49 -2
  172. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +0 -1
  173. package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +5 -1
  174. package/corpus/templates/mail/.agents/skills/workspace-conventions/SKILL.md +4 -1
  175. package/corpus/templates/mail/CHANGELOG.md +201 -2
  176. package/corpus/templates/mail/app/components/email/EmailList.tsx +0 -1
  177. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +2 -2
  178. package/corpus/templates/mail/shared/markdown.ts +3 -0
  179. package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +5 -1
  180. package/corpus/templates/plan/.agents/skills/workspace-conventions/SKILL.md +4 -1
  181. package/corpus/templates/plan/CHANGELOG.md +277 -2
  182. package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +5 -1
  183. package/corpus/templates/slides/.agents/skills/workspace-conventions/SKILL.md +4 -1
  184. package/corpus/templates/slides/CHANGELOG.md +437 -2
  185. package/corpus/templates/slides/actions/add-slide.ts +0 -1
  186. package/corpus/templates/slides/actions/list-decks.ts +1 -1
  187. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +1 -4
  188. package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +0 -1
  189. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +1 -1
  190. package/corpus/templates/slides/app/pages/DeckEditor.tsx +1 -6
  191. package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +5 -1
  192. package/corpus/templates/tasks/.agents/skills/workspace-conventions/SKILL.md +4 -1
  193. package/corpus/templates/tasks/CHANGELOG.md +32 -2
  194. package/corpus/templates/tasks/app/components/layout/Layout.tsx +0 -1
  195. package/corpus/templates/tasks/app/hooks/use-visible-task-fields.ts +1 -4
  196. package/corpus/templates/tasks/server/custom-fields/store.ts +1 -6
  197. package/corpus/templates/tasks/shared/list-screen-snapshot.ts +2 -2
  198. package/dist/agent/engine/registry.js +27 -14
  199. package/dist/agent/index.d.ts +1 -1
  200. package/dist/agent/production-agent.d.ts +19 -6
  201. package/dist/agent/production-agent.js +57 -16
  202. package/dist/agent/types.d.ts +3 -0
  203. package/dist/changelog/parse.d.ts +3 -3
  204. package/dist/changelog/parse.js +35 -16
  205. package/dist/client/EnvironmentBadge.d.ts +1 -0
  206. package/dist/client/EnvironmentBadge.js +7 -0
  207. package/dist/collab/awareness.d.ts +2 -2
  208. package/dist/collab/routes.d.ts +1 -1
  209. package/dist/collab/struct-routes.d.ts +1 -1
  210. package/dist/config.d.ts +11 -0
  211. package/dist/config.js +248 -0
  212. package/dist/deploy/build.js +12 -1
  213. package/dist/index.d.ts +1 -1
  214. package/dist/notifications/routes.d.ts +3 -3
  215. package/dist/observability/routes.d.ts +6 -6
  216. package/dist/resources/handlers.d.ts +2 -2
  217. package/dist/secrets/routes.d.ts +9 -9
  218. package/dist/server/agent-chat/plugin-options.d.ts +3 -2
  219. package/dist/server/agent-chat-plugin.js +5 -2
  220. package/dist/server/index.d.ts +1 -1
  221. package/dist/server/realtime-token.d.ts +1 -1
  222. package/dist/server/transcribe-voice.d.ts +1 -1
  223. package/dist/templates/chat/.agents/skills/secrets/SKILL.md +5 -1
  224. package/dist/templates/chat/.agents/skills/workspace-conventions/SKILL.md +4 -1
  225. package/dist/templates/chat/CHANGELOG.md +89 -2
  226. package/dist/templates/chat/actions/navigate.ts +2 -2
  227. package/dist/templates/default/.agents/skills/secrets/SKILL.md +5 -1
  228. package/dist/templates/default/.agents/skills/workspace-conventions/SKILL.md +4 -1
  229. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +5 -1
  230. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +5 -1
  231. package/dist/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +4 -1
  232. package/dist/vite/agent-native-config-loader.d.ts +1 -0
  233. package/dist/vite/agent-native-config-loader.js +3 -3
  234. package/dist/vite/agents-bundle-plugin.d.ts +1 -1
  235. package/dist/vite/agents-bundle-plugin.js +13 -1
  236. package/dist/vite/client.js +14 -14
  237. package/docs/content/agent-native-config.mdx +62 -11
  238. package/docs/content/agent-surfaces.mdx +6 -0
  239. package/docs/content/environment-variables.mdx +5 -2
  240. package/package.json +3 -3
  241. package/src/templates/chat/.agents/skills/secrets/SKILL.md +5 -1
  242. package/src/templates/chat/.agents/skills/workspace-conventions/SKILL.md +4 -1
  243. package/src/templates/chat/CHANGELOG.md +89 -2
  244. package/src/templates/chat/actions/navigate.ts +2 -2
  245. package/src/templates/default/.agents/skills/secrets/SKILL.md +5 -1
  246. package/src/templates/default/.agents/skills/workspace-conventions/SKILL.md +4 -1
  247. package/src/templates/headless/.agents/skills/secrets/SKILL.md +5 -1
  248. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +5 -1
  249. package/src/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +4 -1
@@ -0,0 +1,83 @@
1
+ export interface FreeformGeometry {
2
+ container: { width: number; height: number } | null;
3
+ children: Record<
4
+ string,
5
+ { x: number; y: number; width: number; height: number }
6
+ >;
7
+ }
8
+
9
+ const NOTHING_MEASURED: FreeformGeometry = { container: null, children: {} };
10
+
11
+ /**
12
+ * Container-relative geometry for a node and its direct children, read from
13
+ * whichever preview iframe actually holds the node — the board and each screen
14
+ * have their own document, so a single global iframe lookup finds the wrong one.
15
+ */
16
+ export function measureFreeformGeometry(nodeId: string): FreeformGeometry {
17
+ if (typeof document === "undefined") return NOTHING_MEASURED;
18
+ const selector = `[data-agent-native-node-id="${CSS.escape(nodeId)}"]`;
19
+ const iframes = Array.from(
20
+ document.querySelectorAll<HTMLIFrameElement>(
21
+ "iframe[data-design-preview-iframe],iframe[data-screen-iframe-id]",
22
+ ),
23
+ );
24
+ for (const iframe of iframes) {
25
+ let container: HTMLElement | null = null;
26
+ try {
27
+ container =
28
+ iframe.contentDocument?.querySelector<HTMLElement>(selector) ?? null;
29
+ } catch {
30
+ // Cross-origin preview surfaces are not measurable; try the next one.
31
+ continue;
32
+ }
33
+ if (!container) continue;
34
+ const view = container.ownerDocument.defaultView;
35
+ const origin = container.getBoundingClientRect();
36
+ // Absolute offsets resolve against the padding box, but a client rect is
37
+ // the border box, so a bordered container shifts every child it pins.
38
+ const borders = view?.getComputedStyle(container);
39
+ // Client rects are viewport-relative, so a scrolled container reports its
40
+ // children where they currently sit, not where the content box holds them.
41
+ const originLeft =
42
+ origin.left + edgeWidth(borders?.borderLeftWidth) - container.scrollLeft;
43
+ const originTop =
44
+ origin.top + edgeWidth(borders?.borderTopWidth) - container.scrollTop;
45
+ const rects: Record<
46
+ string,
47
+ { x: number; y: number; width: number; height: number }
48
+ > = {};
49
+ for (const child of Array.from(container.children)) {
50
+ const childId = child.getAttribute("data-agent-native-node-id");
51
+ if (!childId) continue;
52
+ const rect = child.getBoundingClientRect();
53
+ rects[childId] = {
54
+ x: rect.left - originLeft,
55
+ y: rect.top - originTop,
56
+ width: rect.width,
57
+ height: rect.height,
58
+ };
59
+ }
60
+ // Own box, in the same box-sizing terms as a width/height declaration on
61
+ // this element, so writing it back reproduces the rendered size.
62
+ const own = borders
63
+ ? {
64
+ width: Number.parseFloat(borders.width),
65
+ height: Number.parseFloat(borders.height),
66
+ }
67
+ : null;
68
+ return {
69
+ container:
70
+ own && Number.isFinite(own.width) && Number.isFinite(own.height)
71
+ ? own
72
+ : null,
73
+ children: rects,
74
+ };
75
+ }
76
+ return NOTHING_MEASURED;
77
+ }
78
+
79
+ function edgeWidth(value: string | undefined): number {
80
+ const parsed = Number.parseFloat(value ?? "");
81
+ // A missing or non-length border computes to no edge; both mean zero inset.
82
+ return Number.isFinite(parsed) ? parsed : 0;
83
+ }
@@ -131,3 +131,69 @@ export function resolvePastePlacementForSelection(args: {
131
131
  if (!node) return null;
132
132
  return resolvePastePlacement(pasteTargetFromCodeLayerNode(node));
133
133
  }
134
+
135
+ export interface PasteSourceAnchor {
136
+ fileId: string;
137
+ /**
138
+ * null when the entries do not share one resolvable parent. Never an empty
139
+ * array — a caller must not read "unresolved" as "insert at the root here",
140
+ * because the stored left/top are relative to a parent that is not there.
141
+ */
142
+ parentSelectors: string[] | null;
143
+ }
144
+
145
+ /**
146
+ * A copied layer's left/top are parent-relative, so a paste that lands
147
+ * anywhere else reads them in the wrong coordinate space. Null means the
148
+ * source is unknown — never "the document root".
149
+ */
150
+ export function resolvePasteSourceAnchor(args: {
151
+ entries: ReadonlyArray<{ rootNodeId?: string; sourceFileId: string }>;
152
+ getContent: (fileId: string) => string | undefined;
153
+ }): PasteSourceAnchor | null {
154
+ const first = args.entries[0];
155
+ if (!first) return null;
156
+ if (args.entries.some((entry) => entry.sourceFileId !== first.sourceFileId)) {
157
+ return null;
158
+ }
159
+ const content = args.getContent(first.sourceFileId);
160
+ if (!content) return null;
161
+ const projection = buildCodeLayerProjection(content);
162
+ const unresolved: PasteSourceAnchor = {
163
+ fileId: first.sourceFileId,
164
+ parentSelectors: null,
165
+ };
166
+ const parentIds = args.entries.map((entry) => {
167
+ const node = entry.rootNodeId
168
+ ? projection.nodes.find(
169
+ (candidate) =>
170
+ candidate.dataAttributes["data-agent-native-node-id"] ===
171
+ entry.rootNodeId || candidate.id === entry.rootNodeId,
172
+ )
173
+ : undefined;
174
+ return node?.parentId ?? null;
175
+ });
176
+ const [sharedParentId] = parentIds;
177
+ // Layers copied out of different parents have no common coordinate space, so
178
+ // forcing them into the first one's parent moves the rest.
179
+ if (!sharedParentId || parentIds.some((id) => id !== sharedParentId)) {
180
+ return unresolved;
181
+ }
182
+ const parent = projection.nodes.find(
183
+ (candidate) => candidate.id === sharedParentId,
184
+ );
185
+ if (!parent) return unresolved;
186
+ const parentNodeId = parent.dataAttributes["data-agent-native-node-id"];
187
+ const parentSelectors = [
188
+ // A node-id selector is unique by construction; the projection's
189
+ // class/path aliases can match several siblings, and
190
+ // insertClonedHtmlLayers fails closed on that ambiguity.
191
+ parentNodeId
192
+ ? `[data-agent-native-node-id="${parentNodeId.replace(/["\\]/g, "\\$&")}"]`
193
+ : null,
194
+ parent.selector,
195
+ ...parent.selectors,
196
+ ].filter((selector): selector is string => Boolean(selector));
197
+ if (parentSelectors.length === 0) return unresolved;
198
+ return { fileId: first.sourceFileId, parentSelectors };
199
+ }
@@ -10,7 +10,6 @@ import {
10
10
  } from "@agent-native/core/shared";
11
11
  import {
12
12
  defineEventHandler,
13
- getHeader,
14
13
  getQuery,
15
14
  getRequestURL,
16
15
  setResponseHeader,
@@ -498,6 +498,17 @@ export interface AutoLayoutEditIntent {
498
498
  enabled: boolean;
499
499
  direction?: "row" | "column";
500
500
  gap?: string;
501
+ /**
502
+ * Measured child geometry, container-relative, keyed by stable node id.
503
+ * Supplied when disabling so children keep their rendered positions and
504
+ * become freely draggable; without it they re-stack in block flow.
505
+ */
506
+ childRects?: Record<
507
+ string,
508
+ { x: number; y: number; width: number; height: number }
509
+ >;
510
+ /** Rendered size of the container, so it cannot collapse once flow empties. */
511
+ containerRect?: { width: number; height: number };
501
512
  }
502
513
 
503
514
  /**
@@ -950,17 +961,6 @@ function cssIdent(value: string): string | null {
950
961
  return null;
951
962
  }
952
963
 
953
- function unquoteHtmlAttributeValue(value: string): string {
954
- const trimmed = value.trim();
955
- if (
956
- (trimmed.startsWith('"') && trimmed.endsWith('"')) ||
957
- (trimmed.startsWith("'") && trimmed.endsWith("'"))
958
- ) {
959
- return trimmed.slice(1, -1);
960
- }
961
- return trimmed;
962
- }
963
-
964
964
  function escapeHtmlAttribute(value: string): string {
965
965
  return value
966
966
  .replace(/&/g, "&amp;")
@@ -1777,18 +1777,6 @@ function utilityToStyleProperty(
1777
1777
  return null;
1778
1778
  }
1779
1779
 
1780
- function classStyleToken(token: string): StyleToken | null {
1781
- const { utility } = parseClassToken(token);
1782
- const mapped = utilityToStyleProperty(utility);
1783
- if (!mapped) return null;
1784
- const { property, confidence } = mapped;
1785
- // The legacy value field preserves the original full token (including prefix)
1786
- // for backward compatibility. The responsive path uses `breakpointValues`.
1787
- const value =
1788
- property === "display" ? (utility === "hidden" ? "none" : utility) : token;
1789
- return { property, value, token, source: "class", confidence };
1790
- }
1791
-
1792
1780
  function layoutFor(
1793
1781
  element: ParsedElement,
1794
1782
  parent: ParsedElement | undefined,
@@ -3385,43 +3373,6 @@ const FLEX_ITEM_STRIP_PROPS = [
3385
3373
  "order",
3386
3374
  ] as const;
3387
3375
 
3388
- /**
3389
- * Apply display:flex + direction + gap to a raw open-tag string and return it.
3390
- * Only touches the style attribute.
3391
- */
3392
- function addAutoLayoutStyleToOpenTag(
3393
- openTag: string,
3394
- element: ParsedElement,
3395
- html: string,
3396
- direction: "row" | "column",
3397
- gap: string,
3398
- ): string {
3399
- const currentStyle = attributeValue(element, "style");
3400
- let declarations = parseStyleDeclarations(currentStyle);
3401
- const setOrReplace = (prop: string, val: string) => {
3402
- const existing = declarations.find((d) => d.property === prop);
3403
- if (existing) {
3404
- existing.value = val;
3405
- } else {
3406
- declarations.push({ property: prop, value: val });
3407
- }
3408
- };
3409
- setOrReplace("display", "flex");
3410
- setOrReplace("flex-direction", direction);
3411
- setOrReplace("gap", gap);
3412
- const nextStyle = serializeStyleDeclarations(declarations);
3413
- // We work on a scratch copy relative to element boundaries
3414
- const attr = getAttribute(element, "style");
3415
- if (attr) {
3416
- return `${openTag.slice(0, attr.start - element.start)}${attr.name}="${escapeHtmlAttribute(nextStyle)}"${openTag.slice(attr.end - element.start)}`;
3417
- }
3418
- // Insert before closing >
3419
- const closeChar = openTag.endsWith("/>")
3420
- ? openTag.length - 2
3421
- : openTag.length - 1;
3422
- return `${openTag.slice(0, closeChar)} style="${escapeHtmlAttribute(nextStyle)}"${openTag.slice(closeChar)}`;
3423
- }
3424
-
3425
3376
  /**
3426
3377
  * Strip absolute-positioning properties from a child's inline style, applying
3427
3378
  * the edit directly to the html string at the child element's source spans.
@@ -3889,6 +3840,13 @@ function applyUnwrap(
3889
3840
  /**
3890
3841
  * CONVERT: toggle auto-layout (display:flex) on an existing container.
3891
3842
  */
3843
+ /** Whether an existing min-width/min-height already preserves `extent` px. */
3844
+ function holdsOpen(value: string, extent: number): boolean {
3845
+ const trimmed = value.trim();
3846
+ if (!/^[\d.]+px$/i.test(trimmed)) return !/^0[a-z%]*$/i.test(trimmed);
3847
+ return Number.parseFloat(trimmed) >= extent;
3848
+ }
3849
+
3892
3850
  function applyAutoLayout(
3893
3851
  html: string,
3894
3852
  build: ProjectionBuild,
@@ -3907,21 +3865,113 @@ function applyAutoLayout(
3907
3865
  if (!element) return "conflict";
3908
3866
 
3909
3867
  if (!enabled) {
3910
- // Turn off auto-layout: set display:block.
3868
+ const childRects = intent.childRects;
3869
+ const hasRects = !!childRects && Object.keys(childRects).length > 0;
3911
3870
  const currentStyle = attributeValue(element, "style");
3912
- let declarations = parseStyleDeclarations(currentStyle);
3913
- const displayDecl = declarations.find((d) => d.property === "display");
3914
- if (displayDecl) {
3915
- displayDecl.value = "block";
3916
- } else {
3917
- declarations.push({ property: "display", value: "block" });
3871
+ const declarations = parseStyleDeclarations(currentStyle);
3872
+ const setOnContainer = (property: string, value: string) => {
3873
+ const existing = declarations.find((d) => d.property === property);
3874
+ if (existing) existing.value = value;
3875
+ else declarations.push({ property, value });
3876
+ };
3877
+ setOnContainer("display", "block");
3878
+ if (hasRects) {
3879
+ // Absolute children resolve against the nearest positioned ancestor, so
3880
+ // a static container would let them escape to the page.
3881
+ const position = declarations.find((d) => d.property === "position");
3882
+ if (!position || position.value === "static") {
3883
+ setOnContainer("position", "relative");
3884
+ }
3885
+ // With every child absolute the content box is empty, so a hug-sized
3886
+ // container collapses and overflow:hidden then hides what we just pinned.
3887
+ const rect = intent.containerRect;
3888
+ if (rect) {
3889
+ for (const [property, value] of [
3890
+ ["min-width", rect.width],
3891
+ ["min-height", rect.height],
3892
+ ] as const) {
3893
+ const existing = declarations.find((d) => d.property === property);
3894
+ // `min-height: 0` is the standard flex idiom and holds nothing open.
3895
+ // Only a px minimum at least as large as the measured extent does.
3896
+ if (existing && !holdsOpen(existing.value, value)) {
3897
+ existing.value = `${Math.round(value)}px`;
3898
+ } else if (!existing) {
3899
+ declarations.push({ property, value: `${Math.round(value)}px` });
3900
+ }
3901
+ }
3902
+ }
3903
+ }
3904
+ let result = replaceOrInsertAttribute(
3905
+ html,
3906
+ element,
3907
+ "style",
3908
+ serializeStyleDeclarations(declarations),
3909
+ );
3910
+ if (!hasRects) {
3911
+ return {
3912
+ content: result,
3913
+ capability: { kind: "style", properties: ["display"], confidence: 0.9 },
3914
+ };
3915
+ }
3916
+
3917
+ const updatedElements = parseHtmlElements(result);
3918
+ const targetAttr = attributeValue(element, "data-agent-native-node-id");
3919
+ const updatedTarget =
3920
+ (targetAttr
3921
+ ? updatedElements.find(
3922
+ (fe) =>
3923
+ attributeValue(fe, "data-agent-native-node-id") === targetAttr,
3924
+ )
3925
+ : undefined) ??
3926
+ updatedElements.find((fe) => fe.start === element.start);
3927
+ if (updatedTarget) {
3928
+ // Reverse order keeps earlier offsets valid as each write shifts the rest.
3929
+ for (const childIndex of [...updatedTarget.childIndexes].reverse()) {
3930
+ const child = updatedElements[childIndex];
3931
+ if (!child) continue;
3932
+ const childId = attributeValue(child, "data-agent-native-node-id");
3933
+ const rect = childId ? childRects[childId] : undefined;
3934
+ if (!rect) continue;
3935
+ const childDecls = parseStyleDeclarations(
3936
+ attributeValue(child, "style"),
3937
+ );
3938
+ const setOnChild = (property: string, value: string) => {
3939
+ const existing = childDecls.find((d) => d.property === property);
3940
+ if (existing) existing.value = value;
3941
+ else childDecls.push({ property, value });
3942
+ };
3943
+ // The measured rect is a border box placed by its margin edge, so a
3944
+ // content-box child would grow by its padding and a margin would shift
3945
+ // it off the position we just measured.
3946
+ setOnChild("box-sizing", "border-box");
3947
+ setOnChild("margin", "0");
3948
+ setOnChild("position", "absolute");
3949
+ setOnChild("left", `${Math.round(rect.x)}px`);
3950
+ setOnChild("top", `${Math.round(rect.y)}px`);
3951
+ setOnChild("width", `${Math.round(rect.width)}px`);
3952
+ setOnChild("height", `${Math.round(rect.height)}px`);
3953
+ result = replaceOrInsertAttribute(
3954
+ result,
3955
+ child,
3956
+ "style",
3957
+ serializeStyleDeclarations(childDecls),
3958
+ );
3959
+ }
3918
3960
  }
3919
- const nextStyle = serializeStyleDeclarations(declarations);
3920
3961
  return {
3921
- content: replaceOrInsertAttribute(html, element, "style", nextStyle),
3962
+ content: result,
3922
3963
  capability: {
3923
3964
  kind: "style",
3924
- properties: ["display"],
3965
+ properties: [
3966
+ "display",
3967
+ "position",
3968
+ "min-width",
3969
+ "min-height",
3970
+ "left",
3971
+ "top",
3972
+ "width",
3973
+ "height",
3974
+ ],
3925
3975
  confidence: 0.9,
3926
3976
  },
3927
3977
  };
@@ -13,7 +13,6 @@
13
13
  * See `DESIGN-STUDIO-PLAN.md` §4.2 for rationale.
14
14
  */
15
15
 
16
- import type { CodeLayerNode } from "./code-layer";
17
16
  import type { DesignCapabilityName } from "./design-source-capabilities";
18
17
  import type { DesignSourceType } from "./source-mode";
19
18
 
@@ -683,7 +683,3 @@ function roundCoord(value: number) {
683
683
  function samePoint(a: PenPoint, b: PenPoint) {
684
684
  return a.x === b.x && a.y === b.y;
685
685
  }
686
-
687
- function isPenPoint(point: PenPoint | undefined): point is PenPoint {
688
- return !!point;
689
- }
@@ -38,7 +38,11 @@ connection exists:
38
38
  register a `kind: "oauth"` entry so the shared UI renders Connect and the
39
39
  runtime owns status, refresh, and reauthorization.
40
40
  - **Deploy- or app-level configuration** - use deployment/runtime
41
- configuration, not a per-user secret row.
41
+ configuration, not a per-user secret row. For a non-secret public setting
42
+ already represented by `AgentNativeConfig`, put the default in
43
+ `agent-native.config.ts` and use its `AGENT_NATIVE_CONFIG_<PATH>` alias only
44
+ for a deployment override. Never put a credential or provider key in that
45
+ public namespace.
42
46
  - **Account, customer, manager, or other non-secret identifier** - store it as
43
47
  scoped connection metadata or app data, not as a masked secret field.
44
48
 
@@ -55,7 +55,10 @@ Preview before `--apply`, commit `agent-native.ejections.json`, and never edit
55
55
  ZIPs, screenshots, thumbnails, session replay chunks) in configured file/blob
56
56
  storage and persist only URLs, ids, or handles.
57
57
  - Store shared runtime configuration in the workspace root `.env`; use
58
- `apps/<app>/.env` only for app-specific overrides. Never hardcode API keys,
58
+ `apps/<app>/.env` only for app-specific overrides. For public app behavior,
59
+ prefer the default in `agent-native.config.ts` and use the deterministic
60
+ `AGENT_NATIVE_CONFIG_<UPPER_SNAKE_PATH>` alias only when a non-secret value
61
+ needs a deployment override. Never hardcode API keys,
59
62
  tokens, webhook URLs, signing secrets, private Builder/internal data, customer
60
63
  data, or credential-looking literals in source, docs, prompts, fixtures,
61
64
  application state, action responses, or generated app content. Use
@@ -3,8 +3,6 @@
3
3
  All notable user-facing changes to Agent-Native Dispatch are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new").
5
5
 
6
- Older updates live in [the changelog folder](./changelog/) and are included in the in-app "What's new" view.
7
-
8
6
  ## 2026-08-20
9
7
 
10
8
  ### Fixed
@@ -57,3 +55,199 @@ Older updates live in [the changelog folder](./changelog/) and are included in t
57
55
  ### Added
58
56
 
59
57
  - Chat-first navigation keeps conversations central while opening workspace apps and watched sessions beside them.
58
+
59
+ ## 2026-08-07
60
+
61
+ ### Changed
62
+
63
+ - Language selection now lives in Settings instead of the Dispatch header.
64
+
65
+ ## 2026-08-06
66
+
67
+ ### Improved
68
+
69
+ - Dispatch keeps everyday navigation focused while management tools live in a dedicated Admin area
70
+ - Ready workspace apps stay one click away in a compact Dispatch navigation rail
71
+
72
+ ### Security
73
+
74
+ - Shared Vault values and management are now restricted to workspace owners and admins
75
+
76
+ ## 2026-08-05
77
+
78
+ ### Fixed
79
+
80
+ - Transactional email catalogs and delivery activity are available in Dispatch again.
81
+
82
+ ## 2026-08-04
83
+
84
+ ### Improved
85
+
86
+ - Dispatch keeps connected chats out of local history by default and lets you show all sources on demand.
87
+
88
+ ## 2026-08-03
89
+
90
+ ### Improved
91
+
92
+ - Automation details now show scheduler checks, past runs, and actionable failure diagnostics
93
+
94
+ ## 2026-07-30
95
+
96
+ ### Improved
97
+
98
+ - Delegated Dispatch work can now continue reliably in the background.
99
+ - Thread Debug now lists recent failed agent runs across connected workspace apps for one-click inspection.
100
+
101
+ ## 2026-07-29
102
+
103
+ ### Added
104
+
105
+ - Browser chat can securely connect the Agent-Native Chrome extension to Dispatch with page context.
106
+
107
+ ### Fixed
108
+
109
+ - Workspace members without admin access now see a clear permission message when opening usage metrics.
110
+
111
+ ## 2026-07-28
112
+
113
+ ### Improved
114
+
115
+ - Pending apps are hidden by default and app ownership details are available from the overflow menu
116
+
117
+ ## 2026-07-27
118
+
119
+ ### Improved
120
+
121
+ - Creating an app from a curated template now uses clearer, more direct language.
122
+ - Thread Debug can open a run directly from the copied request ID in an Agent Native chat.
123
+
124
+ ## 2026-07-26
125
+
126
+ ### Fixed
127
+
128
+ - Slack replies now recover after a connected app finishes an update, without repeating the update or losing the delivered reply from future thread context.
129
+
130
+ ## 2026-07-25
131
+
132
+ ### Improved
133
+
134
+ - App branding now uses the product name without the Agent-Native prefix.
135
+ - Settings navigation now keeps Manage agent as a dedicated linked destination at the bottom.
136
+
137
+ ## 2026-07-24
138
+
139
+ ### Improved
140
+
141
+ - Secondary controls and dashboard surfaces now use quieter borderless styling.
142
+ - Sidebar utility controls now follow a consistent footer order.
143
+
144
+ ### Fixed
145
+
146
+ - Signing in now reliably puts you in your company's workspace instead of stranding you in a personal one, and the workspace switcher stays reachable when the sidebar is collapsed.
147
+
148
+ ## 2026-07-23
149
+
150
+ ### Improved
151
+
152
+ - Agent settings are clearly labeled Manage agent in the sidebar.
153
+ - Dispatch keeps messaging setup and destination details behind focused expandable panels.
154
+
155
+ ## 2026-07-22
156
+
157
+ ### Improved
158
+
159
+ - Manage agent navigation now uses the connected-nodes icon.
160
+
161
+ ## 2026-07-21
162
+
163
+ ### Fixed
164
+
165
+ - Slack agent requests recover automatically when the first background handoff is interrupted.
166
+
167
+ ## 2026-07-17
168
+
169
+ ### Added
170
+
171
+ - Dispatch now offers curated workspace templates that can be used to create private apps.
172
+
173
+ ### Improved
174
+
175
+ - Dispatch now links to other available apps from the Apps page.
176
+
177
+ ### Fixed
178
+
179
+ - The agent chat sidebar stays closed until you open it or start a chat handoff.
180
+
181
+ ## 2026-07-14
182
+
183
+ ### Fixed
184
+
185
+ - Dispatch now distinguishes connected agents from locally mounted apps when routing cross-app work.
186
+
187
+ ## 2026-07-13
188
+
189
+ ### Added
190
+
191
+ - New Agent page: see and manage your agent's context, files, connections, jobs, and external access in one place
192
+
193
+ ## 2026-07-11
194
+
195
+ ### Improved
196
+
197
+ - Dispatch MCP connections now start with safer app access and stay signed in more reliably in ChatGPT.
198
+ - Overview and Chat now share a cleaner flow with cross-app prompting, smoother transitions, and a stable bottom chat field.
199
+
200
+ ### Fixed
201
+
202
+ - Data loading failures now show a clear error with a retry option instead of appearing as empty lists.
203
+
204
+ ## 2026-07-10
205
+
206
+ ### Added
207
+
208
+ - Connect Slack workspaces with OAuth, Agent view, and direct messages, then manage channel identity, memory, routines, policies, and AI budgets.
209
+ - Microsoft Teams bots and Discord slash commands can now connect with verified webhooks, while Telegram topics and WhatsApp replies preserve conversation context.
210
+
211
+ ### Improved
212
+
213
+ - Dispatch now has a cleaner chat history and quieter sidebar identity.
214
+ - Dispatch now groups its workspace controls more clearly and adds an Operations console for agent monitoring, experiments, feedback, and Code-mode database inspection.
215
+ - Slack and Telegram now route uptime-monitor requests to Analytics and return the created monitor link
216
+
217
+ ## 2026-07-08
218
+
219
+ ### Added
220
+
221
+ - Added an Automations page to review, pause, and create scheduled or event-triggered jobs.
222
+
223
+ ### Improved
224
+
225
+ - Destinations now shows outbound delivery-queue health, and Overview links quietly to Automations and other workspace tools.
226
+ - Settings are cleaner and searchable, with a consistent navigation that jumps straight to any setting.
227
+
228
+ ## 2026-07-07
229
+
230
+ ### Improved
231
+
232
+ - Overview is now just Ask Dispatch and a list of apps you can open.
233
+
234
+ ## 2026-06-29
235
+
236
+ ### Fixed
237
+
238
+ - Integration layouts now adapt cleanly when the agent sidebar narrows the app.
239
+
240
+ ## 2026-06-27
241
+
242
+ ### Fixed
243
+
244
+ - Traditional Chinese copy now uses Taiwan terminology and clearer technical wording.
245
+
246
+ ## 2026-06-24
247
+
248
+ ### Added
249
+
250
+ - A new Settings page gives quick access to language, workspace, and agent preferences.
251
+ - Added a language picker and localized app chrome for supported languages.
252
+
253
+ For the full list of updates, see the [changelog folder](./changelog/).