@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.
Files changed (50) hide show
  1. package/dist/cjs/events.cjs +3 -3
  2. package/dist/cjs/events.cjs.map +1 -1
  3. package/dist/cjs/main.cjs +5 -2
  4. package/dist/cjs/main.cjs.map +1 -1
  5. package/dist/cjs/messages/ids.cjs +23 -0
  6. package/dist/cjs/messages/ids.cjs.map +1 -0
  7. package/dist/cjs/stream.cjs +8 -155
  8. package/dist/cjs/stream.cjs.map +1 -1
  9. package/dist/cjs/tools/handlers.cjs +144 -0
  10. package/dist/cjs/tools/handlers.cjs.map +1 -0
  11. package/dist/cjs/tools/search/search.cjs +18 -8
  12. package/dist/cjs/tools/search/search.cjs.map +1 -1
  13. package/dist/cjs/tools/search/tool.cjs +85 -61
  14. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  15. package/dist/cjs/tools/search/utils.cjs +3 -1
  16. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  17. package/dist/esm/events.mjs +1 -1
  18. package/dist/esm/events.mjs.map +1 -1
  19. package/dist/esm/main.mjs +3 -1
  20. package/dist/esm/main.mjs.map +1 -1
  21. package/dist/esm/messages/ids.mjs +21 -0
  22. package/dist/esm/messages/ids.mjs.map +1 -0
  23. package/dist/esm/stream.mjs +7 -152
  24. package/dist/esm/stream.mjs.map +1 -1
  25. package/dist/esm/tools/handlers.mjs +141 -0
  26. package/dist/esm/tools/handlers.mjs.map +1 -0
  27. package/dist/esm/tools/search/search.mjs +18 -8
  28. package/dist/esm/tools/search/search.mjs.map +1 -1
  29. package/dist/esm/tools/search/tool.mjs +84 -60
  30. package/dist/esm/tools/search/tool.mjs.map +1 -1
  31. package/dist/esm/tools/search/utils.mjs +3 -1
  32. package/dist/esm/tools/search/utils.mjs.map +1 -1
  33. package/dist/types/index.d.ts +1 -0
  34. package/dist/types/messages/ids.d.ts +3 -0
  35. package/dist/types/messages/index.d.ts +1 -0
  36. package/dist/types/stream.d.ts +0 -8
  37. package/dist/types/tools/handlers.d.ts +8 -0
  38. package/dist/types/tools/search/search.d.ts +1 -1
  39. package/dist/types/tools/search/types.d.ts +28 -8
  40. package/package.json +1 -1
  41. package/src/events.ts +49 -15
  42. package/src/index.ts +1 -0
  43. package/src/messages/ids.ts +26 -0
  44. package/src/messages/index.ts +1 -0
  45. package/src/stream.ts +4 -186
  46. package/src/tools/handlers.ts +167 -0
  47. package/src/tools/search/search.ts +27 -15
  48. package/src/tools/search/tool.ts +137 -91
  49. package/src/tools/search/types.ts +37 -10
  50. package/src/tools/search/utils.ts +5 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@librechat/agents",
3
- "version": "2.4.318",
3
+ "version": "2.4.320",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
package/src/events.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  /* eslint-disable no-console */
2
2
  // src/events.ts
3
- import type { UsageMetadata, BaseMessageFields } from '@langchain/core/messages';
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 '@/stream';
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(event: string, data: t.ModelEndData, metadata?: Record<string, unknown>, graph?: Graph): void {
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
- usage,
48
- }, { depth: null });
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(event: string, data: t.StreamEventData | undefined, metadata?: Record<string, unknown>, graph?: Graph): void {
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({ input: toolEndData.input, output: toolEndData.output }, metadata);
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 isMessageChunk = !!(chunk && 'message' in chunk);
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(event: string, data: t.StreamEventData | undefined, metadata?: Record<string, unknown>): void {
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 isMessageChunk = !!(chunk && 'message' in chunk);
144
+ const isMessageChunk = !!(chunk && 'message' in chunk);
122
145
  const msg = isMessageChunk && chunk.message;
123
- if (metadata) { console.log(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 = (_collected?: Record<string, NonNullable<BaseMessageFields['response_metadata']>>[]): t.MetadataAggregatorResult => {
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 = (generations[generations.length - 1] as (t.StreamGeneration | undefined)[] | undefined)?.[0];
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
@@ -10,6 +10,7 @@ export * from './graphs';
10
10
 
11
11
  /* Tools */
12
12
  export * from './tools/CodeExecutor';
13
+ export * from './tools/handlers';
13
14
  export * from './tools/search';
14
15
 
15
16
  /* Misc. */
@@ -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
+ };
@@ -1,3 +1,4 @@
1
1
  export * from './core';
2
+ export * from './ids';
2
3
  export * from './prune';
3
4
  export * from './format';
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, ToolCallChunk } from '@langchain/core/messages/tool';
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
- this.handleToolCallChunks({
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
- const createSourceUpdateCallback = (sourceMap: Map<string, t.ValidSource>) => {
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
- result: t.SearchResult,
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 (const currentLink of links) {
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({ query, links: initialLinks });
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: t.SearchResult,
445
- numElements: number,
446
- query: string,
447
- proMode: boolean = false
448
- ): Promise<t.SearchResultData> => {
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
  });