@librechat/agents 3.0.776 → 3.1.1

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 (108) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +2 -5
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +20 -5
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/graphs/MultiAgentGraph.cjs +26 -17
  6. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  7. package/dist/cjs/llm/bedrock/index.cjs +98 -25
  8. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  9. package/dist/cjs/llm/openai/index.cjs +1 -0
  10. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  11. package/dist/cjs/main.cjs +3 -0
  12. package/dist/cjs/main.cjs.map +1 -1
  13. package/dist/cjs/messages/core.cjs +1 -1
  14. package/dist/cjs/messages/core.cjs.map +1 -1
  15. package/dist/cjs/stream.cjs +4 -2
  16. package/dist/cjs/stream.cjs.map +1 -1
  17. package/dist/cjs/tools/CodeExecutor.cjs +37 -27
  18. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  19. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +21 -17
  20. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  21. package/dist/cjs/tools/ToolNode.cjs +10 -5
  22. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  23. package/dist/cjs/tools/ToolSearch.cjs +37 -30
  24. package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
  25. package/dist/cjs/tools/search/schema.cjs +25 -23
  26. package/dist/cjs/tools/search/schema.cjs.map +1 -1
  27. package/dist/cjs/tools/search/tool.cjs +9 -33
  28. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  29. package/dist/cjs/utils/schema.cjs +27 -0
  30. package/dist/cjs/utils/schema.cjs.map +1 -0
  31. package/dist/cjs/utils/title.cjs +28 -14
  32. package/dist/cjs/utils/title.cjs.map +1 -1
  33. package/dist/esm/agents/AgentContext.mjs +2 -5
  34. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  35. package/dist/esm/graphs/Graph.mjs +20 -5
  36. package/dist/esm/graphs/Graph.mjs.map +1 -1
  37. package/dist/esm/graphs/MultiAgentGraph.mjs +26 -17
  38. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  39. package/dist/esm/llm/bedrock/index.mjs +97 -24
  40. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  41. package/dist/esm/llm/openai/index.mjs +1 -0
  42. package/dist/esm/llm/openai/index.mjs.map +1 -1
  43. package/dist/esm/main.mjs +1 -0
  44. package/dist/esm/main.mjs.map +1 -1
  45. package/dist/esm/messages/core.mjs +1 -1
  46. package/dist/esm/messages/core.mjs.map +1 -1
  47. package/dist/esm/stream.mjs +4 -2
  48. package/dist/esm/stream.mjs.map +1 -1
  49. package/dist/esm/tools/CodeExecutor.mjs +37 -27
  50. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  51. package/dist/esm/tools/ProgrammaticToolCalling.mjs +21 -17
  52. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  53. package/dist/esm/tools/ToolNode.mjs +10 -5
  54. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  55. package/dist/esm/tools/ToolSearch.mjs +37 -30
  56. package/dist/esm/tools/ToolSearch.mjs.map +1 -1
  57. package/dist/esm/tools/search/schema.mjs +25 -23
  58. package/dist/esm/tools/search/schema.mjs.map +1 -1
  59. package/dist/esm/tools/search/tool.mjs +10 -34
  60. package/dist/esm/tools/search/tool.mjs.map +1 -1
  61. package/dist/esm/utils/schema.mjs +24 -0
  62. package/dist/esm/utils/schema.mjs.map +1 -0
  63. package/dist/esm/utils/title.mjs +28 -14
  64. package/dist/esm/utils/title.mjs.map +1 -1
  65. package/dist/types/llm/bedrock/index.d.ts +86 -7
  66. package/dist/types/llm/bedrock/types.d.ts +27 -0
  67. package/dist/types/llm/bedrock/utils/index.d.ts +5 -0
  68. package/dist/types/llm/bedrock/utils/message_inputs.d.ts +31 -0
  69. package/dist/types/llm/bedrock/utils/message_outputs.d.ts +33 -0
  70. package/dist/types/tools/CodeExecutor.d.ts +1 -15
  71. package/dist/types/tools/ProgrammaticToolCalling.d.ts +1 -13
  72. package/dist/types/tools/ToolSearch.d.ts +1 -15
  73. package/dist/types/tools/search/schema.d.ts +25 -7
  74. package/dist/types/tools/search/tool.d.ts +1 -52
  75. package/dist/types/tools/search/types.d.ts +5 -23
  76. package/dist/types/types/tools.d.ts +2 -0
  77. package/dist/types/utils/index.d.ts +1 -0
  78. package/dist/types/utils/schema.d.ts +8 -0
  79. package/package.json +5 -2
  80. package/src/agents/AgentContext.ts +5 -11
  81. package/src/graphs/Graph.ts +23 -5
  82. package/src/graphs/MultiAgentGraph.ts +26 -17
  83. package/src/llm/bedrock/index.ts +180 -43
  84. package/src/llm/bedrock/llm.spec.ts +616 -0
  85. package/src/llm/bedrock/types.ts +51 -0
  86. package/src/llm/bedrock/utils/index.ts +18 -0
  87. package/src/llm/bedrock/utils/message_inputs.ts +563 -0
  88. package/src/llm/bedrock/utils/message_outputs.ts +310 -0
  89. package/src/messages/core.ts +1 -1
  90. package/src/scripts/code_exec_multi_session.ts +241 -0
  91. package/src/scripts/thinking-bedrock.ts +159 -0
  92. package/src/scripts/thinking.ts +39 -18
  93. package/src/scripts/tools.ts +7 -3
  94. package/src/specs/agent-handoffs.test.ts +1 -2
  95. package/src/specs/tool-error.test.ts +7 -2
  96. package/src/stream.ts +4 -2
  97. package/src/test/mockTools.ts +34 -14
  98. package/src/tools/CodeExecutor.ts +48 -31
  99. package/src/tools/ProgrammaticToolCalling.ts +24 -23
  100. package/src/tools/ToolNode.ts +9 -5
  101. package/src/tools/ToolSearch.ts +54 -43
  102. package/src/tools/search/schema.ts +30 -25
  103. package/src/tools/search/tool.ts +23 -16
  104. package/src/tools/search/types.ts +5 -29
  105. package/src/types/tools.ts +2 -0
  106. package/src/utils/index.ts +1 -0
  107. package/src/utils/schema.ts +35 -0
  108. package/src/utils/title.ts +31 -19
