@mastra/react 1.2.5 → 1.2.6-alpha.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.
- package/CHANGELOG.md +10 -0
- package/dist/agent/signal-data.d.ts +3 -0
- package/dist/agent/signal-data.d.ts.map +1 -1
- package/dist/index.cjs +76 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +76 -38
- package/dist/index.js.map +1 -1
- package/dist/lib/mastra-db/accumulator.d.ts.map +1 -1
- package/dist/lib/mastra-db/fromCoreUserMessage.d.ts.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @mastra/react
|
|
2
2
|
|
|
3
|
+
## 1.2.6-alpha.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed binary file attachments missing during live streaming in `useChat` when `enableThreadSignals` is enabled. Attachments sent as `Uint8Array` or `ArrayBuffer` now render in the optimistic pending bubble and stay visible after the signal echo, without requiring a page refresh. ([#19439](https://github.com/mastra-ai/mastra/pull/19439))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`8a0d145`](https://github.com/mastra-ai/mastra/commit/8a0d145aadbdf7278665aceaaec364b35dd9bd94), [`bd2f1d2`](https://github.com/mastra-ai/mastra/commit/bd2f1d274d05e60e2366f005ea0d94d5cea0d5ff), [`21a0eb8`](https://github.com/mastra-ai/mastra/commit/21a0eb86746ba0b703acea360d4f84c6a5a493f2), [`de86fd7`](https://github.com/mastra-ai/mastra/commit/de86fd7119f0438381d1a642e3d258143c0b9c29), [`2745031`](https://github.com/mastra-ai/mastra/commit/2745031d1d4a4978f037092da371428c32e2842a), [`db650ce`](https://github.com/mastra-ai/mastra/commit/db650ce490348914e85b93651d83acdf8f2a4c31), [`6354eeb`](https://github.com/mastra-ai/mastra/commit/6354eeb32efa9f5f68f51dda394e90e2ee76f1fb)]:
|
|
10
|
+
- @mastra/core@1.51.1-alpha.0
|
|
11
|
+
- @mastra/client-js@1.32.1-alpha.0
|
|
12
|
+
|
|
3
13
|
## 1.2.5
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
+
export declare const uint8ArrayToBase64: (bytes: Uint8Array) => string;
|
|
1
2
|
export declare function convertSignalDataToBase64String(content: string | ArrayBuffer | Uint8Array): string;
|
|
3
|
+
/** Canonical DB `file` part `data` for optimistic UI and memory-shaped storage. */
|
|
4
|
+
export declare function encodeFilePartDataForStorage(data: string | URL | ArrayBuffer | Uint8Array, mimeType: string): string;
|
|
2
5
|
//# sourceMappingURL=signal-data.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal-data.d.ts","sourceRoot":"","sources":["../../src/agent/signal-data.ts"],"names":[],"mappings":"AAAA,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"signal-data.d.ts","sourceRoot":"","sources":["../../src/agent/signal-data.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,GAAI,OAAO,UAAU,KAAG,MAOtD,CAAC;AAEF,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAOlG;AAED,mFAAmF;AACnF,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,GAAG,WAAW,GAAG,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgBpH"}
|
package/dist/index.cjs
CHANGED
|
@@ -70,6 +70,37 @@ var MastraReactProvider = ({
|
|
|
70
70
|
);
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
+
// src/agent/signal-data.ts
|
|
74
|
+
var uint8ArrayToBase64 = (bytes) => {
|
|
75
|
+
const chunkSize = 32768;
|
|
76
|
+
let binary = "";
|
|
77
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
78
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
|
|
79
|
+
}
|
|
80
|
+
return btoa(binary);
|
|
81
|
+
};
|
|
82
|
+
function convertSignalDataToBase64String(content) {
|
|
83
|
+
if (typeof content === "string") {
|
|
84
|
+
return content;
|
|
85
|
+
}
|
|
86
|
+
const bytes = content instanceof ArrayBuffer ? new Uint8Array(content) : content;
|
|
87
|
+
return uint8ArrayToBase64(bytes);
|
|
88
|
+
}
|
|
89
|
+
function encodeFilePartDataForStorage(data, mimeType) {
|
|
90
|
+
if (typeof data === "string") {
|
|
91
|
+
return data;
|
|
92
|
+
}
|
|
93
|
+
if (data instanceof URL) {
|
|
94
|
+
return data.toString();
|
|
95
|
+
}
|
|
96
|
+
const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
|
|
97
|
+
const base64 = uint8ArrayToBase64(bytes);
|
|
98
|
+
if (base64.startsWith("data:")) {
|
|
99
|
+
return base64;
|
|
100
|
+
}
|
|
101
|
+
return `data:${mimeType};base64,${base64}`;
|
|
102
|
+
}
|
|
103
|
+
|
|
73
104
|
// src/lib/mastra-db/formatCompletionFeedback.ts
|
|
74
105
|
var formatBaseCompletionFeedback = (result, maxIterationReached, formatScorerHeading, incompleteMessage) => {
|
|
75
106
|
const lines = [];
|
|
@@ -120,14 +151,6 @@ var CLIENT_MESSAGE_ID_KEY = "clientMessageId";
|
|
|
120
151
|
|
|
121
152
|
// src/lib/mastra-db/accumulator.ts
|
|
122
153
|
var cloneMetadata = (metadata) => metadata ? { ...metadata } : {};
|
|
123
|
-
var uint8ArrayToBase64 = (bytes) => {
|
|
124
|
-
const chunkSize = 32768;
|
|
125
|
-
let binary = "";
|
|
126
|
-
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
127
|
-
binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));
|
|
128
|
-
}
|
|
129
|
-
return btoa(binary);
|
|
130
|
-
};
|
|
131
154
|
var withParts = (message, parts) => ({
|
|
132
155
|
...message,
|
|
133
156
|
content: {
|
|
@@ -324,22 +347,37 @@ var signalContentsToUserMessages = (contents, metadata) => {
|
|
|
324
347
|
}
|
|
325
348
|
if (typedPart.type === "image") {
|
|
326
349
|
const image = typedPart.image;
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
350
|
+
const mimeType = typeof typedPart.mediaType === "string" ? typedPart.mediaType : typeof typedPart.mimeType === "string" ? typedPart.mimeType : "image/*";
|
|
351
|
+
if (typeof image === "string" || image instanceof URL || image instanceof ArrayBuffer || image instanceof Uint8Array) {
|
|
352
|
+
return [
|
|
353
|
+
{
|
|
354
|
+
type: "file",
|
|
355
|
+
mimeType,
|
|
356
|
+
data: encodeFilePartDataForStorage(image, mimeType)
|
|
357
|
+
}
|
|
358
|
+
];
|
|
359
|
+
}
|
|
360
|
+
return [{ type: "file", mimeType, data: "" }];
|
|
334
361
|
}
|
|
335
362
|
if (typedPart.type === "file") {
|
|
336
363
|
const data = typedPart.data;
|
|
337
|
-
const
|
|
364
|
+
const mimeType = typeof typedPart.mediaType === "string" ? typedPart.mediaType : typeof typedPart.mimeType === "string" ? typedPart.mimeType : "application/octet-stream";
|
|
365
|
+
if (typeof data === "string" || data instanceof URL || data instanceof ArrayBuffer || data instanceof Uint8Array) {
|
|
366
|
+
return [
|
|
367
|
+
{
|
|
368
|
+
type: "file",
|
|
369
|
+
mimeType,
|
|
370
|
+
data: encodeFilePartDataForStorage(data, mimeType),
|
|
371
|
+
...typeof typedPart.filename === "string" ? { filename: typedPart.filename } : {}
|
|
372
|
+
}
|
|
373
|
+
];
|
|
374
|
+
}
|
|
375
|
+
const urlFallback = typeof typedPart.url === "string" ? typedPart.url : "";
|
|
338
376
|
return [
|
|
339
377
|
{
|
|
340
378
|
type: "file",
|
|
341
|
-
mimeType
|
|
342
|
-
data:
|
|
379
|
+
mimeType,
|
|
380
|
+
data: urlFallback,
|
|
343
381
|
...typeof typedPart.filename === "string" ? { filename: typedPart.filename } : {}
|
|
344
382
|
}
|
|
345
383
|
];
|
|
@@ -364,6 +402,15 @@ var signalContentsToUserMessages = (contents, metadata) => {
|
|
|
364
402
|
const parts = content.flatMap(toMessagePart);
|
|
365
403
|
return parts.length ? [makeUserMessage(parts)] : [];
|
|
366
404
|
};
|
|
405
|
+
var reconcilePendingUserEcho = (message, echoedContents, metadata, options) => {
|
|
406
|
+
const echoedMessages = signalContentsToUserMessages(echoedContents, metadata);
|
|
407
|
+
const echoedParts = echoedMessages[0]?.content.parts;
|
|
408
|
+
let reconciled = typeof options.signalId === "string" ? { ...message, id: options.signalId } : message;
|
|
409
|
+
if (echoedParts?.length) {
|
|
410
|
+
reconciled = { ...reconciled, content: { ...reconciled.content, parts: echoedParts } };
|
|
411
|
+
}
|
|
412
|
+
return options.keepClientMessageId ? clearPendingStatusKeepClientId(reconciled) : clearPendingStatus(reconciled);
|
|
413
|
+
};
|
|
367
414
|
var makeToolInvocationPart = (invocation) => ({
|
|
368
415
|
type: "tool-invocation",
|
|
369
416
|
toolInvocation: invocation
|
|
@@ -384,14 +431,19 @@ var accumulateChunk = ({ chunk, conversation, metadata }) => {
|
|
|
384
431
|
)) {
|
|
385
432
|
return finishStreamingAssistantMessage(
|
|
386
433
|
result.map(
|
|
387
|
-
(message) => message.content.metadata?.status === "pending" && message.content.metadata[CLIENT_MESSAGE_ID_KEY] === echoedClientMessageId ?
|
|
434
|
+
(message) => message.content.metadata?.status === "pending" && message.content.metadata[CLIENT_MESSAGE_ID_KEY] === echoedClientMessageId ? reconcilePendingUserEcho(message, chunk.data.contents, metadata, {
|
|
435
|
+
signalId: typeof signalId === "string" ? signalId : void 0,
|
|
436
|
+
keepClientMessageId: true
|
|
437
|
+
}) : message
|
|
388
438
|
)
|
|
389
439
|
);
|
|
390
440
|
}
|
|
391
441
|
if (typeof signalId === "string" && result.some((message) => message.id === signalId)) {
|
|
392
442
|
return finishStreamingAssistantMessage(
|
|
393
443
|
result.map(
|
|
394
|
-
(message) => message.id === signalId && message.content.metadata?.status === "pending" ?
|
|
444
|
+
(message) => message.id === signalId && message.content.metadata?.status === "pending" ? reconcilePendingUserEcho(message, chunk.data.contents, metadata, {
|
|
445
|
+
keepClientMessageId: false
|
|
446
|
+
}) : message
|
|
395
447
|
)
|
|
396
448
|
);
|
|
397
449
|
}
|
|
@@ -1678,19 +1730,18 @@ var coreUserMessageToParts = (coreUserMessage) => typeof coreUserMessage.content
|
|
|
1678
1730
|
return { type: "text", text: part.text };
|
|
1679
1731
|
}
|
|
1680
1732
|
case "image": {
|
|
1681
|
-
const
|
|
1733
|
+
const mimeType = part.mimeType ?? "image/*";
|
|
1682
1734
|
return {
|
|
1683
1735
|
type: "file",
|
|
1684
|
-
mimeType
|
|
1685
|
-
data
|
|
1736
|
+
mimeType,
|
|
1737
|
+
data: encodeFilePartDataForStorage(part.image, mimeType)
|
|
1686
1738
|
};
|
|
1687
1739
|
}
|
|
1688
1740
|
case "file": {
|
|
1689
|
-
const data = typeof part.data === "string" ? part.data : part.data instanceof URL ? part.data.toString() : "";
|
|
1690
1741
|
return {
|
|
1691
1742
|
type: "file",
|
|
1692
1743
|
mimeType: part.mimeType,
|
|
1693
|
-
data,
|
|
1744
|
+
data: encodeFilePartDataForStorage(part.data, part.mimeType),
|
|
1694
1745
|
...part.filename !== void 0 ? { filename: part.filename } : {}
|
|
1695
1746
|
};
|
|
1696
1747
|
}
|
|
@@ -1818,19 +1869,6 @@ var extractRunIdFromMessages = (messages) => {
|
|
|
1818
1869
|
return void 0;
|
|
1819
1870
|
};
|
|
1820
1871
|
|
|
1821
|
-
// src/agent/signal-data.ts
|
|
1822
|
-
function convertSignalDataToBase64String(content) {
|
|
1823
|
-
if (typeof content === "string") {
|
|
1824
|
-
return content;
|
|
1825
|
-
}
|
|
1826
|
-
const bytes = content instanceof ArrayBuffer ? new Uint8Array(content) : content;
|
|
1827
|
-
let binary = "";
|
|
1828
|
-
for (const byte of bytes) {
|
|
1829
|
-
binary += String.fromCharCode(byte);
|
|
1830
|
-
}
|
|
1831
|
-
return btoa(binary);
|
|
1832
|
-
}
|
|
1833
|
-
|
|
1834
1872
|
// src/agent/hooks.ts
|
|
1835
1873
|
var extractPendingToolApprovalIdsFromMessages = (messages) => {
|
|
1836
1874
|
const pendingToolApprovalIds = /* @__PURE__ */ new Set();
|