@librechat/agents 3.2.57 → 3.2.59

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 (120) 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/main.cjs +7 -0
  10. package/dist/cjs/run.cjs +2 -2
  11. package/dist/cjs/run.cjs.map +1 -1
  12. package/dist/cjs/stream.cjs +2 -1
  13. package/dist/cjs/stream.cjs.map +1 -1
  14. package/dist/cjs/tools/BashExecutor.cjs +58 -9
  15. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  16. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +4 -2
  17. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  18. package/dist/cjs/tools/CodeExecutor.cjs +57 -7
  19. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  20. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +9 -3
  21. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  22. package/dist/cjs/tools/ToolNode.cjs +19 -1
  23. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  24. package/dist/cjs/tools/eagerEventExecution.cjs +18 -1
  25. package/dist/cjs/tools/eagerEventExecution.cjs.map +1 -1
  26. package/dist/cjs/tools/search/keenable-search.cjs +68 -0
  27. package/dist/cjs/tools/search/keenable-search.cjs.map +1 -0
  28. package/dist/cjs/tools/search/rerankers.cjs +28 -11
  29. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  30. package/dist/cjs/tools/search/search.cjs +30 -4
  31. package/dist/cjs/tools/search/search.cjs.map +1 -1
  32. package/dist/cjs/tools/search/tool.cjs +14 -6
  33. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  34. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +12 -1
  35. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  36. package/dist/cjs/utils/title.cjs +9 -9
  37. package/dist/cjs/utils/title.cjs.map +1 -1
  38. package/dist/esm/agents/AgentContext.mjs +7 -1
  39. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  40. package/dist/esm/graphs/Graph.mjs +2 -2
  41. package/dist/esm/graphs/Graph.mjs.map +1 -1
  42. package/dist/esm/langfuseToolOutputTracing.mjs +4 -0
  43. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
  44. package/dist/esm/langfuseTraceShaping.mjs +171 -0
  45. package/dist/esm/langfuseTraceShaping.mjs.map +1 -0
  46. package/dist/esm/main.mjs +3 -3
  47. package/dist/esm/run.mjs +2 -2
  48. package/dist/esm/run.mjs.map +1 -1
  49. package/dist/esm/stream.mjs +2 -1
  50. package/dist/esm/stream.mjs.map +1 -1
  51. package/dist/esm/tools/BashExecutor.mjs +56 -10
  52. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  53. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +4 -2
  54. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  55. package/dist/esm/tools/CodeExecutor.mjs +54 -8
  56. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  57. package/dist/esm/tools/ProgrammaticToolCalling.mjs +9 -3
  58. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  59. package/dist/esm/tools/ToolNode.mjs +20 -2
  60. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  61. package/dist/esm/tools/eagerEventExecution.mjs +18 -2
  62. package/dist/esm/tools/eagerEventExecution.mjs.map +1 -1
  63. package/dist/esm/tools/search/keenable-search.mjs +66 -0
  64. package/dist/esm/tools/search/keenable-search.mjs.map +1 -0
  65. package/dist/esm/tools/search/rerankers.mjs +28 -11
  66. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  67. package/dist/esm/tools/search/search.mjs +30 -4
  68. package/dist/esm/tools/search/search.mjs.map +1 -1
  69. package/dist/esm/tools/search/tool.mjs +14 -6
  70. package/dist/esm/tools/search/tool.mjs.map +1 -1
  71. package/dist/esm/tools/subagent/SubagentExecutor.mjs +12 -1
  72. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  73. package/dist/esm/utils/title.mjs +9 -9
  74. package/dist/esm/utils/title.mjs.map +1 -1
  75. package/dist/types/langfuseTraceShaping.d.ts +20 -0
  76. package/dist/types/tools/BashExecutor.d.ts +13 -0
  77. package/dist/types/tools/CodeExecutor.d.ts +14 -0
  78. package/dist/types/tools/ToolNode.d.ts +3 -0
  79. package/dist/types/tools/eagerEventExecution.d.ts +8 -0
  80. package/dist/types/tools/search/keenable-search.d.ts +4 -0
  81. package/dist/types/tools/search/rerankers.d.ts +7 -2
  82. package/dist/types/tools/search/types.d.ts +38 -1
  83. package/dist/types/types/graph.d.ts +22 -0
  84. package/dist/types/types/tools.d.ts +58 -0
  85. package/package.json +1 -1
  86. package/src/agents/AgentContext.ts +9 -0
  87. package/src/agents/__tests__/AgentContext.test.ts +40 -0
  88. package/src/graphs/Graph.ts +25 -2
  89. package/src/graphs/__tests__/composition.smoke.test.ts +53 -0
  90. package/src/langfuseToolOutputTracing.ts +11 -0
  91. package/src/langfuseTraceShaping.ts +280 -0
  92. package/src/llm/anthropic/inherited-stream-events.spec.ts +6 -3
  93. package/src/run.ts +3 -3
  94. package/src/specs/langfuse-routing.integration.test.ts +1 -1
  95. package/src/specs/langfuse-trace-shaping.test.ts +194 -0
  96. package/src/stream.ts +17 -1
  97. package/src/tools/BashExecutor.ts +107 -14
  98. package/src/tools/BashProgrammaticToolCalling.ts +20 -1
  99. package/src/tools/CodeExecutor.ts +113 -9
  100. package/src/tools/ProgrammaticToolCalling.ts +27 -1
  101. package/src/tools/ToolNode.ts +36 -4
  102. package/src/tools/__tests__/BashExecutor.test.ts +39 -0
  103. package/src/tools/__tests__/CodeExecutor.stateful.test.ts +113 -0
  104. package/src/tools/__tests__/SubagentExecutor.test.ts +44 -0
  105. package/src/tools/__tests__/ToolNode.session.test.ts +86 -0
  106. package/src/tools/__tests__/eagerEventExecution.session.test.ts +92 -0
  107. package/src/tools/__tests__/hitl.test.ts +85 -0
  108. package/src/tools/eagerEventExecution.ts +32 -5
  109. package/src/tools/search/jina-reranker.test.ts +70 -1
  110. package/src/tools/search/keenable-search.ts +98 -0
  111. package/src/tools/search/keenable.test.ts +183 -0
  112. package/src/tools/search/rerankers.ts +41 -4
  113. package/src/tools/search/search.ts +58 -2
  114. package/src/tools/search/source-processing.test.ts +86 -0
  115. package/src/tools/search/tool.ts +29 -4
  116. package/src/tools/search/types.ts +42 -1
  117. package/src/tools/subagent/SubagentExecutor.ts +11 -0
  118. package/src/types/graph.ts +22 -0
  119. package/src/types/tools.ts +65 -0
  120. 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 {
@@ -292,6 +292,15 @@ export type CodeExecutionToolParams =
292
292
  files?: CodeEnvFile[];
293
293
  /** Optional host-supplied Code API auth headers. */
294
294
  authHeaders?: CodeApiAuthHeaders;
295
+ /**
296
+ * Advertise best-effort stateful sessions in the tool description
297
+ * (variables/files may persist between calls, may reset). Prompt text
298
+ * only, and it must be set here because the description is bound to the
299
+ * LLM at construction time. Pair it with the run-scoped
300
+ * `toolExecution.sandbox.statefulSessions` gate, which drives the wire
301
+ * hint — set both from one flag so the prompt and the backend agree.
302
+ */
303
+ statefulSessions?: boolean;
295
304
  };
