@convex-dev/agent 0.2.8-alpha.2 → 0.2.8-alpha.3
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/dist/UIMessages.d.ts +2 -1
- package/dist/UIMessages.d.ts.map +1 -1
- package/dist/UIMessages.js +12 -17
- package/dist/UIMessages.js.map +1 -1
- package/dist/component/streams.d.ts +8 -8
- package/dist/component/streams.d.ts.map +1 -1
- package/dist/component/streams.js +18 -21
- package/dist/component/streams.js.map +1 -1
- package/dist/react/useStreamingUIMessages.d.ts.map +1 -1
- package/dist/react/useStreamingUIMessages.js +22 -17
- package/dist/react/useStreamingUIMessages.js.map +1 -1
- package/dist/react/useThreadMessages.d.ts.map +1 -1
- package/dist/react/useThreadMessages.js +3 -2
- package/dist/react/useThreadMessages.js.map +1 -1
- package/dist/react/useUIMessages.d.ts +10 -6
- package/dist/react/useUIMessages.d.ts.map +1 -1
- package/dist/react/useUIMessages.js +24 -34
- package/dist/react/useUIMessages.js.map +1 -1
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +7 -4
- package/dist/shared.js.map +1 -1
- package/package.json +1 -1
- package/src/UIMessages.ts +16 -21
- package/src/component/streams.ts +20 -21
- package/src/deltas.test.ts +311 -97
- package/src/react/useStreamingUIMessages.ts +34 -24
- package/src/react/useThreadMessages.ts +10 -5
- package/src/react/useUIMessages.test.ts +255 -0
- package/src/react/useUIMessages.ts +38 -52
- package/src/shared.ts +6 -4
- package/src/toUIMessages.test.ts +1 -1
|
@@ -67,51 +67,41 @@ import { useStreamingUIMessages } from "./useStreamingUIMessages.js";
|
|
|
67
67
|
export function useUIMessages(query, args, options) {
|
|
68
68
|
// These are full messages
|
|
69
69
|
const paginated = usePaginatedQuery(query, args, { initialNumItems: options.initialNumItems });
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (!m.streaming && m.status === "pending") {
|
|
74
|
-
// round down to the nearest 10 for some cache benefits
|
|
75
|
-
startOrder = m.order - (m.order % 10);
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
70
|
+
const startOrder = paginated.results.length
|
|
71
|
+
? Math.min(...paginated.results.map((m) => m.order))
|
|
72
|
+
: 0;
|
|
79
73
|
// These are streaming messages that will not include full messages.
|
|
80
74
|
const streamMessages = useStreamingUIMessages(query, !options.stream ||
|
|
81
75
|
args === "skip" ||
|
|
82
76
|
paginated.status === "LoadingFirstPage"
|
|
83
77
|
? "skip"
|
|
84
78
|
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
-
{ ...args, paginationOpts: { cursor: null, numItems: 0 } }, { startOrder });
|
|
79
|
+
{ ...args, paginationOpts: { cursor: null, numItems: 0 } }, { startOrder, skipStreamIds: options.skipStreamIds });
|
|
86
80
|
const merged = useMemo(() => {
|
|
87
|
-
const streamListMessages = streamMessages?.map((m) => ({
|
|
88
|
-
...m,
|
|
89
|
-
streaming: m.status === "streaming",
|
|
90
|
-
})) ?? [];
|
|
91
81
|
return {
|
|
92
82
|
...paginated,
|
|
93
|
-
results:
|
|
94
|
-
.map((m) => ({ ...m, streaming: false }))
|
|
95
|
-
// Note: this is intentionally after paginated results.
|
|
96
|
-
.concat(streamListMessages)).reduce((msgs, msg) => {
|
|
97
|
-
const last = msgs.at(-1);
|
|
98
|
-
if (!last) {
|
|
99
|
-
return [msg];
|
|
100
|
-
}
|
|
101
|
-
if (last.order !== msg.order || last.stepOrder !== msg.stepOrder) {
|
|
102
|
-
return [...msgs, msg];
|
|
103
|
-
}
|
|
104
|
-
if (last.status === "pending" &&
|
|
105
|
-
(msg.streaming || msg.status !== "pending")) {
|
|
106
|
-
// Let's prefer a streaming or finalized message over a pending
|
|
107
|
-
// one.
|
|
108
|
-
return [...msgs.slice(0, -1), msg];
|
|
109
|
-
}
|
|
110
|
-
// skip the new one if the previous one (listed) was finalized
|
|
111
|
-
return msgs;
|
|
112
|
-
}, []),
|
|
83
|
+
results: dedupeMessages(paginated.results, streamMessages ?? []),
|
|
113
84
|
};
|
|
114
85
|
}, [paginated, streamMessages]);
|
|
115
86
|
return merged;
|
|
116
87
|
}
|
|
88
|
+
export function dedupeMessages(messages, streamMessages) {
|
|
89
|
+
return sorted(messages.concat(streamMessages)).reduce((msgs, msg) => {
|
|
90
|
+
const last = msgs.at(-1);
|
|
91
|
+
if (!last) {
|
|
92
|
+
return [msg];
|
|
93
|
+
}
|
|
94
|
+
if (last.order !== msg.order || last.stepOrder !== msg.stepOrder) {
|
|
95
|
+
return [...msgs, msg];
|
|
96
|
+
}
|
|
97
|
+
if ((last.status === "pending" || last.status === "streaming") &&
|
|
98
|
+
msg.status !== "pending") {
|
|
99
|
+
// Let's prefer a streaming or finalized message over a pending
|
|
100
|
+
// one.
|
|
101
|
+
return [...msgs.slice(0, -1), msg];
|
|
102
|
+
}
|
|
103
|
+
// skip the new one if the previous one (listed) was finalized
|
|
104
|
+
return msgs;
|
|
105
|
+
}, []);
|
|
106
|
+
}
|
|
117
107
|
//# sourceMappingURL=useUIMessages.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUIMessages.js","sourceRoot":"","sources":["../../src/react/useUIMessages.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,EAIN,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAGN,MAAM,cAAc,CAAC;AAOtB,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAIhC,OAAO,
|
|
1
|
+
{"version":3,"file":"useUIMessages.js","sourceRoot":"","sources":["../../src/react/useUIMessages.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,EAIN,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAGN,MAAM,cAAc,CAAC;AAOtB,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAIhC,OAAO,EAAiC,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAuCrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,MAAM,UAAU,aAAa,CAI3B,KAAY,EACZ,IAAyC,EACzC,OAMC;IAED,0BAA0B;IAC1B,MAAM,SAAS,GAAG,iBAAiB,CACjC,KAAK,EACL,IAA0C,EAC1C,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CAC7C,CAAC;IAEF,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM;QACzC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC,CAAC;IACN,oEAAoE;IACpE,MAAM,cAAc,GAAG,sBAAsB,CAC3C,KAAgD,EAChD,CAAC,OAAO,CAAC,MAAM;QACb,IAAI,KAAK,MAAM;QACf,SAAS,CAAC,MAAM,KAAK,kBAAkB;QACvC,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,8DAA8D;YAC7D,EAAE,GAAG,IAAI,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAU,EACvE,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CACrD,CAAC;IAEF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE;QAC1B,OAAO;YACL,GAAG,SAAS;YACZ,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,OAAO,EAAE,cAAc,IAAI,EAAE,CAAC;SACjE,CAAC;IACJ,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC;IAEhC,OAAO,MAAsC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,cAAc,CAM5B,QAAa,EAAE,cAAmB;IAClC,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAClE,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,KAAK,GAAG,CAAC,SAAS,EAAE,CAAC;YACjE,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC;QACxB,CAAC;QACD,IACE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC;YAC1D,GAAG,CAAC,MAAM,KAAK,SAAS,EACxB,CAAC;YACD,+DAA+D;YAC/D,OAAO;YACP,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACrC,CAAC;QACD,8DAA8D;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC,EAAE,EAAS,CAAC,CAAC;AAChB,CAAC"}
|
package/dist/shared.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,WAOrD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAE3C,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,WAOrD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,sBAyB1D;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,sBAQ/D;AAED,eAAO,MAAM,qBAAqB;;;CAA0B,CAAC;AAE7D,wBAAgB,MAAM,CAAC,CAAC,SAAS;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EACnE,QAAQ,EAAE,CAAC,EAAE,EACb,KAAK,GAAE,KAAK,GAAG,MAAc,GAC5B,CAAC,EAAE,CAML;AAED,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAAC;AAEvE,wBAAgB,YAAY,CAAC,cAAc,EAAE,eAAe,GAAG,MAAM,CAUpE;AAED,wBAAgB,eAAe,CAAC,cAAc,EAAE,eAAe,GAAG,MAAM,CAKvE"}
|
package/dist/shared.js
CHANGED
|
@@ -19,10 +19,13 @@ export function extractText(message) {
|
|
|
19
19
|
if (typeof message.content === "string") {
|
|
20
20
|
return message.content;
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
.filter((c) => c.type === "text")
|
|
24
|
-
.
|
|
25
|
-
|
|
22
|
+
else {
|
|
23
|
+
const textParts = message.content.filter((c) => c.type === "text");
|
|
24
|
+
if (!textParts.length) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
return textParts.map((c) => c.text).join("");
|
|
28
|
+
}
|
|
26
29
|
case "system":
|
|
27
30
|
return message.content;
|
|
28
31
|
// we don't extract text from tool messages
|
package/dist/shared.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAE3C,MAAM,UAAU,MAAM,CAAC,OAA+B;IACpD,OAAO,CACL,OAAO,CAAC,IAAI,KAAK,MAAM;QACvB,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;YAC3B,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;YAC9B,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CACvD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAA+B;IACzD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,MAAM;YACT,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACxC,OAAO,OAAO,CAAC,OAAO,CAAC;YACzB,CAAC;YACD,OAAO,OAAO,CAAC,OAAO;iBACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;iBAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;iBAClB,IAAI,CAAC,EAAE,CAAC,CAAC;QACd,KAAK,WAAW;YACd,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACxC,OAAO,OAAO,CAAC,OAAO,CAAC;YACzB,CAAC;
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/UIMessages.ts
CHANGED
|
@@ -27,6 +27,8 @@ import type {
|
|
|
27
27
|
} from "./validators.js";
|
|
28
28
|
import { omit, pick } from "convex-helpers";
|
|
29
29
|
|
|
30
|
+
export type UIStatus = "streaming" | MessageStatus;
|
|
31
|
+
|
|
30
32
|
export type UIMessage<
|
|
31
33
|
METADATA = unknown,
|
|
32
34
|
DATA_PARTS extends UIDataTypes = UIDataTypes,
|
|
@@ -35,7 +37,7 @@ export type UIMessage<
|
|
|
35
37
|
key: string;
|
|
36
38
|
order: number;
|
|
37
39
|
stepOrder: number;
|
|
38
|
-
status:
|
|
40
|
+
status: UIStatus;
|
|
39
41
|
agentName?: string;
|
|
40
42
|
text: string;
|
|
41
43
|
_creationTime: number;
|
|
@@ -160,7 +162,7 @@ export function toUIMessages<
|
|
|
160
162
|
messages: (MessageDoc & ExtraFields<METADATA>)[],
|
|
161
163
|
): UIMessage<METADATA, DATA_PARTS, TOOLS>[] {
|
|
162
164
|
// Group assistant and tool messages together
|
|
163
|
-
const assistantGroups = groupAssistantMessages(messages);
|
|
165
|
+
const assistantGroups = groupAssistantMessages(sorted(messages));
|
|
164
166
|
|
|
165
167
|
const uiMessages: UIMessage<METADATA, DATA_PARTS, TOOLS>[] = [];
|
|
166
168
|
for (const group of assistantGroups) {
|
|
@@ -196,13 +198,10 @@ function groupAssistantMessages<METADATA = unknown>(
|
|
|
196
198
|
): Group<METADATA>[] {
|
|
197
199
|
const groups: Group<METADATA>[] = [];
|
|
198
200
|
|
|
199
|
-
// Sort messages by order and stepOrder first to handle out-of-order arrivals
|
|
200
|
-
const sortedMessages = sorted(messages);
|
|
201
|
-
|
|
202
201
|
let currentAssistantGroup: (MessageDoc & ExtraFields<METADATA>)[] = [];
|
|
203
202
|
let currentOrder: number | undefined;
|
|
204
203
|
|
|
205
|
-
for (const message of
|
|
204
|
+
for (const message of messages) {
|
|
206
205
|
const coreMessage = message.message && deserializeMessage(message.message);
|
|
207
206
|
if (!coreMessage) continue;
|
|
208
207
|
|
|
@@ -239,7 +238,6 @@ function groupAssistantMessages<METADATA = unknown>(
|
|
|
239
238
|
currentAssistantGroup.push(message);
|
|
240
239
|
|
|
241
240
|
// End group if this is an assistant message without tool calls
|
|
242
|
-
// But only if we're processing messages in order (which we are now due to sorting)
|
|
243
241
|
if (coreMessage.role === "assistant" && !message.tool) {
|
|
244
242
|
groups.push({
|
|
245
243
|
role: "assistant",
|
|
@@ -294,7 +292,7 @@ function createSystemUIMessage<
|
|
|
294
292
|
|
|
295
293
|
function extractTextFromMessageDoc(message: MessageDoc): string {
|
|
296
294
|
return (
|
|
297
|
-
|
|
295
|
+
(message.message && extractText(message.message)) || message.text || ""
|
|
298
296
|
);
|
|
299
297
|
}
|
|
300
298
|
|
|
@@ -373,9 +371,9 @@ function createAssistantUIMessage<
|
|
|
373
371
|
|
|
374
372
|
// Concatenate text from all messages in group
|
|
375
373
|
const allText = group
|
|
376
|
-
.map((msg) =>
|
|
374
|
+
.map((msg) => extractTextFromMessageDoc(msg))
|
|
377
375
|
.filter(Boolean)
|
|
378
|
-
.join("");
|
|
376
|
+
.join(" ");
|
|
379
377
|
|
|
380
378
|
// Get status from last message
|
|
381
379
|
const lastMessage = group[group.length - 1];
|
|
@@ -393,8 +391,7 @@ function createAssistantUIMessage<
|
|
|
393
391
|
const content = coreMessage.content;
|
|
394
392
|
const nonStringContent =
|
|
395
393
|
content && typeof content !== "string" ? content : [];
|
|
396
|
-
const text =
|
|
397
|
-
message.text || ((message.message && extractText(message.message)) ?? "");
|
|
394
|
+
const text = extractTextFromMessageDoc(message);
|
|
398
395
|
|
|
399
396
|
const partCommon = {
|
|
400
397
|
state: message.streaming ? ("streaming" as const) : ("done" as const),
|
|
@@ -465,6 +462,10 @@ function createAssistantUIMessage<
|
|
|
465
462
|
break;
|
|
466
463
|
}
|
|
467
464
|
case "tool-result": {
|
|
465
|
+
const output =
|
|
466
|
+
contentPart.output?.type === "json"
|
|
467
|
+
? contentPart.output.value
|
|
468
|
+
: contentPart.output;
|
|
468
469
|
const call = allParts.find(
|
|
469
470
|
(part) =>
|
|
470
471
|
part.type === `tool-${contentPart.toolName}` &&
|
|
@@ -475,13 +476,10 @@ function createAssistantUIMessage<
|
|
|
475
476
|
if (message.error) {
|
|
476
477
|
call.state = "output-error";
|
|
477
478
|
call.errorText = message.error;
|
|
478
|
-
call.output =
|
|
479
|
+
call.output = output;
|
|
479
480
|
} else {
|
|
480
481
|
call.state = "output-available";
|
|
481
|
-
call.output =
|
|
482
|
-
contentPart.output?.type === "json"
|
|
483
|
-
? contentPart.output.value
|
|
484
|
-
: contentPart.output;
|
|
482
|
+
call.output = output;
|
|
485
483
|
}
|
|
486
484
|
} else {
|
|
487
485
|
console.warn(
|
|
@@ -503,10 +501,7 @@ function createAssistantUIMessage<
|
|
|
503
501
|
toolCallId: contentPart.toolCallId,
|
|
504
502
|
state: "output-available",
|
|
505
503
|
input: undefined,
|
|
506
|
-
output
|
|
507
|
-
contentPart.output?.type === "json"
|
|
508
|
-
? contentPart.output.value
|
|
509
|
-
: contentPart.output,
|
|
504
|
+
output,
|
|
510
505
|
callProviderMetadata: message.providerMetadata,
|
|
511
506
|
} satisfies ToolUIPart<TOOLS>);
|
|
512
507
|
}
|
package/src/component/streams.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { v } from "convex/values";
|
|
|
3
3
|
import {
|
|
4
4
|
type MessageWithMetadataInternal,
|
|
5
5
|
type StreamDelta,
|
|
6
|
+
type StreamMessage,
|
|
6
7
|
vStreamDelta,
|
|
7
8
|
vStreamMessage,
|
|
8
9
|
} from "../validators.js";
|
|
@@ -136,23 +137,27 @@ export const list = query({
|
|
|
136
137
|
["order", "stepOrder"],
|
|
137
138
|
).take(100);
|
|
138
139
|
|
|
139
|
-
return messages.map((m) => (
|
|
140
|
-
streamId: m._id,
|
|
141
|
-
status: m.state.kind,
|
|
142
|
-
...pick(m, [
|
|
143
|
-
"format",
|
|
144
|
-
"order",
|
|
145
|
-
"stepOrder",
|
|
146
|
-
"userId",
|
|
147
|
-
"agentName",
|
|
148
|
-
"model",
|
|
149
|
-
"provider",
|
|
150
|
-
"providerOptions",
|
|
151
|
-
]),
|
|
152
|
-
}));
|
|
140
|
+
return messages.map((m) => publicStreamMessage(m));
|
|
153
141
|
},
|
|
154
142
|
});
|
|
155
143
|
|
|
144
|
+
function publicStreamMessage(m: Doc<"streamingMessages">): StreamMessage {
|
|
145
|
+
return {
|
|
146
|
+
streamId: m._id,
|
|
147
|
+
status: m.state.kind,
|
|
148
|
+
...pick(m, [
|
|
149
|
+
"format",
|
|
150
|
+
"order",
|
|
151
|
+
"stepOrder",
|
|
152
|
+
"userId",
|
|
153
|
+
"agentName",
|
|
154
|
+
"model",
|
|
155
|
+
"provider",
|
|
156
|
+
"providerOptions",
|
|
157
|
+
]),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
156
161
|
export const abortByOrder = mutation({
|
|
157
162
|
args: { threadId: v.id("threads"), order: v.number(), reason: v.string() },
|
|
158
163
|
returns: v.boolean(),
|
|
@@ -526,13 +531,7 @@ export async function getStreamingMessagesWithMetadata(
|
|
|
526
531
|
.take(1000);
|
|
527
532
|
const uiMessages = await deriveUIMessagesFromDeltas(
|
|
528
533
|
threadId,
|
|
529
|
-
[
|
|
530
|
-
{
|
|
531
|
-
...streamingMessage,
|
|
532
|
-
status: "streaming",
|
|
533
|
-
streamId: streamingMessage._id,
|
|
534
|
-
},
|
|
535
|
-
],
|
|
534
|
+
[publicStreamMessage(streamingMessage)],
|
|
536
535
|
deltas,
|
|
537
536
|
);
|
|
538
537
|
// We don't save messages that have already been saved
|