@agent-native/core 0.78.9 → 0.79.1

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 (180) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +17 -0
  3. package/corpus/core/docs/content/actions.md +4 -2
  4. package/corpus/core/docs/content/agent-surfaces.md +9 -0
  5. package/corpus/core/docs/content/extensions.md +10 -0
  6. package/corpus/core/docs/content/generative-ui.md +217 -0
  7. package/corpus/core/docs/content/key-concepts.md +2 -2
  8. package/corpus/core/docs/content/mcp-apps.md +3 -5
  9. package/corpus/core/docs/content/native-chat-ui.md +9 -5
  10. package/corpus/core/docs/content/tracking.md +9 -3
  11. package/corpus/core/package.json +1 -1
  12. package/corpus/core/src/action-ui.ts +1 -0
  13. package/corpus/core/src/agent/production-agent.ts +8 -0
  14. package/corpus/core/src/client/analytics.ts +195 -12
  15. package/corpus/core/src/client/chat/index.ts +1 -0
  16. package/corpus/core/src/client/chat/tool-call-display.tsx +5 -2
  17. package/corpus/core/src/client/chat/widgets/InlineExtensionWidget.tsx +139 -0
  18. package/corpus/core/src/client/chat/widgets/builtin-tool-renderers.tsx +27 -1
  19. package/corpus/core/src/client/conversation/AgentConversation.tsx +38 -0
  20. package/corpus/core/src/client/conversation/code-agent-transcript.ts +9 -0
  21. package/corpus/core/src/client/conversation/types.ts +4 -0
  22. package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +27 -5
  23. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +26 -5
  24. package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +654 -0
  25. package/corpus/core/src/client/extensions/iframe-bridge.ts +30 -0
  26. package/corpus/core/src/client/extensions/index.ts +5 -0
  27. package/corpus/core/src/client/index.ts +1 -0
  28. package/corpus/core/src/client/session-replay.ts +89 -14
  29. package/corpus/core/src/code-agents/transcript-normalizer.ts +14 -0
  30. package/corpus/core/src/extensions/actions.ts +218 -1
  31. package/corpus/core/src/extensions/html-shell.ts +70 -3
  32. package/corpus/core/src/extensions/routes.ts +12 -4
  33. package/corpus/core/src/index.browser.ts +1 -0
  34. package/corpus/core/src/index.ts +1 -0
  35. package/corpus/core/src/server/agent-chat-plugin.ts +21 -9
  36. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +13 -0
  37. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/references/api.md +2 -0
  38. package/corpus/core/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +115 -0
  39. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +198 -59
  40. package/corpus/templates/analytics/AGENTS.md +12 -0
  41. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +1105 -0
  42. package/corpus/templates/analytics/actions/dashboard-panel-order.ts +169 -0
  43. package/corpus/templates/analytics/actions/get-sql-dashboard.ts +89 -6
  44. package/corpus/templates/analytics/actions/mutate-dashboard.ts +333 -0
  45. package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +214 -0
  46. package/corpus/templates/analytics/actions/send-dashboard-report-now.ts +48 -21
  47. package/corpus/templates/analytics/actions/update-dashboard.ts +193 -100
  48. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +11 -0
  49. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -1
  50. package/corpus/templates/analytics/app/global.css +81 -10
  51. package/corpus/templates/analytics/app/i18n-data.ts +249 -4
  52. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +3 -3
  53. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +41 -1
  54. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/EmailReportDialog.tsx +1 -1
  55. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +4 -4
  56. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +48 -18
  57. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +32 -0
  58. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +204 -70
  59. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +1101 -227
  60. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +160 -133
  61. package/corpus/templates/analytics/changelog/2026-06-26-agents-can-now-edit-dashboards-through-a-typed-mutation-scri.md +6 -0
  62. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-bar-chart-hovers-stay-subtle-in-dark-mode.md +6 -0
  63. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-chart-moves-are-now-handled-by-panel-id-making-sim.md +6 -0
  64. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-charts-drag-smoothly-with-stable-cards-inactive-ch.md +6 -0
  65. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-charts-show-a-refresh-spinner-while-keeping-existi.md +6 -0
  66. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-edits-stay-stable-while-chart-order-and-deletions-.md +6 -0
  67. package/corpus/templates/analytics/changelog/2026-06-26-dashboard-email-reports-queue-immediate-sends.md +6 -0
  68. package/corpus/templates/analytics/changelog/2026-06-26-explorer-dashboards-now-drag-charts-with-a-stable-preview-an.md +6 -0
  69. package/corpus/templates/analytics/changelog/2026-06-26-session-replay-playback-can-now-be-toggled-by-clicking-the-r.md +6 -0
  70. package/corpus/templates/analytics/changelog/2026-06-26-session-replays-now-open-from-the-full-row-and-play-with-tim.md +6 -0
  71. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +21 -0
  72. package/corpus/templates/analytics/server/lib/dashboard-report.ts +41 -17
  73. package/corpus/templates/analytics/server/plugins/agent-chat.ts +5 -0
  74. package/dist/action-ui.d.ts +1 -0
  75. package/dist/action-ui.d.ts.map +1 -1
  76. package/dist/action-ui.js +1 -0
  77. package/dist/action-ui.js.map +1 -1
  78. package/dist/agent/production-agent.d.ts.map +1 -1
  79. package/dist/agent/production-agent.js +6 -0
  80. package/dist/agent/production-agent.js.map +1 -1
  81. package/dist/client/analytics.d.ts.map +1 -1
  82. package/dist/client/analytics.js +173 -12
  83. package/dist/client/analytics.js.map +1 -1
  84. package/dist/client/chat/index.d.ts +1 -1
  85. package/dist/client/chat/index.d.ts.map +1 -1
  86. package/dist/client/chat/index.js +1 -1
  87. package/dist/client/chat/index.js.map +1 -1
  88. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  89. package/dist/client/chat/tool-call-display.js +3 -1
  90. package/dist/client/chat/tool-call-display.js.map +1 -1
  91. package/dist/client/chat/widgets/InlineExtensionWidget.d.ts +17 -0
  92. package/dist/client/chat/widgets/InlineExtensionWidget.d.ts.map +1 -0
  93. package/dist/client/chat/widgets/InlineExtensionWidget.js +85 -0
  94. package/dist/client/chat/widgets/InlineExtensionWidget.js.map +1 -0
  95. package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
  96. package/dist/client/chat/widgets/builtin-tool-renderers.js +15 -2
  97. package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
  98. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  99. package/dist/client/conversation/AgentConversation.js +33 -0
  100. package/dist/client/conversation/AgentConversation.js.map +1 -1
  101. package/dist/client/conversation/code-agent-transcript.js +8 -0
  102. package/dist/client/conversation/code-agent-transcript.js.map +1 -1
  103. package/dist/client/conversation/types.d.ts +4 -0
  104. package/dist/client/conversation/types.d.ts.map +1 -1
  105. package/dist/client/conversation/types.js.map +1 -1
  106. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  107. package/dist/client/extensions/EmbeddedExtension.js +29 -1
  108. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  109. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  110. package/dist/client/extensions/ExtensionViewer.js +28 -1
  111. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  112. package/dist/client/extensions/InlineExtensionFrame.d.ts +25 -0
  113. package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -0
  114. package/dist/client/extensions/InlineExtensionFrame.js +488 -0
  115. package/dist/client/extensions/InlineExtensionFrame.js.map +1 -0
  116. package/dist/client/extensions/iframe-bridge.d.ts +2 -0
  117. package/dist/client/extensions/iframe-bridge.d.ts.map +1 -1
  118. package/dist/client/extensions/iframe-bridge.js +23 -0
  119. package/dist/client/extensions/iframe-bridge.js.map +1 -1
  120. package/dist/client/extensions/index.d.ts +1 -0
  121. package/dist/client/extensions/index.d.ts.map +1 -1
  122. package/dist/client/extensions/index.js +1 -0
  123. package/dist/client/extensions/index.js.map +1 -1
  124. package/dist/client/index.d.ts +1 -1
  125. package/dist/client/index.d.ts.map +1 -1
  126. package/dist/client/index.js +1 -1
  127. package/dist/client/index.js.map +1 -1
  128. package/dist/client/session-replay.d.ts +11 -1
  129. package/dist/client/session-replay.d.ts.map +1 -1
  130. package/dist/client/session-replay.js +74 -14
  131. package/dist/client/session-replay.js.map +1 -1
  132. package/dist/code-agents/transcript-normalizer.d.ts +2 -0
  133. package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
  134. package/dist/code-agents/transcript-normalizer.js +8 -0
  135. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  136. package/dist/collab/awareness.d.ts +2 -2
  137. package/dist/collab/awareness.d.ts.map +1 -1
  138. package/dist/collab/routes.d.ts +1 -1
  139. package/dist/extensions/actions.d.ts.map +1 -1
  140. package/dist/extensions/actions.js +200 -1
  141. package/dist/extensions/actions.js.map +1 -1
  142. package/dist/extensions/html-shell.d.ts.map +1 -1
  143. package/dist/extensions/html-shell.js +70 -3
  144. package/dist/extensions/html-shell.js.map +1 -1
  145. package/dist/extensions/routes.d.ts.map +1 -1
  146. package/dist/extensions/routes.js +11 -4
  147. package/dist/extensions/routes.js.map +1 -1
  148. package/dist/index.browser.d.ts +1 -1
  149. package/dist/index.browser.d.ts.map +1 -1
  150. package/dist/index.browser.js +1 -1
  151. package/dist/index.browser.js.map +1 -1
  152. package/dist/index.d.ts +1 -1
  153. package/dist/index.d.ts.map +1 -1
  154. package/dist/index.js +1 -1
  155. package/dist/index.js.map +1 -1
  156. package/dist/notifications/routes.d.ts +3 -3
  157. package/dist/observability/routes.d.ts +3 -3
  158. package/dist/progress/routes.d.ts +1 -1
  159. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  160. package/dist/resources/handlers.d.ts +3 -3
  161. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  162. package/dist/server/agent-chat-plugin.js +21 -9
  163. package/dist/server/agent-chat-plugin.js.map +1 -1
  164. package/dist/server/agent-engine-api-key-route.d.ts +2 -2
  165. package/dist/server/transcribe-voice.d.ts +1 -1
  166. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +13 -0
  167. package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +2 -0
  168. package/dist/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +115 -0
  169. package/docs/content/actions.md +4 -2
  170. package/docs/content/agent-surfaces.md +9 -0
  171. package/docs/content/extensions.md +10 -0
  172. package/docs/content/generative-ui.md +217 -0
  173. package/docs/content/key-concepts.md +2 -2
  174. package/docs/content/mcp-apps.md +3 -5
  175. package/docs/content/native-chat-ui.md +9 -5
  176. package/docs/content/tracking.md +9 -3
  177. package/package.json +1 -1
  178. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +13 -0
  179. package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +2 -0
  180. package/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +115 -0
