diff --git a/.husky/pre-push b/.husky/pre-push index 7ed106ecac510..88fb8887e5006 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,7 +1,7 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -npx pnpm install -r +npx pnpm install --frozen-lockfile if ! (git diff HEAD --quiet pnpm-lock.yaml); then echo "modified pnpm-lock.yaml - please commit the file" diff --git a/components/_302_ai/302_ai_components.mdc b/components/_302_ai/302_ai_components.mdc new file mode 100644 index 0000000000000..a63d01a3a46d5 --- /dev/null +++ b/components/_302_ai/302_ai_components.mdc @@ -0,0 +1,79 @@ +--- +alwaysApply: true +--- +Write the actions for the 302.AI app. + +General guidelines: +- Avoid manual truthiness checks for optional parameters, as @pipedream/platform utilities (@pipedream/axios) automatically exclude undefined values. +- Make sure to wrap API calls with the _makeRequest method. All actions methods need to call the _makeRequest methods. No actions method should call axios directly. +- Don't use the "number" datatype in props, use "string" instead for "number" datatypes. +- Parameters that in the API documentation are boolean will be defined as type "string with options as `default: "0",options: ["0","1",],` setting the default to "0" or "1" as appropiate per the API documentation. Then in the component code parse it to boolean type variable such as in `include_performers: parseInt(this.includePerformers) === 1,` +- In the package.json file essentially you'll only set the dependencies property, set version prop to "0.1.0", you can refer to the following example that was created for Leonardo AI components: +``` +{ + "name": "@pipedream/leonardo_ai", + "version": "0.1.0", + "description": "Pipedream Leonardo AI Components", + "main": "leonardo_ai.app.mjs", + "keywords": [ + "pipedream", + "leonardo_ai" + ], + "homepage": "https://pipedream.com/apps/leonardo_ai", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.1.0", + "form-data": "^4.0.4" + } +} +``` +--as a reference of an example API call to 302.AI API, including authorization, you can use the one we feature at Pipedream. Remember, you'll wrap API calls inside _makeRequest and action methods need to call _makeRequest. +``` +import { axios } from "@pipedream/platform" +export default defineComponent({ + props: { + _302_ai: { + type: "app", + app: "_302_ai", + } + }, + async run({steps, $}) { + return await axios($, { + url: `https://api.302.ai/v1/models`, + headers: { + Authorization: `Bearer ${this._302_ai.$auth.api_key}`, + }, + }) + }, +}) +--The 302.AI API is "OpenAI compliant", so 302.AI API URL is https://api.302.ai or https://api.302.ai/v1 and are analogous to OpenAI's https://api.openai.com and https://api.openai.com/v1 respectively +--For each prop that is used more than one create a propDefinition for it and reuse it in component code, changing description, detaults as needed. +--For the model prop which is likely used in several components using async options based on the List Models enpoint documented at https://doc.302.ai/147522038e0 +``` +chat-with-302-ai +Prompt: Send a message to the 302.AI Chat API using. Ideal for dynamic conversations, contextual assistance, and creative generation. +-When you come up for the description for this component follow format: . [See documentation](https://doc.302.ai/147522039e0) + +chat-using-functions +Prompt: Enable your 302.AI model to invoke user-defined functions. Useful for conditional logic, workflow orchestration, and tool invocation within conversations. +-When you come up for the description for this component follow format: . [See documentation](https://doc.302.ai/211560247e0) + +summarize-text +Prompt: Summarize long-form text into concise, readable output using the 302.AI Chat API. Great for reports, content digestion, and executive briefs. +-When you come up for the description for this component follow format: . [See documentation](https://doc.302.ai/147522039e0) + +classify-items +Prompt: Classify input items into predefined categories using 302.AI models. Perfect for tagging, segmentation, and automated organization. +-When you come up for the description for this component follow format: . [See documentation](https://doc.302.ai/147522039e0) + +create-embeddings +Prompt: Generate vector embeddings from text using the 302.AI Embeddings API. Useful for semantic search, clustering, and vector store indexing. +-When you come up for the description for this component follow format: . [See documentation](https://doc.302.ai/147522048e0) + +create-completion +Prompt: Send a prompt to the legacy endpoint on 302.AI to generate text using models like . Recommended for backward-compatible flows. +-When you come up for the description for this component follow format: . [See documentation](https://doc.302.ai/147522039e0) + diff --git a/components/_302_ai/_302_ai.app.mjs b/components/_302_ai/_302_ai.app.mjs index c50b2337222fc..87984c7465730 100644 --- a/components/_302_ai/_302_ai.app.mjs +++ b/components/_302_ai/_302_ai.app.mjs @@ -1,11 +1,121 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "_302_ai", - propDefinitions: {}, + propDefinitions: { + modelId: { + type: "string", + label: "Model", + description: "The ID of the model to use", + async options() { + const models = await this.listModels(); + return models.map((model) => ({ + label: model.id, + value: model.id, + })); + }, + }, + chatCompletionModelId: { + type: "string", + label: "Model", + description: "The ID of the model to use for chat completions", + async options() { + const models = await this.listModels(); + // Filter for chat models (similar to OpenAI) + return models + .filter((model) => model.id.match(/gpt|claude|gemini|llama|mistral|deepseek/gi)) + .map((model) => ({ + label: model.id, + value: model.id, + })); + }, + }, + embeddingsModelId: { + type: "string", + label: "Model", + description: "The ID of the embeddings model to use", + async options() { + const models = await this.listModels(); + // Filter for embedding models + return models + .filter((model) => model.id.match(/embedding/gi)) + .map((model) => ({ + label: model.id, + value: model.id, + })); + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _apiKey() { + return this.$auth.api_key; + }, + _baseApiUrl() { + return "https://api.302.ai/v1"; + }, + _makeRequest({ + $ = this, + path, + ...args + } = {}) { + return axios($, { + ...args, + url: `${this._baseApiUrl()}${path}`, + headers: { + ...args.headers, + "Authorization": `Bearer ${this._apiKey()}`, + "Content-Type": "application/json", + }, + }); + }, + async listModels({ $ } = {}) { + const { data: models } = await this._makeRequest({ + $, + path: "/models", + }); + return models || []; + }, + async _makeCompletion({ + path, ...args + }) { + const data = await this._makeRequest({ + path, + method: "POST", + ...args, + }); + + // For completions, return the text of the first choice at the top-level + let generated_text; + if (path === "/completions") { + const { choices } = data; + generated_text = choices?.[0]?.text; + } + // For chat completions, return the assistant message at the top-level + let generated_message; + if (path === "/chat/completions") { + const { choices } = data; + generated_message = choices?.[0]?.message; + } + + return { + generated_text, + generated_message, + ...data, + }; + }, + createChatCompletion(args = {}) { + return this._makeCompletion({ + path: "/chat/completions", + ...args, + }); + }, + createEmbeddings(args = {}) { + return this._makeRequest({ + path: "/embeddings", + method: "POST", + ...args, + }); }, }, -}; \ No newline at end of file +}; diff --git a/components/_302_ai/actions/chat-using-functions/chat-using-functions.mjs b/components/_302_ai/actions/chat-using-functions/chat-using-functions.mjs new file mode 100644 index 0000000000000..3276b90e5efcb --- /dev/null +++ b/components/_302_ai/actions/chat-using-functions/chat-using-functions.mjs @@ -0,0 +1,211 @@ +import _302_ai from "../../_302_ai.app.mjs"; +import constants from "../common/constants.mjs"; + +export default { + name: "Chat using Functions", + version: "0.0.1", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + key: "_302_ai-chat-using-functions", + description: "Enable your 302.AI model to invoke user-defined functions. Useful for conditional logic, workflow orchestration, and tool invocation within conversations. [See documentation](https://doc.302.ai/211560247e0)", + type: "action", + props: { + _302_ai, + modelId: { + propDefinition: [ + _302_ai, + "chatCompletionModelId", + ], + }, + input: { + type: "string", + label: "Chat Input", + description: "Text input to the model used to generate a response", + }, + functions: { + type: "string", + label: "Functions", + description: "A valid JSON array of tools/functions using the OpenAI function schema definition. Each tool must have a `type` property set to \"function\" and a `function` object with `name`, `description`, and `parameters`.", + default: +`[ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA" + }, + "unit": { + "type": "string", + "enum": ["celsius", "fahrenheit"] + } + }, + "required": ["location"] + } + } + } +]`, + }, + instructions: { + type: "string", + label: "Instructions", + description: "System instructions for the model", + optional: true, + }, + toolChoice: { + type: "string", + label: "Tool Choice", + description: "- **auto**: The model decides whether and how many functions to call.\n- **required**: The model must call one or more functions.\n- **function_name**: Enter a custom function name to force the model to call this specific function.", + optional: true, + default: "auto", + options: [ + "auto", + "required", + ], + }, + parallelToolCalls: { + type: "string", + label: "Parallel Function Calling", + description: "Allow or prevent the model to call multiple functions in a single turn", + optional: true, + default: "1", + options: [ + { + label: "Enabled", + value: "1", + }, + { + label: "Disabled", + value: "0", + }, + ], + }, + maxTokens: { + label: "Max Tokens", + description: "The maximum number of tokens to generate in the completion.", + type: "string", + optional: true, + }, + temperature: { + label: "Temperature", + description: "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.", + type: "string", + optional: true, + }, + responseFormat: { + type: "string", + label: "Response Format", + description: "- **Text**: Returns unstructured text output.\n- **JSON Schema**: Enables you to define a specific structure for the model's output using a JSON schema.", + options: [ + constants.CHAT_RESPONSE_FORMAT.TEXT.value, + constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value, + ], + default: constants.CHAT_RESPONSE_FORMAT.TEXT.value, + optional: true, + reloadProps: true, + }, + }, + additionalProps() { + const props = {}; + + if (this.responseFormat === constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value) { + props.jsonSchema = { + type: "string", + label: "JSON Schema", + description: "Define the schema that the model's output must adhere to.", + }; + } + + return props; + }, + async run({ $ }) { + const messages = []; + + if (this.instructions) { + messages.push({ + role: "system", + content: this.instructions, + }); + } + + messages.push({ + role: "user", + content: this.input, + }); + + const data = { + model: this.modelId, + messages, + parallel_tool_calls: parseInt(this.parallelToolCalls) === 1, + tools: [], + }; + + if (this.maxTokens) { + data.max_tokens = parseInt(this.maxTokens); + } + + if (this.temperature) { + data.temperature = parseFloat(this.temperature); + } + + let functions = this.functions; + if (typeof functions === "string") { + try { + functions = JSON.parse(functions); + } catch (error) { + throw new Error("Invalid JSON format in the provided Functions Schema"); + } + } + + if (Array.isArray(functions)) { + data.tools.push(...functions); + } else { + data.tools.push(functions); + } + + if (this.toolChoice) { + if (this.toolChoice === "auto" || this.toolChoice === "required") { + data.tool_choice = this.toolChoice; + } else { + data.tool_choice = { + type: "function", + name: this.toolChoice, + }; + } + } + + if (this.responseFormat === constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value + && this.jsonSchema) { + try { + data.response_format = { + type: this.responseFormat, + json_schema: typeof this.jsonSchema === "string" + ? JSON.parse(this.jsonSchema) + : this.jsonSchema, + }; + } catch (error) { + throw new Error("Invalid JSON format in the provided JSON Schema"); + } + } + + const response = await this._302_ai.createChatCompletion({ + $, + data, + }); + + if (response) { + $.export("$summary", `Successfully sent chat with id ${response.id}`); + } + + return response; + }, +}; + diff --git a/components/_302_ai/actions/chat-with-302-ai/chat-with-302-ai.mjs b/components/_302_ai/actions/chat-with-302-ai/chat-with-302-ai.mjs new file mode 100644 index 0000000000000..fc69bcde78b29 --- /dev/null +++ b/components/_302_ai/actions/chat-with-302-ai/chat-with-302-ai.mjs @@ -0,0 +1,171 @@ +import _302_ai from "../../_302_ai.app.mjs"; +import common from "../common/common.mjs"; +import constants from "../common/constants.mjs"; + +export default { + ...common, + name: "Chat with 302.AI", + version: "0.0.1", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: false, + }, + key: "_302_ai-chat-with-302-ai", + description: "Send a message to the 302.AI Chat API. Ideal for dynamic conversations, contextual assistance, and creative generation. [See documentation](https://doc.302.ai/147522039e0)", + type: "action", + props: { + _302_ai, + modelId: { + propDefinition: [ + _302_ai, + "chatCompletionModelId", + ], + }, + userMessage: { + label: "User Message", + type: "string", + description: "The user message to send to the model", + }, + ...common.props, + systemInstructions: { + label: "System Instructions", + type: "string", + description: "The system message helps set the behavior of the assistant. For example: \"You are a helpful assistant.\"", + optional: true, + }, + messages: { + label: "Prior Message History", + type: "string[]", + description: "Because the models have no memory of past chat requests, all relevant information must be supplied via the conversation. You can provide an array of messages from prior conversations here. **Formats supported:** 1) Plain strings with role prefix (e.g., `User: Hello` or `Assistant: Hi there`), 2) JSON strings (e.g., `{\"role\": \"user\", \"content\": \"Hello\"}`), 3) Plain strings without prefix (defaults to user role).", + optional: true, + }, + responseFormat: { + type: "string", + label: "Response Format", + description: "- **Text**: Returns unstructured text output.\n- **JSON Object**: Returns a JSON object.\n- **JSON Schema**: Enables you to define a specific structure for the model's output using a JSON schema.", + options: Object.values(constants.CHAT_RESPONSE_FORMAT).map((format) => format.value), + default: constants.CHAT_RESPONSE_FORMAT.TEXT.value, + optional: true, + reloadProps: true, + }, + }, + additionalProps() { + const props = {}; + if (this.responseFormat === constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value) { + props.jsonSchema = { + type: "string", + label: "JSON Schema", + description: "Define the schema that the model's output must adhere to. Must be a valid JSON schema object.", + }; + } + return props; + }, + async run({ $ }) { + let messages = []; + + if (this.messages && this.messages.length) { + for (const message of this.messages) { + let parsed; + + if (typeof message === "string") { + // Try to parse as JSON first + try { + parsed = JSON.parse(message); + } catch { + // If not JSON, treat as a plain string and infer role from content + // Check if message starts with "User:" or "Assistant:" or "System:" + if (message.toLowerCase().startsWith("user:")) { + parsed = { + role: "user", + content: message.replace(/^user:\s*/i, "").trim(), + }; + } else if (message.toLowerCase().startsWith("assistant:")) { + parsed = { + role: "assistant", + content: message.replace(/^assistant:\s*/i, "").trim(), + }; + } else if (message.toLowerCase().startsWith("system:")) { + parsed = { + role: "system", + content: message.replace(/^system:\s*/i, "").trim(), + }; + } else { + // Default to user role if no prefix + parsed = { + role: "user", + content: message, + }; + } + } + } else { + parsed = message; + } + + messages.push(parsed); + } + } else { + if (this.systemInstructions) { + messages.push({ + "role": "system", + "content": this.systemInstructions, + }); + } + } + + messages.push({ + "role": "user", + "content": this.userMessage, + }); + + const responseFormat = this.responseFormat === + constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value && this.jsonSchema + ? { + response_format: { + type: this.responseFormat, + json_schema: typeof this.jsonSchema === "string" + ? JSON.parse(this.jsonSchema) + : this.jsonSchema, + }, + } + : this.responseFormat && this.responseFormat !== constants.CHAT_RESPONSE_FORMAT.TEXT.value + ? { + response_format: { + type: this.responseFormat, + }, + } + : {}; + + const data = { + ...this._getCommonArgs(), + ...responseFormat, + messages, + }; + + const response = await this._302_ai.createChatCompletion({ + $, + data, + }); + + if (this.responseFormat === constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value) { + for (const choice of response.choices) { + try { + choice.message.content = JSON.parse(choice.message.content); + } catch { + console.log(`Unable to parse JSON: ${choice.message.content}`); + } + } + } + + if (response) { + $.export("$summary", `Successfully sent chat with id ${response.id}`); + } + + return { + original_messages: messages, + original_messages_with_assistant_response: messages.concat(response.choices[0]?.message), + ...response, + }; + }, +}; + diff --git a/components/_302_ai/actions/classify-items/classify-items.mjs b/components/_302_ai/actions/classify-items/classify-items.mjs new file mode 100644 index 0000000000000..1a38cae344ed5 --- /dev/null +++ b/components/_302_ai/actions/classify-items/classify-items.mjs @@ -0,0 +1,82 @@ +import common from "../common/common-helper.mjs"; + +export default { + ...common, + name: "Classify Items", + version: "0.0.1", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + key: "_302_ai-classify-items", + description: "Classify input items into predefined categories using 302.AI models. Perfect for tagging, segmentation, and automated organization. [See documentation](https://doc.302.ai/147522039e0)", + type: "action", + props: { + ...common.props, + info: { + type: "alert", + alertType: "info", + content: `Provide a list of **items** and a list of **categories**. The output will contain an array of objects, each with properties \`item\` and \`category\` + \nExample: + \nIf **Categories** is \`["people", "pets"]\`, and **Items** is \`["dog", "George Washington"]\` + \n The output will contain the following categorizations: + \n \`[{"item":"dog","category":"pets"},{"item":"George Washington","category":"people"}]\` + `, + }, + items: { + label: "Items", + description: "Items to categorize", + type: "string[]", + }, + categories: { + label: "Categories", + description: "Categories to classify items into", + type: "string[]", + }, + }, + methods: { + ...common.methods, + systemInstructions() { + return "Your goal is to categorize items into specific categories and produce ONLY JSON. The user will provide both the items and categories. Please only categorize items into the specific categories, and no others, and output ONLY JSON."; + }, + outputFormat() { + return "Please only categorize items into the specific categories, and no others. Output a valid JSON string — an array of objects, where each object has the following properties: item, category. Do not return any English text other than the JSON, either before or after the JSON. I need to parse the response as JSON, and parsing will fail if you return any English before or after the JSON"; + }, + userMessage() { + return `Categorize each of the following items:\n\n${this.items.join("\n")}\n\ninto one of the following categories:\n\n${this.categories.join("\n")}\n\n${this.outputFormat()}}`; + }, + summary() { + return `Categorized ${this.items.length} items into ${this.categories.length} categories`; + }, + formatOutput({ + messages, response, + }) { + if (!messages || !response) { + throw new Error("Invalid API output, please reach out to https://pipedream.com/support"); + } + const responses = response.choices?.map(({ message }) => message.content); + const categorizations = []; + for (const response of responses) { + try { + categorizations.push(JSON.parse(response)); + } catch (err) { + console.log("Failed to parse output, assistant returned malformed JSON"); + } + } + const output = { + messages, + }; + const n = this.n + ? parseInt(this.n) + : 1; + if (n > 1) { + output.categorizations = categorizations; + } else { + output.categorizations = categorizations[0]; + } + return output; + }, + }, +}; + diff --git a/components/_302_ai/actions/common/common-helper.mjs b/components/_302_ai/actions/common/common-helper.mjs new file mode 100644 index 0000000000000..24332aed6344b --- /dev/null +++ b/components/_302_ai/actions/common/common-helper.mjs @@ -0,0 +1,63 @@ +import _302_ai from "../../_302_ai.app.mjs"; +import common from "./common.mjs"; + +export default { + ...common, + props: { + _302_ai, + modelId: { + propDefinition: [ + _302_ai, + "chatCompletionModelId", + ], + description: "The ID of the model to use for chat completions", + }, + ...common.props, + }, + methods: { + ...common.methods, + systemInstructions() { + throw new Error("systemInstructions() must be implemented by the component"); + }, + userMessage() { + throw new Error("userMessage() must be implemented by the component"); + }, + summary() { + return; + }, + formatOutput() { + throw new Error("formatOutput() must be implemented by the component"); + }, + }, + async run({ $ }) { + const messages = [ + { + role: "system", + content: this.systemInstructions(), + }, + { + role: "user", + content: this.userMessage(), + }, + ]; + const data = { + ...this._getCommonArgs(), + model: this.modelId, + messages, + }; + const response = await this._302_ai.createChatCompletion({ + $, + data, + }); + + if (this.summary() && response) { + $.export("$summary", this.summary()); + } + + return this.formatOutput({ + response, + messages, + }); + }, +}; + diff --git a/components/_302_ai/actions/common/common.mjs b/components/_302_ai/actions/common/common.mjs new file mode 100644 index 0000000000000..3d3484b4aaf5f --- /dev/null +++ b/components/_302_ai/actions/common/common.mjs @@ -0,0 +1,122 @@ +import constants from "./constants.mjs"; + +export default { + props: { + maxTokens: { + label: "Max Tokens", + description: "The maximum number of tokens to generate in the completion.", + type: "string", + optional: true, + }, + temperature: { + label: "Temperature", + description: "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.", + type: "string", + optional: true, + }, + topP: { + label: "Top P", + description: "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.", + type: "string", + optional: true, + }, + n: { + label: "N", + description: "How many completions to generate for each prompt", + type: "string", + optional: true, + }, + stop: { + label: "Stop", + description: "Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.", + type: "string[]", + optional: true, + }, + presencePenalty: { + label: "Presence Penalty", + description: "Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.", + type: "string", + optional: true, + }, + frequencyPenalty: { + label: "Frequency Penalty", + description: "Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.", + type: "string", + optional: true, + }, + user: { + label: "User", + description: "A unique identifier representing your end-user, which can help monitor and detect abuse.", + type: "string", + optional: true, + }, + }, + methods: { + _getCommonArgs() { + const args = { + model: this.modelId, + temperature: this.temperature + ? parseFloat(this.temperature) + : undefined, + top_p: this.topP + ? parseFloat(this.topP) + : undefined, + n: this.n + ? parseInt(this.n) + : undefined, + stop: this.stop, + presence_penalty: this.presencePenalty + ? parseFloat(this.presencePenalty) + : undefined, + frequency_penalty: this.frequencyPenalty + ? parseFloat(this.frequencyPenalty) + : undefined, + max_tokens: this.maxTokens + ? parseInt(this.maxTokens) + : undefined, + user: this.user, + }; + return args; + }, + async _getChatArgs() { + const messages = []; + + if (this.systemInstructions) { + messages.push({ + "role": "system", + "content": this.systemInstructions, + }); + } + + messages.push({ + "role": "user", + "content": this.userMessage, + }); + + const responseFormat = this.responseFormat + === constants.CHAT_RESPONSE_FORMAT.JSON_SCHEMA.value && this.jsonSchema + ? { + response_format: { + type: this.responseFormat, + json_schema: typeof this.jsonSchema === "string" + ? JSON.parse(this.jsonSchema) + : this.jsonSchema, + }, + } + : this.responseFormat + ? { + response_format: { + type: this.responseFormat, + }, + } + : {}; + + return { + ...this._getCommonArgs(), + ...responseFormat, + messages, + }; + }, + }, +}; + diff --git a/components/_302_ai/actions/common/constants.mjs b/components/_302_ai/actions/common/constants.mjs new file mode 100644 index 0000000000000..9fb6275a21fdc --- /dev/null +++ b/components/_302_ai/actions/common/constants.mjs @@ -0,0 +1,27 @@ +const CHAT_RESPONSE_FORMAT = { + TEXT: { + label: "Text", + value: "text", + }, + JSON_OBJECT: { + label: "JSON Object", + value: "json_object", + }, + JSON_SCHEMA: { + label: "JSON Schema", + value: "json_schema", + }, +}; + +const SUMMARIZE_LENGTH = [ + "word", + "sentence", + "paragraph", + "page", +]; + +export default { + CHAT_RESPONSE_FORMAT, + SUMMARIZE_LENGTH, +}; + diff --git a/components/_302_ai/actions/create-embeddings/create-embeddings.mjs b/components/_302_ai/actions/create-embeddings/create-embeddings.mjs new file mode 100644 index 0000000000000..c6eb54cb9b8a6 --- /dev/null +++ b/components/_302_ai/actions/create-embeddings/create-embeddings.mjs @@ -0,0 +1,92 @@ +import { ConfigurationError } from "@pipedream/platform"; +import _302_ai from "../../_302_ai.app.mjs"; + +export default { + name: "Create Embeddings", + version: "0.0.1", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + key: "_302_ai-create-embeddings", + description: "Generate vector embeddings from text using the 302.AI Embeddings API. Useful for semantic search, clustering, and vector store indexing. [See documentation](https://doc.302.ai/147522048e0)", + type: "action", + props: { + _302_ai, + modelId: { + propDefinition: [ + _302_ai, + "embeddingsModelId", + ], + }, + input: { + label: "Input", + description: "Input text to get embeddings for, encoded as a string or array of tokens. To get embeddings for multiple inputs in a single request, pass an array of strings or array of token arrays. Each input must not exceed 8192 tokens in length.", + type: "string[]", + }, + user: { + label: "User", + description: "A unique identifier representing your end-user, which can help monitor and detect abuse.", + type: "string", + optional: true, + }, + encodingFormat: { + label: "Encoding Format", + description: "The format to return the embeddings in. Can be either `float` or `base64`.", + type: "string", + optional: true, + options: [ + "float", + "base64", + ], + default: "float", + }, + dimensions: { + label: "Dimensions", + description: "The number of dimensions the resulting output embeddings should have. Only supported in some models.", + type: "string", + optional: true, + }, + }, + async run({ $ }) { + // Confirm no element is more than 8192 tokens in length + for (const [ + i, + element, + ] of this.input.entries()) { + if (element.length > 8192) { + throw new ConfigurationError(`Element #${i} is more than 8192 tokens in length. Each input must not exceed 8192 tokens in length.`); + } + } + + const data = { + model: this.modelId, + input: this.input, + }; + + if (this.user) { + data.user = this.user; + } + + if (this.encodingFormat) { + data.encoding_format = this.encodingFormat; + } + + if (this.dimensions) { + data.dimensions = parseInt(this.dimensions); + } + + const response = await this._302_ai.createEmbeddings({ + $, + data, + }); + + if (response) { + $.export("$summary", "Successfully created embeddings"); + } + + return response; + }, +}; + diff --git a/components/_302_ai/actions/summarize-text/summarize-text.mjs b/components/_302_ai/actions/summarize-text/summarize-text.mjs new file mode 100644 index 0000000000000..14d6a54f5554c --- /dev/null +++ b/components/_302_ai/actions/summarize-text/summarize-text.mjs @@ -0,0 +1,65 @@ +import common from "../common/common-helper.mjs"; +import constants from "../common/constants.mjs"; + +export default { + ...common, + name: "Summarize Text", + version: "0.0.1", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + key: "_302_ai-summarize-text", + description: "Summarize long-form text into concise, readable output using the 302.AI Chat API. Great for reports, content digestion, and executive briefs. [See documentation](https://doc.302.ai/147522039e0)", + type: "action", + props: { + ...common.props, + text: { + label: "Text", + description: "The text to summarize", + type: "string", + }, + length: { + label: "Summary Length", + description: "The length of the summary", + type: "string", + optional: true, + options: constants.SUMMARIZE_LENGTH, + }, + }, + methods: { + ...common.methods, + systemInstructions() { + return "Your goal is to summarize the text the user provides. Please follow the length guidelines presented in the prompt."; + }, + maxLength() { + return this.length + ? ` in one ${this.length}` + : ""; + }, + userMessage() { + return `Summarize the following text${this.maxLength()}: ${this.text}`; + }, + formatOutput({ + messages, response, + }) { + if (!messages || !response) { + throw new Error("Invalid API output, please reach out to https://pipedream.com/support"); + } + const output = { + messages, + }; + const n = this.n + ? parseInt(this.n) + : 1; + if (n > 1) { + output.summaries = response.choices?.map(({ message }) => message.content); + } else { + output.summary = response.choices?.[0]?.message?.content; + } + return output; + }, + }, +}; + diff --git a/components/_302_ai/package.json b/components/_302_ai/package.json index 62b5914423c5c..f4bcd9bfc7d91 100644 --- a/components/_302_ai/package.json +++ b/components/_302_ai/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/_302_ai", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream 302.ai Components", "main": "_302_ai.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.1.0" } -} \ No newline at end of file +} diff --git a/components/memory.mdc b/components/memory.mdc new file mode 100644 index 0000000000000..4f9d68a894b8a --- /dev/null +++ b/components/memory.mdc @@ -0,0 +1 @@ +Components should use wrapper methods in the app file for API requests rather than calling the app's private makeRequest directly. Avoid manual truthiness checks for optional parameters, as @pipedream/platform utilities (@pipedream/axios) automatically exclude undefined values. For file reading, use getFileStreamAndMetadata from @pipedream/platform. \ No newline at end of file diff --git a/components/pipedream-context.mdc b/components/pipedream-context.mdc new file mode 100644 index 0000000000000..4a89f2cbf16f6 --- /dev/null +++ b/components/pipedream-context.mdc @@ -0,0 +1,32 @@ +--- +alwaysApply: true +--- +We work on Pipedream components (API reference: https://pipedream.com/docs/components/contributing/api/ ). From our working folder, we focus on the 'components' folder, where we have a list of apps, and each app (e.g. 'google_sheets') may have several components. Here are some guidelines we've assembled over previous sessions: + +# Pipedream Component Development Guide + +## Best Practices +1. **File Structure** + - App file (`app.mjs`) contains shared logic, auth, and propDefinitions + - Actions in `actions/[action-name]/[action-name].mjs` + - Sources in `sources/[source-name]/[source-name].mjs` + - Common code in `common/` directories + +2. **Naming Conventions** + - Folder names match component keys (e.g., `add-person-to-cadence`) + - Component keys follow pattern: `[app-name]-[component-name]` + - File names match folder names + +3. **Code Patterns** + - Use `@pipedream/platform`'s axios (no need to extract .data) + - Because `@pipedream/platform`'s axios already filters out undefined values, no need to check parameters individually before including them + - Use `ConfigurationError` from `@pipedream/platform` for user-facing errors + - Include documentation links in component descriptions + - Use propDefinitions in app file for reusable props with dynamic options + +4. **Sources (Webhooks)** + - Create common webhook functionality in `sources/common/webhook.mjs` + - Implement `activate()` and `deactivate()` hooks for webhook management + - Use `$.service.db` for storing webhook IDs + - Set `dedupe: "unique"` for webhook sources + - Include proper event type and summary methods diff --git a/components/ticketsauce/ticketsauce_components.mdc b/components/ticketsauce/ticketsauce_components.mdc new file mode 100644 index 0000000000000..3bed89e10813f --- /dev/null +++ b/components/ticketsauce/ticketsauce_components.mdc @@ -0,0 +1,749 @@ +--- +alwaysApply: true +--- +Write the actions for the TicketSauce app. + +General guidelines: +- Avoid manual truthiness checks for optional parameters, as @pipedream/platform utilities (@pipedream/axios) automatically exclude undefined values. +- Make sure to wrap API calls with the _makeRequest method. All actions methods need to call the _makeRequest methods. No actions method should call axios directly. +- Don't use the "number" datatype in props, use "string" instead for "number" datatypes. +- In the package.json file essentially you'll only set the dependencies property, set version prop to "0.1.0", you can refer to the following example that was created for Leonardo AI components: +``` +{ + "name": "@pipedream/leonardo_ai", + "version": "0.1.0", + "description": "Pipedream Leonardo AI Components", + "main": "leonardo_ai.app.mjs", + "keywords": [ + "pipedream", + "leonardo_ai" + ], + "homepage": "https://pipedream.com/apps/leonardo_ai", + "author": "Pipedream (https://pipedream.com/)", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.1.0", + "form-data": "^4.0.4" + } +} +``` +--as a reference of an example API call to TicketSauce API, including authorization, you can use the one we feature at Pipedream. Remember, you'll wrap API calls inside _makeRequest and action methods need to call _makeRequest. +``` +import { axios } from "@pipedream/platform" +export default defineComponent({ + props: { + ticketsauce: { + type: "app", + app: "ticketsauce", + } + }, + async run({steps, $}) { + return await axios($, { + url: `https://api.ticketsauce.com/v2/events`, + params: { + access_token: `${this.ticketsauce.$auth.oauth_access_token}`, + }, + }) + }, +}) + +``` +Specific actions: +get-events +Prompt +Get a list of all events owned by the authenticated account. + +-When you come up for the description for this component follow format: . [See documentation](https://speca.io/ticketsauce/ticketsauce-public-api?key=204000d6bda66da78315e721920f43aa#list-of-events) +- Here are the parameters for the related list events API endpoint, use as a basis for props: +``` +partner_id +string optional +Including this ID will limit the result set to the specific partner. + +organization_id +string optional +Including this ID will limit the result set to the specific organization. + +start_after +string optional +Only retrieve events that start AFTER the specified UTC date (format: YYYY-MM-DD). + +start_before +string optional +Only retrieve events that start BEFORE the specified UTC date (format: YYYY-MM-DD). + +start_phrase +string optional +A string representing the date to pull events that start __. Possible values are: today, yesterday, tomorrow, this_week, this_weekend, next_week, next_weekend, this_month, next_month + +end_after +string optional +Only retrieve events that end AFTER the specified UTC date (format: YYYY-MM-DD). + +end_before +string optional +Only retrieve events that end BEFORE the specified UTC date (format: YYYY-MM-DD). + +created_after +string optional +Only retrieve events that were created AFTER the specified UTC date (format: YYYY-MM-DD). + +created_before +string optional +Only retrieve events that were created BEFORE the specified UTC date (format: YYYY-MM-DD). + +active_only +boolean optional +Leaving this as true will restrict retrieved events to only ‘active’ events. Setting to false will allow the retrieval of both active and inactive events. +Default: +true + +inactive_only +boolean optional +Setting to true will restrict retrieved events to only ‘inactive’ events. +Default: +false + +privacy_type +string optional +By default, this will restrict events to only those that are public. Changing to ‘all’ will remove all restriction, or changing to ‘unlisted’ will make it only pull those events that are set to unlisted. +Default: +public + +sort_by +string optional +Which field to sort by. By default (‘date’), will sort events by their start date. Other options are ‘name’ (event name) or ‘city’ (the city where the event is located). +Default: +date + +sort_dir +string optional +Which direction you’d like to sort - either ascending (‘asc’ - the default) or descending (‘desc’). +Default: +asc + +include_performers +string optional +Returns any associated performers/artists with an event + +Default: +false +``` + +get-event-details +Prompt +Get details for a specified event. + +-When you come up for the description for this component following format: . [See documentation](https://speca.io/ticketsauce/ticketsauce-public-api?key=204000d6bda66da78315e721920f43aa#event-details) +- Here are the parameters for the related API endpoint, use as a basis for props: +``` +id_or_slug +path parameter, string required + +photos +query string parameter, integer optional +Whether or not to return the event’s photo gallery records. +Default: +0 + +include_performers +query string parameter, string optional +Returns any associated performers/artists with the event. +Default: +false +``` +-for the prop related to id_or_slug use async options so users can select an event. +-as referece examples for async options you can use those found in apps zendesk, guru, etsy and recently you helped me come up with async options for prop imageId in generate-motion.mjs of leonardo ai app. +-when returning the context object, if there are no more options to return, simply return an empty object {} +-here is the response example for "list events" endpoint for you to come up with logic on how to implement async options for the prop related to id_or_slug +``` +[ + { + "Event": { + "active": true, + "address": "1221 Saint James Street", + "address2": "", + "city": "Philadelphia", + "country": "United States", + "created": "2025-06-26 02:40:59", + "custom_id": null, + "show_start": true, + "show_end": false, + "end": "2029-03-01 23:45:00", + "end_utc": "2029-03-02 04:45:00", + "featured": false, + "id": "685cb33b-0dc8-462d-ae5b-00410a1e60d3", + "location": "Voyeur Nightclub", + "latitude": "39.948357", + "longitude": "-75.161697", + "map_zoom": "13", + "modified": "2025-09-16 22:08:06", + "name": "Badge Conference Event TEST", + "online_only": false, + "activity_producer_id": null, + "organization_id": "64ad9d19-1bd0-490f-b332-7c9f0ad1e024", + "partner_id": "64ac69a6-a344-4e05-bbc7-64670ad1e030", + "postal_code": "19107", + "privacy_type": "0", + "region": null, + "slug": "badge-conference-event-test", + "start": "2029-03-01 23:30:00", + "start_utc": "2029-03-02 04:30:00", + "state": "PA", + "tickets_active": true, + "timezone": "America/New_York", + "website": "", + "event_topic_id": "589e8222-c4f8-4794-bde7-73d40a004b01", + "organization_name": "Voyeur DC", + "scheduled_publish_datetime_utc": null, + "event_topic": "Business", + "category": "Business", + "event_url": "https://grindr.ticketsauce.com/e/badge-conference-event-test", + "tickets_url": "https://grindr.ticketsauce.com/e/badge-conference-event-test/tickets", + "display_times": true, + "order_count": 4, + "partner_name": "Grindr Demo" + }, + "Logo": { + "url": "https://res.cloudinary.com/eventservice/image/upload/q_auto,f_auto/v1751769059/saas/logos/image_1751769042730_r9qr7df7d.webp", + "created": "2025-06-26 03:04:39" + }, + "Masthead": { + "url": null, + "created": null + } + }, + { + "Event": { + "active": true, + "address": "", + "address2": "", + "city": "San Jose", + "country": "United States", + "created": "2025-07-23 01:23:07", + "custom_id": null, + "show_start": true, + "show_end": false, + "end": "2026-05-03 23:00:00", + "end_utc": "2026-05-04 06:00:00", + "featured": false, + "id": "6880397b-3624-4dc9-8e62-00140a1e60f5", + "location": "San Jose", + "latitude": null, + "longitude": null, + "map_zoom": "13", + "modified": "2025-07-23 07:10:35", + "name": "Festival Wristband Event", + "online_only": false, + "activity_producer_id": null, + "organization_id": "64ad9d19-1bd0-490f-b332-7c9f0ad1e024", + "partner_id": "64ac69a6-a344-4e05-bbc7-64670ad1e030", + "postal_code": "", + "privacy_type": "0", + "region": null, + "slug": "festival-wristband-event", + "start": "2026-05-01 18:00:00", + "start_utc": "2026-05-02 01:00:00", + "state": "CA", + "tickets_active": true, + "timezone": "America/Los_Angeles", + "website": "", + "event_topic_id": "c2fc3d42-c85f-4ecf-a0df-19d0a8659353", + "organization_name": "Voyeur DC", + "scheduled_publish_datetime_utc": null, + "event_topic": "Festival", + "category": "Festival", + "event_url": "https://grindr.ticketsauce.com/e/festival-wristband-event", + "tickets_url": "https://grindr.ticketsauce.com/e/festival-wristband-event/tickets", + "display_times": true, + "order_count": 1, + "partner_name": "Grindr Demo" + }, + "Logo": { + "url": "https://res.cloudinary.com/eventservice/image/upload/q_auto,f_auto/v1753233876/saas/logos/image_1753233797906_s3hyoqr1m.webp", + "created": "2025-07-23 01:24:38" + }, + "Masthead": { + "url": null, + "created": null + } + } +``` + +get-orders +Prompt +Get a list of orders from the specified event. + +-When you come up for the description for this component following format: . [See documentation](https://speca.io/ticketsauce/ticketsauce-public-api?key=204000d6bda66da78315e721920f43aa#orders) +-for the prop related to event_id (path parameter) use async options so users can select an event. +-as referece examples for async options you can use those found in apps zendesk, guru, etsy and recently you helped me come up with async options for prop imageId in generate-motion.mjs of leonardo ai app. +-when returning the context object, if there are no more options to return, simply return an empty object {} +-here is the response example for "list events" endpoint for you to come up with logic on how to implement async options for the prop related to event_id +``` +[ + { + "Event": { + "active": true, + "address": "1221 Saint James Street", + "address2": "", + "city": "Philadelphia", + "country": "United States", + "created": "2025-06-26 02:40:59", + "custom_id": null, + "show_start": true, + "show_end": false, + "end": "2029-03-01 23:45:00", + "end_utc": "2029-03-02 04:45:00", + "featured": false, + "id": "685cb33b-0dc8-462d-ae5b-00410a1e60d3", + "location": "Voyeur Nightclub", + "latitude": "39.948357", + "longitude": "-75.161697", + "map_zoom": "13", + "modified": "2025-09-16 22:08:06", + "name": "Badge Conference Event TEST", + "online_only": false, + "activity_producer_id": null, + "organization_id": "64ad9d19-1bd0-490f-b332-7c9f0ad1e024", + "partner_id": "64ac69a6-a344-4e05-bbc7-64670ad1e030", + "postal_code": "19107", + "privacy_type": "0", + "region": null, + "slug": "badge-conference-event-test", + "start": "2029-03-01 23:30:00", + "start_utc": "2029-03-02 04:30:00", + "state": "PA", + "tickets_active": true, + "timezone": "America/New_York", + "website": "", + "event_topic_id": "589e8222-c4f8-4794-bde7-73d40a004b01", + "organization_name": "Voyeur DC", + "scheduled_publish_datetime_utc": null, + "event_topic": "Business", + "category": "Business", + "event_url": "https://grindr.ticketsauce.com/e/badge-conference-event-test", + "tickets_url": "https://grindr.ticketsauce.com/e/badge-conference-event-test/tickets", + "display_times": true, + "order_count": 4, + "partner_name": "Grindr Demo" + }, + "Logo": { + "url": "https://res.cloudinary.com/eventservice/image/upload/q_auto,f_auto/v1751769059/saas/logos/image_1751769042730_r9qr7df7d.webp", + "created": "2025-06-26 03:04:39" + }, + "Masthead": { + "url": null, + "created": null + } + }, + { + "Event": { + "active": true, + "address": "", + "address2": "", + "city": "San Jose", + "country": "United States", + "created": "2025-07-23 01:23:07", + "custom_id": null, + "show_start": true, + "show_end": false, + "end": "2026-05-03 23:00:00", + "end_utc": "2026-05-04 06:00:00", + "featured": false, + "id": "6880397b-3624-4dc9-8e62-00140a1e60f5", + "location": "San Jose", + "latitude": null, + "longitude": null, + "map_zoom": "13", + "modified": "2025-07-23 07:10:35", + "name": "Festival Wristband Event", + "online_only": false, + "activity_producer_id": null, + "organization_id": "64ad9d19-1bd0-490f-b332-7c9f0ad1e024", + "partner_id": "64ac69a6-a344-4e05-bbc7-64670ad1e030", + "postal_code": "", + "privacy_type": "0", + "region": null, + "slug": "festival-wristband-event", + "start": "2026-05-01 18:00:00", + "start_utc": "2026-05-02 01:00:00", + "state": "CA", + "tickets_active": true, + "timezone": "America/Los_Angeles", + "website": "", + "event_topic_id": "c2fc3d42-c85f-4ecf-a0df-19d0a8659353", + "organization_name": "Voyeur DC", + "scheduled_publish_datetime_utc": null, + "event_topic": "Festival", + "category": "Festival", + "event_url": "https://grindr.ticketsauce.com/e/festival-wristband-event", + "tickets_url": "https://grindr.ticketsauce.com/e/festival-wristband-event/tickets", + "display_times": true, + "order_count": 1, + "partner_name": "Grindr Demo" + }, + "Logo": { + "url": "https://res.cloudinary.com/eventservice/image/upload/q_auto,f_auto/v1753233876/saas/logos/image_1753233797906_s3hyoqr1m.webp", + "created": "2025-07-23 01:24:38" + }, + "Masthead": { + "url": null, + "created": null + } + } +``` +- Here are the parameters for the related get orders API endpoint, use as a basis for props: +per_page +integer optional +How many results to retrieve (per page). Max 500. +Default: +100 + +page +integer optional +Which page to return. For example, if per_page is 20, and page is 3, the results would show 41-60. +Default: +1 + +q +string optional +Exact email address or last name attached to an order. + +return_questionnaires +boolean optional +Whether or not to return the question responses from questionnaires (will include attendee responses as well IF tickets are returned) +Default: +false + +return_tickets +boolean optional +Whether or not to return the tickets for each order as well. +Default: +false + +return_line_item_fees +boolean optional +Whether or not to return the itemized line item fees for each order (if they exist). +Default: +false + +ordered_after +string optional +Only retrieve orders that were ordered AFTER the specified date/time (format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS). + +ordered_before +string optional +Only retrieve orders that were ordered BEFORE the specified date/time (format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS). + +ordered_phrase +string optional +A string representing the date to pull orders created ___. Possible values are: today, yesterday, tomorrow, this_week, this_weekend, next_week, next_weekend, this_month, next_month + +modified_after +string optional +Only retrieve orders that were modified AFTER the specified date/time (format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS). + +modified_before +string optional +Only retrieve orders that were modified BEFORE the specified date/time (format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS). + +sort_by +string optional +Which field to sort by. By default (‘date’), this will sort orders by their ordered date. Or ‘name’ to order by last name. +Default: +'date' + +sort_dir +string optional +Which direction you’d like to sort - either ascending (‘asc’ - the default) or descending (‘desc’). +Default: +'asc' +total_above + +number optional +Return only orders who’s order total is greater than this value. +Default: +0 + +total_below +string optional +Return only orders who’s order total is lesss than this value. + +promo_used_only +boolean optional +If set to true, this will return only orders who used a promo code. +Default: +false +``` + +get-order-details +Get details for the specified order. +-When you come up for the description for this component following format: . [See documentation](https://speca.io/ticketsauce/ticketsauce-public-api?key=204000d6bda66da78315e721920f43aa#order-details) +- Here are the parameters for the related get order details API endpoint, use as a basis for props: +order_id +path parameter, string required +-add an additional prop related to event_id and use async options so users can select an event. +-as referece examples for async options you can use those found in apps zendesk, guru, etsy and recently you helped me come up with async options for prop imageId in generate-motion.mjs of leonardo ai app. +-when returning the context object, if there are no more options to return, simply return an empty object {} +-here is the response example for "list events" endpoint for you to come up with logic on how to implement async options for the prop related to id_or_slug +``` +[ + { + "Event": { + "active": true, + "address": "1221 Saint James Street", + "address2": "", + "city": "Philadelphia", + "country": "United States", + "created": "2025-06-26 02:40:59", + "custom_id": null, + "show_start": true, + "show_end": false, + "end": "2029-03-01 23:45:00", + "end_utc": "2029-03-02 04:45:00", + "featured": false, + "id": "685cb33b-0dc8-462d-ae5b-00410a1e60d3", + "location": "Voyeur Nightclub", + "latitude": "39.948357", + "longitude": "-75.161697", + "map_zoom": "13", + "modified": "2025-09-16 22:08:06", + "name": "Badge Conference Event TEST", + "online_only": false, + "activity_producer_id": null, + "organization_id": "64ad9d19-1bd0-490f-b332-7c9f0ad1e024", + "partner_id": "64ac69a6-a344-4e05-bbc7-64670ad1e030", + "postal_code": "19107", + "privacy_type": "0", + "region": null, + "slug": "badge-conference-event-test", + "start": "2029-03-01 23:30:00", + "start_utc": "2029-03-02 04:30:00", + "state": "PA", + "tickets_active": true, + "timezone": "America/New_York", + "website": "", + "event_topic_id": "589e8222-c4f8-4794-bde7-73d40a004b01", + "organization_name": "Voyeur DC", + "scheduled_publish_datetime_utc": null, + "event_topic": "Business", + "category": "Business", + "event_url": "https://grindr.ticketsauce.com/e/badge-conference-event-test", + "tickets_url": "https://grindr.ticketsauce.com/e/badge-conference-event-test/tickets", + "display_times": true, + "order_count": 4, + "partner_name": "Grindr Demo" + }, + "Logo": { + "url": "https://res.cloudinary.com/eventservice/image/upload/q_auto,f_auto/v1751769059/saas/logos/image_1751769042730_r9qr7df7d.webp", + "created": "2025-06-26 03:04:39" + }, + "Masthead": { + "url": null, + "created": null + } + }, + { + "Event": { + "active": true, + "address": "", + "address2": "", + "city": "San Jose", + "country": "United States", + "created": "2025-07-23 01:23:07", + "custom_id": null, + "show_start": true, + "show_end": false, + "end": "2026-05-03 23:00:00", + "end_utc": "2026-05-04 06:00:00", + "featured": false, + "id": "6880397b-3624-4dc9-8e62-00140a1e60f5", + "location": "San Jose", + "latitude": null, + "longitude": null, + "map_zoom": "13", + "modified": "2025-07-23 07:10:35", + "name": "Festival Wristband Event", + "online_only": false, + "activity_producer_id": null, + "organization_id": "64ad9d19-1bd0-490f-b332-7c9f0ad1e024", + "partner_id": "64ac69a6-a344-4e05-bbc7-64670ad1e030", + "postal_code": "", + "privacy_type": "0", + "region": null, + "slug": "festival-wristband-event", + "start": "2026-05-01 18:00:00", + "start_utc": "2026-05-02 01:00:00", + "state": "CA", + "tickets_active": true, + "timezone": "America/Los_Angeles", + "website": "", + "event_topic_id": "c2fc3d42-c85f-4ecf-a0df-19d0a8659353", + "organization_name": "Voyeur DC", + "scheduled_publish_datetime_utc": null, + "event_topic": "Festival", + "category": "Festival", + "event_url": "https://grindr.ticketsauce.com/e/festival-wristband-event", + "tickets_url": "https://grindr.ticketsauce.com/e/festival-wristband-event/tickets", + "display_times": true, + "order_count": 1, + "partner_name": "Grindr Demo" + }, + "Logo": { + "url": "https://res.cloudinary.com/eventservice/image/upload/q_auto,f_auto/v1753233876/saas/logos/image_1753233797906_s3hyoqr1m.webp", + "created": "2025-07-23 01:24:38" + }, + "Masthead": { + "url": null, + "created": null + } + } +``` +- with the user selection of event_id you will dynamically populate async options for the order_id prop. You can reference the Google Sheets app, delete rows action, where Worksheet ID prop is dynamically populated based off the Spreadsheet ID selecfed by the user. +-here is the response example for "get orders" endpoint for you to come up with logic on how to implement async options for the prop related to order_id +``` +[{"Order":{"id":"68803b8b-d290-4476-bed7-00120a1e6305","status":"1","last_name":"Lawrence","first_name":"Reid","dob":null,"email":"gmreid@gmail.com","phone":"(999) 888-5555","title":null,"company":null,"address":null,"address2":null,"city":"Philly","state":"PA","postal_code":null,"country":"US","opted_in":false,"opted_in_sms":false,"subtotal":"0.00","total_paid":"0.00","refund_amount":"0.00","taxes":"0.00","contributions":"0.00","service_charges":"0.00","cc_fees":"0.00","admin_charges":"0.00","custom_line_item_fees":"0.00","policy_total":"0.00","policy_refunded":"0.00","ticket_count":"4","promo_code_amount":"0.00","promo_code":null,"promo_code_id":null,"purchase_location":"online","paid_date":"2025-07-22 18:31:55","paid_date_utc":"2025-07-23 01:31:55","affiliate_code":null,"event_id":"6880397b-3624-4dc9-8e62-00140a1e60f5","modified":"2025-07-23 01:31:55","delivery_method":"email","affiliate_code_id":null,"affiliate_code_name":null,"promoter_id":null,"promoter_name":null}}] +``` + +get-ticket-checkin-ids +Prompt +Get a list of ticket check-in IDs from the specified event. +-When you come up for the description for this component following format: . [See documentation](https://speca.io/ticketsauce/ticketsauce-public-api?key=204000d6bda66da78315e721920f43aa#ticket-checkin-ids) +- Here are the parameters for the related API endpoint, use as a basis for props: +``` +Path parameters +event_id +string required +ID of event + +query string parameters +per_page +integer optional +How many results to retrieve (per page). Max 5000. + +page +integer optional +Which page to return. For example, if per_page is 20, and page is 3, the results would show 41-60. +Default: +1 +``` +-for the prop related to id_or_slug use async options so users can select an event. +-as reference examples for async options you can use those found in apps zendesk, guru, etsy and recently you helped me come up with async options for prop imageId in generate-motion.mjs of leonardo ai app. +-when returning the context object, if there are no more options to return, simply return an empty object {} +-here is the response example for "list events" endpoint for you to come up with logic on how to implement async options for the prop related to id_or_slug +``` +[ + { + "Event": { + "active": true, + "address": "1221 Saint James Street", + "address2": "", + "city": "Philadelphia", + "country": "United States", + "created": "2025-06-26 02:40:59", + "custom_id": null, + "show_start": true, + "show_end": false, + "end": "2029-03-01 23:45:00", + "end_utc": "2029-03-02 04:45:00", + "featured": false, + "id": "685cb33b-0dc8-462d-ae5b-00410a1e60d3", + "location": "Voyeur Nightclub", + "latitude": "39.948357", + "longitude": "-75.161697", + "map_zoom": "13", + "modified": "2025-09-16 22:08:06", + "name": "Badge Conference Event TEST", + "online_only": false, + "activity_producer_id": null, + "organization_id": "64ad9d19-1bd0-490f-b332-7c9f0ad1e024", + "partner_id": "64ac69a6-a344-4e05-bbc7-64670ad1e030", + "postal_code": "19107", + "privacy_type": "0", + "region": null, + "slug": "badge-conference-event-test", + "start": "2029-03-01 23:30:00", + "start_utc": "2029-03-02 04:30:00", + "state": "PA", + "tickets_active": true, + "timezone": "America/New_York", + "website": "", + "event_topic_id": "589e8222-c4f8-4794-bde7-73d40a004b01", + "organization_name": "Voyeur DC", + "scheduled_publish_datetime_utc": null, + "event_topic": "Business", + "category": "Business", + "event_url": "https://grindr.ticketsauce.com/e/badge-conference-event-test", + "tickets_url": "https://grindr.ticketsauce.com/e/badge-conference-event-test/tickets", + "display_times": true, + "order_count": 4, + "partner_name": "Grindr Demo" + }, + "Logo": { + "url": "https://res.cloudinary.com/eventservice/image/upload/q_auto,f_auto/v1751769059/saas/logos/image_1751769042730_r9qr7df7d.webp", + "created": "2025-06-26 03:04:39" + }, + "Masthead": { + "url": null, + "created": null + } + }, + { + "Event": { + "active": true, + "address": "", + "address2": "", + "city": "San Jose", + "country": "United States", + "created": "2025-07-23 01:23:07", + "custom_id": null, + "show_start": true, + "show_end": false, + "end": "2026-05-03 23:00:00", + "end_utc": "2026-05-04 06:00:00", + "featured": false, + "id": "6880397b-3624-4dc9-8e62-00140a1e60f5", + "location": "San Jose", + "latitude": null, + "longitude": null, + "map_zoom": "13", + "modified": "2025-07-23 07:10:35", + "name": "Festival Wristband Event", + "online_only": false, + "activity_producer_id": null, + "organization_id": "64ad9d19-1bd0-490f-b332-7c9f0ad1e024", + "partner_id": "64ac69a6-a344-4e05-bbc7-64670ad1e030", + "postal_code": "", + "privacy_type": "0", + "region": null, + "slug": "festival-wristband-event", + "start": "2026-05-01 18:00:00", + "start_utc": "2026-05-02 01:00:00", + "state": "CA", + "tickets_active": true, + "timezone": "America/Los_Angeles", + "website": "", + "event_topic_id": "c2fc3d42-c85f-4ecf-a0df-19d0a8659353", + "organization_name": "Voyeur DC", + "scheduled_publish_datetime_utc": null, + "event_topic": "Festival", + "category": "Festival", + "event_url": "https://grindr.ticketsauce.com/e/festival-wristband-event", + "tickets_url": "https://grindr.ticketsauce.com/e/festival-wristband-event/tickets", + "display_times": true, + "order_count": 1, + "partner_name": "Grindr Demo" + }, + "Logo": { + "url": "https://res.cloudinary.com/eventservice/image/upload/q_auto,f_auto/v1753233876/saas/logos/image_1753233797906_s3hyoqr1m.webp", + "created": "2025-07-23 01:24:38" + }, + "Masthead": { + "url": null, + "created": null + } + } +``` + diff --git a/mdc_memory.mdc b/mdc_memory.mdc new file mode 100644 index 0000000000000..4f9d68a894b8a --- /dev/null +++ b/mdc_memory.mdc @@ -0,0 +1 @@ +Components should use wrapper methods in the app file for API requests rather than calling the app's private makeRequest directly. Avoid manual truthiness checks for optional parameters, as @pipedream/platform utilities (@pipedream/axios) automatically exclude undefined values. For file reading, use getFileStreamAndMetadata from @pipedream/platform. \ No newline at end of file diff --git a/mdc_pipedream-context.mdc b/mdc_pipedream-context.mdc new file mode 100644 index 0000000000000..4a89f2cbf16f6 --- /dev/null +++ b/mdc_pipedream-context.mdc @@ -0,0 +1,32 @@ +--- +alwaysApply: true +--- +We work on Pipedream components (API reference: https://pipedream.com/docs/components/contributing/api/ ). From our working folder, we focus on the 'components' folder, where we have a list of apps, and each app (e.g. 'google_sheets') may have several components. Here are some guidelines we've assembled over previous sessions: + +# Pipedream Component Development Guide + +## Best Practices +1. **File Structure** + - App file (`app.mjs`) contains shared logic, auth, and propDefinitions + - Actions in `actions/[action-name]/[action-name].mjs` + - Sources in `sources/[source-name]/[source-name].mjs` + - Common code in `common/` directories + +2. **Naming Conventions** + - Folder names match component keys (e.g., `add-person-to-cadence`) + - Component keys follow pattern: `[app-name]-[component-name]` + - File names match folder names + +3. **Code Patterns** + - Use `@pipedream/platform`'s axios (no need to extract .data) + - Because `@pipedream/platform`'s axios already filters out undefined values, no need to check parameters individually before including them + - Use `ConfigurationError` from `@pipedream/platform` for user-facing errors + - Include documentation links in component descriptions + - Use propDefinitions in app file for reusable props with dynamic options + +4. **Sources (Webhooks)** + - Create common webhook functionality in `sources/common/webhook.mjs` + - Implement `activate()` and `deactivate()` hooks for webhook management + - Use `$.service.db` for storing webhook IDs + - Set `dedupe: "unique"` for webhook sources + - Include proper event type and summary methods diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fdd0c9e7898fc..a2117c07459a1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -104,7 +104,7 @@ importers: version: 4.0.0 ts-jest: specifier: ^29.1.1 - version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.6.3)))(typescript@5.6.3) + version: 29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.6.3)))(typescript@5.6.3) tsc-esm-fix: specifier: ^2.18.0 version: 2.20.27 @@ -157,7 +157,11 @@ importers: specifier: ^4.0.1 version: 4.0.1 - components/_302_ai: {} + components/_302_ai: + dependencies: + '@pipedream/platform': + specifier: ^3.1.0 + version: 3.1.0 components/_360nrs: dependencies: @@ -629,8 +633,7 @@ importers: specifier: ^3.1.0 version: 3.1.0 - components/airweave: - specifiers: {} + components/airweave: {} components/aitable_ai: dependencies: @@ -2679,8 +2682,7 @@ importers: specifier: ^3.0.1 version: 3.0.1(web-streams-polyfill@3.3.3) - components/clarifai: - specifiers: {} + components/clarifai: {} components/clarify: {} @@ -2998,8 +3000,7 @@ importers: components/codeberg: {} - components/codefresh: - specifiers: {} + components/codefresh: {} components/codegpt: {} @@ -3112,8 +3113,7 @@ importers: specifier: ^0.0.6 version: 0.0.6 - components/cometapi: - specifiers: {} + components/cometapi: {} components/cometly: dependencies: @@ -6588,8 +6588,7 @@ importers: specifier: ^3.0.3 version: 3.0.3 - components/hex: - specifiers: {} + components/hex: {} components/heygen: dependencies: @@ -10912,8 +10911,7 @@ importers: specifier: ^1.3.0 version: 1.6.6 - components/piwik_pro: - specifiers: {} + components/piwik_pro: {} components/pixelbin: dependencies: @@ -16961,7 +16959,7 @@ importers: version: 3.1.7 ts-jest: specifier: ^29.2.5 - version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.24.2)(jest@29.7.0(@types/node@20.17.30)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.30)(typescript@5.7.2)))(typescript@5.7.2) + version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.30)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.30)(typescript@5.7.2)))(typescript@5.7.2) tsup: specifier: ^8.3.6 version: 8.3.6(@microsoft/api-extractor@7.47.12(@types/node@20.17.30))(jiti@2.4.2)(postcss@8.5.6)(tsx@4.19.4)(typescript@5.7.2)(yaml@2.8.0) @@ -28331,6 +28329,7 @@ packages: mailsplit@5.4.0: resolution: {integrity: sha512-wnYxX5D5qymGIPYLwnp6h8n1+6P6vz/MJn5AzGjZ8pwICWssL+CCQjWBIToOVHASmATot4ktvlLo6CyLfOXWYA==} + deprecated: This package has been renamed to @zone-eu/mailsplit. Please update your dependencies. make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} @@ -35785,7 +35784,7 @@ snapshots: '@babel/traverse': 7.25.9 '@babel/types': 7.26.0 convert-source-map: 2.0.0 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7(supports-color@9.4.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -36056,21 +36055,45 @@ snapshots: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -36081,16 +36104,34 @@ snapshots: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -36101,41 +36142,89 @@ snapshots: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@8.0.0-alpha.13)': + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/helper-plugin-utils': 7.25.9 + optional: true + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -37198,7 +37287,7 @@ snapshots: '@eslint/eslintrc@3.2.0': dependencies: ajv: 6.12.6 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7(supports-color@9.4.0) espree: 10.3.0 globals: 14.0.0 ignore: 5.3.2 @@ -39704,6 +39793,8 @@ snapshots: '@putout/operator-filesystem': 5.0.0(putout@36.13.1(eslint@8.57.1)(typescript@5.6.3)) '@putout/operator-json': 2.2.0 putout: 36.13.1(eslint@8.57.1)(typescript@5.6.3) + transitivePeerDependencies: + - supports-color '@putout/operator-regexp@1.0.0(putout@36.13.1(eslint@8.57.1)(typescript@5.6.3))': dependencies: @@ -42264,7 +42355,7 @@ snapshots: '@typescript-eslint/types': 8.15.0 '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3) '@typescript-eslint/visitor-keys': 8.15.0 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7(supports-color@9.4.0) eslint: 8.57.1 optionalDependencies: typescript: 5.6.3 @@ -43158,6 +43249,20 @@ snapshots: transitivePeerDependencies: - supports-color + babel-jest@29.7.0(@babel/core@8.0.0-alpha.13): + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@8.0.0-alpha.13) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + optional: true + babel-plugin-istanbul@6.1.1: dependencies: '@babel/helper-plugin-utils': 7.25.9 @@ -43224,12 +43329,39 @@ snapshots: '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.0) '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.0) + babel-preset-current-node-syntax@1.1.0(@babel/core@8.0.0-alpha.13): + dependencies: + '@babel/core': 8.0.0-alpha.13 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@8.0.0-alpha.13) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@8.0.0-alpha.13) + optional: true + babel-preset-jest@29.6.3(@babel/core@7.26.0): dependencies: '@babel/core': 7.26.0 babel-plugin-jest-hoist: 29.6.3 babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) + babel-preset-jest@29.6.3(@babel/core@8.0.0-alpha.13): + dependencies: + '@babel/core': 8.0.0-alpha.13 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@8.0.0-alpha.13) + optional: true + backoff@2.5.0: dependencies: precond: 0.2.3 @@ -45438,7 +45570,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7(supports-color@9.4.0) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -47299,7 +47431,7 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7(supports-color@9.4.0) transitivePeerDependencies: - supports-color @@ -49880,7 +50012,7 @@ snapshots: dependencies: '@tediousjs/connection-string': 0.5.0 commander: 11.1.0 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7(supports-color@9.4.0) rfdc: 1.4.1 tarn: 3.0.2 tedious: 16.7.1 @@ -51629,7 +51761,7 @@ snapshots: ajv: 8.17.1 chalk: 5.3.0 ci-info: 4.1.0 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7(supports-color@9.4.0) deepmerge: 4.3.1 escalade: 3.2.0 fast-glob: 3.3.2 @@ -53765,7 +53897,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(esbuild@0.24.2)(jest@29.7.0(@types/node@20.17.30)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.30)(typescript@5.7.2)))(typescript@5.7.2): + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.30)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.30)(typescript@5.7.2)))(typescript@5.7.2): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 @@ -53783,9 +53915,8 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.26.0) - esbuild: 0.24.2 - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.6.3)))(typescript@5.6.3): + ts-jest@29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.17.6)(typescript@5.6.3)))(typescript@5.6.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 @@ -53799,10 +53930,10 @@ snapshots: typescript: 5.6.3 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 7.26.0 + '@babel/core': 8.0.0-alpha.13 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.26.0) + babel-jest: 29.7.0(@babel/core@8.0.0-alpha.13) ts-node@10.9.2(@types/node@20.17.30)(typescript@5.7.2): dependencies: @@ -53974,7 +54105,7 @@ snapshots: cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.0 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7(supports-color@9.4.0) esbuild: 0.24.2 joycon: 3.1.1 picocolors: 1.1.1 @@ -54002,7 +54133,7 @@ snapshots: cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.0 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7(supports-color@9.4.0) esbuild: 0.24.2 joycon: 3.1.1 picocolors: 1.1.1 @@ -54626,7 +54757,7 @@ snapshots: '@volar/typescript': 2.4.10 '@vue/language-core': 2.1.6(typescript@5.9.2) compare-versions: 6.1.1 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.3.7(supports-color@9.4.0) kolorist: 1.8.0 local-pkg: 0.5.1 magic-string: 0.30.13