@librechat/agents 3.2.57 → 3.2.58

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 (73) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +7 -1
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +2 -2
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/langfuseToolOutputTracing.cjs +4 -0
  6. package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
  7. package/dist/cjs/langfuseTraceShaping.cjs +172 -0
  8. package/dist/cjs/langfuseTraceShaping.cjs.map +1 -0
  9. package/dist/cjs/run.cjs +2 -2
  10. package/dist/cjs/run.cjs.map +1 -1
  11. package/dist/cjs/tools/search/keenable-search.cjs +68 -0
  12. package/dist/cjs/tools/search/keenable-search.cjs.map +1 -0
  13. package/dist/cjs/tools/search/rerankers.cjs +28 -11
  14. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  15. package/dist/cjs/tools/search/search.cjs +30 -4
  16. package/dist/cjs/tools/search/search.cjs.map +1 -1
  17. package/dist/cjs/tools/search/tool.cjs +14 -6
  18. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  19. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +12 -1
  20. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  21. package/dist/cjs/utils/title.cjs +9 -9
  22. package/dist/cjs/utils/title.cjs.map +1 -1
  23. package/dist/esm/agents/AgentContext.mjs +7 -1
  24. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  25. package/dist/esm/graphs/Graph.mjs +2 -2
  26. package/dist/esm/graphs/Graph.mjs.map +1 -1
  27. package/dist/esm/langfuseToolOutputTracing.mjs +4 -0
  28. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
  29. package/dist/esm/langfuseTraceShaping.mjs +171 -0
  30. package/dist/esm/langfuseTraceShaping.mjs.map +1 -0
  31. package/dist/esm/run.mjs +2 -2
  32. package/dist/esm/run.mjs.map +1 -1
  33. package/dist/esm/tools/search/keenable-search.mjs +66 -0
  34. package/dist/esm/tools/search/keenable-search.mjs.map +1 -0
  35. package/dist/esm/tools/search/rerankers.mjs +28 -11
  36. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  37. package/dist/esm/tools/search/search.mjs +30 -4
  38. package/dist/esm/tools/search/search.mjs.map +1 -1
  39. package/dist/esm/tools/search/tool.mjs +14 -6
  40. package/dist/esm/tools/search/tool.mjs.map +1 -1
  41. package/dist/esm/tools/subagent/SubagentExecutor.mjs +12 -1
  42. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  43. package/dist/esm/utils/title.mjs +9 -9
  44. package/dist/esm/utils/title.mjs.map +1 -1
  45. package/dist/types/langfuseTraceShaping.d.ts +20 -0
  46. package/dist/types/tools/search/keenable-search.d.ts +4 -0
  47. package/dist/types/tools/search/rerankers.d.ts +7 -2
  48. package/dist/types/tools/search/types.d.ts +38 -1
  49. package/dist/types/types/graph.d.ts +22 -0
  50. package/package.json +1 -1
  51. package/src/agents/AgentContext.ts +9 -0
  52. package/src/agents/__tests__/AgentContext.test.ts +40 -0
  53. package/src/graphs/Graph.ts +25 -2
  54. package/src/graphs/__tests__/composition.smoke.test.ts +53 -0
  55. package/src/langfuseToolOutputTracing.ts +11 -0
  56. package/src/langfuseTraceShaping.ts +280 -0
  57. package/src/llm/anthropic/inherited-stream-events.spec.ts +6 -3
  58. package/src/run.ts +3 -3
  59. package/src/specs/langfuse-routing.integration.test.ts +1 -1
  60. package/src/specs/langfuse-trace-shaping.test.ts +194 -0
  61. package/src/tools/__tests__/SubagentExecutor.test.ts +44 -0
  62. package/src/tools/__tests__/hitl.test.ts +85 -0
  63. package/src/tools/search/jina-reranker.test.ts +70 -1
  64. package/src/tools/search/keenable-search.ts +98 -0
  65. package/src/tools/search/keenable.test.ts +183 -0
  66. package/src/tools/search/rerankers.ts +41 -4
  67. package/src/tools/search/search.ts +58 -2
  68. package/src/tools/search/source-processing.test.ts +86 -0
  69. package/src/tools/search/tool.ts +29 -4
  70. package/src/tools/search/types.ts +42 -1
  71. package/src/tools/subagent/SubagentExecutor.ts +11 -0
  72. package/src/types/graph.ts +22 -0
  73. package/src/utils/title.ts +9 -9
@@ -3,7 +3,7 @@ import type { Logger as WinstonLogger } from 'winston';
3
3
  import type { BaseReranker } from './rerankers';
4
4
  import { DATE_RANGE } from './schema';
5
5
 
6
- export type SearchProvider = 'serper' | 'searxng' | 'tavily';
6
+ export type SearchProvider = 'serper' | 'searxng' | 'tavily' | 'keenable';
7
7
  export type ScraperProvider = 'firecrawl' | 'serper' | 'tavily';
8
8
  export type RerankerType = 'infinity' | 'jina' | 'cohere' | 'none';
9
9
 
