migrate n8n integration (#3004)

This commit is contained in:
LawyZheng
2025-07-22 02:03:19 +08:00
committed by GitHub
parent e7a2816470
commit 5f5bae5347
23 changed files with 4 additions and 12920 deletions

1
integrations/n8n Submodule

Submodule integrations/n8n added at c14752f27a

View File

@@ -1,20 +0,0 @@
root = true
[*]
charset = utf-8
indent_style = tab
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[package.json]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
[*.yml]
indent_style = space
indent_size = 2

View File

@@ -1,63 +0,0 @@
/**
* @type {import('@types/eslint').ESLint.ConfigData}
*/
module.exports = {
root: true,
env: {
browser: true,
es6: true,
node: true,
},
parser: "@typescript-eslint/parser",
parserOptions: {
project: ["./tsconfig.json"],
sourceType: "module",
extraFileExtensions: [".json"],
},
ignorePatterns: [
".eslintrc.js",
"**/*.js",
"**/node_modules/**",
"**/dist/**",
],
overrides: [
{
files: ["package.json"],
plugins: ["eslint-plugin-n8n-nodes-base"],
extends: ["plugin:n8n-nodes-base/community"],
rules: {
"n8n-nodes-base/community-package-json-name-still-default": "off",
},
},
{
files: ["./credentials/**/*.ts"],
plugins: ["eslint-plugin-n8n-nodes-base"],
extends: ["plugin:n8n-nodes-base/credentials"],
rules: {
"n8n-nodes-base/cred-class-field-documentation-url-missing": "off",
"n8n-nodes-base/cred-class-field-documentation-url-miscased": "off",
},
},
{
files: ["./nodes/**/*.ts"],
plugins: ["eslint-plugin-n8n-nodes-base"],
extends: ["plugin:n8n-nodes-base/nodes"],
rules: {
"n8n-nodes-base/node-execute-block-missing-continue-on-fail": "off",
"n8n-nodes-base/node-resource-description-filename-against-convention":
"off",
"n8n-nodes-base/node-param-fixed-collection-type-unsorted-items": "off",
"n8n-nodes-base/node-class-description-inputs-wrong-regular-node":
"off",
"n8n-nodes-base/node-class-description-outputs-wrong": "off",
"n8n-nodes-base/node-param-description-wrong-for-dynamic-options":
"off",
},
},
],
};

View File

@@ -1,16 +0,0 @@
/**
* @type {import('@types/eslint').ESLint.ConfigData}
*/
module.exports = {
extends: "./.eslintrc.js",
overrides: [
{
files: ["package.json"],
plugins: ["eslint-plugin-n8n-nodes-base"],
rules: {
"n8n-nodes-base/community-package-json-name-still-default": "error",
},
},
],
};

View File

@@ -1,8 +0,0 @@
node_modules
.DS_Store
.tmp
tmp
dist
npm-debug.log*
yarn.lock
.vscode/launch.json

View File

@@ -1,4 +0,0 @@
.DS_Store
*.tsbuildinfo
node_modules/
dist/

View File

@@ -1,51 +0,0 @@
module.exports = {
/**
* https://prettier.io/docs/en/options.html#semicolons
*/
semi: true,
/**
* https://prettier.io/docs/en/options.html#trailing-commas
*/
trailingComma: "all",
/**
* https://prettier.io/docs/en/options.html#bracket-spacing
*/
bracketSpacing: true,
/**
* https://prettier.io/docs/en/options.html#tabs
*/
useTabs: true,
/**
* https://prettier.io/docs/en/options.html#tab-width
*/
tabWidth: 2,
/**
* https://prettier.io/docs/en/options.html#arrow-function-parentheses
*/
arrowParens: "always",
/**
* https://prettier.io/docs/en/options.html#quotes
*/
singleQuote: true,
/**
* https://prettier.io/docs/en/options.html#quote-props
*/
quoteProps: "as-needed",
/**
* https://prettier.io/docs/en/options.html#end-of-line
*/
endOfLine: "lf",
/**
* https://prettier.io/docs/en/options.html#print-width
*/
printWidth: 100,
};

View File

@@ -1,89 +0,0 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Contributor Covenant Code of Conduct](#contributor-covenant-code-of-conduct)
- [Our Pledge](#our-pledge)
- [Our Standards](#our-standards)
- [Our Responsibilities](#our-responsibilities)
- [Scope](#scope)
- [Enforcement](#enforcement)
- [Attribution](#attribution)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at jan@n8n.io. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@@ -1,19 +0,0 @@
Copyright 2022 n8n
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,45 +0,0 @@
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [n8n-nodes-skyvern](#n8n-nodes-skyvern)
- [Installation](#installation)
- [Operations](#operations)
- [Credentials](#credentials)
- [Resources](#resources)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
# n8n-nodes-skyvern
This is an n8n community node. It lets you use [Skyvern](https://www.skyvern.com/) in your n8n workflows.
[Skyvern](https://www.skyvern.com/) is an [open-source](https://github.com/Skyvern-AI/skyvern) product. It automates browser-based workflows using LLMs and computer vision. It provides a simple API endpoint to fully automate manual workflows on a large number of websites, replacing brittle or unreliable automation solutions.
[n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.
[Installation](#installation)
[Operations](#operations)
[Credentials](#credentials)
[Resources](#resources)
## Installation
Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.
## Operations
- Task: interact with Skyvern task
- Workflow: interact with Skyvern workflow
## Credentials
- API Token: Skyvern API token. You can get it from the Skyvern UI
- Base URL: The endpoint for your Skyvern service. Default is Skyvern Cloud Service, you can also set it to your self-host Skyvern.
## Resources
* [n8n community nodes documentation](https://docs.n8n.io/integrations/community-nodes/)
* [Skyvern documentation](https://docs.skyvern.com/introduction)
* [n8n integration code](https://github.com/Skyvern-AI/skyvern/tree/main/integrations/n8n)

View File

@@ -1,45 +0,0 @@
import {
IAuthenticateGeneric,
ICredentialTestRequest,
ICredentialType,
INodeProperties,
} from 'n8n-workflow';
export class SkyvernApi implements ICredentialType {
name = 'skyvernApi';
displayName = 'Skyvern API';
// Uses the link to this tutorial as an example
// Replace with your own docs links when building your own nodes
documentationUrl = 'https://docs.skyvern.ai/';
properties: INodeProperties[] = [
{
displayName: 'API Key',
name: 'apiKey',
type: 'string',
typeOptions: { password: true },
default: '',
},
{
displayName: 'Base URL',
name: 'baseUrl',
type: 'string',
default: 'https://api.skyvern.com',
placeholder: 'https://api.skyvern.com',
},
];
authenticate: IAuthenticateGeneric = {
type: 'generic',
properties: {
headers: {
'x-api-key': '={{$credentials.apiKey}}',
'Content-Type': 'application/json',
}
},
};
test: ICredentialTestRequest = {
request: {
baseURL: '={{$credentials?.baseUrl}}',
url: '/api/v1/organizations',
},
};
}

View File

@@ -1,16 +0,0 @@
const path = require("path");
const { task, src, dest } = require("gulp");
task("build:icons", copyIcons);
function copyIcons() {
const nodeSource = path.resolve("nodes", "**", "*.{png,svg}");
const nodeDestination = path.resolve("dist", "nodes");
src(nodeSource).pipe(dest(nodeDestination));
const credSource = path.resolve("credentials", "**", "*.{png,svg}");
const credDestination = path.resolve("dist", "credentials");
return src(credSource).pipe(dest(credDestination));
}

View File

@@ -1,21 +0,0 @@
{
"node": "n8n-nodes-skyvern",
"nodeVersion": "1.0",
"codexVersion": "1.0",
"categories": [
"Miscellaneous",
"Utility"
],
"resources": {
"credentialDocumentation": [
{
"url": ""
}
],
"primaryDocumentation": [
{
"url": ""
}
]
}
}

View File

@@ -1,508 +0,0 @@
import {
FieldType,
IDataObject,
IExecuteSingleFunctions,
IHttpRequestMethods,
IHttpRequestOptions,
ILoadOptionsFunctions,
INodePropertyOptions,
INodeType,
INodeTypeDescription,
NodeConnectionType,
ResourceMapperField,
ResourceMapperFields,
} from 'n8n-workflow';
async function skyvernApiRequest(
this: IExecuteSingleFunctions | ILoadOptionsFunctions,
method: IHttpRequestMethods,
endpoint: string,
body: IDataObject | undefined = undefined,
): Promise<any> {
const credentials = await this.getCredentials('skyvernApi');
const options: IHttpRequestOptions = {
baseURL: credentials.baseUrl as string,
method,
url: endpoint,
body,
json: true,
};
return this.helpers.requestWithAuthentication.call(this, 'skyvernApi', options);
}
export class Skyvern implements INodeType {
description: INodeTypeDescription = {
displayName: 'Skyvern',
name: 'skyvern',
icon: 'file:skyvern.svg',
group: ['transform'],
description: 'Node to interact with Skyvern',
defaults: {
name: 'Skyvern',
},
inputs: [NodeConnectionType.Main],
outputs: [NodeConnectionType.Main],
credentials: [
{
name: 'skyvernApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Task',
value: 'task',
},
{
name: 'Workflow',
value: 'workflow',
},
],
default: 'task',
},
// Task Operations
{
displayName: 'Operation',
name: 'taskOperation',
type: 'options',
noDataExpression: true,
required: true,
default: 'dispatchTask',
displayOptions: {
show: {
resource: ['task'],
},
},
options: [
{
name: 'Dispatch a Task',
value: 'dispatchTask',
action: 'Dispatch a task to execute asynchronously',
description: 'Dispatch a task to execute asynchronously',
},
{
name: 'Get a Task',
value: 'getTask',
action: 'Get a task by ID',
description: 'Get a task by ID',
},
],
routing: {
request: {
baseURL: '={{$credentials.baseUrl}}',
method: '={{ $value === "dispatchTask" ? "POST" : "GET" }}' as IHttpRequestMethods,
url: '={{"/v1/run/tasks"}}',
},
send: {
preSend: [
async function (
this: IExecuteSingleFunctions,
requestOptions: IHttpRequestOptions,
): Promise<IHttpRequestOptions> {
const taskOperation = this.getNodeParameter('taskOperation');
if (taskOperation === "getTask") return requestOptions;
const taskOptions = this.getNodeParameter('taskOptions') as IDataObject;
const legacy_engine = taskOptions['engine'] as string | null;
if (legacy_engine === 'v1') {
(requestOptions.body as IDataObject)['engine'] = 'skyvern-1.0';
} else if (legacy_engine === 'v2') {
(requestOptions.body as IDataObject)['engine'] = 'skyvern-2.0';
}
return requestOptions;
},
],
},
},
},
// Workflow Operations
{
displayName: 'Operation',
name: 'workflowOperation',
type: 'options',
noDataExpression: true,
required: true,
default: 'getWorkflow',
displayOptions: {
show: {
resource: ['workflow'],
},
},
options: [
{
name: 'Get a Workflow Run',
value: 'getWorkflow',
action: 'Get a workflow run by ID',
description: 'Get a workflow run by ID',
},
{
name: 'Dispatch a Workflow Run',
value: 'dispatchWorkflow',
action: 'Dispatch a workflow run to execute asynchronously',
description: 'Dispatch a workflow run to execute asynchronously',
},
],
routing: {
request: {
baseURL: '={{$credentials.baseUrl}}',
method: '={{ $value === "dispatchWorkflow" ? "POST" : "GET" }}' as IHttpRequestMethods,
},
},
},
{
displayName: 'User Prompt',
description: 'The prompt for Skyvern to execute',
name: 'userPrompt',
type: 'string',
required: true,
default: '',
placeholder: 'eg: Navigate to the Hacker News homepage and get the top 3 posts.',
displayOptions: {
show: {
resource: ['task'],
taskOperation: ['dispatchTask'],
},
},
routing: {
request: {
body: {
prompt: '={{$value}}',
},
},
},
},
{
displayName: 'URL',
description: 'The URL to navigate to',
name: 'url',
type: 'string',
default: '',
placeholder: 'eg: https://news.ycombinator.com/',
displayOptions: {
show: {
resource: ['task'],
taskOperation: ['dispatchTask'],
},
},
routing: {
request: {
body: {
url: '={{$value ? $value : null}}',
},
},
},
},
{
displayName: 'Webhook Callback URL',
description: 'Optional URL that Skyvern will call when the task finishes',
name: 'webhookUrl',
type: 'string',
default: '',
placeholder: 'https://example.com/webhook',
displayOptions: {
show: {
resource: ['task'],
taskOperation: ['dispatchTask'],
},
},
routing: {
request: {
body: {
webhook_url: '={{$value ? $value : null}}',
},
},
},
},
{
displayName: 'Task ID',
description: 'The ID of the task',
name: 'taskId',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['task'],
taskOperation: ['getTask'],
},
},
routing: {
request: {
method: 'GET',
url: '={{"/v1/runs/" + $value}}',
},
},
},
{
displayName: 'Task Options',
name: 'taskOptions',
type: 'collection',
description: 'Optional Configuration for the task',
placeholder: 'Add Task Options',
default: {},
options: [
{
displayName: 'Engine(Deprecated)',
description: 'Deprecated: please migrate to use "Engine" option',
name: 'engine',
type: 'options',
default: '',
options: [
{
name: 'TaskV1',
value: 'v1',
},
{
name: 'TaskV2',
value: 'v2',
},
{
name: 'THIS FIELD IS DEPRECATED',
value: '',
},
],
},
{
displayName: 'Engine',
name: 'runEngine',
type: 'options',
default: 'skyvern-2.0',
options: [
{
name: 'Skyvern 1.0',
value: 'skyvern-1.0',
},
{
name: 'Skyvern 2.0',
value: 'skyvern-2.0',
},
{
name: 'OpenAI CUA',
value: 'openai-cua',
},
{
name: 'Anthropic CUA',
value: 'anthropic-cua',
}
],
routing: {
request: {
body: {
engine: '={{$value}}',
},
},
},
}
],
displayOptions: {
show: {
resource: ['task'],
taskOperation: ['dispatchTask'],
},
},
},
{
displayName: 'Workflow Name or ID',
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
name: 'workflowId',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getWorkflows',
loadOptionsDependsOn: ['resource'],
},
required: true,
default: '',
displayOptions: {
show: {
resource: ['workflow'],
},
},
},
{
displayName: 'Workflow Run ID',
description: 'The ID of the workflow run',
name: 'workflowRunId',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: ['workflow'],
workflowOperation: ['getWorkflow'],
},
},
routing: {
request: {
url: '={{"/api/v1/workflows/" + $parameter["workflowId"] + "/runs/" + $value}}',
},
},
},
{
displayName: 'Workflow Run Parameters',
name: 'workflowRunParameters',
type: 'resourceMapper',
noDataExpression: true,
description: 'The JSON-formatted parameters to pass the workflow run to execute',
required: true,
default: {
mappingMode: 'defineBelow',
value: null,
},
displayOptions: {
show: {
resource: ['workflow'],
workflowOperation: ['dispatchWorkflow'],
},
},
typeOptions: {
loadOptionsDependsOn: ['workflowId'],
resourceMapper: {
resourceMapperMethod: 'getWorkflowRunParameters',
mode: 'update',
fieldWords: {
singular: 'workflowRunParameter',
plural: 'workflowRunParameters',
},
addAllFields: true,
multiKeyMatch: true,
},
},
routing: {
request: {
url: '={{"/api/v1/workflows/" + $parameter["workflowId"] + "/run"}}',
body: {
data: '={{$value["value"]}}',
},
},
},
},
{
displayName: 'Webhook Callback URL',
description: 'Optional URL that Skyvern will call when the workflow run finishes',
name: 'webhookCallbackUrl',
type: 'string',
default: '',
placeholder: 'https://example.com/webhook',
displayOptions: {
show: {
resource: ['workflow'],
workflowOperation: ['dispatchWorkflow'],
},
},
routing: {
request: {
body: {
webhook_callback_url: '={{$value ? $value : null}}',
},
},
},
},
],
version: 1,
};
methods = {
loadOptions: {
async getWorkflows(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
const resource = this.getCurrentNodeParameter('resource') as string;
if (resource !== 'workflow') return [];
const response = await skyvernApiRequest.call(
this,
'GET',
'/api/v1/workflows?page_size=100',
);
const data = response;
return data.map((workflow: any) => ({
name: workflow.title,
value: workflow.workflow_permanent_id,
}));
},
},
resourceMapping: {
async getWorkflowRunParameters(this: ILoadOptionsFunctions): Promise<ResourceMapperFields> {
const resource = this.getCurrentNodeParameter('resource') as string;
if (resource !== 'workflow') return { fields: [] };
const operation = this.getCurrentNodeParameter('workflowOperation') as string;
if (operation !== 'dispatchWorkflow') return { fields: [] };
const workflowId = this.getCurrentNodeParameter('workflowId') as string;
if (!workflowId) return { fields: [] };
const workflow = await skyvernApiRequest.call(
this,
'GET',
`/api/v1/workflows/${workflowId}`,
);
const parameters: any[] = workflow.workflow_definition.parameters;
const fields: ResourceMapperField[] = await Promise.all(
parameters
.filter((parameter: any) => parameter.parameter_type === 'workflow' || parameter.parameter_type === 'credential')
.map(async (parameter: any) => {
let options: INodePropertyOptions[] | undefined = undefined;
let parameterType: FieldType | undefined = undefined;
if (parameter.parameter_type === 'credential') {
const credData = await skyvernApiRequest.call(
this,
'GET',
'/api/v1/credentials',
);
options = credData.map((credential: any) => ({
name: credential.name,
value: credential.credential_id,
}));
parameterType = 'options';
} else {
const parameter_type_map: Record<string, FieldType> = {
string: 'string',
integer: 'number',
float: 'number',
boolean: 'boolean',
json: 'object',
file_url: 'url',
}
parameterType = parameter_type_map[parameter.workflow_parameter_type];
}
return {
id: parameter.key,
displayName: parameter.key,
defaultMatch: true,
canBeUsedToMatch: false,
required: parameter.default_value === undefined || parameter.default_value === null,
display: true,
type: parameterType,
options: options,
};
})
);
// HACK: If there are no parameters, add a empty field to avoid the resource mapper from crashing
if (fields.length === 0) {
fields.push({
id: 'NO_PARAMETERS',
displayName: 'No Parameters',
defaultMatch: false,
canBeUsedToMatch: false,
required: false,
display: true,
type: 'string',
});
}
return {
fields: fields,
}
},
},
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 132 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,59 +0,0 @@
{
"name": "n8n-nodes-skyvern",
"version": "0.0.8",
"description": "Skyvern Node for n8n",
"keywords": [
"n8n-community-node-package"
],
"license": "MIT",
"homepage": "",
"author": {
"name": "lawy",
"email": "lawy@skyvern.com"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Skyvern-AI/skyvern.git"
},
"engines": {
"node": ">=18.10",
"pnpm": ">=9.1"
},
"packageManager": "pnpm@9.1.4",
"main": "index.js",
"scripts": {
"preinstall": "npx only-allow pnpm",
"build": "rimraf dist && tsc && gulp build:icons",
"dev": "tsc --watch",
"format": "prettier nodes credentials --write",
"lint": "eslint nodes credentials package.json",
"lintfix": "eslint nodes credentials package.json --fix",
"prepublishOnly": "pnpm build && pnpm lint -c .eslintrc.prepublish.js nodes credentials package.json"
},
"files": [
"dist"
],
"n8n": {
"n8nNodesApiVersion": 1,
"credentials": [
"dist/credentials/SkyvernApi.credentials.js"
],
"nodes": [
"dist/nodes/Skyvern/Skyvern.node.js"
]
},
"devDependencies": {
"@types/node": "^22.13.10",
"@typescript-eslint/parser": "^7.15.0",
"braces": "^3.0.3",
"eslint": "^8.56.0",
"eslint-plugin-n8n-nodes-base": "^1.16.1",
"gulp": "^4.0.2",
"prettier": "^3.3.2",
"rimraf": "^6.0.1",
"typescript": "^5.5.3"
},
"peerDependencies": {
"n8n-workflow": "^1.82.0"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +0,0 @@
{
"compilerOptions": {
"strict": true,
"module": "commonjs",
"moduleResolution": "node",
"target": "es2019",
"lib": ["es2019", "es2020", "es2022.error"],
"removeComments": true,
"useUnknownInCatchVariables": false,
"forceConsistentCasingInFileNames": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"strictNullChecks": true,
"preserveConstEnums": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"incremental": true,
"declaration": true,
"sourceMap": true,
"skipLibCheck": true,
"outDir": "./dist/",
},
"include": [
"credentials/**/*",
"nodes/**/*",
"nodes/**/*.json",
"package.json",
],
}