@langchain/openai 1.5.5 → 1.5.7
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.
- package/CHANGELOG.md +12 -0
- package/dist/azure/chat_models/common.cjs.map +1 -1
- package/dist/azure/chat_models/common.d.cts +1 -1
- package/dist/azure/chat_models/common.d.cts.map +1 -1
- package/dist/azure/chat_models/common.d.ts +1 -1
- package/dist/azure/chat_models/common.d.ts.map +1 -1
- package/dist/azure/chat_models/common.js.map +1 -1
- package/dist/azure/chat_models/completions.cjs.map +1 -1
- package/dist/azure/chat_models/completions.d.cts +0 -1
- package/dist/azure/chat_models/completions.d.cts.map +1 -1
- package/dist/azure/chat_models/completions.d.ts +0 -1
- package/dist/azure/chat_models/completions.d.ts.map +1 -1
- package/dist/azure/chat_models/completions.js.map +1 -1
- package/dist/azure/chat_models/index.cjs.map +1 -1
- package/dist/azure/chat_models/index.d.cts +1 -2
- package/dist/azure/chat_models/index.d.cts.map +1 -1
- package/dist/azure/chat_models/index.d.ts +0 -1
- package/dist/azure/chat_models/index.d.ts.map +1 -1
- package/dist/azure/chat_models/index.js.map +1 -1
- package/dist/azure/chat_models/responses.cjs.map +1 -1
- package/dist/azure/chat_models/responses.d.cts +0 -1
- package/dist/azure/chat_models/responses.d.cts.map +1 -1
- package/dist/azure/chat_models/responses.d.ts +0 -1
- package/dist/azure/chat_models/responses.d.ts.map +1 -1
- package/dist/azure/chat_models/responses.js.map +1 -1
- package/dist/azure/embeddings.cjs.map +1 -1
- package/dist/azure/embeddings.d.cts +2 -2
- package/dist/azure/embeddings.d.cts.map +1 -1
- package/dist/azure/embeddings.d.ts +2 -2
- package/dist/azure/embeddings.d.ts.map +1 -1
- package/dist/azure/embeddings.js.map +1 -1
- package/dist/azure/llms.cjs.map +1 -1
- package/dist/azure/llms.d.cts +0 -1
- package/dist/azure/llms.d.cts.map +1 -1
- package/dist/azure/llms.d.ts +0 -1
- package/dist/azure/llms.d.ts.map +1 -1
- package/dist/azure/llms.js.map +1 -1
- package/dist/chat_models/base.cjs +37 -3
- package/dist/chat_models/base.cjs.map +1 -1
- package/dist/chat_models/base.d.cts +6 -7
- package/dist/chat_models/base.d.cts.map +1 -1
- package/dist/chat_models/base.d.ts +5 -6
- package/dist/chat_models/base.d.ts.map +1 -1
- package/dist/chat_models/base.js +37 -3
- package/dist/chat_models/base.js.map +1 -1
- package/dist/chat_models/completions.cjs.map +1 -1
- package/dist/chat_models/completions.d.cts +0 -1
- package/dist/chat_models/completions.d.cts.map +1 -1
- package/dist/chat_models/completions.d.ts +0 -1
- package/dist/chat_models/completions.d.ts.map +1 -1
- package/dist/chat_models/completions.js.map +1 -1
- package/dist/chat_models/index.cjs.map +1 -1
- package/dist/chat_models/index.d.cts +14 -17
- package/dist/chat_models/index.d.cts.map +1 -1
- package/dist/chat_models/index.d.ts +14 -17
- package/dist/chat_models/index.d.ts.map +1 -1
- package/dist/chat_models/index.js.map +1 -1
- package/dist/chat_models/profiles.cjs.map +1 -1
- package/dist/chat_models/profiles.js.map +1 -1
- package/dist/chat_models/responses.cjs.map +1 -1
- package/dist/chat_models/responses.d.cts +0 -1
- package/dist/chat_models/responses.d.cts.map +1 -1
- package/dist/chat_models/responses.d.ts +0 -1
- package/dist/chat_models/responses.d.ts.map +1 -1
- package/dist/chat_models/responses.js.map +1 -1
- package/dist/converters/completions.cjs +2 -4
- package/dist/converters/completions.cjs.map +1 -1
- package/dist/converters/completions.d.cts +0 -1
- package/dist/converters/completions.d.cts.map +1 -1
- package/dist/converters/completions.d.ts +0 -1
- package/dist/converters/completions.d.ts.map +1 -1
- package/dist/converters/completions.js +2 -4
- package/dist/converters/completions.js.map +1 -1
- package/dist/converters/index.cjs +14 -2
- package/dist/converters/index.d.cts +2 -1
- package/dist/converters/index.d.ts +2 -1
- package/dist/converters/index.js +3 -3
- package/dist/converters/responses.cjs.map +1 -1
- package/dist/converters/responses.d.cts +0 -1
- package/dist/converters/responses.d.cts.map +1 -1
- package/dist/converters/responses.d.ts +0 -1
- package/dist/converters/responses.d.ts.map +1 -1
- package/dist/converters/responses.js.map +1 -1
- package/dist/embeddings.cjs.map +1 -1
- package/dist/embeddings.d.cts +2 -2
- package/dist/embeddings.d.cts.map +1 -1
- package/dist/embeddings.d.ts +2 -2
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/llms.cjs +1 -1
- package/dist/llms.cjs.map +1 -1
- package/dist/llms.d.cts +1 -2
- package/dist/llms.d.cts.map +1 -1
- package/dist/llms.d.ts +1 -2
- package/dist/llms.d.ts.map +1 -1
- package/dist/llms.js +1 -1
- package/dist/llms.js.map +1 -1
- package/dist/tools/applyPatch.cjs +4 -0
- package/dist/tools/applyPatch.cjs.map +1 -1
- package/dist/tools/applyPatch.d.cts +1 -2
- package/dist/tools/applyPatch.d.cts.map +1 -1
- package/dist/tools/applyPatch.d.ts +1 -2
- package/dist/tools/applyPatch.d.ts.map +1 -1
- package/dist/tools/applyPatch.js +1 -1
- package/dist/tools/applyPatch.js.map +1 -1
- package/dist/tools/codeInterpreter.cjs.map +1 -1
- package/dist/tools/codeInterpreter.d.cts +0 -1
- package/dist/tools/codeInterpreter.d.cts.map +1 -1
- package/dist/tools/codeInterpreter.d.ts +0 -1
- package/dist/tools/codeInterpreter.d.ts.map +1 -1
- package/dist/tools/codeInterpreter.js.map +1 -1
- package/dist/tools/computerUse.cjs +1 -0
- package/dist/tools/computerUse.cjs.map +1 -1
- package/dist/tools/computerUse.d.cts +1 -2
- package/dist/tools/computerUse.d.cts.map +1 -1
- package/dist/tools/computerUse.d.ts +1 -2
- package/dist/tools/computerUse.d.ts.map +1 -1
- package/dist/tools/computerUse.js +1 -1
- package/dist/tools/computerUse.js.map +1 -1
- package/dist/tools/custom.cjs.map +1 -1
- package/dist/tools/custom.d.cts +1 -2
- package/dist/tools/custom.d.cts.map +1 -1
- package/dist/tools/custom.d.ts +1 -2
- package/dist/tools/custom.d.ts.map +1 -1
- package/dist/tools/custom.js.map +1 -1
- package/dist/tools/dalle.cjs.map +1 -1
- package/dist/tools/dalle.d.cts +0 -1
- package/dist/tools/dalle.d.cts.map +1 -1
- package/dist/tools/dalle.d.ts +0 -1
- package/dist/tools/dalle.d.ts.map +1 -1
- package/dist/tools/dalle.js.map +1 -1
- package/dist/tools/fileSearch.cjs.map +1 -1
- package/dist/tools/fileSearch.d.cts +0 -1
- package/dist/tools/fileSearch.d.cts.map +1 -1
- package/dist/tools/fileSearch.d.ts +0 -1
- package/dist/tools/fileSearch.d.ts.map +1 -1
- package/dist/tools/fileSearch.js.map +1 -1
- package/dist/tools/imageGeneration.cjs.map +1 -1
- package/dist/tools/imageGeneration.d.cts +0 -1
- package/dist/tools/imageGeneration.d.cts.map +1 -1
- package/dist/tools/imageGeneration.d.ts +0 -1
- package/dist/tools/imageGeneration.d.ts.map +1 -1
- package/dist/tools/imageGeneration.js.map +1 -1
- package/dist/tools/index.cjs +2 -1
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.d.cts +1 -2
- package/dist/tools/index.d.cts.map +1 -1
- package/dist/tools/index.d.ts +1 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/localShell.cjs +2 -0
- package/dist/tools/localShell.cjs.map +1 -1
- package/dist/tools/localShell.d.cts +1 -2
- package/dist/tools/localShell.d.cts.map +1 -1
- package/dist/tools/localShell.d.ts +1 -2
- package/dist/tools/localShell.d.ts.map +1 -1
- package/dist/tools/localShell.js +1 -1
- package/dist/tools/localShell.js.map +1 -1
- package/dist/tools/mcp.cjs.map +1 -1
- package/dist/tools/mcp.d.cts +0 -1
- package/dist/tools/mcp.d.cts.map +1 -1
- package/dist/tools/mcp.d.ts +0 -1
- package/dist/tools/mcp.d.ts.map +1 -1
- package/dist/tools/mcp.js.map +1 -1
- package/dist/tools/shell.cjs +1 -0
- package/dist/tools/shell.cjs.map +1 -1
- package/dist/tools/shell.d.cts +1 -2
- package/dist/tools/shell.d.cts.map +1 -1
- package/dist/tools/shell.d.ts +1 -2
- package/dist/tools/shell.d.ts.map +1 -1
- package/dist/tools/shell.js +1 -1
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/toolSearch.cjs.map +1 -1
- package/dist/tools/toolSearch.d.cts +0 -1
- package/dist/tools/toolSearch.d.cts.map +1 -1
- package/dist/tools/toolSearch.d.ts +0 -1
- package/dist/tools/toolSearch.d.ts.map +1 -1
- package/dist/tools/toolSearch.js.map +1 -1
- package/dist/tools/webSearch.cjs.map +1 -1
- package/dist/tools/webSearch.d.cts +1 -2
- package/dist/tools/webSearch.d.cts.map +1 -1
- package/dist/tools/webSearch.d.ts +1 -2
- package/dist/tools/webSearch.d.ts.map +1 -1
- package/dist/tools/webSearch.js.map +1 -1
- package/dist/types.d.cts +0 -1
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/azure.cjs.map +1 -1
- package/dist/utils/azure.d.cts.map +1 -1
- package/dist/utils/azure.d.ts.map +1 -1
- package/dist/utils/azure.js.map +1 -1
- package/dist/utils/client.cjs.map +1 -1
- package/dist/utils/client.d.cts.map +1 -1
- package/dist/utils/client.d.ts.map +1 -1
- package/dist/utils/client.js.map +1 -1
- package/dist/utils/errors.cjs.map +1 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/misc.cjs +2 -0
- package/dist/utils/misc.cjs.map +1 -1
- package/dist/utils/misc.d.cts +0 -1
- package/dist/utils/misc.d.cts.map +1 -1
- package/dist/utils/misc.d.ts +0 -1
- package/dist/utils/misc.d.ts.map +1 -1
- package/dist/utils/misc.js +1 -1
- package/dist/utils/misc.js.map +1 -1
- package/dist/utils/output.cjs.map +1 -1
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/prompts.cjs.map +1 -1
- package/dist/utils/prompts.d.cts +0 -1
- package/dist/utils/prompts.d.cts.map +1 -1
- package/dist/utils/prompts.d.ts +0 -1
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js.map +1 -1
- package/dist/utils/responses_stream_events.cjs.map +1 -1
- package/dist/utils/responses_stream_events.d.cts +0 -1
- package/dist/utils/responses_stream_events.d.cts.map +1 -1
- package/dist/utils/responses_stream_events.d.ts +0 -1
- package/dist/utils/responses_stream_events.d.ts.map +1 -1
- package/dist/utils/responses_stream_events.js.map +1 -1
- package/dist/utils/tools.cjs.map +1 -1
- package/dist/utils/tools.d.cts +2 -0
- package/dist/utils/tools.d.cts.map +1 -1
- package/dist/utils/tools.d.ts +2 -0
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js.map +1 -1
- package/package.json +6 -6
package/dist/utils/misc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"misc.d.ts","names":[],"sources":["../../src/utils/misc.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"misc.d.ts","names":[],"sources":["../../src/utils/misc.ts"],"mappings":";;;iBAmEgB,oBACd,SAAS,cACR,OAAa"}
|
package/dist/utils/misc.js
CHANGED
|
@@ -45,6 +45,6 @@ function _modelPrefersResponsesAPI(model) {
|
|
|
45
45
|
return false;
|
|
46
46
|
}
|
|
47
47
|
//#endregion
|
|
48
|
-
export { _modelPrefersResponsesAPI, getFilenameFromMetadata, getRequiredFilenameFromMetadata, iife$1 as iife, isReasoningModel, messageToOpenAIRole };
|
|
48
|
+
export { LC_AUTOGENERATED_FILENAME, _modelPrefersResponsesAPI, extractGenericMessageCustomRole, getFilenameFromMetadata, getRequiredFilenameFromMetadata, iife$1 as iife, isReasoningModel, messageToOpenAIRole };
|
|
49
49
|
|
|
50
50
|
//# sourceMappingURL=misc.js.map
|
package/dist/utils/misc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"misc.js","names":["iife"],"sources":["../../src/utils/misc.ts"],"sourcesContent":["import type { OpenAI as OpenAIClient } from \"openai\";\nimport {\n BaseMessage,\n ChatMessage,\n ContentBlock,\n Data,\n} from \"@langchain/core/messages\";\n\nexport const iife = <T>(fn: () => T) => fn();\n\nexport function isReasoningModel(model?: string) {\n if (!model) return false;\n if (/^o\\d/.test(model ?? \"\")) return true;\n if (model.startsWith(\"gpt-5\") && !model.startsWith(\"gpt-5-chat\")) return true;\n return false;\n}\n\nexport function extractGenericMessageCustomRole(message: ChatMessage) {\n if (\n message.role !== \"system\" &&\n message.role !== \"developer\" &&\n message.role !== \"assistant\" &&\n message.role !== \"user\" &&\n message.role !== \"function\" &&\n message.role !== \"tool\"\n ) {\n console.warn(`Unknown message role: ${message.role}`);\n }\n\n return message.role as OpenAIClient.ChatCompletionRole;\n}\n\nexport function getFilenameFromMetadata(\n block:\n | ContentBlock.Multimodal.File\n | ContentBlock.Multimodal.Video\n | Data.StandardFileBlock\n): string | undefined {\n return (block.metadata?.filename ??\n block.metadata?.name ??\n block.metadata?.title) as string;\n}\n\nexport const LC_AUTOGENERATED_FILENAME = \"LC_AUTOGENERATED\";\n\nexport function getRequiredFilenameFromMetadata(\n block:\n | ContentBlock.Multimodal.File\n | ContentBlock.Multimodal.Video\n | Data.StandardFileBlock\n): string {\n const filename = (block.metadata?.filename ??\n block.metadata?.name ??\n block.metadata?.title) as string;\n\n if (!filename) {\n console.warn(\n \"OpenAI may require a filename for file uploads. Specify a filename \" +\n \"in the content block metadata, e.g.: { type: 'file', mimeType: \" +\n \"'...', data: '...', metadata: { filename: 'my-file.pdf' } }. \" +\n \"Using placeholder filename 'LC_AUTOGENERATED'.\"\n );\n return LC_AUTOGENERATED_FILENAME;\n }\n\n return filename;\n}\nexport function messageToOpenAIRole(\n message: BaseMessage\n): OpenAIClient.ChatCompletionRole {\n const type = message._getType();\n switch (type) {\n case \"system\":\n return \"system\";\n case \"ai\":\n return \"assistant\";\n case \"human\":\n return \"user\";\n case \"function\":\n return \"function\";\n case \"tool\":\n return \"tool\";\n case \"generic\": {\n if (!ChatMessage.isInstance(message))\n throw new Error(\"Invalid generic chat message\");\n return extractGenericMessageCustomRole(message);\n }\n default:\n throw new Error(`Unknown message type: ${type}`);\n }\n}\n\nexport function _modelPrefersResponsesAPI(model: string): boolean {\n if (model.includes(\"gpt-5.2-pro\")) return true;\n if (model.includes(\"gpt-5.4-pro\")) return true;\n if (model.includes(\"gpt-5.5-pro\")) return true;\n // Codex models are Responses API only\n if (model.includes(\"codex\")) return true;\n return false;\n}\n"],"mappings":";;AAQA,MAAaA,UAAW,OAAgB,
|
|
1
|
+
{"version":3,"file":"misc.js","names":["iife"],"sources":["../../src/utils/misc.ts"],"sourcesContent":["import type { OpenAI as OpenAIClient } from \"openai\";\nimport {\n BaseMessage,\n ChatMessage,\n ContentBlock,\n Data,\n} from \"@langchain/core/messages\";\n\nexport const iife = <T>(fn: () => T) => fn();\n\nexport function isReasoningModel(model?: string) {\n if (!model) return false;\n if (/^o\\d/.test(model ?? \"\")) return true;\n if (model.startsWith(\"gpt-5\") && !model.startsWith(\"gpt-5-chat\")) return true;\n return false;\n}\n\nexport function extractGenericMessageCustomRole(message: ChatMessage) {\n if (\n message.role !== \"system\" &&\n message.role !== \"developer\" &&\n message.role !== \"assistant\" &&\n message.role !== \"user\" &&\n message.role !== \"function\" &&\n message.role !== \"tool\"\n ) {\n console.warn(`Unknown message role: ${message.role}`);\n }\n\n return message.role as OpenAIClient.ChatCompletionRole;\n}\n\nexport function getFilenameFromMetadata(\n block:\n | ContentBlock.Multimodal.File\n | ContentBlock.Multimodal.Video\n | Data.StandardFileBlock\n): string | undefined {\n return (block.metadata?.filename ??\n block.metadata?.name ??\n block.metadata?.title) as string;\n}\n\nexport const LC_AUTOGENERATED_FILENAME = \"LC_AUTOGENERATED\";\n\nexport function getRequiredFilenameFromMetadata(\n block:\n | ContentBlock.Multimodal.File\n | ContentBlock.Multimodal.Video\n | Data.StandardFileBlock\n): string {\n const filename = (block.metadata?.filename ??\n block.metadata?.name ??\n block.metadata?.title) as string;\n\n if (!filename) {\n console.warn(\n \"OpenAI may require a filename for file uploads. Specify a filename \" +\n \"in the content block metadata, e.g.: { type: 'file', mimeType: \" +\n \"'...', data: '...', metadata: { filename: 'my-file.pdf' } }. \" +\n \"Using placeholder filename 'LC_AUTOGENERATED'.\"\n );\n return LC_AUTOGENERATED_FILENAME;\n }\n\n return filename;\n}\nexport function messageToOpenAIRole(\n message: BaseMessage\n): OpenAIClient.ChatCompletionRole {\n const type = message._getType();\n switch (type) {\n case \"system\":\n return \"system\";\n case \"ai\":\n return \"assistant\";\n case \"human\":\n return \"user\";\n case \"function\":\n return \"function\";\n case \"tool\":\n return \"tool\";\n case \"generic\": {\n if (!ChatMessage.isInstance(message))\n throw new Error(\"Invalid generic chat message\");\n return extractGenericMessageCustomRole(message);\n }\n default:\n throw new Error(`Unknown message type: ${type}`);\n }\n}\n\nexport function _modelPrefersResponsesAPI(model: string): boolean {\n if (model.includes(\"gpt-5.2-pro\")) return true;\n if (model.includes(\"gpt-5.4-pro\")) return true;\n if (model.includes(\"gpt-5.5-pro\")) return true;\n // Codex models are Responses API only\n if (model.includes(\"codex\")) return true;\n return false;\n}\n"],"mappings":";;AAQA,MAAaA,UAAW,OAAgB,GAAG;AAE3C,SAAgB,iBAAiB,OAAgB;CAC/C,IAAI,CAAC,OAAO,OAAO;CACnB,IAAI,OAAO,KAAK,SAAS,EAAE,GAAG,OAAO;CACrC,IAAI,MAAM,WAAW,OAAO,KAAK,CAAC,MAAM,WAAW,YAAY,GAAG,OAAO;CACzE,OAAO;AACT;AAEA,SAAgB,gCAAgC,SAAsB;CACpE,IACE,QAAQ,SAAS,YACjB,QAAQ,SAAS,eACjB,QAAQ,SAAS,eACjB,QAAQ,SAAS,UACjB,QAAQ,SAAS,cACjB,QAAQ,SAAS,QAEjB,QAAQ,KAAK,yBAAyB,QAAQ,MAAM;CAGtD,OAAO,QAAQ;AACjB;AAEA,SAAgB,wBACd,OAIoB;CACpB,OAAQ,MAAM,UAAU,YACtB,MAAM,UAAU,QAChB,MAAM,UAAU;AACpB;AAEA,MAAa,4BAA4B;AAEzC,SAAgB,gCACd,OAIQ;CACR,MAAM,WAAY,MAAM,UAAU,YAChC,MAAM,UAAU,QAChB,MAAM,UAAU;CAElB,IAAI,CAAC,UAAU;EACb,QAAQ,KACN,+OAIF;EACA,OAAO;CACT;CAEA,OAAO;AACT;AACA,SAAgB,oBACd,SACiC;CACjC,MAAM,OAAO,QAAQ,SAAS;CAC9B,QAAQ,MAAR;EACE,KAAK,UACH,OAAO;EACT,KAAK,MACH,OAAO;EACT,KAAK,SACH,OAAO;EACT,KAAK,YACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,KAAK;GACH,IAAI,CAAC,YAAY,WAAW,OAAO,GACjC,MAAM,IAAI,MAAM,8BAA8B;GAChD,OAAO,gCAAgC,OAAO;EAEhD,SACE,MAAM,IAAI,MAAM,yBAAyB,MAAM;CACnD;AACF;AAEA,SAAgB,0BAA0B,OAAwB;CAChE,IAAI,MAAM,SAAS,aAAa,GAAG,OAAO;CAC1C,IAAI,MAAM,SAAS,aAAa,GAAG,OAAO;CAC1C,IAAI,MAAM,SAAS,aAAa,GAAG,OAAO;CAE1C,IAAI,MAAM,SAAS,OAAO,GAAG,OAAO;CACpC,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.cjs","names":[],"sources":["../../src/utils/output.ts"],"sourcesContent":["import { OpenAI as OpenAIClient } from \"openai\";\nimport {\n InteropZodType,\n isZodSchemaV3,\n isZodSchemaV4,\n} from \"@langchain/core/utils/types\";\nimport { parse as parseV4, type $ZodType } from \"zod/v4/core\";\nimport { ResponseFormatJSONSchema } from \"openai/resources\";\nimport { zodResponseFormat } from \"openai/helpers/zod\";\nimport { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { toJsonSchema } from \"@langchain/core/utils/json_schema\";\n\nconst SUPPORTED_METHODS = [\n \"jsonSchema\",\n \"functionCalling\",\n \"jsonMode\",\n] as const;\ntype SupportedMethod = (typeof SUPPORTED_METHODS)[number];\n\n/**\n * Get the structured output method for a given model. By default, it uses\n * `jsonSchema` if the model supports it, otherwise it uses `functionCalling`.\n *\n * @throws if the method is invalid, e.g. is not a string or invalid method is provided.\n * @param model - The model name.\n * @param config - The structured output method options.\n * @returns The structured output method.\n */\nexport function getStructuredOutputMethod(\n model: string,\n method: unknown\n): SupportedMethod {\n /**\n * If a method is provided, validate it.\n */\n if (\n typeof method !== \"undefined\" &&\n !SUPPORTED_METHODS.includes(method as SupportedMethod)\n ) {\n throw new Error(\n `Invalid method: ${method}. Supported methods are: ${SUPPORTED_METHODS.join(\n \", \"\n )}`\n );\n }\n\n const hasSupportForJsonSchema =\n !model.startsWith(\"gpt-3\") &&\n !model.startsWith(\"gpt-4-\") &&\n model !== \"gpt-4\";\n\n /**\n * If the model supports JSON Schema, use it by default.\n */\n if (hasSupportForJsonSchema && !method) {\n return \"jsonSchema\";\n }\n\n if (!hasSupportForJsonSchema && method === \"jsonSchema\") {\n throw new Error(\n `JSON Schema is not supported for model \"${model}\". Please use a different method, e.g. \"functionCalling\" or \"jsonMode\".`\n );\n }\n\n /**\n * If the model does not support JSON Schema, use function calling by default.\n */\n return (method as SupportedMethod) ?? \"functionCalling\";\n}\n\n// inlined from openai/lib/parser.ts\nfunction makeParseableResponseFormat<ParsedT>(\n response_format: ResponseFormatJSONSchema,\n parser: (content: string) => ParsedT\n) {\n const obj = { ...response_format };\n\n Object.defineProperties(obj, {\n $brand: {\n value: \"auto-parseable-response-format\",\n enumerable: false,\n },\n $parseRaw: {\n value: parser,\n enumerable: false,\n },\n });\n\n return obj;\n}\n\nexport function interopZodResponseFormat(\n zodSchema: InteropZodType,\n name: string,\n props: Omit<ResponseFormatJSONSchema.JSONSchema, \"schema\" | \"strict\" | \"name\">\n) {\n if (isZodSchemaV3(zodSchema)) {\n return zodResponseFormat(zodSchema as never, name, props);\n }\n if (isZodSchemaV4(zodSchema)) {\n return makeParseableResponseFormat(\n {\n type: \"json_schema\",\n json_schema: {\n ...props,\n name,\n strict: true,\n schema: toJsonSchema(zodSchema, {\n cycles: \"ref\", // equivalent to nameStrategy: 'duplicate-ref'\n reused: \"ref\", // equivalent to $refStrategy: 'extract-to-root'\n override(ctx) {\n ctx.jsonSchema.title = name; // equivalent to `name` property\n // TODO: implement `nullableStrategy` patch-fix (zod doesn't support openApi3 json schema target)\n // TODO: implement `openaiStrictMode` patch-fix (where optional properties without `nullable` are not supported)\n },\n /// property equivalents from native `zodResponseFormat` fn\n // openaiStrictMode: true,\n // name,\n // nameStrategy: 'duplicate-ref',\n // $refStrategy: 'extract-to-root',\n // nullableStrategy: 'property',\n }),\n },\n },\n (content) =>\n parseV4(zodSchema as unknown as $ZodType, JSON.parse(content))\n );\n }\n throw new Error(\"Unsupported schema response format\");\n}\n\n/**\n * Handle multi modal response content.\n *\n * @param content The content of the message.\n * @param messages The messages of the response.\n * @returns The new content of the message.\n */\nexport function handleMultiModalOutput(\n content: string,\n messages: unknown\n): ContentBlock[] | string {\n /**\n * Handle OpenRouter image responses\n * @see https://openrouter.ai/docs/features/multimodal/image-generation#api-usage\n */\n if (\n messages &&\n typeof messages === \"object\" &&\n \"images\" in messages &&\n Array.isArray(messages.images)\n ) {\n const images = messages.images\n .filter((image) => typeof image?.image_url?.url === \"string\")\n .map(\n (image) =>\n ({\n type: \"image\",\n url: image.image_url.url as string,\n }) as const\n );\n return [{ type: \"text\", text: content }, ...images];\n }\n\n return content;\n}\n\n// TODO: make this a converter\nexport function _convertOpenAIResponsesUsageToLangChainUsage(\n usage?: OpenAIClient.Responses.ResponseUsage\n): UsageMetadata {\n const inputTokenDetails = {\n ...(usage?.input_tokens_details?.cached_tokens != null && {\n cache_read: usage?.input_tokens_details?.cached_tokens,\n }),\n };\n const outputTokenDetails = {\n ...(usage?.output_tokens_details?.reasoning_tokens != null && {\n reasoning: usage?.output_tokens_details?.reasoning_tokens,\n }),\n };\n return {\n input_tokens: usage?.input_tokens ?? 0,\n output_tokens: usage?.output_tokens ?? 0,\n total_tokens: usage?.total_tokens ?? 0,\n input_token_details: inputTokenDetails,\n output_token_details: outputTokenDetails,\n };\n}\n"],"mappings":";;;;;AAYA,MAAM,oBAAoB;CACxB;CACA;CACA;
|
|
1
|
+
{"version":3,"file":"output.cjs","names":[],"sources":["../../src/utils/output.ts"],"sourcesContent":["import { OpenAI as OpenAIClient } from \"openai\";\nimport {\n InteropZodType,\n isZodSchemaV3,\n isZodSchemaV4,\n} from \"@langchain/core/utils/types\";\nimport { parse as parseV4, type $ZodType } from \"zod/v4/core\";\nimport { ResponseFormatJSONSchema } from \"openai/resources\";\nimport { zodResponseFormat } from \"openai/helpers/zod\";\nimport { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { toJsonSchema } from \"@langchain/core/utils/json_schema\";\n\nconst SUPPORTED_METHODS = [\n \"jsonSchema\",\n \"functionCalling\",\n \"jsonMode\",\n] as const;\ntype SupportedMethod = (typeof SUPPORTED_METHODS)[number];\n\n/**\n * Get the structured output method for a given model. By default, it uses\n * `jsonSchema` if the model supports it, otherwise it uses `functionCalling`.\n *\n * @throws if the method is invalid, e.g. is not a string or invalid method is provided.\n * @param model - The model name.\n * @param config - The structured output method options.\n * @returns The structured output method.\n */\nexport function getStructuredOutputMethod(\n model: string,\n method: unknown\n): SupportedMethod {\n /**\n * If a method is provided, validate it.\n */\n if (\n typeof method !== \"undefined\" &&\n !SUPPORTED_METHODS.includes(method as SupportedMethod)\n ) {\n throw new Error(\n `Invalid method: ${method}. Supported methods are: ${SUPPORTED_METHODS.join(\n \", \"\n )}`\n );\n }\n\n const hasSupportForJsonSchema =\n !model.startsWith(\"gpt-3\") &&\n !model.startsWith(\"gpt-4-\") &&\n model !== \"gpt-4\";\n\n /**\n * If the model supports JSON Schema, use it by default.\n */\n if (hasSupportForJsonSchema && !method) {\n return \"jsonSchema\";\n }\n\n if (!hasSupportForJsonSchema && method === \"jsonSchema\") {\n throw new Error(\n `JSON Schema is not supported for model \"${model}\". Please use a different method, e.g. \"functionCalling\" or \"jsonMode\".`\n );\n }\n\n /**\n * If the model does not support JSON Schema, use function calling by default.\n */\n return (method as SupportedMethod) ?? \"functionCalling\";\n}\n\n// inlined from openai/lib/parser.ts\nfunction makeParseableResponseFormat<ParsedT>(\n response_format: ResponseFormatJSONSchema,\n parser: (content: string) => ParsedT\n) {\n const obj = { ...response_format };\n\n Object.defineProperties(obj, {\n $brand: {\n value: \"auto-parseable-response-format\",\n enumerable: false,\n },\n $parseRaw: {\n value: parser,\n enumerable: false,\n },\n });\n\n return obj;\n}\n\nexport function interopZodResponseFormat(\n zodSchema: InteropZodType,\n name: string,\n props: Omit<ResponseFormatJSONSchema.JSONSchema, \"schema\" | \"strict\" | \"name\">\n) {\n if (isZodSchemaV3(zodSchema)) {\n return zodResponseFormat(zodSchema as never, name, props);\n }\n if (isZodSchemaV4(zodSchema)) {\n return makeParseableResponseFormat(\n {\n type: \"json_schema\",\n json_schema: {\n ...props,\n name,\n strict: true,\n schema: toJsonSchema(zodSchema, {\n cycles: \"ref\", // equivalent to nameStrategy: 'duplicate-ref'\n reused: \"ref\", // equivalent to $refStrategy: 'extract-to-root'\n override(ctx) {\n ctx.jsonSchema.title = name; // equivalent to `name` property\n // TODO: implement `nullableStrategy` patch-fix (zod doesn't support openApi3 json schema target)\n // TODO: implement `openaiStrictMode` patch-fix (where optional properties without `nullable` are not supported)\n },\n /// property equivalents from native `zodResponseFormat` fn\n // openaiStrictMode: true,\n // name,\n // nameStrategy: 'duplicate-ref',\n // $refStrategy: 'extract-to-root',\n // nullableStrategy: 'property',\n }),\n },\n },\n (content) =>\n parseV4(zodSchema as unknown as $ZodType, JSON.parse(content))\n );\n }\n throw new Error(\"Unsupported schema response format\");\n}\n\n/**\n * Handle multi modal response content.\n *\n * @param content The content of the message.\n * @param messages The messages of the response.\n * @returns The new content of the message.\n */\nexport function handleMultiModalOutput(\n content: string,\n messages: unknown\n): ContentBlock[] | string {\n /**\n * Handle OpenRouter image responses\n * @see https://openrouter.ai/docs/features/multimodal/image-generation#api-usage\n */\n if (\n messages &&\n typeof messages === \"object\" &&\n \"images\" in messages &&\n Array.isArray(messages.images)\n ) {\n const images = messages.images\n .filter((image) => typeof image?.image_url?.url === \"string\")\n .map(\n (image) =>\n ({\n type: \"image\",\n url: image.image_url.url as string,\n }) as const\n );\n return [{ type: \"text\", text: content }, ...images];\n }\n\n return content;\n}\n\n// TODO: make this a converter\nexport function _convertOpenAIResponsesUsageToLangChainUsage(\n usage?: OpenAIClient.Responses.ResponseUsage\n): UsageMetadata {\n const inputTokenDetails = {\n ...(usage?.input_tokens_details?.cached_tokens != null && {\n cache_read: usage?.input_tokens_details?.cached_tokens,\n }),\n };\n const outputTokenDetails = {\n ...(usage?.output_tokens_details?.reasoning_tokens != null && {\n reasoning: usage?.output_tokens_details?.reasoning_tokens,\n }),\n };\n return {\n input_tokens: usage?.input_tokens ?? 0,\n output_tokens: usage?.output_tokens ?? 0,\n total_tokens: usage?.total_tokens ?? 0,\n input_token_details: inputTokenDetails,\n output_token_details: outputTokenDetails,\n };\n}\n"],"mappings":";;;;;AAYA,MAAM,oBAAoB;CACxB;CACA;CACA;AACF;;;;;;;;;;AAYA,SAAgB,0BACd,OACA,QACiB;;;;CAIjB,IACE,OAAO,WAAW,eAClB,CAAC,kBAAkB,SAAS,MAAyB,GAErD,MAAM,IAAI,MACR,mBAAmB,OAAO,2BAA2B,kBAAkB,KACrE,IACF,GACF;CAGF,MAAM,0BACJ,CAAC,MAAM,WAAW,OAAO,KACzB,CAAC,MAAM,WAAW,QAAQ,KAC1B,UAAU;;;;CAKZ,IAAI,2BAA2B,CAAC,QAC9B,OAAO;CAGT,IAAI,CAAC,2BAA2B,WAAW,cACzC,MAAM,IAAI,MACR,2CAA2C,MAAM,wEACnD;;;;CAMF,OAAQ,UAA8B;AACxC;AAGA,SAAS,4BACP,iBACA,QACA;CACA,MAAM,MAAM,EAAE,GAAG,gBAAgB;CAEjC,OAAO,iBAAiB,KAAK;EAC3B,QAAQ;GACN,OAAO;GACP,YAAY;EACd;EACA,WAAW;GACT,OAAO;GACP,YAAY;EACd;CACF,CAAC;CAED,OAAO;AACT;AAEA,SAAgB,yBACd,WACA,MACA,OACA;CACA,KAAA,GAAA,4BAAA,cAAA,CAAkB,SAAS,GACzB,QAAA,GAAA,mBAAA,kBAAA,CAAyB,WAAoB,MAAM,KAAK;CAE1D,KAAA,GAAA,4BAAA,cAAA,CAAkB,SAAS,GACzB,OAAO,4BACL;EACE,MAAM;EACN,aAAa;GACX,GAAG;GACH;GACA,QAAQ;GACR,SAAA,GAAA,kCAAA,aAAA,CAAqB,WAAW;IAC9B,QAAQ;IACR,QAAQ;IACR,SAAS,KAAK;KACZ,IAAI,WAAW,QAAQ;IAGzB;GAOF,CAAC;EACH;CACF,IACC,aAAA,GAAA,YAAA,MAAA,CACS,WAAkC,KAAK,MAAM,OAAO,CAAC,CACjE;CAEF,MAAM,IAAI,MAAM,oCAAoC;AACtD;;;;;;;;AASA,SAAgB,uBACd,SACA,UACyB;;;;;CAKzB,IACE,YACA,OAAO,aAAa,YACpB,YAAY,YACZ,MAAM,QAAQ,SAAS,MAAM,GAC7B;EACA,MAAM,SAAS,SAAS,OACrB,QAAQ,UAAU,OAAO,OAAO,WAAW,QAAQ,QAAQ,CAAC,CAC5D,KACE,WACE;GACC,MAAM;GACN,KAAK,MAAM,UAAU;EACvB,EACJ;EACF,OAAO,CAAC;GAAE,MAAM;GAAQ,MAAM;EAAQ,GAAG,GAAG,MAAM;CACpD;CAEA,OAAO;AACT"}
|
package/dist/utils/output.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","names":["parseV4"],"sources":["../../src/utils/output.ts"],"sourcesContent":["import { OpenAI as OpenAIClient } from \"openai\";\nimport {\n InteropZodType,\n isZodSchemaV3,\n isZodSchemaV4,\n} from \"@langchain/core/utils/types\";\nimport { parse as parseV4, type $ZodType } from \"zod/v4/core\";\nimport { ResponseFormatJSONSchema } from \"openai/resources\";\nimport { zodResponseFormat } from \"openai/helpers/zod\";\nimport { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { toJsonSchema } from \"@langchain/core/utils/json_schema\";\n\nconst SUPPORTED_METHODS = [\n \"jsonSchema\",\n \"functionCalling\",\n \"jsonMode\",\n] as const;\ntype SupportedMethod = (typeof SUPPORTED_METHODS)[number];\n\n/**\n * Get the structured output method for a given model. By default, it uses\n * `jsonSchema` if the model supports it, otherwise it uses `functionCalling`.\n *\n * @throws if the method is invalid, e.g. is not a string or invalid method is provided.\n * @param model - The model name.\n * @param config - The structured output method options.\n * @returns The structured output method.\n */\nexport function getStructuredOutputMethod(\n model: string,\n method: unknown\n): SupportedMethod {\n /**\n * If a method is provided, validate it.\n */\n if (\n typeof method !== \"undefined\" &&\n !SUPPORTED_METHODS.includes(method as SupportedMethod)\n ) {\n throw new Error(\n `Invalid method: ${method}. Supported methods are: ${SUPPORTED_METHODS.join(\n \", \"\n )}`\n );\n }\n\n const hasSupportForJsonSchema =\n !model.startsWith(\"gpt-3\") &&\n !model.startsWith(\"gpt-4-\") &&\n model !== \"gpt-4\";\n\n /**\n * If the model supports JSON Schema, use it by default.\n */\n if (hasSupportForJsonSchema && !method) {\n return \"jsonSchema\";\n }\n\n if (!hasSupportForJsonSchema && method === \"jsonSchema\") {\n throw new Error(\n `JSON Schema is not supported for model \"${model}\". Please use a different method, e.g. \"functionCalling\" or \"jsonMode\".`\n );\n }\n\n /**\n * If the model does not support JSON Schema, use function calling by default.\n */\n return (method as SupportedMethod) ?? \"functionCalling\";\n}\n\n// inlined from openai/lib/parser.ts\nfunction makeParseableResponseFormat<ParsedT>(\n response_format: ResponseFormatJSONSchema,\n parser: (content: string) => ParsedT\n) {\n const obj = { ...response_format };\n\n Object.defineProperties(obj, {\n $brand: {\n value: \"auto-parseable-response-format\",\n enumerable: false,\n },\n $parseRaw: {\n value: parser,\n enumerable: false,\n },\n });\n\n return obj;\n}\n\nexport function interopZodResponseFormat(\n zodSchema: InteropZodType,\n name: string,\n props: Omit<ResponseFormatJSONSchema.JSONSchema, \"schema\" | \"strict\" | \"name\">\n) {\n if (isZodSchemaV3(zodSchema)) {\n return zodResponseFormat(zodSchema as never, name, props);\n }\n if (isZodSchemaV4(zodSchema)) {\n return makeParseableResponseFormat(\n {\n type: \"json_schema\",\n json_schema: {\n ...props,\n name,\n strict: true,\n schema: toJsonSchema(zodSchema, {\n cycles: \"ref\", // equivalent to nameStrategy: 'duplicate-ref'\n reused: \"ref\", // equivalent to $refStrategy: 'extract-to-root'\n override(ctx) {\n ctx.jsonSchema.title = name; // equivalent to `name` property\n // TODO: implement `nullableStrategy` patch-fix (zod doesn't support openApi3 json schema target)\n // TODO: implement `openaiStrictMode` patch-fix (where optional properties without `nullable` are not supported)\n },\n /// property equivalents from native `zodResponseFormat` fn\n // openaiStrictMode: true,\n // name,\n // nameStrategy: 'duplicate-ref',\n // $refStrategy: 'extract-to-root',\n // nullableStrategy: 'property',\n }),\n },\n },\n (content) =>\n parseV4(zodSchema as unknown as $ZodType, JSON.parse(content))\n );\n }\n throw new Error(\"Unsupported schema response format\");\n}\n\n/**\n * Handle multi modal response content.\n *\n * @param content The content of the message.\n * @param messages The messages of the response.\n * @returns The new content of the message.\n */\nexport function handleMultiModalOutput(\n content: string,\n messages: unknown\n): ContentBlock[] | string {\n /**\n * Handle OpenRouter image responses\n * @see https://openrouter.ai/docs/features/multimodal/image-generation#api-usage\n */\n if (\n messages &&\n typeof messages === \"object\" &&\n \"images\" in messages &&\n Array.isArray(messages.images)\n ) {\n const images = messages.images\n .filter((image) => typeof image?.image_url?.url === \"string\")\n .map(\n (image) =>\n ({\n type: \"image\",\n url: image.image_url.url as string,\n }) as const\n );\n return [{ type: \"text\", text: content }, ...images];\n }\n\n return content;\n}\n\n// TODO: make this a converter\nexport function _convertOpenAIResponsesUsageToLangChainUsage(\n usage?: OpenAIClient.Responses.ResponseUsage\n): UsageMetadata {\n const inputTokenDetails = {\n ...(usage?.input_tokens_details?.cached_tokens != null && {\n cache_read: usage?.input_tokens_details?.cached_tokens,\n }),\n };\n const outputTokenDetails = {\n ...(usage?.output_tokens_details?.reasoning_tokens != null && {\n reasoning: usage?.output_tokens_details?.reasoning_tokens,\n }),\n };\n return {\n input_tokens: usage?.input_tokens ?? 0,\n output_tokens: usage?.output_tokens ?? 0,\n total_tokens: usage?.total_tokens ?? 0,\n input_token_details: inputTokenDetails,\n output_token_details: outputTokenDetails,\n };\n}\n"],"mappings":";;;;;AAYA,MAAM,oBAAoB;CACxB;CACA;CACA;
|
|
1
|
+
{"version":3,"file":"output.js","names":["parseV4"],"sources":["../../src/utils/output.ts"],"sourcesContent":["import { OpenAI as OpenAIClient } from \"openai\";\nimport {\n InteropZodType,\n isZodSchemaV3,\n isZodSchemaV4,\n} from \"@langchain/core/utils/types\";\nimport { parse as parseV4, type $ZodType } from \"zod/v4/core\";\nimport { ResponseFormatJSONSchema } from \"openai/resources\";\nimport { zodResponseFormat } from \"openai/helpers/zod\";\nimport { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { toJsonSchema } from \"@langchain/core/utils/json_schema\";\n\nconst SUPPORTED_METHODS = [\n \"jsonSchema\",\n \"functionCalling\",\n \"jsonMode\",\n] as const;\ntype SupportedMethod = (typeof SUPPORTED_METHODS)[number];\n\n/**\n * Get the structured output method for a given model. By default, it uses\n * `jsonSchema` if the model supports it, otherwise it uses `functionCalling`.\n *\n * @throws if the method is invalid, e.g. is not a string or invalid method is provided.\n * @param model - The model name.\n * @param config - The structured output method options.\n * @returns The structured output method.\n */\nexport function getStructuredOutputMethod(\n model: string,\n method: unknown\n): SupportedMethod {\n /**\n * If a method is provided, validate it.\n */\n if (\n typeof method !== \"undefined\" &&\n !SUPPORTED_METHODS.includes(method as SupportedMethod)\n ) {\n throw new Error(\n `Invalid method: ${method}. Supported methods are: ${SUPPORTED_METHODS.join(\n \", \"\n )}`\n );\n }\n\n const hasSupportForJsonSchema =\n !model.startsWith(\"gpt-3\") &&\n !model.startsWith(\"gpt-4-\") &&\n model !== \"gpt-4\";\n\n /**\n * If the model supports JSON Schema, use it by default.\n */\n if (hasSupportForJsonSchema && !method) {\n return \"jsonSchema\";\n }\n\n if (!hasSupportForJsonSchema && method === \"jsonSchema\") {\n throw new Error(\n `JSON Schema is not supported for model \"${model}\". Please use a different method, e.g. \"functionCalling\" or \"jsonMode\".`\n );\n }\n\n /**\n * If the model does not support JSON Schema, use function calling by default.\n */\n return (method as SupportedMethod) ?? \"functionCalling\";\n}\n\n// inlined from openai/lib/parser.ts\nfunction makeParseableResponseFormat<ParsedT>(\n response_format: ResponseFormatJSONSchema,\n parser: (content: string) => ParsedT\n) {\n const obj = { ...response_format };\n\n Object.defineProperties(obj, {\n $brand: {\n value: \"auto-parseable-response-format\",\n enumerable: false,\n },\n $parseRaw: {\n value: parser,\n enumerable: false,\n },\n });\n\n return obj;\n}\n\nexport function interopZodResponseFormat(\n zodSchema: InteropZodType,\n name: string,\n props: Omit<ResponseFormatJSONSchema.JSONSchema, \"schema\" | \"strict\" | \"name\">\n) {\n if (isZodSchemaV3(zodSchema)) {\n return zodResponseFormat(zodSchema as never, name, props);\n }\n if (isZodSchemaV4(zodSchema)) {\n return makeParseableResponseFormat(\n {\n type: \"json_schema\",\n json_schema: {\n ...props,\n name,\n strict: true,\n schema: toJsonSchema(zodSchema, {\n cycles: \"ref\", // equivalent to nameStrategy: 'duplicate-ref'\n reused: \"ref\", // equivalent to $refStrategy: 'extract-to-root'\n override(ctx) {\n ctx.jsonSchema.title = name; // equivalent to `name` property\n // TODO: implement `nullableStrategy` patch-fix (zod doesn't support openApi3 json schema target)\n // TODO: implement `openaiStrictMode` patch-fix (where optional properties without `nullable` are not supported)\n },\n /// property equivalents from native `zodResponseFormat` fn\n // openaiStrictMode: true,\n // name,\n // nameStrategy: 'duplicate-ref',\n // $refStrategy: 'extract-to-root',\n // nullableStrategy: 'property',\n }),\n },\n },\n (content) =>\n parseV4(zodSchema as unknown as $ZodType, JSON.parse(content))\n );\n }\n throw new Error(\"Unsupported schema response format\");\n}\n\n/**\n * Handle multi modal response content.\n *\n * @param content The content of the message.\n * @param messages The messages of the response.\n * @returns The new content of the message.\n */\nexport function handleMultiModalOutput(\n content: string,\n messages: unknown\n): ContentBlock[] | string {\n /**\n * Handle OpenRouter image responses\n * @see https://openrouter.ai/docs/features/multimodal/image-generation#api-usage\n */\n if (\n messages &&\n typeof messages === \"object\" &&\n \"images\" in messages &&\n Array.isArray(messages.images)\n ) {\n const images = messages.images\n .filter((image) => typeof image?.image_url?.url === \"string\")\n .map(\n (image) =>\n ({\n type: \"image\",\n url: image.image_url.url as string,\n }) as const\n );\n return [{ type: \"text\", text: content }, ...images];\n }\n\n return content;\n}\n\n// TODO: make this a converter\nexport function _convertOpenAIResponsesUsageToLangChainUsage(\n usage?: OpenAIClient.Responses.ResponseUsage\n): UsageMetadata {\n const inputTokenDetails = {\n ...(usage?.input_tokens_details?.cached_tokens != null && {\n cache_read: usage?.input_tokens_details?.cached_tokens,\n }),\n };\n const outputTokenDetails = {\n ...(usage?.output_tokens_details?.reasoning_tokens != null && {\n reasoning: usage?.output_tokens_details?.reasoning_tokens,\n }),\n };\n return {\n input_tokens: usage?.input_tokens ?? 0,\n output_tokens: usage?.output_tokens ?? 0,\n total_tokens: usage?.total_tokens ?? 0,\n input_token_details: inputTokenDetails,\n output_token_details: outputTokenDetails,\n };\n}\n"],"mappings":";;;;;AAYA,MAAM,oBAAoB;CACxB;CACA;CACA;AACF;;;;;;;;;;AAYA,SAAgB,0BACd,OACA,QACiB;;;;CAIjB,IACE,OAAO,WAAW,eAClB,CAAC,kBAAkB,SAAS,MAAyB,GAErD,MAAM,IAAI,MACR,mBAAmB,OAAO,2BAA2B,kBAAkB,KACrE,IACF,GACF;CAGF,MAAM,0BACJ,CAAC,MAAM,WAAW,OAAO,KACzB,CAAC,MAAM,WAAW,QAAQ,KAC1B,UAAU;;;;CAKZ,IAAI,2BAA2B,CAAC,QAC9B,OAAO;CAGT,IAAI,CAAC,2BAA2B,WAAW,cACzC,MAAM,IAAI,MACR,2CAA2C,MAAM,wEACnD;;;;CAMF,OAAQ,UAA8B;AACxC;AAGA,SAAS,4BACP,iBACA,QACA;CACA,MAAM,MAAM,EAAE,GAAG,gBAAgB;CAEjC,OAAO,iBAAiB,KAAK;EAC3B,QAAQ;GACN,OAAO;GACP,YAAY;EACd;EACA,WAAW;GACT,OAAO;GACP,YAAY;EACd;CACF,CAAC;CAED,OAAO;AACT;AAEA,SAAgB,yBACd,WACA,MACA,OACA;CACA,IAAI,cAAc,SAAS,GACzB,OAAO,kBAAkB,WAAoB,MAAM,KAAK;CAE1D,IAAI,cAAc,SAAS,GACzB,OAAO,4BACL;EACE,MAAM;EACN,aAAa;GACX,GAAG;GACH;GACA,QAAQ;GACR,QAAQ,aAAa,WAAW;IAC9B,QAAQ;IACR,QAAQ;IACR,SAAS,KAAK;KACZ,IAAI,WAAW,QAAQ;IAGzB;GAOF,CAAC;EACH;CACF,IACC,YACCA,MAAQ,WAAkC,KAAK,MAAM,OAAO,CAAC,CACjE;CAEF,MAAM,IAAI,MAAM,oCAAoC;AACtD;;;;;;;;AASA,SAAgB,uBACd,SACA,UACyB;;;;;CAKzB,IACE,YACA,OAAO,aAAa,YACpB,YAAY,YACZ,MAAM,QAAQ,SAAS,MAAM,GAC7B;EACA,MAAM,SAAS,SAAS,OACrB,QAAQ,UAAU,OAAO,OAAO,WAAW,QAAQ,QAAQ,CAAC,CAC5D,KACE,WACE;GACC,MAAM;GACN,KAAK,MAAM,UAAU;EACvB,EACJ;EACF,OAAO,CAAC;GAAE,MAAM;GAAQ,MAAM;EAAQ,GAAG,GAAG,MAAM;CACpD;CAEA,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.cjs","names":["convertMessagesToCompletionsMessageParams"],"sources":["../../src/utils/prompts.ts"],"sourcesContent":["import type { BasePromptValue } from \"@langchain/core/prompt_values\";\nimport type { OpenAI } from \"openai\";\nimport { convertMessagesToCompletionsMessageParams } from \"../converters/completions.js\";\n\n/**\n * Convert a formatted LangChain prompt (e.g. pulled from the hub) into\n * a format expected by OpenAI's JS SDK.\n *\n * Requires the \"@langchain/openai\" package to be installed in addition\n * to the OpenAI SDK.\n *\n * @example\n * ```ts\n * import { convertPromptToOpenAI } from \"langsmith/utils/hub/openai\";\n * import { pull } from \"langchain/hub\";\n *\n * import OpenAI from 'openai';\n *\n * const prompt = await pull(\"jacob/joke-generator\");\n * const formattedPrompt = await prompt.invoke({\n * topic: \"cats\",\n * });\n *\n * const { messages } = convertPromptToOpenAI(formattedPrompt);\n *\n * const openAIClient = new OpenAI();\n *\n * const openaiResponse = await openAIClient.chat.completions.create({\n * model: \"gpt-4o-mini\",\n * messages,\n * });\n * ```\n * @param formattedPrompt\n * @returns A partial OpenAI payload.\n */\n// TODO: make this a converter\nexport function convertPromptToOpenAI(formattedPrompt: BasePromptValue): {\n messages: OpenAI.Chat.ChatCompletionMessageParam[];\n} {\n const messages = formattedPrompt.toChatMessages();\n return {\n messages: convertMessagesToCompletionsMessageParams({\n messages,\n }) as OpenAI.Chat.ChatCompletionMessageParam[],\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,sBAAsB,iBAEpC;
|
|
1
|
+
{"version":3,"file":"prompts.cjs","names":["convertMessagesToCompletionsMessageParams"],"sources":["../../src/utils/prompts.ts"],"sourcesContent":["import type { BasePromptValue } from \"@langchain/core/prompt_values\";\nimport type { OpenAI } from \"openai\";\nimport { convertMessagesToCompletionsMessageParams } from \"../converters/completions.js\";\n\n/**\n * Convert a formatted LangChain prompt (e.g. pulled from the hub) into\n * a format expected by OpenAI's JS SDK.\n *\n * Requires the \"@langchain/openai\" package to be installed in addition\n * to the OpenAI SDK.\n *\n * @example\n * ```ts\n * import { convertPromptToOpenAI } from \"langsmith/utils/hub/openai\";\n * import { pull } from \"langchain/hub\";\n *\n * import OpenAI from 'openai';\n *\n * const prompt = await pull(\"jacob/joke-generator\");\n * const formattedPrompt = await prompt.invoke({\n * topic: \"cats\",\n * });\n *\n * const { messages } = convertPromptToOpenAI(formattedPrompt);\n *\n * const openAIClient = new OpenAI();\n *\n * const openaiResponse = await openAIClient.chat.completions.create({\n * model: \"gpt-4o-mini\",\n * messages,\n * });\n * ```\n * @param formattedPrompt\n * @returns A partial OpenAI payload.\n */\n// TODO: make this a converter\nexport function convertPromptToOpenAI(formattedPrompt: BasePromptValue): {\n messages: OpenAI.Chat.ChatCompletionMessageParam[];\n} {\n const messages = formattedPrompt.toChatMessages();\n return {\n messages: convertMessagesToCompletionsMessageParams({\n messages,\n }) as OpenAI.Chat.ChatCompletionMessageParam[],\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,sBAAsB,iBAEpC;CAEA,OAAO,EACL,UAAUA,oBAAAA,0CAA0C,EAClD,UAHa,gBAAgB,eAGtB,EACT,CAAC,EACH;AACF"}
|
package/dist/utils/prompts.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.cts","names":[],"sources":["../../src/utils/prompts.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"prompts.d.cts","names":[],"sources":["../../src/utils/prompts.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoCgB,sBAAsB,iBAAiB;EACrD,UAAU,OAAO,KAAK"}
|
package/dist/utils/prompts.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","names":[],"sources":["../../src/utils/prompts.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","names":[],"sources":["../../src/utils/prompts.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoCgB,sBAAsB,iBAAiB;EACrD,UAAU,OAAO,KAAK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","names":[],"sources":["../../src/utils/prompts.ts"],"sourcesContent":["import type { BasePromptValue } from \"@langchain/core/prompt_values\";\nimport type { OpenAI } from \"openai\";\nimport { convertMessagesToCompletionsMessageParams } from \"../converters/completions.js\";\n\n/**\n * Convert a formatted LangChain prompt (e.g. pulled from the hub) into\n * a format expected by OpenAI's JS SDK.\n *\n * Requires the \"@langchain/openai\" package to be installed in addition\n * to the OpenAI SDK.\n *\n * @example\n * ```ts\n * import { convertPromptToOpenAI } from \"langsmith/utils/hub/openai\";\n * import { pull } from \"langchain/hub\";\n *\n * import OpenAI from 'openai';\n *\n * const prompt = await pull(\"jacob/joke-generator\");\n * const formattedPrompt = await prompt.invoke({\n * topic: \"cats\",\n * });\n *\n * const { messages } = convertPromptToOpenAI(formattedPrompt);\n *\n * const openAIClient = new OpenAI();\n *\n * const openaiResponse = await openAIClient.chat.completions.create({\n * model: \"gpt-4o-mini\",\n * messages,\n * });\n * ```\n * @param formattedPrompt\n * @returns A partial OpenAI payload.\n */\n// TODO: make this a converter\nexport function convertPromptToOpenAI(formattedPrompt: BasePromptValue): {\n messages: OpenAI.Chat.ChatCompletionMessageParam[];\n} {\n const messages = formattedPrompt.toChatMessages();\n return {\n messages: convertMessagesToCompletionsMessageParams({\n messages,\n }) as OpenAI.Chat.ChatCompletionMessageParam[],\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,sBAAsB,iBAEpC;
|
|
1
|
+
{"version":3,"file":"prompts.js","names":[],"sources":["../../src/utils/prompts.ts"],"sourcesContent":["import type { BasePromptValue } from \"@langchain/core/prompt_values\";\nimport type { OpenAI } from \"openai\";\nimport { convertMessagesToCompletionsMessageParams } from \"../converters/completions.js\";\n\n/**\n * Convert a formatted LangChain prompt (e.g. pulled from the hub) into\n * a format expected by OpenAI's JS SDK.\n *\n * Requires the \"@langchain/openai\" package to be installed in addition\n * to the OpenAI SDK.\n *\n * @example\n * ```ts\n * import { convertPromptToOpenAI } from \"langsmith/utils/hub/openai\";\n * import { pull } from \"langchain/hub\";\n *\n * import OpenAI from 'openai';\n *\n * const prompt = await pull(\"jacob/joke-generator\");\n * const formattedPrompt = await prompt.invoke({\n * topic: \"cats\",\n * });\n *\n * const { messages } = convertPromptToOpenAI(formattedPrompt);\n *\n * const openAIClient = new OpenAI();\n *\n * const openaiResponse = await openAIClient.chat.completions.create({\n * model: \"gpt-4o-mini\",\n * messages,\n * });\n * ```\n * @param formattedPrompt\n * @returns A partial OpenAI payload.\n */\n// TODO: make this a converter\nexport function convertPromptToOpenAI(formattedPrompt: BasePromptValue): {\n messages: OpenAI.Chat.ChatCompletionMessageParam[];\n} {\n const messages = formattedPrompt.toChatMessages();\n return {\n messages: convertMessagesToCompletionsMessageParams({\n messages,\n }) as OpenAI.Chat.ChatCompletionMessageParam[],\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,sBAAsB,iBAEpC;CAEA,OAAO,EACL,UAAU,0CAA0C,EAClD,UAHa,gBAAgB,eAGtB,EACT,CAAC,EACH;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responses_stream_events.cjs","names":["convertResponsesUsageToUsageMetadata"],"sources":["../../src/utils/responses_stream_events.ts"],"sourcesContent":["/**\n * Converts OpenAI Responses API stream events into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { finalizeContentBlock } from \"@langchain/core/language_models/compat\";\nimport type {\n ChatModelStreamEvent,\n FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { convertResponsesUsageToUsageMetadata } from \"../converters/responses.js\";\n\nexport interface ConvertOpenAIResponsesStreamOptions {\n streamUsage?: boolean;\n provider?: string;\n}\n\ntype RawEvent = OpenAIClient.Responses.ResponseStreamEvent;\ntype BlockKey =\n | `text:${number}:${number}`\n | `reasoning:${number}:${number}`\n | `tool:${number}`;\n\nexport async function* convertOpenAIResponsesStream(\n source: AsyncIterable<RawEvent>,\n options: ConvertOpenAIResponsesStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n const shouldStreamUsage = options.streamUsage ?? true;\n const provider = options.provider ?? \"openai\";\n\n const blockAccumulators = new Map<\n number,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, any>\n >();\n const blockKeyToIndex = new Map<BlockKey, number>();\n let nextBlockIndex = 0;\n let messageStarted = false;\n let messageId: string | undefined;\n let usageSnapshot: UsageMetadata | undefined;\n let finishReason: FinishReason | undefined;\n let responseMetadata: Record<string, unknown> | undefined;\n const finalizedBlockIndices = new Set<number>();\n\n const getOrCreateBlockIndex = (\n key: BlockKey,\n initial: Record<string, unknown>\n ): { index: number; isNew: boolean } => {\n const existing = blockKeyToIndex.get(key);\n if (existing !== undefined) {\n return { index: existing, isNew: false };\n }\n const index = nextBlockIndex++;\n blockKeyToIndex.set(key, index);\n blockAccumulators.set(index, { ...initial });\n return { index, isNew: true };\n };\n\n const ensureMessageStart = function* () {\n if (!messageStarted) {\n messageStarted = true;\n yield {\n event: \"message-start\" as const,\n id: messageId,\n };\n }\n };\n\n const finalizeBlock = function* (index: number) {\n if (finalizedBlockIndices.has(index)) {\n return;\n }\n const acc = blockAccumulators.get(index);\n if (!acc) {\n return;\n }\n finalizedBlockIndices.add(index);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalizeContentBlock(acc as ContentBlock),\n };\n };\n\n for await (const event of source) {\n if (event.type === \"response.created\") {\n messageId = event.response.id;\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: \"response.created\",\n payload: { model: event.response.model, id: event.response.id },\n };\n continue;\n }\n\n if (event.type === \"response.output_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `text:${event.output_index}:${event.content_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"text\",\n text: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"text\", text: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.text = (acc.text ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"text-delta\" as const, text: event.delta },\n };\n continue;\n }\n\n if (event.type === \"response.reasoning_summary_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `reasoning:${event.output_index}:${event.summary_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"reasoning\",\n reasoning: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"reasoning\", reasoning: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.reasoning = (acc.reasoning ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"reasoning-delta\" as const, reasoning: event.delta },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.added\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const isCustom = event.item.type === \"custom_tool_call\";\n const initialArgs =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n ...(isCustom ? { isCustomTool: true } : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n } as ContentBlock,\n };\n }\n if (initialArgs) {\n const acc = blockAccumulators.get(index)!;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n continue;\n }\n\n if (\n event.type === \"response.function_call_arguments.delta\" ||\n event.type === \"response.custom_tool_call_input.delta\"\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n ...(event.type === \"response.custom_tool_call_input.delta\"\n ? { isCustomTool: true }\n : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.args = (acc.args ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.done\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const args =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n } as ContentBlock,\n };\n } else {\n const acc = blockAccumulators.get(index)!;\n acc.args = args;\n acc.id = event.item.call_id;\n acc.name = event.item.name;\n }\n yield* finalizeBlock(index);\n continue;\n }\n\n if (\n event.type === \"response.completed\" ||\n event.type === \"response.incomplete\"\n ) {\n yield* ensureMessageStart();\n messageId = event.response.id;\n finishReason = mapResponseStatusToFinishReason(\n event.response.status,\n event.type\n );\n responseMetadata = {\n model_provider: provider,\n id: event.response.id,\n model: event.response.model,\n status: event.response.status,\n };\n if (shouldStreamUsage && event.response.usage) {\n usageSnapshot = convertResponsesUsageToUsageMetadata(\n event.response.usage\n );\n yield { event: \"usage\" as const, usage: usageSnapshot };\n }\n continue;\n }\n\n if (event.type === \"response.image_generation_call.partial_image\") {\n continue;\n }\n\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: event.type,\n payload: event,\n };\n }\n\n if (!messageStarted) {\n yield { event: \"message-start\" as const };\n }\n\n for (const [index] of blockAccumulators) {\n if (!finalizedBlockIndices.has(index)) {\n yield* finalizeBlock(index);\n }\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: finishReason,\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n ...(responseMetadata ? { responseMetadata } : {}),\n };\n}\n\nfunction mapResponseStatusToFinishReason(\n status: string | undefined,\n eventType: \"response.completed\" | \"response.incomplete\"\n): FinishReason {\n if (eventType === \"response.incomplete\") {\n return \"length\";\n }\n if (status === \"completed\") {\n return \"stop\";\n }\n if (status === \"incomplete\") {\n return \"length\";\n }\n return \"stop\";\n}\n"],"mappings":";;;AA0BA,gBAAuB,6BACrB,QACA,UAA+C,EAAE,EACX;CACtC,MAAM,oBAAoB,QAAQ,eAAe;CACjD,MAAM,WAAW,QAAQ,YAAY;CAErC,MAAM,oCAAoB,IAAI,KAI3B;CACH,MAAM,kCAAkB,IAAI,KAAuB;CACnD,IAAI,iBAAiB;CACrB,IAAI,iBAAiB;CACrB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM,wCAAwB,IAAI,KAAa;CAE/C,MAAM,yBACJ,KACA,YACsC;EACtC,MAAM,WAAW,gBAAgB,IAAI,IAAI;AACzC,MAAI,aAAa,KAAA,EACf,QAAO;GAAE,OAAO;GAAU,OAAO;GAAO;EAE1C,MAAM,QAAQ;AACd,kBAAgB,IAAI,KAAK,MAAM;AAC/B,oBAAkB,IAAI,OAAO,EAAE,GAAG,SAAS,CAAC;AAC5C,SAAO;GAAE;GAAO,OAAO;GAAM;;CAG/B,MAAM,qBAAqB,aAAa;AACtC,MAAI,CAAC,gBAAgB;AACnB,oBAAiB;AACjB,SAAM;IACJ,OAAO;IACP,IAAI;IACL;;;CAIL,MAAM,gBAAgB,WAAW,OAAe;AAC9C,MAAI,sBAAsB,IAAI,MAAM,CAClC;EAEF,MAAM,MAAM,kBAAkB,IAAI,MAAM;AACxC,MAAI,CAAC,IACH;AAEF,wBAAsB,IAAI,MAAM;AAChC,QAAM;GACJ,OAAO;GACP;GACA,UAAA,GAAA,uCAAA,sBAA8B,IAAoB;GACnD;;AAGH,YAAW,MAAM,SAAS,QAAQ;AAChC,MAAI,MAAM,SAAS,oBAAoB;AACrC,eAAY,MAAM,SAAS;AAC3B,UAAO,oBAAoB;AAC3B,SAAM;IACJ,OAAO;IACP;IACA,MAAM;IACN,SAAS;KAAE,OAAO,MAAM,SAAS;KAAO,IAAI,MAAM,SAAS;KAAI;IAChE;AACD;;AAGF,MAAI,MAAM,SAAS,8BAA8B;AAC/C,UAAO,oBAAoB;GAE3B,MAAM,EAAE,OAAO,UAAU,sBAAsB,QADjB,MAAM,aAAa,GAAG,MAAM,iBACN;IAClD,MAAM;IACN,MAAM;IACP,CAAC;AACF,OAAI,MACF,OAAM;IACJ,OAAO;IACP;IACA,SAAS;KAAE,MAAM;KAAQ,MAAM;KAAI;IACpC;GAEH,MAAM,MAAM,kBAAkB,IAAI,MAAM;AACxC,OAAI,QAAQ,IAAI,QAAQ,MAAM,MAAM;AACpC,SAAM;IACJ,OAAO;IACP;IACA,OAAO;KAAE,MAAM;KAAuB,MAAM,MAAM;KAAO;IAC1D;AACD;;AAGF,MAAI,MAAM,SAAS,yCAAyC;AAC1D,UAAO,oBAAoB;GAE3B,MAAM,EAAE,OAAO,UAAU,sBAAsB,aADZ,MAAM,aAAa,GAAG,MAAM,iBACX;IAClD,MAAM;IACN,WAAW;IACZ,CAAC;AACF,OAAI,MACF,OAAM;IACJ,OAAO;IACP;IACA,SAAS;KAAE,MAAM;KAAa,WAAW;KAAI;IAC9C;GAEH,MAAM,MAAM,kBAAkB,IAAI,MAAM;AACxC,OAAI,aAAa,IAAI,aAAa,MAAM,MAAM;AAC9C,SAAM;IACJ,OAAO;IACP;IACA,OAAO;KAAE,MAAM;KAA4B,WAAW,MAAM;KAAO;IACpE;AACD;;AAGF,MACE,MAAM,SAAS,iCACd,MAAM,KAAK,SAAS,mBACnB,MAAM,KAAK,SAAS,qBACtB;AACA,UAAO,oBAAoB;GAC3B,MAAM,MAAgB,QAAQ,MAAM;GACpC,MAAM,WAAW,MAAM,KAAK,SAAS;GACrC,MAAM,cACJ,MAAM,KAAK,SAAS,kBACf,MAAM,KAAK,aAAa,KACxB,MAAM,KAAK,SAAS;GAC3B,MAAM,EAAE,OAAO,UAAU,sBAAsB,KAAK;IAClD,MAAM;IACN,IAAI,MAAM,KAAK;IACf,MAAM,MAAM,KAAK;IACjB,MAAM;IACN,OAAO,MAAM;IACb,GAAI,WAAW,EAAE,cAAc,MAAM,GAAG,EAAE;IAC3C,CAAC;AACF,OAAI,MACF,OAAM;IACJ,OAAO;IACP;IACA,SAAS;KACP,MAAM;KACN,IAAI,MAAM,KAAK;KACf,MAAM,MAAM,KAAK;KACjB,MAAM;KACN,OAAO,MAAM;KACd;IACF;AAEH,OAAI,aAAa;IACf,MAAM,MAAM,kBAAkB,IAAI,MAAM;AACxC,UAAM;KACJ,OAAO;KACP;KACA,OAAO;MACL,MAAM;MACN,QAAQ;OACN,MAAM;OACN,GAAI,IAAI,MAAM,OAAO,EAAE,IAAI,IAAI,IAAI,GAAG,EAAE;OACxC,GAAI,IAAI,QAAQ,OAAO,EAAE,MAAM,IAAI,MAAM,GAAG,EAAE;OAC9C,MAAM,IAAI;OACX;MACF;KACF;;AAEH;;AAGF,MACE,MAAM,SAAS,4CACf,MAAM,SAAS,yCACf;AACA,UAAO,oBAAoB;GAE3B,MAAM,EAAE,OAAO,UAAU,sBAAsB,QADjB,MAAM,gBACgB;IAClD,MAAM;IACN,MAAM;IACN,OAAO,MAAM;IACb,GAAI,MAAM,SAAS,0CACf,EAAE,cAAc,MAAM,GACtB,EAAE;IACP,CAAC;AACF,OAAI,MACF,OAAM;IACJ,OAAO;IACP;IACA,SAAS;KACP,MAAM;KACN,MAAM;KACN,OAAO,MAAM;KACd;IACF;GAEH,MAAM,MAAM,kBAAkB,IAAI,MAAM;AACxC,OAAI,QAAQ,IAAI,QAAQ,MAAM,MAAM;AACpC,SAAM;IACJ,OAAO;IACP;IACA,OAAO;KACL,MAAM;KACN,QAAQ;MACN,MAAM;MACN,GAAI,IAAI,MAAM,OAAO,EAAE,IAAI,IAAI,IAAI,GAAG,EAAE;MACxC,GAAI,IAAI,QAAQ,OAAO,EAAE,MAAM,IAAI,MAAM,GAAG,EAAE;MAC9C,MAAM,IAAI;MACX;KACF;IACF;AACD;;AAGF,MACE,MAAM,SAAS,gCACd,MAAM,KAAK,SAAS,mBACnB,MAAM,KAAK,SAAS,qBACtB;AACA,UAAO,oBAAoB;GAC3B,MAAM,MAAgB,QAAQ,MAAM;GACpC,MAAM,OACJ,MAAM,KAAK,SAAS,kBACf,MAAM,KAAK,aAAa,KACxB,MAAM,KAAK,SAAS;GAC3B,MAAM,EAAE,OAAO,UAAU,sBAAsB,KAAK;IAClD,MAAM;IACN,IAAI,MAAM,KAAK;IACf,MAAM,MAAM,KAAK;IACjB;IACA,OAAO,MAAM;IACd,CAAC;AACF,OAAI,MACF,OAAM;IACJ,OAAO;IACP;IACA,SAAS;KACP,MAAM;KACN,IAAI,MAAM,KAAK;KACf,MAAM,MAAM,KAAK;KACjB;KACA,OAAO,MAAM;KACd;IACF;QACI;IACL,MAAM,MAAM,kBAAkB,IAAI,MAAM;AACxC,QAAI,OAAO;AACX,QAAI,KAAK,MAAM,KAAK;AACpB,QAAI,OAAO,MAAM,KAAK;;AAExB,UAAO,cAAc,MAAM;AAC3B;;AAGF,MACE,MAAM,SAAS,wBACf,MAAM,SAAS,uBACf;AACA,UAAO,oBAAoB;AAC3B,eAAY,MAAM,SAAS;AAC3B,kBAAe,gCACb,MAAM,SAAS,QACf,MAAM,KACP;AACD,sBAAmB;IACjB,gBAAgB;IAChB,IAAI,MAAM,SAAS;IACnB,OAAO,MAAM,SAAS;IACtB,QAAQ,MAAM,SAAS;IACxB;AACD,OAAI,qBAAqB,MAAM,SAAS,OAAO;AAC7C,oBAAgBA,kBAAAA,qCACd,MAAM,SAAS,MAChB;AACD,UAAM;KAAE,OAAO;KAAkB,OAAO;KAAe;;AAEzD;;AAGF,MAAI,MAAM,SAAS,+CACjB;AAGF,SAAO,oBAAoB;AAC3B,QAAM;GACJ,OAAO;GACP;GACA,MAAM,MAAM;GACZ,SAAS;GACV;;AAGH,KAAI,CAAC,eACH,OAAM,EAAE,OAAO,iBAA0B;AAG3C,MAAK,MAAM,CAAC,UAAU,kBACpB,KAAI,CAAC,sBAAsB,IAAI,MAAM,CACnC,QAAO,cAAc,MAAM;AAI/B,OAAM;EACJ,OAAO;EACP,QAAQ;EACR,GAAI,gBAAgB,EAAE,OAAO,eAAe,GAAG,EAAE;EACjD,GAAI,mBAAmB,EAAE,kBAAkB,GAAG,EAAE;EACjD;;AAGH,SAAS,gCACP,QACA,WACc;AACd,KAAI,cAAc,sBAChB,QAAO;AAET,KAAI,WAAW,YACb,QAAO;AAET,KAAI,WAAW,aACb,QAAO;AAET,QAAO"}
|
|
1
|
+
{"version":3,"file":"responses_stream_events.cjs","names":["convertResponsesUsageToUsageMetadata"],"sources":["../../src/utils/responses_stream_events.ts"],"sourcesContent":["/**\n * Converts OpenAI Responses API stream events into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { finalizeContentBlock } from \"@langchain/core/language_models/compat\";\nimport type {\n ChatModelStreamEvent,\n FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { convertResponsesUsageToUsageMetadata } from \"../converters/responses.js\";\n\nexport interface ConvertOpenAIResponsesStreamOptions {\n streamUsage?: boolean;\n provider?: string;\n}\n\ntype RawEvent = OpenAIClient.Responses.ResponseStreamEvent;\ntype BlockKey =\n | `text:${number}:${number}`\n | `reasoning:${number}:${number}`\n | `tool:${number}`;\n\nexport async function* convertOpenAIResponsesStream(\n source: AsyncIterable<RawEvent>,\n options: ConvertOpenAIResponsesStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n const shouldStreamUsage = options.streamUsage ?? true;\n const provider = options.provider ?? \"openai\";\n\n const blockAccumulators = new Map<\n number,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, any>\n >();\n const blockKeyToIndex = new Map<BlockKey, number>();\n let nextBlockIndex = 0;\n let messageStarted = false;\n let messageId: string | undefined;\n let usageSnapshot: UsageMetadata | undefined;\n let finishReason: FinishReason | undefined;\n let responseMetadata: Record<string, unknown> | undefined;\n const finalizedBlockIndices = new Set<number>();\n\n const getOrCreateBlockIndex = (\n key: BlockKey,\n initial: Record<string, unknown>\n ): { index: number; isNew: boolean } => {\n const existing = blockKeyToIndex.get(key);\n if (existing !== undefined) {\n return { index: existing, isNew: false };\n }\n const index = nextBlockIndex++;\n blockKeyToIndex.set(key, index);\n blockAccumulators.set(index, { ...initial });\n return { index, isNew: true };\n };\n\n const ensureMessageStart = function* () {\n if (!messageStarted) {\n messageStarted = true;\n yield {\n event: \"message-start\" as const,\n id: messageId,\n };\n }\n };\n\n const finalizeBlock = function* (index: number) {\n if (finalizedBlockIndices.has(index)) {\n return;\n }\n const acc = blockAccumulators.get(index);\n if (!acc) {\n return;\n }\n finalizedBlockIndices.add(index);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalizeContentBlock(acc as ContentBlock),\n };\n };\n\n for await (const event of source) {\n if (event.type === \"response.created\") {\n messageId = event.response.id;\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: \"response.created\",\n payload: { model: event.response.model, id: event.response.id },\n };\n continue;\n }\n\n if (event.type === \"response.output_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `text:${event.output_index}:${event.content_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"text\",\n text: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"text\", text: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.text = (acc.text ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"text-delta\" as const, text: event.delta },\n };\n continue;\n }\n\n if (event.type === \"response.reasoning_summary_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `reasoning:${event.output_index}:${event.summary_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"reasoning\",\n reasoning: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"reasoning\", reasoning: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.reasoning = (acc.reasoning ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"reasoning-delta\" as const, reasoning: event.delta },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.added\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const isCustom = event.item.type === \"custom_tool_call\";\n const initialArgs =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n ...(isCustom ? { isCustomTool: true } : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n } as ContentBlock,\n };\n }\n if (initialArgs) {\n const acc = blockAccumulators.get(index)!;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n continue;\n }\n\n if (\n event.type === \"response.function_call_arguments.delta\" ||\n event.type === \"response.custom_tool_call_input.delta\"\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n ...(event.type === \"response.custom_tool_call_input.delta\"\n ? { isCustomTool: true }\n : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.args = (acc.args ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.done\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const args =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n } as ContentBlock,\n };\n } else {\n const acc = blockAccumulators.get(index)!;\n acc.args = args;\n acc.id = event.item.call_id;\n acc.name = event.item.name;\n }\n yield* finalizeBlock(index);\n continue;\n }\n\n if (\n event.type === \"response.completed\" ||\n event.type === \"response.incomplete\"\n ) {\n yield* ensureMessageStart();\n messageId = event.response.id;\n finishReason = mapResponseStatusToFinishReason(\n event.response.status,\n event.type\n );\n responseMetadata = {\n model_provider: provider,\n id: event.response.id,\n model: event.response.model,\n status: event.response.status,\n };\n if (shouldStreamUsage && event.response.usage) {\n usageSnapshot = convertResponsesUsageToUsageMetadata(\n event.response.usage\n );\n yield { event: \"usage\" as const, usage: usageSnapshot };\n }\n continue;\n }\n\n if (event.type === \"response.image_generation_call.partial_image\") {\n continue;\n }\n\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: event.type,\n payload: event,\n };\n }\n\n if (!messageStarted) {\n yield { event: \"message-start\" as const };\n }\n\n for (const [index] of blockAccumulators) {\n if (!finalizedBlockIndices.has(index)) {\n yield* finalizeBlock(index);\n }\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: finishReason,\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n ...(responseMetadata ? { responseMetadata } : {}),\n };\n}\n\nfunction mapResponseStatusToFinishReason(\n status: string | undefined,\n eventType: \"response.completed\" | \"response.incomplete\"\n): FinishReason {\n if (eventType === \"response.incomplete\") {\n return \"length\";\n }\n if (status === \"completed\") {\n return \"stop\";\n }\n if (status === \"incomplete\") {\n return \"length\";\n }\n return \"stop\";\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responses_stream_events.d.cts","names":[],"sources":["../../src/utils/responses_stream_events.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"responses_stream_events.d.cts","names":[],"sources":["../../src/utils/responses_stream_events.ts"],"mappings":";;;UAeiB;EACf;EACA;;KAGG,WAAW,OAAa,UAAU;iBAMhB,6BACrB,QAAQ,cAAc,WACtB,UAAS,sCACR,eAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responses_stream_events.d.ts","names":[],"sources":["../../src/utils/responses_stream_events.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"responses_stream_events.d.ts","names":[],"sources":["../../src/utils/responses_stream_events.ts"],"mappings":";;;UAeiB;EACf;EACA;;KAGG,WAAW,OAAa,UAAU;iBAMhB,6BACrB,QAAQ,cAAc,WACtB,UAAS,sCACR,eAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responses_stream_events.js","names":[],"sources":["../../src/utils/responses_stream_events.ts"],"sourcesContent":["/**\n * Converts OpenAI Responses API stream events into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { finalizeContentBlock } from \"@langchain/core/language_models/compat\";\nimport type {\n ChatModelStreamEvent,\n FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { convertResponsesUsageToUsageMetadata } from \"../converters/responses.js\";\n\nexport interface ConvertOpenAIResponsesStreamOptions {\n streamUsage?: boolean;\n provider?: string;\n}\n\ntype RawEvent = OpenAIClient.Responses.ResponseStreamEvent;\ntype BlockKey =\n | `text:${number}:${number}`\n | `reasoning:${number}:${number}`\n | `tool:${number}`;\n\nexport async function* convertOpenAIResponsesStream(\n source: AsyncIterable<RawEvent>,\n options: ConvertOpenAIResponsesStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n const shouldStreamUsage = options.streamUsage ?? true;\n const provider = options.provider ?? \"openai\";\n\n const blockAccumulators = new Map<\n number,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, any>\n >();\n const blockKeyToIndex = new Map<BlockKey, number>();\n let nextBlockIndex = 0;\n let messageStarted = false;\n let messageId: string | undefined;\n let usageSnapshot: UsageMetadata | undefined;\n let finishReason: FinishReason | undefined;\n let responseMetadata: Record<string, unknown> | undefined;\n const finalizedBlockIndices = new Set<number>();\n\n const getOrCreateBlockIndex = (\n key: BlockKey,\n initial: Record<string, unknown>\n ): { index: number; isNew: boolean } => {\n const existing = blockKeyToIndex.get(key);\n if (existing !== undefined) {\n return { index: existing, isNew: false };\n }\n const index = nextBlockIndex++;\n blockKeyToIndex.set(key, index);\n blockAccumulators.set(index, { ...initial });\n return { index, isNew: true };\n };\n\n const ensureMessageStart = function* () {\n if (!messageStarted) {\n messageStarted = true;\n yield {\n event: \"message-start\" as const,\n id: messageId,\n };\n }\n };\n\n const finalizeBlock = function* (index: number) {\n if (finalizedBlockIndices.has(index)) {\n return;\n }\n const acc = blockAccumulators.get(index);\n if (!acc) {\n return;\n }\n finalizedBlockIndices.add(index);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalizeContentBlock(acc as ContentBlock),\n };\n };\n\n for await (const event of source) {\n if (event.type === \"response.created\") {\n messageId = event.response.id;\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: \"response.created\",\n payload: { model: event.response.model, id: event.response.id },\n };\n continue;\n }\n\n if (event.type === \"response.output_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `text:${event.output_index}:${event.content_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"text\",\n text: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"text\", text: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.text = (acc.text ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"text-delta\" as const, text: event.delta },\n };\n continue;\n }\n\n if (event.type === \"response.reasoning_summary_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `reasoning:${event.output_index}:${event.summary_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"reasoning\",\n reasoning: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"reasoning\", reasoning: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.reasoning = (acc.reasoning ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"reasoning-delta\" as const, reasoning: event.delta },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.added\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const isCustom = event.item.type === \"custom_tool_call\";\n const initialArgs =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n ...(isCustom ? { isCustomTool: true } : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n } as ContentBlock,\n };\n }\n if (initialArgs) {\n const acc = blockAccumulators.get(index)!;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n continue;\n }\n\n if (\n event.type === \"response.function_call_arguments.delta\" ||\n event.type === \"response.custom_tool_call_input.delta\"\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n ...(event.type === \"response.custom_tool_call_input.delta\"\n ? { isCustomTool: true }\n : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.args = (acc.args ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.done\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const args =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n } as ContentBlock,\n };\n } else {\n const acc = blockAccumulators.get(index)!;\n acc.args = args;\n acc.id = event.item.call_id;\n acc.name = event.item.name;\n }\n yield* finalizeBlock(index);\n continue;\n }\n\n if (\n event.type === \"response.completed\" ||\n event.type === \"response.incomplete\"\n ) {\n yield* ensureMessageStart();\n messageId = event.response.id;\n finishReason = mapResponseStatusToFinishReason(\n event.response.status,\n event.type\n );\n responseMetadata = {\n model_provider: provider,\n id: event.response.id,\n model: event.response.model,\n status: event.response.status,\n };\n if (shouldStreamUsage && event.response.usage) {\n usageSnapshot = convertResponsesUsageToUsageMetadata(\n event.response.usage\n );\n yield { event: \"usage\" as const, usage: usageSnapshot };\n }\n continue;\n }\n\n if (event.type === \"response.image_generation_call.partial_image\") {\n continue;\n }\n\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: event.type,\n payload: event,\n };\n }\n\n if (!messageStarted) {\n yield { event: \"message-start\" as const };\n }\n\n for (const [index] of blockAccumulators) {\n if (!finalizedBlockIndices.has(index)) {\n yield* finalizeBlock(index);\n }\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: finishReason,\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n ...(responseMetadata ? { responseMetadata } : {}),\n };\n}\n\nfunction mapResponseStatusToFinishReason(\n status: string | undefined,\n eventType: \"response.completed\" | \"response.incomplete\"\n): FinishReason {\n if (eventType === \"response.incomplete\") {\n return \"length\";\n }\n if (status === \"completed\") {\n return \"stop\";\n }\n if (status === \"incomplete\") {\n return \"length\";\n }\n return \"stop\";\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"responses_stream_events.js","names":[],"sources":["../../src/utils/responses_stream_events.ts"],"sourcesContent":["/**\n * Converts OpenAI Responses API stream events into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { finalizeContentBlock } from \"@langchain/core/language_models/compat\";\nimport type {\n ChatModelStreamEvent,\n FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { convertResponsesUsageToUsageMetadata } from \"../converters/responses.js\";\n\nexport interface ConvertOpenAIResponsesStreamOptions {\n streamUsage?: boolean;\n provider?: string;\n}\n\ntype RawEvent = OpenAIClient.Responses.ResponseStreamEvent;\ntype BlockKey =\n | `text:${number}:${number}`\n | `reasoning:${number}:${number}`\n | `tool:${number}`;\n\nexport async function* convertOpenAIResponsesStream(\n source: AsyncIterable<RawEvent>,\n options: ConvertOpenAIResponsesStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n const shouldStreamUsage = options.streamUsage ?? true;\n const provider = options.provider ?? \"openai\";\n\n const blockAccumulators = new Map<\n number,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, any>\n >();\n const blockKeyToIndex = new Map<BlockKey, number>();\n let nextBlockIndex = 0;\n let messageStarted = false;\n let messageId: string | undefined;\n let usageSnapshot: UsageMetadata | undefined;\n let finishReason: FinishReason | undefined;\n let responseMetadata: Record<string, unknown> | undefined;\n const finalizedBlockIndices = new Set<number>();\n\n const getOrCreateBlockIndex = (\n key: BlockKey,\n initial: Record<string, unknown>\n ): { index: number; isNew: boolean } => {\n const existing = blockKeyToIndex.get(key);\n if (existing !== undefined) {\n return { index: existing, isNew: false };\n }\n const index = nextBlockIndex++;\n blockKeyToIndex.set(key, index);\n blockAccumulators.set(index, { ...initial });\n return { index, isNew: true };\n };\n\n const ensureMessageStart = function* () {\n if (!messageStarted) {\n messageStarted = true;\n yield {\n event: \"message-start\" as const,\n id: messageId,\n };\n }\n };\n\n const finalizeBlock = function* (index: number) {\n if (finalizedBlockIndices.has(index)) {\n return;\n }\n const acc = blockAccumulators.get(index);\n if (!acc) {\n return;\n }\n finalizedBlockIndices.add(index);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalizeContentBlock(acc as ContentBlock),\n };\n };\n\n for await (const event of source) {\n if (event.type === \"response.created\") {\n messageId = event.response.id;\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: \"response.created\",\n payload: { model: event.response.model, id: event.response.id },\n };\n continue;\n }\n\n if (event.type === \"response.output_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `text:${event.output_index}:${event.content_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"text\",\n text: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"text\", text: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.text = (acc.text ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"text-delta\" as const, text: event.delta },\n };\n continue;\n }\n\n if (event.type === \"response.reasoning_summary_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `reasoning:${event.output_index}:${event.summary_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"reasoning\",\n reasoning: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"reasoning\", reasoning: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.reasoning = (acc.reasoning ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"reasoning-delta\" as const, reasoning: event.delta },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.added\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const isCustom = event.item.type === \"custom_tool_call\";\n const initialArgs =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n ...(isCustom ? { isCustomTool: true } : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n } as ContentBlock,\n };\n }\n if (initialArgs) {\n const acc = blockAccumulators.get(index)!;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n continue;\n }\n\n if (\n event.type === \"response.function_call_arguments.delta\" ||\n event.type === \"response.custom_tool_call_input.delta\"\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n ...(event.type === \"response.custom_tool_call_input.delta\"\n ? { isCustomTool: true }\n : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.args = (acc.args ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.done\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const args =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n } as ContentBlock,\n };\n } else {\n const acc = blockAccumulators.get(index)!;\n acc.args = args;\n acc.id = event.item.call_id;\n acc.name = event.item.name;\n }\n yield* finalizeBlock(index);\n continue;\n }\n\n if (\n event.type === \"response.completed\" ||\n event.type === \"response.incomplete\"\n ) {\n yield* ensureMessageStart();\n messageId = event.response.id;\n finishReason = mapResponseStatusToFinishReason(\n event.response.status,\n event.type\n );\n responseMetadata = {\n model_provider: provider,\n id: event.response.id,\n model: event.response.model,\n status: event.response.status,\n };\n if (shouldStreamUsage && event.response.usage) {\n usageSnapshot = convertResponsesUsageToUsageMetadata(\n event.response.usage\n );\n yield { event: \"usage\" as const, usage: usageSnapshot };\n }\n continue;\n }\n\n if (event.type === \"response.image_generation_call.partial_image\") {\n continue;\n }\n\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: event.type,\n payload: event,\n };\n }\n\n if (!messageStarted) {\n yield { event: \"message-start\" as const };\n }\n\n for (const [index] of blockAccumulators) {\n if (!finalizedBlockIndices.has(index)) {\n yield* finalizeBlock(index);\n }\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: finishReason,\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n ...(responseMetadata ? { responseMetadata } : {}),\n };\n}\n\nfunction mapResponseStatusToFinishReason(\n status: string | undefined,\n eventType: \"response.completed\" | \"response.incomplete\"\n): FinishReason {\n if (eventType === \"response.incomplete\") {\n return \"length\";\n }\n if (status === \"completed\") {\n return \"stop\";\n }\n if (status === \"incomplete\") {\n return \"length\";\n }\n return \"stop\";\n}\n"],"mappings":"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"}
|
package/dist/utils/tools.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.cjs","names":[],"sources":["../../src/utils/tools.ts"],"sourcesContent":["import { OpenAI as OpenAIClient } from \"openai\";\n\nimport { ToolDefinition } from \"@langchain/core/language_models/base\";\nimport { BindToolsInput } from \"@langchain/core/language_models/chat_models\";\nimport {\n convertToOpenAITool as formatToOpenAITool,\n isLangChainTool,\n} from \"@langchain/core/utils/function_calling\";\nimport { DynamicTool, StructuredToolInterface } from \"@langchain/core/tools\";\nimport { isInteropZodSchema } from \"@langchain/core/utils/types\";\nimport { toJsonSchema } from \"@langchain/core/utils/json_schema\";\nimport { ToolCall } from \"@langchain/core/messages/tool\";\n\n/**\n * Formats a tool in either OpenAI format, or LangChain structured tool format\n * into an OpenAI tool format. If the tool is already in OpenAI format, return without\n * any changes. If it is in LangChain structured tool format, convert it to OpenAI tool format\n * using OpenAI's `zodFunction` util, falling back to `convertToOpenAIFunction` if the parameters\n * returned from the `zodFunction` util are not defined.\n *\n * @param {BindToolsInput} tool The tool to convert to an OpenAI tool.\n * @param {Object} [fields] Additional fields to add to the OpenAI tool.\n * @returns {ToolDefinition} The inputted tool in OpenAI tool format.\n */\nexport function _convertToOpenAITool(\n tool: BindToolsInput,\n fields?: {\n /**\n * If `true`, model output is guaranteed to exactly match the JSON Schema\n * provided in the function definition.\n */\n strict?: boolean;\n }\n): OpenAIClient.Chat.Completions.ChatCompletionFunctionTool {\n let toolDef: OpenAIClient.Chat.Completions.ChatCompletionFunctionTool;\n\n if (isLangChainTool(tool)) {\n toolDef = formatToOpenAITool(\n tool\n ) as OpenAIClient.Chat.Completions.ChatCompletionFunctionTool;\n } else {\n toolDef = tool as OpenAIClient.Chat.Completions.ChatCompletionFunctionTool;\n }\n\n if (fields?.strict !== undefined) {\n toolDef.function.strict = fields.strict;\n }\n\n return toolDef;\n}\n\ntype OpenAIFunction = OpenAIClient.Chat.ChatCompletionCreateParams.Function;\n\n// Types representing the OpenAI function definitions. While the OpenAI client library\n// does have types for function definitions, the properties are just Record<string, unknown>,\n// which isn't very useful for type checking this formatting code.\nexport interface FunctionDef extends Omit<OpenAIFunction, \"parameters\"> {\n name: string;\n description?: string;\n parameters: ObjectProp;\n}\n\ninterface ObjectProp {\n type: \"object\";\n properties?: {\n [key: string]: Prop;\n };\n required?: string[];\n}\n\ninterface AnyOfProp {\n anyOf: Prop[];\n}\n\ntype Prop = {\n description?: string;\n} & (\n | AnyOfProp\n | ObjectProp\n | {\n type: \"string\";\n enum?: string[];\n }\n | {\n type: \"number\" | \"integer\";\n minimum?: number;\n maximum?: number;\n enum?: number[];\n }\n | { type: \"boolean\" }\n | { type: \"null\" }\n | {\n type: \"array\";\n items?: Prop;\n }\n);\n\nfunction isAnyOfProp(prop: Prop): prop is AnyOfProp {\n return (\n (prop as AnyOfProp).anyOf !== undefined &&\n Array.isArray((prop as AnyOfProp).anyOf)\n );\n}\n\n// When OpenAI use functions in the prompt, they format them as TypeScript definitions rather than OpenAPI JSON schemas.\n// This function converts the JSON schemas into TypeScript definitions.\nexport function formatFunctionDefinitions(functions: FunctionDef[]) {\n const lines = [\"namespace functions {\", \"\"];\n for (const f of functions) {\n if (f.description) {\n lines.push(`// ${f.description}`);\n }\n if (Object.keys(f.parameters.properties ?? {}).length > 0) {\n lines.push(`type ${f.name} = (_: {`);\n lines.push(formatObjectProperties(f.parameters, 0));\n lines.push(\"}) => any;\");\n } else {\n lines.push(`type ${f.name} = () => any;`);\n }\n lines.push(\"\");\n }\n lines.push(\"} // namespace functions\");\n return lines.join(\"\\n\");\n}\n\n// Format just the properties of an object (not including the surrounding braces)\nfunction formatObjectProperties(obj: ObjectProp, indent: number): string {\n const lines: string[] = [];\n for (const [name, param] of Object.entries(obj.properties ?? {})) {\n if (param.description && indent < 2) {\n lines.push(`// ${param.description}`);\n }\n if (obj.required?.includes(name)) {\n lines.push(`${name}: ${formatType(param, indent)},`);\n } else {\n lines.push(`${name}?: ${formatType(param, indent)},`);\n }\n }\n return lines.map((line) => \" \".repeat(indent) + line).join(\"\\n\");\n}\n\n// Format a single property type\nfunction formatType(param: Prop, indent: number): string {\n if (isAnyOfProp(param)) {\n return param.anyOf.map((v) => formatType(v, indent)).join(\" | \");\n }\n switch (param.type) {\n case \"string\":\n if (param.enum) {\n return param.enum.map((v) => `\"${v}\"`).join(\" | \");\n }\n return \"string\";\n case \"number\":\n if (param.enum) {\n return param.enum.map((v) => `${v}`).join(\" | \");\n }\n return \"number\";\n case \"integer\":\n if (param.enum) {\n return param.enum.map((v) => `${v}`).join(\" | \");\n }\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"null\":\n return \"null\";\n case \"object\":\n return [\"{\", formatObjectProperties(param, indent + 2), \"}\"].join(\"\\n\");\n case \"array\":\n if (param.items) {\n return `${formatType(param.items, indent)}[]`;\n }\n return \"any[]\";\n default:\n return \"\";\n }\n}\n\nexport function formatToOpenAIAssistantTool(\n tool: StructuredToolInterface\n): ToolDefinition {\n return {\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: isInteropZodSchema(tool.schema)\n ? toJsonSchema(tool.schema)\n : tool.schema,\n },\n };\n}\n\nexport type OpenAIToolChoice =\n | OpenAIClient.ChatCompletionToolChoiceOption\n | \"any\"\n | string;\n\nexport type ResponsesToolChoice = NonNullable<\n OpenAIClient.Responses.ResponseCreateParams[\"tool_choice\"]\n>;\n\nexport type ChatOpenAIToolType =\n | BindToolsInput\n | OpenAIClient.Chat.ChatCompletionTool\n | ResponsesTool;\n\nexport type ResponsesTool = NonNullable<\n OpenAIClient.Responses.ResponseCreateParams[\"tools\"]\n>[number];\n\nexport function formatToOpenAIToolChoice(\n toolChoice?: OpenAIToolChoice\n): OpenAIClient.ChatCompletionToolChoiceOption | undefined {\n if (!toolChoice) {\n return undefined;\n } else if (toolChoice === \"any\" || toolChoice === \"required\") {\n return \"required\";\n } else if (toolChoice === \"auto\") {\n return \"auto\";\n } else if (toolChoice === \"none\") {\n return \"none\";\n } else if (typeof toolChoice === \"string\") {\n return {\n type: \"function\",\n function: {\n name: toolChoice,\n },\n };\n } else {\n return toolChoice;\n }\n}\n\nexport function isBuiltInTool(tool: ChatOpenAIToolType): tool is ResponsesTool {\n return \"type\" in tool && tool.type !== \"function\";\n}\n\n/**\n * Type for LangChain tools that have a provider-specific tool definition\n * stored in extras.providerToolDefinition.\n */\ntype LangchainToolWithProviderDefinition = StructuredToolInterface & {\n extras: {\n providerToolDefinition: ResponsesTool;\n };\n};\n\n/**\n * Checks if a tool has a provider-specific tool definition in extras.providerToolDefinition.\n * This is used for tools like localShell, shell, computerUse, and applyPatch\n * that need to be sent as built-in tool types to the OpenAI API.\n */\nexport function hasProviderToolDefinition(\n tool: unknown\n): tool is LangchainToolWithProviderDefinition {\n return (\n typeof tool === \"object\" &&\n tool !== null &&\n \"extras\" in tool &&\n typeof (tool as LangchainToolWithProviderDefinition).extras === \"object\" &&\n (tool as LangchainToolWithProviderDefinition).extras !== null &&\n \"providerToolDefinition\" in\n (tool as LangchainToolWithProviderDefinition).extras &&\n typeof (tool as LangchainToolWithProviderDefinition).extras\n .providerToolDefinition === \"object\" &&\n (tool as LangchainToolWithProviderDefinition).extras\n .providerToolDefinition !== null\n );\n}\n\nexport function isBuiltInToolChoice(\n tool_choice: OpenAIToolChoice | ResponsesToolChoice | undefined\n): tool_choice is ResponsesToolChoice {\n return (\n tool_choice != null &&\n typeof tool_choice === \"object\" &&\n \"type\" in tool_choice &&\n tool_choice.type !== \"function\"\n );\n}\n\nexport type CustomToolCall = ToolCall & {\n call_id: string;\n isCustomTool: true;\n};\n\ntype LangchainCustomTool = DynamicTool<string> & {\n metadata: {\n customTool: OpenAIClient.Responses.CustomTool;\n };\n};\n\nexport function isCustomTool(tool: unknown): tool is LangchainCustomTool {\n return (\n typeof tool === \"object\" &&\n tool !== null &&\n \"metadata\" in tool &&\n typeof tool.metadata === \"object\" &&\n tool.metadata !== null &&\n \"customTool\" in tool.metadata &&\n typeof tool.metadata.customTool === \"object\" &&\n tool.metadata.customTool !== null\n );\n}\n\nexport function isOpenAICustomTool(\n tool: ChatOpenAIToolType\n): tool is OpenAIClient.Chat.ChatCompletionCustomTool {\n return (\n \"type\" in tool &&\n tool.type === \"custom\" &&\n \"custom\" in tool &&\n typeof tool.custom === \"object\" &&\n tool.custom !== null\n );\n}\n\nexport function parseCustomToolCall(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n rawToolCall: Record<string, any>\n): CustomToolCall | undefined {\n if (rawToolCall.type !== \"custom_tool_call\") {\n return undefined;\n }\n return {\n ...rawToolCall,\n type: \"tool_call\",\n call_id: rawToolCall.id,\n id: rawToolCall.call_id,\n name: rawToolCall.name,\n isCustomTool: true,\n args: {\n input: rawToolCall.input,\n },\n };\n}\n\nexport type ComputerToolCall = ToolCall & {\n call_id: string;\n /**\n * marker to indicate that the tool call is a computer tool call\n */\n isComputerTool: true;\n};\n\n/**\n * Parses a computer_call output item from the OpenAI Responses API\n * into a ToolCall format that can be processed by the ToolNode.\n *\n * @param rawToolCall - The raw computer_call output item from the API\n * @returns A ComputerToolCall object if valid, undefined otherwise\n */\nexport function parseComputerCall(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n rawToolCall: Record<string, any>\n): ComputerToolCall | undefined {\n if (rawToolCall.type !== \"computer_call\") {\n return undefined;\n }\n return {\n ...rawToolCall,\n type: \"tool_call\",\n call_id: rawToolCall.id,\n id: rawToolCall.call_id,\n name: \"computer_use\",\n isComputerTool: true,\n args: {\n action: rawToolCall.action,\n },\n };\n}\n\n/**\n * Checks if a tool call is a computer tool call.\n * @param toolCall - The tool call to check.\n * @returns True if the tool call is a computer tool call, false otherwise.\n */\nexport function isComputerToolCall(\n toolCall: unknown\n): toolCall is ComputerToolCall {\n return (\n typeof toolCall === \"object\" &&\n toolCall !== null &&\n \"type\" in toolCall &&\n toolCall.type === \"tool_call\" &&\n \"isComputerTool\" in toolCall &&\n toolCall.isComputerTool === true\n );\n}\n\nexport function isCustomToolCall(\n toolCall: unknown,\n customToolCallIds?: Record<string, string>\n): toolCall is CustomToolCall {\n if (\n typeof toolCall !== \"object\" ||\n toolCall === null ||\n !(\"type\" in toolCall) ||\n toolCall.type !== \"tool_call\"\n ) {\n return false;\n }\n if (\"isCustomTool\" in toolCall && toolCall.isCustomTool === true) {\n return true;\n }\n if (\n customToolCallIds &&\n \"id\" in toolCall &&\n typeof toolCall.id === \"string\" &&\n toolCall.id in customToolCallIds\n ) {\n return true;\n }\n return false;\n}\n\nexport function convertCompletionsCustomTool(\n tool: OpenAIClient.Chat.ChatCompletionCustomTool\n): OpenAIClient.Responses.CustomTool {\n const getFormat = () => {\n if (!tool.custom.format) {\n return undefined;\n }\n if (tool.custom.format.type === \"grammar\") {\n return {\n type: \"grammar\" as const,\n definition: tool.custom.format.grammar.definition,\n syntax: tool.custom.format.grammar.syntax,\n };\n }\n if (tool.custom.format.type === \"text\") {\n return {\n type: \"text\" as const,\n };\n }\n return undefined;\n };\n return {\n type: \"custom\",\n name: tool.custom.name,\n description: tool.custom.description,\n format: getFormat(),\n };\n}\n\nexport function convertResponsesCustomTool(\n tool: OpenAIClient.Responses.CustomTool\n): OpenAIClient.Chat.ChatCompletionCustomTool {\n const getFormat = () => {\n if (!tool.format) {\n return undefined;\n }\n if (tool.format.type === \"grammar\") {\n return {\n type: \"grammar\" as const,\n grammar: {\n definition: tool.format.definition,\n syntax: tool.format.syntax,\n },\n };\n }\n if (tool.format.type === \"text\") {\n return {\n type: \"text\" as const,\n };\n }\n return undefined;\n };\n return {\n type: \"custom\",\n custom: {\n name: tool.name,\n description: tool.description,\n format: getFormat(),\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tools.cjs","names":[],"sources":["../../src/utils/tools.ts"],"sourcesContent":["import { OpenAI as OpenAIClient } from \"openai\";\n\nimport { ToolDefinition } from \"@langchain/core/language_models/base\";\nimport { BindToolsInput } from \"@langchain/core/language_models/chat_models\";\nimport {\n convertToOpenAITool as formatToOpenAITool,\n isLangChainTool,\n} from \"@langchain/core/utils/function_calling\";\nimport { DynamicTool, StructuredToolInterface } from \"@langchain/core/tools\";\nimport { isInteropZodSchema } from \"@langchain/core/utils/types\";\nimport { toJsonSchema } from \"@langchain/core/utils/json_schema\";\nimport { ToolCall } from \"@langchain/core/messages/tool\";\n\n/**\n * Formats a tool in either OpenAI format, or LangChain structured tool format\n * into an OpenAI tool format. If the tool is already in OpenAI format, return without\n * any changes. If it is in LangChain structured tool format, convert it to OpenAI tool format\n * using OpenAI's `zodFunction` util, falling back to `convertToOpenAIFunction` if the parameters\n * returned from the `zodFunction` util are not defined.\n *\n * @param {BindToolsInput} tool The tool to convert to an OpenAI tool.\n * @param {Object} [fields] Additional fields to add to the OpenAI tool.\n * @returns {ToolDefinition} The inputted tool in OpenAI tool format.\n */\nexport function _convertToOpenAITool(\n tool: BindToolsInput,\n fields?: {\n /**\n * If `true`, model output is guaranteed to exactly match the JSON Schema\n * provided in the function definition.\n */\n strict?: boolean;\n }\n): OpenAIClient.Chat.Completions.ChatCompletionFunctionTool {\n let toolDef: OpenAIClient.Chat.Completions.ChatCompletionFunctionTool;\n\n if (isLangChainTool(tool)) {\n toolDef = formatToOpenAITool(\n tool\n ) as OpenAIClient.Chat.Completions.ChatCompletionFunctionTool;\n } else {\n toolDef = tool as OpenAIClient.Chat.Completions.ChatCompletionFunctionTool;\n }\n\n if (fields?.strict !== undefined) {\n toolDef.function.strict = fields.strict;\n }\n\n return toolDef;\n}\n\ntype OpenAIFunction = OpenAIClient.Chat.ChatCompletionCreateParams.Function;\n\n// Types representing the OpenAI function definitions. While the OpenAI client library\n// does have types for function definitions, the properties are just Record<string, unknown>,\n// which isn't very useful for type checking this formatting code.\nexport interface FunctionDef extends Omit<OpenAIFunction, \"parameters\"> {\n name: string;\n description?: string;\n parameters: ObjectProp;\n}\n\ninterface ObjectProp {\n type: \"object\";\n properties?: {\n [key: string]: Prop;\n };\n required?: string[];\n}\n\ninterface AnyOfProp {\n anyOf: Prop[];\n}\n\ntype Prop = {\n description?: string;\n} & (\n | AnyOfProp\n | ObjectProp\n | {\n type: \"string\";\n enum?: string[];\n }\n | {\n type: \"number\" | \"integer\";\n minimum?: number;\n maximum?: number;\n enum?: number[];\n }\n | { type: \"boolean\" }\n | { type: \"null\" }\n | {\n type: \"array\";\n items?: Prop;\n }\n);\n\nfunction isAnyOfProp(prop: Prop): prop is AnyOfProp {\n return (\n (prop as AnyOfProp).anyOf !== undefined &&\n Array.isArray((prop as AnyOfProp).anyOf)\n );\n}\n\n// When OpenAI use functions in the prompt, they format them as TypeScript definitions rather than OpenAPI JSON schemas.\n// This function converts the JSON schemas into TypeScript definitions.\nexport function formatFunctionDefinitions(functions: FunctionDef[]) {\n const lines = [\"namespace functions {\", \"\"];\n for (const f of functions) {\n if (f.description) {\n lines.push(`// ${f.description}`);\n }\n if (Object.keys(f.parameters.properties ?? {}).length > 0) {\n lines.push(`type ${f.name} = (_: {`);\n lines.push(formatObjectProperties(f.parameters, 0));\n lines.push(\"}) => any;\");\n } else {\n lines.push(`type ${f.name} = () => any;`);\n }\n lines.push(\"\");\n }\n lines.push(\"} // namespace functions\");\n return lines.join(\"\\n\");\n}\n\n// Format just the properties of an object (not including the surrounding braces)\nfunction formatObjectProperties(obj: ObjectProp, indent: number): string {\n const lines: string[] = [];\n for (const [name, param] of Object.entries(obj.properties ?? {})) {\n if (param.description && indent < 2) {\n lines.push(`// ${param.description}`);\n }\n if (obj.required?.includes(name)) {\n lines.push(`${name}: ${formatType(param, indent)},`);\n } else {\n lines.push(`${name}?: ${formatType(param, indent)},`);\n }\n }\n return lines.map((line) => \" \".repeat(indent) + line).join(\"\\n\");\n}\n\n// Format a single property type\nfunction formatType(param: Prop, indent: number): string {\n if (isAnyOfProp(param)) {\n return param.anyOf.map((v) => formatType(v, indent)).join(\" | \");\n }\n switch (param.type) {\n case \"string\":\n if (param.enum) {\n return param.enum.map((v) => `\"${v}\"`).join(\" | \");\n }\n return \"string\";\n case \"number\":\n if (param.enum) {\n return param.enum.map((v) => `${v}`).join(\" | \");\n }\n return \"number\";\n case \"integer\":\n if (param.enum) {\n return param.enum.map((v) => `${v}`).join(\" | \");\n }\n return \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"null\":\n return \"null\";\n case \"object\":\n return [\"{\", formatObjectProperties(param, indent + 2), \"}\"].join(\"\\n\");\n case \"array\":\n if (param.items) {\n return `${formatType(param.items, indent)}[]`;\n }\n return \"any[]\";\n default:\n return \"\";\n }\n}\n\nexport function formatToOpenAIAssistantTool(\n tool: StructuredToolInterface\n): ToolDefinition {\n return {\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: isInteropZodSchema(tool.schema)\n ? toJsonSchema(tool.schema)\n : tool.schema,\n },\n };\n}\n\nexport type OpenAIToolChoice =\n | OpenAIClient.ChatCompletionToolChoiceOption\n | \"any\"\n | string;\n\nexport type ResponsesToolChoice = NonNullable<\n OpenAIClient.Responses.ResponseCreateParams[\"tool_choice\"]\n>;\n\nexport type ChatOpenAIToolType =\n | BindToolsInput\n | OpenAIClient.Chat.ChatCompletionTool\n | ResponsesTool;\n\nexport type ResponsesTool = NonNullable<\n OpenAIClient.Responses.ResponseCreateParams[\"tools\"]\n>[number];\n\nexport function formatToOpenAIToolChoice(\n toolChoice?: OpenAIToolChoice\n): OpenAIClient.ChatCompletionToolChoiceOption | undefined {\n if (!toolChoice) {\n return undefined;\n } else if (toolChoice === \"any\" || toolChoice === \"required\") {\n return \"required\";\n } else if (toolChoice === \"auto\") {\n return \"auto\";\n } else if (toolChoice === \"none\") {\n return \"none\";\n } else if (typeof toolChoice === \"string\") {\n return {\n type: \"function\",\n function: {\n name: toolChoice,\n },\n };\n } else {\n return toolChoice;\n }\n}\n\nexport function isBuiltInTool(tool: ChatOpenAIToolType): tool is ResponsesTool {\n return \"type\" in tool && tool.type !== \"function\";\n}\n\n/**\n * Type for LangChain tools that have a provider-specific tool definition\n * stored in extras.providerToolDefinition.\n */\ntype LangchainToolWithProviderDefinition = StructuredToolInterface & {\n extras: {\n providerToolDefinition: ResponsesTool;\n };\n};\n\n/**\n * Checks if a tool has a provider-specific tool definition in extras.providerToolDefinition.\n * This is used for tools like localShell, shell, computerUse, and applyPatch\n * that need to be sent as built-in tool types to the OpenAI API.\n */\nexport function hasProviderToolDefinition(\n tool: unknown\n): tool is LangchainToolWithProviderDefinition {\n return (\n typeof tool === \"object\" &&\n tool !== null &&\n \"extras\" in tool &&\n typeof (tool as LangchainToolWithProviderDefinition).extras === \"object\" &&\n (tool as LangchainToolWithProviderDefinition).extras !== null &&\n \"providerToolDefinition\" in\n (tool as LangchainToolWithProviderDefinition).extras &&\n typeof (tool as LangchainToolWithProviderDefinition).extras\n .providerToolDefinition === \"object\" &&\n (tool as LangchainToolWithProviderDefinition).extras\n .providerToolDefinition !== null\n );\n}\n\nexport function isBuiltInToolChoice(\n tool_choice: OpenAIToolChoice | ResponsesToolChoice | undefined\n): tool_choice is ResponsesToolChoice {\n return (\n tool_choice != null &&\n typeof tool_choice === \"object\" &&\n \"type\" in tool_choice &&\n tool_choice.type !== \"function\"\n );\n}\n\nexport type CustomToolCall = ToolCall & {\n call_id: string;\n isCustomTool: true;\n};\n\ntype LangchainCustomTool = DynamicTool<string> & {\n metadata: {\n customTool: OpenAIClient.Responses.CustomTool;\n };\n};\n\nexport function isCustomTool(tool: unknown): tool is LangchainCustomTool {\n return (\n typeof tool === \"object\" &&\n tool !== null &&\n \"metadata\" in tool &&\n typeof tool.metadata === \"object\" &&\n tool.metadata !== null &&\n \"customTool\" in tool.metadata &&\n typeof tool.metadata.customTool === \"object\" &&\n tool.metadata.customTool !== null\n );\n}\n\nexport function isOpenAICustomTool(\n tool: ChatOpenAIToolType\n): tool is OpenAIClient.Chat.ChatCompletionCustomTool {\n return (\n \"type\" in tool &&\n tool.type === \"custom\" &&\n \"custom\" in tool &&\n typeof tool.custom === \"object\" &&\n tool.custom !== null\n );\n}\n\nexport function parseCustomToolCall(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n rawToolCall: Record<string, any>\n): CustomToolCall | undefined {\n if (rawToolCall.type !== \"custom_tool_call\") {\n return undefined;\n }\n return {\n ...rawToolCall,\n type: \"tool_call\",\n call_id: rawToolCall.id,\n id: rawToolCall.call_id,\n name: rawToolCall.name,\n isCustomTool: true,\n args: {\n input: rawToolCall.input,\n },\n };\n}\n\nexport type ComputerToolCall = ToolCall & {\n call_id: string;\n /**\n * marker to indicate that the tool call is a computer tool call\n */\n isComputerTool: true;\n};\n\n/**\n * Parses a computer_call output item from the OpenAI Responses API\n * into a ToolCall format that can be processed by the ToolNode.\n *\n * @param rawToolCall - The raw computer_call output item from the API\n * @returns A ComputerToolCall object if valid, undefined otherwise\n */\nexport function parseComputerCall(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n rawToolCall: Record<string, any>\n): ComputerToolCall | undefined {\n if (rawToolCall.type !== \"computer_call\") {\n return undefined;\n }\n return {\n ...rawToolCall,\n type: \"tool_call\",\n call_id: rawToolCall.id,\n id: rawToolCall.call_id,\n name: \"computer_use\",\n isComputerTool: true,\n args: {\n action: rawToolCall.action,\n },\n };\n}\n\n/**\n * Checks if a tool call is a computer tool call.\n * @param toolCall - The tool call to check.\n * @returns True if the tool call is a computer tool call, false otherwise.\n */\nexport function isComputerToolCall(\n toolCall: unknown\n): toolCall is ComputerToolCall {\n return (\n typeof toolCall === \"object\" &&\n toolCall !== null &&\n \"type\" in toolCall &&\n toolCall.type === \"tool_call\" &&\n \"isComputerTool\" in toolCall &&\n toolCall.isComputerTool === true\n );\n}\n\nexport function isCustomToolCall(\n toolCall: unknown,\n customToolCallIds?: Record<string, string>\n): toolCall is CustomToolCall {\n if (\n typeof toolCall !== \"object\" ||\n toolCall === null ||\n !(\"type\" in toolCall) ||\n toolCall.type !== \"tool_call\"\n ) {\n return false;\n }\n if (\"isCustomTool\" in toolCall && toolCall.isCustomTool === true) {\n return true;\n }\n if (\n customToolCallIds &&\n \"id\" in toolCall &&\n typeof toolCall.id === \"string\" &&\n toolCall.id in customToolCallIds\n ) {\n return true;\n }\n return false;\n}\n\nexport function convertCompletionsCustomTool(\n tool: OpenAIClient.Chat.ChatCompletionCustomTool\n): OpenAIClient.Responses.CustomTool {\n const getFormat = () => {\n if (!tool.custom.format) {\n return undefined;\n }\n if (tool.custom.format.type === \"grammar\") {\n return {\n type: \"grammar\" as const,\n definition: tool.custom.format.grammar.definition,\n syntax: tool.custom.format.grammar.syntax,\n };\n }\n if (tool.custom.format.type === \"text\") {\n return {\n type: \"text\" as const,\n };\n }\n return undefined;\n };\n return {\n type: \"custom\",\n name: tool.custom.name,\n description: tool.custom.description,\n format: getFormat(),\n };\n}\n\nexport function convertResponsesCustomTool(\n tool: OpenAIClient.Responses.CustomTool\n): OpenAIClient.Chat.ChatCompletionCustomTool {\n const getFormat = () => {\n if (!tool.format) {\n return undefined;\n }\n if (tool.format.type === \"grammar\") {\n return {\n type: \"grammar\" as const,\n grammar: {\n definition: tool.format.definition,\n syntax: tool.format.syntax,\n },\n };\n }\n if (tool.format.type === \"text\") {\n return {\n type: \"text\" as const,\n };\n }\n return undefined;\n };\n return {\n type: \"custom\",\n custom: {\n name: tool.name,\n description: tool.description,\n format: getFormat(),\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/utils/tools.d.cts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { OpenAI } from "openai";
|
|
2
|
+
import "@langchain/core/language_models/base";
|
|
2
3
|
import { BindToolsInput } from "@langchain/core/language_models/chat_models";
|
|
3
4
|
import { DynamicTool } from "@langchain/core/tools";
|
|
5
|
+
import "@langchain/core/messages/tool";
|
|
4
6
|
//#region src/utils/tools.d.ts
|
|
5
7
|
type OpenAIToolChoice = OpenAI.ChatCompletionToolChoiceOption | "any" | string;
|
|
6
8
|
type ResponsesToolChoice = NonNullable<OpenAI.Responses.ResponseCreateParams["tool_choice"]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.cts","names":[],"sources":["../../src/utils/tools.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"tools.d.cts","names":[],"sources":["../../src/utils/tools.ts"],"mappings":";;;;;;KAiMY,mBACR,OAAa;KAIL,sBAAsB,YAChC,OAAa,UAAU;KAGb,qBACR,iBACA,OAAa,KAAK,qBAClB;KAEQ,gBAAgB,YAC1B,OAAa,UAAU"}
|
package/dist/utils/tools.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { OpenAI } from "openai";
|
|
2
2
|
import { BindToolsInput } from "@langchain/core/language_models/chat_models";
|
|
3
|
+
import "@langchain/core/language_models/base";
|
|
3
4
|
import { DynamicTool } from "@langchain/core/tools";
|
|
5
|
+
import "@langchain/core/messages/tool";
|
|
4
6
|
//#region src/utils/tools.d.ts
|
|
5
7
|
type OpenAIToolChoice = OpenAI.ChatCompletionToolChoiceOption | "any" | string;
|
|
6
8
|
type ResponsesToolChoice = NonNullable<OpenAI.Responses.ResponseCreateParams["tool_choice"]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","names":[],"sources":["../../src/utils/tools.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"tools.d.ts","names":[],"sources":["../../src/utils/tools.ts"],"mappings":";;;;;;KAiMY,mBACR,OAAa;KAIL,sBAAsB,YAChC,OAAa,UAAU;KAGb,qBACR,iBACA,OAAa,KAAK,qBAClB;KAEQ,gBAAgB,YAC1B,OAAa,UAAU"}
|