@miskokodi/n8n-nodes-kie-ai 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,76 @@
1
+ # @miskokodi/n8n-nodes-kie-ai
2
+
3
+ n8n community node that adds a **KIE.ai Chat Model** — use [KIE.ai](https://kie.ai)'s discounted LLM APIs (Gemini, GPT, Claude, DeepSeek, Grok) as the language model provider for **AI Agent**, chains, and any other LangChain root node, exactly like the built-in OpenRouter / OpenAI chat model nodes.
4
+
5
+ ## Why
6
+
7
+ KIE routes each LLM through its own OpenAI-compatible endpoint path
8
+ (`https://api.kie.ai/{model}/v1/chat/completions`) and has no `/models`
9
+ listing endpoint — which breaks n8n's stock OpenAI node (credential test
10
+ and model dropdown both fail). This node handles the path-based routing
11
+ internally and ships a model dropdown, so it Just Works.
12
+
13
+ ## Install
14
+
15
+ Self-hosted n8n → **Settings → Community Nodes → Install** → enter:
16
+
17
+ ```
18
+ @miskokodi/n8n-nodes-kie-ai
19
+ ```
20
+
21
+ (Requires `N8N_COMMUNITY_PACKAGES_ENABLED=true`, which is the default on self-hosted.)
22
+
23
+ ## Use
24
+
25
+ 1. Create a **KIE.ai API** credential with your API key (kie.ai → Dashboard → API Keys). The credential test validates the key against KIE's credit endpoint.
26
+ 2. Add **KIE.ai Chat Model** as the language model of your AI Agent / chain.
27
+ 3. Pick a model from the dropdown, or switch the field to an expression and pass any KIE model slug directly.
28
+
29
+ ### Options
30
+
31
+ Temperature, top-p, penalties, max tokens, retries, timeout — same surface as the built-in OpenAI chat model node. A **Base URL Override** option (with `{model}` placeholder) is included in case KIE changes its gateway layout.
32
+
33
+ ## Model list
34
+
35
+ KIE has no public models-list API, so the dropdown is a curated list in
36
+ `nodes/LmChatKieAi/LmChatKieAi.node.ts` (`KIE_MODELS`). PRs welcome when
37
+ KIE adds/renames models; the dropdown is wired through `loadOptions`, so a
38
+ remote fetch can be dropped in later without a schema change.
39
+
40
+ ## Development
41
+
42
+ ```bash
43
+ npm install
44
+ npm run build # tsc + copy icon to dist
45
+ ```
46
+
47
+ Local testing without publishing:
48
+
49
+ ```bash
50
+ # in this repo
51
+ npm run build && npm pack # produces miskokodi-n8n-nodes-kie-ai-0.1.0.tgz
52
+
53
+ # on your n8n host
54
+ cd ~/.n8n/nodes # create if missing
55
+ npm install /path/to/miskokodi-n8n-nodes-kie-ai-0.1.0.tgz
56
+ # restart n8n
57
+ ```
58
+
59
+ ## Publish
60
+
61
+ ```bash
62
+ npm login
63
+ npm publish --access public
64
+ ```
65
+
66
+ Then optionally submit for n8n's verified community node listing:
67
+ https://docs.n8n.io/integrations/creating-nodes/deploy/submit-community-nodes/
68
+
69
+ ## Notes
70
+
71
+ - Function calling / tools are supported (KIE's chat endpoints accept the standard `tools` param), so AI Agent tool use works. Behavior fidelity varies per underlying model, as with any aggregator.
72
+ - The `model` field in the request body is effectively ignored by KIE's gateway — the URL path decides the model. The node sets both consistently.
73
+
74
+ ## License
75
+
76
+ MIT
@@ -0,0 +1,9 @@
1
+ import type { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class KieAiApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ authenticate: IAuthenticateGeneric;
8
+ test: ICredentialTestRequest;
9
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KieAiApi = void 0;
4
+ class KieAiApi {
5
+ name = 'kieAiApi';
6
+ displayName = 'KIE.ai API';
7
+ documentationUrl = 'https://docs.kie.ai/';
8
+ properties = [
9
+ {
10
+ displayName: 'API Key',
11
+ name: 'apiKey',
12
+ type: 'string',
13
+ typeOptions: { password: true },
14
+ required: true,
15
+ default: '',
16
+ description: 'Your KIE.ai API key. Get it at https://kie.ai → Dashboard → API Keys.',
17
+ },
18
+ ];
19
+ authenticate = {
20
+ type: 'generic',
21
+ properties: {
22
+ headers: {
23
+ Authorization: '=Bearer {{$credentials.apiKey}}',
24
+ },
25
+ },
26
+ };
27
+ // KIE has no /models endpoint, so we validate the key against the
28
+ // account credit endpoint instead — it exists for every account and
29
+ // returns 401 on a bad key.
30
+ test = {
31
+ request: {
32
+ baseURL: 'https://api.kie.ai',
33
+ url: '/api/v1/chat/credit',
34
+ method: 'GET',
35
+ },
36
+ };
37
+ }
38
+ exports.KieAiApi = KieAiApi;
@@ -0,0 +1,10 @@
1
+ import { type ILoadOptionsFunctions, type INodePropertyOptions, type INodeType, type INodeTypeDescription, type ISupplyDataFunctions, type SupplyData } from 'n8n-workflow';
2
+ export declare class LmChatKieAi implements INodeType {
3
+ description: INodeTypeDescription;
4
+ methods: {
5
+ loadOptions: {
6
+ getModels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
7
+ };
8
+ };
9
+ supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData>;
10
+ }
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LmChatKieAi = void 0;
4
+ const openai_1 = require("@langchain/openai");
5
+ const n8n_workflow_1 = require("n8n-workflow");
6
+ /**
7
+ * KIE routes LLM traffic per-model via the URL path:
8
+ * POST https://api.kie.ai/{model-slug}/v1/chat/completions
9
+ * The `model` field in the request body is ignored by the gateway —
10
+ * the path segment is the source of truth. Each endpoint is
11
+ * OpenAI-chat-completions compatible (messages, tools, streaming).
12
+ *
13
+ * There is currently no public /models listing endpoint, so the
14
+ * dropdown is a curated list of the LLM slugs KIE exposes. Update
15
+ * KIE_MODELS below when KIE adds models, or use an expression to
16
+ * pass any slug directly.
17
+ */
18
+ const KIE_MODELS = [
19
+ // Google
20
+ { name: 'Gemini 3.1 Pro', value: 'gemini-3-1-pro' },
21
+ { name: 'Gemini 3 Pro', value: 'gemini-3-pro' },
22
+ { name: 'Gemini 3 Flash', value: 'gemini-3-flash' },
23
+ { name: 'Gemini 2.5 Pro', value: 'gemini-2-5-pro' },
24
+ { name: 'Gemini 2.5 Flash', value: 'gemini-2-5-flash' },
25
+ // OpenAI
26
+ { name: 'GPT-5.5', value: 'gpt-5-5' },
27
+ { name: 'GPT-5.4 Mini', value: 'gpt-5-4-mini' },
28
+ { name: 'GPT-5.2', value: 'gpt-5-2' },
29
+ // Anthropic
30
+ { name: 'Claude Opus 4.7', value: 'claude-opus-4-7' },
31
+ { name: 'Claude Sonnet 4.6', value: 'claude-sonnet-4-6' },
32
+ { name: 'Claude Haiku 4.5', value: 'claude-haiku-4-5' },
33
+ // DeepSeek
34
+ { name: 'DeepSeek Chat (V3)', value: 'deepseek-chat' },
35
+ { name: 'DeepSeek Reasoner (R1)', value: 'deepseek-reasoner' },
36
+ // xAI
37
+ { name: 'Grok 4.3', value: 'grok-4-3' },
38
+ { name: 'Grok 4.2 Fast', value: 'grok-4-2-fast' },
39
+ ];
40
+ class LmChatKieAi {
41
+ description = {
42
+ displayName: 'KIE.ai Chat Model',
43
+ name: 'lmChatKieAi',
44
+ icon: 'file:kieai.svg',
45
+ group: ['transform'],
46
+ version: 1,
47
+ description: 'Use KIE.ai discounted LLM APIs (Gemini, GPT, Claude, DeepSeek, Grok) as the language model for AI Agents and chains',
48
+ defaults: {
49
+ name: 'KIE.ai Chat Model',
50
+ },
51
+ codex: {
52
+ categories: ['AI'],
53
+ subcategories: {
54
+ AI: ['Language Models', 'Root Nodes'],
55
+ 'Language Models': ['Chat Models (Recommended)'],
56
+ },
57
+ resources: {
58
+ primaryDocumentation: [
59
+ {
60
+ url: 'https://docs.kie.ai/',
61
+ },
62
+ ],
63
+ },
64
+ },
65
+ // Sub-node: no main input, supplies an ai_languageModel connection
66
+ inputs: [],
67
+ outputs: [n8n_workflow_1.NodeConnectionTypes.AiLanguageModel],
68
+ outputNames: ['Model'],
69
+ credentials: [
70
+ {
71
+ name: 'kieAiApi',
72
+ required: true,
73
+ },
74
+ ],
75
+ properties: [
76
+ {
77
+ displayName: 'KIE routes each model via its own endpoint path. Pick a model from the list, or switch the field to an expression to pass any KIE model slug (e.g. "gemini-3-flash").',
78
+ name: 'notice',
79
+ type: 'notice',
80
+ default: '',
81
+ },
82
+ {
83
+ displayName: 'Model',
84
+ name: 'model',
85
+ type: 'options',
86
+ description: 'The KIE.ai model to use. Choose from the list, or specify a slug using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
87
+ typeOptions: {
88
+ loadOptionsMethod: 'getModels',
89
+ },
90
+ default: 'gemini-3-flash',
91
+ required: true,
92
+ },
93
+ {
94
+ displayName: 'Options',
95
+ name: 'options',
96
+ type: 'collection',
97
+ placeholder: 'Add Option',
98
+ default: {},
99
+ options: [
100
+ {
101
+ displayName: 'Base URL Override',
102
+ name: 'baseURL',
103
+ type: 'string',
104
+ default: '',
105
+ placeholder: 'https://api.kie.ai/{model}/v1',
106
+ description: 'Override the endpoint base URL. Use {model} as a placeholder for the model slug. Leave empty for the default KIE gateway.',
107
+ },
108
+ {
109
+ displayName: 'Frequency Penalty',
110
+ name: 'frequencyPenalty',
111
+ type: 'number',
112
+ typeOptions: { minValue: -2, maxValue: 2, numberPrecision: 1 },
113
+ default: 0,
114
+ description: 'Positive values penalize tokens based on their existing frequency, decreasing repetition',
115
+ },
116
+ {
117
+ displayName: 'Maximum Number of Tokens',
118
+ name: 'maxTokens',
119
+ type: 'number',
120
+ default: -1,
121
+ description: 'Maximum tokens to generate in the completion. -1 lets the provider decide.',
122
+ typeOptions: { maxValue: 128000 },
123
+ },
124
+ {
125
+ displayName: 'Max Retries',
126
+ name: 'maxRetries',
127
+ type: 'number',
128
+ default: 2,
129
+ description: 'Maximum number of retries on failed requests',
130
+ },
131
+ {
132
+ displayName: 'Presence Penalty',
133
+ name: 'presencePenalty',
134
+ type: 'number',
135
+ typeOptions: { minValue: -2, maxValue: 2, numberPrecision: 1 },
136
+ default: 0,
137
+ description: 'Positive values penalize tokens that already appeared, increasing topic diversity',
138
+ },
139
+ {
140
+ displayName: 'Sampling Temperature',
141
+ name: 'temperature',
142
+ type: 'number',
143
+ typeOptions: { minValue: 0, maxValue: 2, numberPrecision: 1 },
144
+ default: 0.7,
145
+ description: 'Controls randomness. Lower is more deterministic, higher more creative.',
146
+ },
147
+ {
148
+ displayName: 'Timeout (Ms)',
149
+ name: 'timeout',
150
+ type: 'number',
151
+ default: 300000,
152
+ description: 'Maximum request time in milliseconds',
153
+ },
154
+ {
155
+ displayName: 'Top P',
156
+ name: 'topP',
157
+ type: 'number',
158
+ typeOptions: { minValue: 0, maxValue: 1, numberPrecision: 1 },
159
+ default: 1,
160
+ description: 'Nucleus sampling: consider only tokens within this cumulative probability mass',
161
+ },
162
+ ],
163
+ },
164
+ ],
165
+ };
166
+ methods = {
167
+ loadOptions: {
168
+ async getModels() {
169
+ // No public models-list endpoint on KIE yet — serve the curated
170
+ // list. Kept as a loadOptions method so a remote fetch can be
171
+ // dropped in here later without changing the node schema.
172
+ return KIE_MODELS.map(({ name, value }) => ({ name, value }));
173
+ },
174
+ },
175
+ };
176
+ async supplyData(itemIndex) {
177
+ const credentials = await this.getCredentials('kieAiApi');
178
+ const modelSlug = this.getNodeParameter('model', itemIndex);
179
+ const options = this.getNodeParameter('options', itemIndex, {});
180
+ const baseURL = (options.baseURL && options.baseURL.trim() !== ''
181
+ ? options.baseURL
182
+ : 'https://api.kie.ai/{model}/v1').replace('{model}', modelSlug);
183
+ const model = new openai_1.ChatOpenAI({
184
+ apiKey: credentials.apiKey,
185
+ model: modelSlug,
186
+ temperature: options.temperature,
187
+ topP: options.topP,
188
+ frequencyPenalty: options.frequencyPenalty,
189
+ presencePenalty: options.presencePenalty,
190
+ maxRetries: options.maxRetries ?? 2,
191
+ timeout: options.timeout ?? 300000,
192
+ ...(options.maxTokens && options.maxTokens > 0
193
+ ? { maxTokens: options.maxTokens }
194
+ : {}),
195
+ configuration: {
196
+ baseURL,
197
+ },
198
+ });
199
+ return {
200
+ response: model,
201
+ };
202
+ }
203
+ }
204
+ exports.LmChatKieAi = LmChatKieAi;
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60">
2
+ <rect width="60" height="60" rx="12" fill="#0F0F14"/>
3
+ <path d="M16 14v32h7V33.5l4-4.4L38.5 46H47L32 27.8 45.5 14h-8.9L23 28.6V14z" fill="#7C5CFF"/>
4
+ <circle cx="47" cy="15" r="5" fill="#00E5A0"/>
5
+ </svg>
package/index.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = {};
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@miskokodi/n8n-nodes-kie-ai",
3
+ "version": "0.1.0",
4
+ "description": "n8n community node: KIE.ai Chat Model — use KIE's discounted LLM APIs (Gemini, GPT, Claude, DeepSeek, Grok) as a language model provider for AI Agents and chains, just like the OpenRouter node.",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "kie",
8
+ "kie.ai",
9
+ "llm",
10
+ "ai",
11
+ "langchain",
12
+ "chat-model"
13
+ ],
14
+ "license": "MIT",
15
+ "author": {
16
+ "name": "Martin",
17
+ "email": "mconqueror17@gmail.com"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/YOUR_GH_USER/n8n-nodes-kie-ai.git"
22
+ },
23
+ "engines": {
24
+ "node": ">=18"
25
+ },
26
+ "main": "index.js",
27
+ "scripts": {
28
+ "build": "tsc && npm run copy:assets",
29
+ "copy:assets": "node scripts/copy-assets.js",
30
+ "dev": "tsc --watch",
31
+ "lint": "eslint nodes credentials --ext .ts",
32
+ "prepublishOnly": "npm run build"
33
+ },
34
+ "files": [
35
+ "dist"
36
+ ],
37
+ "n8n": {
38
+ "n8nNodesApiVersion": 1,
39
+ "credentials": [
40
+ "dist/credentials/KieAiApi.credentials.js"
41
+ ],
42
+ "nodes": [
43
+ "dist/nodes/LmChatKieAi/LmChatKieAi.node.js"
44
+ ]
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^22.0.0",
48
+ "n8n-workflow": "^1.70.0",
49
+ "typescript": "^5.6.0"
50
+ },
51
+ "dependencies": {
52
+ "@langchain/openai": "^0.3.14"
53
+ },
54
+ "peerDependencies": {
55
+ "n8n-workflow": "*"
56
+ }
57
+ }