@convex-dev/agent 0.1.15-alpha.2 → 0.1.16-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/README.md +41 -700
- package/dist/client/index.d.ts +23 -20
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +34 -18
- package/dist/client/index.js.map +1 -1
- package/dist/client/streaming.d.ts +24 -2
- package/dist/client/streaming.d.ts.map +1 -1
- package/dist/client/streaming.js +35 -4
- package/dist/client/streaming.js.map +1 -1
- package/dist/client/types.d.ts +2 -20
- package/dist/client/types.d.ts.map +1 -1
- package/dist/component/_generated/api.d.ts +7 -150
- package/dist/component/messages.d.ts +0 -59
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +8 -24
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts +4 -4
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +1 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/component/streams.d.ts +7 -2
- package/dist/component/streams.d.ts.map +1 -1
- package/dist/component/streams.js +40 -14
- package/dist/component/streams.js.map +1 -1
- package/dist/component/vector/tables.d.ts +3 -3
- package/dist/component/vector/tables.d.ts.map +1 -1
- package/dist/mapping.d.ts +5 -0
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +8 -1
- package/dist/mapping.js.map +1 -1
- package/dist/react/deltas.d.ts.map +1 -1
- package/dist/react/deltas.js +20 -1
- package/dist/react/deltas.js.map +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/toUIMessages.js +2 -2
- package/dist/react/toUIMessages.js.map +1 -1
- package/dist/validators.d.ts +217 -265
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +1 -7
- package/dist/validators.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +41 -29
- package/src/client/streaming.ts +55 -4
- package/src/client/types.ts +2 -21
- package/src/component/_generated/api.d.ts +7 -150
- package/src/component/messages.ts +13 -30
- package/src/component/schema.ts +1 -1
- package/src/component/streams.ts +49 -16
- package/src/component/vector/tables.ts +5 -5
- package/src/mapping.ts +8 -1
- package/src/react/deltas.ts +24 -3
- package/src/react/index.ts +1 -1
- package/src/react/toUIMessages.ts +2 -2
- package/src/validators.ts +1 -26
|
@@ -578,160 +578,11 @@ export type Mounts = {
|
|
|
578
578
|
>;
|
|
579
579
|
}>
|
|
580
580
|
>;
|
|
581
|
-
getThreadMessages: FunctionReference<
|
|
582
|
-
"query",
|
|
583
|
-
"public",
|
|
584
|
-
{ deprecated: "Use listMessagesByThreadId instead" },
|
|
585
|
-
{
|
|
586
|
-
continueCursor: string;
|
|
587
|
-
isDone: boolean;
|
|
588
|
-
page: Array<{
|
|
589
|
-
_creationTime: number;
|
|
590
|
-
_id: string;
|
|
591
|
-
agentName?: string;
|
|
592
|
-
embeddingId?: string;
|
|
593
|
-
error?: string;
|
|
594
|
-
fileIds?: Array<string>;
|
|
595
|
-
finishReason?:
|
|
596
|
-
| "stop"
|
|
597
|
-
| "length"
|
|
598
|
-
| "content-filter"
|
|
599
|
-
| "tool-calls"
|
|
600
|
-
| "error"
|
|
601
|
-
| "other"
|
|
602
|
-
| "unknown";
|
|
603
|
-
id?: string;
|
|
604
|
-
message?:
|
|
605
|
-
| {
|
|
606
|
-
content:
|
|
607
|
-
| string
|
|
608
|
-
| Array<
|
|
609
|
-
| {
|
|
610
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
611
|
-
text: string;
|
|
612
|
-
type: "text";
|
|
613
|
-
}
|
|
614
|
-
| {
|
|
615
|
-
image: string | ArrayBuffer;
|
|
616
|
-
mimeType?: string;
|
|
617
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
618
|
-
type: "image";
|
|
619
|
-
}
|
|
620
|
-
| {
|
|
621
|
-
data: string | ArrayBuffer;
|
|
622
|
-
filename?: string;
|
|
623
|
-
mimeType: string;
|
|
624
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
625
|
-
type: "file";
|
|
626
|
-
}
|
|
627
|
-
>;
|
|
628
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
629
|
-
role: "user";
|
|
630
|
-
}
|
|
631
|
-
| {
|
|
632
|
-
content:
|
|
633
|
-
| string
|
|
634
|
-
| Array<
|
|
635
|
-
| {
|
|
636
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
637
|
-
text: string;
|
|
638
|
-
type: "text";
|
|
639
|
-
}
|
|
640
|
-
| {
|
|
641
|
-
data: string | ArrayBuffer;
|
|
642
|
-
filename?: string;
|
|
643
|
-
mimeType: string;
|
|
644
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
645
|
-
type: "file";
|
|
646
|
-
}
|
|
647
|
-
| {
|
|
648
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
649
|
-
signature?: string;
|
|
650
|
-
text: string;
|
|
651
|
-
type: "reasoning";
|
|
652
|
-
}
|
|
653
|
-
| {
|
|
654
|
-
data: string;
|
|
655
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
656
|
-
type: "redacted-reasoning";
|
|
657
|
-
}
|
|
658
|
-
| {
|
|
659
|
-
args: any;
|
|
660
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
661
|
-
toolCallId: string;
|
|
662
|
-
toolName: string;
|
|
663
|
-
type: "tool-call";
|
|
664
|
-
}
|
|
665
|
-
>;
|
|
666
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
667
|
-
role: "assistant";
|
|
668
|
-
}
|
|
669
|
-
| {
|
|
670
|
-
content: Array<{
|
|
671
|
-
args?: any;
|
|
672
|
-
experimental_content?: Array<
|
|
673
|
-
| { text: string; type: "text" }
|
|
674
|
-
| { data: string; mimeType?: string; type: "image" }
|
|
675
|
-
>;
|
|
676
|
-
isError?: boolean;
|
|
677
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
678
|
-
result: any;
|
|
679
|
-
toolCallId: string;
|
|
680
|
-
toolName: string;
|
|
681
|
-
type: "tool-result";
|
|
682
|
-
}>;
|
|
683
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
684
|
-
role: "tool";
|
|
685
|
-
}
|
|
686
|
-
| {
|
|
687
|
-
content: string;
|
|
688
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
689
|
-
role: "system";
|
|
690
|
-
};
|
|
691
|
-
model?: string;
|
|
692
|
-
order: number;
|
|
693
|
-
provider?: string;
|
|
694
|
-
providerMetadata?: Record<string, Record<string, any>>;
|
|
695
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
696
|
-
reasoning?: string;
|
|
697
|
-
reasoningDetails?: Array<
|
|
698
|
-
| { signature?: string; text: string; type: "text" }
|
|
699
|
-
| { data: string; type: "redacted" }
|
|
700
|
-
>;
|
|
701
|
-
sources?: Array<{
|
|
702
|
-
id: string;
|
|
703
|
-
providerOptions?: Record<string, Record<string, any>>;
|
|
704
|
-
sourceType: "url";
|
|
705
|
-
title?: string;
|
|
706
|
-
url: string;
|
|
707
|
-
}>;
|
|
708
|
-
status: "pending" | "success" | "failed";
|
|
709
|
-
stepOrder: number;
|
|
710
|
-
text?: string;
|
|
711
|
-
threadId: string;
|
|
712
|
-
tool: boolean;
|
|
713
|
-
usage?: {
|
|
714
|
-
completionTokens: number;
|
|
715
|
-
promptTokens: number;
|
|
716
|
-
totalTokens: number;
|
|
717
|
-
};
|
|
718
|
-
userId?: string;
|
|
719
|
-
warnings?: Array<
|
|
720
|
-
| { details?: string; setting: string; type: "unsupported-setting" }
|
|
721
|
-
| { details?: string; tool: any; type: "unsupported-tool" }
|
|
722
|
-
| { message: string; type: "other" }
|
|
723
|
-
>;
|
|
724
|
-
}>;
|
|
725
|
-
pageStatus?: "SplitRecommended" | "SplitRequired" | null;
|
|
726
|
-
splitCursor?: string | null;
|
|
727
|
-
}
|
|
728
|
-
>;
|
|
729
581
|
listMessagesByThreadId: FunctionReference<
|
|
730
582
|
"query",
|
|
731
583
|
"public",
|
|
732
584
|
{
|
|
733
585
|
excludeToolMessages?: boolean;
|
|
734
|
-
isTool?: "use excludeToolMessages instead of this";
|
|
735
586
|
order: "asc" | "desc";
|
|
736
587
|
paginationOpts?: {
|
|
737
588
|
cursor: string | null;
|
|
@@ -1437,7 +1288,13 @@ export type Mounts = {
|
|
|
1437
1288
|
"mutation",
|
|
1438
1289
|
"public",
|
|
1439
1290
|
{ reason: string; streamId: string },
|
|
1440
|
-
|
|
1291
|
+
boolean
|
|
1292
|
+
>;
|
|
1293
|
+
abortByOrder: FunctionReference<
|
|
1294
|
+
"mutation",
|
|
1295
|
+
"public",
|
|
1296
|
+
{ order: number; reason: string; threadId: string },
|
|
1297
|
+
boolean
|
|
1441
1298
|
>;
|
|
1442
1299
|
addDelta: FunctionReference<
|
|
1443
1300
|
"mutation",
|
|
@@ -40,15 +40,6 @@ import {
|
|
|
40
40
|
} from "./vector/tables.js";
|
|
41
41
|
import { changeRefcount } from "./files.js";
|
|
42
42
|
|
|
43
|
-
/** @deprecated Use *.threads.listMessagesByThreadId instead. */
|
|
44
|
-
export const listThreadsByUserId = _listThreadsByUserId;
|
|
45
|
-
|
|
46
|
-
/** @deprecated Use *.threads.getThread */
|
|
47
|
-
export const getThread = _getThread;
|
|
48
|
-
|
|
49
|
-
/** @deprecated Use *.threads.updateThread instead */
|
|
50
|
-
export const updateThread = _updateThread;
|
|
51
|
-
|
|
52
43
|
function publicMessage(message: Doc<"messages">): MessageDoc {
|
|
53
44
|
return omit(message, ["parentMessageId", "stepId", "files"]);
|
|
54
45
|
}
|
|
@@ -385,8 +376,6 @@ export const listMessagesByThreadId = query({
|
|
|
385
376
|
args: {
|
|
386
377
|
threadId: v.id("threads"),
|
|
387
378
|
excludeToolMessages: v.optional(v.boolean()),
|
|
388
|
-
/** @deprecated Use excludeToolMessages instead. */
|
|
389
|
-
isTool: v.optional(v.literal("use excludeToolMessages instead of this")),
|
|
390
379
|
/** What order to sort the messages in. To get the latest, use "desc". */
|
|
391
380
|
order: v.union(v.literal("asc"), v.literal("desc")),
|
|
392
381
|
paginationOpts: v.optional(paginationOptsValidator),
|
|
@@ -421,10 +410,8 @@ export const listMessagesByThreadId = query({
|
|
|
421
410
|
})
|
|
422
411
|
.order(order)
|
|
423
412
|
.filterWith(
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
m.order < last.order ||
|
|
427
|
-
(m.order === last.order && m.stepOrder <= last.stepOrder)
|
|
413
|
+
// We allow all messages on the same order.
|
|
414
|
+
async (m) => !last || m.order < last.order || m.order === last.order
|
|
428
415
|
)
|
|
429
416
|
)
|
|
430
417
|
);
|
|
@@ -452,15 +439,6 @@ export const getMessagesByIds = query({
|
|
|
452
439
|
returns: v.array(v.union(v.null(), vMessageDoc)),
|
|
453
440
|
});
|
|
454
441
|
|
|
455
|
-
/** @deprecated Use listMessagesByThreadId instead. */
|
|
456
|
-
export const getThreadMessages = query({
|
|
457
|
-
args: { deprecated: v.literal("Use listMessagesByThreadId instead") },
|
|
458
|
-
handler: async () => {
|
|
459
|
-
throw new Error("Use listMessagesByThreadId instead of getThreadMessages");
|
|
460
|
-
},
|
|
461
|
-
returns: vPaginationResult(vMessageDoc),
|
|
462
|
-
});
|
|
463
|
-
|
|
464
442
|
export const searchMessages = action({
|
|
465
443
|
args: {
|
|
466
444
|
threadId: v.optional(v.id("threads")),
|
|
@@ -563,14 +541,19 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
563
541
|
args.vectorIds.map((embeddingId) =>
|
|
564
542
|
ctx.db
|
|
565
543
|
.query("messages")
|
|
566
|
-
.withIndex("
|
|
567
|
-
.filter((q) =>
|
|
544
|
+
.withIndex("embeddingId_threadId", (q) =>
|
|
568
545
|
searchAllMessagesForUserId
|
|
569
|
-
? q.eq(
|
|
570
|
-
: q.eq(
|
|
546
|
+
? q.eq("embeddingId", embeddingId)
|
|
547
|
+
: q.eq("embeddingId", embeddingId).eq("threadId", threadId!)
|
|
548
|
+
)
|
|
549
|
+
.filter((q) =>
|
|
550
|
+
q.and(
|
|
551
|
+
q.eq(q.field("status"), "success"),
|
|
552
|
+
searchAllMessagesForUserId
|
|
553
|
+
? q.eq(q.field("userId"), searchAllMessagesForUserId)
|
|
554
|
+
: q.eq(q.field("threadId"), threadId)
|
|
555
|
+
)
|
|
571
556
|
)
|
|
572
|
-
// Don't include pending. Failed messages hopefully are deleted but may as well be safe.
|
|
573
|
-
.filter((q) => q.eq(q.field("status"), "success"))
|
|
574
557
|
.first()
|
|
575
558
|
)
|
|
576
559
|
)
|
package/src/component/schema.ts
CHANGED
|
@@ -85,7 +85,7 @@ export const schema = defineSchema({
|
|
|
85
85
|
filterFields: ["userId", "threadId"],
|
|
86
86
|
})
|
|
87
87
|
// Allows finding messages by vector embedding id
|
|
88
|
-
.index("
|
|
88
|
+
.index("embeddingId_threadId", ["embeddingId", "threadId"]),
|
|
89
89
|
|
|
90
90
|
// Status: if it's done, it's deleted, then deltas are vacuumed
|
|
91
91
|
streamingMessages: defineTable({
|
package/src/component/streams.ts
CHANGED
|
@@ -151,30 +151,63 @@ export const list = query({
|
|
|
151
151
|
},
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
-
export const
|
|
154
|
+
export const abortByOrder = mutation({
|
|
155
155
|
args: {
|
|
156
|
-
|
|
156
|
+
threadId: v.id("threads"),
|
|
157
|
+
order: v.number(),
|
|
157
158
|
reason: v.string(),
|
|
158
159
|
},
|
|
159
|
-
returns: v.
|
|
160
|
+
returns: v.boolean(),
|
|
160
161
|
handler: async (ctx, args) => {
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
)
|
|
169
|
-
|
|
162
|
+
const streams = await ctx.db
|
|
163
|
+
.query("streamingMessages")
|
|
164
|
+
.withIndex("threadId_state_order_stepOrder", (q) =>
|
|
165
|
+
q
|
|
166
|
+
.eq("threadId", args.threadId)
|
|
167
|
+
.eq("state.kind", "streaming")
|
|
168
|
+
.eq("order", args.order)
|
|
169
|
+
)
|
|
170
|
+
.take(100);
|
|
171
|
+
for (const stream of streams) {
|
|
172
|
+
await abortById(ctx, {
|
|
173
|
+
streamId: stream._id,
|
|
174
|
+
reason: args.reason,
|
|
175
|
+
});
|
|
170
176
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
177
|
+
return streams.length > 0;
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
export const abort = mutation({
|
|
182
|
+
args: {
|
|
183
|
+
streamId: v.id("streamingMessages"),
|
|
184
|
+
reason: v.string(),
|
|
175
185
|
},
|
|
186
|
+
returns: v.boolean(),
|
|
187
|
+
handler: abortById,
|
|
176
188
|
});
|
|
177
189
|
|
|
190
|
+
async function abortById(
|
|
191
|
+
ctx: MutationCtx,
|
|
192
|
+
args: { streamId: Id<"streamingMessages">; reason: string }
|
|
193
|
+
) {
|
|
194
|
+
const stream = await ctx.db.get(args.streamId);
|
|
195
|
+
if (!stream) {
|
|
196
|
+
throw new Error(`Stream not found: ${args.streamId}`);
|
|
197
|
+
}
|
|
198
|
+
if (stream.state.kind !== "streaming") {
|
|
199
|
+
console.warn(
|
|
200
|
+
`Stream trying to abort but not currently streaming (${stream.state.kind}): ${args.streamId}`
|
|
201
|
+
);
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
await cleanupTimeoutFn(ctx, stream);
|
|
205
|
+
await ctx.db.patch(args.streamId, {
|
|
206
|
+
state: { kind: "aborted", reason: args.reason },
|
|
207
|
+
});
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
|
|
178
211
|
async function cleanupTimeoutFn(
|
|
179
212
|
ctx: MutationCtx,
|
|
180
213
|
stream: Doc<"streamingMessages">
|
|
@@ -37,7 +37,7 @@ export type EmbeddingsWithoutDenormalizedFields = Infer<
|
|
|
37
37
|
typeof vEmbeddingsWithoutDenormalizedFields
|
|
38
38
|
>;
|
|
39
39
|
|
|
40
|
-
function table<D extends number>(dimensions: D):
|
|
40
|
+
function table<D extends number>(dimensions: D): VectorTable<D> {
|
|
41
41
|
return defineTable(embeddings)
|
|
42
42
|
.vectorIndex("vector", {
|
|
43
43
|
vectorField: "vector",
|
|
@@ -47,7 +47,7 @@ function table<D extends number>(dimensions: D): Table<D> {
|
|
|
47
47
|
.index("model_table_threadId", ["model", "table", "threadId"]);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
type
|
|
50
|
+
type VectorTable<D extends number> = TableDefinition<
|
|
51
51
|
VObject<ObjectType<typeof embeddings>, typeof embeddings>,
|
|
52
52
|
{ model_table_threadId: ["model", "table", "threadId", "_creationTime"] },
|
|
53
53
|
GenericTableSearchIndexes,
|
|
@@ -63,7 +63,7 @@ type VectorIndex<D extends number> = {
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
export type VectorSchema = SchemaDefinition<
|
|
66
|
-
{ [key in VectorTableName]:
|
|
66
|
+
{ [key in VectorTableName]: VectorTable<128> },
|
|
67
67
|
true
|
|
68
68
|
>;
|
|
69
69
|
|
|
@@ -110,7 +110,7 @@ export function getVectorIdInfo(ctx: QueryCtx, id: VectorTableId) {
|
|
|
110
110
|
|
|
111
111
|
const tables: {
|
|
112
112
|
[K in keyof typeof VectorDimensions &
|
|
113
|
-
number as `embeddings_${(typeof VectorDimensions)[K]}`]:
|
|
113
|
+
number as `embeddings_${(typeof VectorDimensions)[K]}`]: VectorTable<
|
|
114
114
|
(typeof VectorDimensions)[K]
|
|
115
115
|
>;
|
|
116
116
|
} = Object.fromEntries(
|
|
@@ -120,7 +120,7 @@ const tables: {
|
|
|
120
120
|
])
|
|
121
121
|
) as Record<
|
|
122
122
|
`embeddings_${(typeof VectorDimensions)[number]}`,
|
|
123
|
-
|
|
123
|
+
VectorTable<(typeof VectorDimensions)[number]>
|
|
124
124
|
>;
|
|
125
125
|
|
|
126
126
|
export default tables;
|
package/src/mapping.ts
CHANGED
|
@@ -125,7 +125,6 @@ export async function serializeObjectResult(
|
|
|
125
125
|
const { message, fileIds } = await serializeMessage(ctx, component, {
|
|
126
126
|
role: "assistant" as const,
|
|
127
127
|
content: text,
|
|
128
|
-
id: result.response.id,
|
|
129
128
|
});
|
|
130
129
|
return {
|
|
131
130
|
messages: [
|
|
@@ -187,6 +186,9 @@ export async function serializeContent(
|
|
|
187
186
|
}
|
|
188
187
|
return { ...part, data };
|
|
189
188
|
}
|
|
189
|
+
case "tool-result": {
|
|
190
|
+
return { ...part, result: part.result ?? null };
|
|
191
|
+
}
|
|
190
192
|
default:
|
|
191
193
|
return part;
|
|
192
194
|
}
|
|
@@ -281,6 +283,11 @@ export function guessMimeType(buf: ArrayBuffer | string): string {
|
|
|
281
283
|
return "application/octet-stream";
|
|
282
284
|
}
|
|
283
285
|
|
|
286
|
+
/**
|
|
287
|
+
* Serialize an AI SDK `DataContent` or `URL` to a Convex-serializable format.
|
|
288
|
+
* @param dataOrUrl - The data or URL to serialize.
|
|
289
|
+
* @returns The serialized data as an ArrayBuffer or the URL as a string.
|
|
290
|
+
*/
|
|
284
291
|
export function serializeDataOrUrl(
|
|
285
292
|
dataOrUrl: DataContent | URL
|
|
286
293
|
): ArrayBuffer | string {
|
package/src/react/deltas.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { TextPart, ToolCallPart, ToolResultPart } from "ai";
|
|
|
2
2
|
import type { MessageDoc } from "../client/index.js";
|
|
3
3
|
import type {
|
|
4
4
|
Message,
|
|
5
|
+
MessageStatus,
|
|
5
6
|
StreamDelta,
|
|
6
7
|
StreamMessage,
|
|
7
8
|
TextStreamPart,
|
|
@@ -99,6 +100,12 @@ export function applyDeltasToStreamMessage(
|
|
|
99
100
|
cursor = delta.end;
|
|
100
101
|
parts.push(...delta.parts);
|
|
101
102
|
}
|
|
103
|
+
if (existing && existing.messages.length > 0 && !changed) {
|
|
104
|
+
const lastMessage = existing.messages.at(-1)!;
|
|
105
|
+
if (statusFromStreamStatus(streamMessage.status) !== lastMessage.status) {
|
|
106
|
+
changed = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
102
109
|
if (!changed) {
|
|
103
110
|
return [
|
|
104
111
|
existing ?? { streamId: streamMessage.streamId, cursor, messages: [] },
|
|
@@ -115,6 +122,7 @@ export function applyDeltasToStreamMessage(
|
|
|
115
122
|
currentMessage = {
|
|
116
123
|
...lastMessage,
|
|
117
124
|
message: cloneMessageAndContent(lastMessage.message),
|
|
125
|
+
status: statusFromStreamStatus(streamMessage.status),
|
|
118
126
|
};
|
|
119
127
|
} else {
|
|
120
128
|
const newMessage = createStreamingMessage(
|
|
@@ -248,6 +256,21 @@ function getLastContent(message: MessageDoc) {
|
|
|
248
256
|
return undefined;
|
|
249
257
|
}
|
|
250
258
|
|
|
259
|
+
function statusFromStreamStatus(
|
|
260
|
+
status: StreamMessage["status"]
|
|
261
|
+
): MessageStatus {
|
|
262
|
+
switch (status) {
|
|
263
|
+
case "streaming":
|
|
264
|
+
return "pending";
|
|
265
|
+
case "finished":
|
|
266
|
+
return "success";
|
|
267
|
+
case "aborted":
|
|
268
|
+
return "failed";
|
|
269
|
+
default:
|
|
270
|
+
return "pending";
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
251
274
|
export function createStreamingMessage(
|
|
252
275
|
threadId: string,
|
|
253
276
|
message: StreamMessage,
|
|
@@ -259,9 +282,7 @@ export function createStreamingMessage(
|
|
|
259
282
|
...rest,
|
|
260
283
|
_id: `${streamId}-${index}`,
|
|
261
284
|
_creationTime: Date.now(),
|
|
262
|
-
status: (
|
|
263
|
-
{ streaming: "pending", finished: "success", aborted: "failed" } as const
|
|
264
|
-
)[message.status],
|
|
285
|
+
status: statusFromStreamStatus(message.status),
|
|
265
286
|
threadId,
|
|
266
287
|
tool: false,
|
|
267
288
|
};
|
package/src/react/index.ts
CHANGED
|
@@ -114,7 +114,7 @@ export function useThreadMessages<
|
|
|
114
114
|
const streamListMessages =
|
|
115
115
|
streamMessages?.map((m) => ({
|
|
116
116
|
...m,
|
|
117
|
-
streaming: !m.status || m.status === "
|
|
117
|
+
streaming: !m.status || m.status === "pending",
|
|
118
118
|
})) ?? [];
|
|
119
119
|
return {
|
|
120
120
|
...paginated,
|
|
@@ -25,7 +25,7 @@ export function toUIMessages(
|
|
|
25
25
|
content && typeof content !== "string" ? content : [];
|
|
26
26
|
if (!coreMessage) continue;
|
|
27
27
|
const common = {
|
|
28
|
-
id: message.
|
|
28
|
+
id: message._id,
|
|
29
29
|
createdAt: new Date(message._creationTime),
|
|
30
30
|
order: message.order,
|
|
31
31
|
stepOrder: message.stepOrder,
|
|
@@ -82,7 +82,7 @@ export function toUIMessages(
|
|
|
82
82
|
: message.status;
|
|
83
83
|
}
|
|
84
84
|
// update it to the last message's id
|
|
85
|
-
assistantMessage.id = message.
|
|
85
|
+
assistantMessage.id = message._id;
|
|
86
86
|
if (message.reasoning) {
|
|
87
87
|
assistantMessage.parts.push({
|
|
88
88
|
type: "reasoning",
|
package/src/validators.ts
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
type ObjectType,
|
|
5
5
|
type Validator,
|
|
6
6
|
type Value,
|
|
7
|
-
type VObject,
|
|
8
7
|
} from "convex/values";
|
|
9
8
|
import { vVectorDimension } from "./component/vector/tables.js";
|
|
10
9
|
|
|
@@ -312,30 +311,6 @@ export const vStorageOptions = v.object({
|
|
|
312
311
|
),
|
|
313
312
|
});
|
|
314
313
|
|
|
315
|
-
const vStorageOptionsIncludingDeprecated = v.object({
|
|
316
|
-
...vStorageOptions.fields,
|
|
317
|
-
saveAllInputMessages: v.optional(v.boolean()),
|
|
318
|
-
saveAnyInputMessages: v.optional(v.boolean()),
|
|
319
|
-
saveOutputMessages: v.optional(v.boolean()),
|
|
320
|
-
}) as VObject<
|
|
321
|
-
{
|
|
322
|
-
saveMessages?: "all" | "none" | "promptAndOutput";
|
|
323
|
-
/**
|
|
324
|
-
* @deprecated Use saveMessages instead.
|
|
325
|
-
*/
|
|
326
|
-
saveAllInputMessages?: boolean;
|
|
327
|
-
/**
|
|
328
|
-
* @deprecated Use saveMessages instead.
|
|
329
|
-
*/
|
|
330
|
-
saveAnyInputMessages?: boolean;
|
|
331
|
-
/**
|
|
332
|
-
* @deprecated Use saveMessages instead.
|
|
333
|
-
*/
|
|
334
|
-
saveOutputMessages?: boolean;
|
|
335
|
-
},
|
|
336
|
-
typeof vStorageOptions.fields
|
|
337
|
-
>;
|
|
338
|
-
|
|
339
314
|
const vPromptFields = {
|
|
340
315
|
system: v.optional(v.string()),
|
|
341
316
|
prompt: v.optional(v.string()),
|
|
@@ -360,7 +335,7 @@ const vCommonArgs = {
|
|
|
360
335
|
userId: v.optional(v.string()),
|
|
361
336
|
threadId: v.optional(v.string()),
|
|
362
337
|
contextOptions: v.optional(vContextOptions),
|
|
363
|
-
storageOptions: v.optional(
|
|
338
|
+
storageOptions: v.optional(vStorageOptions),
|
|
364
339
|
providerOptions,
|
|
365
340
|
...vCallSettingsFields,
|
|
366
341
|
...vPromptFields,
|