@agent-native/core 0.139.0 → 0.141.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 (94) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  3. package/corpus/templates/analytics/changelog/2026-08-05-historical-analytics-rollups-stay-complete-and-atomic.md +6 -0
  4. package/corpus/templates/analytics/server/lib/dashboard-report.ts +0 -2
  5. package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +11 -6
  6. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +8 -18
  7. package/corpus/templates/analytics/server/plugins/db.ts +174 -0
  8. package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +38 -38
  9. package/corpus/templates/calendar/changelog/2026-08-05-out-of-office-blocks-now-open-from-their-scheduled-time-rang.md +6 -0
  10. package/corpus/templates/calendar/server/lib/booking-emails.ts +70 -154
  11. package/corpus/templates/calendar/server/lib/event-guest-notifications.ts +28 -64
  12. package/corpus/templates/clips/actions/get-recording-player-data.ts +1 -0
  13. package/corpus/templates/clips/actions/invite-member.ts +16 -39
  14. package/corpus/templates/clips/app/components/player/comments-panel.tsx +2 -3
  15. package/corpus/templates/clips/app/components/player/reaction-emojis.ts +10 -0
  16. package/corpus/templates/clips/app/components/player/reactions-tray.tsx +2 -2
  17. package/corpus/templates/clips/app/components/player/video-player.tsx +20 -6
  18. package/corpus/templates/clips/app/routes/embed.$shareId.tsx +33 -0
  19. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +5 -1
  20. package/corpus/templates/clips/app/routes/share.$shareId.tsx +27 -1
  21. package/corpus/templates/clips/changelog/2026-08-05-comment-and-video-reaction-pickers-now-include-eyes-and-mind.md +6 -0
  22. package/corpus/templates/clips/changelog/2026-08-05-fresh-recordings-now-open-with-the-complete-video.md +6 -0
  23. package/corpus/templates/clips/server/lib/transactional-email-templates.ts +0 -24
  24. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +1 -0
  25. package/corpus/templates/content/server/lib/comment-notifications.ts +26 -57
  26. package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +16 -3
  27. package/corpus/templates/forms/server/lib/response-email.ts +0 -2
  28. package/corpus/templates/plan/actions/request-plan-access.ts +12 -33
  29. package/corpus/templates/plan/server/lib/comment-notifications.ts +27 -53
  30. package/corpus/templates/slides/server/lib/comment-notifications.ts +21 -44
  31. package/dist/a2a/handlers.js +9 -10
  32. package/dist/collab/routes.d.ts +1 -1
  33. package/dist/db/client.js +8 -8
  34. package/dist/db/migrations.js +39 -19
  35. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  36. package/dist/localization/default-messages.d.ts +0 -45
  37. package/dist/localization/default-messages.js +0 -45
  38. package/dist/notifications/routes.d.ts +5 -5
  39. package/dist/observability/routes.d.ts +3 -3
  40. package/dist/org/handlers.js +1 -8
  41. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  42. package/dist/provider-api/actions/provider-api.d.ts +12 -12
  43. package/dist/secrets/routes.d.ts +9 -9
  44. package/dist/server/action-discovery.js +0 -22
  45. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  46. package/dist/server/auth.js +3 -1
  47. package/dist/server/better-auth-instance.js +2 -17
  48. package/dist/server/email.d.ts +0 -9
  49. package/dist/server/email.js +3 -44
  50. package/dist/server/index.d.ts +0 -1
  51. package/dist/server/index.js +0 -1
  52. package/dist/server/transcribe-voice.d.ts +1 -1
  53. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +3 -2
  54. package/docs/content/authentication.mdx +25 -19
  55. package/package.json +2 -1
  56. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +3 -2
  57. package/corpus/templates/analytics/server/lib/emails.ts +0 -51
  58. package/corpus/templates/analytics/server/plugins/transactional-emails.ts +0 -5
  59. package/corpus/templates/calendar/server/lib/emails.ts +0 -167
  60. package/corpus/templates/calendar/server/plugins/transactional-emails.ts +0 -5
  61. package/corpus/templates/clips/server/lib/emails.ts +0 -256
  62. package/corpus/templates/clips/server/plugins/transactional-email-catalog.ts +0 -5
  63. package/corpus/templates/content/server/lib/emails.ts +0 -70
  64. package/corpus/templates/content/server/plugins/transactional-emails.ts +0 -5
  65. package/corpus/templates/dispatch/app/routes/transactional-email.$appId.$id.tsx +0 -4
  66. package/corpus/templates/dispatch/app/routes/transactional-email.tsx +0 -4
  67. package/corpus/templates/forms/server/lib/emails.ts +0 -52
  68. package/corpus/templates/forms/server/plugins/transactional-emails.ts +0 -5
  69. package/corpus/templates/plan/server/lib/emails.ts +0 -67
  70. package/corpus/templates/plan/server/plugins/transactional-emails.ts +0 -5
  71. package/corpus/templates/slides/server/lib/emails.ts +0 -40
  72. package/corpus/templates/slides/server/plugins/transactional-emails.ts +0 -5
  73. package/dist/email-catalog/actions/list-email-activity.d.ts +0 -6
  74. package/dist/email-catalog/actions/list-email-activity.js +0 -15
  75. package/dist/email-catalog/actions/list-email-engagement.d.ts +0 -6
  76. package/dist/email-catalog/actions/list-email-engagement.js +0 -15
  77. package/dist/email-catalog/actions/list-email-log.d.ts +0 -8
  78. package/dist/email-catalog/actions/list-email-log.js +0 -22
  79. package/dist/email-catalog/actions/list-transactional-emails.d.ts +0 -23
  80. package/dist/email-catalog/actions/list-transactional-emails.js +0 -61
  81. package/dist/email-catalog/actions/render-transactional-email-preview.d.ts +0 -10
  82. package/dist/email-catalog/actions/render-transactional-email-preview.js +0 -24
  83. package/dist/email-catalog/authorize.d.ts +0 -2
  84. package/dist/email-catalog/authorize.js +0 -10
  85. package/dist/email-catalog/log.d.ts +0 -57
  86. package/dist/email-catalog/log.js +0 -117
  87. package/dist/email-catalog/provider-metrics.d.ts +0 -34
  88. package/dist/email-catalog/provider-metrics.js +0 -165
  89. package/dist/email-catalog/registry.d.ts +0 -79
  90. package/dist/email-catalog/registry.js +0 -71
  91. package/dist/email-catalog/schema.d.ts +0 -212
  92. package/dist/email-catalog/schema.js +0 -49
  93. package/dist/email-catalog/system-emails.d.ts +0 -14
  94. package/dist/email-catalog/system-emails.js +0 -68