@@ -145,9 +145,9 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
145
145
 
146
146
  /**
147
147
  * Inject session context for code execution tools when available.
148
+ * Each file uses its own session_id (supporting multi-session file tracking).
148
149
  * Both session_id and _injected_files are injected directly to invokeParams
149
150
  * (not inside args) so they bypass Zod schema validation and reach config.toolCall.
150
- * This avoids /files endpoint race conditions.
151
151
  */
152
152
  if (
153
153
  call.name === Constants.EXECUTE_CODE ||
@@ -156,14 +156,18 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
156
156
  const codeSession = this.sessions?.get(Constants.EXECUTE_CODE) as
157
157
  | t.CodeSessionContext
158
158
  | undefined;
159
- if (codeSession?.session_id != null && codeSession.files.length > 0) {
160
- /** Convert tracked files to CodeEnvFile format for the API */
159
+ if (codeSession?.files != null && codeSession.files.length > 0) {
160
+ /**
161
+ * Convert tracked files to CodeEnvFile format for the API.
162
+ * Each file uses its own session_id (set when file was created).
163
+ * This supports files from multiple parallel/sequential executions.
164
+ */
161
165
  const fileRefs: t.CodeEnvFile[] = codeSession.files.map((file) => ({
162
- session_id: codeSession.session_id,
166
+ session_id: file.session_id ?? codeSession.session_id,
163
167
  id: file.id,
164
168
  name: file.name,
165
169
  }));
166
- /** Inject session_id and files directly - bypasses Zod, reaches config.toolCall */
170
+ /** Inject latest session_id and files - bypasses Zod, reaches config.toolCall */
167
171
  invokeParams = {
168
172
  ...invokeParams,
169
173
  session_id: codeSession.session_id,
@@ -1,5 +1,4 @@
1
1
  // src/tools/ToolSearch.ts
2
- import { z } from 'zod';
3
2
  import * as okapibm25Module from 'okapibm25';
4
3
  import { config } from 'dotenv';
5
4
 
@@ -40,20 +39,25 @@ const MAX_REGEX_COMPLEXITY = 5;
40
39
  /** Default search timeout in milliseconds */
41
40
  const SEARCH_TIMEOUT = 5000;
42
41
 
43
- /** Zod schema type for tool search parameters */
44
- type ToolSearchSchema = z.ZodObject<{
45
- query: z.ZodDefault<z.ZodOptional<z.ZodString>>;
46
- fields: z.ZodDefault<
47
- z.ZodOptional<z.ZodArray<z.ZodEnum<['name', 'description', 'parameters']>>>
48
- >;
49
- max_results: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
50
- mcp_server: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString>]>>;
51
- }>;
42
+ /** JSON schema type for tool search parameters */
43
+ interface ToolSearchSchema {
44
+ type: 'object';
45
+ properties: Record<string, unknown>;
46
+ required: string[];
47
+ }
48
+
49
+ /** Input params type for tool search */
50
+ interface ToolSearchParams {
51
+ query?: string;
52
+ fields?: ('name' | 'description' | 'parameters')[];
53
+ max_results?: number;
54
+ mcp_server?: string | string[];
55
+ }
52
56
 
53
57
  /**
54
- * Creates the Zod schema with dynamic query description based on mode.
58
+ * Creates the JSON schema with dynamic query description based on mode.
55
59
  * @param mode - The search mode determining query interpretation
56
- * @returns Zod schema for tool search parameters
60
+ * @returns JSON schema for tool search parameters
57
61
  */
58
62
  function createToolSearchSchema(mode: t.ToolSearchMode): ToolSearchSchema {
59
63
  const queryDescription =
@@ -61,33 +65,39 @@ function createToolSearchSchema(mode: t.ToolSearchMode): ToolSearchSchema {
61
65
  ? 'Search term to find in tool names and descriptions. Case-insensitive substring matching. Optional if mcp_server is provided.'
62
66
  : 'Regex pattern to search tool names and descriptions. Optional if mcp_server is provided.';
63
67
 
64
- return z.object({
65
- query: z
66
- .string()
67
- .max(MAX_PATTERN_LENGTH)
68
- .optional()
69
- .default('')
70
- .describe(queryDescription),
71
- fields: z
72
- .array(z.enum(['name', 'description', 'parameters']))
73
- .optional()
74
- .default(['name', 'description'])
75
- .describe('Which fields to search. Default: name and description'),
76
- max_results: z
77
- .number()
78
- .int()
79
- .min(1)
80
- .max(50)
81
- .optional()
82
- .default(10)
83
- .describe('Maximum number of matching tools to return'),
84
- mcp_server: z
85
- .union([z.string(), z.array(z.string())])
86
- .optional()
87
- .describe(
88
- 'Filter to tools from specific MCP server(s). Can be a single server name or array of names. If provided without a query, lists all tools from those servers.'
89
- ),
90
- });
68
+ return {
69
+ type: 'object',
70
+ properties: {
71
+ query: {
72
+ type: 'string',
73
+ maxLength: MAX_PATTERN_LENGTH,
74
+ default: '',
75
+ description: queryDescription,
76
+ },
77
+ fields: {
78
+ type: 'array',
79
+ items: { type: 'string', enum: ['name', 'description', 'parameters'] },
80
+ default: ['name', 'description'],
81
+ description: 'Which fields to search. Default: name and description',
82
+ },
83
+ max_results: {
84
+ type: 'integer',
85
+ minimum: 1,
86
+ maximum: 50,
87
+ default: 10,
88
+ description: 'Maximum number of matching tools to return',
89
+ },
90
+ mcp_server: {
91
+ oneOf: [
92
+ { type: 'string' },
93
+ { type: 'array', items: { type: 'string' } },
94
+ ],
95
+ description:
96
+ 'Filter to tools from specific MCP server(s). Can be a single server name or array of names. If provided without a query, lists all tools from those servers.',
97
+ },
98
+ },
99
+ required: [],
100
+ };
91
101
  }
92
102
 
93
103
  /**
@@ -748,7 +758,7 @@ function formatServerListing(
748
758
  */
749
759
  function createToolSearch(
750
760
  initParams: t.ToolSearchParams = {}
751
- ): DynamicStructuredTool<ReturnType<typeof createToolSearchSchema>> {
761
+ ): DynamicStructuredTool {
752
762
  const mode: t.ToolSearchMode = initParams.mode ?? 'code_interpreter';
753
763
  const defaultOnlyDeferred = initParams.onlyDeferred ?? true;
754
764
  const schema = createToolSearchSchema(mode);
@@ -802,10 +812,11 @@ Searches deferred tools by regex pattern.
802
812
  ${mcpNote}${toolsListSection}
803
813
  `.trim();
804
814
 
805
- return tool<typeof schema>(
806
- async (params, config) => {
815
+ return tool(
816
+ async (rawParams, config) => {
817
+ const params = rawParams as ToolSearchParams;
807
818
  const {
808
- query,
819
+ query = '',
809
820
  fields = ['name', 'description'],
810
821
  max_results = 10,
811
822
  mcp_server,
@@ -1,5 +1,3 @@
1
- import { z } from 'zod';
2
-
3
1
  export enum DATE_RANGE {
4
2
  PAST_HOUR = 'h',
5
3
  PAST_24_HOURS = 'd',
@@ -38,26 +36,33 @@ Examples:
38
36
  - "in" for India
39
37
  `.trim();
40
38
 
41
- export const querySchema = z.string().describe(DEFAULT_QUERY_DESCRIPTION);
42
- export const dateSchema = z
43
- .nativeEnum(DATE_RANGE)
44
- .optional()
45
- .describe('Date range for search results.');
46
- export const countrySchema = z
47
- .string()
48
- .optional()
49
- .describe(DEFAULT_COUNTRY_DESCRIPTION);
50
- export const imagesSchema = z
51
- .boolean()
52
- .optional()
53
- .describe('Whether to also run an image search.');
54
-
55
- export const videosSchema = z
56
- .boolean()
57
- .optional()
58
- .describe('Whether to also run a video search.');
59
-
60
- export const newsSchema = z
61
- .boolean()
62
- .optional()
63
- .describe('Whether to also run a news search.');
39
+ export const querySchema = {
40
+ type: 'string',
41
+ description: DEFAULT_QUERY_DESCRIPTION,
42
+ } as const;
43
+
44
+ export const dateSchema = {
45
+ type: 'string',
46
+ enum: Object.values(DATE_RANGE),
47
+ description: 'Date range for search results.',
48
+ } as const;
49
+
50
+ export const countrySchema = {
51
+ type: 'string',
52
+ description: DEFAULT_COUNTRY_DESCRIPTION,
53
+ } as const;
54
+
55
+ export const imagesSchema = {
56
+ type: 'boolean',
57
+ description: 'Whether to also run an image search.',
58
+ } as const;
59
+
60
+ export const videosSchema = {
61
+ type: 'boolean',
62
+ description: 'Whether to also run a video search.',
63
+ } as const;
64
+
65
+ export const newsSchema = {
66
+ type: 'boolean',
67
+ description: 'Whether to also run a news search.',
68
+ } as const;
@@ -1,4 +1,3 @@
1
- import { z } from 'zod';
2
1
  import { tool, DynamicStructuredTool } from '@langchain/core/tools';
3
2
  import type { RunnableConfig } from '@langchain/core/runnables';
4
3
  import type * as t from './types';
@@ -269,12 +268,13 @@ function createTool({
269
268
  search,
270
269
  onSearchResults: _onSearchResults,
271
270
  }: {
272
- schema: t.SearchToolSchema;
271
+ schema: Record<string, unknown>;
273
272
  search: ReturnType<typeof createSearchProcessor>;
274
273
  onSearchResults: t.SearchToolConfig['onSearchResults'];
275
- }): DynamicStructuredTool<typeof schema> {
276
- return tool<typeof schema>(
277
- async (params, runnableConfig) => {
274
+ }): DynamicStructuredTool {
275
+ return tool(
276
+ async (rawParams, runnableConfig) => {
277
+ const params = rawParams as SearchToolParams;
278
278
  const { query, date, country: _c, images, videos, news } = params;
279
279
  const country = typeof _c === 'string' && _c ? _c : undefined;
280
280
  const searchResult = await search({
@@ -353,9 +353,19 @@ Use anchor marker(s) immediately after the statement:
353
353
  * @param config - The search tool configuration
354
354
  * @returns A DynamicStructuredTool with a schema that depends on the searchProvider
355
355
  */
356
+ /** Input params type for search tool */
357
+ interface SearchToolParams {
358
+ query: string;
359
+ date?: DATE_RANGE;
360
+ country?: string;
361
+ images?: boolean;
362
+ videos?: boolean;
363
+ news?: boolean;
364
+ }
365
+
356
366
  export const createSearchTool = (
357
367
  config: t.SearchToolConfig = {}
358
- ): DynamicStructuredTool<typeof toolSchema> => {
368
+ ): DynamicStructuredTool => {
359
369
  const {
360
370
  searchProvider = 'serper',
361
371
  serperApiKey,
@@ -382,14 +392,7 @@ export const createSearchTool = (
382
392
 
383
393
  const logger = config.logger || createDefaultLogger();
384
394
 
385
- const schemaObject: {
386
- query: z.ZodString;
387
- date: z.ZodOptional<z.ZodNativeEnum<typeof DATE_RANGE>>;
388
- country?: z.ZodOptional<z.ZodString>;
389
- images: z.ZodOptional<z.ZodBoolean>;
390
- videos: z.ZodOptional<z.ZodBoolean>;
391
- news: z.ZodOptional<z.ZodBoolean>;
392
- } = {
395
+ const schemaProperties: Record<string, unknown> = {
393
396
  query: querySchema,
394
397
  date: dateSchema,
395
398
  images: imagesSchema,
@@ -398,10 +401,14 @@ export const createSearchTool = (
398
401
  };
399
402
 
400
403
  if (searchProvider === 'serper') {
401
- schemaObject.country = countrySchema;
404
+ schemaProperties.country = countrySchema;
402
405
  }
403
406
 
404
- const toolSchema = z.object(schemaObject);
407
+ const toolSchema = {
408
+ type: 'object',
409
+ properties: schemaProperties,
410
+ required: ['query'],
411
+ };
405
412
 
406
413
  const searchAPI = createSearchAPI({
407
414
  searchProvider,
@@ -1,4 +1,3 @@
1
- import { z } from 'zod';
2
1
  import type { Logger as WinstonLogger } from 'winston';
3
2
  import type { RunnableConfig } from '@langchain/core/runnables';
4
3
  import type { BaseReranker } from './rerankers';
@@ -657,31 +656,8 @@ export type ProcessSourcesFields = {
657
656
  onGetHighlights: SearchToolConfig['onGetHighlights'];
658
657
  };
659
658
 
660
- export type SearchToolSchema = z.ZodObject<
661
- {
662
- query: z.ZodString;
663
- date: z.ZodOptional<z.ZodNativeEnum<typeof DATE_RANGE>>;
664
- country?: z.ZodOptional<z.ZodString>;
665
- images: z.ZodOptional<z.ZodBoolean>;
666
- videos: z.ZodOptional<z.ZodBoolean>;
667
- news: z.ZodOptional<z.ZodBoolean>;
668
- },
669
- 'strip',
670
- z.ZodTypeAny,
671
- {
672
- query: string;
673
- date?: DATE_RANGE;
674
- country?: unknown;
675
- images?: boolean;
676
- videos?: boolean;
677
- news?: boolean;
678
- },
679
- {
680
- query: string;
681
- date?: DATE_RANGE;
682
- country?: unknown;
683
- images?: boolean;
684
- videos?: boolean;
685
- news?: boolean;
686
- }
687
- >;
659
+ export interface SearchToolSchema {
660
+ type: 'object';
661
+ properties: Record<string, unknown>;
662
+ required: string[];
663
+ }
@@ -74,6 +74,8 @@ export type FileRef = {
74
74
  id: string;
75
75
  name: string;
76
76
  path?: string;
77
+ /** Session ID this file belongs to (for multi-session file tracking) */
78
+ session_id?: string;
77
79
  };
78
80
 
79
81
  export type FileRefs = FileRef[];
@@ -4,3 +4,4 @@ export * from './misc';
4
4
  export * from './handlers';
5
5
  export * from './run';
6
6
  export * from './tokens';
7
+ export * from './schema';
@@ -0,0 +1,35 @@
1
+ // src/utils/schema.ts
2
+ import { zodToJsonSchema } from 'zod-to-json-schema';
3
+ import type { ZodTypeAny } from 'zod';
4
+
5
+ /** Checks if a schema is a Zod schema by looking for the _def property */
6
+ export function isZodSchema(schema: unknown): schema is ZodTypeAny {
7
+ return (
8
+ schema != null && typeof schema === 'object' && '_def' in (schema as object)
9
+ );
10
+ }
11
+
12
+ /**
13
+ * Converts a schema to JSON schema format.
14
+ * Handles both Zod schemas (converts) and JSON schemas (passthrough).
15
+ */
16
+ export function toJsonSchema(
17
+ schema: unknown,
18
+ name?: string,
19
+ description?: string
20
+ ): Record<string, unknown> {
21
+ if (isZodSchema(schema)) {
22
+ const zodSchema = schema as ZodTypeAny & {
23
+ describe: (desc: string) => ZodTypeAny;
24
+ };
25
+ const described =
26
+ description != null && description !== ''
27
+ ? zodSchema.describe(description)
28
+ : schema;
29
+ return zodToJsonSchema(
30
+ described as Parameters<typeof zodToJsonSchema>[0],
31
+ name ?? ''
32
+ );
33
+ }
34
+ return schema as Record<string, unknown>;
35
+ }
@@ -1,4 +1,3 @@
1
- import { z } from 'zod';
2
1
  import { ChatPromptTemplate } from '@langchain/core/prompts';
3
2
  import { RunnableLambda, RunnableSequence } from '@langchain/core/runnables';
4
3
  import type { Runnable, RunnableConfig } from '@langchain/core/runnables';
@@ -12,22 +11,33 @@ const defaultTitlePrompt = `Analyze this conversation and provide:
12
11
 
13
12
  {convo}`;
14
13
 
15
- const titleSchema = z.object({
16
- title: z
17
- .string()
18
- .describe(
19
- 'A concise title for the conversation in 5 words or less, without punctuation or quotation'
20
- ),
21
- });
22
-
23
- const combinedSchema = z.object({
24
- language: z.string().describe('The detected language of the conversation'),
25
- title: z
26
- .string()
27
- .describe(
28
- 'A concise title for the conversation in 5 words or less, without punctuation or quotation'
29
- ),
30
- });
14
+ const titleSchema = {
15
+ type: 'object',
16
+ properties: {
17
+ title: {
18
+ type: 'string',
19
+ description:
20
+ 'A concise title for the conversation in 5 words or less, without punctuation or quotation',
21
+ },
22
+ },
23
+ required: ['title'],
24
+ } as const;
25
+
26
+ const combinedSchema = {
27
+ type: 'object',
28
+ properties: {
29
+ language: {
30
+ type: 'string',
31
+ description: 'The detected language of the conversation',
32
+ },
33
+ title: {
34
+ type: 'string',
35
+ description:
36
+ 'A concise title for the conversation in 5 words or less, without punctuation or quotation',
37
+ },
38
+ },
39
+ required: ['language', 'title'],
40
+ } as const;
31
41
 
32
42
  export const createTitleRunnable = async (
33
43
  model: t.ChatModelInstance,
@@ -54,7 +64,8 @@ export const createTitleRunnable = async (
54
64
  input: { convo: string },
55
65
  config?: Partial<RunnableConfig>
56
66
  ): Promise<{ title: string }> => {
57
- return await titleOnlyInnerChain.invoke(input, config);
67
+ const result = await titleOnlyInnerChain.invoke(input, config);
68
+ return result as { title: string };
58
69
  },
59
70
  }).withConfig({ runName: 'TitleOnlyChain' });
60
71
 
@@ -64,7 +75,8 @@ export const createTitleRunnable = async (
64
75
  input: { convo: string },
65
76
  config?: Partial<RunnableConfig>
66
77
  ): Promise<{ language: string; title: string }> => {
67
- return await combinedInnerChain.invoke(input, config);
78
+ const result = await combinedInnerChain.invoke(input, config);
79
+ return result as { language: string; title: string };
68
80
  },
69
81
  }).withConfig({ runName: 'TitleLanguageChain' });
70
82