diff --git a/components/openai/actions/chat-using-file-search/chat-using-file-search.mjs b/components/openai/actions/chat-using-file-search/chat-using-file-search.mjs index 6e2951b359ead..1c5fa0a7b6add 100644 --- a/components/openai/actions/chat-using-file-search/chat-using-file-search.mjs +++ b/components/openai/actions/chat-using-file-search/chat-using-file-search.mjs @@ -5,7 +5,7 @@ import constants from "../../common/constants.mjs"; export default { ...common, name: "Chat using File Search", - version: "0.0.5", + version: "0.0.6", key: "openai-chat-using-file-search", description: "Chat with your files knowledge base (vector stores). [See the documentation](https://platform.openai.com/docs/guides/tools-file-search)", type: "action", diff --git a/components/openai/actions/chat-using-functions/chat-using-functions.mjs b/components/openai/actions/chat-using-functions/chat-using-functions.mjs index c667bf03780db..668cd73527b8e 100644 --- a/components/openai/actions/chat-using-functions/chat-using-functions.mjs +++ b/components/openai/actions/chat-using-functions/chat-using-functions.mjs @@ -5,7 +5,7 @@ import constants from "../../common/constants.mjs"; export default { ...common, name: "Chat using Functions", - version: "0.0.6", + version: "0.0.7", key: "openai-chat-using-functions", description: "Chat with your models and allow them to invoke functions. Optionally, you can build and invoke workflows as functions. [See the documentation](https://platform.openai.com/docs/guides/function-calling)", type: "action", diff --git a/components/openai/actions/chat-using-web-search/chat-using-web-search.mjs b/components/openai/actions/chat-using-web-search/chat-using-web-search.mjs index eff989903678c..b65d0d5d666ce 100644 --- a/components/openai/actions/chat-using-web-search/chat-using-web-search.mjs +++ b/components/openai/actions/chat-using-web-search/chat-using-web-search.mjs @@ -5,7 +5,7 @@ import constants from "../../common/constants.mjs"; export default { ...common, name: "Chat using Web Search", - version: "0.0.5", + version: "0.0.6", key: "openai-chat-using-web-search", description: "Chat using the web search tool. [See the documentation](https://platform.openai.com/docs/guides/tools-web-search)", type: "action", diff --git a/components/openai/actions/chat-with-responses-api/chat-with-responses-api.mjs b/components/openai/actions/chat-with-responses-api/chat-with-responses-api.mjs new file mode 100644 index 0000000000000..265c0a4b3c8bd --- /dev/null +++ b/components/openai/actions/chat-with-responses-api/chat-with-responses-api.mjs @@ -0,0 +1,171 @@ +import openai from "../../openai.app.mjs"; +import common from "../common/common.mjs"; +import constants from "../../common/constants.mjs"; +import { + parseArray, + parseJson, +} from "../../common/helpers.mjs"; + +export default { + ...common, + key: "openai-chat-with-responses-api", + name: "Chat With Responses API", + version: "0.0.1", + description: "Send a chat via the Responses API, mixing built-in tools and MCP server tools. [See the documentation](https://platform.openai.com/docs/guides/tools?api-mode=responses).", + type: "action", + props: { + openai, + modelId: { + description: "Model used to generate the response", + propDefinition: [ + openai, + "chatCompletionModelId", + ], + }, + input: { + description: "Text input to the model used to generate a response", + propDefinition: [ + openai, + "input", + ], + }, + instructions: { + description: "Inserts a system (or developer) message as the first item in the model's context", + propDefinition: [ + openai, + "instructions", + ], + }, + previousResponseId: { + type: "string", + label: "Previous Response ID", + description: "The unique ID of the previous response to the model. Use this to create multi-turn conversations", + optional: true, + }, + truncation: { + type: "string", + label: "Truncation", + description: + "Specifies the truncation mode for the response if it exceeds the context window", + default: "auto", + options: [ + "auto", + "disabled", + ], + optional: true, + }, + responseFormat: { + type: "string", + label: "Response Format", + description: "- `text`: Returns unstructured text output.\n- `json_schema`: Enforces a specific structure using a JSON schema.", + options: [ + "text", + "json_schema", + ], + default: "text", + optional: true, + reloadProps: true, + }, + builtInTools: { + type: "string[]", + label: "Built-In Tools", + description: "Which of OpenAI's first-party tools to enable (web search, file search, code interpreter).", + options: [ + { + label: "Web Search", + value: "web_search_preview", + }, + { + label: "File Search", + value: "file_search", + }, + { + label: "Code Interpreter", + value: "code_interpreter", + }, + ], + default: [], + }, + otherTools: { + type: "string[]", + label: "Other Tools", + description: "Other tools to include in the chat. [See the documentation](https://platform.openai.com/docs/guides/tools-remote-mcp). Example: `{ type: \"mcp\", server_label: \"gmail\", server_url: \"https://remote.mcp.pipedream.net\", headers: {}, require_approval: \"never\" }`", + optional: true, + }, + }, + additionalProps() { + if (this.responseFormat === constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value) { + return { + schemaName: { + type: "string", + label: "Name", + description: "The name of the schema.", + }, + schema: { + type: "string", + label: "JSON Schema", + description: "Define the schema that the model's output must adhere to. Only supported models are `gpt-4o-mini`, `gpt-4o-mini-2024-07-18`, `gpt-4o-2024-08-06` and later.", + }, + }; + } + return {}; + }, + async run({ $ }) { + const { + builtInTools, + otherTools, + modelId, + input, + instructions, + previousResponseId, + truncation, + responseFormat, + schemaName, + schema, + } = this; + + const tools = builtInTools.map((tool) => ({ + type: tool, + })); + + if (otherTools) { + tools.push(...parseArray(otherTools)); + } + + const data = { + model: modelId, + input, + instructions, + previous_response_id: previousResponseId, + truncation, + tools, + }; + + if (responseFormat === constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value) { + try { + data.text = { + format: { + type: responseFormat, + name: schemaName, + schema: parseJson(schema), + }, + }; + } catch { + throw new Error("Invalid JSON format in the provided JSON Schema"); + } + } + + const response = await this.openai.responses({ + $, + data, + debug: true, + }); + + if (response) { + $.export("$summary", `Successfully sent chat to OpenAI Responses API with ID \`${response.id}\`.`); + $.export("chat_responses", response.output); + } + + return response; + }, +}; diff --git a/components/openai/actions/chat/chat.mjs b/components/openai/actions/chat/chat.mjs index 1e8ce7a22b575..a74cf78cbc933 100644 --- a/components/openai/actions/chat/chat.mjs +++ b/components/openai/actions/chat/chat.mjs @@ -5,7 +5,7 @@ import constants from "../../common/constants.mjs"; export default { ...common, name: "Chat", - version: "0.3.1", + version: "0.3.2", key: "openai-chat", description: "The Chat API, using the `gpt-3.5-turbo` or `gpt-4` model. [See the documentation](https://platform.openai.com/docs/api-reference/chat)", type: "action", diff --git a/components/openai/actions/classify-items-into-categories/classify-items-into-categories.mjs b/components/openai/actions/classify-items-into-categories/classify-items-into-categories.mjs index 34826e091b76e..ec8bb2e91bc3b 100644 --- a/components/openai/actions/classify-items-into-categories/classify-items-into-categories.mjs +++ b/components/openai/actions/classify-items-into-categories/classify-items-into-categories.mjs @@ -3,7 +3,7 @@ import common from "../common/common-helper.mjs"; export default { ...common, name: "Classify Items into Categories", - version: "0.1.7", + version: "0.1.8", key: "openai-classify-items-into-categories", description: "Classify items into specific categories using the Chat API. [See the documentation](https://platform.openai.com/docs/api-reference/chat)", type: "action", diff --git a/components/openai/actions/create-embeddings/create-embeddings.mjs b/components/openai/actions/create-embeddings/create-embeddings.mjs index d620786cc696d..4c317981d8f1c 100644 --- a/components/openai/actions/create-embeddings/create-embeddings.mjs +++ b/components/openai/actions/create-embeddings/create-embeddings.mjs @@ -4,7 +4,7 @@ import common from "../common/common.mjs"; export default { name: "Create Embeddings", - version: "0.0.19", + version: "0.0.20", key: "openai-create-embeddings", description: "Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. [See the documentation](https://platform.openai.com/docs/api-reference/embeddings)", type: "action", diff --git a/components/openai/actions/send-prompt/send-prompt.mjs b/components/openai/actions/send-prompt/send-prompt.mjs index 77cdb8469dd43..506c02110bbdb 100644 --- a/components/openai/actions/send-prompt/send-prompt.mjs +++ b/components/openai/actions/send-prompt/send-prompt.mjs @@ -4,7 +4,7 @@ import common from "../common/common.mjs"; export default { ...common, name: "Create Completion (Send Prompt)", - version: "0.1.18", + version: "0.1.19", key: "openai-send-prompt", description: "OpenAI recommends using the **Chat** action for the latest `gpt-3.5-turbo` API, since it's faster and 10x cheaper. This action creates a completion for the provided prompt and parameters using the older `/completions` API. [See the documentation](https://beta.openai.com/docs/api-reference/completions/create)", type: "action", diff --git a/components/openai/actions/summarize/summarize.mjs b/components/openai/actions/summarize/summarize.mjs index 49b5d11ac3989..b420f446c7898 100644 --- a/components/openai/actions/summarize/summarize.mjs +++ b/components/openai/actions/summarize/summarize.mjs @@ -4,7 +4,7 @@ import constants from "../../common/constants.mjs"; export default { ...common, name: "Summarize Text", - version: "0.1.7", + version: "0.1.8", key: "openai-summarize", description: "Summarizes text using the Chat API. [See the documentation](https://platform.openai.com/docs/api-reference/chat)", type: "action", diff --git a/components/openai/actions/translate-text/translate-text.mjs b/components/openai/actions/translate-text/translate-text.mjs index ad4491d870fe4..aedeb22df631a 100644 --- a/components/openai/actions/translate-text/translate-text.mjs +++ b/components/openai/actions/translate-text/translate-text.mjs @@ -9,7 +9,7 @@ const langOptions = lang.LANGUAGES.map((l) => ({ export default { ...common, name: "Translate Text (Whisper)", - version: "0.1.7", + version: "0.1.8", key: "openai-translate-text", description: "Translate text from one language to another using the Chat API. [See the documentation](https://platform.openai.com/docs/api-reference/chat)", type: "action", diff --git a/components/openai/common/helpers.mjs b/components/openai/common/helpers.mjs index 0a984c0024aa5..c15f53d900180 100644 --- a/components/openai/common/helpers.mjs +++ b/components/openai/common/helpers.mjs @@ -37,3 +37,52 @@ export function parse(value) { throw new ConfigurationError("Make sure the schema contains a valid JSON object."); } } + +export const parseJson = (input, maxDepth = 100) => { + const seen = new WeakSet(); + const parse = (value) => { + if (maxDepth <= 0) { + return value; + } + if (typeof(value) === "string") { + // Only parse if the string looks like a JSON object or array + const trimmed = value.trim(); + if ( + (trimmed.startsWith("{") && trimmed.endsWith("}")) || + (trimmed.startsWith("[") && trimmed.endsWith("]")) + ) { + try { + return parseJson(JSON.parse(value), maxDepth - 1); + } catch (e) { + return value; + } + } + return value; + } else if (typeof(value) === "object" && value !== null && !Array.isArray(value)) { + if (seen.has(value)) { + return value; + } + seen.add(value); + return Object.entries(value) + .reduce((acc, [ + key, + val, + ]) => Object.assign(acc, { + [key]: parse(val), + }), {}); + } else if (Array.isArray(value)) { + return value.map((item) => parse(item)); + } + return value; + }; + + return parse(input); +}; + +export function parseArray (input, maxDepth = 100) { + if (!Array.isArray(input)) { + return input; + } + + return input.map((item) => parseJson(item, maxDepth)); +} diff --git a/components/openai/package.json b/components/openai/package.json index 1f2777f01d59f..58e4ff80f0113 100644 --- a/components/openai/package.json +++ b/components/openai/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/openai", - "version": "1.0.2", + "version": "1.1.0", "description": "Pipedream OpenAI Components", "main": "openai.app.mjs", "keywords": [ @@ -16,7 +16,6 @@ "dependencies": { "@pipedream/platform": "^3.1.0", "@pipedream/types": "^0.1.4", - "axios": "^1.6.2", "bottleneck": "^2.19.5", "form-data": "^4.0.0", "got": "^12.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f4116b014806..e8e725d89ff9a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9405,9 +9405,6 @@ importers: '@pipedream/types': specifier: ^0.1.4 version: 0.1.6 - axios: - specifier: ^1.6.2 - version: 1.7.7 bottleneck: specifier: ^2.19.5 version: 2.19.5 @@ -38964,7 +38961,7 @@ snapshots: '@supabase/node-fetch': 2.6.15 '@types/phoenix': 1.6.5 '@types/ws': 8.5.13 - ws: 8.18.0 + ws: 8.18.2 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -38974,7 +38971,7 @@ snapshots: '@supabase/node-fetch': 2.6.15 '@types/phoenix': 1.6.5 '@types/ws': 8.5.13 - ws: 8.18.0 + ws: 8.18.2 transitivePeerDependencies: - bufferutil - utf-8-validate