diff --git a/packages/nodes-base/credentials/JinaAiApi.credentials.ts b/packages/nodes-base/credentials/JinaAiApi.credentials.ts new file mode 100644 index 0000000000..6f8d1efec1 --- /dev/null +++ b/packages/nodes-base/credentials/JinaAiApi.credentials.ts @@ -0,0 +1,43 @@ +import type { + IAuthenticateGeneric, + ICredentialTestRequest, + ICredentialType, + INodeProperties, +} from 'n8n-workflow'; + +export class JinaAiApi implements ICredentialType { + name = 'jinaAiApi'; + + displayName = 'Jina AI API'; + + documentationUrl = 'jinaAi'; + + properties: INodeProperties[] = [ + { + displayName: 'API Key', + name: 'apiKey', + type: 'string', + typeOptions: { password: true }, + default: '', + }, + ]; + + authenticate: IAuthenticateGeneric = { + type: 'generic', + properties: { + headers: { + Authorization: '=Bearer {{ $credentials?.apiKey }}', + }, + }, + }; + + test: ICredentialTestRequest = { + request: { + method: 'GET', + url: 'https://embeddings-dashboard-api.jina.ai/api/v1/api_key/fe_user', + qs: { + api_key: '={{$credentials.apiKey}}', + }, + }, + }; +} diff --git a/packages/nodes-base/nodes/JinaAI/JinaAi.node.json b/packages/nodes-base/nodes/JinaAI/JinaAi.node.json new file mode 100644 index 0000000000..7afbfa8b30 --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/JinaAi.node.json @@ -0,0 +1,18 @@ +{ + "node": "n8n-nodes-base.jinaAi", + "nodeVersion": "1.0", + "codexVersion": "1.0", + "categories": ["Miscellaneous"], + "resources": { + "credentialDocumentation": [ + { + "url": "https://docs.n8n.io/integrations/builtin/credentials/jinaai/" + } + ], + "primaryDocumentation": [ + { + "url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.jinaai/" + } + ] + } +} diff --git a/packages/nodes-base/nodes/JinaAI/JinaAi.node.ts b/packages/nodes-base/nodes/JinaAI/JinaAi.node.ts new file mode 100644 index 0000000000..9828710b73 --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/JinaAi.node.ts @@ -0,0 +1,465 @@ +import { NodeConnectionTypes, type INodeType, type INodeTypeDescription } from 'n8n-workflow'; + +export class JinaAi implements INodeType { + description: INodeTypeDescription = { + displayName: 'Jina AI', + name: 'jinaAi', + icon: { + light: 'file:jinaAi.svg', + dark: 'file:jinaAi.dark.svg', + }, + group: ['transform'], + version: 1, + subtitle: '={{ $parameter["operation"] + ": " + $parameter["resource"] }}', + description: 'Interact with Jina AI API', + defaults: { + name: 'Jina AI', + }, + inputs: [NodeConnectionTypes.Main], + outputs: [NodeConnectionTypes.Main], + usableAsTool: true, + credentials: [ + { + name: 'jinaAiApi', + required: true, + }, + ], + requestDefaults: { + headers: { + Accept: 'application/json', + }, + }, + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + noDataExpression: true, + options: [ + { + name: 'Reader', + value: 'reader', + }, + { + name: 'Research', + value: 'research', + }, + ], + default: 'reader', + }, + // Operations + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['reader'], + }, + }, + options: [ + { + name: 'Read', + value: 'read', + action: 'Read URL content', + description: + 'Fetches content from a URL and converts it to clean, LLM-friendly formats', + routing: { + request: { + method: 'GET', + url: '=https://r.jina.ai/{{ $parameter["url"] }}', + headers: { + 'X-Return-Format': '={{ $parameter["options"]["outputFormat"] }}', + 'X-Target-Selector': '={{ $parameter["options"]["targetSelector"] }}', + 'X-Remove-Selector': '={{ $parameter["options"]["excludeSelector"] }}', + 'X-With-Generated-Alt': '={{ $parameter["options"]["enableImageCaptioning"] }}', + 'X-Wait-For-Selector': '={{ $parameter["options"]["waitForSelector"] }}', + }, + }, + output: { + postReceive: [ + { + type: 'rootProperty', + enabled: '={{ $parameter["simplify"] }}', + properties: { + property: 'data', + }, + }, + ], + }, + }, + }, + { + name: 'Search', + value: 'search', + action: 'Search web', + description: + 'Performs a web search via Jina AI and returns top results as clean, LLM-friendly formats', + routing: { + request: { + method: 'GET', + url: 'https://s.jina.ai/', + headers: { + 'X-Return-Format': '={{ $parameter["options"]["outputFormat"] }}', + 'X-Site': '={{ $parameter["options"]["siteFilter"] }}', + }, + qs: { + q: '={{ $parameter["searchQuery"] }}', + page: '={{ $parameter["options"]["pageNumber"] }}', + }, + }, + output: { + postReceive: [ + { + type: 'rootProperty', + enabled: '={{ $parameter["simplify"] }}', + properties: { + property: 'data', + }, + }, + ], + }, + }, + }, + ], + default: 'read', + }, + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['research'], + }, + }, + options: [ + { + name: 'Deep Research', + value: 'deepResearch', + action: 'Perform deep research', + description: 'Research a topic and generate a structured research report', + routing: { + request: { + method: 'POST', + url: 'https://deepsearch.jina.ai/v1/chat/completions', + body: { + messages: [ + { + role: 'user', + content: '={{ $parameter["researchQuery"] }}', + }, + ], + max_returned_urls: '={{ $parameter["options"]["maxReturnedSources"] }}', + boost_hostnames: + '={{ $parameter["options"]["prioritizeSources"].split(/,\\s*/) }}', + bad_hostnames: '={{ $parameter["options"]["excludeSources"].split(/,\\s*/) }}', + only_hostnames: '={{ $parameter["options"]["siteFilter"].split(/,\\s*/) }}', + }, + }, + output: { + postReceive: [ + { + type: 'setKeyValue', + enabled: '={{ $parameter["simplify"] }}', + properties: { + content: '={{ $responseItem["choices"][0]["message"]["content"] }}', + annotations: '={{ $responseItem["choices"][0]["message"]["annotations"] }}', + usage: '={{ $responseItem["usage"] }}', + }, + }, + ], + }, + }, + }, + ], + default: 'deepResearch', + }, + // Options for Reader + { + displayName: 'URL', + name: 'url', + type: 'string', + required: true, + default: '', + placeholder: 'https://jina.ai/', + description: 'The URL to fetch content from', + displayOptions: { + show: { + resource: ['reader'], + operation: ['read'], + }, + }, + }, + { + displayName: 'Simplify', + name: 'simplify', + type: 'boolean', + default: true, + description: + 'Whether to return a simplified version of the response instead of the raw data', + displayOptions: { + show: { + resource: ['reader'], + operation: ['read'], + }, + }, + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + resource: ['reader'], + operation: ['read'], + }, + }, + options: [ + { + displayName: 'Output Format', + name: 'outputFormat', + description: 'Specify desired output format', + type: 'options', + options: [ + { + name: 'HTML', + value: 'html', + }, + { + name: 'JSON', + value: '', + }, + { + name: 'Markdown', + value: 'markdown', + }, + { + name: 'Screenshot', + value: 'screenshot', + }, + { + name: 'Text', + value: 'text', + }, + ], + default: '', + }, + { + displayName: 'Target CSS Selector', + name: 'targetSelector', + type: 'string', + description: 'CSS selector to focus on specific page elements', + default: '', + placeholder: 'e.g. #main-content .article', + }, + { + displayName: 'Exclude CSS Selector', + name: 'excludeSelector', + type: 'string', + description: 'CSS selector for elements to exclude', + default: '', + placeholder: 'e.g. header, footer, .ads', + }, + { + displayName: 'Enable Image Captioning', + name: 'enableImageCaptioning', + type: 'boolean', + default: false, + description: 'Whether to generate captions for images within the content', + }, + { + displayName: 'Wait for CSS Selector', + name: 'waitForSelector', + type: 'string', + description: + 'Wait for a specific element to appear before extracting content (for dynamic pages)', + default: '', + placeholder: 'e.g. #results-loaded', + }, + ], + }, + { + displayName: 'Search Query', + name: 'searchQuery', + type: 'string', + required: true, + default: '', + placeholder: 'e.g. Jina AI', + displayOptions: { + show: { + resource: ['reader'], + operation: ['search'], + }, + }, + }, + { + displayName: 'Simplify', + name: 'simplify', + type: 'boolean', + default: true, + description: + 'Whether to return a simplified version of the response instead of the raw data', + displayOptions: { + show: { + resource: ['reader'], + operation: ['search'], + }, + }, + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + resource: ['reader'], + operation: ['search'], + }, + }, + options: [ + { + displayName: 'Output Format', + name: 'outputFormat', + description: 'Specify desired output format', + type: 'options', + options: [ + { + name: 'HTML', + value: 'html', + }, + { + name: 'JSON', + value: '', + }, + { + name: 'Markdown', + value: 'markdown', + }, + { + name: 'Screenshot', + value: 'screenshot', + }, + { + name: 'Text', + value: 'text', + }, + ], + default: 'json', + }, + { + displayName: 'Site Filter', + name: 'siteFilter', + type: 'string', + description: 'Restrict search to specific websites', + default: '', + placeholder: 'e.g. jina.ai, github.com', + }, + { + displayName: 'Page Number', + name: 'pageNumber', + type: 'number', + typeOptions: { + minValue: 1, + numberPrecision: 0, + }, + description: 'The page number of the search results to retrieve', + default: '', + placeholder: '1', + }, + ], + }, + // Options for Research + { + displayName: 'Research Query', + name: 'researchQuery', + type: 'string', + required: true, + default: '', + description: 'The topic or question for the AI to research', + placeholder: + 'e.g. Analyze the impact of renewable energy sources on climate change mitigation', + typeOptions: { + rows: 2, + }, + displayOptions: { + show: { + resource: ['research'], + operation: ['deepResearch'], + }, + }, + }, + { + displayName: 'Simplify', + name: 'simplify', + type: 'boolean', + default: true, + description: + 'Whether to return a simplified version of the response instead of the raw data', + displayOptions: { + show: { + resource: ['research'], + operation: ['deepResearch'], + }, + }, + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + resource: ['research'], + operation: ['deepResearch'], + }, + }, + options: [ + { + displayName: 'Max Returned Sources', + name: 'maxReturnedSources', + description: 'The maximum number of URLs to include in the final answer', + type: 'number', + typeOptions: { + minValue: 1, + numberPrecision: 0, + }, + default: '', + placeholder: 'e.g. 5', + }, + { + displayName: 'Prioritize Sources', + name: 'prioritizeSources', + type: 'string', + description: 'A list of domains that are given a higher priority for content retrieval', + default: '', + placeholder: 'e.g. jina.ai, github.com', + }, + { + displayName: 'Exclude Sources', + name: 'excludeSources', + type: 'string', + description: 'A list of domains to be strictly excluded from content retrieval', + default: '', + placeholder: 'e.g. jina.ai, github.com', + }, + { + displayName: 'Site Filter', + name: 'siteFilter', + type: 'string', + description: 'Restrict search to specific websites', + default: '', + placeholder: 'e.g. jina.ai, github.com', + }, + ], + }, + ], + }; +} diff --git a/packages/nodes-base/nodes/JinaAI/__test__/node/JinaAi.node.test.ts b/packages/nodes-base/nodes/JinaAI/__test__/node/JinaAi.node.test.ts new file mode 100644 index 0000000000..89f53e90d0 --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/__test__/node/JinaAi.node.test.ts @@ -0,0 +1,109 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; +import nock from 'nock'; + +import deepResearchResult from './fixtures/deepResearch.json'; +import readResult from './fixtures/read.json'; +import searchResult from './fixtures/search.json'; + +describe('JinaAI Node', () => { + const credentials = { + jinaAiApi: { + apiKey: 'API-KEY', + }, + }; + + describe('Reader -> Read', () => { + const jinaAiNock = nock('https://r.jina.ai'); + + beforeAll(() => { + jinaAiNock.get('/https://first.com/some/path').times(2).reply(200, readResult); + jinaAiNock + .get('/https://second.com/other') + .query({ + foo: 'bar', + }) + .matchHeader('X-Return-Format', 'markdown') + .matchHeader('X-Target-Selector', 'article') + .matchHeader('X-Remove-Selector', '.ad') + .matchHeader('X-With-Generated-Alt', 'true') + .matchHeader('X-Wait-For-Selector', '#posts') + .reply(200, readResult); + }); + + afterAll(() => jinaAiNock.done()); + + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['read.workflow.json'], + }); + }); + + describe('Reader -> Search', () => { + const jinaAiNock = nock('https://s.jina.ai'); + + beforeAll(() => { + jinaAiNock + .get('/') + .query({ + q: 'Jina AI', + }) + .times(2) + .reply(200, searchResult); + jinaAiNock + .get('/') + .query({ + q: 'Jina AI', + page: 2, + }) + .matchHeader('X-Return-Format', 'markdown') + .matchHeader('X-Site', 'jina.ai') + .reply(200, searchResult); + }); + + afterAll(() => jinaAiNock.done()); + + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['search.workflow.json'], + }); + }); + + describe('Research -> Deep Research', () => { + const jinaAiNock = nock('https://deepsearch.jina.ai'); + + beforeAll(() => { + jinaAiNock + .post('/v1/chat/completions', { + messages: [ + { + role: 'user', + content: 'Describe the latest features in Jina AI', + }, + ], + }) + .times(2) + .reply(200, deepResearchResult); + jinaAiNock + .post('/v1/chat/completions', { + messages: [ + { + role: 'user', + content: 'Describe the latest features in Jina AI', + }, + ], + max_returned_urls: 5, + boost_hostnames: ['jina.ai'], + bad_hostnames: ['medium.com'], + only_hostnames: ['jina.ai', 'github.com'], + }) + .reply(200, deepResearchResult); + }); + + afterAll(() => jinaAiNock.done()); + + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['deepResearch.workflow.json'], + }); + }); +}); diff --git a/packages/nodes-base/nodes/JinaAI/__test__/node/deepResearch.workflow.json b/packages/nodes-base/nodes/JinaAI/__test__/node/deepResearch.workflow.json new file mode 100644 index 0000000000..6ab5d8c54a --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/__test__/node/deepResearch.workflow.json @@ -0,0 +1,226 @@ +{ + "name": "Jina AI -> Research -> Deep Research", + "nodes": [ + { + "parameters": {}, + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [-240, 260], + "id": "8a73e8c0-c2b8-4933-98e1-a2577b9f4902", + "name": "When clicking ‘Test workflow’" + }, + { + "parameters": { + "resource": "research", + "researchQuery": "Describe the latest features in Jina AI", + "simplify": false, + "options": {}, + "requestOptions": {} + }, + "type": "n8n-nodes-base.jinaAi", + "typeVersion": 1, + "position": [-20, 60], + "id": "cf8f337f-841c-4715-9ecd-d1b877d5b098", + "name": "No options", + "credentials": { + "jinaAiApi": { + "id": "8ph5AE62dQFfqkLx", + "name": "Jina AI account" + } + } + }, + { + "parameters": { + "resource": "research", + "researchQuery": "Describe the latest features in Jina AI", + "simplify": false, + "options": { + "maxReturnedSources": 5, + "prioritizeSources": "jina.ai", + "excludeSources": "medium.com", + "siteFilter": "jina.ai, github.com" + }, + "requestOptions": {} + }, + "type": "n8n-nodes-base.jinaAi", + "typeVersion": 1, + "position": [-20, 260], + "id": "c353f860-0bc4-453f-a620-2f054721f52a", + "name": "With options", + "credentials": { + "jinaAiApi": { + "id": "8ph5AE62dQFfqkLx", + "name": "Jina AI account" + } + } + }, + { + "parameters": { + "resource": "research", + "researchQuery": "Describe the latest features in Jina AI", + "options": {}, + "requestOptions": {} + }, + "type": "n8n-nodes-base.jinaAi", + "typeVersion": 1, + "position": [-20, 460], + "id": "91269e77-35b1-4bf5-b0b6-8876e0126b36", + "name": "Simplified", + "credentials": { + "jinaAiApi": { + "id": "8ph5AE62dQFfqkLx", + "name": "Jina AI account" + } + } + } + ], + "pinData": { + "No options": [ + { + "json": { + "id": "123", + "object": "chat.completion", + "created": 1746186539, + "system_fingerprint": "fp_123", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "type": "text", + "annotations": [ + { + "type": "url_citation", + "url_citation": { + "title": "Lorem ipsum dolor sit amet", + "exactQuote": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + "url": "https://some.referenced.site.com/article", + "dateTime": "Aug 30, 2024" + } + } + ] + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + }, + "visitedURLs": ["https://first.com/some/path", "https://second.com/?foo=bar"], + "readURLs": [ + "https://example.com", + "https://example.com/2", + "https://some.other.site.com/path" + ], + "numURLs": 5 + } + } + ], + "With options": [ + { + "json": { + "id": "123", + "object": "chat.completion", + "created": 1746186539, + "system_fingerprint": "fp_123", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "type": "text", + "annotations": [ + { + "type": "url_citation", + "url_citation": { + "title": "Lorem ipsum dolor sit amet", + "exactQuote": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + "url": "https://some.referenced.site.com/article", + "dateTime": "Aug 30, 2024" + } + } + ] + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + }, + "visitedURLs": ["https://first.com/some/path", "https://second.com/?foo=bar"], + "readURLs": [ + "https://example.com", + "https://example.com/2", + "https://some.other.site.com/path" + ], + "numURLs": 5 + } + } + ], + "Simplified": [ + { + "json": { + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "annotations": [ + { + "type": "url_citation", + "url_citation": { + "title": "Lorem ipsum dolor sit amet", + "exactQuote": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + "url": "https://some.referenced.site.com/article", + "dateTime": "Aug 30, 2024" + } + } + ], + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + } + } + } + ] + }, + "connections": { + "When clicking ‘Test workflow’": { + "main": [ + [ + { + "node": "No options", + "type": "main", + "index": 0 + }, + { + "node": "With options", + "type": "main", + "index": 0 + }, + { + "node": "Simplified", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1" + }, + "versionId": "b822e0dc-3c01-43d5-ad56-419814a40af7", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "e115be144a6a5547dbfca93e774dfffa178aa94a181854c13e2ce5e14d195b2e" + }, + "id": "Qttu9wESqI9vHYBA", + "tags": [] +} diff --git a/packages/nodes-base/nodes/JinaAI/__test__/node/fixtures/deepResearch.json b/packages/nodes-base/nodes/JinaAI/__test__/node/fixtures/deepResearch.json new file mode 100644 index 0000000000..85473b07fe --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/__test__/node/fixtures/deepResearch.json @@ -0,0 +1,37 @@ +{ + "id": "123", + "object": "chat.completion", + "created": 1746186539, + "system_fingerprint": "fp_123", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "type": "text", + "annotations": [ + { + "type": "url_citation", + "url_citation": { + "title": "Lorem ipsum dolor sit amet", + "exactQuote": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + "url": "https://some.referenced.site.com/article", + "dateTime": "Aug 30, 2024" + } + } + ] + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + }, + "visitedURLs": ["https://first.com/some/path", "https://second.com/?foo=bar"], + "readURLs": ["https://example.com", "https://example.com/2", "https://some.other.site.com/path"], + "numURLs": 5 +} diff --git a/packages/nodes-base/nodes/JinaAI/__test__/node/fixtures/read.json b/packages/nodes-base/nodes/JinaAI/__test__/node/fixtures/read.json new file mode 100644 index 0000000000..939669dc09 --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/__test__/node/fixtures/read.json @@ -0,0 +1,18 @@ +{ + "code": 200, + "status": 20000, + "data": { + "title": "Jina AI - Your Search Foundation, Supercharged.", + "url": "https://jina.ai/", + "description": "Best-in-class embeddings, rerankers, web crawler scraper, deepsearch, small LMs. The search AI for multilingual and multimodal data.", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + }, + "meta": { + "usage": { + "tokens": 123 + } + } +} diff --git a/packages/nodes-base/nodes/JinaAI/__test__/node/fixtures/search.json b/packages/nodes-base/nodes/JinaAI/__test__/node/fixtures/search.json new file mode 100644 index 0000000000..3c03a7dd8b --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/__test__/node/fixtures/search.json @@ -0,0 +1,30 @@ +{ + "code": 200, + "status": 20000, + "data": [ + { + "title": "Jina AI - Your Search Foundation, Supercharged.", + "url": "https://jina.ai/", + "description": "Best-in-class embeddings, rerankers, web crawler scraper, deepsearch, small LMs. The search AI for multilingual and multimodal data.", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + }, + { + "title": "Jina AI", + "url": "https://github.com/jina-ai", + "description": "Your Search Foundation, Supercharged! Jina AI has 243 repositories available. Follow their code on GitHub.", + "date": "Mar 24, 2025", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + } + ], + "meta": { + "usage": { + "tokens": 246 + } + } +} diff --git a/packages/nodes-base/nodes/JinaAI/__test__/node/read.workflow.json b/packages/nodes-base/nodes/JinaAI/__test__/node/read.workflow.json new file mode 100644 index 0000000000..0d31ba3ead --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/__test__/node/read.workflow.json @@ -0,0 +1,168 @@ +{ + "name": "Jina AI -> Reader -> Read", + "nodes": [ + { + "parameters": {}, + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [0, 100], + "id": "75a081a7-14e6-4f63-a0b6-86f54937d59d", + "name": "When clicking ‘Test workflow’" + }, + { + "parameters": { + "url": "https://first.com/some/path", + "simplify": false, + "options": {}, + "requestOptions": {} + }, + "type": "n8n-nodes-base.jinaAi", + "typeVersion": 1, + "position": [220, -100], + "id": "92e091b7-42dd-4751-8432-58a211840b35", + "name": "No options", + "credentials": { + "jinaAiApi": { + "id": "8ph5AE62dQFfqkLx", + "name": "Jina AI account" + } + } + }, + { + "parameters": { + "url": "https://second.com/other?foo=bar", + "simplify": false, + "options": { + "outputFormat": "markdown", + "targetSelector": "article", + "excludeSelector": ".ad", + "enableImageCaptioning": true, + "waitForSelector": "#posts" + }, + "requestOptions": {} + }, + "type": "n8n-nodes-base.jinaAi", + "typeVersion": 1, + "position": [220, 100], + "id": "f598a0ee-794e-4c31-8833-327768f7eecb", + "name": "With options", + "credentials": { + "jinaAiApi": { + "id": "8ph5AE62dQFfqkLx", + "name": "Jina AI account" + } + } + }, + { + "parameters": { + "url": "https://first.com/some/path", + "options": {}, + "requestOptions": {} + }, + "type": "n8n-nodes-base.jinaAi", + "typeVersion": 1, + "position": [220, 300], + "id": "79d27978-20af-494d-b9bd-32f68883ac54", + "name": "Simplified", + "credentials": { + "jinaAiApi": { + "id": "8ph5AE62dQFfqkLx", + "name": "Jina AI account" + } + } + } + ], + "pinData": { + "No options": [ + { + "json": { + "code": 200, + "status": 20000, + "data": { + "title": "Jina AI - Your Search Foundation, Supercharged.", + "url": "https://jina.ai/", + "description": "Best-in-class embeddings, rerankers, web crawler scraper, deepsearch, small LMs. The search AI for multilingual and multimodal data.", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + }, + "meta": { + "usage": { + "tokens": 123 + } + } + } + } + ], + "With options": [ + { + "json": { + "code": 200, + "status": 20000, + "data": { + "title": "Jina AI - Your Search Foundation, Supercharged.", + "url": "https://jina.ai/", + "description": "Best-in-class embeddings, rerankers, web crawler scraper, deepsearch, small LMs. The search AI for multilingual and multimodal data.", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + }, + "meta": { + "usage": { + "tokens": 123 + } + } + } + } + ], + "Simplified": [ + { + "json": { + "title": "Jina AI - Your Search Foundation, Supercharged.", + "url": "https://jina.ai/", + "description": "Best-in-class embeddings, rerankers, web crawler scraper, deepsearch, small LMs. The search AI for multilingual and multimodal data.", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + } + } + ] + }, + "connections": { + "When clicking ‘Test workflow’": { + "main": [ + [ + { + "node": "No options", + "type": "main", + "index": 0 + }, + { + "node": "With options", + "type": "main", + "index": 0 + }, + { + "node": "Simplified", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1" + }, + "versionId": "41f0e679-7754-4b3c-a86c-e130a18d4378", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "e115be144a6a5547dbfca93e774dfffa178aa94a181854c13e2ce5e14d195b2e" + }, + "id": "MFBoiglfRhCu9HgF", + "tags": [] +} diff --git a/packages/nodes-base/nodes/JinaAI/__test__/node/search.workflow.json b/packages/nodes-base/nodes/JinaAI/__test__/node/search.workflow.json new file mode 100644 index 0000000000..d1cf6eaedd --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/__test__/node/search.workflow.json @@ -0,0 +1,205 @@ +{ + "name": "Jina AI -> Reader -> Search", + "nodes": [ + { + "parameters": {}, + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [-360, 40], + "id": "b7e0a085-eb10-48a7-a25e-853b36aef252", + "name": "When clicking ‘Test workflow’" + }, + { + "parameters": { + "operation": "search", + "searchQuery": "Jina AI", + "simplify": false, + "options": {}, + "requestOptions": {} + }, + "type": "n8n-nodes-base.jinaAi", + "typeVersion": 1, + "position": [-140, -160], + "id": "ea197991-8539-4221-9798-842f4026f31b", + "name": "No options", + "credentials": { + "jinaAiApi": { + "id": "8ph5AE62dQFfqkLx", + "name": "Jina AI account" + } + } + }, + { + "parameters": { + "operation": "search", + "searchQuery": "Jina AI", + "simplify": false, + "options": { + "outputFormat": "markdown", + "siteFilter": "jina.ai", + "pageNumber": 2 + }, + "requestOptions": {} + }, + "type": "n8n-nodes-base.jinaAi", + "typeVersion": 1, + "position": [-140, 40], + "id": "dbfbbf4a-caa1-4922-b200-723748636773", + "name": "With options", + "credentials": { + "jinaAiApi": { + "id": "8ph5AE62dQFfqkLx", + "name": "Jina AI account" + } + } + }, + { + "parameters": { + "operation": "search", + "searchQuery": "Jina AI", + "options": {}, + "requestOptions": {} + }, + "type": "n8n-nodes-base.jinaAi", + "typeVersion": 1, + "position": [-140, 240], + "id": "91ca27b2-eab4-4131-a544-5ae4794ac0b3", + "name": "Simplified", + "credentials": { + "jinaAiApi": { + "id": "8ph5AE62dQFfqkLx", + "name": "Jina AI account" + } + } + } + ], + "pinData": { + "No options": [ + { + "json": { + "code": 200, + "status": 20000, + "data": [ + { + "title": "Jina AI - Your Search Foundation, Supercharged.", + "url": "https://jina.ai/", + "description": "Best-in-class embeddings, rerankers, web crawler scraper, deepsearch, small LMs. The search AI for multilingual and multimodal data.", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + }, + { + "title": "Jina AI", + "url": "https://github.com/jina-ai", + "description": "Your Search Foundation, Supercharged! Jina AI has 243 repositories available. Follow their code on GitHub.", + "date": "Mar 24, 2025", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + } + ], + "meta": { + "usage": { + "tokens": 246 + } + } + } + } + ], + "With options": [ + { + "json": { + "code": 200, + "status": 20000, + "data": [ + { + "title": "Jina AI - Your Search Foundation, Supercharged.", + "url": "https://jina.ai/", + "description": "Best-in-class embeddings, rerankers, web crawler scraper, deepsearch, small LMs. The search AI for multilingual and multimodal data.", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + }, + { + "title": "Jina AI", + "url": "https://github.com/jina-ai", + "description": "Your Search Foundation, Supercharged! Jina AI has 243 repositories available. Follow their code on GitHub.", + "date": "Mar 24, 2025", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + } + ], + "meta": { + "usage": { + "tokens": 246 + } + } + } + } + ], + "Simplified": [ + { + "json": { + "title": "Jina AI - Your Search Foundation, Supercharged.", + "url": "https://jina.ai/", + "description": "Best-in-class embeddings, rerankers, web crawler scraper, deepsearch, small LMs. The search AI for multilingual and multimodal data.", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + } + }, + { + "json": { + "title": "Jina AI", + "url": "https://github.com/jina-ai", + "description": "Your Search Foundation, Supercharged! Jina AI has 243 repositories available. Follow their code on GitHub.", + "date": "Mar 24, 2025", + "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", + "usage": { + "tokens": 123 + } + } + } + ] + }, + "connections": { + "When clicking ‘Test workflow’": { + "main": [ + [ + { + "node": "No options", + "type": "main", + "index": 0 + }, + { + "node": "With options", + "type": "main", + "index": 0 + }, + { + "node": "Simplified", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1" + }, + "versionId": "b425b5ec-f0b1-4f81-a83b-ca6a787d7a1d", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "e115be144a6a5547dbfca93e774dfffa178aa94a181854c13e2ce5e14d195b2e" + }, + "id": "QVbuEahHyMKrgfFc", + "tags": [] +} diff --git a/packages/nodes-base/nodes/JinaAI/jinaAi.dark.svg b/packages/nodes-base/nodes/JinaAI/jinaAi.dark.svg new file mode 100644 index 0000000000..b94c3aec17 --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/jinaAi.dark.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/nodes-base/nodes/JinaAI/jinaAi.svg b/packages/nodes-base/nodes/JinaAI/jinaAi.svg new file mode 100644 index 0000000000..13c6ec0242 --- /dev/null +++ b/packages/nodes-base/nodes/JinaAI/jinaAi.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 5075f47b60..9eee546f10 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -186,6 +186,7 @@ "dist/credentials/InvoiceNinjaApi.credentials.js", "dist/credentials/IterableApi.credentials.js", "dist/credentials/JenkinsApi.credentials.js", + "dist/credentials/JinaAiApi.credentials.js", "dist/credentials/JiraSoftwareCloudApi.credentials.js", "dist/credentials/JiraSoftwareServerApi.credentials.js", "dist/credentials/JiraSoftwareServerPatApi.credentials.js", @@ -597,6 +598,7 @@ "dist/nodes/ItemLists/ItemLists.node.js", "dist/nodes/Iterable/Iterable.node.js", "dist/nodes/Jenkins/Jenkins.node.js", + "dist/nodes/JinaAI/JinaAi.node.js", "dist/nodes/Jira/Jira.node.js", "dist/nodes/Jira/JiraTrigger.node.js", "dist/nodes/JotForm/JotFormTrigger.node.js",