n8n-nodes-prompt-library 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # n8n-nodes-prompt-library
2
+
3
+ n8n community node to fetch and render prompts from [n8n-library](https://github.com/your-org/n8n-library)'s prompt versioning system.
4
+
5
+ ## Features
6
+
7
+ - **Get Prompt** - Fetch a prompt by slug (latest or specific version)
8
+ - **List Prompts** - List all published prompts
9
+ - **Render Prompt** - Fetch a prompt and replace `{{variable}}` template variables with values
10
+ - **AI Tool compatible** - `usableAsTool: true` so AI agents can use this node
11
+
12
+ ## Installation
13
+
14
+ ### In n8n (community nodes)
15
+
16
+ 1. Go to **Settings > Community Nodes**
17
+ 2. Install `n8n-nodes-prompt-library`
18
+
19
+ ### Manual installation
20
+
21
+ ```bash
22
+ cd ~/.n8n/custom
23
+ npm install n8n-nodes-prompt-library
24
+ ```
25
+
26
+ ## Credentials
27
+
28
+ | Field | Description |
29
+ |-------|-------------|
30
+ | Instance URL | Base URL of your n8n-library instance (e.g. `https://library.example.com`) |
31
+ | API Key | API key from n8n-library Settings > API Keys (`n8nlib_...`) |
32
+
33
+ ## Operations
34
+
35
+ ### Get Prompt
36
+
37
+ Fetches a single prompt by its slug. Optionally specify a version number (0 = latest).
38
+
39
+ ### List Prompts
40
+
41
+ Returns all published prompts with their metadata (name, slug, description, variables, category, tags).
42
+
43
+ ### Render Prompt
44
+
45
+ Fetches a prompt and replaces template variables. For example, if the prompt contains `{{customer_name}}`, provide a variable with name `customer_name` and value `Alice` to get the rendered output.
46
+
47
+ ## Example Usage
48
+
49
+ ```
50
+ [Trigger] -> [Prompt Library: Render Prompt] -> [OpenAI Chat]
51
+ ```
52
+
53
+ Fetch a versioned prompt with variables, then pass the rendered content to an LLM.
@@ -0,0 +1,9 @@
1
+ import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class PromptLibraryApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ authenticate: IAuthenticateGeneric;
8
+ test: ICredentialTestRequest;
9
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PromptLibraryApi = void 0;
4
+ class PromptLibraryApi {
5
+ constructor() {
6
+ this.name = 'promptLibraryApi';
7
+ this.displayName = 'Prompt Library API';
8
+ this.documentationUrl = 'https://github.com/your-org/n8n-nodes-prompt-library';
9
+ this.properties = [
10
+ {
11
+ displayName: 'Instance URL',
12
+ name: 'instanceUrl',
13
+ type: 'string',
14
+ default: '',
15
+ placeholder: 'https://library.example.com',
16
+ description: 'Base URL of your n8n-library instance',
17
+ required: true,
18
+ },
19
+ {
20
+ displayName: 'API Key',
21
+ name: 'apiKey',
22
+ type: 'string',
23
+ typeOptions: { password: true },
24
+ default: '',
25
+ placeholder: 'n8nlib_...',
26
+ description: 'API key from n8n-library Settings > API Keys',
27
+ required: true,
28
+ },
29
+ ];
30
+ this.authenticate = {
31
+ type: 'generic',
32
+ properties: {
33
+ headers: {
34
+ Authorization: '=Bearer {{$credentials.apiKey}}',
35
+ },
36
+ },
37
+ };
38
+ this.test = {
39
+ request: {
40
+ baseURL: '={{$credentials.instanceUrl}}',
41
+ url: '/api/public/prompts',
42
+ method: 'GET',
43
+ },
44
+ };
45
+ }
46
+ }
47
+ exports.PromptLibraryApi = PromptLibraryApi;
@@ -0,0 +1,11 @@
1
+ import type { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, INodePropertyOptions, ILoadOptionsFunctions } from 'n8n-workflow';
2
+ export declare class PromptLibrary implements INodeType {
3
+ description: INodeTypeDescription;
4
+ methods: {
5
+ loadOptions: {
6
+ getPrompts(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
7
+ getVersions(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
8
+ };
9
+ };
10
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
11
+ }
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PromptLibrary = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ class PromptLibrary {
6
+ constructor() {
7
+ this.description = {
8
+ displayName: 'Prompt Library',
9
+ name: 'promptLibrary',
10
+ icon: 'file:promptlibrary.svg',
11
+ group: ['input'],
12
+ version: 1,
13
+ subtitle: '={{$parameter["operation"]}}',
14
+ description: 'Fetch and render prompts from n8n-library',
15
+ defaults: {
16
+ name: 'Prompt Library',
17
+ },
18
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
19
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
20
+ usableAsTool: true,
21
+ credentials: [
22
+ {
23
+ name: 'promptLibraryApi',
24
+ required: true,
25
+ },
26
+ ],
27
+ properties: [
28
+ {
29
+ displayName: 'Operation',
30
+ name: 'operation',
31
+ type: 'options',
32
+ noDataExpression: true,
33
+ options: [
34
+ {
35
+ name: 'Get Prompt',
36
+ value: 'getPrompt',
37
+ description: 'Fetch a prompt by slug (latest or specific version)',
38
+ action: 'Get a prompt',
39
+ },
40
+ {
41
+ name: 'List Prompts',
42
+ value: 'listPrompts',
43
+ description: 'List all published prompts',
44
+ action: 'List all prompts',
45
+ },
46
+ {
47
+ name: 'Render Prompt',
48
+ value: 'renderPrompt',
49
+ description: 'Fetch a prompt and replace template variables',
50
+ action: 'Render a prompt with variables',
51
+ },
52
+ ],
53
+ default: 'getPrompt',
54
+ },
55
+ {
56
+ displayName: 'Prompt',
57
+ name: 'slug',
58
+ type: 'options',
59
+ typeOptions: {
60
+ loadOptionsMethod: 'getPrompts',
61
+ },
62
+ required: true,
63
+ default: '',
64
+ description: 'Select the prompt to fetch',
65
+ displayOptions: {
66
+ show: {
67
+ operation: ['getPrompt', 'renderPrompt'],
68
+ },
69
+ },
70
+ },
71
+ {
72
+ displayName: 'Version',
73
+ name: 'version',
74
+ type: 'options',
75
+ typeOptions: {
76
+ loadOptionsMethod: 'getVersions',
77
+ loadOptionsDependsOn: ['slug'],
78
+ },
79
+ required: true,
80
+ default: '',
81
+ description: 'Select the prompt version to fetch',
82
+ displayOptions: {
83
+ show: {
84
+ operation: ['getPrompt', 'renderPrompt'],
85
+ },
86
+ },
87
+ },
88
+ {
89
+ displayName: 'Variables',
90
+ name: 'variables',
91
+ type: 'fixedCollection',
92
+ typeOptions: {
93
+ multipleValues: true,
94
+ },
95
+ default: {},
96
+ description: 'Template variables to replace in the prompt (e.g. {{customer_name}})',
97
+ displayOptions: {
98
+ show: {
99
+ operation: ['renderPrompt'],
100
+ },
101
+ },
102
+ options: [
103
+ {
104
+ name: 'variable',
105
+ displayName: 'Variable',
106
+ values: [
107
+ {
108
+ displayName: 'Name',
109
+ name: 'name',
110
+ type: 'string',
111
+ default: '',
112
+ description: 'Variable name (without {{ }})',
113
+ },
114
+ {
115
+ displayName: 'Value',
116
+ name: 'value',
117
+ type: 'string',
118
+ default: '',
119
+ description: 'Value to substitute',
120
+ },
121
+ ],
122
+ },
123
+ ],
124
+ },
125
+ ],
126
+ };
127
+ this.methods = {
128
+ loadOptions: {
129
+ async getPrompts() {
130
+ const credentials = await this.getCredentials('promptLibraryApi');
131
+ const options = {
132
+ method: 'GET',
133
+ url: `${credentials.instanceUrl.replace(/\/+$/, '')}/api/public/prompts`,
134
+ json: true,
135
+ };
136
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'promptLibraryApi', options);
137
+ const prompts = response.prompts;
138
+ if (!Array.isArray(prompts))
139
+ return [];
140
+ return prompts.map((p) => ({
141
+ name: `${p.name} (${p.slug})`,
142
+ value: p.slug,
143
+ description: p.description || undefined,
144
+ }));
145
+ },
146
+ async getVersions() {
147
+ const slug = this.getCurrentNodeParameter('slug');
148
+ if (!slug)
149
+ return [];
150
+ const credentials = await this.getCredentials('promptLibraryApi');
151
+ const baseUrl = credentials.instanceUrl.replace(/\/+$/, '');
152
+ const options = {
153
+ method: 'GET',
154
+ url: `${baseUrl}/api/public/prompts/${encodeURIComponent(slug)}/versions`,
155
+ json: true,
156
+ };
157
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'promptLibraryApi', options);
158
+ const versions = response.versions;
159
+ if (!Array.isArray(versions))
160
+ return [];
161
+ const result = [
162
+ {
163
+ name: 'Latest',
164
+ value: 'latest',
165
+ description: 'Always fetch the latest version',
166
+ },
167
+ ];
168
+ for (const v of versions) {
169
+ const version = v.version;
170
+ const changeNote = v.change_note;
171
+ result.push({
172
+ name: `v${version}${changeNote ? ` – ${changeNote}` : ''}`,
173
+ value: version,
174
+ });
175
+ }
176
+ return result;
177
+ },
178
+ },
179
+ };
180
+ }
181
+ async execute() {
182
+ const items = this.getInputData();
183
+ const returnData = [];
184
+ const operation = this.getNodeParameter('operation', 0);
185
+ const credentials = await this.getCredentials('promptLibraryApi');
186
+ const baseUrl = credentials.instanceUrl.replace(/\/+$/, '');
187
+ for (let i = 0; i < items.length; i++) {
188
+ try {
189
+ if (operation === 'listPrompts') {
190
+ const options = {
191
+ method: 'GET',
192
+ url: `${baseUrl}/api/public/prompts`,
193
+ json: true,
194
+ };
195
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'promptLibraryApi', options);
196
+ const prompts = response.prompts;
197
+ for (const prompt of prompts) {
198
+ returnData.push({ json: prompt });
199
+ }
200
+ }
201
+ else if (operation === 'getPrompt' || operation === 'renderPrompt') {
202
+ const slug = this.getNodeParameter('slug', i);
203
+ const versionParam = this.getNodeParameter('version', i, 'latest');
204
+ const version = versionParam === 'latest' ? 0 : Number(versionParam);
205
+ const url = version > 0
206
+ ? `${baseUrl}/api/public/prompts/${encodeURIComponent(slug)}/v/${version}`
207
+ : `${baseUrl}/api/public/prompts/${encodeURIComponent(slug)}`;
208
+ const options = {
209
+ method: 'GET',
210
+ url,
211
+ json: true,
212
+ };
213
+ const prompt = (await this.helpers.httpRequestWithAuthentication.call(this, 'promptLibraryApi', options));
214
+ if (operation === 'renderPrompt') {
215
+ let content = prompt.content;
216
+ const variablesData = this.getNodeParameter('variables', i, {});
217
+ const variablesList = variablesData.variable || [];
218
+ for (const v of variablesList) {
219
+ const varName = v.name;
220
+ const varValue = v.value;
221
+ if (varName) {
222
+ const pattern = new RegExp(`\\{\\{\\s*${varName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*\\}\\}`, 'g');
223
+ content = content.replace(pattern, varValue);
224
+ }
225
+ }
226
+ returnData.push({
227
+ json: {
228
+ ...prompt,
229
+ content,
230
+ rendered: true,
231
+ },
232
+ });
233
+ }
234
+ else {
235
+ returnData.push({ json: prompt });
236
+ }
237
+ }
238
+ }
239
+ catch (error) {
240
+ if (this.continueOnFail()) {
241
+ returnData.push({
242
+ json: { error: error.message },
243
+ });
244
+ continue;
245
+ }
246
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i });
247
+ }
248
+ }
249
+ return [returnData];
250
+ }
251
+ }
252
+ exports.PromptLibrary = PromptLibrary;
@@ -0,0 +1,31 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
+ <!-- Deepest doc (smallest, most faded, furthest back) -->
3
+ <rect x="18" y="6" width="28" height="36" rx="3" fill="#a5b4fc" opacity="0.3" transform="scale(0.82) translate(7, 4)"/>
4
+
5
+ <!-- Middle-back doc -->
6
+ <rect x="16" y="10" width="30" height="38" rx="3.5" fill="#818cf8" opacity="0.45" transform="scale(0.88) translate(4, 2)"/>
7
+
8
+ <!-- Middle doc -->
9
+ <rect x="14" y="14" width="32" height="40" rx="4" fill="#6366f1" opacity="0.6"/>
10
+ <rect x="19" y="20" width="18" height="2.5" rx="1.25" fill="#fff" opacity="0.5"/>
11
+ <rect x="19" y="25" width="14" height="2.5" rx="1.25" fill="#fff" opacity="0.4"/>
12
+ <rect x="19" y="30" width="16" height="2.5" rx="1.25" fill="#fff" opacity="0.35"/>
13
+
14
+ <!-- Front doc (largest, fully opaque, closest) -->
15
+ <rect x="12" y="18" width="36" height="42" rx="4.5" fill="#6366f1"/>
16
+ <!-- Subtle inner shadow/border -->
17
+ <rect x="12" y="18" width="36" height="42" rx="4.5" fill="none" stroke="#4f46e5" stroke-width="0.8"/>
18
+ <!-- Text lines -->
19
+ <rect x="18" y="25" width="24" height="3" rx="1.5" fill="#fff" opacity="0.9"/>
20
+ <rect x="18" y="31" width="19" height="3" rx="1.5" fill="#fff" opacity="0.7"/>
21
+ <rect x="18" y="37" width="22" height="3" rx="1.5" fill="#fff" opacity="0.6"/>
22
+ <rect x="18" y="43" width="15" height="3" rx="1.5" fill="#fff" opacity="0.5"/>
23
+ <!-- Cursor / prompt indicator -->
24
+ <rect x="18" y="49" width="2" height="3" rx="0.5" fill="#c7d2fe" opacity="0.8"/>
25
+
26
+ <!-- Floating sparkle/glow dots suggesting depth/space -->
27
+ <circle cx="50" cy="12" r="1.5" fill="#a5b4fc" opacity="0.6"/>
28
+ <circle cx="54" cy="20" r="1" fill="#c7d2fe" opacity="0.5"/>
29
+ <circle cx="8" cy="14" r="1.2" fill="#a5b4fc" opacity="0.4"/>
30
+ <circle cx="52" cy="8" r="0.8" fill="#e0e7ff" opacity="0.5"/>
31
+ </svg>
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "n8n-nodes-prompt-library",
3
+ "version": "0.1.0",
4
+ "description": "n8n community node to fetch and render prompts from n8n-library's prompt versioning system",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "n8n-community-node-package"
8
+ ],
9
+ "scripts": {
10
+ "build": "tsc && cp nodes/PromptLibrary/promptlibrary.svg dist/nodes/PromptLibrary/",
11
+ "lint": "tsc --noEmit",
12
+ "prepublishOnly": "npm run build"
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "n8n": {
18
+ "n8nNodesApiVersion": 1,
19
+ "credentials": [
20
+ "dist/credentials/PromptLibraryApi.credentials.js"
21
+ ],
22
+ "nodes": [
23
+ "dist/nodes/PromptLibrary/PromptLibrary.node.js"
24
+ ]
25
+ },
26
+ "devDependencies": {
27
+ "typescript": "~5.7.0"
28
+ },
29
+ "peerDependencies": {
30
+ "n8n-workflow": "*"
31
+ }
32
+ }