@@ -0,0 +1,214 @@
1
+ import { defineAction, embedApp } from "@agent-native/core";
2
+ import {
3
+ applyText,
4
+ hasCollabState,
5
+ seedFromText,
6
+ } from "@agent-native/core/collab";
7
+ import {
8
+ buildDeepLink,
9
+ getRequestOrgId,
10
+ getRequestUserEmail,
11
+ } from "@agent-native/core/server";
12
+ import { z } from "zod";
13
+
14
+ import { getDashboard, upsertDashboard } from "../server/lib/dashboards-store";
15
+ import {
16
+ compactDashboardResult,
17
+ movePanelsById,
18
+ type PanelOrderTarget,
19
+ } from "./dashboard-panel-order";
20
+
21
+ function parseJsonArrayString(value: string, fieldName: string): string[] {
22
+ let parsed: unknown;
23
+ try {
24
+ parsed = JSON.parse(value);
25
+ } catch (err: any) {
26
+ throw new Error(`${fieldName} must be a JSON array: ${err.message}`);
27
+ }
28
+ if (!Array.isArray(parsed)) {
29
+ throw new Error(`${fieldName} must be a JSON array`);
30
+ }
31
+ return parsed.map((item) => String(item));
32
+ }
33
+
34
+ const panelIdsSchema = z.union([
35
+ z.array(z.string()),
36
+ z.string().transform((value) => parseJsonArrayString(value, "panelIds")),
37
+ ]);
38
+
39
+ function resolveScope() {
40
+ const orgId = getRequestOrgId() || null;
41
+ const email = getRequestUserEmail();
42
+ if (!email) throw new Error("no authenticated user");
43
+ return { orgId, email };
44
+ }
45
+
46
+ function resolveDashboardId(args: { dashboardId?: string; id?: string }) {
47
+ const dashboardId = args.dashboardId || args.id;
48
+ if (!dashboardId) {
49
+ throw new Error("provide `dashboardId` (or legacy `id`).");
50
+ }
51
+ return dashboardId;
52
+ }
53
+
54
+ function resolveTarget(args: {
55
+ position?: "top" | "bottom";
56
+ index?: number;
57
+ beforePanelId?: string;
58
+ afterPanelId?: string;
59
+ }): PanelOrderTarget {
60
+ const explicitTargets = [
61
+ args.index !== undefined,
62
+ !!args.beforePanelId,
63
+ !!args.afterPanelId,
64
+ ].filter(Boolean).length;
65
+ if (explicitTargets > 1) {
66
+ throw new Error(
67
+ "provide only one of `index`, `beforePanelId`, or `afterPanelId`.",
68
+ );
69
+ }
70
+ if (args.beforePanelId) return { beforePanelId: args.beforePanelId };
71
+ if (args.afterPanelId) return { afterPanelId: args.afterPanelId };
72
+ if (args.index !== undefined) return { index: args.index };
73
+ return { position: args.position ?? "top" };
74
+ }
75
+
76
+ async function syncToCollab(
77
+ dashboardId: string,
78
+ config: Record<string, unknown>,
79
+ ): Promise<void> {
80
+ const docId = `dash-${dashboardId}`;
81
+ const configStr = JSON.stringify(config);
82
+ try {
83
+ const exists = await hasCollabState(docId);
84
+ if (exists) {
85
+ await applyText(docId, configStr, "content", "agent");
86
+ } else {
87
+ await seedFromText(docId, configStr);
88
+ }
89
+ } catch {
90
+ // SQL remains the source of truth; live collab sync is best-effort.
91
+ }
92
+ }
93
+
94
+ export default defineAction({
95
+ agentTool: false,
96
+ description:
97
+ "Move one or more existing SQL dashboard panels by panel id in ONE atomic save. Use this for requests like 'move these charts to the top', 'put panel A before panel B', or 'send this section to the bottom'. This avoids brittle /panels/<index> JSON-pointer math and keeps omitted panels in their existing relative order. Returns compact proof: panelCount, movedPanelIds, firstPanelIds, and panelOrder.",
98
+ schema: z.object({
99
+ dashboardId: z
100
+ .string()
101
+ .optional()
102
+ .describe("Dashboard id, e.g. 'agent-native-templates-first-party'."),
103
+ id: z
104
+ .string()
105
+ .optional()
106
+ .describe("Legacy alias for dashboardId. Prefer dashboardId."),
107
+ panelIds: panelIdsSchema.describe(
108
+ "Panel ids to move as a group, in the order they should appear at the target. Accepts a native array, or a JSON string for shell/legacy callers.",
109
+ ),
110
+ position: z
111
+ .enum(["top", "bottom"])
112
+ .optional()
113
+ .describe(
114
+ "Move the group to the top or bottom when no explicit index/before/after target is provided. Defaults to top.",
115
+ ),
116
+ index: z
117
+ .number()
118
+ .int()
119
+ .nonnegative()
120
+ .optional()
121
+ .describe(
122
+ "Insert the moved group at this zero-based index after removing those panels from their old positions.",
123
+ ),
124
+ beforePanelId: z
125
+ .string()
126
+ .optional()
127
+ .describe(
128
+ "Insert the moved group immediately before this existing panel id.",
129
+ ),
130
+ afterPanelId: z
131
+ .string()
132
+ .optional()
133
+ .describe(
134
+ "Insert the moved group immediately after this existing panel id.",
135
+ ),
136
+ returnConfig: z
137
+ .boolean()
138
+ .optional()
139
+ .describe(
140
+ "If true, include the full dashboard config in the result. Defaults to false to keep tool output compact.",
141
+ ),
142
+ }),
143
+ http: { method: "POST" },
144
+ mcpApp: {
145
+ compactCatalog: true,
146
+ resource: embedApp({
147
+ title: "Dashboard preview",
148
+ description: "Open the reordered dashboard in the real Analytics UI.",
149
+ iframeTitle: "Agent-Native Analytics",
150
+ openLabel: "Open dashboard",
151
+ height: 680,
152
+ }),
153
+ },
154
+ run: async (args) => {
155
+ const dashboardId = resolveDashboardId(args);
156
+ const scope = resolveScope();
157
+ const ctx = { email: scope.email, orgId: scope.orgId };
158
+ const existing = await getDashboard(dashboardId, ctx);
159
+ if (!existing) {
160
+ throw new Error(
161
+ `dashboard "${dashboardId}" not found (or you don't have access).`,
162
+ );
163
+ }
164
+
165
+ const root = existing.config as Record<string, unknown>;
166
+ const orderResult = movePanelsById(
167
+ root,
168
+ args.panelIds,
169
+ resolveTarget(args),
170
+ );
171
+ await upsertDashboard(dashboardId, existing.kind, root, ctx);
172
+ await syncToCollab(dashboardId, root);
173
+
174
+ const compact = compactDashboardResult(root, orderResult.movedPanelIds);
175
+ return {
176
+ id: dashboardId,
177
+ dashboardId,
178
+ name: typeof root.name === "string" ? root.name : dashboardId,
179
+ ...compact,
180
+ appliedOps: 1,
181
+ insertIndex: orderResult.insertIndex,
182
+ skippedDuplicatePanelIds: orderResult.skippedDuplicatePanelIds,
183
+ summary:
184
+ `Moved ${orderResult.movedPanelIds.join(", ")} in dashboard "${dashboardId}". ` +
185
+ `First panels: ${compact.firstPanelIds.join(", ")}.`,
186
+ ...(args.returnConfig === true ? { config: root } : {}),
187
+ urlPath: `/dashboards/${dashboardId}`,
188
+ deepLink: buildDeepLink({
189
+ app: "analytics",
190
+ view: "adhoc",
191
+ params: { dashboardId },
192
+ }),
193
+ message:
194
+ `Dashboard "${dashboardId}" reordered. ` +
195
+ `First panels: ${compact.firstPanelIds.join(", ")}.`,
196
+ };
197
+ },
198
+ link: ({ result }) => {
199
+ const dashboardId =
200
+ result && typeof result === "object"
201
+ ? (result as { dashboardId?: string }).dashboardId
202
+ : undefined;
203
+ if (!dashboardId) return null;
204
+ return {
205
+ url: buildDeepLink({
206
+ app: "analytics",
207
+ view: "adhoc",
208
+ params: { dashboardId },
209
+ }),
210
+ label: "Open dashboard in Analytics",
211
+ view: "adhoc",
212
+ };
213
+ },
214
+ });
@@ -1,20 +1,58 @@
1
1
  import { defineAction } from "@agent-native/core";
