@convex-dev/agent 0.1.3 → 0.1.4
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/commonjs/client/index.d.ts +6 -5
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +37 -11
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/client/streaming.d.ts +2 -2
- package/dist/commonjs/client/streaming.d.ts.map +1 -1
- package/dist/commonjs/client/streaming.js +2 -1
- package/dist/commonjs/client/streaming.js.map +1 -1
- package/dist/commonjs/component/messages.d.ts +3 -3
- package/dist/commonjs/component/messages.d.ts.map +1 -1
- package/dist/commonjs/component/messages.js +16 -14
- package/dist/commonjs/component/messages.js.map +1 -1
- package/dist/commonjs/component/streams.d.ts.map +1 -1
- package/dist/commonjs/component/streams.js +1 -4
- package/dist/commonjs/component/streams.js.map +1 -1
- package/dist/commonjs/component/users.d.ts +3 -0
- package/dist/commonjs/component/users.d.ts.map +1 -1
- package/dist/commonjs/component/users.js +11 -1
- package/dist/commonjs/component/users.js.map +1 -1
- package/dist/commonjs/component/vector/index.d.ts +3 -1
- package/dist/commonjs/component/vector/index.d.ts.map +1 -1
- package/dist/commonjs/component/vector/index.js +6 -2
- package/dist/commonjs/component/vector/index.js.map +1 -1
- package/dist/commonjs/react/deltas.d.ts +29 -0
- package/dist/commonjs/react/deltas.d.ts.map +1 -0
- package/dist/commonjs/react/deltas.js +267 -0
- package/dist/commonjs/react/deltas.js.map +1 -0
- package/dist/commonjs/react/index.d.ts +4 -49
- package/dist/commonjs/react/index.d.ts.map +1 -1
- package/dist/commonjs/react/index.js +15 -446
- package/dist/commonjs/react/index.js.map +1 -1
- package/dist/commonjs/react/optimisticallySendMessage.d.ts +8 -0
- package/dist/commonjs/react/optimisticallySendMessage.d.ts.map +1 -0
- package/dist/commonjs/react/optimisticallySendMessage.js +40 -0
- package/dist/commonjs/react/optimisticallySendMessage.js.map +1 -0
- package/dist/commonjs/react/toUIMessages.d.ts.map +1 -1
- package/dist/commonjs/react/toUIMessages.js +4 -2
- package/dist/commonjs/react/toUIMessages.js.map +1 -1
- package/dist/commonjs/react/types.d.ts +26 -0
- package/dist/commonjs/react/types.d.ts.map +1 -0
- package/dist/commonjs/react/types.js +2 -0
- package/dist/commonjs/react/types.js.map +1 -0
- package/dist/commonjs/react/useSmoothText.d.ts +20 -0
- package/dist/commonjs/react/useSmoothText.d.ts.map +1 -0
- package/dist/commonjs/react/useSmoothText.js +50 -0
- package/dist/commonjs/react/useSmoothText.js.map +1 -0
- package/dist/esm/client/index.d.ts +6 -5
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +37 -11
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/streaming.d.ts +2 -2
- package/dist/esm/client/streaming.d.ts.map +1 -1
- package/dist/esm/client/streaming.js +2 -1
- package/dist/esm/client/streaming.js.map +1 -1
- package/dist/esm/component/messages.d.ts +3 -3
- package/dist/esm/component/messages.d.ts.map +1 -1
- package/dist/esm/component/messages.js +16 -14
- package/dist/esm/component/messages.js.map +1 -1
- package/dist/esm/component/streams.d.ts.map +1 -1
- package/dist/esm/component/streams.js +1 -4
- package/dist/esm/component/streams.js.map +1 -1
- package/dist/esm/component/users.d.ts +3 -0
- package/dist/esm/component/users.d.ts.map +1 -1
- package/dist/esm/component/users.js +11 -1
- package/dist/esm/component/users.js.map +1 -1
- package/dist/esm/component/vector/index.d.ts +3 -1
- package/dist/esm/component/vector/index.d.ts.map +1 -1
- package/dist/esm/component/vector/index.js +6 -2
- package/dist/esm/component/vector/index.js.map +1 -1
- package/dist/esm/react/deltas.d.ts +29 -0
- package/dist/esm/react/deltas.d.ts.map +1 -0
- package/dist/esm/react/deltas.js +267 -0
- package/dist/esm/react/deltas.js.map +1 -0
- package/dist/esm/react/index.d.ts +4 -49
- package/dist/esm/react/index.d.ts.map +1 -1
- package/dist/esm/react/index.js +15 -446
- package/dist/esm/react/index.js.map +1 -1
- package/dist/esm/react/optimisticallySendMessage.d.ts +8 -0
- package/dist/esm/react/optimisticallySendMessage.d.ts.map +1 -0
- package/dist/esm/react/optimisticallySendMessage.js +40 -0
- package/dist/esm/react/optimisticallySendMessage.js.map +1 -0
- package/dist/esm/react/toUIMessages.d.ts.map +1 -1
- package/dist/esm/react/toUIMessages.js +4 -2
- package/dist/esm/react/toUIMessages.js.map +1 -1
- package/dist/esm/react/types.d.ts +26 -0
- package/dist/esm/react/types.d.ts.map +1 -0
- package/dist/esm/react/types.js +2 -0
- package/dist/esm/react/types.js.map +1 -0
- package/dist/esm/react/useSmoothText.d.ts +20 -0
- package/dist/esm/react/useSmoothText.d.ts.map +1 -0
- package/dist/esm/react/useSmoothText.js +50 -0
- package/dist/esm/react/useSmoothText.js.map +1 -0
- package/package.json +4 -1
- package/src/client/index.ts +41 -23
- package/src/client/streaming.ts +3 -2
- package/src/component/_generated/api.d.ts +2 -2
- package/src/component/messages.ts +26 -15
- package/src/component/streams.ts +3 -4
- package/src/component/users.ts +12 -0
- package/src/component/vector/index.ts +9 -3
- package/src/react/deltas.test.ts +298 -0
- package/src/react/deltas.ts +340 -0
- package/src/react/index.ts +26 -589
- package/src/react/optimisticallySendMessage.ts +46 -0
- package/src/react/toUIMessages.test.ts +301 -0
- package/src/react/toUIMessages.ts +6 -2
- package/src/react/types.ts +52 -0
- package/src/react/useSmoothText.ts +76 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { BetterOmit, Expand } from "convex-helpers";
|
|
2
|
+
import type { FunctionArgs, FunctionReference, PaginationOptions, PaginationResult } from "convex/server";
|
|
3
|
+
import type { MessageDoc } from "../client";
|
|
4
|
+
import type { SyncStreamsReturnValue } from "../client/types";
|
|
5
|
+
import type { StreamArgs } from "../validators";
|
|
6
|
+
export type ThreadQuery<Args = unknown, M extends MessageDoc = MessageDoc> = FunctionReference<"query", "public", {
|
|
7
|
+
threadId: string;
|
|
8
|
+
paginationOpts: PaginationOptions;
|
|
9
|
+
/**
|
|
10
|
+
* If { stream: true } is passed, it will also query for stream deltas.
|
|
11
|
+
* In order for this to work, the query must take as an argument streamArgs.
|
|
12
|
+
*/
|
|
13
|
+
streamArgs?: StreamArgs;
|
|
14
|
+
} & Args, PaginationResult<M> & {
|
|
15
|
+
streams?: SyncStreamsReturnValue;
|
|
16
|
+
}>;
|
|
17
|
+
export type ThreadStreamQuery<Args = Record<string, unknown>, M extends MessageDoc = MessageDoc> = FunctionReference<"query", "public", {
|
|
18
|
+
threadId: string;
|
|
19
|
+
paginationOpts: PaginationOptions;
|
|
20
|
+
streamArgs?: StreamArgs;
|
|
21
|
+
} & Args, PaginationResult<M> & {
|
|
22
|
+
streams: SyncStreamsReturnValue;
|
|
23
|
+
}>;
|
|
24
|
+
export type ThreadMessagesArgs<Query extends ThreadQuery<unknown, MessageDoc>> = Query extends ThreadQuery<unknown, MessageDoc> ? Expand<BetterOmit<FunctionArgs<Query>, "paginationOpts" | "streamArgs">> : never;
|
|
25
|
+
export type ThreadMessagesResult<Query extends ThreadQuery<unknown, MessageDoc>> = Query extends ThreadQuery<unknown, infer M> ? M : never;
|
|
26
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/react/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,MAAM,WAAW,CACrB,IAAI,GAAG,OAAO,EACd,CAAC,SAAS,UAAU,GAAG,UAAU,IAC/B,iBAAiB,CACnB,OAAO,EACP,QAAQ,EACR;IACE,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,iBAAiB,CAAC;IAElC;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,GAAG,IAAI,EACR,gBAAgB,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,sBAAsB,CAAA;CAAE,CAC3D,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAC3B,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,CAAC,SAAS,UAAU,GAAG,UAAU,IAC/B,iBAAiB,CACnB,OAAO,EACP,QAAQ,EACR;IACE,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,iBAAiB,CAAC;IAClC,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,GAAG,IAAI,EACR,gBAAgB,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,EAAE,sBAAsB,CAAA;CAAE,CAC1D,CAAC;AAEF,MAAM,MAAM,kBAAkB,CAAC,KAAK,SAAS,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,IAC3E,KAAK,SAAS,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,GAC1C,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,gBAAgB,GAAG,YAAY,CAAC,CAAC,GACxE,KAAK,CAAC;AAEZ,MAAM,MAAM,oBAAoB,CAC9B,KAAK,SAAS,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,IAC5C,KAAK,SAAS,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/react/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A hook that smoothly displays text as it is streamed.
|
|
3
|
+
*
|
|
4
|
+
* @param text The text to display. Pass in the full text each time.
|
|
5
|
+
* @param charsPerSec The number of characters to display per second.
|
|
6
|
+
* @returns A tuple of the visible text and the state of the smooth text,
|
|
7
|
+
* including the current cursor position and whether it's still streaming.
|
|
8
|
+
* This allows you to decide if it's too far behind and you want to adjust
|
|
9
|
+
* the charsPerSec or just prefer the full text.
|
|
10
|
+
*/
|
|
11
|
+
export declare function useSmoothText(text: string, { charsPerSec, }?: {
|
|
12
|
+
/**
|
|
13
|
+
* The number of characters to display per second.
|
|
14
|
+
*/
|
|
15
|
+
charsPerSec?: number;
|
|
16
|
+
}): [string, {
|
|
17
|
+
cursor: number;
|
|
18
|
+
isStreaming: boolean;
|
|
19
|
+
}];
|
|
20
|
+
//# sourceMappingURL=useSmoothText.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSmoothText.d.ts","sourceRoot":"","sources":["../../../src/react/useSmoothText.ts"],"names":[],"mappings":"AAKA;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,EACE,WAAiB,GAClB,GAAE;IACD;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACjB,GACL,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC,CAkDpD"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
|
+
const FPS = 20;
|
|
3
|
+
const MS_PER_FRAME = 1000 / FPS;
|
|
4
|
+
const MAX_TIME_JUMP_MS = 250;
|
|
5
|
+
/**
|
|
6
|
+
* A hook that smoothly displays text as it is streamed.
|
|
7
|
+
*
|
|
8
|
+
* @param text The text to display. Pass in the full text each time.
|
|
9
|
+
* @param charsPerSec The number of characters to display per second.
|
|
10
|
+
* @returns A tuple of the visible text and the state of the smooth text,
|
|
11
|
+
* including the current cursor position and whether it's still streaming.
|
|
12
|
+
* This allows you to decide if it's too far behind and you want to adjust
|
|
13
|
+
* the charsPerSec or just prefer the full text.
|
|
14
|
+
*/
|
|
15
|
+
export function useSmoothText(text, { charsPerSec = 256, } = {}) {
|
|
16
|
+
const [visibleText, setVisibleText] = useState(text);
|
|
17
|
+
const smoothState = useRef({
|
|
18
|
+
tick: Date.now() + (text.length * 1000) / charsPerSec,
|
|
19
|
+
cursor: text.length,
|
|
20
|
+
start: Date.now(),
|
|
21
|
+
initialLength: text.length,
|
|
22
|
+
charsPerMs: charsPerSec / 1000,
|
|
23
|
+
});
|
|
24
|
+
const isStreaming = smoothState.current.cursor < text.length;
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (!isStreaming) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const latestCharsPerMs = (text.length - smoothState.current.initialLength) /
|
|
30
|
+
(Date.now() - smoothState.current.start);
|
|
31
|
+
// Smooth out the charsPerSec by averaging it with the previous value.
|
|
32
|
+
smoothState.current.charsPerMs = Math.min((2 * latestCharsPerMs + smoothState.current.charsPerMs) / 3, smoothState.current.charsPerMs * 2);
|
|
33
|
+
function update() {
|
|
34
|
+
if (smoothState.current.cursor >= text.length) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
const timeSinceLastUpdate = Math.min(MAX_TIME_JUMP_MS, now - smoothState.current.tick);
|
|
39
|
+
const chars = Math.floor(timeSinceLastUpdate * smoothState.current.charsPerMs);
|
|
40
|
+
smoothState.current.cursor = Math.min(smoothState.current.cursor + chars, text.length);
|
|
41
|
+
smoothState.current.tick = now;
|
|
42
|
+
setVisibleText(text.slice(0, smoothState.current.cursor));
|
|
43
|
+
}
|
|
44
|
+
update();
|
|
45
|
+
const interval = setInterval(update, MS_PER_FRAME);
|
|
46
|
+
return () => clearInterval(interval);
|
|
47
|
+
}, [text, isStreaming, charsPerSec]);
|
|
48
|
+
return [visibleText, { cursor: smoothState.current.cursor, isStreaming }];
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=useSmoothText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSmoothText.js","sourceRoot":"","sources":["../../../src/react/useSmoothText.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEpD,MAAM,GAAG,GAAG,EAAE,CAAC;AACf,MAAM,YAAY,GAAG,IAAI,GAAG,GAAG,CAAC;AAChC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,EACE,WAAW,GAAG,GAAG,MAMf,EAAE;IAEN,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,WAAW,GAAG,MAAM,CAAC;QACzB,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,WAAW;QACrD,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE;QACjB,aAAa,EAAE,IAAI,CAAC,MAAM;QAC1B,UAAU,EAAE,WAAW,GAAG,IAAI;KAC/B,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAE7D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,MAAM,gBAAgB,GACpB,CAAC,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC;YACjD,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC3C,sEAAsE;QACtE,WAAW,CAAC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CACvC,CAAC,CAAC,GAAG,gBAAgB,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAC3D,WAAW,CAAC,OAAO,CAAC,UAAU,GAAG,CAAC,CACnC,CAAC;QAEF,SAAS,MAAM;YACb,IAAI,WAAW,CAAC,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAC9C,OAAO;YACT,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAClC,gBAAgB,EAChB,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAC/B,CAAC;YACF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CACtB,mBAAmB,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,CACrD,CAAC;YACF,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CACnC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,KAAK,EAClC,IAAI,CAAC,MAAM,CACZ,CAAC;YACF,WAAW,CAAC,OAAO,CAAC,IAAI,GAAG,GAAG,CAAC;YAC/B,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,EAAE,CAAC;QACT,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACnD,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IAErC,OAAO,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;AAC5E,CAAC"}
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"email": "support@convex.dev",
|
|
8
8
|
"url": "https://github.com/get-convex/agent/issues"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.1.
|
|
10
|
+
"version": "0.1.4",
|
|
11
11
|
"license": "Apache-2.0",
|
|
12
12
|
"keywords": [
|
|
13
13
|
"convex",
|
|
@@ -105,6 +105,9 @@
|
|
|
105
105
|
"chokidar-cli": "^3.0.0",
|
|
106
106
|
"convex-test": "^0.0.37",
|
|
107
107
|
"eslint": "^9.24.0",
|
|
108
|
+
"eslint-plugin-jsx-a11y": "^6.8.0",
|
|
109
|
+
"eslint-plugin-react": "^7.34.0",
|
|
110
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
108
111
|
"globals": "^15.15.0",
|
|
109
112
|
"prettier": "3.2.5",
|
|
110
113
|
"typescript": "^5.8.3",
|
package/src/client/index.ts
CHANGED
|
@@ -464,7 +464,15 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
464
464
|
const searchMessages = await ctx.runAction(
|
|
465
465
|
this.component.messages.searchMessages,
|
|
466
466
|
{
|
|
467
|
-
|
|
467
|
+
searchAllMessagesForUserId: opts?.searchOtherThreads
|
|
468
|
+
? args.userId ??
|
|
469
|
+
(args.threadId &&
|
|
470
|
+
(
|
|
471
|
+
await ctx.runQuery(this.component.threads.getThread, {
|
|
472
|
+
threadId: args.threadId,
|
|
473
|
+
})
|
|
474
|
+
)?.userId)
|
|
475
|
+
: undefined,
|
|
468
476
|
threadId: args.threadId,
|
|
469
477
|
beforeMessageId: args.upToAndIncludingMessageId,
|
|
470
478
|
...(await this._searchOptionsWithDefaults(opts, messagesToSearch)),
|
|
@@ -752,7 +760,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
752
760
|
>(
|
|
753
761
|
ctx: RunActionCtx,
|
|
754
762
|
{
|
|
755
|
-
userId,
|
|
763
|
+
userId: argsUserId,
|
|
756
764
|
threadId,
|
|
757
765
|
usageHandler,
|
|
758
766
|
tools: threadTools,
|
|
@@ -773,11 +781,12 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
773
781
|
GenerateTextResult<TOOLS extends undefined ? AgentTools : TOOLS, OUTPUT> &
|
|
774
782
|
GenerationOutputMetadata
|
|
775
783
|
> {
|
|
776
|
-
const
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
);
|
|
784
|
+
const context = await this._saveMessagesAndFetchContext(ctx, args, {
|
|
785
|
+
userId: argsUserId,
|
|
786
|
+
threadId,
|
|
787
|
+
...options,
|
|
788
|
+
});
|
|
789
|
+
const { args: aiArgs, messageId, userId } = context;
|
|
781
790
|
const toolCtx = { ...ctx, userId, threadId, messageId, agent: this };
|
|
782
791
|
const tools = wrapTools(
|
|
783
792
|
toolCtx,
|
|
@@ -848,7 +857,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
848
857
|
>(
|
|
849
858
|
ctx: RunActionCtx,
|
|
850
859
|
{
|
|
851
|
-
userId,
|
|
860
|
+
userId: argsUserId,
|
|
852
861
|
threadId,
|
|
853
862
|
usageHandler,
|
|
854
863
|
/**
|
|
@@ -891,11 +900,11 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
891
900
|
GenerationOutputMetadata
|
|
892
901
|
> {
|
|
893
902
|
const context = await this._saveMessagesAndFetchContext(ctx, args, {
|
|
894
|
-
userId,
|
|
903
|
+
userId: argsUserId,
|
|
895
904
|
threadId,
|
|
896
905
|
...options,
|
|
897
906
|
});
|
|
898
|
-
const { args: aiArgs, messageId, order, stepOrder } = context;
|
|
907
|
+
const { args: aiArgs, messageId, order, stepOrder, userId } = context;
|
|
899
908
|
const toolCtx = { ...ctx, userId, threadId, messageId, agent: this };
|
|
900
909
|
const tools = wrapTools(
|
|
901
910
|
toolCtx,
|
|
@@ -993,7 +1002,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
993
1002
|
ctx: RunActionCtx | RunMutationCtx,
|
|
994
1003
|
args: T,
|
|
995
1004
|
{
|
|
996
|
-
userId,
|
|
1005
|
+
userId: argsUserId,
|
|
997
1006
|
threadId,
|
|
998
1007
|
contextOptions,
|
|
999
1008
|
storageOptions,
|
|
@@ -1003,6 +1012,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1003
1012
|
} & Options
|
|
1004
1013
|
): Promise<{
|
|
1005
1014
|
args: T & { model: LanguageModelV1 };
|
|
1015
|
+
userId: string | undefined;
|
|
1006
1016
|
messageId: string | undefined;
|
|
1007
1017
|
order: number | undefined;
|
|
1008
1018
|
stepOrder: number | undefined;
|
|
@@ -1013,6 +1023,11 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1013
1023
|
const messages = args.promptMessageId
|
|
1014
1024
|
? []
|
|
1015
1025
|
: promptOrMessagesToCoreMessages(args);
|
|
1026
|
+
const userId =
|
|
1027
|
+
argsUserId ??
|
|
1028
|
+
(threadId &&
|
|
1029
|
+
(await ctx.runQuery(this.component.threads.getThread, { threadId }))
|
|
1030
|
+
?.userId);
|
|
1016
1031
|
assert(
|
|
1017
1032
|
!args.promptMessageId || !(args.prompt || args.messages),
|
|
1018
1033
|
"you can't specify a prompt or message if you specify a promptMessageId"
|
|
@@ -1063,6 +1078,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1063
1078
|
...messages,
|
|
1064
1079
|
],
|
|
1065
1080
|
} as T & { model: LanguageModelV1 },
|
|
1081
|
+
userId,
|
|
1066
1082
|
messageId,
|
|
1067
1083
|
order,
|
|
1068
1084
|
stepOrder,
|
|
@@ -1079,7 +1095,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1079
1095
|
async generateObject<T>(
|
|
1080
1096
|
ctx: RunActionCtx,
|
|
1081
1097
|
{
|
|
1082
|
-
userId,
|
|
1098
|
+
userId: argsUserId,
|
|
1083
1099
|
threadId,
|
|
1084
1100
|
usageHandler,
|
|
1085
1101
|
}: { userId?: string; threadId?: string; usageHandler?: UsageHandler },
|
|
@@ -1093,11 +1109,12 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1093
1109
|
*/
|
|
1094
1110
|
options?: Options
|
|
1095
1111
|
): Promise<GenerateObjectResult<T> & GenerationOutputMetadata> {
|
|
1096
|
-
const
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
);
|
|
1112
|
+
const context = await this._saveMessagesAndFetchContext(ctx, args, {
|
|
1113
|
+
userId: argsUserId,
|
|
1114
|
+
threadId,
|
|
1115
|
+
...options,
|
|
1116
|
+
});
|
|
1117
|
+
const { args: aiArgs, messageId, userId } = context;
|
|
1101
1118
|
const trackUsage = usageHandler ?? this.options.usageHandler;
|
|
1102
1119
|
const saveOutputMessages =
|
|
1103
1120
|
options?.storageOptions?.saveOutputMessages ??
|
|
@@ -1150,7 +1167,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1150
1167
|
async streamObject<T>(
|
|
1151
1168
|
ctx: RunActionCtx,
|
|
1152
1169
|
{
|
|
1153
|
-
userId,
|
|
1170
|
+
userId: argsUserId,
|
|
1154
1171
|
threadId,
|
|
1155
1172
|
usageHandler,
|
|
1156
1173
|
}: { userId?: string; threadId?: string; usageHandler?: UsageHandler },
|
|
@@ -1167,11 +1184,12 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1167
1184
|
StreamObjectResult<DeepPartial<T>, T, never> & GenerationOutputMetadata
|
|
1168
1185
|
> {
|
|
1169
1186
|
// TODO: unify all this shared code between all the generate* and stream* functions
|
|
1170
|
-
const
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
);
|
|
1187
|
+
const context = await this._saveMessagesAndFetchContext(ctx, args, {
|
|
1188
|
+
userId: argsUserId,
|
|
1189
|
+
threadId,
|
|
1190
|
+
...options,
|
|
1191
|
+
});
|
|
1192
|
+
const { args: aiArgs, messageId, userId } = context;
|
|
1175
1193
|
const trackUsage = usageHandler ?? this.options.usageHandler;
|
|
1176
1194
|
const saveOutputMessages =
|
|
1177
1195
|
options?.storageOptions?.saveOutputMessages ??
|
package/src/client/streaming.ts
CHANGED
|
@@ -9,7 +9,7 @@ export type StreamingOptions = {
|
|
|
9
9
|
* Note: this is not a guarantee that every delta will be exactly one line.
|
|
10
10
|
* E.g. if "line" is specified, it won't save any deltas until it encounters
|
|
11
11
|
* a newline character.
|
|
12
|
-
* Defaults to
|
|
12
|
+
* Defaults to a regex that chunks by punctuation followed by whitespace.
|
|
13
13
|
*/
|
|
14
14
|
chunking?: "word" | "line" | RegExp | ChunkDetector;
|
|
15
15
|
/**
|
|
@@ -19,7 +19,8 @@ export type StreamingOptions = {
|
|
|
19
19
|
throttleMs?: number;
|
|
20
20
|
};
|
|
21
21
|
export const DEFAULT_STREAMING_OPTIONS = {
|
|
22
|
-
|
|
22
|
+
// This chunks by sentences / clauses. Punctuation followed by whitespace.
|
|
23
|
+
chunking: /[\p{P}\s]/u,
|
|
23
24
|
throttleMs: 250,
|
|
24
25
|
} satisfies StreamingOptions;
|
|
25
26
|
|
|
@@ -1375,9 +1375,9 @@ export type Mounts = {
|
|
|
1375
1375
|
beforeMessageId?: string;
|
|
1376
1376
|
limit: number;
|
|
1377
1377
|
messageRange?: { after: number; before: number };
|
|
1378
|
+
searchAllMessagesForUserId?: string;
|
|
1378
1379
|
text?: string;
|
|
1379
1380
|
threadId?: string;
|
|
1380
|
-
userId?: string;
|
|
1381
1381
|
vector?: Array<number>;
|
|
1382
1382
|
vectorModel?: string;
|
|
1383
1383
|
vectorScoreThreshold?: number;
|
|
@@ -1529,9 +1529,9 @@ export type Mounts = {
|
|
|
1529
1529
|
{
|
|
1530
1530
|
beforeMessageId?: string;
|
|
1531
1531
|
limit: number;
|
|
1532
|
+
searchAllMessagesForUserId?: string;
|
|
1532
1533
|
text: string;
|
|
1533
1534
|
threadId?: string;
|
|
1534
|
-
userId?: string;
|
|
1535
1535
|
},
|
|
1536
1536
|
Array<{
|
|
1537
1537
|
_creationTime: number;
|
|
@@ -454,19 +454,22 @@ export const getThreadMessages = query({
|
|
|
454
454
|
|
|
455
455
|
export const searchMessages = action({
|
|
456
456
|
args: {
|
|
457
|
-
userId: v.optional(v.string()),
|
|
458
457
|
threadId: v.optional(v.id("threads")),
|
|
458
|
+
searchAllMessagesForUserId: v.optional(v.string()),
|
|
459
459
|
beforeMessageId: v.optional(v.id("messages")),
|
|
460
460
|
...vSearchOptions.fields,
|
|
461
461
|
},
|
|
462
462
|
returns: v.array(vMessageDoc),
|
|
463
463
|
handler: async (ctx, args): Promise<MessageDoc[]> => {
|
|
464
|
-
assert(
|
|
464
|
+
assert(
|
|
465
|
+
args.searchAllMessagesForUserId || args.threadId,
|
|
466
|
+
"Specify userId or threadId"
|
|
467
|
+
);
|
|
465
468
|
const limit = args.limit;
|
|
466
469
|
let textSearchMessages: MessageDoc[] | undefined;
|
|
467
470
|
if (args.text) {
|
|
468
471
|
textSearchMessages = await ctx.runQuery(api.messages.textSearch, {
|
|
469
|
-
|
|
472
|
+
searchAllMessagesForUserId: args.searchAllMessagesForUserId,
|
|
470
473
|
threadId: args.threadId,
|
|
471
474
|
text: args.text,
|
|
472
475
|
limit,
|
|
@@ -483,7 +486,7 @@ export const searchMessages = action({
|
|
|
483
486
|
dimension,
|
|
484
487
|
model: args.vectorModel ?? "unknown",
|
|
485
488
|
table: "messages",
|
|
486
|
-
|
|
489
|
+
searchAllMessagesForUserId: args.searchAllMessagesForUserId,
|
|
487
490
|
threadId: args.threadId,
|
|
488
491
|
limit,
|
|
489
492
|
})
|
|
@@ -503,7 +506,7 @@ export const searchMessages = action({
|
|
|
503
506
|
const messages: MessageDoc[] = await ctx.runQuery(
|
|
504
507
|
internal.messages._fetchSearchMessages,
|
|
505
508
|
{
|
|
506
|
-
|
|
509
|
+
searchAllMessagesForUserId: args.searchAllMessagesForUserId,
|
|
507
510
|
threadId: args.threadId,
|
|
508
511
|
vectorIds,
|
|
509
512
|
textSearchMessages: textSearchMessages?.filter(
|
|
@@ -522,9 +525,9 @@ export const searchMessages = action({
|
|
|
522
525
|
|
|
523
526
|
export const _fetchSearchMessages = internalQuery({
|
|
524
527
|
args: {
|
|
525
|
-
userId: v.optional(v.string()),
|
|
526
528
|
threadId: v.optional(v.id("threads")),
|
|
527
529
|
vectorIds: v.array(vVectorId),
|
|
530
|
+
searchAllMessagesForUserId: v.optional(v.string()),
|
|
528
531
|
textSearchMessages: v.optional(v.array(vMessageDoc)),
|
|
529
532
|
messageRange: v.object({ before: v.number(), after: v.number() }),
|
|
530
533
|
beforeMessageId: v.optional(v.id("messages")),
|
|
@@ -534,8 +537,11 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
534
537
|
handler: async (ctx, args): Promise<MessageDoc[]> => {
|
|
535
538
|
const beforeMessage =
|
|
536
539
|
args.beforeMessageId && (await ctx.db.get(args.beforeMessageId));
|
|
537
|
-
const {
|
|
538
|
-
assert(
|
|
540
|
+
const { searchAllMessagesForUserId, threadId } = args;
|
|
541
|
+
assert(
|
|
542
|
+
searchAllMessagesForUserId || threadId,
|
|
543
|
+
"Specify searchAllMessagesForUserId or threadId to search"
|
|
544
|
+
);
|
|
539
545
|
let messages: MessageDoc[] = (
|
|
540
546
|
await Promise.all(
|
|
541
547
|
args.vectorIds.map((embeddingId) =>
|
|
@@ -543,9 +549,9 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
543
549
|
.query("messages")
|
|
544
550
|
.withIndex("embeddingId", (q) => q.eq("embeddingId", embeddingId))
|
|
545
551
|
.filter((q) =>
|
|
546
|
-
|
|
547
|
-
? q.eq(q.field("userId"),
|
|
548
|
-
: q.eq(q.field("threadId"), threadId)
|
|
552
|
+
searchAllMessagesForUserId
|
|
553
|
+
? q.eq(q.field("userId"), searchAllMessagesForUserId)
|
|
554
|
+
: q.eq(q.field("threadId"), threadId!)
|
|
549
555
|
)
|
|
550
556
|
// Don't include pending. Failed messages hopefully are deleted but may as well be safe.
|
|
551
557
|
.filter((q) => q.eq(q.field("status"), "success"))
|
|
@@ -632,21 +638,26 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
632
638
|
export const textSearch = query({
|
|
633
639
|
args: {
|
|
634
640
|
threadId: v.optional(v.id("threads")),
|
|
635
|
-
|
|
641
|
+
searchAllMessagesForUserId: v.optional(v.string()),
|
|
636
642
|
text: v.string(),
|
|
637
643
|
limit: v.number(),
|
|
638
644
|
beforeMessageId: v.optional(v.id("messages")),
|
|
639
645
|
},
|
|
640
646
|
handler: async (ctx, args) => {
|
|
641
|
-
assert(
|
|
647
|
+
assert(
|
|
648
|
+
args.searchAllMessagesForUserId || args.threadId,
|
|
649
|
+
"Specify userId or threadId"
|
|
650
|
+
);
|
|
642
651
|
const beforeMessage =
|
|
643
652
|
args.beforeMessageId && (await ctx.db.get(args.beforeMessageId));
|
|
644
653
|
const order = beforeMessage?.order;
|
|
645
654
|
const messages = await ctx.db
|
|
646
655
|
.query("messages")
|
|
647
656
|
.withSearchIndex("text_search", (q) =>
|
|
648
|
-
args.
|
|
649
|
-
? q
|
|
657
|
+
args.searchAllMessagesForUserId
|
|
658
|
+
? q
|
|
659
|
+
.search("text", args.text)
|
|
660
|
+
.eq("userId", args.searchAllMessagesForUserId)
|
|
650
661
|
: q.search("text", args.text).eq("threadId", args.threadId!)
|
|
651
662
|
)
|
|
652
663
|
// Just in case tool messages slip through
|
package/src/component/streams.ts
CHANGED
|
@@ -51,10 +51,9 @@ export const listDeltas = query({
|
|
|
51
51
|
);
|
|
52
52
|
totalDeltas += streamDeltas.length;
|
|
53
53
|
deltas.push(
|
|
54
|
-
...streamDeltas.map((d) =>
|
|
55
|
-
streamId
|
|
56
|
-
|
|
57
|
-
}))
|
|
54
|
+
...streamDeltas.map((d) =>
|
|
55
|
+
pick(d, ["streamId", "start", "end", "parts"])
|
|
56
|
+
)
|
|
58
57
|
);
|
|
59
58
|
if (totalDeltas >= MAX_DELTAS_PER_REQUEST) {
|
|
60
59
|
break;
|
package/src/component/users.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { internal } from "./_generated/api.js";
|
|
|
5
5
|
import {
|
|
6
6
|
action,
|
|
7
7
|
internalMutation,
|
|
8
|
+
internalQuery,
|
|
8
9
|
mutation,
|
|
9
10
|
MutationCtx,
|
|
10
11
|
query,
|
|
@@ -168,3 +169,14 @@ async function deletePageForUserId(
|
|
|
168
169
|
isDone: false,
|
|
169
170
|
};
|
|
170
171
|
}
|
|
172
|
+
|
|
173
|
+
export const getThreadUserId = internalQuery({
|
|
174
|
+
args: {
|
|
175
|
+
threadId: v.id("threads"),
|
|
176
|
+
},
|
|
177
|
+
returns: v.union(v.string(), v.null()),
|
|
178
|
+
handler: async (ctx, args) => {
|
|
179
|
+
const thread = await ctx.db.get(args.threadId);
|
|
180
|
+
return thread?.userId ?? null;
|
|
181
|
+
},
|
|
182
|
+
});
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import schema from "../schema";
|
|
13
13
|
import { mergedStream } from "convex-helpers/server/stream";
|
|
14
14
|
import { stream } from "convex-helpers/server/stream";
|
|
15
|
+
import { Id } from "../_generated/dataModel";
|
|
15
16
|
|
|
16
17
|
export const paginate = query({
|
|
17
18
|
args: {
|
|
@@ -124,7 +125,8 @@ export function searchVectors(
|
|
|
124
125
|
model: string;
|
|
125
126
|
table: string;
|
|
126
127
|
userId?: string;
|
|
127
|
-
threadId?:
|
|
128
|
+
threadId?: Id<"threads">;
|
|
129
|
+
searchAllMessagesForUserId?: string;
|
|
128
130
|
limit?: number;
|
|
129
131
|
}
|
|
130
132
|
) {
|
|
@@ -133,8 +135,12 @@ export function searchVectors(
|
|
|
133
135
|
vector,
|
|
134
136
|
// TODO: to support more tables, add more "OR" clauses for each.
|
|
135
137
|
filter: (q) =>
|
|
136
|
-
args.
|
|
137
|
-
? q.eq("model_table_userId", [
|
|
138
|
+
args.searchAllMessagesForUserId
|
|
139
|
+
? q.eq("model_table_userId", [
|
|
140
|
+
args.model,
|
|
141
|
+
args.table,
|
|
142
|
+
args.searchAllMessagesForUserId,
|
|
143
|
+
])
|
|
138
144
|
: q.eq("model_table_threadId", [
|
|
139
145
|
args.model,
|
|
140
146
|
args.table,
|