296
305
 
297
306
  export type CodeApiAuthHeaderMap = Record<string, string>;
@@ -347,6 +356,13 @@ export type ExecuteResult = {
347
356
  stdout: string;
348
357
  stderr: string;
349
358
  files?: FileRefs;
359
+ /**
360
+ * Durable runtime session id echoed by a stateful Code API backend
361
+ * (hash of tenant+user+hint). Additive; absent on stateless servers.
362
+ */
363
+ runtime_session_id?: string;
364
+ /** Whether this execution reused a warm runtime session or started fresh. */
365
+ runtime_status?: 'new' | 'reused';
350
366
  };
351
367
 
352
368
  /** JSON Schema type definition for tool parameters */
@@ -413,6 +429,12 @@ export type ToolCallRequest = {
413
429
  session_id: string;
414
430
  files?: CodeEnvFile[];
415
431
  };
432
+ /**
433
+ * Stable runtime session hint for stateful sandbox sessions. Orthogonal to
434
+ * `codeSessionContext` (which threads the transient exec-session for file
435
+ * continuity): the hint identifies the durable server-side runtime session.
436
+ */
437
+ runtimeSessionHint?: string;
416
438
  };
417
439
 
418
440
  /** Batch request containing ALL tool calls for a graph step */
@@ -969,6 +991,32 @@ export type CloudflareSandboxExecutionConfig = {
969
991
  postEditSyntaxCheck?: LocalExecutionConfig['postEditSyntaxCheck'];
970
992
  };
