@librechat/agents 2.4.318 → 2.4.320
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/cjs/events.cjs +3 -3
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/main.cjs +5 -2
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/ids.cjs +23 -0
- package/dist/cjs/messages/ids.cjs.map +1 -0
- package/dist/cjs/stream.cjs +8 -155
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +144 -0
- package/dist/cjs/tools/handlers.cjs.map +1 -0
- package/dist/cjs/tools/search/search.cjs +18 -8
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +85 -61
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +3 -1
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/esm/events.mjs +1 -1
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/main.mjs +3 -1
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/messages/ids.mjs +21 -0
- package/dist/esm/messages/ids.mjs.map +1 -0
- package/dist/esm/stream.mjs +7 -152
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +141 -0
- package/dist/esm/tools/handlers.mjs.map +1 -0
- package/dist/esm/tools/search/search.mjs +18 -8
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +84 -60
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +3 -1
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/messages/ids.d.ts +3 -0
- package/dist/types/messages/index.d.ts +1 -0
- package/dist/types/stream.d.ts +0 -8
- package/dist/types/tools/handlers.d.ts +8 -0
- package/dist/types/tools/search/search.d.ts +1 -1
- package/dist/types/tools/search/types.d.ts +28 -8
- package/package.json +1 -1
- package/src/events.ts +49 -15
- package/src/index.ts +1 -0
- package/src/messages/ids.ts +26 -0
- package/src/messages/index.ts +1 -0
- package/src/stream.ts +4 -186
- package/src/tools/handlers.ts +167 -0
- package/src/tools/search/search.ts +27 -15
- package/src/tools/search/tool.ts +137 -91
- package/src/tools/search/types.ts +37 -10
- package/src/tools/search/utils.ts +5 -1
package/package.json
CHANGED
package/src/events.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
// src/events.ts
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
UsageMetadata,
|
|
5
|
+
BaseMessageFields,
|
|
6
|
+
} from '@langchain/core/messages';
|
|
4
7
|
import type { Graph } from '@/graphs';
|
|
5
8
|
import type * as t from '@/types';
|
|
6
|
-
import { handleToolCalls } from '@/
|
|
9
|
+
import { handleToolCalls } from '@/tools/handlers';
|
|
7
10
|
import { Providers } from '@/common';
|
|
8
11
|
|
|
9
12
|
export class HandlerRegistry {
|
|
@@ -27,7 +30,12 @@ export class ModelEndHandler implements t.EventHandler {
|
|
|
27
30
|
this.collectedUsage = collectedUsage;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
|
-
handle(
|
|
33
|
+
handle(
|
|
34
|
+
event: string,
|
|
35
|
+
data: t.ModelEndData,
|
|
36
|
+
metadata?: Record<string, unknown>,
|
|
37
|
+
graph?: Graph
|
|
38
|
+
): void {
|
|
31
39
|
if (!graph || !metadata) {
|
|
32
40
|
console.warn(`Graph or metadata not found in ${event} event`);
|
|
33
41
|
return;
|
|
@@ -43,9 +51,12 @@ export class ModelEndHandler implements t.EventHandler {
|
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
console.log(`====== ${event.toUpperCase()} ======`);
|
|
46
|
-
console.dir(
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
console.dir(
|
|
55
|
+
{
|
|
56
|
+
usage,
|
|
57
|
+
},
|
|
58
|
+
{ depth: null }
|
|
59
|
+
);
|
|
49
60
|
|
|
50
61
|
if (metadata.provider !== Providers.GOOGLE) {
|
|
51
62
|
return;
|
|
@@ -60,7 +71,12 @@ export class ToolEndHandler implements t.EventHandler {
|
|
|
60
71
|
constructor(callback?: t.ToolEndCallback) {
|
|
61
72
|
this.callback = callback;
|
|
62
73
|
}
|
|
63
|
-
handle(
|
|
74
|
+
handle(
|
|
75
|
+
event: string,
|
|
76
|
+
data: t.StreamEventData | undefined,
|
|
77
|
+
metadata?: Record<string, unknown>,
|
|
78
|
+
graph?: Graph
|
|
79
|
+
): void {
|
|
64
80
|
if (!graph || !metadata) {
|
|
65
81
|
console.warn(`Graph or metadata not found in ${event} event`);
|
|
66
82
|
return;
|
|
@@ -74,14 +90,17 @@ export class ToolEndHandler implements t.EventHandler {
|
|
|
74
90
|
|
|
75
91
|
this.callback?.(toolEndData, metadata);
|
|
76
92
|
|
|
77
|
-
graph.handleToolCallCompleted(
|
|
93
|
+
graph.handleToolCallCompleted(
|
|
94
|
+
{ input: toolEndData.input, output: toolEndData.output },
|
|
95
|
+
metadata
|
|
96
|
+
);
|
|
78
97
|
}
|
|
79
98
|
}
|
|
80
99
|
|
|
81
100
|
export class TestLLMStreamHandler implements t.EventHandler {
|
|
82
101
|
handle(event: string, data: t.StreamEventData | undefined): void {
|
|
83
102
|
const chunk = data?.chunk;
|
|
84
|
-
const
|
|
103
|
+
const isMessageChunk = !!(chunk && 'message' in chunk);
|
|
85
104
|
const msg = isMessageChunk ? chunk.message : undefined;
|
|
86
105
|
if (msg && msg.tool_call_chunks && msg.tool_call_chunks.length > 0) {
|
|
87
106
|
console.log(msg.tool_call_chunks);
|
|
@@ -116,11 +135,17 @@ export class TestChatStreamHandler implements t.EventHandler {
|
|
|
116
135
|
}
|
|
117
136
|
|
|
118
137
|
export class LLMStreamHandler implements t.EventHandler {
|
|
119
|
-
handle(
|
|
138
|
+
handle(
|
|
139
|
+
event: string,
|
|
140
|
+
data: t.StreamEventData | undefined,
|
|
141
|
+
metadata?: Record<string, unknown>
|
|
142
|
+
): void {
|
|
120
143
|
const chunk = data?.chunk;
|
|
121
|
-
const
|
|
144
|
+
const isMessageChunk = !!(chunk && 'message' in chunk);
|
|
122
145
|
const msg = isMessageChunk && chunk.message;
|
|
123
|
-
if (metadata) {
|
|
146
|
+
if (metadata) {
|
|
147
|
+
console.log(metadata);
|
|
148
|
+
}
|
|
124
149
|
if (msg && msg.tool_call_chunks && msg.tool_call_chunks.length > 0) {
|
|
125
150
|
console.log(msg.tool_call_chunks);
|
|
126
151
|
} else if (msg && msg.content) {
|
|
@@ -133,12 +158,21 @@ export class LLMStreamHandler implements t.EventHandler {
|
|
|
133
158
|
}
|
|
134
159
|
}
|
|
135
160
|
|
|
136
|
-
export const createMetadataAggregator = (
|
|
161
|
+
export const createMetadataAggregator = (
|
|
162
|
+
_collected?: Record<
|
|
163
|
+
string,
|
|
164
|
+
NonNullable<BaseMessageFields['response_metadata']>
|
|
165
|
+
>[]
|
|
166
|
+
): t.MetadataAggregatorResult => {
|
|
137
167
|
const collected = _collected || [];
|
|
138
168
|
|
|
139
169
|
const handleLLMEnd: t.HandleLLMEnd = (output) => {
|
|
140
170
|
const { generations } = output;
|
|
141
|
-
const lastMessageOutput = (
|
|
171
|
+
const lastMessageOutput = (
|
|
172
|
+
generations[generations.length - 1] as
|
|
173
|
+
| (t.StreamGeneration | undefined)[]
|
|
174
|
+
| undefined
|
|
175
|
+
)?.[0];
|
|
142
176
|
if (!lastMessageOutput) {
|
|
143
177
|
return;
|
|
144
178
|
}
|
|
@@ -149,4 +183,4 @@ export const createMetadataAggregator = (_collected?: Record<string, NonNullable
|
|
|
149
183
|
};
|
|
150
184
|
|
|
151
185
|
return { handleLLMEnd, collected };
|
|
152
|
-
};
|
|
186
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/stream.ts
|
|
2
|
+
import { nanoid } from 'nanoid';
|
|
3
|
+
import type { Graph } from '@/graphs';
|
|
4
|
+
import type * as t from '@/types';
|
|
5
|
+
|
|
6
|
+
export const getMessageId = (
|
|
7
|
+
stepKey: string,
|
|
8
|
+
graph: Graph<t.BaseGraphState>,
|
|
9
|
+
returnExistingId = false
|
|
10
|
+
): string | undefined => {
|
|
11
|
+
const messageId = graph.messageIdsByStepKey.get(stepKey);
|
|
12
|
+
if (messageId != null && messageId) {
|
|
13
|
+
return returnExistingId ? messageId : undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const prelimMessageId = graph.prelimMessageIdsByStepKey.get(stepKey);
|
|
17
|
+
if (prelimMessageId != null && prelimMessageId) {
|
|
18
|
+
graph.prelimMessageIdsByStepKey.delete(stepKey);
|
|
19
|
+
graph.messageIdsByStepKey.set(stepKey, prelimMessageId);
|
|
20
|
+
return prelimMessageId;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const message_id = `msg_${nanoid()}`;
|
|
24
|
+
graph.messageIdsByStepKey.set(stepKey, message_id);
|
|
25
|
+
return message_id;
|
|
26
|
+
};
|
package/src/messages/index.ts
CHANGED
package/src/stream.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// src/stream.ts
|
|
2
|
-
import { nanoid } from 'nanoid';
|
|
3
2
|
import type { AIMessageChunk } from '@langchain/core/messages';
|
|
4
|
-
import type { ToolCall
|
|
3
|
+
import type { ToolCall } from '@langchain/core/messages/tool';
|
|
5
4
|
import type { Graph } from '@/graphs';
|
|
6
5
|
import type * as t from '@/types';
|
|
7
6
|
import { StepTypes, ContentTypes, GraphEvents, ToolCallTypes } from '@/common';
|
|
7
|
+
import { handleToolCalls, handleToolCallChunks } from '@/tools/handlers';
|
|
8
|
+
import { getMessageId } from '@/messages';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Parses content to extract thinking sections enclosed in <think> tags using string operations
|
|
@@ -65,107 +66,6 @@ function getNonEmptyValue(possibleValues: string[]): string | undefined {
|
|
|
65
66
|
}
|
|
66
67
|
return undefined;
|
|
67
68
|
}
|
|
68
|
-
|
|
69
|
-
export const getMessageId = (
|
|
70
|
-
stepKey: string,
|
|
71
|
-
graph: Graph<t.BaseGraphState>,
|
|
72
|
-
returnExistingId = false
|
|
73
|
-
): string | undefined => {
|
|
74
|
-
const messageId = graph.messageIdsByStepKey.get(stepKey);
|
|
75
|
-
if (messageId != null && messageId) {
|
|
76
|
-
return returnExistingId ? messageId : undefined;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const prelimMessageId = graph.prelimMessageIdsByStepKey.get(stepKey);
|
|
80
|
-
if (prelimMessageId != null && prelimMessageId) {
|
|
81
|
-
graph.prelimMessageIdsByStepKey.delete(stepKey);
|
|
82
|
-
graph.messageIdsByStepKey.set(stepKey, prelimMessageId);
|
|
83
|
-
return prelimMessageId;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const message_id = `msg_${nanoid()}`;
|
|
87
|
-
graph.messageIdsByStepKey.set(stepKey, message_id);
|
|
88
|
-
return message_id;
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export const handleToolCalls = (
|
|
92
|
-
toolCalls?: ToolCall[],
|
|
93
|
-
metadata?: Record<string, unknown>,
|
|
94
|
-
graph?: Graph
|
|
95
|
-
): void => {
|
|
96
|
-
if (!graph || !metadata) {
|
|
97
|
-
console.warn(`Graph or metadata not found in ${event} event`);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (!toolCalls) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (toolCalls.length === 0) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const stepKey = graph.getStepKey(metadata);
|
|
110
|
-
|
|
111
|
-
for (const tool_call of toolCalls) {
|
|
112
|
-
const toolCallId = tool_call.id ?? `toolu_${nanoid()}`;
|
|
113
|
-
tool_call.id = toolCallId;
|
|
114
|
-
if (!toolCallId || graph.toolCallStepIds.has(toolCallId)) {
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
let prevStepId = '';
|
|
119
|
-
let prevRunStep: t.RunStep | undefined;
|
|
120
|
-
try {
|
|
121
|
-
prevStepId = graph.getStepIdByKey(stepKey, graph.contentData.length - 1);
|
|
122
|
-
prevRunStep = graph.getRunStep(prevStepId);
|
|
123
|
-
} catch {
|
|
124
|
-
// no previous step
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const dispatchToolCallIds = (lastMessageStepId: string): void => {
|
|
128
|
-
graph.dispatchMessageDelta(lastMessageStepId, {
|
|
129
|
-
content: [
|
|
130
|
-
{
|
|
131
|
-
type: 'text',
|
|
132
|
-
text: '',
|
|
133
|
-
tool_call_ids: [toolCallId],
|
|
134
|
-
},
|
|
135
|
-
],
|
|
136
|
-
});
|
|
137
|
-
};
|
|
138
|
-
/* If the previous step exists and is a message creation */
|
|
139
|
-
if (
|
|
140
|
-
prevStepId &&
|
|
141
|
-
prevRunStep &&
|
|
142
|
-
prevRunStep.type === StepTypes.MESSAGE_CREATION
|
|
143
|
-
) {
|
|
144
|
-
dispatchToolCallIds(prevStepId);
|
|
145
|
-
graph.messageStepHasToolCalls.set(prevStepId, true);
|
|
146
|
-
/* If the previous step doesn't exist or is not a message creation */
|
|
147
|
-
} else if (
|
|
148
|
-
!prevRunStep ||
|
|
149
|
-
prevRunStep.type !== StepTypes.MESSAGE_CREATION
|
|
150
|
-
) {
|
|
151
|
-
const messageId = getMessageId(stepKey, graph, true) ?? '';
|
|
152
|
-
const stepId = graph.dispatchRunStep(stepKey, {
|
|
153
|
-
type: StepTypes.MESSAGE_CREATION,
|
|
154
|
-
message_creation: {
|
|
155
|
-
message_id: messageId,
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
dispatchToolCallIds(stepId);
|
|
159
|
-
graph.messageStepHasToolCalls.set(prevStepId, true);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
graph.dispatchRunStep(stepKey, {
|
|
163
|
-
type: StepTypes.TOOL_CALLS,
|
|
164
|
-
tool_calls: [tool_call],
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
|
|
169
69
|
export class ChatModelStreamHandler implements t.EventHandler {
|
|
170
70
|
handle(
|
|
171
71
|
event: string,
|
|
@@ -230,7 +130,7 @@ export class ChatModelStreamHandler implements t.EventHandler {
|
|
|
230
130
|
chunk.tool_call_chunks.length &&
|
|
231
131
|
typeof chunk.tool_call_chunks[0]?.index === 'number'
|
|
232
132
|
) {
|
|
233
|
-
|
|
133
|
+
handleToolCallChunks({
|
|
234
134
|
graph,
|
|
235
135
|
stepKey,
|
|
236
136
|
toolCallChunks: chunk.tool_call_chunks,
|
|
@@ -358,88 +258,6 @@ hasToolCallChunks: ${hasToolCallChunks}
|
|
|
358
258
|
});
|
|
359
259
|
}
|
|
360
260
|
}
|
|
361
|
-
handleToolCallChunks = ({
|
|
362
|
-
graph,
|
|
363
|
-
stepKey,
|
|
364
|
-
toolCallChunks,
|
|
365
|
-
}: {
|
|
366
|
-
graph: Graph;
|
|
367
|
-
stepKey: string;
|
|
368
|
-
toolCallChunks: ToolCallChunk[];
|
|
369
|
-
}): void => {
|
|
370
|
-
let prevStepId: string;
|
|
371
|
-
let prevRunStep: t.RunStep | undefined;
|
|
372
|
-
try {
|
|
373
|
-
prevStepId = graph.getStepIdByKey(stepKey, graph.contentData.length - 1);
|
|
374
|
-
prevRunStep = graph.getRunStep(prevStepId);
|
|
375
|
-
} catch {
|
|
376
|
-
/** Edge Case: If no previous step exists, create a new message creation step */
|
|
377
|
-
const message_id = getMessageId(stepKey, graph, true) ?? '';
|
|
378
|
-
prevStepId = graph.dispatchRunStep(stepKey, {
|
|
379
|
-
type: StepTypes.MESSAGE_CREATION,
|
|
380
|
-
message_creation: {
|
|
381
|
-
message_id,
|
|
382
|
-
},
|
|
383
|
-
});
|
|
384
|
-
prevRunStep = graph.getRunStep(prevStepId);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
const _stepId = graph.getStepIdByKey(stepKey, prevRunStep?.index);
|
|
388
|
-
|
|
389
|
-
/** Edge Case: Tool Call Run Step or `tool_call_ids` never dispatched */
|
|
390
|
-
const tool_calls: ToolCall[] | undefined =
|
|
391
|
-
prevStepId &&
|
|
392
|
-
prevRunStep &&
|
|
393
|
-
prevRunStep.type === StepTypes.MESSAGE_CREATION
|
|
394
|
-
? []
|
|
395
|
-
: undefined;
|
|
396
|
-
|
|
397
|
-
/** Edge Case: `id` and `name` fields cannot be empty strings */
|
|
398
|
-
for (const toolCallChunk of toolCallChunks) {
|
|
399
|
-
if (toolCallChunk.name === '') {
|
|
400
|
-
toolCallChunk.name = undefined;
|
|
401
|
-
}
|
|
402
|
-
if (toolCallChunk.id === '') {
|
|
403
|
-
toolCallChunk.id = undefined;
|
|
404
|
-
} else if (
|
|
405
|
-
tool_calls != null &&
|
|
406
|
-
toolCallChunk.id != null &&
|
|
407
|
-
toolCallChunk.name != null
|
|
408
|
-
) {
|
|
409
|
-
tool_calls.push({
|
|
410
|
-
args: {},
|
|
411
|
-
id: toolCallChunk.id,
|
|
412
|
-
name: toolCallChunk.name,
|
|
413
|
-
type: ToolCallTypes.TOOL_CALL,
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
let stepId: string = _stepId;
|
|
419
|
-
const alreadyDispatched =
|
|
420
|
-
prevRunStep?.type === StepTypes.MESSAGE_CREATION &&
|
|
421
|
-
graph.messageStepHasToolCalls.has(prevStepId);
|
|
422
|
-
if (!alreadyDispatched && tool_calls?.length === toolCallChunks.length) {
|
|
423
|
-
graph.dispatchMessageDelta(prevStepId, {
|
|
424
|
-
content: [
|
|
425
|
-
{
|
|
426
|
-
type: ContentTypes.TEXT,
|
|
427
|
-
text: '',
|
|
428
|
-
tool_call_ids: tool_calls.map((tc) => tc.id ?? ''),
|
|
429
|
-
},
|
|
430
|
-
],
|
|
431
|
-
});
|
|
432
|
-
graph.messageStepHasToolCalls.set(prevStepId, true);
|
|
433
|
-
stepId = graph.dispatchRunStep(stepKey, {
|
|
434
|
-
type: StepTypes.TOOL_CALLS,
|
|
435
|
-
tool_calls,
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
graph.dispatchRunStepDelta(stepId, {
|
|
439
|
-
type: StepTypes.TOOL_CALLS,
|
|
440
|
-
tool_calls: toolCallChunks,
|
|
441
|
-
});
|
|
442
|
-
};
|
|
443
261
|
handleReasoning(chunk: Partial<AIMessageChunk>, graph: Graph): void {
|
|
444
262
|
let reasoning_content = chunk.additional_kwargs?.[graph.reasoningKey] as
|
|
445
263
|
| string
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
// src/tools/handlers.ts
|
|
3
|
+
import { nanoid } from 'nanoid';
|
|
4
|
+
import type { ToolCall, ToolCallChunk } from '@langchain/core/messages/tool';
|
|
5
|
+
import type { Graph } from '@/graphs';
|
|
6
|
+
import type * as t from '@/types';
|
|
7
|
+
import { StepTypes, ContentTypes, ToolCallTypes } from '@/common';
|
|
8
|
+
import { getMessageId } from '@/messages';
|
|
9
|
+
|
|
10
|
+
export function handleToolCallChunks({
|
|
11
|
+
graph,
|
|
12
|
+
stepKey,
|
|
13
|
+
toolCallChunks,
|
|
14
|
+
}: {
|
|
15
|
+
graph: Graph;
|
|
16
|
+
stepKey: string;
|
|
17
|
+
toolCallChunks: ToolCallChunk[];
|
|
18
|
+
}): void {
|
|
19
|
+
let prevStepId: string;
|
|
20
|
+
let prevRunStep: t.RunStep | undefined;
|
|
21
|
+
try {
|
|
22
|
+
prevStepId = graph.getStepIdByKey(stepKey, graph.contentData.length - 1);
|
|
23
|
+
prevRunStep = graph.getRunStep(prevStepId);
|
|
24
|
+
} catch {
|
|
25
|
+
/** Edge Case: If no previous step exists, create a new message creation step */
|
|
26
|
+
const message_id = getMessageId(stepKey, graph, true) ?? '';
|
|
27
|
+
prevStepId = graph.dispatchRunStep(stepKey, {
|
|
28
|
+
type: StepTypes.MESSAGE_CREATION,
|
|
29
|
+
message_creation: {
|
|
30
|
+
message_id,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
prevRunStep = graph.getRunStep(prevStepId);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const _stepId = graph.getStepIdByKey(stepKey, prevRunStep?.index);
|
|
37
|
+
|
|
38
|
+
/** Edge Case: Tool Call Run Step or `tool_call_ids` never dispatched */
|
|
39
|
+
const tool_calls: ToolCall[] | undefined =
|
|
40
|
+
prevStepId && prevRunStep && prevRunStep.type === StepTypes.MESSAGE_CREATION
|
|
41
|
+
? []
|
|
42
|
+
: undefined;
|
|
43
|
+
|
|
44
|
+
/** Edge Case: `id` and `name` fields cannot be empty strings */
|
|
45
|
+
for (const toolCallChunk of toolCallChunks) {
|
|
46
|
+
if (toolCallChunk.name === '') {
|
|
47
|
+
toolCallChunk.name = undefined;
|
|
48
|
+
}
|
|
49
|
+
if (toolCallChunk.id === '') {
|
|
50
|
+
toolCallChunk.id = undefined;
|
|
51
|
+
} else if (
|
|
52
|
+
tool_calls != null &&
|
|
53
|
+
toolCallChunk.id != null &&
|
|
54
|
+
toolCallChunk.name != null
|
|
55
|
+
) {
|
|
56
|
+
tool_calls.push({
|
|
57
|
+
args: {},
|
|
58
|
+
id: toolCallChunk.id,
|
|
59
|
+
name: toolCallChunk.name,
|
|
60
|
+
type: ToolCallTypes.TOOL_CALL,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let stepId: string = _stepId;
|
|
66
|
+
const alreadyDispatched =
|
|
67
|
+
prevRunStep?.type === StepTypes.MESSAGE_CREATION &&
|
|
68
|
+
graph.messageStepHasToolCalls.has(prevStepId);
|
|
69
|
+
if (!alreadyDispatched && tool_calls?.length === toolCallChunks.length) {
|
|
70
|
+
graph.dispatchMessageDelta(prevStepId, {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: ContentTypes.TEXT,
|
|
74
|
+
text: '',
|
|
75
|
+
tool_call_ids: tool_calls.map((tc) => tc.id ?? ''),
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
});
|
|
79
|
+
graph.messageStepHasToolCalls.set(prevStepId, true);
|
|
80
|
+
stepId = graph.dispatchRunStep(stepKey, {
|
|
81
|
+
type: StepTypes.TOOL_CALLS,
|
|
82
|
+
tool_calls,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
graph.dispatchRunStepDelta(stepId, {
|
|
86
|
+
type: StepTypes.TOOL_CALLS,
|
|
87
|
+
tool_calls: toolCallChunks,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const handleToolCalls = (
|
|
92
|
+
toolCalls?: ToolCall[],
|
|
93
|
+
metadata?: Record<string, unknown>,
|
|
94
|
+
graph?: Graph
|
|
95
|
+
): void => {
|
|
96
|
+
if (!graph || !metadata) {
|
|
97
|
+
console.warn(`Graph or metadata not found in ${event} event`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!toolCalls) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (toolCalls.length === 0) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const stepKey = graph.getStepKey(metadata);
|
|
110
|
+
|
|
111
|
+
for (const tool_call of toolCalls) {
|
|
112
|
+
const toolCallId = tool_call.id ?? `toolu_${nanoid()}`;
|
|
113
|
+
tool_call.id = toolCallId;
|
|
114
|
+
if (!toolCallId || graph.toolCallStepIds.has(toolCallId)) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
let prevStepId = '';
|
|
119
|
+
let prevRunStep: t.RunStep | undefined;
|
|
120
|
+
try {
|
|
121
|
+
prevStepId = graph.getStepIdByKey(stepKey, graph.contentData.length - 1);
|
|
122
|
+
prevRunStep = graph.getRunStep(prevStepId);
|
|
123
|
+
} catch {
|
|
124
|
+
// no previous step
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const dispatchToolCallIds = (lastMessageStepId: string): void => {
|
|
128
|
+
graph.dispatchMessageDelta(lastMessageStepId, {
|
|
129
|
+
content: [
|
|
130
|
+
{
|
|
131
|
+
type: 'text',
|
|
132
|
+
text: '',
|
|
133
|
+
tool_call_ids: [toolCallId],
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
/* If the previous step exists and is a message creation */
|
|
139
|
+
if (
|
|
140
|
+
prevStepId &&
|
|
141
|
+
prevRunStep &&
|
|
142
|
+
prevRunStep.type === StepTypes.MESSAGE_CREATION
|
|
143
|
+
) {
|
|
144
|
+
dispatchToolCallIds(prevStepId);
|
|
145
|
+
graph.messageStepHasToolCalls.set(prevStepId, true);
|
|
146
|
+
/* If the previous step doesn't exist or is not a message creation */
|
|
147
|
+
} else if (
|
|
148
|
+
!prevRunStep ||
|
|
149
|
+
prevRunStep.type !== StepTypes.MESSAGE_CREATION
|
|
150
|
+
) {
|
|
151
|
+
const messageId = getMessageId(stepKey, graph, true) ?? '';
|
|
152
|
+
const stepId = graph.dispatchRunStep(stepKey, {
|
|
153
|
+
type: StepTypes.MESSAGE_CREATION,
|
|
154
|
+
message_creation: {
|
|
155
|
+
message_id: messageId,
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
dispatchToolCallIds(stepId);
|
|
159
|
+
graph.messageStepHasToolCalls.set(prevStepId, true);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
graph.dispatchRunStep(stepKey, {
|
|
163
|
+
type: StepTypes.TOOL_CALLS,
|
|
164
|
+
tool_calls: [tool_call],
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
};
|
|
@@ -65,7 +65,7 @@ const chunker = {
|
|
|
65
65
|
},
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
function createSourceUpdateCallback(sourceMap: Map<string, t.ValidSource>) {
|
|
69
69
|
return (link: string, update?: Partial<t.ValidSource>): void => {
|
|
70
70
|
const source = sourceMap.get(link);
|
|
71
71
|
if (source) {
|
|
@@ -75,7 +75,7 @@ const createSourceUpdateCallback = (sourceMap: Map<string, t.ValidSource>) => {
|
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
77
|
};
|
|
78
|
-
}
|
|
78
|
+
}
|
|
79
79
|
|
|
80
80
|
const getHighlights = async ({
|
|
81
81
|
query,
|
|
@@ -315,10 +315,7 @@ export const createSourceProcessor = (
|
|
|
315
315
|
scraperInstance?: FirecrawlScraper
|
|
316
316
|
): {
|
|
317
317
|
processSources: (
|
|
318
|
-
|
|
319
|
-
numElements: number,
|
|
320
|
-
query: string,
|
|
321
|
-
proMode?: boolean
|
|
318
|
+
fields: t.ProcessSourcesFields
|
|
322
319
|
) => Promise<t.SearchResultData>;
|
|
323
320
|
topResults: number;
|
|
324
321
|
} => {
|
|
@@ -338,14 +335,17 @@ export const createSourceProcessor = (
|
|
|
338
335
|
scrapeMany: async ({
|
|
339
336
|
query,
|
|
340
337
|
links,
|
|
338
|
+
onGetHighlights,
|
|
341
339
|
}: {
|
|
342
340
|
query: string;
|
|
343
341
|
links: string[];
|
|
342
|
+
onGetHighlights: t.SearchToolConfig['onGetHighlights'];
|
|
344
343
|
}): Promise<Array<t.ScrapeResult>> => {
|
|
345
344
|
console.log(`Scraping ${links.length} links with Firecrawl`);
|
|
346
345
|
const promises: Array<Promise<t.ScrapeResult>> = [];
|
|
347
346
|
try {
|
|
348
|
-
for (
|
|
347
|
+
for (let i = 0; i < links.length; i++) {
|
|
348
|
+
const currentLink = links[i];
|
|
349
349
|
const promise: Promise<t.ScrapeResult> = firecrawlScraper
|
|
350
350
|
.scrapeUrl(currentLink, {})
|
|
351
351
|
.then(([url, response]) => {
|
|
@@ -383,6 +383,9 @@ export const createSourceProcessor = (
|
|
|
383
383
|
reranker,
|
|
384
384
|
content: result.content,
|
|
385
385
|
});
|
|
386
|
+
if (onGetHighlights) {
|
|
387
|
+
onGetHighlights(result.url);
|
|
388
|
+
}
|
|
386
389
|
return {
|
|
387
390
|
...result,
|
|
388
391
|
highlights,
|
|
@@ -416,16 +419,22 @@ export const createSourceProcessor = (
|
|
|
416
419
|
links,
|
|
417
420
|
query,
|
|
418
421
|
target,
|
|
422
|
+
onGetHighlights,
|
|
419
423
|
onContentScraped,
|
|
420
424
|
}: {
|
|
421
425
|
links: string[];
|
|
422
426
|
query: string;
|
|
423
427
|
target: number;
|
|
428
|
+
onGetHighlights: t.SearchToolConfig['onGetHighlights'];
|
|
424
429
|
onContentScraped?: (link: string, update?: Partial<t.ValidSource>) => void;
|
|
425
430
|
}): Promise<void> => {
|
|
426
431
|
const initialLinks = links.slice(0, target);
|
|
427
432
|
// const remainingLinks = links.slice(target).reverse();
|
|
428
|
-
const results = await webScraper.scrapeMany({
|
|
433
|
+
const results = await webScraper.scrapeMany({
|
|
434
|
+
query,
|
|
435
|
+
links: initialLinks,
|
|
436
|
+
onGetHighlights,
|
|
437
|
+
});
|
|
429
438
|
for (const result of results) {
|
|
430
439
|
if (result.error === true) {
|
|
431
440
|
continue;
|
|
@@ -440,12 +449,13 @@ export const createSourceProcessor = (
|
|
|
440
449
|
}
|
|
441
450
|
};
|
|
442
451
|
|
|
443
|
-
const processSources = async (
|
|
444
|
-
result
|
|
445
|
-
numElements
|
|
446
|
-
query
|
|
447
|
-
proMode
|
|
448
|
-
|
|
452
|
+
const processSources = async ({
|
|
453
|
+
result,
|
|
454
|
+
numElements,
|
|
455
|
+
query,
|
|
456
|
+
proMode = true,
|
|
457
|
+
onGetHighlights,
|
|
458
|
+
}: t.ProcessSourcesFields): Promise<t.SearchResultData> => {
|
|
449
459
|
try {
|
|
450
460
|
if (!result.data) {
|
|
451
461
|
return {
|
|
@@ -473,6 +483,7 @@ export const createSourceProcessor = (
|
|
|
473
483
|
await fetchContents({
|
|
474
484
|
query,
|
|
475
485
|
target: 1,
|
|
486
|
+
onGetHighlights,
|
|
476
487
|
onContentScraped,
|
|
477
488
|
links: [wikiSources[0].link],
|
|
478
489
|
});
|
|
@@ -507,8 +518,9 @@ export const createSourceProcessor = (
|
|
|
507
518
|
|
|
508
519
|
const onContentScraped = createSourceUpdateCallback(sourceMap);
|
|
509
520
|
await fetchContents({
|
|
510
|
-
links: allLinks,
|
|
511
521
|
query,
|
|
522
|
+
links: allLinks,
|
|
523
|
+
onGetHighlights,
|
|
512
524
|
onContentScraped,
|
|
513
525
|
target: numElements,
|
|
514
526
|
});
|