@@ -115,6 +115,36 @@ export interface SearchConfig {
115
115
  tavilySearchUrl?: string;
116
116
  tavilyExtractUrl?: string;
117
117
  tavilySearchOptions?: TavilySearchOptions;
118
+ keenableApiKey?: string;
119
+ keenableApiUrl?: string;
120
+ keenableSearchOptions?: KeenableSearchOptions;
121
+ }
122
+
123
+ export interface KeenableSearchOptions {
124
+ maxResults?: number;
125
+ /** Restrict results to a single domain, e.g. "github.com". */
126
+ site?: string;
127
+ /** Sent as the X-Keenable-Title attribution header. Defaults to "LibreChat". */
128
+ attributionTitle?: string;
129
+ timeout?: number;
130
+ }
131
+
132
+ export interface KeenableSearchPayload {
133
+ query: string;
134
+ site?: string;
135
+ published_after?: string;
136
+ }
137
+
138
+ export interface KeenableSearchResult {
139
+ title?: string;
140
+ url?: string;
141
+ description?: string;
142
+ snippet?: string;
143
+ published_at?: string;
144
+ }
145
+
146
+ export interface KeenableSearchResponse {
147
+ results?: KeenableSearchResult[];
118
148
  }
119
149
 
120
150
  export type References = {
@@ -137,6 +167,15 @@ export interface ProcessSourcesConfig {
137
167
  * chunker/reranker. Defaults to 50,000; also configurable via the
138
168
  * `SEARCH_MAX_CONTENT_LENGTH` env var. */
139
169
  maxContentLength?: number;
170
+ /** Chunk size (chars) for splitting scraped content before reranking.
171
+ * Defaults to 150; also configurable via the `SEARCH_CHUNK_SIZE` env var.
172
+ * Larger chunks send fewer documents to the reranker (lower cost/latency);
173
+ * highlights are expanded ±300-450 chars around each hit either way. */
174
+ chunkSize?: number;
175
+ /** Overlap (chars) between adjacent chunks. Defaults to 50; also
176
+ * configurable via the `SEARCH_CHUNK_OVERLAP` env var. Clamped below
177
+ * `chunkSize`. */
178
+ chunkOverlap?: number;
140
179
  strategies?: string[];
141
180
  filterContent?: boolean;
142
181
  reranker?: BaseReranker;
@@ -231,6 +270,8 @@ export interface SearchToolConfig
231
270
  jinaApiUrl?: string;
232
271
  cohereApiKey?: string;
233
272
  rerankerType?: RerankerType;
273
+ /** Timeout (ms) for rerank API requests. Defaults to 10,000. */
274
+ rerankerTimeout?: number;
234
275
  scraperProvider?: ScraperProvider;
235
276
  scraperTimeout?: number;
236
277
  serperScraperOptions?: SerperScraperConfig;
@@ -1422,6 +1422,17 @@ export function buildChildInputs(
1422
1422
  */
1423
1423
  initialSummary: undefined,
1424
1424
  discoveredTools: undefined,
1425
+ /**
1426
+ * Host-supplied direct tools are scrubbed from INHERITED configs only.
1427
+ * A self-spawn config's `agentInputs` is a shallow spread of the parent's
1428
+ * `_sourceInputs`, so without this a parent-scoped graph tool (e.g. an
1429
+ * interrupt-raising ask_user_question, which needs the parent's
1430
+ * checkpointer — child graphs compile without one) would silently leak
1431
+ * into the child and deterministically throw `No checkpointer set`. An
1432
+ * EXPLICIT child config that lists its own `graphTools` is a deliberate
1433
+ * host choice and keeps them (Codex #289 P2).
1434
+ */
1435
+ graphTools: config.self === true ? undefined : agentInputs.graphTools,
1425
1436
  };
1426
1437
 
1427
1438
  if (config.allowNested === true) {
@@ -610,6 +610,28 @@ export interface AgentInputs {
610
610
  subagentConfigs?: SubagentConfig[];
611
611
  /** Maximum subagent nesting depth. Default 1 means top-level agents can spawn subagents but subagents cannot nest further. */
612
612
  maxSubagentDepth?: number;
613
+ /**
614
+ * Host-supplied tool instances that must execute IN-PROCESS inside the graph's
615
+ * ToolNode even when the run is event-driven (`toolDefinitions` non-empty). Each
616
+ * instance is bound to the model alongside the schema-only event tools and its
617
+ * name is marked direct, so calls bypass ON_TOOL_EXECUTE dispatch and run inside
618
+ * the Pregel task frame. This is the only execution mode where a tool body may
619
+ * raise a LangGraph `interrupt()` (e.g. a tool built on `askUserQuestion()`) —
620
+ * the host-side event handler runs outside the graph task, where `interrupt()`
621
+ * throws. Do NOT also list these tools in `toolDefinitions` (they would be bound
622
+ * twice). NOT inherited by SELF-SPAWNED subagent children (their config is a
623
+ * shallow spread of the parent's inputs, and child graphs compile without a
624
+ * checkpointer, so an interrupt-capable tool could never pause there) —
625
+ * `buildChildInputs` scrubs the inherited copy; an EXPLICIT child config that
626
+ * lists its own `graphTools` keeps them.
627
+ *
628
+ * Deliberately `GenericTool[]`, not `GraphTools`: the wider union admits
629
+ * schema-only shapes (OpenAI `BindToolsInput`, Google tool objects) that
630
+ * `initializeTools` cannot register in the ToolNode direct map — the model
631
+ * would bind a tool the SDK advertised as in-process but cannot execute.
632
+ * Every entry must be a real executable tool instance with a `name`.
633
+ */
634
+ graphTools?: GenericTool[];
613
635
  }
614
636
 
615
637
  export interface ContextPruningConfig {
@@ -53,7 +53,7 @@ export const createTitleRunnable = async (
53
53
 
54
54
  const titlePrompt = ChatPromptTemplate.fromTemplate(
55
55
  _titlePrompt ?? defaultTitlePrompt
56
- ).withConfig({ runName: 'TitlePrompt' });
56
+ ).withConfig({ runName: 'BuildTitlePrompt' });
57
57
 
58
58
  const titleOnlyInnerChain = RunnableSequence.from([titlePrompt, titleLLM]);
59
59
  const combinedInnerChain = RunnableSequence.from([titlePrompt, combinedLLM]);
@@ -67,7 +67,7 @@ export const createTitleRunnable = async (
67
67
  const result = await titleOnlyInnerChain.invoke(input, config);
68
68
  return result as { title: string };
69
69
  },
70
- }).withConfig({ runName: 'TitleOnlyChain' });
70
+ }).withConfig({ runName: 'GenerateTitleOnly' });
71
71
 
