@agent-native/dispatch 0.31.26 → 0.31.27-nightly-20260827111940

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.
@@ -1 +1 @@
1
- {"version":3,"file":"transactional-email-preview.d.ts","sourceRoot":"","sources":["../../src/components/transactional-email-preview.tsx"],"names":[],"mappings":"AAkCA,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,OAAO,EACP,EAAE,EACF,IAAI,GACL,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,mDA2CA"}
1
+ {"version":3,"file":"transactional-email-preview.d.ts","sourceRoot":"","sources":["../../src/components/transactional-email-preview.tsx"],"names":[],"mappings":"AAmCA,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,OAAO,EACP,EAAE,EACF,IAAI,GACL,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,mDA2CA"}
@@ -4,6 +4,7 @@ import { useT } from "@agent-native/core/client/i18n";
4
4
  import { IconAlertTriangle } from "@tabler/icons-react";
5
5
  import { useQuery } from "@tanstack/react-query";
6
6
  import { fetchEmailPreview, } from "../client/transactional-emails.js";
7
+ import { resolveEmailPreviewAssets } from "../lib/transactional-email-preview.js";
7
8
  import { Alert, AlertDescription, AlertTitle } from "./ui/alert.js";
8
9
  import { Skeleton } from "./ui/skeleton.js";
