@typia/langchain 13.1.19 → 13.2.0

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.
@@ -0,0 +1,66 @@
1
+ import type { DynamicStructuredTool } from "@langchain/core/tools";
2
+ import { IHttpLlmController, ILlmController } from "@typia/interface";
3
+ type ILangChainController = ILlmController | IHttpLlmController;
4
+ interface ILangChainToolsOptions {
5
+ /**
6
+ * Whether to add controller name as prefix to tool names.
7
+ *
8
+ * If `true`, tool names become `{controllerName}_{methodName}`. If `false`,
9
+ * tool names are just `{methodName}`.
10
+ *
11
+ * @default false
12
+ */
13
+ prefix?: boolean | undefined;
14
+ }
15
+ interface ILangChainToolsProps extends ILangChainToolsOptions {
16
+ /**
17
+ * List of controllers to convert to LangChain tools.
18
+ *
19
+ * - {@link ILlmController}: from `typia.llm.controller<Class>()`, converts all
20
+ * methods of the class to tools
21
+ * - {@link IHttpLlmController}: from `HttpLlm.controller()`, converts all
22
+ * operations from OpenAPI document to tools
23
+ */
24
+ controllers: ILangChainController[];
25
+ }
26
+ /**
27
+ * Convert typia controllers to LangChain tools.
28
+ *
29
+ * Converts TypeScript class methods via `typia.llm.controller<Class>()` or
30
+ * OpenAPI operations via `HttpLlm.controller()` to LangChain tools.
31
+ *
32
+ * Every tool call is validated by typia. If LLM provides invalid arguments,
33
+ * returns validation error formatted by {@link LlmJson.stringify} so that LLM
34
+ * can correct them automatically.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * import { initChatModel } from "langchain/chat_models/universal";
39
+ * import typia from "typia";
40
+ * import { toLangChainTools } from "@typia/langchain";
41
+ *
42
+ * class Calculator {
43
+ * add(input: { a: number; b: number }): { value: number } {
44
+ * return { value: input.a + input.b };
45
+ * }
46
+ * }
47
+ *
48
+ * const controller = typia.llm.controller<Calculator>(
49
+ * "calculator",
50
+ * new Calculator(),
51
+ * );
52
+ * const tools = toLangChainTools(controller);
53
+ *
54
+ * const llm = await initChatModel();
55
+ * const modelWithTools = llm.bindTools(tools);
56
+ * const result = await modelWithTools.invoke("What is 10 + 5?");
57
+ * ```;
58
+ *
59
+ * @param input Controller, controller list, or conversion properties
60
+ * @param options Conversion options when `input` is not a properties object
61
+ * @returns Array of LangChain DynamicStructuredTool
62
+ */
63
+ export declare function toLangChainTools(controller: ILangChainController, options?: ILangChainToolsOptions | undefined): DynamicStructuredTool[];
64
+ export declare function toLangChainTools(controllers: ILangChainController[], options?: ILangChainToolsOptions | undefined): DynamicStructuredTool[];
65
+ export declare function toLangChainTools(props: ILangChainToolsProps): DynamicStructuredTool[];
66
+ export {};
@@ -0,0 +1,66 @@
1
+ import type { DynamicStructuredTool } from "@langchain/core/tools";
2
+ import { IHttpLlmController, ILlmController } from "@typia/interface";
3
+ type ILangChainController = ILlmController | IHttpLlmController;
4
+ interface ILangChainToolsOptions {
5
+ /**
6
+ * Whether to add controller name as prefix to tool names.
7
+ *
8
+ * If `true`, tool names become `{controllerName}_{methodName}`. If `false`,
9
+ * tool names are just `{methodName}`.
10
+ *
11
+ * @default false
12
+ */
13
+ prefix?: boolean | undefined;
14
+ }
15
+ interface ILangChainToolsProps extends ILangChainToolsOptions {
16
+ /**
17
+ * List of controllers to convert to LangChain tools.
18
+ *
19
+ * - {@link ILlmController}: from `typia.llm.controller<Class>()`, converts all
20
+ * methods of the class to tools
21
+ * - {@link IHttpLlmController}: from `HttpLlm.controller()`, converts all
22
+ * operations from OpenAPI document to tools
23
+ */
24
+ controllers: ILangChainController[];
25
+ }
26
+ /**
27
+ * Convert typia controllers to LangChain tools.
28
+ *
29
+ * Converts TypeScript class methods via `typia.llm.controller<Class>()` or
30
+ * OpenAPI operations via `HttpLlm.controller()` to LangChain tools.
31
+ *
32
+ * Every tool call is validated by typia. If LLM provides invalid arguments,
33
+ * returns validation error formatted by {@link LlmJson.stringify} so that LLM
34
+ * can correct them automatically.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * import { initChatModel } from "langchain/chat_models/universal";
39
+ * import typia from "typia";
40
+ * import { toLangChainTools } from "@typia/langchain";
41
+ *
42
+ * class Calculator {
43
+ * add(input: { a: number; b: number }): { value: number } {
44
+ * return { value: input.a + input.b };
45
+ * }
46
+ * }
47
+ *
48
+ * const controller = typia.llm.controller<Calculator>(
49
+ * "calculator",
50
+ * new Calculator(),
51
+ * );
52
+ * const tools = toLangChainTools(controller);
53
+ *
54
+ * const llm = await initChatModel();
55
+ * const modelWithTools = llm.bindTools(tools);
56
+ * const result = await modelWithTools.invoke("What is 10 + 5?");
57
+ * ```;
58
+ *
59
+ * @param input Controller, controller list, or conversion properties
60
+ * @param options Conversion options when `input` is not a properties object
61
+ * @returns Array of LangChain DynamicStructuredTool
62
+ */
63
+ export declare function toLangChainTools(controller: ILangChainController, options?: ILangChainToolsOptions | undefined): DynamicStructuredTool[];
64
+ export declare function toLangChainTools(controllers: ILangChainController[], options?: ILangChainToolsOptions | undefined): DynamicStructuredTool[];
65
+ export declare function toLangChainTools(props: ILangChainToolsProps): DynamicStructuredTool[];
66
+ export {};
@@ -3,29 +3,31 @@ import { IHttpLlmFunction, ILlmFunction } from "@typia/interface";
3
3
  /**
4
4
  * A Standard JSON Schema view of one typia function's parameters.
5
5
  *
6
- * LangChain's tool `schema` fills two roles at once: `toJsonSchema(tool.schema)`
7
- * turns it into the parameters the model is shown, and `StructuredTool.call`
8
- * validates incoming arguments against it before the tool body runs. Handing
9
- * over a bare `ILlmSchema.IParameters` fills the first role but forfeits the
10
- * second — LangChain validates it with `@cfworker/json-schema`, which rejects
11
- * what typia would have coerced and reports the failure in its own words, so
12
- * typia's coercion and its correctable feedback both become unreachable.
6
+ * LangChain's tool `schema` fills two roles at once:
7
+ * `toJsonSchema(tool.schema)` turns it into the parameters the model is shown,
8
+ * and `StructuredTool.call` validates incoming arguments against it before the
9
+ * tool body runs. Handing over a bare `ILlmSchema.IParameters` fills the first
10
+ * role but forfeits the second — LangChain validates it with
11
+ * `@cfworker/json-schema`, which rejects what typia would have coerced and
12
+ * reports the failure in its own words, so typia's coercion and its correctable
13
+ * feedback both become unreachable.
13
14
  *
14
- * Standard JSON Schema separates the two roles. It carries a model-facing schema
15
- * under `~standard.jsonSchema` and, by declaring no `~standard.validate`, no
16
- * validator — which is exactly typia's position: show the model this schema, and
17
- * leave validation to `LlmJson.validateArguments` in the tool body. LangChain
18
- * reads the schema back through its own `toJsonSchema`, so the model sees the
19
- * same parameters document as before, byte for byte.
15
+ * Standard JSON Schema separates the two roles. It carries a model-facing
16
+ * schema under `~standard.jsonSchema` and, by declaring no
17
+ * `~standard.validate`, no validator — which is exactly typia's position: show
18
+ * the model this schema, and leave validation to `LlmJson.validateArguments` in
19
+ * the tool body. LangChain reads the schema back through its own
20
+ * `toJsonSchema`, so the model sees the same parameters document as before,
21
+ * byte for byte.
20
22
  *
21
- * `@typia/vercel` states the same contract to the AI SDK through `jsonSchema()`,
22
- * whose `validate` is likewise left undefined so that `safeValidateTypes`
23
- * short-circuits its own validation.
23
+ * `@typia/vercel` states the same contract to the AI SDK through
24
+ * `jsonSchema()`, whose `validate` is likewise left undefined so that
25
+ * `safeValidateTypes` short-circuits its own validation.
24
26
  *
25
27
  * Two version floors hold this together, and both are pinned in the package
26
28
  * manifest. `toJsonSchema` only reads `~standard.jsonSchema` from
27
- * `@langchain/core@1.1.30` onwards — older versions return the wrapper itself and
28
- * would advertise *that* to the model in place of the parameters — and
29
+ * `@langchain/core@1.1.30` onwards — older versions return the wrapper itself
30
+ * and would advertise _that_ to the model in place of the parameters — and
29
31
  * `StandardJSONSchemaV1` only exists from `@standard-schema/spec@1.1.0`.
30
32
  *
31
33
  * @see https://github.com/standard-schema/standard-schema
@@ -4,29 +4,31 @@ exports.LangChainParameterConverter = void 0;
4
4
  /**
5
5
  * A Standard JSON Schema view of one typia function's parameters.
6
6
  *
7
- * LangChain's tool `schema` fills two roles at once: `toJsonSchema(tool.schema)`
8
- * turns it into the parameters the model is shown, and `StructuredTool.call`
9
- * validates incoming arguments against it before the tool body runs. Handing
10
- * over a bare `ILlmSchema.IParameters` fills the first role but forfeits the
11
- * second — LangChain validates it with `@cfworker/json-schema`, which rejects
12
- * what typia would have coerced and reports the failure in its own words, so
13
- * typia's coercion and its correctable feedback both become unreachable.
7
+ * LangChain's tool `schema` fills two roles at once:
8
+ * `toJsonSchema(tool.schema)` turns it into the parameters the model is shown,
9
+ * and `StructuredTool.call` validates incoming arguments against it before the
10
+ * tool body runs. Handing over a bare `ILlmSchema.IParameters` fills the first
11
+ * role but forfeits the second — LangChain validates it with
12
+ * `@cfworker/json-schema`, which rejects what typia would have coerced and
13
+ * reports the failure in its own words, so typia's coercion and its correctable
14
+ * feedback both become unreachable.
14
15
  *
15
- * Standard JSON Schema separates the two roles. It carries a model-facing schema
16
- * under `~standard.jsonSchema` and, by declaring no `~standard.validate`, no
17
- * validator — which is exactly typia's position: show the model this schema, and
18
- * leave validation to `LlmJson.validateArguments` in the tool body. LangChain
19
- * reads the schema back through its own `toJsonSchema`, so the model sees the
20
- * same parameters document as before, byte for byte.
16
+ * Standard JSON Schema separates the two roles. It carries a model-facing
17
+ * schema under `~standard.jsonSchema` and, by declaring no
18
+ * `~standard.validate`, no validator — which is exactly typia's position: show
19
+ * the model this schema, and leave validation to `LlmJson.validateArguments` in
20
+ * the tool body. LangChain reads the schema back through its own
21
+ * `toJsonSchema`, so the model sees the same parameters document as before,
22
+ * byte for byte.
21
23
  *
22
- * `@typia/vercel` states the same contract to the AI SDK through `jsonSchema()`,
23
- * whose `validate` is likewise left undefined so that `safeValidateTypes`
24
- * short-circuits its own validation.
24
+ * `@typia/vercel` states the same contract to the AI SDK through
25
+ * `jsonSchema()`, whose `validate` is likewise left undefined so that
26
+ * `safeValidateTypes` short-circuits its own validation.
25
27
  *
26
28
  * Two version floors hold this together, and both are pinned in the package
27
29
  * manifest. `toJsonSchema` only reads `~standard.jsonSchema` from
28
- * `@langchain/core@1.1.30` onwards — older versions return the wrapper itself and
29
- * would advertise *that* to the model in place of the parameters — and
30
+ * `@langchain/core@1.1.30` onwards — older versions return the wrapper itself
31
+ * and would advertise _that_ to the model in place of the parameters — and
30
32
  * `StandardJSONSchemaV1` only exists from `@standard-schema/spec@1.1.0`.
31
33
  *
32
34
  * @see https://github.com/standard-schema/standard-schema
@@ -1 +1 @@
1
- {"version":3,"file":"LangChainParameterConverter.js","sourceRoot":"","sources":["../../src/internal/LangChainParameterConverter.ts"],"names":[],"mappings":";;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,IAAiB,2BAA2B,CAmB3C;AAnBD,WAAiB,2BAA2B;IAC7B,mCAAO,GAAG,CACrB,IAAqC,EACf,EAAE;QACxB,4EAA4E;QAC5E,wCAAwC;QACxC,MAAM,UAAU,GAAG,GAA4B,EAAE,CAC/C,IAAI,CAAC,UAAgD,CAAC;QACxD,OAAO;YACL,WAAW,EAAE;gBACX,OAAO,EAAE,CAAC;gBACV,MAAM,EAAE,OAAO;gBACf,UAAU,EAAE;oBACV,KAAK,EAAE,UAAU;oBACjB,MAAM,EAAE,UAAU;iBACnB;aACF;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC,EAnBgB,2BAA2B,aAA3B,2BAA2B,GAA3B,2BAA2B,QAmB3C"}
1
+ {"version":3,"file":"LangChainParameterConverter.js","sourceRoot":"","sources":["../../src/internal/LangChainParameterConverter.ts"],"names":[],"mappings":";;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,IAAiB,2BAA2B,CAmB3C;AAnBD,WAAiB,2BAA2B;IAC7B,mCAAO,GAAG,CACrB,IAAqC,EACf,EAAE;QACxB,4EAA4E;QAC5E,wCAAwC;QACxC,MAAM,UAAU,GAAG,GAA4B,EAAE,CAC/C,IAAI,CAAC,UAAgD,CAAC;QACxD,OAAO;YACL,WAAW,EAAE;gBACX,OAAO,EAAE,CAAC;gBACV,MAAM,EAAE,OAAO;gBACf,UAAU,EAAE;oBACV,KAAK,EAAE,UAAU;oBACjB,MAAM,EAAE,UAAU;iBACnB;aACF;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC,EAnBgB,2BAA2B,aAA3B,2BAA2B,GAA3B,2BAA2B,QAmB3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"LangChainParameterConverter.mjs","names":[],"sources":["../../src/internal/LangChainParameterConverter.ts"],"sourcesContent":["import { StandardJSONSchemaV1 } from \"@standard-schema/spec\";\nimport { IHttpLlmFunction, ILlmFunction } from \"@typia/interface\";\n\n/**\n * A Standard JSON Schema view of one typia function's parameters.\n *\n * LangChain's tool `schema` fills two roles at once: `toJsonSchema(tool.schema)`\n * turns it into the parameters the model is shown, and `StructuredTool.call`\n * validates incoming arguments against it before the tool body runs. Handing\n * over a bare `ILlmSchema.IParameters` fills the first role but forfeits the\n * second — LangChain validates it with `@cfworker/json-schema`, which rejects\n * what typia would have coerced and reports the failure in its own words, so\n * typia's coercion and its correctable feedback both become unreachable.\n *\n * Standard JSON Schema separates the two roles. It carries a model-facing schema\n * under `~standard.jsonSchema` and, by declaring no `~standard.validate`, no\n * validator — which is exactly typia's position: show the model this schema, and\n * leave validation to `LlmJson.validateArguments` in the tool body. LangChain\n * reads the schema back through its own `toJsonSchema`, so the model sees the\n * same parameters document as before, byte for byte.\n *\n * `@typia/vercel` states the same contract to the AI SDK through `jsonSchema()`,\n * whose `validate` is likewise left undefined so that `safeValidateTypes`\n * short-circuits its own validation.\n *\n * Two version floors hold this together, and both are pinned in the package\n * manifest. `toJsonSchema` only reads `~standard.jsonSchema` from\n * `@langchain/core@1.1.30` onwards — older versions return the wrapper itself and\n * would advertise *that* to the model in place of the parameters — and\n * `StandardJSONSchemaV1` only exists from `@standard-schema/spec@1.1.0`.\n *\n * @see https://github.com/standard-schema/standard-schema\n */\nexport namespace LangChainParameterConverter {\n export const convert = (\n func: ILlmFunction | IHttpLlmFunction,\n ): StandardJSONSchemaV1 => {\n // Coercion never changes the shape a value must end up in, so the input and\n // output schemas are the same document.\n const jsonSchema = (): Record<string, unknown> =>\n func.parameters as unknown as Record<string, unknown>;\n return {\n \"~standard\": {\n version: 1,\n vendor: \"typia\",\n jsonSchema: {\n input: jsonSchema,\n output: jsonSchema,\n },\n },\n };\n };\n}\n"],"mappings":";AAiCO,IAAA;;yCAEH,SACyB;EAGzB,MAAM,mBACJ,KAAK;EACP,OAAO,EACL,aAAa;GACX,SAAS;GACT,QAAQ;GACR,YAAY;IACV,OAAO;IACP,QAAQ;GACV;EACF,EACF;CACF;GACD,gCAAA,8BAAA,CAAA,EAAD"}
1
+ {"version":3,"file":"LangChainParameterConverter.mjs","names":[],"sources":["../../src/internal/LangChainParameterConverter.ts"],"sourcesContent":["import { StandardJSONSchemaV1 } from \"@standard-schema/spec\";\nimport { IHttpLlmFunction, ILlmFunction } from \"@typia/interface\";\n\n/**\n * A Standard JSON Schema view of one typia function's parameters.\n *\n * LangChain's tool `schema` fills two roles at once:\n * `toJsonSchema(tool.schema)` turns it into the parameters the model is shown,\n * and `StructuredTool.call` validates incoming arguments against it before the\n * tool body runs. Handing over a bare `ILlmSchema.IParameters` fills the first\n * role but forfeits the second — LangChain validates it with\n * `@cfworker/json-schema`, which rejects what typia would have coerced and\n * reports the failure in its own words, so typia's coercion and its correctable\n * feedback both become unreachable.\n *\n * Standard JSON Schema separates the two roles. It carries a model-facing\n * schema under `~standard.jsonSchema` and, by declaring no\n * `~standard.validate`, no validator — which is exactly typia's position: show\n * the model this schema, and leave validation to `LlmJson.validateArguments` in\n * the tool body. LangChain reads the schema back through its own\n * `toJsonSchema`, so the model sees the same parameters document as before,\n * byte for byte.\n *\n * `@typia/vercel` states the same contract to the AI SDK through\n * `jsonSchema()`, whose `validate` is likewise left undefined so that\n * `safeValidateTypes` short-circuits its own validation.\n *\n * Two version floors hold this together, and both are pinned in the package\n * manifest. `toJsonSchema` only reads `~standard.jsonSchema` from\n * `@langchain/core@1.1.30` onwards — older versions return the wrapper itself\n * and would advertise _that_ to the model in place of the parameters — and\n * `StandardJSONSchemaV1` only exists from `@standard-schema/spec@1.1.0`.\n *\n * @see https://github.com/standard-schema/standard-schema\n */\nexport namespace LangChainParameterConverter {\n export const convert = (\n func: ILlmFunction | IHttpLlmFunction,\n ): StandardJSONSchemaV1 => {\n // Coercion never changes the shape a value must end up in, so the input and\n // output schemas are the same document.\n const jsonSchema = (): Record<string, unknown> =>\n func.parameters as unknown as Record<string, unknown>;\n return {\n \"~standard\": {\n version: 1,\n vendor: \"typia\",\n jsonSchema: {\n input: jsonSchema,\n output: jsonSchema,\n },\n },\n };\n };\n}\n"],"mappings":";AAmCO,IAAA;;yCAEH,SACyB;EAGzB,MAAM,mBACJ,KAAK;EACP,OAAO,EACL,aAAa;GACX,SAAS;GACT,QAAQ;GACR,YAAY;IACV,OAAO;IACP,QAAQ;GACV;EACF,EACF;CACF;GACD,gCAAA,8BAAA,CAAA,EAAD"}
@@ -59,6 +59,7 @@ var LangChainToolsRegistrar;
59
59
  tools.push(createTool({
60
60
  name: toolName,
61
61
  function: func,
62
+ config: controller.application.config,
62
63
  execute: (args) => __awaiter(this, void 0, void 0, function* () { return method.call(execute, args); }),
63
64
  }));
64
65
  }
@@ -71,6 +72,7 @@ var LangChainToolsRegistrar;
71
72
  tools.push(createTool({
72
73
  name: toolName,
73
74
  function: func,
75
+ config: application.config,
74
76
  execute: (args) => __awaiter(this, void 0, void 0, function* () {
75
77
  if (controller.execute !== undefined) {
76
78
  const response = yield controller.execute({
@@ -91,42 +93,68 @@ var LangChainToolsRegistrar;
91
93
  }));
92
94
  }
93
95
  };
94
- const createTool = (entry) => { var _a; return (0, tools_1.tool)((args) => __awaiter(this, void 0, void 0, function* () {
95
- const valid = utils_1.LlmJson.validateArguments(entry.function, args !== null && args !== void 0 ? args : {});
96
- if (valid.success === false)
97
- throw new tools_1.ToolInputParsingException(`Type errors in "${entry.name}" arguments:\n\n` +
98
- utils_1.LlmJson.stringify(valid), JSON.stringify(args !== null && args !== void 0 ? args : {}));
99
- try {
100
- const result = yield entry.execute(valid.data);
101
- if (result === undefined) {
102
- return entry.function.output === undefined
103
- ? { success: true }
104
- : {
105
- success: false,
106
- error: `Function "${entry.name}" returned undefined despite declaring an output schema`,
107
- };
96
+ const createTool = (entry) => {
97
+ var _a;
98
+ // A declared return type is a promise to the model, so a result that breaks
99
+ // it is reported rather than delivered. `@typia/mcp` and `@typia/vercel`
100
+ // already refuse one; this tool consulted `output` for its existence alone,
101
+ // so a method returning nothing was reported while a method returning the
102
+ // wrong shape was not (#2302).
103
+ //
104
+ // The application's own config decides how the schema is read back: a
105
+ // strict application carries its constraints as description tags instead of
106
+ // keywords, and only that config tells the inverter to read them.
107
+ const validateOutput = entry.function.output === undefined
108
+ ? undefined
109
+ : utils_1.LlmJson.validate(entry.function.output, true, entry.config);
110
+ return (0, tools_1.tool)((args) => __awaiter(this, void 0, void 0, function* () {
111
+ const valid = utils_1.LlmJson.validateArguments(entry.function, args !== null && args !== void 0 ? args : {});
112
+ if (valid.success === false)
113
+ throw new tools_1.ToolInputParsingException(`Type errors in "${entry.name}" arguments:\n\n` +
114
+ utils_1.LlmJson.stringify(valid), JSON.stringify(args !== null && args !== void 0 ? args : {}));
115
+ try {
116
+ const result = yield entry.execute(valid.data);
117
+ if (result === undefined) {
118
+ return validateOutput === undefined
119
+ ? { success: true }
120
+ : {
121
+ success: false,
122
+ error: `Function "${entry.name}" returned undefined despite declaring an output schema`,
123
+ };
124
+ }
125
+ if (validateOutput !== undefined) {
126
+ const output = validateOutput(result);
127
+ if (output.success === false)
128
+ return {
129
+ success: false,
130
+ error: `Type errors in "${entry.name}" output:
131
+
132
+ ` + utils_1.LlmJson.stringify(output),
133
+ };
134
+ return { success: true, data: output.data };
135
+ }
136
+ return { success: true, data: result };
108
137
  }
109
- return { success: true, data: result };
110
- }
111
- catch (error) {
112
- return {
113
- success: false,
114
- error: error instanceof Error
115
- ? `${error.name}: ${error.message}`
116
- : String(error),
117
- };
118
- }
119
- }), {
120
- name: entry.name,
121
- description: (_a = entry.function.description) !== null && _a !== void 0 ? _a : "",
122
- // Declares the model-facing schema without a validator, so the
123
- // coerce-and-validate step above is the only one that runs; see
124
- // `LangChainParameterConverter`. The cast is needed because `tool()`
125
- // still types `schema` as Zod-or-JSON-Schema, even though the
126
- // `toJsonSchema` it reads that schema back with accepts Standard JSON
127
- // Schema by its own public signature.
128
- schema: LangChainParameterConverter_1.LangChainParameterConverter.convert(entry.function),
129
- }); };
138
+ catch (error) {
139
+ return {
140
+ success: false,
141
+ error: error instanceof Error
142
+ ? `${error.name}: ${error.message}`
143
+ : String(error),
144
+ };
145
+ }
146
+ }), {
147
+ name: entry.name,
148
+ description: (_a = entry.function.description) !== null && _a !== void 0 ? _a : "",
149
+ // Declares the model-facing schema without a validator, so the
150
+ // coerce-and-validate step above is the only one that runs; see
151
+ // `LangChainParameterConverter`. The cast is needed because `tool()`
152
+ // still types `schema` as Zod-or-JSON-Schema, even though the
153
+ // `toJsonSchema` it reads that schema back with accepts Standard JSON
154
+ // Schema by its own public signature.
155
+ schema: LangChainParameterConverter_1.LangChainParameterConverter.convert(entry.function),
156
+ });
157
+ };
130
158
  const getToolName = (controllerName, functionName, prefix) => (prefix ? `${controllerName}_${functionName}` : functionName);
131
159
  })(LangChainToolsRegistrar || (exports.LangChainToolsRegistrar = LangChainToolsRegistrar = {}));
132
160
  //# sourceMappingURL=LangChainToolsRegistrar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LangChainToolsRegistrar.js","sourceRoot":"","sources":["../../src/internal/LangChainToolsRegistrar.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LangChainToolsRegistrar.js","sourceRoot":"","sources":["../../src/internal/LangChainToolsRegistrar.ts"],"names":[],"mappings":"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"}
@@ -32,6 +32,7 @@ let LangChainToolsRegistrar;
32
32
  tools.push(createTool({
33
33
  name: toolName,
34
34
  function: func,
35
+ config: controller.application.config,
35
36
  execute: async (args) => method.call(execute, args)
36
37
  }));
37
38
  }
@@ -44,6 +45,7 @@ let LangChainToolsRegistrar;
44
45
  tools.push(createTool({
45
46
  name: toolName,
46
47
  function: func,
48
+ config: application.config,
47
49
  execute: async (args) => {
48
50
  if (controller.execute !== void 0) return (await controller.execute({
49
51
  connection,
@@ -61,30 +63,46 @@ let LangChainToolsRegistrar;
61
63
  }));
62
64
  }
63
65
  };
64
- const createTool = (entry) => tool(async (args) => {
65
- const valid = LlmJson.validateArguments(entry.function, args ?? {});
66
- if (valid.success === false) throw new ToolInputParsingException(`Type errors in "${entry.name}" arguments:\n\n` + LlmJson.stringify(valid), JSON.stringify(args ?? {}));
67
- try {
68
- const result = await entry.execute(valid.data);
69
- if (result === void 0) return entry.function.output === void 0 ? { success: true } : {
70
- success: false,
71
- error: `Function "${entry.name}" returned undefined despite declaring an output schema`
72
- };
73
- return {
74
- success: true,
75
- data: result
76
- };
77
- } catch (error) {
78
- return {
79
- success: false,
80
- error: error instanceof Error ? `${error.name}: ${error.message}` : String(error)
81
- };
82
- }
83
- }, {
84
- name: entry.name,
85
- description: entry.function.description ?? "",
86
- schema: LangChainParameterConverter.convert(entry.function)
87
- });
66
+ const createTool = (entry) => {
67
+ const validateOutput = entry.function.output === void 0 ? void 0 : LlmJson.validate(entry.function.output, true, entry.config);
68
+ return tool(async (args) => {
69
+ const valid = LlmJson.validateArguments(entry.function, args ?? {});
70
+ if (valid.success === false) throw new ToolInputParsingException(`Type errors in "${entry.name}" arguments:\n\n` + LlmJson.stringify(valid), JSON.stringify(args ?? {}));
71
+ try {
72
+ const result = await entry.execute(valid.data);
73
+ if (result === void 0) return validateOutput === void 0 ? { success: true } : {
74
+ success: false,
75
+ error: `Function "${entry.name}" returned undefined despite declaring an output schema`
76
+ };
77
+ if (validateOutput !== void 0) {
78
+ const output = validateOutput(result);
79
+ if (output.success === false) return {
80
+ success: false,
81
+ error: `Type errors in "${entry.name}" output:
82
+
83
+ ` + LlmJson.stringify(output)
84
+ };
85
+ return {
86
+ success: true,
87
+ data: output.data
88
+ };
89
+ }
90
+ return {
91
+ success: true,
92
+ data: result
93
+ };
94
+ } catch (error) {
95
+ return {
96
+ success: false,
97
+ error: error instanceof Error ? `${error.name}: ${error.message}` : String(error)
98
+ };
99
+ }
100
+ }, {
101
+ name: entry.name,
102
+ description: entry.function.description ?? "",
103
+ schema: LangChainParameterConverter.convert(entry.function)
104
+ });
105
+ };
88
106
  const getToolName = (controllerName, functionName, prefix) => prefix ? `${controllerName}_${functionName}` : functionName;
89
107
  })(LangChainToolsRegistrar || (LangChainToolsRegistrar = {}));
90
108
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"LangChainToolsRegistrar.mjs","names":[],"sources":["../../src/internal/LangChainToolsRegistrar.ts"],"sourcesContent":["import {\n DynamicStructuredTool,\n ToolInputParsingException,\n tool,\n} from \"@langchain/core/tools\";\nimport type { JSONSchema } from \"@langchain/core/utils/json_schema\";\nimport {\n IHttpLlmController,\n IHttpLlmFunction,\n ILlmController,\n ILlmFunction,\n IValidation,\n} from \"@typia/interface\";\nimport { HttpLlm, LlmJson } from \"@typia/utils\";\n\nimport { LangChainParameterConverter } from \"./LangChainParameterConverter\";\n\nexport namespace LangChainToolsRegistrar {\n export const convert = (props: {\n controllers: Array<ILlmController | IHttpLlmController>;\n prefix?: boolean | undefined;\n }): DynamicStructuredTool[] => {\n const prefix: boolean = props.prefix ?? false;\n const tools: DynamicStructuredTool[] = [];\n\n // check duplicate tool names\n if (props.controllers.length >= 2) {\n const names: Map<string, string> = new Map();\n const duplicates: string[] = [];\n for (const controller of props.controllers) {\n for (const func of controller.application.functions) {\n const toolName: string = getToolName(\n controller.name,\n func.name,\n prefix,\n );\n const existing: string | undefined = names.get(toolName);\n const origin: string = `${controller.protocol} controller \"${controller.name}\" function \"${func.name}\"`;\n if (existing !== undefined)\n duplicates.push(\n `\"${toolName}\" from ${origin} (conflicts with ${existing})`,\n );\n else names.set(toolName, origin);\n }\n }\n if (duplicates.length > 0)\n throw new Error(\n `Duplicate tool names found:\\n - ${duplicates.join(\"\\n - \")}`,\n );\n }\n\n // convert controllers to tools\n for (const controller of props.controllers) {\n if (controller.protocol === \"class\") {\n convertClassController(tools, controller, prefix);\n } else {\n convertHttpController(tools, controller, prefix);\n }\n }\n\n return tools;\n };\n\n const convertClassController = (\n tools: DynamicStructuredTool[],\n controller: ILlmController,\n prefix: boolean,\n ): void => {\n const execute: Record<string, unknown> = controller.execute;\n\n for (const func of controller.application.functions) {\n const toolName: string = getToolName(controller.name, func.name, prefix);\n\n const method: unknown = execute[func.name];\n if (typeof method !== \"function\") {\n throw new Error(\n `Method \"${func.name}\" not found on controller \"${controller.name}\"`,\n );\n }\n\n tools.push(\n createTool({\n name: toolName,\n function: func,\n execute: async (args: unknown) => method.call(execute, args),\n }),\n );\n }\n };\n\n const convertHttpController = (\n tools: DynamicStructuredTool[],\n controller: IHttpLlmController,\n prefix: boolean,\n ): void => {\n const application = controller.application;\n const connection = controller.connection;\n\n for (const func of application.functions) {\n const toolName: string = getToolName(controller.name, func.name, prefix);\n\n tools.push(\n createTool({\n name: toolName,\n function: func,\n execute: async (args: unknown) => {\n if (controller.execute !== undefined) {\n const response = await controller.execute({\n connection,\n application,\n function: func,\n arguments: args as object,\n });\n return response.body;\n }\n return HttpLlm.execute({\n application,\n function: func,\n connection,\n input: args as object,\n });\n },\n }),\n );\n }\n };\n\n const createTool = (entry: {\n name: string;\n function: ILlmFunction | IHttpLlmFunction;\n execute: (args: unknown) => Promise<unknown>;\n }): DynamicStructuredTool =>\n tool(\n async (args: unknown): Promise<unknown> => {\n const valid: IValidation<unknown> = LlmJson.validateArguments(\n entry.function,\n args ?? {},\n );\n if (valid.success === false)\n throw new ToolInputParsingException(\n `Type errors in \"${entry.name}\" arguments:\\n\\n` +\n LlmJson.stringify(valid),\n JSON.stringify(args ?? {}),\n );\n try {\n const result: unknown = await entry.execute(valid.data);\n if (result === undefined) {\n return entry.function.output === undefined\n ? ({ success: true } satisfies ITryResult)\n : ({\n success: false,\n error: `Function \"${entry.name}\" returned undefined despite declaring an output schema`,\n } satisfies ITryResult);\n }\n return { success: true, data: result } satisfies ITryResult;\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? `${error.name}: ${error.message}`\n : String(error),\n } satisfies ITryResult;\n }\n },\n {\n name: entry.name,\n description: entry.function.description ?? \"\",\n // Declares the model-facing schema without a validator, so the\n // coerce-and-validate step above is the only one that runs; see\n // `LangChainParameterConverter`. The cast is needed because `tool()`\n // still types `schema` as Zod-or-JSON-Schema, even though the\n // `toJsonSchema` it reads that schema back with accepts Standard JSON\n // Schema by its own public signature.\n schema: LangChainParameterConverter.convert(\n entry.function,\n ) as JSONSchema,\n },\n );\n\n const getToolName = (\n controllerName: string,\n functionName: string,\n prefix: boolean,\n ): string => (prefix ? `${controllerName}_${functionName}` : functionName);\n}\n\ntype ITryResult =\n | { success: true; data?: unknown | undefined }\n | { success: false; error: string };\n"],"mappings":"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"}
1
+ {"version":3,"file":"LangChainToolsRegistrar.mjs","names":[],"sources":["../../src/internal/LangChainToolsRegistrar.ts"],"sourcesContent":["import {\n DynamicStructuredTool,\n ToolInputParsingException,\n tool,\n} from \"@langchain/core/tools\";\nimport type { JSONSchema } from \"@langchain/core/utils/json_schema\";\nimport {\n IHttpLlmController,\n IHttpLlmFunction,\n ILlmController,\n ILlmFunction,\n ILlmSchema,\n IValidation,\n} from \"@typia/interface\";\nimport { HttpLlm, LlmJson } from \"@typia/utils\";\n\nimport { LangChainParameterConverter } from \"./LangChainParameterConverter\";\n\nexport namespace LangChainToolsRegistrar {\n export const convert = (props: {\n controllers: Array<ILlmController | IHttpLlmController>;\n prefix?: boolean | undefined;\n }): DynamicStructuredTool[] => {\n const prefix: boolean = props.prefix ?? false;\n const tools: DynamicStructuredTool[] = [];\n\n // check duplicate tool names\n if (props.controllers.length >= 2) {\n const names: Map<string, string> = new Map();\n const duplicates: string[] = [];\n for (const controller of props.controllers) {\n for (const func of controller.application.functions) {\n const toolName: string = getToolName(\n controller.name,\n func.name,\n prefix,\n );\n const existing: string | undefined = names.get(toolName);\n const origin: string = `${controller.protocol} controller \"${controller.name}\" function \"${func.name}\"`;\n if (existing !== undefined)\n duplicates.push(\n `\"${toolName}\" from ${origin} (conflicts with ${existing})`,\n );\n else names.set(toolName, origin);\n }\n }\n if (duplicates.length > 0)\n throw new Error(\n `Duplicate tool names found:\\n - ${duplicates.join(\"\\n - \")}`,\n );\n }\n\n // convert controllers to tools\n for (const controller of props.controllers) {\n if (controller.protocol === \"class\") {\n convertClassController(tools, controller, prefix);\n } else {\n convertHttpController(tools, controller, prefix);\n }\n }\n\n return tools;\n };\n\n const convertClassController = (\n tools: DynamicStructuredTool[],\n controller: ILlmController,\n prefix: boolean,\n ): void => {\n const execute: Record<string, unknown> = controller.execute;\n\n for (const func of controller.application.functions) {\n const toolName: string = getToolName(controller.name, func.name, prefix);\n\n const method: unknown = execute[func.name];\n if (typeof method !== \"function\") {\n throw new Error(\n `Method \"${func.name}\" not found on controller \"${controller.name}\"`,\n );\n }\n\n tools.push(\n createTool({\n name: toolName,\n function: func,\n config: controller.application.config,\n execute: async (args: unknown) => method.call(execute, args),\n }),\n );\n }\n };\n\n const convertHttpController = (\n tools: DynamicStructuredTool[],\n controller: IHttpLlmController,\n prefix: boolean,\n ): void => {\n const application = controller.application;\n const connection = controller.connection;\n\n for (const func of application.functions) {\n const toolName: string = getToolName(controller.name, func.name, prefix);\n\n tools.push(\n createTool({\n name: toolName,\n function: func,\n config: application.config,\n execute: async (args: unknown) => {\n if (controller.execute !== undefined) {\n const response = await controller.execute({\n connection,\n application,\n function: func,\n arguments: args as object,\n });\n return response.body;\n }\n return HttpLlm.execute({\n application,\n function: func,\n connection,\n input: args as object,\n });\n },\n }),\n );\n }\n };\n\n const createTool = (entry: {\n name: string;\n function: ILlmFunction | IHttpLlmFunction;\n config: ILlmSchema.IConfig;\n execute: (args: unknown) => Promise<unknown>;\n }): DynamicStructuredTool => {\n // A declared return type is a promise to the model, so a result that breaks\n // it is reported rather than delivered. `@typia/mcp` and `@typia/vercel`\n // already refuse one; this tool consulted `output` for its existence alone,\n // so a method returning nothing was reported while a method returning the\n // wrong shape was not (#2302).\n //\n // The application's own config decides how the schema is read back: a\n // strict application carries its constraints as description tags instead of\n // keywords, and only that config tells the inverter to read them.\n const validateOutput:\n | ((output: unknown) => IValidation<unknown>)\n | undefined =\n entry.function.output === undefined\n ? undefined\n : LlmJson.validate(entry.function.output, true, entry.config);\n return tool(\n async (args: unknown): Promise<unknown> => {\n const valid: IValidation<unknown> = LlmJson.validateArguments(\n entry.function,\n args ?? {},\n );\n if (valid.success === false)\n throw new ToolInputParsingException(\n `Type errors in \"${entry.name}\" arguments:\\n\\n` +\n LlmJson.stringify(valid),\n JSON.stringify(args ?? {}),\n );\n try {\n const result: unknown = await entry.execute(valid.data);\n if (result === undefined) {\n return validateOutput === undefined\n ? ({ success: true } satisfies ITryResult)\n : ({\n success: false,\n error: `Function \"${entry.name}\" returned undefined despite declaring an output schema`,\n } satisfies ITryResult);\n }\n if (validateOutput !== undefined) {\n const output: IValidation<unknown> = validateOutput(result);\n if (output.success === false)\n return {\n success: false,\n error:\n `Type errors in \"${entry.name}\" output:\n\n` + LlmJson.stringify(output),\n } satisfies ITryResult;\n return { success: true, data: output.data } satisfies ITryResult;\n }\n return { success: true, data: result } satisfies ITryResult;\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof Error\n ? `${error.name}: ${error.message}`\n : String(error),\n } satisfies ITryResult;\n }\n },\n {\n name: entry.name,\n description: entry.function.description ?? \"\",\n // Declares the model-facing schema without a validator, so the\n // coerce-and-validate step above is the only one that runs; see\n // `LangChainParameterConverter`. The cast is needed because `tool()`\n // still types `schema` as Zod-or-JSON-Schema, even though the\n // `toJsonSchema` it reads that schema back with accepts Standard JSON\n // Schema by its own public signature.\n schema: LangChainParameterConverter.convert(\n entry.function,\n ) as JSONSchema,\n },\n );\n };\n\n const getToolName = (\n controllerName: string,\n functionName: string,\n prefix: boolean,\n ): string => (prefix ? `${controllerName}_${functionName}` : functionName);\n}\n\ntype ITryResult =\n | { success: true; data?: unknown | undefined }\n | { success: false; error: string };\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,12 +1,19 @@
1
1
  {
2
2
  "name": "@typia/langchain",
3
- "version": "13.1.19",
3
+ "version": "13.2.0",
4
4
  "description": "LangChain.js integration for typia",
5
5
  "main": "lib/index.js",
6
6
  "exports": {
7
7
  ".": {
8
+ "import": {
9
+ "types": "./lib/index.d.mts",
10
+ "default": "./lib/index.mjs"
11
+ },
12
+ "require": {
13
+ "types": "./lib/index.d.cts",
14
+ "default": "./lib/index.js"
15
+ },
8
16
  "types": "./lib/index.d.ts",
9
- "import": "./lib/index.mjs",
10
17
  "default": "./lib/index.js"
11
18
  },
12
19
  "./package.json": "./package.json"
@@ -23,8 +30,8 @@
23
30
  "homepage": "https://typia.io",
24
31
  "dependencies": {
25
32
  "@standard-schema/spec": "^1.1.0",
26
- "@typia/interface": "^13.1.19",
27
- "@typia/utils": "^13.1.19"
33
+ "@typia/interface": "^13.2.0",
34
+ "@typia/utils": "^13.2.0"
28
35
  },
29
36
  "peerDependencies": {
30
37
  "@langchain/core": ">=1.1.30"
@@ -61,7 +68,7 @@
61
68
  "access": "public"
62
69
  },
63
70
  "scripts": {
64
- "build": "rimraf lib && ttsc && rolldown -c",
71
+ "build": "rimraf lib && ttsc && node ../../scripts/create-conditional-declarations.cjs lib/index.d.ts && rolldown -c",
65
72
  "dev": "ttsc --watch"
66
73
  },
67
74
  "module": "lib/index.mjs",
@@ -4,29 +4,31 @@ import { IHttpLlmFunction, ILlmFunction } from "@typia/interface";
4
4
  /**
5
5
  * A Standard JSON Schema view of one typia function's parameters.
6
6
  *
7
- * LangChain's tool `schema` fills two roles at once: `toJsonSchema(tool.schema)`
8
- * turns it into the parameters the model is shown, and `StructuredTool.call`
9
- * validates incoming arguments against it before the tool body runs. Handing
10
- * over a bare `ILlmSchema.IParameters` fills the first role but forfeits the
11
- * second — LangChain validates it with `@cfworker/json-schema`, which rejects
12
- * what typia would have coerced and reports the failure in its own words, so
13
- * typia's coercion and its correctable feedback both become unreachable.
7
+ * LangChain's tool `schema` fills two roles at once:
8
+ * `toJsonSchema(tool.schema)` turns it into the parameters the model is shown,
9
+ * and `StructuredTool.call` validates incoming arguments against it before the
10
+ * tool body runs. Handing over a bare `ILlmSchema.IParameters` fills the first
11
+ * role but forfeits the second — LangChain validates it with
12
+ * `@cfworker/json-schema`, which rejects what typia would have coerced and
13
+ * reports the failure in its own words, so typia's coercion and its correctable
14
+ * feedback both become unreachable.
14
15
  *
15
- * Standard JSON Schema separates the two roles. It carries a model-facing schema
16
- * under `~standard.jsonSchema` and, by declaring no `~standard.validate`, no
17
- * validator — which is exactly typia's position: show the model this schema, and
18
- * leave validation to `LlmJson.validateArguments` in the tool body. LangChain
19
- * reads the schema back through its own `toJsonSchema`, so the model sees the
20
- * same parameters document as before, byte for byte.
16
+ * Standard JSON Schema separates the two roles. It carries a model-facing
17
+ * schema under `~standard.jsonSchema` and, by declaring no
18
+ * `~standard.validate`, no validator — which is exactly typia's position: show
19
+ * the model this schema, and leave validation to `LlmJson.validateArguments` in
20
+ * the tool body. LangChain reads the schema back through its own
21
+ * `toJsonSchema`, so the model sees the same parameters document as before,
22
+ * byte for byte.
21
23
  *
22
- * `@typia/vercel` states the same contract to the AI SDK through `jsonSchema()`,
23
- * whose `validate` is likewise left undefined so that `safeValidateTypes`
24
- * short-circuits its own validation.
24
+ * `@typia/vercel` states the same contract to the AI SDK through
25
+ * `jsonSchema()`, whose `validate` is likewise left undefined so that
26
+ * `safeValidateTypes` short-circuits its own validation.
25
27
  *
26
28
  * Two version floors hold this together, and both are pinned in the package
27
29
  * manifest. `toJsonSchema` only reads `~standard.jsonSchema` from
28
- * `@langchain/core@1.1.30` onwards — older versions return the wrapper itself and
29
- * would advertise *that* to the model in place of the parameters — and
30
+ * `@langchain/core@1.1.30` onwards — older versions return the wrapper itself
31
+ * and would advertise _that_ to the model in place of the parameters — and
30
32
  * `StandardJSONSchemaV1` only exists from `@standard-schema/spec@1.1.0`.
31
33
  *
32
34
  * @see https://github.com/standard-schema/standard-schema
@@ -9,6 +9,7 @@ import {
9
9
  IHttpLlmFunction,
10
10
  ILlmController,
11
11
  ILlmFunction,
12
+ ILlmSchema,
12
13
  IValidation,
13
14
  } from "@typia/interface";
14
15
  import { HttpLlm, LlmJson } from "@typia/utils";
@@ -82,6 +83,7 @@ export namespace LangChainToolsRegistrar {
82
83
  createTool({
83
84
  name: toolName,
84
85
  function: func,
86
+ config: controller.application.config,
85
87
  execute: async (args: unknown) => method.call(execute, args),
86
88
  }),
87
89
  );
@@ -103,6 +105,7 @@ export namespace LangChainToolsRegistrar {
103
105
  createTool({
104
106
  name: toolName,
105
107
  function: func,
108
+ config: application.config,
106
109
  execute: async (args: unknown) => {
107
110
  if (controller.execute !== undefined) {
108
111
  const response = await controller.execute({
@@ -128,9 +131,25 @@ export namespace LangChainToolsRegistrar {
128
131
  const createTool = (entry: {
129
132
  name: string;
130
133
  function: ILlmFunction | IHttpLlmFunction;
134
+ config: ILlmSchema.IConfig;
131
135
  execute: (args: unknown) => Promise<unknown>;
132
- }): DynamicStructuredTool =>
133
- tool(
136
+ }): DynamicStructuredTool => {
137
+ // A declared return type is a promise to the model, so a result that breaks
138
+ // it is reported rather than delivered. `@typia/mcp` and `@typia/vercel`
139
+ // already refuse one; this tool consulted `output` for its existence alone,
140
+ // so a method returning nothing was reported while a method returning the
141
+ // wrong shape was not (#2302).
142
+ //
143
+ // The application's own config decides how the schema is read back: a
144
+ // strict application carries its constraints as description tags instead of
145
+ // keywords, and only that config tells the inverter to read them.
146
+ const validateOutput:
147
+ | ((output: unknown) => IValidation<unknown>)
148
+ | undefined =
149
+ entry.function.output === undefined
150
+ ? undefined
151
+ : LlmJson.validate(entry.function.output, true, entry.config);
152
+ return tool(
134
153
  async (args: unknown): Promise<unknown> => {
135
154
  const valid: IValidation<unknown> = LlmJson.validateArguments(
136
155
  entry.function,
@@ -145,13 +164,25 @@ export namespace LangChainToolsRegistrar {
145
164
  try {
146
165
  const result: unknown = await entry.execute(valid.data);
147
166
  if (result === undefined) {
148
- return entry.function.output === undefined
167
+ return validateOutput === undefined
149
168
  ? ({ success: true } satisfies ITryResult)
150
169
  : ({
151
170
  success: false,
152
171
  error: `Function "${entry.name}" returned undefined despite declaring an output schema`,
153
172
  } satisfies ITryResult);
154
173
  }
174
+ if (validateOutput !== undefined) {
175
+ const output: IValidation<unknown> = validateOutput(result);
176
+ if (output.success === false)
177
+ return {
178
+ success: false,
179
+ error:
180
+ `Type errors in "${entry.name}" output:
181
+
182
+ ` + LlmJson.stringify(output),
183
+ } satisfies ITryResult;
184
+ return { success: true, data: output.data } satisfies ITryResult;
185
+ }
155
186
  return { success: true, data: result } satisfies ITryResult;
156
187
  } catch (error) {
157
188
  return {
@@ -177,6 +208,7 @@ export namespace LangChainToolsRegistrar {
177
208
  ) as JSONSchema,
178
209
  },
179
210
  );
211
+ };
180
212
 
181
213
  const getToolName = (
182
214
  controllerName: string,