@typia/langchain 13.1.1 → 13.1.19

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,35 @@
1
+ import { StandardJSONSchemaV1 } from "@standard-schema/spec";
2
+ import { IHttpLlmFunction, ILlmFunction } from "@typia/interface";
3
+ /**
4
+ * A Standard JSON Schema view of one typia function's parameters.
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.
13
+ *
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.
20
+ *
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.
24
+ *
25
+ * Two version floors hold this together, and both are pinned in the package
26
+ * 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
+ * `StandardJSONSchemaV1` only exists from `@standard-schema/spec@1.1.0`.
30
+ *
31
+ * @see https://github.com/standard-schema/standard-schema
32
+ */
33
+ export declare namespace LangChainParameterConverter {
34
+ const convert: (func: ILlmFunction | IHttpLlmFunction) => StandardJSONSchemaV1;
35
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LangChainParameterConverter = void 0;
4
+ /**
5
+ * A Standard JSON Schema view of one typia function's parameters.
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.
14
+ *
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.
21
+ *
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.
25
+ *
26
+ * Two version floors hold this together, and both are pinned in the package
27
+ * 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
+ * `StandardJSONSchemaV1` only exists from `@standard-schema/spec@1.1.0`.
31
+ *
32
+ * @see https://github.com/standard-schema/standard-schema
33
+ */
34
+ var LangChainParameterConverter;
35
+ (function (LangChainParameterConverter) {
36
+ LangChainParameterConverter.convert = (func) => {
37
+ // Coercion never changes the shape a value must end up in, so the input and
38
+ // output schemas are the same document.
39
+ const jsonSchema = () => func.parameters;
40
+ return {
41
+ "~standard": {
42
+ version: 1,
43
+ vendor: "typia",
44
+ jsonSchema: {
45
+ input: jsonSchema,
46
+ output: jsonSchema,
47
+ },
48
+ },
49
+ };
50
+ };
51
+ })(LangChainParameterConverter || (exports.LangChainParameterConverter = LangChainParameterConverter = {}));
52
+ //# sourceMappingURL=LangChainParameterConverter.js.map
@@ -0,0 +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"}
@@ -0,0 +1,19 @@
1
+ //#region src/internal/LangChainParameterConverter.ts
2
+ let LangChainParameterConverter;
3
+ (function(_LangChainParameterConverter) {
4
+ _LangChainParameterConverter.convert = (func) => {
5
+ const jsonSchema = () => func.parameters;
6
+ return { "~standard": {
7
+ version: 1,
8
+ vendor: "typia",
9
+ jsonSchema: {
10
+ input: jsonSchema,
11
+ output: jsonSchema
12
+ }
13
+ } };
14
+ };
15
+ })(LangChainParameterConverter || (LangChainParameterConverter = {}));
16
+ //#endregion
17
+ export { LangChainParameterConverter };
18
+
19
+ //# sourceMappingURL=LangChainParameterConverter.mjs.map
@@ -0,0 +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"}
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.LangChainToolsRegistrar = void 0;
13
13
  const tools_1 = require("@langchain/core/tools");
14
14
  const utils_1 = require("@typia/utils");
15
+ const LangChainParameterConverter_1 = require("./LangChainParameterConverter");
15
16
  var LangChainToolsRegistrar;
16
17
  (function (LangChainToolsRegistrar) {
17
18
  LangChainToolsRegistrar.convert = (props) => {
@@ -19,16 +20,18 @@ var LangChainToolsRegistrar;
19
20
  const prefix = (_a = props.prefix) !== null && _a !== void 0 ? _a : false;
20
21
  const tools = [];
21
22
  // check duplicate tool names
22
- if (prefix === false && props.controllers.length >= 2) {
23
+ if (props.controllers.length >= 2) {
23
24
  const names = new Map();
24
25
  const duplicates = [];
25
26
  for (const controller of props.controllers) {
26
27
  for (const func of controller.application.functions) {
27
- const existing = names.get(func.name);
28
+ const toolName = getToolName(controller.name, func.name, prefix);
29
+ const existing = names.get(toolName);
30
+ const origin = `${controller.protocol} controller "${controller.name}" function "${func.name}"`;
28
31
  if (existing !== undefined)
29
- duplicates.push(`"${func.name}" in "${controller.name}" (conflicts with "${existing}")`);
32
+ duplicates.push(`"${toolName}" from ${origin} (conflicts with ${existing})`);
30
33
  else
31
- names.set(func.name, controller.name);
34
+ names.set(toolName, origin);
32
35
  }
33
36
  }
34
37
  if (duplicates.length > 0)
@@ -48,9 +51,7 @@ var LangChainToolsRegistrar;
48
51
  const convertClassController = (tools, controller, prefix) => {
49
52
  const execute = controller.execute;
50
53
  for (const func of controller.application.functions) {
51
- const toolName = prefix
52
- ? `${controller.name}_${func.name}`
53
- : func.name;
54
+ const toolName = getToolName(controller.name, func.name, prefix);
54
55
  const method = execute[func.name];
55
56
  if (typeof method !== "function") {
56
57
  throw new Error(`Method "${func.name}" not found on controller "${controller.name}"`);
@@ -66,9 +67,7 @@ var LangChainToolsRegistrar;
66
67
  const application = controller.application;
67
68
  const connection = controller.connection;
68
69
  for (const func of application.functions) {
69
- const toolName = prefix
70
- ? `${controller.name}_${func.name}`
71
- : func.name;
70
+ const toolName = getToolName(controller.name, func.name, prefix);
72
71
  tools.push(createTool({
73
72
  name: toolName,
74
73
  function: func,
@@ -96,7 +95,7 @@ var LangChainToolsRegistrar;
96
95
  const valid = utils_1.LlmJson.validateArguments(entry.function, args !== null && args !== void 0 ? args : {});
97
96
  if (valid.success === false)
98
97
  throw new tools_1.ToolInputParsingException(`Type errors in "${entry.name}" arguments:\n\n` +
99
- `\`\`\`json\n${utils_1.LlmJson.stringify(valid)}\n\`\`\``, JSON.stringify(args !== null && args !== void 0 ? args : {}));
98
+ utils_1.LlmJson.stringify(valid), JSON.stringify(args !== null && args !== void 0 ? args : {}));
100
99
  try {
101
100
  const result = yield entry.execute(valid.data);
102
101
  if (result === undefined) {
@@ -120,7 +119,14 @@ var LangChainToolsRegistrar;
120
119
  }), {
121
120
  name: entry.name,
122
121
  description: (_a = entry.function.description) !== null && _a !== void 0 ? _a : "",
123
- schema: entry.function.parameters,
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),
124
129
  }); };
130
+ const getToolName = (controllerName, functionName, prefix) => (prefix ? `${controllerName}_${functionName}` : functionName);
125
131
  })(LangChainToolsRegistrar || (exports.LangChainToolsRegistrar = LangChainToolsRegistrar = {}));
126
132
  //# 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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"}
@@ -1,3 +1,4 @@
1
+ import { LangChainParameterConverter } from "./LangChainParameterConverter.mjs";
1
2
  import { ToolInputParsingException, tool } from "@langchain/core/tools";
2
3
  import { HttpLlm, LlmJson } from "@typia/utils";
3
4
  //#region src/internal/LangChainToolsRegistrar.ts
@@ -6,13 +7,15 @@ let LangChainToolsRegistrar;
6
7
  _LangChainToolsRegistrar.convert = (props) => {
7
8
  const prefix = props.prefix ?? false;
8
9
  const tools = [];
9
- if (prefix === false && props.controllers.length >= 2) {
10
+ if (props.controllers.length >= 2) {
10
11
  const names = /* @__PURE__ */ new Map();
11
12
  const duplicates = [];
12
13
  for (const controller of props.controllers) for (const func of controller.application.functions) {
13
- const existing = names.get(func.name);
14
- if (existing !== void 0) duplicates.push(`"${func.name}" in "${controller.name}" (conflicts with "${existing}")`);
15
- else names.set(func.name, controller.name);
14
+ const toolName = getToolName(controller.name, func.name, prefix);
15
+ const existing = names.get(toolName);
16
+ const origin = `${controller.protocol} controller "${controller.name}" function "${func.name}"`;
17
+ if (existing !== void 0) duplicates.push(`"${toolName}" from ${origin} (conflicts with ${existing})`);
18
+ else names.set(toolName, origin);
16
19
  }
17
20
  if (duplicates.length > 0) throw new Error(`Duplicate tool names found:\n - ${duplicates.join("\n - ")}`);
18
21
  }
@@ -23,7 +26,7 @@ let LangChainToolsRegistrar;
23
26
  const convertClassController = (tools, controller, prefix) => {
24
27
  const execute = controller.execute;
25
28
  for (const func of controller.application.functions) {
26
- const toolName = prefix ? `${controller.name}_${func.name}` : func.name;
29
+ const toolName = getToolName(controller.name, func.name, prefix);
27
30
  const method = execute[func.name];
28
31
  if (typeof method !== "function") throw new Error(`Method "${func.name}" not found on controller "${controller.name}"`);
29
32
  tools.push(createTool({
@@ -37,7 +40,7 @@ let LangChainToolsRegistrar;
37
40
  const application = controller.application;
38
41
  const connection = controller.connection;
39
42
  for (const func of application.functions) {
40
- const toolName = prefix ? `${controller.name}_${func.name}` : func.name;
43
+ const toolName = getToolName(controller.name, func.name, prefix);
41
44
  tools.push(createTool({
42
45
  name: toolName,
43
46
  function: func,
@@ -60,7 +63,7 @@ let LangChainToolsRegistrar;
60
63
  };
61
64
  const createTool = (entry) => tool(async (args) => {
62
65
  const valid = LlmJson.validateArguments(entry.function, args ?? {});
63
- if (valid.success === false) throw new ToolInputParsingException(`Type errors in "${entry.name}" arguments:\n\n\`\`\`json\n${LlmJson.stringify(valid)}\n\`\`\``, JSON.stringify(args ?? {}));
66
+ if (valid.success === false) throw new ToolInputParsingException(`Type errors in "${entry.name}" arguments:\n\n` + LlmJson.stringify(valid), JSON.stringify(args ?? {}));
64
67
  try {
65
68
  const result = await entry.execute(valid.data);
66
69
  if (result === void 0) return entry.function.output === void 0 ? { success: true } : {
@@ -80,8 +83,9 @@ let LangChainToolsRegistrar;
80
83
  }, {
81
84
  name: entry.name,
82
85
  description: entry.function.description ?? "",
83
- schema: entry.function.parameters
86
+ schema: LangChainParameterConverter.convert(entry.function)
84
87
  });
88
+ const getToolName = (controllerName, functionName, prefix) => prefix ? `${controllerName}_${functionName}` : functionName;
85
89
  })(LangChainToolsRegistrar || (LangChainToolsRegistrar = {}));
86
90
  //#endregion
87
91
  export { LangChainToolsRegistrar };
@@ -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 {\n IHttpLlmController,\n IHttpLlmFunction,\n ILlmController,\n ILlmFunction,\n IValidation,\n} from \"@typia/interface\";\nimport { HttpLlm, LlmJson } from \"@typia/utils\";\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 (prefix === false && 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 existing: string | undefined = names.get(func.name);\n if (existing !== undefined)\n duplicates.push(\n `\"${func.name}\" in \"${controller.name}\" (conflicts with \"${existing}\")`,\n );\n else names.set(func.name, controller.name);\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 = prefix\n ? `${controller.name}_${func.name}`\n : func.name;\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 = prefix\n ? `${controller.name}_${func.name}`\n : func.name;\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 `\\`\\`\\`json\\n${LlmJson.stringify(valid)}\\n\\`\\`\\``,\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 schema: entry.function.parameters,\n },\n );\n}\n\ntype ITryResult =\n | { success: true; data?: unknown | undefined }\n | { success: false; error: string };\n"],"mappings":";;;AAcO,IAAA;;qCACmB,UAGO;EAC7B,MAAM,SAAkB,MAAM,UAAU;EACxC,MAAM,QAAiC,CAAC;EAGxC,IAAI,WAAW,SAAS,MAAM,YAAY,UAAU,GAAG;GACrD,MAAM,wBAA6B,IAAI,IAAI;GAC3C,MAAM,aAAuB,CAAC;GAC9B,KAAK,MAAM,cAAc,MAAM,aAC7B,KAAK,MAAM,QAAQ,WAAW,YAAY,WAAW;IACnD,MAAM,WAA+B,MAAM,IAAI,KAAK,IAAI;IACxD,IAAI,aAAa,KAAA,GACf,WAAW,KACT,IAAI,KAAK,KAAK,QAAQ,WAAW,KAAK,qBAAqB,SAAS,GACtE;SACG,MAAM,IAAI,KAAK,MAAM,WAAW,IAAI;GAC3C;GAEF,IAAI,WAAW,SAAS,GACtB,MAAM,IAAI,MACR,oCAAoC,WAAW,KAAK,QAAQ,GAC9D;EACJ;EAGA,KAAK,MAAM,cAAc,MAAM,aAC7B,IAAI,WAAW,aAAa,SAC1B,uBAAuB,OAAO,YAAY,MAAM;OAEhD,sBAAsB,OAAO,YAAY,MAAM;EAInD,OAAO;CACT;CAEA,MAAM,0BACJ,OACA,YACA,WACS;EACT,MAAM,UAAmC,WAAW;EAEpD,KAAK,MAAM,QAAQ,WAAW,YAAY,WAAW;GACnD,MAAM,WAAmB,SACrB,GAAG,WAAW,KAAK,GAAG,KAAK,SAC3B,KAAK;GAET,MAAM,SAAkB,QAAQ,KAAK;GACrC,IAAI,OAAO,WAAW,YACpB,MAAM,IAAI,MACR,WAAW,KAAK,KAAK,6BAA6B,WAAW,KAAK,EACpE;GAGF,MAAM,KACJ,WAAW;IACT,MAAM;IACN,UAAU;IACV,SAAS,OAAO,SAAkB,OAAO,KAAK,SAAS,IAAI;GAC7D,CAAC,CACH;EACF;CACF;CAEA,MAAM,yBACJ,OACA,YACA,WACS;EACT,MAAM,cAAc,WAAW;EAC/B,MAAM,aAAa,WAAW;EAE9B,KAAK,MAAM,QAAQ,YAAY,WAAW;GACxC,MAAM,WAAmB,SACrB,GAAG,WAAW,KAAK,GAAG,KAAK,SAC3B,KAAK;GAET,MAAM,KACJ,WAAW;IACT,MAAM;IACN,UAAU;IACV,SAAS,OAAO,SAAkB;KAChC,IAAI,WAAW,YAAY,KAAA,GAOzB,QAAO,MANgB,WAAW,QAAQ;MACxC;MACA;MACA,UAAU;MACV,WAAW;KACb,CAAC,EAAA,CACe;KAElB,OAAO,QAAQ,QAAQ;MACrB;MACA,UAAU;MACV;MACA,OAAO;KACT,CAAC;IACH;GACF,CAAC,CACH;EACF;CACF;CAEA,MAAM,cAAc,UAKlB,KACE,OAAO,SAAoC;EACzC,MAAM,QAA8B,QAAQ,kBAC1C,MAAM,UACN,QAAQ,CAAC,CACX;EACA,IAAI,MAAM,YAAY,OACpB,MAAM,IAAI,0BACR,mBAAmB,MAAM,KAAK,8BACb,QAAQ,UAAU,KAAK,EAAE,WAC1C,KAAK,UAAU,QAAQ,CAAC,CAAC,CAC3B;EACF,IAAI;GACF,MAAM,SAAkB,MAAM,MAAM,QAAQ,MAAM,IAAI;GACtD,IAAI,WAAW,KAAA,GACb,OAAO,MAAM,SAAS,WAAW,KAAA,IAC5B,EAAE,SAAS,KAAK,IAChB;IACC,SAAS;IACT,OAAO,aAAa,MAAM,KAAK;GACjC;GAEN,OAAO;IAAE,SAAS;IAAM,MAAM;GAAO;EACvC,SAAS,OAAO;GACd,OAAO;IACL,SAAS;IACT,OACE,iBAAiB,QACb,GAAG,MAAM,KAAK,IAAI,MAAM,YACxB,OAAO,KAAK;GACpB;EACF;CACF,GACA;EACE,MAAM,MAAM;EACZ,aAAa,MAAM,SAAS,eAAe;EAC3C,QAAQ,MAAM,SAAS;CACzB,CACF;GACH,4BAAA,0BAAA,CAAA,EAAD"}
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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typia/langchain",
3
- "version": "13.1.1",
3
+ "version": "13.1.19",
4
4
  "description": "LangChain.js integration for typia",
5
5
  "main": "lib/index.js",
6
6
  "exports": {
@@ -22,18 +22,19 @@
22
22
  },
23
23
  "homepage": "https://typia.io",
24
24
  "dependencies": {
25
- "@typia/utils": "^13.1.1",
26
- "@typia/interface": "^13.1.1"
25
+ "@standard-schema/spec": "^1.1.0",
26
+ "@typia/interface": "^13.1.19",
27
+ "@typia/utils": "^13.1.19"
27
28
  },
28
29
  "peerDependencies": {
29
- "@langchain/core": ">=1.0.0"
30
+ "@langchain/core": ">=1.1.30"
30
31
  },
31
32
  "devDependencies": {
32
33
  "@langchain/core": "^1.1.31",
33
34
  "rimraf": "^6.1.2",
34
35
  "rolldown": "^1.1.5",
35
36
  "tinyglobby": "^0.2.12",
36
- "ttsc": "^0.18.4",
37
+ "ttsc": "^0.19.2",
37
38
  "typescript": "^7.0.2"
38
39
  },
39
40
  "sideEffects": false,
@@ -0,0 +1,53 @@
1
+ import { StandardJSONSchemaV1 } from "@standard-schema/spec";
2
+ import { IHttpLlmFunction, ILlmFunction } from "@typia/interface";
3
+
4
+ /**
5
+ * A Standard JSON Schema view of one typia function's parameters.
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.
14
+ *
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.
21
+ *
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.
25
+ *
26
+ * Two version floors hold this together, and both are pinned in the package
27
+ * 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
+ * `StandardJSONSchemaV1` only exists from `@standard-schema/spec@1.1.0`.
31
+ *
32
+ * @see https://github.com/standard-schema/standard-schema
33
+ */
34
+ export namespace LangChainParameterConverter {
35
+ export const convert = (
36
+ func: ILlmFunction | IHttpLlmFunction,
37
+ ): StandardJSONSchemaV1 => {
38
+ // Coercion never changes the shape a value must end up in, so the input and
39
+ // output schemas are the same document.
40
+ const jsonSchema = (): Record<string, unknown> =>
41
+ func.parameters as unknown as Record<string, unknown>;
42
+ return {
43
+ "~standard": {
44
+ version: 1,
45
+ vendor: "typia",
46
+ jsonSchema: {
47
+ input: jsonSchema,
48
+ output: jsonSchema,
49
+ },
50
+ },
51
+ };
52
+ };
53
+ }
@@ -3,6 +3,7 @@ import {
3
3
  ToolInputParsingException,
4
4
  tool,
5
5
  } from "@langchain/core/tools";
6
+ import type { JSONSchema } from "@langchain/core/utils/json_schema";
6
7
  import {
7
8
  IHttpLlmController,
8
9
  IHttpLlmFunction,
@@ -12,6 +13,8 @@ import {
12
13
  } from "@typia/interface";
13
14
  import { HttpLlm, LlmJson } from "@typia/utils";
14
15
 
16
+ import { LangChainParameterConverter } from "./LangChainParameterConverter";
17
+
15
18
  export namespace LangChainToolsRegistrar {
16
19
  export const convert = (props: {
17
20
  controllers: Array<ILlmController | IHttpLlmController>;
@@ -21,17 +24,23 @@ export namespace LangChainToolsRegistrar {
21
24
  const tools: DynamicStructuredTool[] = [];
22
25
 
23
26
  // check duplicate tool names
24
- if (prefix === false && props.controllers.length >= 2) {
27
+ if (props.controllers.length >= 2) {
25
28
  const names: Map<string, string> = new Map();
26
29
  const duplicates: string[] = [];
27
30
  for (const controller of props.controllers) {
28
31
  for (const func of controller.application.functions) {
29
- const existing: string | undefined = names.get(func.name);
32
+ const toolName: string = getToolName(
33
+ controller.name,
34
+ func.name,
35
+ prefix,
36
+ );
37
+ const existing: string | undefined = names.get(toolName);
38
+ const origin: string = `${controller.protocol} controller "${controller.name}" function "${func.name}"`;
30
39
  if (existing !== undefined)
31
40
  duplicates.push(
32
- `"${func.name}" in "${controller.name}" (conflicts with "${existing}")`,
41
+ `"${toolName}" from ${origin} (conflicts with ${existing})`,
33
42
  );
34
- else names.set(func.name, controller.name);
43
+ else names.set(toolName, origin);
35
44
  }
36
45
  }
37
46
  if (duplicates.length > 0)
@@ -60,9 +69,7 @@ export namespace LangChainToolsRegistrar {
60
69
  const execute: Record<string, unknown> = controller.execute;
61
70
 
62
71
  for (const func of controller.application.functions) {
63
- const toolName: string = prefix
64
- ? `${controller.name}_${func.name}`
65
- : func.name;
72
+ const toolName: string = getToolName(controller.name, func.name, prefix);
66
73
 
67
74
  const method: unknown = execute[func.name];
68
75
  if (typeof method !== "function") {
@@ -90,9 +97,7 @@ export namespace LangChainToolsRegistrar {
90
97
  const connection = controller.connection;
91
98
 
92
99
  for (const func of application.functions) {
93
- const toolName: string = prefix
94
- ? `${controller.name}_${func.name}`
95
- : func.name;
100
+ const toolName: string = getToolName(controller.name, func.name, prefix);
96
101
 
97
102
  tools.push(
98
103
  createTool({
@@ -134,7 +139,7 @@ export namespace LangChainToolsRegistrar {
134
139
  if (valid.success === false)
135
140
  throw new ToolInputParsingException(
136
141
  `Type errors in "${entry.name}" arguments:\n\n` +
137
- `\`\`\`json\n${LlmJson.stringify(valid)}\n\`\`\``,
142
+ LlmJson.stringify(valid),
138
143
  JSON.stringify(args ?? {}),
139
144
  );
140
145
  try {
@@ -161,9 +166,23 @@ export namespace LangChainToolsRegistrar {
161
166
  {
162
167
  name: entry.name,
163
168
  description: entry.function.description ?? "",
164
- schema: entry.function.parameters,
169
+ // Declares the model-facing schema without a validator, so the
170
+ // coerce-and-validate step above is the only one that runs; see
171
+ // `LangChainParameterConverter`. The cast is needed because `tool()`
172
+ // still types `schema` as Zod-or-JSON-Schema, even though the
173
+ // `toJsonSchema` it reads that schema back with accepts Standard JSON
174
+ // Schema by its own public signature.
175
+ schema: LangChainParameterConverter.convert(
176
+ entry.function,
177
+ ) as JSONSchema,
165
178
  },
166
179
  );
180
+
181
+ const getToolName = (
182
+ controllerName: string,
183
+ functionName: string,
184
+ prefix: boolean,
185
+ ): string => (prefix ? `${controllerName}_${functionName}` : functionName);
167
186
  }
168
187
 
169
188
  type ITryResult =