9
10
  /**
@@ -34,7 +35,7 @@ export function EmailPreviewPane({ appId, appPath, id, name, }) {
34
35
  if (preview.isLoading || !preview.data) {
35
36
  return _jsx(Skeleton, { className: "h-96 w-full" });
36
37
  }
37
- return (_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: t("dispatch.transactionalEmail.subject") }), _jsx("div", { className: "text-sm font-medium text-foreground", children: preview.data.subject })] }), _jsx("iframe", { title: t("dispatch.transactionalEmail.previewFrameTitle", { name }), sandbox: "", srcDoc: preview.data.html,
38
+ return (_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-xs text-muted-foreground", children: t("dispatch.transactionalEmail.subject") }), _jsx("div", { className: "text-sm font-medium text-foreground", children: preview.data.subject })] }), _jsx("iframe", { title: t("dispatch.transactionalEmail.previewFrameTitle", { name }), sandbox: "", srcDoc: resolveEmailPreviewAssets(preview.data.html),
38
39
  // guard:allow-raw-color — the frame previews email HTML, which renders on white in mail clients regardless of app theme.
39
40
  className: "h-96 w-full rounded-xl border bg-white" })] }));
40
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transactional-email-preview.js","sourceRoot":"","sources":["../../src/components/transactional-email-preview.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EACL,iBAAiB,GAElB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,KAAa,EAAE,OAAe,EAAE,EAAU;IACtE,MAAM,MAAM,GAAG,KAAK,KAAK,MAAM,CAAC;IAChC,MAAM,KAAK,GAAG,cAAc,CAC1B,oCAAoC,EACpC,EAAE,EAAE,EAAE,EACN,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAClC,CAAC;IACF,MAAM,MAAM,GAAG,QAAQ,CAAC;QACtB,QAAQ,EAAE,CAAC,6BAA6B,EAAE,OAAO,EAAE,EAAE,CAAC;QACtD,OAAO,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,OAAO,EAAE,EAAE,CAAC;QAC7C,OAAO,EAAE,CAAC,MAAM;QAChB,KAAK,EAAE,KAAK;KACb,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAC/B,KAAK,EACL,OAAO,EACP,EAAE,EACF,IAAI,GAML;IACC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;IAEzD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CACL,MAAC,KAAK,IAAC,OAAO,EAAC,aAAa,aAC1B,KAAC,iBAAiB,IAAC,SAAS,EAAC,QAAQ,GAAG,EACxC,KAAC,UAAU,cACR,CAAC,CAAC,2CAA2C,CAAC,GACpC,EACb,KAAC,gBAAgB,cACd,OAAO,CAAC,KAAK,YAAY,KAAK;wBAC7B,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO;wBACvB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GACR,IACb,CACT,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACvC,OAAO,KAAC,QAAQ,IAAC,SAAS,EAAC,aAAa,GAAG,CAAC;IAC9C,CAAC;IACD,OAAO,CACL,eAAK,SAAS,EAAC,WAAW,aACxB,0BACE,cAAK,SAAS,EAAC,+BAA+B,YAC3C,CAAC,CAAC,qCAAqC,CAAC,GACrC,EACN,cAAK,SAAS,EAAC,qCAAqC,YACjD,OAAO,CAAC,IAAI,CAAC,OAAO,GACjB,IACF,EAGN,iBACE,KAAK,EAAE,CAAC,CAAC,+CAA+C,EAAE,EAAE,IAAI,EAAE,CAAC,EACnE,OAAO,EAAC,EAAE,EACV,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI;gBACzB,yHAAyH;gBACzH,SAAS,EAAC,wCAAwC,GAClD,IACE,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { useActionQuery } from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { IconAlertTriangle } from \"@tabler/icons-react\";\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport {\n fetchEmailPreview,\n type EmailPreview,\n} from \"../client/transactional-emails\";\nimport { Alert, AlertDescription, AlertTitle } from \"./ui/alert\";\nimport { Skeleton } from \"./ui/skeleton\";\n\n/**\n * The \"core\" app id means the email was read from Dispatch's own local\n * catalog (see transactional-email.tsx), not a cross-app fetch, so its\n * preview must render the same way — Dispatch always has the definition\n * registered locally and a cross-app fetch would have no real appPath to hit.\n */\nfunction useEmailPreviewQuery(appId: string, appPath: string, id: string) {\n const isCore = appId === \"core\";\n const local = useActionQuery<EmailPreview>(\n \"render-transactional-email-preview\",\n { id },\n { enabled: isCore, retry: false },\n );\n const remote = useQuery({\n queryKey: [\"transactional-email-preview\", appPath, id],\n queryFn: () => fetchEmailPreview(appPath, id),\n enabled: !isCore,\n retry: false,\n });\n return isCore ? local : remote;\n}\n\nexport function EmailPreviewPane({\n appId,\n appPath,\n id,\n name,\n}: {\n appId: string;\n appPath: string;\n id: string;\n name: string;\n}) {\n const t = useT();\n const preview = useEmailPreviewQuery(appId, appPath, id);\n\n if (preview.isError) {\n return (\n <Alert variant=\"destructive\">\n <IconAlertTriangle className=\"size-4\" />\n <AlertTitle>\n {t(\"dispatch.transactionalEmail.previewFailed\")}\n </AlertTitle>\n <AlertDescription>\n {preview.error instanceof Error\n ? preview.error.message\n : String(preview.error)}\n </AlertDescription>\n </Alert>\n );\n }\n if (preview.isLoading || !preview.data) {\n return <Skeleton className=\"h-96 w-full\" />;\n }\n return (\n <div className=\"space-y-3\">\n <div>\n <div className=\"text-xs text-muted-foreground\">\n {t(\"dispatch.transactionalEmail.subject\")}\n </div>\n <div className=\"text-sm font-medium text-foreground\">\n {preview.data.subject}\n </div>\n </div>\n {/* sandbox=\"\" (no allow-scripts) keeps arbitrary email HTML from\n running script in the Dispatch origin. */}\n <iframe\n title={t(\"dispatch.transactionalEmail.previewFrameTitle\", { name })}\n sandbox=\"\"\n srcDoc={preview.data.html}\n // guard:allow-raw-color — the frame previews email HTML, which renders on white in mail clients regardless of app theme.\n className=\"h-96 w-full rounded-xl border bg-white\"\n />\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"transactional-email-preview.js","sourceRoot":"","sources":["../../src/components/transactional-email-preview.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EACL,iBAAiB,GAElB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,KAAa,EAAE,OAAe,EAAE,EAAU;IACtE,MAAM,MAAM,GAAG,KAAK,KAAK,MAAM,CAAC;IAChC,MAAM,KAAK,GAAG,cAAc,CAC1B,oCAAoC,EACpC,EAAE,EAAE,EAAE,EACN,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAClC,CAAC;IACF,MAAM,MAAM,GAAG,QAAQ,CAAC;QACtB,QAAQ,EAAE,CAAC,6BAA6B,EAAE,OAAO,EAAE,EAAE,CAAC;QACtD,OAAO,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,OAAO,EAAE,EAAE,CAAC;QAC7C,OAAO,EAAE,CAAC,MAAM;QAChB,KAAK,EAAE,KAAK;KACb,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAC/B,KAAK,EACL,OAAO,EACP,EAAE,EACF,IAAI,GAML;IACC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;IAEzD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CACL,MAAC,KAAK,IAAC,OAAO,EAAC,aAAa,aAC1B,KAAC,iBAAiB,IAAC,SAAS,EAAC,QAAQ,GAAG,EACxC,KAAC,UAAU,cACR,CAAC,CAAC,2CAA2C,CAAC,GACpC,EACb,KAAC,gBAAgB,cACd,OAAO,CAAC,KAAK,YAAY,KAAK;wBAC7B,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO;wBACvB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GACR,IACb,CACT,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACvC,OAAO,KAAC,QAAQ,IAAC,SAAS,EAAC,aAAa,GAAG,CAAC;IAC9C,CAAC;IACD,OAAO,CACL,eAAK,SAAS,EAAC,WAAW,aACxB,0BACE,cAAK,SAAS,EAAC,+BAA+B,YAC3C,CAAC,CAAC,qCAAqC,CAAC,GACrC,EACN,cAAK,SAAS,EAAC,qCAAqC,YACjD,OAAO,CAAC,IAAI,CAAC,OAAO,GACjB,IACF,EAGN,iBACE,KAAK,EAAE,CAAC,CAAC,+CAA+C,EAAE,EAAE,IAAI,EAAE,CAAC,EACnE,OAAO,EAAC,EAAE,EACV,MAAM,EAAE,yBAAyB,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;gBACpD,yHAAyH;gBACzH,SAAS,EAAC,wCAAwC,GAClD,IACE,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { useActionQuery } from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { IconAlertTriangle } from \"@tabler/icons-react\";\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport {\n fetchEmailPreview,\n type EmailPreview,\n} from \"../client/transactional-emails\";\nimport { resolveEmailPreviewAssets } from \"../lib/transactional-email-preview\";\nimport { Alert, AlertDescription, AlertTitle } from \"./ui/alert\";\nimport { Skeleton } from \"./ui/skeleton\";\n\n/**\n * The \"core\" app id means the email was read from Dispatch's own local\n * catalog (see transactional-email.tsx), not a cross-app fetch, so its\n * preview must render the same way — Dispatch always has the definition\n * registered locally and a cross-app fetch would have no real appPath to hit.\n */\nfunction useEmailPreviewQuery(appId: string, appPath: string, id: string) {\n const isCore = appId === \"core\";\n const local = useActionQuery<EmailPreview>(\n \"render-transactional-email-preview\",\n { id },\n { enabled: isCore, retry: false },\n );\n const remote = useQuery({\n queryKey: [\"transactional-email-preview\", appPath, id],\n queryFn: () => fetchEmailPreview(appPath, id),\n enabled: !isCore,\n retry: false,\n });\n return isCore ? local : remote;\n}\n\nexport function EmailPreviewPane({\n appId,\n appPath,\n id,\n name,\n}: {\n appId: string;\n appPath: string;\n id: string;\n name: string;\n}) {\n const t = useT();\n const preview = useEmailPreviewQuery(appId, appPath, id);\n\n if (preview.isError) {\n return (\n <Alert variant=\"destructive\">\n <IconAlertTriangle className=\"size-4\" />\n <AlertTitle>\n {t(\"dispatch.transactionalEmail.previewFailed\")}\n </AlertTitle>\n <AlertDescription>\n {preview.error instanceof Error\n ? preview.error.message\n : String(preview.error)}\n </AlertDescription>\n </Alert>\n );\n }\n if (preview.isLoading || !preview.data) {\n return <Skeleton className=\"h-96 w-full\" />;\n }\n return (\n <div className=\"space-y-3\">\n <div>\n <div className=\"text-xs text-muted-foreground\">\n {t(\"dispatch.transactionalEmail.subject\")}\n </div>\n <div className=\"text-sm font-medium text-foreground\">\n {preview.data.subject}\n </div>\n </div>\n {/* sandbox=\"\" (no allow-scripts) keeps arbitrary email HTML from\n running script in the Dispatch origin. */}\n <iframe\n title={t(\"dispatch.transactionalEmail.previewFrameTitle\", { name })}\n sandbox=\"\"\n srcDoc={resolveEmailPreviewAssets(preview.data.html)}\n // guard:allow-raw-color — the frame previews email HTML, which renders on white in mail clients regardless of app theme.\n className=\"h-96 w-full rounded-xl border bg-white\"\n />\n </div>\n );\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function resolveEmailPreviewAssets(html: string): string;
2
+ //# sourceMappingURL=transactional-email-preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactional-email-preview.d.ts","sourceRoot":"","sources":["../../src/lib/transactional-email-preview.ts"],"names":[],"mappings":"AAEA,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG9D"}
@@ -0,0 +1,6 @@
1
+ const DEFAULT_EMAIL_LOGO_SOURCE = "cid:agent-native-logo";
2
+ export function resolveEmailPreviewAssets(html) {
3
+ // Browser srcdoc previews do not have the MIME parts that resolve email CIDs.
4
+ return html.replaceAll(DEFAULT_EMAIL_LOGO_SOURCE, "/favicon.png");
5
+ }
6
+ //# sourceMappingURL=transactional-email-preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactional-email-preview.js","sourceRoot":"","sources":["../../src/lib/transactional-email-preview.ts"],"names":[],"mappings":"AAAA,MAAM,yBAAyB,GAAG,uBAAuB,CAAC;AAE1D,MAAM,UAAU,yBAAyB,CAAC,IAAY;IACpD,8EAA8E;IAC9E,OAAO,IAAI,CAAC,UAAU,CAAC,yBAAyB,EAAE,cAAc,CAAC,CAAC;AACpE,CAAC","sourcesContent":["const DEFAULT_EMAIL_LOGO_SOURCE = \"cid:agent-native-logo\";\n\nexport function resolveEmailPreviewAssets(html: string): string {\n // Browser srcdoc previews do not have the MIME parts that resolve email CIDs.\n return html.replaceAll(DEFAULT_EMAIL_LOGO_SOURCE, \"/favicon.png\");\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transactional-email-preview.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactional-email-preview.test.d.ts","sourceRoot":"","sources":["../../src/lib/transactional-email-preview.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { resolveEmailPreviewAssets } from "./transactional-email-preview.js";
3
+ describe("resolveEmailPreviewAssets", () => {
4
+ it("uses the canonical logo for browser previews", () => {
5
+ expect(resolveEmailPreviewAssets('<img src="cid:agent-native-logo" alt="Agent-Native" />')).toBe('<img src="/favicon.png" alt="Agent-Native" />');
6
+ });
7
+ it("leaves explicit brand logos unchanged", () => {
8
+ const html = '<img src="https://example.com/logo.png" />';
9
+ expect(resolveEmailPreviewAssets(html)).toBe(html);
10
+ });
11
+ });
12
+ //# sourceMappingURL=transactional-email-preview.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactional-email-preview.test.js","sourceRoot":"","sources":["../../src/lib/transactional-email-preview.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CACJ,yBAAyB,CACvB,wDAAwD,CACzD,CACF,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,IAAI,GAAG,4CAA4C,CAAC;QAE1D,MAAM,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\n\nimport { resolveEmailPreviewAssets } from \"./transactional-email-preview\";\n\ndescribe(\"resolveEmailPreviewAssets\", () => {\n it(\"uses the canonical logo for browser previews\", () => {\n expect(\n resolveEmailPreviewAssets(\n '<img src=\"cid:agent-native-logo\" alt=\"Agent-Native\" />',\n ),\n ).toBe('<img src=\"/favicon.png\" alt=\"Agent-Native\" />');\n });\n\n it(\"leaves explicit brand logos unchanged\", () => {\n const html = '<img src=\"https://example.com/logo.png\" />';\n\n expect(resolveEmailPreviewAssets(html)).toBe(html);\n });\n});\n"]}
@@ -1,14 +1,14 @@
1
1
  import { type LoaderFunctionArgs } from "react-router";
2
2
  export declare function meta(): ({
3
- title: string;
4
3
  name?: undefined;
5
4
  property?: undefined;
6
5
  content?: undefined;
6
+ title: string;
7
7
  } | {
8
8
  title?: undefined;
9
+ property?: undefined;
9
10
  name: string;
10
11
  content: string;
11
- property?: undefined;
12
12
  } | {
13
13
  title?: undefined;
14
14
  name?: undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/dispatch",
3
- "version": "0.31.26",
3
+ "version": "0.31.27-nightly-20260827111940",
4
4
  "description": "Dispatch — workspace control plane for agent-native apps. Vault, integrations, destinations, scheduled jobs, and cross-app delegation, shipped as a single drop-in package.",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -101,10 +101,10 @@
101
101
  "typescript-7": "npm:typescript@^7.0.2",
102
102
  "vite": "8.1.0",
103
103
  "vitest": "^4.1.5",
104
- "@agent-native/core": "0.175.5"
104
+ "@agent-native/core": "0.175.6-nightly-20260827111940"
105
105
  },
106
106
  "peerDependencies": {
107
- "@agent-native/core": ">=0.8.0",
107
+ "@agent-native/core": "0.175.6-nightly-20260827111940",
108
108
  "react": ">=19.2.7",
109
109
  "react-dom": ">=19.2.7",
110
110
  "react-router": ">=8"
@@ -7,6 +7,7 @@ import {
7
7
  fetchEmailPreview,
8
8
  type EmailPreview,
9
9
  } from "../client/transactional-emails";
10
+ import { resolveEmailPreviewAssets } from "../lib/transactional-email-preview";
10
11
  import { Alert, AlertDescription, AlertTitle } from "./ui/alert";
11
12
  import { Skeleton } from "./ui/skeleton";
12
13
 
@@ -79,7 +80,7 @@ export function EmailPreviewPane({
79
80
  <iframe
80
81
  title={t("dispatch.transactionalEmail.previewFrameTitle", { name })}
81
82
  sandbox=""
82
- srcDoc={preview.data.html}
83
+ srcDoc={resolveEmailPreviewAssets(preview.data.html)}
83
84
  // guard:allow-raw-color — the frame previews email HTML, which renders on white in mail clients regardless of app theme.
84
85
  className="h-96 w-full rounded-xl border bg-white"
85
86
  />
@@ -0,0 +1,19 @@
1
+ import { describe, expect, it } from "vitest";
2
+
3
+ import { resolveEmailPreviewAssets } from "./transactional-email-preview";
4
+
5
+ describe("resolveEmailPreviewAssets", () => {
6
+ it("uses the canonical logo for browser previews", () => {
7
+ expect(
8
+ resolveEmailPreviewAssets(
9
+ '<img src="cid:agent-native-logo" alt="Agent-Native" />',
10
+ ),
11
+ ).toBe('<img src="/favicon.png" alt="Agent-Native" />');
12
+ });
13
+
14
+ it("leaves explicit brand logos unchanged", () => {
15
+ const html = '<img src="https://example.com/logo.png" />';
16
+
17
+ expect(resolveEmailPreviewAssets(html)).toBe(html);
18
+ });
19
+ });
@@ -0,0 +1,6 @@
1
+ const DEFAULT_EMAIL_LOGO_SOURCE = "cid:agent-native-logo";
2
+
3
+ export function resolveEmailPreviewAssets(html: string): string {
4
+ // Browser srcdoc previews do not have the MIME parts that resolve email CIDs.
5
+ return html.replaceAll(DEFAULT_EMAIL_LOGO_SOURCE, "/favicon.png");
6
+ }