@agent-native/core 0.192.0-nightly-20260926081002 → 0.192.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 (139) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/CHANGELOG.md +17 -0
  3. package/corpus/templates/analytics/actions/get-sql-dashboard.ts +27 -3
  4. package/corpus/templates/analytics/app/components/AnalyticsReviewArtifactPreview.tsx +8 -2
  5. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +14 -10
  6. package/corpus/templates/analytics/app/root.tsx +2 -4
  7. package/corpus/templates/analytics/app/routes/_index.tsx +1 -36
  8. package/corpus/templates/analytics/app/routes/home.tsx +1 -1
  9. package/corpus/templates/analytics/changelog/2026-09-25-human-review-previews-show-same-organization-dashboard-chart.md +6 -0
  10. package/corpus/templates/analytics/changelog/2026-09-25-human-review-skips-saved-bigquery-queries-in-previews.md +6 -0
  11. package/corpus/templates/analytics/changelog/2026-09-26-the-app-entry-now-opens-the-shared-sign-in-and-sign-up-scree.md +6 -0
  12. package/corpus/templates/analytics/server/lib/dashboards-store.ts +14 -0
  13. package/corpus/templates/analytics/server/plugins/auth.ts +0 -3
  14. package/corpus/templates/assets/CHANGELOG.md +16 -0
  15. package/corpus/templates/assets/app/root.tsx +2 -7
  16. package/corpus/templates/assets/app/routes/_index.tsx +1 -36
  17. package/corpus/templates/assets/changelog/2026-09-26-the-app-entry-now-opens-the-shared-sign-in-and-sign-up-scree.md +6 -0
  18. package/corpus/templates/assets/server/plugins/auth.ts +0 -3
  19. package/corpus/templates/brain/app/root.tsx +2 -13
  20. package/corpus/templates/brain/app/routes/_index.tsx +1 -35
  21. package/corpus/templates/brain/app/routes/home.tsx +1 -1
  22. package/corpus/templates/calendar/CHANGELOG.md +15 -0
  23. package/corpus/templates/calendar/app/root.tsx +2 -10
  24. package/corpus/templates/calendar/app/routes/_index.tsx +1 -34
  25. package/corpus/templates/calendar/changelog/2026-09-26-the-app-entry-now-opens-the-shared-sign-in-and-sign-up-scree.md +6 -0
  26. package/corpus/templates/calendar/server/plugins/auth.ts +0 -3
  27. package/corpus/templates/chat/AGENTS.md +3 -3
  28. package/corpus/templates/chat/app/root.tsx +3 -15
  29. package/corpus/templates/chat/app/routes/_index.tsx +1 -37
  30. package/corpus/templates/chat/server/plugins/auth.ts +0 -3
  31. package/corpus/templates/clips/CHANGELOG.md +10 -0
  32. package/corpus/templates/clips/app/root.tsx +2 -10
  33. package/corpus/templates/clips/app/routes/_index.tsx +1 -33
  34. package/corpus/templates/clips/app/routes/share.$shareId.tsx +2 -3
  35. package/corpus/templates/clips/changelog/2026-09-26-the-app-entry-now-opens-the-shared-sign-in-and-sign-up-scree.md +6 -0
  36. package/corpus/templates/clips/server/plugins/auth.ts +0 -3
  37. package/corpus/templates/content/app/root.tsx +2 -3
  38. package/corpus/templates/content/app/routes/_index.tsx +1 -33
  39. package/corpus/templates/content/server/plugins/auth.ts +0 -3
  40. package/corpus/templates/crm/app/root.tsx +3 -16
  41. package/corpus/templates/crm/app/routes/_index.tsx +1 -36
  42. package/corpus/templates/crm/app/routes/home.tsx +1 -1
  43. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +30 -17
  44. package/corpus/templates/design/CHANGELOG.md +31 -0
  45. package/corpus/templates/design/actions/connect-localhost.ts +98 -37
  46. package/corpus/templates/design/actions/get-design.schema.ts +10 -0
  47. package/corpus/templates/design/actions/get-design.ts +25 -6
  48. package/corpus/templates/design/actions/publish-visual-edit-pending.ts +4 -59
  49. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +108 -49
  50. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +63 -21
  51. package/corpus/templates/design/app/components/design/types.ts +2 -0
  52. package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-element-drop.ts +98 -9
  53. package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-insert-timeout.ts +61 -6
  54. package/corpus/templates/design/app/pages/design-editor/commands/mode-change.ts +6 -5
  55. package/corpus/templates/design/app/pages/design-editor/commands/publish-visual-edit-pending.ts +21 -3
  56. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +4 -7
  57. package/corpus/templates/design/app/root.tsx +2 -20
  58. package/corpus/templates/design/app/routes/_index.tsx +1 -34
  59. package/corpus/templates/design/changelog/2026-09-25-fix-live-visual-edit-recovery-handoff-and-interaction-workfl.md +6 -0
  60. package/corpus/templates/design/changelog/2026-09-25-human-review-previews-show-the-actual-design-when-you-have-o.md +6 -0
  61. package/corpus/templates/design/changelog/2026-09-25-live-screens-recover-safely-from-interrupted-cross-screen-mo.md +6 -0
  62. package/corpus/templates/design/changelog/2026-09-26-canvas-focus-stays-on-toolbar-controls-when-a-live-preview-f.md +6 -0
  63. package/corpus/templates/design/changelog/2026-09-26-the-app-entry-now-opens-the-shared-sign-in-and-sign-up-scree.md +6 -0
  64. package/corpus/templates/design/server/plugins/auth.ts +0 -3
  65. package/corpus/templates/dispatch/app/root.tsx +2 -11
  66. package/corpus/templates/dispatch/app/routes/_index.tsx +1 -34
  67. package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +0 -3
  68. package/corpus/templates/factory/app/root.tsx +3 -15
  69. package/corpus/templates/factory/app/routes/_index.tsx +1 -34
  70. package/corpus/templates/factory/app/routes/home.tsx +1 -1
  71. package/corpus/templates/forms/AGENTS.md +1 -1
  72. package/corpus/templates/forms/app/root.tsx +2 -4
  73. package/corpus/templates/forms/app/routes/_index.tsx +1 -34
  74. package/corpus/templates/forms/server/plugins/auth.ts +0 -3
  75. package/corpus/templates/mail/CHANGELOG.md +8 -0
  76. package/corpus/templates/mail/app/root.tsx +2 -6
  77. package/corpus/templates/mail/app/routes/_index.tsx +1 -36
  78. package/corpus/templates/mail/app/routes/home.tsx +1 -1
  79. package/corpus/templates/mail/changelog/2026-09-26-the-app-entry-now-opens-the-shared-sign-in-and-sign-up-scree.md +6 -0
  80. package/corpus/templates/mail/server/plugins/auth.ts +0 -3
  81. package/corpus/templates/plan/app/root.tsx +7 -13
  82. package/corpus/templates/plan/app/routes/_index.tsx +1 -35
  83. package/corpus/templates/plan/app/routes/home.tsx +1 -1
  84. package/corpus/templates/plan/server/plugins/auth.ts +0 -3
  85. package/corpus/templates/slides/CHANGELOG.md +21 -0
  86. package/corpus/templates/slides/actions/get-deck.ts +49 -12
  87. package/corpus/templates/slides/app/root.tsx +1 -3
  88. package/corpus/templates/slides/app/routes/_index.tsx +1 -36
  89. package/corpus/templates/slides/app/routes/home.tsx +1 -1
  90. package/corpus/templates/slides/changelog/2026-09-25-human-review-previews-show-same-organization-slides-for-orga.md +6 -0
  91. package/corpus/templates/slides/changelog/2026-09-26-the-app-entry-now-opens-the-shared-sign-in-and-sign-up-scree.md +6 -0
  92. package/corpus/templates/slides/server/plugins/auth.ts +0 -3
  93. package/corpus/templates/tasks/AGENTS.md +1 -1
  94. package/corpus/templates/tasks/README.md +1 -1
  95. package/corpus/templates/tasks/app/root.tsx +2 -11
  96. package/corpus/templates/tasks/app/routes/_index.tsx +1 -37
  97. package/corpus/templates/tasks/app/routes/home.tsx +1 -1
  98. package/dist/cli/design-connect.d.ts +1 -0
  99. package/dist/cli/design-connect.js +94 -32
  100. package/dist/client/auth/AuthPage.d.ts +1 -17
  101. package/dist/client/auth/AuthPage.js +7 -49
  102. package/dist/client/observability/OutputPreview.js +8 -2
  103. package/dist/client/sign-in-landing.d.ts +1 -0
  104. package/dist/client/sign-in-landing.js +8 -0
  105. package/dist/collab/awareness.d.ts +2 -2
  106. package/dist/deploy/workspace-deploy.js +32 -8
  107. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  108. package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
  109. package/dist/provider-api/actions/provider-api.d.ts +3 -3
  110. package/dist/server/auth-marketing.d.ts +0 -7
  111. package/dist/server/auth-marketing.js +0 -36
  112. package/dist/server/auth.d.ts +1 -10
  113. package/dist/server/index.d.ts +1 -1
  114. package/dist/server/index.js +1 -1
  115. package/dist/server/onboarding-html.d.ts +1 -12
  116. package/dist/server/onboarding-html.js +4 -817
  117. package/dist/shared/ssr-auth-redirect.d.ts +3 -3
  118. package/dist/shared/ssr-auth-redirect.js +4 -4
  119. package/dist/templates/chat/AGENTS.md +3 -3
  120. package/dist/templates/chat/app/root.tsx +3 -15
  121. package/dist/templates/chat/app/routes/_index.tsx +1 -37
  122. package/dist/templates/chat/server/plugins/auth.ts +0 -3
  123. package/dist/templates/default/AGENTS.md +2 -4
  124. package/dist/templates/default/DEVELOPING.md +3 -5
  125. package/dist/templates/default/app/root.tsx +2 -9
  126. package/dist/templates/default/app/routes/_index.tsx +8 -15
  127. package/package.json +5 -4
  128. package/src/templates/chat/AGENTS.md +3 -3
  129. package/src/templates/chat/app/root.tsx +3 -15
  130. package/src/templates/chat/app/routes/_index.tsx +1 -37
  131. package/src/templates/chat/server/plugins/auth.ts +0 -3
  132. package/src/templates/default/AGENTS.md +2 -4
  133. package/src/templates/default/DEVELOPING.md +3 -5
  134. package/src/templates/default/app/root.tsx +2 -9
  135. package/src/templates/default/app/routes/_index.tsx +8 -15
  136. package/dist/server/auth-marketing-locales.d.ts +0 -9
  137. package/dist/server/auth-marketing-locales.js +0 -1322
  138. package/dist/templates/chat/public/auth-marketing/chat.webp +0 -0
  139. package/src/templates/chat/public/auth-marketing/chat.webp +0 -0