72
72
  /** Wrap combinedChain in RunnableLambda to create parent span */
73
73
  const combinedChain = new RunnableLambda({
@@ -78,7 +78,7 @@ export const createTitleRunnable = async (
78
78
  const result = await combinedInnerChain.invoke(input, config);
79
79
  return result as { language: string; title: string };
80
80
  },
81
- }).withConfig({ runName: 'TitleLanguageChain' });
81
+ }).withConfig({ runName: 'GenerateTitleAndDetectLanguage' });
82
82
 
83
83
  /** Runnable to add default values if needed */
84
84
  const addDefaults = new RunnableLambda({
@@ -88,7 +88,7 @@ export const createTitleRunnable = async (
88
88
  language: result?.language ?? 'English',
89
89
  title: result?.title ?? '',
90
90
  }),
91
- }).withConfig({ runName: 'AddDefaults' });
91
+ }).withConfig({ runName: 'ApplyTitleDefaults' });
92
92
 
93
93
  const combinedChainInner = RunnableSequence.from([
94
94
  combinedChain,
@@ -103,7 +103,7 @@ export const createTitleRunnable = async (
103
103
  ): Promise<{ language: string; title: string }> => {
104
104
  return await combinedChainInner.invoke(input, config);
105
105
  },
106
- }).withConfig({ runName: 'CombinedChainWithDefaults' });
106
+ }).withConfig({ runName: 'GenerateTitleAndDetectLanguageWithDefaults' });
107
107
 
108
108
  return new RunnableLambda({
109
109
  func: async (
@@ -124,7 +124,7 @@ export const createTitleRunnable = async (
124
124
 
125
125
  return await combinedChainWithDefaults.invoke(invokeInput, config);
126
126
  },
127
- }).withConfig({ runName: 'TitleGenerator' });
127
+ }).withConfig({ runName: 'GenerateTitle' });
128
128
  };
129
129
 
130
130
  const defaultCompletionPrompt = `Provide a concise, 5-word-or-less title for the conversation, using title case conventions. Only return the title itself.
@@ -138,7 +138,7 @@ export const createCompletionTitleRunnable = async (
138
138
  ): Promise<Runnable> => {
139
139
  const completionPrompt = ChatPromptTemplate.fromTemplate(
140
140
  titlePrompt ?? defaultCompletionPrompt
141
- ).withConfig({ runName: 'CompletionTitlePrompt' });
141
+ ).withConfig({ runName: 'BuildTitlePrompt' });
142
142
 
143
143
  /** Runnable to extract content from model response */
144
144
  const extractContent = new RunnableLambda({
@@ -157,7 +157,7 @@ export const createCompletionTitleRunnable = async (
157
157
  }
158
158
  return { title: content.trim() };
159
159
  },
160
- }).withConfig({ runName: 'ExtractTitle' });
160
+ }).withConfig({ runName: 'ParseTitleFromResponse' });
161
161
 
162
162
  const innerChain = RunnableSequence.from([
163
163
  completionPrompt,
@@ -173,5 +173,5 @@ export const createCompletionTitleRunnable = async (
173
173
  ): Promise<{ title: string }> => {
174
174
  return await innerChain.invoke(input, config);
175
175
  },
176
- }).withConfig({ runName: 'CompletionTitleChain' });
176
+ }).withConfig({ runName: 'GenerateTitle' });
177
177
  };