971
993
 
994
+ export type SandboxExecutionConfig = {
995
+ /**
996
+ * Opt into best-effort stateful runtime sessions on the remote Code API
997
+ * (its warm per-session MicroVM backend). This gate is run-scoped: it only
998
+ * controls the wire behavior (ToolNode injecting the session hint on
999
+ * execute_code/bash calls). The transport is otherwise unchanged.
1000
+ *
1001
+ * It does NOT change the model-facing tool description. Tool descriptions are
1002
+ * bound to the LLM at construction time (`createCodeExecutionTool` /
1003
+ * `createBashExecutionTool`), before this run config is applied inside the
1004
+ * graph, so they can only be adjusted via the tools' own `statefulSessions`
1005
+ * factory param. Set BOTH from one flag (as LibreChat does): with this on but
1006
+ * the factory param off, the backend runs statefully while the model is still
1007
+ * told the environment is stateless (non-corrupting — the model just won't
1008
+ * exploit persistence).
1009
+ */
1010
+ statefulSessions?: boolean;
1011
+ /**
1012
+ * Stable identity for the runtime session (e.g. the conversation id). The
1013
+ * server derives the real session id as hash(tenant, user, hint), so this
1014
+ * is never a security boundary. Falls back to `configurable.thread_id` when
1015
+ * omitted.
1016
+ */
1017
+ runtimeSessionHint?: string;
1018
+ };
1019
+
972
1020
  export type ToolExecutionConfig = {
973
1021
  /** `sandbox` preserves the remote Code API behavior and is the default. */
974
1022
  engine?: ToolExecutionEngine;
@@ -976,6 +1024,8 @@ export type ToolExecutionConfig = {
976
1024
  local?: LocalExecutionConfig;
977
1025
  /** Cloudflare Sandbox execution settings used when `engine` is `cloudflare-sandbox`. */
978
1026
  cloudflare?: CloudflareSandboxExecutionConfig;
1027
+ /** Remote sandbox settings; applies when `engine` is `sandbox` or omitted. */
1028
+ sandbox?: SandboxExecutionConfig;
979
1029
  };
980
1030
 
981
1031
  export type ProgrammaticCache = {
@@ -1099,6 +1149,10 @@ export type ProgrammaticExecutionResponse = {
1099
1149
  stderr?: string;
1100
1150
  files?: FileRefs;
1101
1151
 
1152
+ /** Durable runtime session echo from a stateful backend (additive). */
1153
+ runtime_session_id?: string;
1154
+ runtime_status?: 'new' | 'reused';
1155
+
1102
1156
  /** Present when status='error' */
1103
1157
  error?: string;
1104
1158
  };
@@ -1110,6 +1164,9 @@ export type ProgrammaticExecutionArtifact = {
1110
1164
  /** Execution session — see `CodeSessionContext.session_id`. */
1111
1165
  session_id?: string;
1112
1166
  files?: FileRefs;
1167
+ /** Durable runtime session echo from a stateful backend (additive). */
1168
+ runtime_session_id?: string;
1169
+ runtime_status?: 'new' | 'reused';
1113
1170
  };
1114
1171
 
1115
1172
  /** Parameters for creating a bash execution tool (same API as CodeExecutor, bash-only) */
@@ -1134,6 +1191,11 @@ export type ProgrammaticToolCallingParams = {
1134
1191
  debug?: boolean;
1135
1192
  /** Optional host-supplied Code API auth headers. */
1136
1193
  authHeaders?: CodeApiAuthHeaders;
1194
+ /* No `statefulSessions` here: PTC is stateless in v1. The initial
1195
+ * /exec/programmatic request still forwards a ToolNode-injected
1196
+ * `_runtime_session_hint` when present, but there is no factory-level opt-in
1197
+ * to advertise (it would be a no-op). Re-add with real behavior when PTC
1198
+ * stateful prompting lands. */
1137
1199
  };
1138
1200
 
1139
1201
  // ============================================================================
@@ -1166,6 +1228,9 @@ export type CodeExecutionArtifact = {
1166
1228
  /** Execution session — see `CodeSessionContext.session_id`. */
1167
1229
  session_id?: string;
1168
1230
  files?: FileRefs;
1231
+ /** Durable runtime session echo from a stateful backend (additive). */
1232
+ runtime_session_id?: string;
1233
+ runtime_status?: 'new' | 'reused';
1169
1234
  };
1170
1235
 
1171
1236
  /**
@@ -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
  };