@@ -5,6 +5,8 @@ import type {
5
5
  } from "@/components/design/types";
6
6
 
7
7
  export const CROSS_SCREEN_INSERT_ACK_TIMEOUT_MS = 2_200;
8
+ const CROSS_SCREEN_CANCEL_RETRY_MAX_DELAY_MS = 30_000;
9
+ const MAX_CROSS_SCREEN_ROLLBACK_RETRIES = 1;
8
10
 
9
11
  export function scheduleCrossScreenInsertTimeout(
10
12
  request: (RuntimeStructureInsertRequest & { screenId: string }) | null,
@@ -31,19 +33,39 @@ export function scheduleCrossScreenDeleteTimeout(
31
33
  ): () => void {
32
34
  if (
33
35
  !request?.transactionId ||
34
- request.cancelRequested ||
35
- request.waitForInsertTransaction !== false ||
36
+ (request.waitForInsertTransaction !== false && !request.cancelRequested) ||
36
37
  request.screenId === boardFileId
37
38
  ) {
38
39
  return () => {};
39
40
  }
40
- const timeout = window.setTimeout(
41
- () => onTimeout(request),
42
- CROSS_SCREEN_INSERT_ACK_TIMEOUT_MS,
43
- );
41
+ const timeoutMs = request.cancelRequested
42
+ ? Math.min(
43
+ CROSS_SCREEN_INSERT_ACK_TIMEOUT_MS *
44
+ 2 ** (request.cancellationRetryCount ?? 0),
45
+ CROSS_SCREEN_CANCEL_RETRY_MAX_DELAY_MS,
46
+ )
47
+ : CROSS_SCREEN_INSERT_ACK_TIMEOUT_MS;
48
+ const timeout = window.setTimeout(() => onTimeout(request), timeoutMs);
44
49
  return () => window.clearTimeout(timeout);
45
50
  }
46
51
 
52
+ export function retryCrossScreenDeleteCancellation<
53
+ T extends RuntimeStructureDeleteRequest & { screenId: string },
54
+ >(request: T): RuntimeStructureDeleteRequest & { screenId: string } {
55
+ const cancellationRetryCount = (request.cancellationRetryCount ?? 0) + 1;
56
+ return {
57
+ ...request,
58
+ cancellationRetryCount,
59
+ };
60
+ }
61
+
62
+ export function crossScreenSourceCancellationNeedsRetry(result: {
63
+ reason: string;
64
+ sourcePresent?: boolean;
65
+ }): boolean {
66
+ return result.reason !== "cancelled" || result.sourcePresent !== true;
67
+ }
68
+
47
69
  export function scheduleCrossScreenRollbackTimeout(
48
70
  request: RuntimeStructureRollbackRequest | null,
49
71
  onTimeout: (request: RuntimeStructureRollbackRequest) => void,
@@ -56,6 +78,21 @@ export function scheduleCrossScreenRollbackTimeout(
56
78
  return () => window.clearTimeout(timeout);
57
79
  }
58
80
 
81
+ export function cancelCrossScreenRollbackTimeout(timeoutRef: {
82
+ current: (() => void) | null;
83
+ }): void {
84
+ timeoutRef.current?.();
85
+ timeoutRef.current = null;
86
+ }
87
+
88
+ export function retryCrossScreenRollbackRequest<
89
+ T extends RuntimeStructureRollbackRequest,
90
+ >(request: T, requestId: string): (T & { retryCount: number }) | null {
91
+ const retryCount = request.retryCount ?? 0;
92
+ if (retryCount >= MAX_CROSS_SCREEN_ROLLBACK_RETRIES) return null;
93
+ return { ...request, requestId, retryCount: retryCount + 1 };
94
+ }
95
+
59
96
  export function crossScreenSourceDeleteCancellation(
60
97
  request: (RuntimeStructureDeleteRequest & { screenId: string }) | null,
61
98
  transactionId: string,
@@ -74,6 +111,24 @@ export function crossScreenSourceDeleteCancellation(
74
111
  return { ...request, cancelRequested: true };
75
112
  }
76
113
 
114
+ export function crossScreenRollbackAfterSourceCancellation(
115
+ request: RuntimeStructureDeleteRequest & { screenId: string },
116
+ sourcePresent: boolean,
117
+ requestId: string,
118
+ ): (RuntimeStructureRollbackRequest & { screenId: string }) | null {
119
+ if (!sourcePresent || !request.rollbackScreenId) {
120
+ return null;
121
+ }
122
+ return {
123
+ screenId: request.rollbackScreenId,
124
+ requestId,
125
+ transactionId: request.transactionId,
126
+ selector: request.rollbackSelector ?? "",
127
+ sourceId: request.rollbackSourceId,
128
+ idempotent: true,
129
+ };
130
+ }
131
+
77
132
  export function crossScreenRollbackIsComplete(
78
133
  request: RuntimeStructureRollbackRequest,
79
134
  result: { applied: boolean; reason?: string },
@@ -16,7 +16,8 @@ import type {
16
16
  export interface ModeChangeArgs {
17
17
  activeFile: DesignFile;
18
18
  canEditDesign: boolean;
19
- blockInteraction?: boolean;
19
+ hasPendingVisualEdits?: boolean;
20
+ onPendingVisualEditsBlocked: () => void;
20
21
  clearPendingLiveEditState: () => void;
21
22
  enterOverviewFromZoom: (nextMode?: EditorMode) => void;
22
23
  enterSingleScreen: (fileId?: string | null) => void;
@@ -44,12 +45,13 @@ export interface ModeChangeArgs {
44
45
  export function runModeChange(
45
46
  {
46
47
  activeFile,
47
- blockInteraction = false,
48
48
  canEditDesign,
49
49
  clearPendingLiveEditState,
50
+ onPendingVisualEditsBlocked,
50
51
  enterOverviewFromZoom,
51
52
  enterSingleScreen,
52
53
  files,
54
+ hasPendingVisualEdits = false,
53
55
  pendingLiveNonStyleEdits,
54
56
  pendingVisualStyleEdits,
55
57
  requestPendingLiveNonStyleRevert,
@@ -81,12 +83,11 @@ export function runModeChange(
81
83
  }
82
84
  if (
83
85
  next === "interact" &&
84
- (blockInteraction ||
85
- pendingVisualStyleEdits.length > 0 ||
86
- pendingLiveNonStyleEdits.length > 0) &&
86
+ hasPendingVisualEdits &&
87
87
  !options?.discardPendingLiveEdits &&
88
88
  !options?.pendingLiveEditsAlreadyHandled
89
89
  ) {
90
+ onPendingVisualEditsBlocked();
90
91
  toast.error(t("designEditor.pendingVisualStyles.interactBlocked"));
91
92
  return;
92
93
  }
@@ -12,6 +12,13 @@ export interface PendingVisualEditHandoff {
12
12
  } | null;
13
13
  }
14
14
 
15
+ interface PublishedVisualEditHandoff {
16
+ designId: string;
17
+ pendingEditCount: number | null;
18
+ revision: number | null;
19
+ status: "empty" | "ready" | "stale";
20
+ }
21
+
15
22
  export interface PublishVisualEditPendingArgs {
16
23
  activeScreenBridgeUrl: string | null | undefined;
17
24
  activeScreenPreviewToken: string | null | undefined;
@@ -20,8 +27,7 @@ export interface PublishVisualEditPendingArgs {
20
27
  name: "publish-visual-edit-pending",
21
28
  payload: PendingVisualEditHandoff,
22
29
  ) => Promise<unknown>;
23
- /** The durable action verifies editor access or the same-origin live-share
24
- * URL; this only decides whether to attempt that action from the browser. */
30
+ /** Only account/editor-capability sessions can publish the durable handoff. */
25
31
  canPublishDurableHandoff: boolean;
26
32
  designId: string;
27
33
  fetchImpl: typeof fetch;
@@ -62,7 +68,19 @@ export async function runPublishVisualEditPending(
62
68
  const clearRequested = pending.pending === null;
63
69
  if (canPublishDurableHandoff) {
64
70
  try {
65
- await callAction("publish-visual-edit-pending", pending);
71
+ const result = (await callAction(
72
+ "publish-visual-edit-pending",
73
+ pending,
74
+ )) as PublishedVisualEditHandoff | null;
75
+ const expectedStatus = clearRequested ? "empty" : "ready";
76
+ if (
77
+ result?.designId !== designId ||
78
+ result.status !== expectedStatus ||
79
+ !Number.isInteger(result.revision) ||
80
+ (result.revision ?? 0) < 1
81
+ ) {
82
+ throw { errorCode: "visual_edit_handoff_unconfirmed" };
83
+ }
66
84
  setPendingVisualEditPublicationFailed(false);
67
85
  if (
68
86
  clearRequested &&
@@ -1741,13 +1741,10 @@ export function formatVisualEditClipboardPrompt(
1741
1741
  prompt,
1742
1742
  ].join("\n");
1743
1743
  }
1744
- if (host === "webmcp") {
1745
- return "Call the get-visual-edit-prompt WebMCP tool in this Design tab and apply the returned instructions.";
1746
- }
1747
- if (host === "chatgpt" || host === "claude" || host === "codex") {
1748
- return `Use the Agent-Native Design MCP tool get-visual-edit-pending${design} to pull the latest edits, then apply its prompt to the connected app source. Verify the running app before acknowledging that revision, then call the tool again to confirm the handoff cleared.`;
1749
- }
1750
- return prompt;
1744
+ const mcpHandoff = `Use the Agent-Native Design MCP tool get-visual-edit-pending with${design} to pull the latest edits. Apply its instructions to the connected app source, verify the running app, then call acknowledge-visual-edit-pending with the returned revision and pull again to confirm the handoff cleared.`;
1745
+ return host === "webmcp"
1746
+ ? `${mcpHandoff} If you cannot access the Design MCP server but can use this open Design tab, use its page-local get-visual-edit-prompt WebMCP tool instead.`
1747
+ : mcpHandoff;
1751
1748
  }
1752
1749
 
1753
1750
  export function isVisualEditHandoffAcknowledged(args: {
@@ -221,21 +221,6 @@ function DesignToaster() {
221
221
  );
222
222
  }
223
223
 
224
- function RootContent() {
225
- const location = useLocation();
226
- if (location.pathname === "/") return <MarketingRootContent />;
227
- return <PrivateRootContent />;
228
- }
229
-
230
- function MarketingRootContent() {
231
- return (
232
- <>
233
- <OpenVisualEditWebMcp />
234
- <Outlet />
235
- </>
236
- );
237
- }
238
-
239
224
  function PrivateRootContent() {
240
225
  const location = useLocation();
241
226
  const { session } = useSession();
@@ -281,8 +266,6 @@ export function computeSessionBypass(pathname: string): boolean {
281
266
  export default function Root() {
282
267
  const [queryClient] = useState(() => createAgentNativeQueryClient());
283
268
  const location = useLocation();
284
- const isMarketingHome = location.pathname === "/";
285
- const isPublicPath = isMarketingHome;
286
269
  // Public design routes still resolve their editor layout client-side; SSR
287
270
  // would render route-state hooks before the document router is available.
288
271
  const sessionBypass = computeSessionBypass(location.pathname);
@@ -290,13 +273,12 @@ export default function Root() {
290
273
  <AppToolkitProvider>
291
274
  <AppProviders
292
275
  queryClient={queryClient}
293
- isPublicPath={isPublicPath}
294
276
  sessionBypass={sessionBypass}
295
277
  webMcpExcludeActionNames={DESIGN_WEBMCP_EXCLUDED_ACTIONS}
296
- i18n={{ catalog: i18nCatalog, persistPreference: !isPublicPath }}
278
+ i18n={{ catalog: i18nCatalog }}
297
279
  toaster={<DesignToaster />}
298
280
  >
299
- <RootContent />
281
+ <PrivateRootContent />
300
282
  </AppProviders>
301
283
  </AppToolkitProvider>
302
284
  );
@@ -1,34 +1 @@
1
- import { appPath } from "@agent-native/core/client/api-path";
2
- import { MarketingHome } from "@agent-native/toolkit/marketing";
3
-
4
- const SEO_TITLE =
5
- "Design - Open Source AI design tool for agent-built prototypes";
6
- const SEO_DESCRIPTION =
7
- "Open Source AI design tool for creating, remixing, and sharing responsive prototypes, design systems, and coding handoffs.";
8
-
9
- export function meta() {
10
- return [
11
- { title: SEO_TITLE },
12
- {
13
- name: "description",
14
- content: SEO_DESCRIPTION,
15
- },
16
- { property: "og:title", content: SEO_TITLE },
17
- { property: "og:description", content: SEO_DESCRIPTION },
18
- { name: "twitter:card", content: "summary" },
19
- { name: "twitter:title", content: SEO_TITLE },
20
- { name: "twitter:description", content: SEO_DESCRIPTION },
21
- ];
22
- }
23
-
24
- export default function MarketingHomeRoute() {
25
- return (
26
- <MarketingHome
27
- appName="Design"
28
- tagline={SEO_TITLE}
29
- description={SEO_DESCRIPTION}
30
- primaryActionHref={appPath("/home")}
31
- secondaryActionHref={appPath("/sign-in")}
32
- />
33
- );
34
- }
1
+ export { signInLandingLoader as loader } from "@agent-native/core/client/sign-in-landing";
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-25
4
+ ---
5
+
6
+ Fix live visual-edit recovery, handoff, and interaction workflows.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-25
4
+ ---
5
+
6
+ Human Review previews show the actual design when you have organization admin access.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-25
4
+ ---
5
+
6
+ Live screens recover safely from interrupted cross-screen moves and keep pending edits accessible before switching to Interact.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-09-26
4
+ ---
5
+
6
+ Canvas focus stays on toolbar controls when a live preview finishes loading
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: changed
3
+ date: 2026-09-26
4
+ ---
5
+
6
+ The app entry now opens the shared sign-in and sign-up screen instead of a separate marketing page.
@@ -10,9 +10,6 @@ export default createAuthPlugin({
10
10
  workspaceAppPublicPaths: ["/", "/visual-edit", "/design", "/present"],
11
11
  marketing: {
12
12
  appName: "Design",
13
- screenshotPath: "/auth-marketing/design.webp",
14
- screenshotWidth: 914,
15
- screenshotHeight: 818,
16
13
  learnMoreUrl: "https://agent-native.com/apps/design",
17
14
  tagline:
18
15
  "Design and prototype by describing what you want. The AI agent turns your ideas into interactive, fully responsive designs in seconds.",
@@ -183,12 +183,6 @@ function ThemeToggleItem() {
183
183
  );
184
184
  }
185
185
 
186
- function AppContent() {
187
- const location = useLocation();
188
- if (location.pathname === "/") return <Outlet />;
189
- return <PrivateAppContent />;
190
- }
191
-
192
186
  function PrivateAppContent() {
193
187
  return (
194
188
  <RequireDispatchAccess>
@@ -269,13 +263,10 @@ function PrivateAppShell() {
269
263
 
270
264
  export default function Root() {
271
265
  const [queryClient] = useState(() => createAgentNativeQueryClient());
272
- const location = useLocation();
273
- const isMarketingHome = location.pathname === "/";
274
266
  return (
275
267
  <AppToolkitProvider>
276
268
  <AppProviders
277
269
  queryClient={queryClient}
278
- isPublicPath={isMarketingHome}
279
270
  toaster={
280
271
  <Toaster
281
272
  richColors
@@ -285,9 +276,9 @@ export default function Root() {
285
276
  mobileOffset={{ bottom: 44, left: 16 }}
286
277
  />
287
278
  }
288
- i18n={{ catalog: i18nCatalog, persistPreference: !isMarketingHome }}
279
+ i18n={{ catalog: i18nCatalog }}
289
280
  >
290
- <AppContent />
281
+ <PrivateAppContent />
291
282
  </AppProviders>
292
283
  </AppToolkitProvider>
293
284
  );
@@ -1,34 +1 @@
1
- import { appPath } from "@agent-native/core/client/api-path";
2
- import { MarketingHome } from "@agent-native/toolkit/marketing";
3
-
4
- const SEO_TITLE =
5
- "Dispatch - Open Source workspace control plane for AI agents";
6
- const SEO_DESCRIPTION =
7
- "Open Source workspace control plane for AI agents to manage apps, secrets, approvals, messages, jobs, and cross-app delegation.";
8
-
9
- export function meta() {
10
- return [
11
- { title: SEO_TITLE },
12
- {
13
- name: "description",
14
- content: SEO_DESCRIPTION,
15
- },
16
- { property: "og:title", content: SEO_TITLE },
17
- { property: "og:description", content: SEO_DESCRIPTION },
18
- { name: "twitter:card", content: "summary" },
19
- { name: "twitter:title", content: SEO_TITLE },
20
- { name: "twitter:description", content: SEO_DESCRIPTION },
21
- ];
22
- }
23
-
24
- export default function MarketingHomeRoute() {
25
- return (
26
- <MarketingHome
27
- appName="Dispatch"
28
- tagline={SEO_TITLE}
29
- description={SEO_DESCRIPTION}
30
- primaryActionHref={appPath("/home")}
31
- secondaryActionHref={appPath("/sign-in")}
32
- />
33
- );
34
- }
1
+ export { signInLandingLoader as loader } from "@agent-native/core/client/sign-in-landing";
@@ -3,9 +3,6 @@ import { setupDispatch } from "@agent-native/dispatch/server";
3
3
  export default setupDispatch({
4
4
  auth: {
5
5
  marketing: {
6
- screenshotPath: "/auth-marketing/dispatch.webp",
7
- screenshotWidth: 914,
8
- screenshotHeight: 818,
9
6
  learnMoreUrl: "https://agent-native.com/apps/dispatch",
10
7
  },
11
8
  publicPaths: [
@@ -170,23 +170,11 @@ function AppContent() {
170
170
 
171
171
  export default function Root() {
172
172
  const [queryClient] = useState(() => createAgentNativeQueryClient());
173
- const location = useLocation();
174
- const isMarketingPath = location.pathname === "/";
175
173
  return (
176
174
  <AppToolkitProvider>
177
- <AppProviders
178
- queryClient={queryClient}
179
- isPublicPath={isMarketingPath}
180
- i18n={{ catalog: i18nCatalog }}
181
- >
182
- {isMarketingPath ? (
183
- <Outlet />
184
- ) : (
185
- <>
186
- <DbSyncSetup />
187
- <AppContent />
188
- </>
189
- )}
175
+ <AppProviders queryClient={queryClient} i18n={{ catalog: i18nCatalog }}>
176
+ <DbSyncSetup />
177
+ <AppContent />
190
178
  </AppProviders>
191
179
  </AppToolkitProvider>
192
180
  );
@@ -1,34 +1 @@
1
- import { appPath } from "@agent-native/core/client/api-path";
2
- import { MarketingHome } from "@agent-native/toolkit/marketing";
3
-
4
- const SEO_TITLE = "Factories";
5
- const SEO_DESCRIPTION = "Review and manage your agent factories.";
6
-
7
- export function meta() {
8
- return [
9
- { title: SEO_TITLE },
10
- { name: "description", content: SEO_DESCRIPTION },
11
- { property: "og:title", content: SEO_TITLE },
12
- { property: "og:description", content: SEO_DESCRIPTION },
13
- { name: "twitter:card", content: "summary" },
14
- { name: "twitter:title", content: SEO_TITLE },
15
- { name: "twitter:description", content: SEO_DESCRIPTION },
16
- ];
17
- }
18
-
19
- export default function MarketingHomeRoute() {
20
- return (
21
- <MarketingHome
22
- appName="Factory"
23
- tagline="Build agent factories: work in one end, shipped changes out the other, with gates you control."
24
- description={SEO_DESCRIPTION}
25
- valueProps={[
26
- "Inspect Slack and pull-request signals in one queue",
27
- "Tune rules with prompts and reviewable feedback",
28
- "Approve bounded agent work with a durable audit trail",
29
- ]}
30
- primaryActionHref={appPath("/home")}
31
- secondaryActionHref={appPath("/sign-in")}
32
- />
33
- );
34
- }
1
+ export { signInLandingLoader as loader } from "@agent-native/core/client/sign-in-landing";
@@ -7,7 +7,7 @@ export function meta() {
7
7
  ];
8
8
  }
9
9
 
10
- // Private app entry retained at /home; / serves the public marketing page.
10
+ // Private app entry retained at /home; / redirects to shared sign-in/signup.
11
11
  export default function IndexRoute() {
12
12
  return <Navigate to="/factory" replace />;
13
13
  }
@@ -82,7 +82,7 @@ Read the relevant skill before deeper work:
82
82
 
83
83
  - The `/home` route is the primary chat surface. Use it to ask clarifying
84
84
  questions, create or edit forms, explain setup, and surface response insights.
85
- The public `/` route is reserved for the SSR marketing page.
85
+ The public `/` route redirects to the shared sign-in/signup page.
86
86
  - When the user needs a focused workspace, call `navigate` to open `/forms`,
87
87
  `/forms/:id?tab=edit`, `/forms/:id?tab=responses`,
88
88
  `/forms/:id?tab=settings`, `/forms/:id?tab=integrations`,
@@ -297,14 +297,12 @@ export default function Root() {
297
297
  const location = useLocation();
298
298
  const isPublicPath =
299
299
  location.pathname === "/f" || location.pathname.startsWith("/f/");
300
- const isMarketingHome = location.pathname === "/";
301
-
302
- if (isPublicPath || isMarketingHome) {
300
+ if (isPublicPath) {
303
301
  return (
304
302
  <AppToolkitProvider>
305
303
  <AppProviders
306
304
  queryClient={queryClient}
307
- isPublicPath={isPublicPath || isMarketingHome}
305
+ isPublicPath={isPublicPath}
308
306
  i18n={{ catalog: i18nCatalog }}
309
307
  >
310
308
  <Outlet />
@@ -1,34 +1 @@
1
- import { appPath } from "@agent-native/core/client/api-path";
2
- import { MarketingHome } from "@agent-native/toolkit/marketing";
3
-
4
- import messages from "@/i18n/en-US";
5
-
6
- const SEO_TITLE = messages.routeTitles.formsIndex;
7
- const SEO_DESCRIPTION = messages.routeDescriptions.formsIndex;
8
-
9
- export function meta() {
10
- return [
11
- { title: SEO_TITLE },
12
- {
13
- name: "description",
14
- content: SEO_DESCRIPTION,
15
- },
16
- { property: "og:title", content: SEO_TITLE },
17
- { property: "og:description", content: SEO_DESCRIPTION },
18
- { name: "twitter:card", content: "summary" },
19
- { name: "twitter:title", content: SEO_TITLE },
20
- { name: "twitter:description", content: SEO_DESCRIPTION },
21
- ];
22
- }
23
-
24
- export default function MarketingHomeRoute() {
25
- return (
26
- <MarketingHome
27
- appName="Forms"
28
- tagline={SEO_TITLE}
29
- description={SEO_DESCRIPTION}
30
- primaryActionHref={appPath("/home")}
31
- secondaryActionHref={appPath("/sign-in")}
32
- />
33
- );
34
- }
1
+ export { signInLandingLoader as loader } from "@agent-native/core/client/sign-in-landing";
@@ -4,9 +4,6 @@ export default createAuthPlugin({
4
4
  workspaceAppPublicPaths: ["/"],
5
5
  marketing: {
6
6
  appName: "Forms",
7
- screenshotPath: "/auth-marketing/forms.webp",
8
- screenshotWidth: 914,
9
- screenshotHeight: 818,
10
7
  learnMoreUrl: "https://agent-native.com/apps/forms",
11
8
  tagline:
12
9
  "Your AI agent builds, publishes, and analyzes forms alongside you.",
@@ -3,14 +3,22 @@
3
3
  All notable user-facing changes to Agent-Native Mail are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
+ ## 2026-09-26
7
+
8
+ ### Changed
9
+
10
+ - The app entry now opens the shared sign-in and sign-up screen instead of a separate marketing page.
11
+
6
12
  ## 2026-09-25
7
13
 
8
14
  ### Improved
9
15
 
16
+ - Mail now guides users to connect Jev before setting up triage and lets them remove existing rules if Jev becomes unavailable.
10
17
  - Tune inbox priorities with Jev, label messages clearly, and teach importance with feedback.
11
18
 
12
19
  ### Fixed
13
20
 
21
+ - Slack conversations can now use all available Mail actions
14
22
  - Editing importance rules preserves disabled instructions and recovers from duplicate-rule deletion failures
15
23
  - Handle astral Unicode letters in autocomplete word boundaries
16
24
  - Keep existing AI filter rules intact when saving a prompt
@@ -32,7 +32,6 @@ import {
32
32
  Outlet,
33
33
  Scripts,
34
34
  ScrollRestoration,
35
- useLocation,
36
35
  useRouteError,
37
36
  } from "react-router";
38
37
  import type { LinksFunction } from "react-router";
@@ -489,20 +488,17 @@ export function computeSessionBypass(): boolean {
489
488
 
490
489
  export default function Root() {
491
490
  const [queryClient] = useState(() => createAgentNativeQueryClient());
492
- const location = useLocation();
493
- const isMarketingPath = location.pathname === "/";
494
491
  return (
495
492
  <AppToolkitProvider>
496
493
  <AppProviders
497
494
  queryClient={queryClient}
498
495
  themeAttribute={["class", "data-theme"]}
499
496
  tooltipDelayDuration={300}
500
- isPublicPath={isMarketingPath}
501
- toaster={isMarketingPath ? null : MAIL_TOASTER}
497
+ toaster={MAIL_TOASTER}
502
498
  sessionBypass={computeSessionBypass()}
503
499
  i18n={{ catalog: i18nCatalog }}
504
500
  >
505
- {isMarketingPath ? <Outlet /> : <AppContent />}
501
+ <AppContent />
506
502
  </AppProviders>
507
503
  </AppToolkitProvider>
508
504
  );