@convex-dev/agent 0.1.9-alpha.1 → 0.1.9-alpha.10
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 +3 -3
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +3 -1
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/client/streaming.d.ts +3 -0
- package/dist/commonjs/client/streaming.d.ts.map +1 -1
- package/dist/commonjs/client/streaming.js +23 -1
- package/dist/commonjs/client/streaming.js.map +1 -1
- package/dist/commonjs/client/types.d.ts +0 -2
- package/dist/commonjs/client/types.d.ts.map +1 -1
- package/dist/commonjs/component/_generated/api.d.ts +12 -4
- package/dist/commonjs/component/streams.d.ts +1 -1
- package/dist/commonjs/component/streams.d.ts.map +1 -1
- package/dist/commonjs/component/streams.js +15 -5
- package/dist/commonjs/component/streams.js.map +1 -1
- package/dist/commonjs/component/threads.d.ts +8 -2
- package/dist/commonjs/component/threads.d.ts.map +1 -1
- package/dist/commonjs/component/threads.js +44 -18
- package/dist/commonjs/component/threads.js.map +1 -1
- package/dist/commonjs/component/vector/tables.d.ts +4 -2
- package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
- package/dist/commonjs/react/deltas.d.ts.map +1 -1
- package/dist/commonjs/react/deltas.js +1 -0
- package/dist/commonjs/react/deltas.js.map +1 -1
- package/dist/commonjs.tsbuildinfo +1 -1
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +3 -1
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/streaming.d.ts +3 -0
- package/dist/esm/client/streaming.d.ts.map +1 -1
- package/dist/esm/client/streaming.js +23 -1
- package/dist/esm/client/streaming.js.map +1 -1
- package/dist/esm/client/types.d.ts +0 -2
- package/dist/esm/client/types.d.ts.map +1 -1
- package/dist/esm/component/_generated/api.d.ts +12 -4
- package/dist/esm/component/streams.d.ts +1 -1
- package/dist/esm/component/streams.d.ts.map +1 -1
- package/dist/esm/component/streams.js +15 -5
- package/dist/esm/component/streams.js.map +1 -1
- package/dist/esm/component/threads.d.ts +8 -2
- package/dist/esm/component/threads.d.ts.map +1 -1
- package/dist/esm/component/threads.js +44 -18
- package/dist/esm/component/threads.js.map +1 -1
- package/dist/esm/component/vector/tables.d.ts +4 -2
- package/dist/esm/component/vector/tables.d.ts.map +1 -1
- package/dist/esm/react/deltas.d.ts.map +1 -1
- package/dist/esm/react/deltas.js +1 -0
- package/dist/esm/react/deltas.js.map +1 -1
- package/dist/esm.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +3 -3
- package/src/client/streaming.ts +26 -1
- package/src/client/types.ts +0 -2
- package/src/component/_generated/api.d.ts +12 -4
- package/src/component/streams.ts +18 -5
- package/src/component/threads.ts +48 -26
- package/src/react/deltas.ts +1 -0
package/src/client/index.ts
CHANGED
|
@@ -9,7 +9,6 @@ import type {
|
|
|
9
9
|
StepResult,
|
|
10
10
|
StreamObjectResult,
|
|
11
11
|
StreamTextResult,
|
|
12
|
-
TextPart,
|
|
13
12
|
ToolSet,
|
|
14
13
|
} from "ai";
|
|
15
14
|
import { generateObject, generateText, streamObject, streamText } from "ai";
|
|
@@ -544,6 +543,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
544
543
|
providerOptions: aiArgs.providerOptions,
|
|
545
544
|
order,
|
|
546
545
|
stepOrder,
|
|
546
|
+
abortSignal: aiArgs.abortSignal,
|
|
547
547
|
})
|
|
548
548
|
: undefined;
|
|
549
549
|
|
|
@@ -552,6 +552,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
552
552
|
maxSteps: this.options.maxSteps,
|
|
553
553
|
...aiArgs,
|
|
554
554
|
tools,
|
|
555
|
+
abortSignal: streamer?.abortController.signal ?? aiArgs.abortSignal,
|
|
555
556
|
experimental_transform: mergeTransforms(
|
|
556
557
|
options?.saveStreamDeltas,
|
|
557
558
|
args.experimental_transform
|
|
@@ -1050,8 +1051,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1050
1051
|
this.component.messages.listMessagesByThreadId,
|
|
1051
1052
|
{
|
|
1052
1053
|
threadId: args.threadId,
|
|
1053
|
-
excludeToolMessages:
|
|
1054
|
-
opts.includeToolCalls === true ? false : opts.excludeToolMessages,
|
|
1054
|
+
excludeToolMessages: opts.excludeToolMessages,
|
|
1055
1055
|
paginationOpts: {
|
|
1056
1056
|
numItems: opts.recentMessages ?? DEFAULT_RECENT_MESSAGES,
|
|
1057
1057
|
cursor: null,
|
package/src/client/streaming.ts
CHANGED
|
@@ -65,6 +65,7 @@ export class DeltaStreamer {
|
|
|
65
65
|
#latestWrite: number = 0;
|
|
66
66
|
#ongoingWrite: Promise<void> | undefined;
|
|
67
67
|
#cursor: number = 0;
|
|
68
|
+
public abortController: AbortController;
|
|
68
69
|
|
|
69
70
|
constructor(
|
|
70
71
|
public readonly component: AgentComponent,
|
|
@@ -79,6 +80,7 @@ export class DeltaStreamer {
|
|
|
79
80
|
userId: string | undefined;
|
|
80
81
|
order: number | undefined;
|
|
81
82
|
stepOrder: number | undefined;
|
|
83
|
+
abortSignal: AbortSignal | undefined;
|
|
82
84
|
}
|
|
83
85
|
) {
|
|
84
86
|
this.options =
|
|
@@ -92,8 +94,17 @@ export class DeltaStreamer {
|
|
|
92
94
|
this.#nextParts = [];
|
|
93
95
|
this.#nextOrder = metadata.order ?? 0;
|
|
94
96
|
this.#nextStepOrder = (metadata.stepOrder ?? 0) + 1;
|
|
97
|
+
this.abortController = new AbortController();
|
|
98
|
+
if (metadata.abortSignal) {
|
|
99
|
+
metadata.abortSignal.addEventListener("abort", () => {
|
|
100
|
+
this.abortController.abort();
|
|
101
|
+
});
|
|
102
|
+
}
|
|
95
103
|
}
|
|
96
104
|
public async addParts(parts: TextStreamPart[]) {
|
|
105
|
+
if (this.abortController.signal.aborted) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
97
108
|
if (!this.streamId) {
|
|
98
109
|
this.streamId = await this.ctx.runMutation(
|
|
99
110
|
this.component.streams.create,
|
|
@@ -114,9 +125,23 @@ export class DeltaStreamer {
|
|
|
114
125
|
}
|
|
115
126
|
|
|
116
127
|
async #sendDelta() {
|
|
128
|
+
if (this.abortController.signal.aborted) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
117
131
|
const delta = this.#createDelta();
|
|
118
132
|
this.#latestWrite = Date.now();
|
|
119
|
-
|
|
133
|
+
try {
|
|
134
|
+
const success = await this.ctx.runMutation(
|
|
135
|
+
this.component.streams.addDelta,
|
|
136
|
+
delta
|
|
137
|
+
);
|
|
138
|
+
if (!success) {
|
|
139
|
+
this.abortController.abort();
|
|
140
|
+
}
|
|
141
|
+
} catch (e) {
|
|
142
|
+
this.abortController.abort();
|
|
143
|
+
throw e;
|
|
144
|
+
}
|
|
120
145
|
// Now that we've sent the delta, check if we need to send another one.
|
|
121
146
|
if (
|
|
122
147
|
this.#nextParts.length > 0 &&
|
package/src/client/types.ts
CHANGED
|
@@ -48,8 +48,6 @@ import type { StreamingOptions } from "./streaming.js";
|
|
|
48
48
|
* automatically with thread.generateText, or directly via search.
|
|
49
49
|
*/
|
|
50
50
|
export type ContextOptions = {
|
|
51
|
-
/** @deprecated Use excludeToolMessages instead. */
|
|
52
|
-
includeToolCalls?: boolean;
|
|
53
51
|
/**
|
|
54
52
|
* Whether to include tool messages in the context.
|
|
55
53
|
* By default, tool calls and results are not included.
|
|
@@ -1467,7 +1467,7 @@ export type Mounts = {
|
|
|
1467
1467
|
start: number;
|
|
1468
1468
|
streamId: string;
|
|
1469
1469
|
},
|
|
1470
|
-
|
|
1470
|
+
boolean
|
|
1471
1471
|
>;
|
|
1472
1472
|
create: FunctionReference<
|
|
1473
1473
|
"mutation",
|
|
@@ -1663,13 +1663,21 @@ export type Mounts = {
|
|
|
1663
1663
|
deleteAllForThreadIdAsync: FunctionReference<
|
|
1664
1664
|
"mutation",
|
|
1665
1665
|
"public",
|
|
1666
|
-
{
|
|
1667
|
-
|
|
1666
|
+
{
|
|
1667
|
+
cursor?: string;
|
|
1668
|
+
deltaCursor?: string;
|
|
1669
|
+
limit?: number;
|
|
1670
|
+
messagesDone?: boolean;
|
|
1671
|
+
streamOrder?: number;
|
|
1672
|
+
streamsDone?: boolean;
|
|
1673
|
+
threadId: string;
|
|
1674
|
+
},
|
|
1675
|
+
{ isDone: boolean }
|
|
1668
1676
|
>;
|
|
1669
1677
|
deleteAllForThreadIdSync: FunctionReference<
|
|
1670
1678
|
"action",
|
|
1671
1679
|
"public",
|
|
1672
|
-
{
|
|
1680
|
+
{ limit?: number; threadId: string },
|
|
1673
1681
|
null
|
|
1674
1682
|
>;
|
|
1675
1683
|
getThread: FunctionReference<
|
package/src/component/streams.ts
CHANGED
|
@@ -17,20 +17,30 @@ import {
|
|
|
17
17
|
import schema from "./schema.js";
|
|
18
18
|
import { stream } from "convex-helpers/server/stream";
|
|
19
19
|
import { mergedStream } from "convex-helpers/server/stream";
|
|
20
|
+
import { paginator } from "convex-helpers/server/pagination";
|
|
21
|
+
|
|
22
|
+
const SECOND = 1000;
|
|
23
|
+
const MINUTE = 60 * SECOND;
|
|
20
24
|
|
|
21
25
|
const MAX_DELTAS_PER_REQUEST = 1000;
|
|
22
26
|
const MAX_DELTAS_PER_STREAM = 100;
|
|
23
|
-
const TIMEOUT_INTERVAL =
|
|
24
|
-
const DELETE_STREAM_DELAY =
|
|
27
|
+
const TIMEOUT_INTERVAL = 10 * MINUTE;
|
|
28
|
+
const DELETE_STREAM_DELAY = MINUTE * 5; // 5 minutes
|
|
25
29
|
|
|
26
30
|
const deltaValidator = schema.tables.streamDeltas.validator;
|
|
27
31
|
|
|
28
32
|
export const addDelta = mutation({
|
|
29
33
|
args: deltaValidator,
|
|
30
|
-
returns: v.
|
|
34
|
+
returns: v.boolean(),
|
|
31
35
|
handler: async (ctx, args) => {
|
|
32
36
|
await ctx.db.insert("streamDeltas", args);
|
|
33
37
|
await heartbeatStream(ctx, { streamId: args.streamId });
|
|
38
|
+
const stream = await ctx.db.get(args.streamId);
|
|
39
|
+
if (stream?.state.kind !== "streaming") {
|
|
40
|
+
console.warn(`Stream is not streaming: ${args.streamId}`);
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
34
44
|
},
|
|
35
45
|
});
|
|
36
46
|
|
|
@@ -138,7 +148,10 @@ export const finish = mutation({
|
|
|
138
148
|
throw new Error(`Stream not found: ${args.streamId}`);
|
|
139
149
|
}
|
|
140
150
|
if (stream.state.kind !== "streaming") {
|
|
141
|
-
|
|
151
|
+
console.warn(
|
|
152
|
+
`Stream trying to finish but not currently streaming: ${args.streamId}`
|
|
153
|
+
);
|
|
154
|
+
return;
|
|
142
155
|
}
|
|
143
156
|
if (stream.state.timeoutFnId) {
|
|
144
157
|
const timeoutFn = await ctx.db.system.get(stream.state.timeoutFnId);
|
|
@@ -221,7 +234,7 @@ async function deletePageForStreamId(
|
|
|
221
234
|
ctx: MutationCtx,
|
|
222
235
|
args: { streamId: Id<"streamingMessages">; cursor?: string }
|
|
223
236
|
) {
|
|
224
|
-
const deltas = await ctx.db
|
|
237
|
+
const deltas = await paginator(ctx.db, schema)
|
|
225
238
|
.query("streamDeltas")
|
|
226
239
|
.withIndex("streamId_start_end", (q) => q.eq("streamId", args.streamId))
|
|
227
240
|
.paginate({
|
package/src/component/threads.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from "./_generated/server.js";
|
|
17
17
|
import { deleteMessage } from "./messages.js";
|
|
18
18
|
import { schema, v } from "./schema.js";
|
|
19
|
+
import { deleteStreamsPageForThreadId } from "./streams.js";
|
|
19
20
|
|
|
20
21
|
function publicThreadOrNull(thread: Doc<"threads"> | null): ThreadDoc | null {
|
|
21
22
|
if (thread === null) {
|
|
@@ -100,29 +101,17 @@ export const updateThread = mutation({
|
|
|
100
101
|
|
|
101
102
|
// TODO: delete thread
|
|
102
103
|
|
|
103
|
-
const deleteThreadArgs = {
|
|
104
|
-
threadId: v.id("threads"),
|
|
105
|
-
cursor: v.optional(v.string()),
|
|
106
|
-
limit: v.optional(v.number()),
|
|
107
|
-
};
|
|
108
|
-
type DeleteThreadArgs = ObjectType<typeof deleteThreadArgs>;
|
|
109
|
-
const deleteThreadReturns = {
|
|
110
|
-
cursor: v.string(),
|
|
111
|
-
isDone: v.boolean(),
|
|
112
|
-
};
|
|
113
|
-
type DeleteThreadReturns = ObjectType<typeof deleteThreadReturns>;
|
|
114
|
-
|
|
115
104
|
/**
|
|
116
105
|
* Use this to delete a thread and everything it contains.
|
|
117
106
|
* It will try to delete all pages synchronously.
|
|
118
107
|
* If it times out or fails, you'll have to run it again.
|
|
119
108
|
*/
|
|
120
109
|
export const deleteAllForThreadIdSync = action({
|
|
121
|
-
args:
|
|
110
|
+
args: { threadId: v.id("threads"), limit: v.optional(v.number()) },
|
|
122
111
|
handler: async (ctx, args) => {
|
|
123
|
-
let cursor =
|
|
112
|
+
let cursor: string | undefined = undefined;
|
|
124
113
|
while (true) {
|
|
125
|
-
const result = await ctx.runMutation(
|
|
114
|
+
const result: DeleteThreadReturns = await ctx.runMutation(
|
|
126
115
|
internal.threads._deletePageForThreadId,
|
|
127
116
|
{ threadId: args.threadId, cursor, limit: args.limit }
|
|
128
117
|
);
|
|
@@ -138,6 +127,22 @@ export const deleteAllForThreadIdSync = action({
|
|
|
138
127
|
returns: v.null(),
|
|
139
128
|
});
|
|
140
129
|
|
|
130
|
+
const deleteThreadArgs = {
|
|
131
|
+
threadId: v.id("threads"),
|
|
132
|
+
cursor: v.optional(v.string()),
|
|
133
|
+
messagesDone: v.optional(v.boolean()),
|
|
134
|
+
streamsDone: v.optional(v.boolean()),
|
|
135
|
+
streamOrder: v.optional(v.number()),
|
|
136
|
+
deltaCursor: v.optional(v.string()),
|
|
137
|
+
limit: v.optional(v.number()),
|
|
138
|
+
};
|
|
139
|
+
type DeleteThreadArgs = ObjectType<typeof deleteThreadArgs>;
|
|
140
|
+
const deleteThreadReturns = {
|
|
141
|
+
cursor: v.string(),
|
|
142
|
+
isDone: v.boolean(),
|
|
143
|
+
};
|
|
144
|
+
type DeleteThreadReturns = ObjectType<typeof deleteThreadReturns>;
|
|
145
|
+
|
|
141
146
|
export const _deletePageForThreadId = internalMutation({
|
|
142
147
|
args: deleteThreadArgs,
|
|
143
148
|
handler: deletePageForThreadIdHandler,
|
|
@@ -151,22 +156,39 @@ export const _deletePageForThreadId = internalMutation({
|
|
|
151
156
|
export const deleteAllForThreadIdAsync = mutation({
|
|
152
157
|
args: deleteThreadArgs,
|
|
153
158
|
handler: async (ctx, args) => {
|
|
154
|
-
|
|
155
|
-
|
|
159
|
+
let messagesResult = {
|
|
160
|
+
isDone: args.messagesDone ?? false,
|
|
161
|
+
cursor: args.cursor,
|
|
162
|
+
};
|
|
163
|
+
if (!args.messagesDone) {
|
|
164
|
+
messagesResult = await deletePageForThreadIdHandler(ctx, args);
|
|
165
|
+
}
|
|
166
|
+
let streamResult = {
|
|
167
|
+
isDone: args.streamsDone ?? false,
|
|
168
|
+
streamOrder: args.streamOrder,
|
|
169
|
+
deltaCursor: args.deltaCursor,
|
|
170
|
+
};
|
|
171
|
+
if (!args.streamsDone) {
|
|
172
|
+
streamResult = await deleteStreamsPageForThreadId(ctx, {
|
|
173
|
+
threadId: args.threadId,
|
|
174
|
+
streamOrder: args.streamOrder,
|
|
175
|
+
deltaCursor: args.deltaCursor,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
const isDone = messagesResult.isDone && streamResult.isDone;
|
|
179
|
+
if (!isDone) {
|
|
156
180
|
await ctx.scheduler.runAfter(0, api.threads.deleteAllForThreadIdAsync, {
|
|
157
181
|
threadId: args.threadId,
|
|
158
|
-
cursor:
|
|
182
|
+
cursor: messagesResult.cursor,
|
|
183
|
+
messagesDone: messagesResult.isDone,
|
|
184
|
+
streamsDone: streamResult.isDone,
|
|
185
|
+
streamOrder: streamResult.streamOrder,
|
|
186
|
+
deltaCursor: streamResult.deltaCursor,
|
|
159
187
|
});
|
|
160
188
|
}
|
|
161
|
-
|
|
162
|
-
await ctx.scheduler.runAfter(
|
|
163
|
-
0,
|
|
164
|
-
api.streams.deleteAllStreamsForThreadIdSync,
|
|
165
|
-
{ threadId: args.threadId }
|
|
166
|
-
);
|
|
167
|
-
return result;
|
|
189
|
+
return { isDone };
|
|
168
190
|
},
|
|
169
|
-
returns:
|
|
191
|
+
returns: v.object({ isDone: v.boolean() }),
|
|
170
192
|
});
|
|
171
193
|
|
|
172
194
|
async function deletePageForThreadIdHandler(
|
package/src/react/deltas.ts
CHANGED