@magemetrics/core 0.12.2 → 0.14.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 (4) hide show
  1. package/README.md +220 -0
  2. package/dist/index.d.ts +1670 -137
  3. package/dist/index.js +1796 -430
  4. package/package.json +9 -9
package/README.md ADDED
@@ -0,0 +1,220 @@
1
+ # @magemetrics/core
2
+
3
+ Headless Magemetrics client for custom integrations.
4
+
5
+ `@magemetrics/core` is designed for customers who want to build their own UI while reusing Magemetrics authentication, flow APIs, chat transport, file uploads, and typed domain models.
6
+
7
+ ## What You Need
8
+
9
+ - `@magemetrics/core` for auth, flow APIs, chat transport, files, and types
10
+ - The AI SDK for chat state and streaming
11
+ - Your own UI layer in React, Svelte, Vue, or another framework
12
+
13
+ ## Create A Client
14
+
15
+ ```ts
16
+ import { MageMetricsClient } from "@magemetrics/core";
17
+
18
+ export const client = new MageMetricsClient({
19
+ apiUrl: "https://your-magemetrics-instance.com",
20
+ apiKey: "mm_live_...",
21
+ externalJwt: "customer-session-jwt",
22
+ });
23
+ ```
24
+
25
+ ## Start Or Resume A Flow
26
+
27
+ ```ts
28
+ const { flowId } = await client.api.createFlow({
29
+ query: "Show me revenue by country for the last 90 days",
30
+ });
31
+
32
+ const existingMessages = await client.api.getChatMessages(flowId);
33
+ const flow = await client.api.getFlow(flowId);
34
+ const reports = await client.api.getFlowDataReports(flowId);
35
+ const visualizations = await client.api.getFlowVisualizations(flowId);
36
+ ```
37
+
38
+ ## Connect The AI SDK
39
+
40
+ The simplest integration is to reuse the Magemetrics transport with an AI SDK `Chat` instance and hydrate it with stored history.
41
+
42
+ ```tsx
43
+ import { Chat, lastAssistantMessageIsCompleteWithToolCalls } from "@ai-sdk/react";
44
+ import { useChat } from "@ai-sdk/react";
45
+ import type { MMChatUIMessage } from "@magemetrics/core";
46
+ import { client } from "./client";
47
+
48
+ const chat = new Chat<MMChatUIMessage>({
49
+ id: `chat-${flowId}`,
50
+ transport: client.api.getChatTransport(flowId),
51
+ sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,
52
+ });
53
+
54
+ chat.setMessages(await client.api.getChatMessages(flowId));
55
+
56
+ const state = useChat({
57
+ chat,
58
+ });
59
+ ```
60
+
61
+ `sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls` is important to support interactive tools such as `askUserQuestion`.
62
+
63
+ ## Bootstrap The First Assistant Turn
64
+
65
+ `createFlow(...)` persists the first user message and returns `flowId`. The first assistant response starts when the chat stream is resumed.
66
+
67
+ After hydrating message history, if there is only one user message, trigger a one-time `regenerate()`:
68
+
69
+ ```tsx
70
+ import { useEffect, useRef } from "react";
71
+ import { hasOnlyInitialUserMessage } from "@magemetrics/core";
72
+
73
+ const hasStartedRef = useRef(false);
74
+
75
+ useEffect(() => {
76
+ if (
77
+ status === "ready" &&
78
+ hasOnlyInitialUserMessage(messages) &&
79
+ !hasStartedRef.current
80
+ ) {
81
+ hasStartedRef.current = true;
82
+ void regenerate();
83
+ }
84
+ }, [messages, status, regenerate]);
85
+ ```
86
+
87
+ ## Handle Frontend Tools
88
+
89
+ Magemetrics can stream tool parts alongside assistant text. The main frontend-executed tool today is `askUserQuestion`.
90
+
91
+ **Important:** You must handle `tool-askUserQuestion` and always send a tool output.
92
+ If your UI never calls `chat.addToolOutput(...)`, the conversation can stay blocked waiting for tool completion.
93
+
94
+ ```ts
95
+ import {
96
+ ASK_USER_QUESTION,
97
+ type AskUserQuestionInput,
98
+ type MMChatUIMessagePart,
99
+ } from "@magemetrics/core";
100
+
101
+ const renderPart = (part: MMChatUIMessagePart) => {
102
+ if (part.type !== `tool-${ASK_USER_QUESTION}`) {
103
+ return null;
104
+ }
105
+
106
+ if (part.state === "input-available") {
107
+ const input: AskUserQuestionInput = part.input;
108
+
109
+ return {
110
+ questions: input.questions,
111
+ submit: async (answers: Record<string, string>) => {
112
+ await chat.addToolOutput({
113
+ tool: ASK_USER_QUESTION,
114
+ toolCallId: part.toolCallId,
115
+ output: {
116
+ tool: ASK_USER_QUESTION,
117
+ result: { status: "success", answers },
118
+ },
119
+ });
120
+ },
121
+ cancel: async () => {
122
+ await chat.addToolOutput({
123
+ tool: ASK_USER_QUESTION,
124
+ toolCallId: part.toolCallId,
125
+ output: {
126
+ tool: ASK_USER_QUESTION,
127
+ result: {
128
+ status: "error",
129
+ message: "User dismissed the question form.",
130
+ },
131
+ },
132
+ });
133
+ },
134
+ };
135
+ }
136
+
137
+ return null;
138
+ };
139
+ ```
140
+
141
+ The transport marks tool submissions correctly and the AI SDK can resume the stream automatically after `chat.addToolOutput(...)`.
142
+
143
+ Required behavior for frontend tools:
144
+
145
+ 1. Detect `tool-askUserQuestion` parts.
146
+ 2. Render the question UI for `state === "input-available"`.
147
+ 3. Call `chat.addToolOutput(...)` for every tool call (submit and cancel paths).
148
+ 4. Keep `sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls` enabled so the stream resumes automatically.
149
+
150
+ ## Read Custom Data Parts
151
+
152
+ Messages can include custom streamed data parts in addition to text and tool calls.
153
+
154
+ - `quick-actions`: suggested follow-up prompts
155
+ - `report-status`: inline report generation status
156
+ - `node-added`: a new canvas node created during the run
157
+
158
+ The exported `MMChatUIMessage`, `MMChatUIMessagePart`, `QuickAction`, and `SignalWithReportId` types are designed for this.
159
+
160
+ ## Send Files
161
+
162
+ ```ts
163
+ import {
164
+ CHAT_FILE_ACCEPT,
165
+ toUploadedFileRefUrl,
166
+ type UploadedFile,
167
+ } from "@magemetrics/core";
168
+
169
+ const uploaded = await client.api.uploadFile(file);
170
+
171
+ const filePart = {
172
+ type: "file" as const,
173
+ filename: uploaded.filename,
174
+ mediaType: uploaded.mediaType,
175
+ url: toUploadedFileRefUrl(uploaded.uploadedFileId),
176
+ };
177
+ ```
178
+
179
+ For the first user request, attach uploaded files during flow creation:
180
+
181
+ ```ts
182
+ const uploaded = await client.api.uploadFile(file);
183
+
184
+ const { flowId } = await client.api.createFlow({
185
+ query: "Summarize this PDF",
186
+ uploadedFileIds: [uploaded.uploadedFileId],
187
+ });
188
+ ```
189
+
190
+ For later requests in an existing conversation, include the file part in the message you send through the AI SDK.
191
+
192
+ ## Typed Domain Data
193
+
194
+ `@magemetrics/core` also exports the main response types you need to build custom views:
195
+
196
+ - `FrontendFlow`
197
+ - `FrontendRecentFlows`
198
+ - `FrontendReport`
199
+ - `FrontendReportColumns`
200
+ - `FrontendReportExplainability`
201
+ - `FrontendVisualization`
202
+ - `FrontendVisualizationWithData`
203
+ - `PromptStarter`
204
+ - `FrontendRecommendations`
205
+
206
+ Use `isFrontendV2VisualizationWithData(...)` if you need to branch on visualization shape at runtime (you will never need to deal with older V1 versions).
207
+
208
+ ## Utilities
209
+
210
+ - `client.api.getPromptStarters(input?)`
211
+ - `client.api.getRecommendations(count)`
212
+ - `toSearchParams(...)` for report filtering and sorting
213
+ - `getMessageTextContent(...)` to extract plain text from an AI SDK message
214
+ - `hasOnlyInitialUserMessage(...)` to detect when a newly created flow still needs its first assistant turn
215
+
216
+ ## Notes
217
+
218
+ - `client.api.getChatTransport(flowId)` assumes the AI SDK stream protocol used by Magemetrics chat.
219
+ - `client.api.getChatMessages(flowId)` returns the redacted frontend-safe message history.
220
+ - Tool outputs exposed through chat are already redacted for frontend use. Use the exported `Redacted*` response types when rendering them.