2
2
  import {
3
+ getAppProductionUrl,
3
4
  getRequestOrgId,
4
5
  getRequestUserEmail,
5
6
  } from "@agent-native/core/server";
6
7
  import { z } from "zod";
7
8
 
8
- import { sendDashboardReportSubscription } from "../server/lib/dashboard-report";
9
+ import { runDashboardReportsOnce } from "../server/jobs/dashboard-report";
9
10
  import {
10
- claimDashboardReportSubscription,
11
11
  getDashboardReportSubscription,
12
- markDashboardReportResult,
12
+ queueDashboardReportSubscriptionNow,
13
13
  } from "../server/lib/dashboard-report-subscriptions";
14
14
 
15
+ function netlifyOwnsDashboardReportSweep(): boolean {
16
+ return process.env.NETLIFY === "true";
17
+ }
18
+
19
+ function appOrigin(): string {
20
+ return (
21
+ process.env.URL ||
22
+ process.env.DEPLOY_URL ||
23
+ getAppProductionUrl()
24
+ ).replace(/\/+$/, "");
25
+ }
26
+
27
+ async function triggerDashboardReportSweep(): Promise<{
28
+ mode: "netlify-background" | "inline-sweep";
29
+ triggerStatus?: number;
30
+ processed?: number;
31
+ failed?: number;
32
+ remaining?: number;
33
+ }> {
34
+ if (netlifyOwnsDashboardReportSweep()) {
35
+ const response = await fetch(
36
+ new URL("/.netlify/functions/dashboard-report-cron", `${appOrigin()}/`),
37
+ { method: "POST" },
38
+ );
39
+ if (!response.ok && response.status !== 202 && response.status !== 204) {
40
+ throw Object.assign(
41
+ new Error(
42
+ `Dashboard report background trigger failed with ${response.status}`,
43
+ ),
44
+ { statusCode: 502 },
45
+ );
46
+ }
47
+ return { mode: "netlify-background", triggerStatus: response.status };
48
+ }
49
+
50
+ return { mode: "inline-sweep", ...(await runDashboardReportsOnce()) };
51
+ }
52
+
15
53
  export default defineAction({
16
54
  description:
17
- "Send a dashboard email report subscription immediately to its saved recipients.",
55
+ "Queue a dashboard email report subscription to send immediately to its saved recipients.",
18
56
  schema: z.object({
19
57
  id: z.string().describe("Subscription ID to send now"),
20
58
  }),
@@ -34,27 +72,16 @@ export default defineAction({
34
72
  });
35
73
  }
36
74
 
37
- const claimed = await claimDashboardReportSubscription(sub.id, {
75
+ const queued = await queueDashboardReportSubscriptionNow(sub.id, {
38
76
  email,
39
77
  orgId,
40
78
  });
41
- if (!claimed) {
42
- throw Object.assign(new Error("Report subscription is already sending"), {
43
- statusCode: 409,
79
+ if (!queued) {
80
+ throw Object.assign(new Error("Report subscription not found"), {
81
+ statusCode: 404,
44
82
  });
45
83
  }
46
-
47
- try {
48
- const result = await sendDashboardReportSubscription(claimed);
49
- await markDashboardReportResult(claimed, "success");
50
- return { id: claimed.id, success: true, ...result };
51
- } catch (err: any) {
52
- await markDashboardReportResult(
53
- claimed,
54
- "error",
55
- err?.message ?? String(err),
56
- );
57
- throw err;
58
- }
84
+ const trigger = await triggerDashboardReportSweep();
85
+ return { id: queued.id, success: true, queued: true, ...trigger };
59
86
  },
60
87
  });