@@ -1,256 +0,0 @@
1
- /**
2
- * Catalog entries for the transactional emails Clips sends.
3
- *
4
- * Registered from `server/plugins/transactional-emails.ts` so Dispatch can list
5
- * and preview them without the app having sent anything yet.
6
- *
7
- * Every entry except the organization invite renders through
8
- * `renderClipsTransactionalEmail`, so a preview shows the real template rather
9
- * than a copy of it.
10
- */
11
-
12
- import { defineTransactionalEmail } from "@agent-native/core/email-catalog";
13
-
14
- import { renderClipsInviteEmail } from "../../actions/invite-member.js";
15
- import {
16
- CLIPS_ACTIVITY_COMMENT_EMAIL_ID,
17
- CLIPS_ACTIVITY_REACTION_EMAIL_ID,
18
- CLIPS_FIRST_AGENT_VIEW_EMAIL_ID,
19
- CLIPS_FIRST_IMPORT_EMAIL_ID,
20
- CLIPS_FIRST_VIEW_EMAIL_ID,
21
- CLIPS_MONTHLY_RECAP_EMAIL_ID,
22
- CLIPS_TWO_CLIPS_EMAIL_ID,
23
- CLIPS_UNVIEWED_REMINDER_EMAIL_ID,
24
- renderClipsTransactionalEmail,
25
- type ClipsTransactionalEmailInput,
26
- type ClipsTransactionalEmailRenderOptions,
27
- } from "./transactional-email-templates.js";
28
-
29
- /** Obviously-fake sample data — these render in a preview pane, never send. */
30
- const PREVIEW_OPTIONS: ClipsTransactionalEmailRenderOptions = {
31
- appUrl: "https://example.com",
32
- };
33
- const SAMPLE_RECORDING_ID = "rec_sample";
34
- const SAMPLE_TITLE = "Onboarding walkthrough";
35
- const SAMPLE_TO = "sam.rivera@example.com";
36
-
37
- function preview(input: ClipsTransactionalEmailInput) {
38
- return renderClipsTransactionalEmail(input, PREVIEW_OPTIONS);
39
- }
40
-
41
- export const CLIPS_ORGANIZATION_INVITE_EMAIL_ID = "clips.organization-invite";
42
-
43
- /**
44
- * How the shared Clips sender resolves From and Reply-To for every kind it
45
- * renders, so each entry can say so without restating the mechanism.
46
- */
47
- const CLIPS_SENDER =
48
- 'From is the configured EMAIL_FROM with the display name "Agent-Native Clips"; on first-party agent-native.com deployments it becomes clips@agent-native.com. Reply-to is hello@agent-native.com.';
49
-
50
- let registered = false;
51
-
52
- export function registerClipsEmails(): void {
53
- if (registered) return;
54
- registered = true;
55
-
56
- defineTransactionalEmail({
57
- id: CLIPS_FIRST_VIEW_EMAIL_ID,
58
- name: "First view on a Clip",
59
- trigger:
60
- "The background transactional-email sweep finds the first counted view of a Clip by someone other than its owner, recorded after transactional email was switched on. One per Clip.",
61
- recipientLabel: "Clip owner",
62
- recipient:
63
- "The Clip's owner. Suppressed recipient addresses are skipped, and the send is dropped if the owner is no longer the recording's owner at send time.",
64
- senderLabel: "Agent-Native Clips",
65
- sender: CLIPS_SENDER,
66
- preview: () =>
67
- preview({
68
- kind: "first-view",
69
- to: SAMPLE_TO,
70
- recordingId: SAMPLE_RECORDING_ID,
71
- title: SAMPLE_TITLE,
72
- viewerEmail: "alex.chen@example.com",
73
- }),
74
- });
75
-
76
- defineTransactionalEmail({
77
- id: CLIPS_UNVIEWED_REMINDER_EMAIL_ID,
78
- name: "Unviewed Clip reminder",
79
- trigger:
80
- "A direct share is 48 hours old and the recipient still has no counted view of that Clip. Re-checked at send time, so a view in the meantime cancels it.",
81
- recipientLabel: "Shared-with address",
82
- recipient:
83
- "The address the Clip was directly shared with. Requires the share to still exist.",
84
- senderLabel: "Sharer via Clips",
85
- sender:
86
- 'Same as the other Clips emails, except the display name becomes "<sharer> (via Agent-Native Clips)" and reply-to is the sharer\'s own address when it is a valid address, falling back to hello@agent-native.com.',
87
- preview: () =>
88
- preview({
89
- kind: "unviewed-reminder",
90
- to: SAMPLE_TO,
91
- recordingId: SAMPLE_RECORDING_ID,
92
- title: SAMPLE_TITLE,
93
- senderEmail: "dana.hill@example.com",
94
- senderName: "Dana Hill",
95
- }),
96
- });
97
-
98
- defineTransactionalEmail({
99
- id: CLIPS_FIRST_AGENT_VIEW_EMAIL_ID,
100
- name: "First agent read of a Clip",
101
- trigger:
102
- "An AI agent reads one of an owner's Clips for the first time since transactional email was switched on. One per owner, not per Clip.",
103
- recipientLabel: "Clip owner",
104
- recipient:
105
- "The owner of the Clip the agent read. Re-checked at send time against the owner's actual first agent view.",
106
- senderLabel: "Agent-Native Clips",
107
- sender: CLIPS_SENDER,
108
- preview: () =>
109
- preview({
110
- kind: "first-agent-view",
111
- to: SAMPLE_TO,
112
- recordingId: SAMPLE_RECORDING_ID,
113
- title: SAMPLE_TITLE,
114
- agentName: "Claude Code",
115
- }),
116
- });
117
-
118
- defineTransactionalEmail({
119
- id: CLIPS_FIRST_IMPORT_EMAIL_ID,
120
- name: "First imported video is ready",
121
- trigger:
122
- "An owner's first imported (rather than recorded) video finishes processing and becomes ready. One per owner.",
123
- recipientLabel: "Clip owner",
124
- recipient:
125
- "The owner of the imported recording, re-checked at send time so a later import does not resend.",
126
- senderLabel: "Agent-Native Clips",
127
- sender: CLIPS_SENDER,
128
- preview: () =>
129
- preview({
130
- kind: "first-import",
131
- to: SAMPLE_TO,
132
- recordingId: SAMPLE_RECORDING_ID,
133
- title: "Quarterly demo recording",
134
- }),
135
- });
136
-
137
- defineTransactionalEmail({
138
- id: CLIPS_MONTHLY_RECAP_EMAIL_ID,
139
- name: "Monthly Clips recap",
140
- trigger:
141
- "Once per owner per calendar month, from 14:00 UTC on the 1st, for owners whose Clips had any human views or agent reads in the closed month. Metrics and the top Clip are recomputed at send time.",
142
- recipientLabel: "Clip owner",
143
- recipient:
144
- "The Clip owner whose audience the recap reports. Suppressed addresses are skipped.",
145
- senderLabel: "Agent-Native Clips",
146
- sender: CLIPS_SENDER,
147
- preview: () =>
148
- preview({
149
- kind: "monthly-recap",
150
- to: SAMPLE_TO,
151
- month: "2025-02",
152
- humanViews: 42,
153
- agentSessions: 7,
154
- topClip: {
155
- recordingId: SAMPLE_RECORDING_ID,
156
- title: SAMPLE_TITLE,
157
- thumbnailUrl: "https://example.com/thumbnails/sample.png",
158
- durationMs: 214_000,
159
- recordedAt: "2025-02-11T16:00:00.000Z",
160
- humanViews: 18,
161
- agentSessions: 4,
162
- },
163
- copy: {
164
- heroLine: "Your clips were watched 42 times. 7 agents read them.",
165
- completionNote: "68% average completion · most stopped at 2:31",
166
- agentBreakdown: "4 from Claude Code · 3 unidentified",
167
- },
168
- }),
169
- });
170
-
171
- defineTransactionalEmail({
172
- id: CLIPS_TWO_CLIPS_EMAIL_ID,
173
- name: "Two Clips received",
174
- trigger:
175
- "A one-time nudge once someone who owns no Clips of their own has had two distinct Clips directly shared with them. The summary line is AI-generated before the job is released to send.",
176
- recipientLabel: "Shared-with address",
177
- recipient:
178
- "The shared-with address. Dropped at send time if they now own a Clip or no longer hold both shares.",
179
- senderLabel: "Agent-Native Clips",
180
- sender: CLIPS_SENDER,
181
- preview: () =>
182
- preview({
183
- kind: "two-clips",
184
- to: SAMPLE_TO,
185
- generatedSummary:
186
- "Two teammates walked you through the new onboarding flow.",
187
- }),
188
- });
189
-
190
- defineTransactionalEmail({
191
- id: CLIPS_ACTIVITY_COMMENT_EMAIL_ID,
192
- name: "Clip comment",
193
- trigger:
194
- "Someone comments or replies on a Clip. Subject and copy differ slightly for a reply; both send under this id.",
195
- recipientLabel: "Owner and thread authors",
196
- recipient:
197
- "The recording owner, plus every prior author in the thread when the comment is a reply. The list is re-checked against the recording's live ACL and filtered by each user's `emailNotifications` preference; the comment's own author never receives it.",
198
- senderLabel: "Agent-Native Clips",
199
- sender: CLIPS_SENDER,
200
- preview: () =>
201
- preview({
202
- kind: "activity-comment",
203
- to: SAMPLE_TO,
204
- recordingId: SAMPLE_RECORDING_ID,
205
- title: SAMPLE_TITLE,
206
- authorEmail: "alex.chen@example.com",
207
- authorName: "Alex Chen",
208
- content: "The step at 1:20 is the part new hires always miss.",
209
- videoTimestampMs: 80_000,
210
- isReply: false,
211
- }),
212
- });
213
-
214
- defineTransactionalEmail({
215
- id: CLIPS_ACTIVITY_REACTION_EMAIL_ID,
216
- name: "Clip reaction",
217
- trigger: "A viewer reacts with an emoji on a Clip.",
218
- recipientLabel: "Clip owner",
219
- recipient:
220
- "The recording owner plus any extra recipients the caller passes, re-checked against the recording's live ACL and filtered by each user's `emailNotifications` preference. The reacting viewer never receives it.",
221
- senderLabel: "Agent-Native Clips",
222
- sender: CLIPS_SENDER,
223
- preview: () =>
224
- preview({
225
- kind: "activity-reaction",
226
- to: SAMPLE_TO,
227
- recordingId: SAMPLE_RECORDING_ID,
228
- title: SAMPLE_TITLE,
229
- emoji: "🎉",
230
- authorEmail: "alex.chen@example.com",
231
- authorName: "Alex Chen",
232
- videoTimestampMs: 45_000,
233
- }),
234
- });
235
-
236
- defineTransactionalEmail({
237
- id: CLIPS_ORGANIZATION_INVITE_EMAIL_ID,
238
- name: "Organization invitation",
239
- trigger:
240
- "An organization admin runs `invite-member`. Any earlier pending invite for the same address is cancelled first, so a re-invite sends a fresh email with a new token.",
241
- recipientLabel: "Invited address",
242
- recipient:
243
- "The address passed to the action, exactly as typed. One email per invite.",
244
- senderLabel: "Default sender",
245
- sender:
246
- "The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`, so unlike the other Clips emails it does not send as Agent-Native Clips.",
247
- preview: () =>
248
- renderClipsInviteEmail({
249
- appName: "Clips",
250
- orgName: "Northwind Design",
251
- inviter: "dana.hill@example.com",
252
- role: "member",
253
- inviteUrl: "https://example.com/invite/sample-token",
254
- }),
255
- });
256
- }
@@ -1,5 +0,0 @@
1
- import { registerClipsEmails } from "../lib/emails.js";
2
-
3
- export default function registerTransactionalEmailCatalog(): void {
4
- registerClipsEmails();
5
- }
@@ -1,70 +0,0 @@
1
- /**
2
- * Catalog entries for the transactional emails Documents sends.
3
- *
4
- * Registered from `server/plugins/transactional-emails.ts` so Dispatch can list
5
- * and preview them without the app having sent anything yet.
6
- */
7
-
8
- import { defineTransactionalEmail } from "@agent-native/core/email-catalog";
9
-
10
- import { renderDocumentCommentEmail } from "./comment-notifications.js";
11
-
12
- /** Obviously-fake sample data — these render in a preview pane, never send. */
13
- const SAMPLE_TITLE = "Q3 launch brief";
14
- const SAMPLE_URL = "https://example.com/page/doc_sample";
15
- const SAMPLE_COMMENT =
16
- "Can we tighten the second paragraph? It repeats the intro.";
17
-
18
- export const CONTENT_DOCUMENT_COMMENT_EMAIL_ID = "content.document-comment";
19
- export const CONTENT_DOCUMENT_MENTION_EMAIL_ID = "content.document-mention";
20
-
21
- let registered = false;
22
-
23
- export function registerContentEmails(): void {
24
- if (registered) return;
25
- registered = true;
26
-
27
- defineTransactionalEmail({
28
- id: CONTENT_DOCUMENT_COMMENT_EMAIL_ID,
29
- name: "Document comment",
30
- trigger:
31
- "Someone posts a comment or a thread reply on a document. Sent to recipients who were not mentioned in it; the copy and subject differ slightly for a reply.",
32
- recipientLabel: "Owner and thread authors",
33
- recipient:
34
- "The document owner, plus every prior author in the thread when the new comment is a reply. The list is re-checked against the document's live ACL and filtered by each user's `emailNotifications` preference; the comment's own author never receives it.",
35
- senderLabel: "Default sender",
36
- sender:
37
- "The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`.",
38
- preview: () =>
39
- renderDocumentCommentEmail({
40
- actor: "Sam Rivera",
41
- title: SAMPLE_TITLE,
42
- url: SAMPLE_URL,
43
- content: SAMPLE_COMMENT,
44
- isReply: false,
45
- wasMentioned: false,
46
- }),
47
- });
48
-
49
- defineTransactionalEmail({
50
- id: CONTENT_DOCUMENT_MENTION_EMAIL_ID,
51
- name: "Document mention",
52
- trigger:
53
- "A comment or reply mentions someone by email. Sent instead of the plain comment notification to each mentioned recipient.",
54
- recipientLabel: "Mentioned users",
55
- recipient:
56
- "The mentioned addresses supplied by the caller, re-checked against the document's live ACL and filtered by each user's `emailNotifications` preference.",
57
- senderLabel: "Default sender",
58
- sender:
59
- "The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`.",
60
- preview: () =>
61
- renderDocumentCommentEmail({
62
- actor: "Sam Rivera",
63
- title: SAMPLE_TITLE,
64
- url: SAMPLE_URL,
65
- content: SAMPLE_COMMENT,
66
- isReply: false,
67
- wasMentioned: true,
68
- }),
69
- });
70
- }
@@ -1,5 +0,0 @@
1
- import { registerContentEmails } from "../lib/emails.js";
2
-
3
- export default function registerTransactionalEmails(): void {
4
- registerContentEmails();
5
- }
@@ -1,4 +0,0 @@
1
- export {
2
- default,
3
- meta,
4
- } from "@agent-native/dispatch/routes/pages/transactional-email.$appId.$id";
@@ -1,4 +0,0 @@
1
- export {
2
- default,
3
- meta,
4
- } from "@agent-native/dispatch/routes/pages/transactional-email";
@@ -1,52 +0,0 @@
1
- /**
2
- * Catalog entries for the transactional emails Forms sends.
3
- *
4
- * Registered from `server/plugins/transactional-emails.ts` so Dispatch can list
5
- * and preview them without the app having sent anything yet.
6
- */
7
-
8
- import { defineTransactionalEmail } from "@agent-native/core/email-catalog";
9
-
10
- import { renderNewResponseEmail } from "./response-email.js";
11
-
12
- export const FORMS_NEW_RESPONSE_EMAIL_ID = "forms.new-response";
13
-
14
- let registered = false;
15
-
16
- export function registerFormsEmails(): void {
17
- if (registered) return;
18
- registered = true;
19
-
20
- defineTransactionalEmail({
21
- id: FORMS_NEW_RESPONSE_EMAIL_ID,
22
- name: "New form response",
23
- trigger:
24
- "A response is submitted and persisted for a form whose settings have `emailOnNewResponses` enabled. Delivery is best-effort: a send failure never rejects the submission.",
25
- recipientLabel: "Form owner",
26
- recipient:
27
- "The form's `ownerEmail`, and only that address — the respondent is never emailed. Skipped when the form has no owner address.",
28
- senderLabel: "Default sender",
29
- sender:
30
- "The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`, so a reply goes to the sending mailbox rather than to the respondent.",
31
- preview: () =>
32
- renderNewResponseEmail({
33
- formTitle: "Beta feedback",
34
- fields: [
35
- { id: "name", type: "text", label: "Name", required: true },
36
- { id: "email", type: "email", label: "Email", required: true },
37
- {
38
- id: "notes",
39
- type: "textarea",
40
- label: "What should we fix first?",
41
- required: false,
42
- },
43
- ],
44
- data: {
45
- name: "Sam Rivera",
46
- email: "sam.rivera@example.com",
47
- notes: "The export button is hard to find on mobile.",
48
- },
49
- submittedAt: "2025-03-04T17:20:00.000Z",
50
- }),
51
- });
52
- }
@@ -1,5 +0,0 @@
1
- import { registerFormsEmails } from "../lib/emails.js";
2
-
3
- export default function registerTransactionalEmails(): void {
4
- registerFormsEmails();
5
- }
@@ -1,67 +0,0 @@
1
- /**
2
- * Catalog entries for the transactional emails Plan sends.
3
- *
4
- * Registered from `server/plugins/transactional-emails.ts` so Dispatch can list
5
- * and preview them without the app having sent anything yet.
6
- */
7
-
8
- import { defineTransactionalEmail } from "@agent-native/core/email-catalog";
9
-
10
- import {
11
- PLAN_ACCESS_REQUEST_EMAIL_ID,
12
- renderPlanAccessRequestEmail,
13
- } from "../../actions/request-plan-access.js";
14
- import {
15
- PLAN_COMMENT_EMAIL_ID,
16
- renderPlanCommentEmail,
17
- } from "./comment-notifications.js";
18
-
19
- let registered = false;
20
-
21
- export function registerPlanEmails(): void {
22
- if (registered) return;
23
- registered = true;
24
-
25
- defineTransactionalEmail({
26
- id: PLAN_COMMENT_EMAIL_ID,
27
- name: "Plan comment",
28
- trigger:
29
- "A human (never the agent) posts a comment or reply on a plan or recap. The subject changes for a reply and the body changes with why the recipient was picked; all variants send under this id.",
30
- recipientLabel: "Owner, mentions, authors",
31
- recipient:
32
- "The plan owner, everyone mentioned in the comment, and — for a reply — every other human author in the same thread. The comment's own author, synthetic QA addresses, and the owner when the comment mentions the source author are all dropped. One email per remaining address.",
33
- senderLabel: "Default sender",
34
- sender:
35
- "The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`.",
36
- preview: () =>
37
- renderPlanCommentEmail({
38
- actor: "Sam Rivera",
39
- app: "Agent-Native Plan",
40
- planTitle: "Checkout rewrite",
41
- planUrl: "https://example.com/plans/plan_sample",
42
- message: "Can we split the migration into two deploys?",
43
- isReply: false,
44
- reason: "plan-owner",
45
- }),
46
- });
47
-
48
- defineTransactionalEmail({
49
- id: PLAN_ACCESS_REQUEST_EMAIL_ID,
50
- name: "Plan access request",
51
- trigger:
52
- "A signed-in user who cannot resolve access calls `request-plan-access` on a private plan URL. Skipped when email is not configured or the requester is the owner.",
53
- recipientLabel: "Plan owner",
54
- recipient:
55
- "The plan's `ownerEmail` column. Anonymous public viewers and guest author identities cannot reach this path.",
56
- senderLabel: "Default sender",
57
- sender:
58
- "The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`, so the owner cannot reply straight to the requester.",
59
- preview: () =>
60
- renderPlanAccessRequestEmail({
61
- requesterName: "Sam Rivera",
62
- requesterEmail: "sam.rivera@example.com",
63
- planTitle: "Checkout rewrite",
64
- url: "https://example.com/plans/plan_sample",
65
- }),
66
- });
67
- }
@@ -1,5 +0,0 @@
1
- import { registerPlanEmails } from "../lib/emails.js";
2
-
3
- export default function registerTransactionalEmails(): void {
4
- registerPlanEmails();
5
- }
@@ -1,40 +0,0 @@
1
- /**
2
- * Catalog entries for the transactional emails Slides sends.
3
- *
4
- * Registered from `server/plugins/transactional-emails.ts` so Dispatch can list
5
- * and preview them without the app having sent anything yet.
6
- */
7
-
8
- import { defineTransactionalEmail } from "@agent-native/core/email-catalog";
9
-
10
- import { renderDeckCommentEmail } from "./comment-notifications.js";
11
-
12
- export const SLIDES_DECK_COMMENT_EMAIL_ID = "slides.deck-comment";
13
-
14
- let registered = false;
15
-
16
- export function registerSlidesEmails(): void {
17
- if (registered) return;
18
- registered = true;
19
-
20
- defineTransactionalEmail({
21
- id: SLIDES_DECK_COMMENT_EMAIL_ID,
22
- name: "Deck comment",
23
- trigger:
24
- "Someone posts a comment or a thread reply on a slide. Subject and copy differ slightly for a reply; both send under this id.",
25
- recipientLabel: "Deck owner and authors",
26
- recipient:
27
- "The deck owner, plus every prior author in the thread when the new comment is a reply. The list is re-checked against the deck's live ACL and filtered by each user's `emailNotifications` preference; the comment's own author never receives it.",
28
- senderLabel: "Default sender",
29
- sender:
30
- "The configured default sender. This call site sets no `from`, `fromName`, `replyTo`, or `appSender`.",
31
- preview: () =>
32
- renderDeckCommentEmail({
33
- actor: "Sam Rivera",
34
- title: "Series A narrative",
35
- url: "https://example.com/decks/deck_sample?slide=3",
36
- content: "Slide 3 needs the updated revenue chart before Thursday.",
37
- isReply: false,
38
- }),
39
- });
40
- }
@@ -1,5 +0,0 @@
1
- import { registerSlidesEmails } from "../lib/emails.js";
2
-
3
- export default function registerTransactionalEmails(): void {
4
- registerSlidesEmails();
5
- }
@@ -1,6 +0,0 @@
1
- declare const _default: import("../../action.js").ActionDefinition<{
2
- templateId: string;
3
- limit?: unknown;
4
- }, import("../provider-metrics.js").ProviderMetricsResult<import("../provider-metrics.js").EmailActivityEntry[]>>;
5
- export default _default;
6
- //# sourceMappingURL=list-email-activity.d.ts.map
@@ -1,15 +0,0 @@
1
- import { z } from "zod";
2
- import { defineAction } from "../../action.js";
3
- import { authorizeTransactionalEmailRead } from "../authorize.js";
4
- import { fetchEmailActivity } from "../provider-metrics.js";
5
- export default defineAction({
6
- description: "List recent provider activity for one registered transactional email in this app. Organization admin only.",
7
- schema: z.object({
8
- templateId: z.string().min(1),
9
- limit: z.coerce.number().int().min(1).max(1000).default(50),
10
- }),
11
- http: { method: "GET" },
12
- authorize: ({ templateId }) => authorizeTransactionalEmailRead([templateId]),
13
- run: async ({ templateId, limit }) => fetchEmailActivity({ templateId, limit }),
14
- });
15
- //# sourceMappingURL=list-email-activity.js.map
@@ -1,6 +0,0 @@
1
- declare const _default: import("../../action.js").ActionDefinition<{
2
- templateIds: string[];
3
- windowDays?: unknown;
4
- }, import("../provider-metrics.js").ProviderMetricsResult<import("../provider-metrics.js").EmailEngagement[]>>;
5
- export default _default;
6
- //# sourceMappingURL=list-email-engagement.d.ts.map
@@ -1,15 +0,0 @@
1
- import { z } from "zod";
2
- import { defineAction } from "../../action.js";
3
- import { authorizeTransactionalEmailRead } from "../authorize.js";
4
- import { fetchEmailEngagement } from "../provider-metrics.js";
5
- export default defineAction({
6
- description: "Read provider engagement metrics for registered transactional emails in this app. Organization admin only.",
7
- schema: z.object({
8
- templateIds: z.array(z.string().min(1)).max(100),
9
- windowDays: z.coerce.number().int().min(1).max(365).default(30),
10
- }),
11
- http: { method: "POST" },
12
- authorize: ({ templateIds }) => authorizeTransactionalEmailRead(templateIds),
13
- run: async ({ templateIds, windowDays }) => fetchEmailEngagement(templateIds, windowDays),
14
- });
15
- //# sourceMappingURL=list-email-engagement.js.map
@@ -1,8 +0,0 @@
1
- declare const _default: import("../../action.js").ActionDefinition<{
2
- templateId?: string;
3
- limit?: unknown;
4
- }, {
5
- entries: import("../log.js").EmailLogEntry[];
6
- }>;
7
- export default _default;
8
- //# sourceMappingURL=list-email-log.d.ts.map
@@ -1,22 +0,0 @@
1
- import { z } from "zod";
2
- import { defineAction } from "../../action.js";
3
- import { getAppSlug } from "../../server/app-name.js";
4
- import { authorizeTransactionalEmailRead } from "../authorize.js";
5
- import { listEmailLog } from "../log.js";
6
- export default defineAction({
7
- description: "List recent transactional email sends from this app, newest first, optionally filtered to one registered email id.",
8
- schema: z.object({
9
- templateId: z.string().optional(),
10
- limit: z.coerce.number().int().min(1).max(500).default(100),
11
- }),
12
- http: { method: "GET" },
13
- authorize: ({ templateId }) => authorizeTransactionalEmailRead(templateId ? [templateId] : []),
14
- run: async ({ templateId, limit }) => ({
15
- entries: await listEmailLog({
16
- app: getAppSlug() ?? "unknown",
17
- templateId,
18
- limit,
19
- }),
20
- }),
21
- });
22
- //# sourceMappingURL=list-email-log.js.map
@@ -1,23 +0,0 @@
1
- declare const _default: import("../../action.js").ActionDefinition<{
2
- windowDays?: unknown;
3
- }, {
4
- app: string;
5
- windowDays: number;
6
- statsAvailable: boolean;
7
- statsError: string;
8
- emails: {
9
- id: string;
10
- app: string;
11
- name: string;
12
- trigger: string;
13
- recipient: string;
14
- recipientLabel: string;
15
- sender: string;
16
- senderLabel: string;
17
- sent: number;
18
- failed: number;
19
- lastSentAt: number;
20
- }[];
21
- }>;
22
- export default _default;
23
- //# sourceMappingURL=list-transactional-emails.d.ts.map