n8n-nodes-github-copilot 2.0.0 → 3.0.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 CHANGED
@@ -4,15 +4,27 @@
4
4
  ![n8n](https://img.shields.io/badge/n8n-Community%20Node-red?logo=n8n)
5
5
  ![License](https://img.shields.io/badge/license-MIT-green)
6
6
 
7
- Este é um **community node** para [n8n](https://n8n.io/) que integra o **GitHub Copilot CLI** diretamente nos seus workflows de automação, permitindo gerar código, explicar funcionalidades e obter sugestões de comandos shell usando IA.
7
+ Este é um **community node** para [n8n](https://n8n.io/) que integra o **GitHub Copilot** de duas formas: através do CLI tradicional e da nova **API oficial do GitHub Copilot**, permitindo acesso direto aos modelos avançados de IA como GPT-5, Claude Opus 4.1, Gemini 2.5 Pro e muito mais usando seus créditos existentes do Copilot.
8
8
 
9
- ## 🎯 Funcionalidades
9
+ ## 🚀 Nodes Disponíveis
10
10
 
11
+ ### 1. GitHub Copilot (CLI)
11
12
  - **Sugestões de Código**: Gere código em múltiplas linguagens de programação
12
13
  - **Explicação de Código**: Obtenha explicações detalhadas sobre funcionalidades de código
13
14
  - **Comandos Shell**: Receba sugestões de comandos para Git, Docker, NPM e muito mais
14
15
  - **Múltiplas Linguagens**: Suporte para JavaScript, TypeScript, Python, Ruby, Java, C#, Go, PHP, C++, Rust, SQL, HTML, CSS
15
- - **Integração Nativa**: Usa o GitHub Copilot CLI oficial por baixo dos panos
16
+
17
+ ### 2. GitHub Copilot Chat API (Novo! ⭐)
18
+ - **Chat Completion**: Conversas diretas com modelos avançados de IA
19
+ - **Análise de Imagens**: Processamento de imagens com modelos de visão
20
+ - **Transcrição de Áudio**: Conversão de áudio para texto (planejado)
21
+ - **Modelos Disponíveis**: GPT-5, GPT-5 Mini, Claude Opus 4.1, Gemini 2.5 Pro, Grok Code Fast 1, GPT-4.1 Copilot
22
+ - **Sem Custos Extras**: Usa seus créditos existentes do GitHub Copilot
23
+
24
+ ## 🎯 Funcionalidades
25
+
26
+ - **Integração Dual**: CLI tradicional + API oficial do GitHub Copilot
27
+ - **Modelos Premium**: Acesso a GPT-5, Claude, Gemini através de sua assinatura Copilot
16
28
 
17
29
  ## 📋 Pré-requisitos
18
30
 
@@ -93,18 +105,49 @@ npm install n8n-nodes-github-copilot
93
105
 
94
106
  ## ⚙️ Configuração
95
107
 
96
- ### 1. Configurar Credenciais
97
- 1. No n8n, vá para **Settings > Credentials**
98
- 2. Clique em **Create New Credential**
99
- 3. Selecione **GitHub API**
100
- 4. Insira seu Personal Access Token
101
- 5. Teste a conexão
108
+ ### 🔐 IMPORTANTE: Autenticação
109
+
110
+ **GitHub Copilot CLI tem requisitos específicos de autenticação:**
111
+
112
+ #### **O que FUNCIONA:**
113
+ - **Autenticação Local**: `gh auth login` (recomendado para servidores)
114
+ - **Tokens do GitHub CLI**: Gerados por `gh auth token` após fazer login
115
+
116
+ #### ❌ **O que NÃO FUNCIONA:**
117
+ - **Personal Access Tokens** criados no site do GitHub
118
+ - **OAuth App Tokens** de aplicações externas
119
+ - **GitHub App Tokens** de aplicações personalizadas
120
+
121
+ ### 🛠️ **Configuração Recomendada:**
122
+
123
+ #### **Opção 1: Autenticação Local (Servidores)**
124
+ ```bash
125
+ # No servidor onde roda o n8n
126
+ gh auth login
127
+ gh extension install github/gh-copilot
128
+
129
+ # Testar se funciona
130
+ gh copilot explain "ls -la"
131
+ ```
132
+
133
+ #### **Opção 2: Token Manual (Para workflows específicos)**
134
+ ```bash
135
+ # Primeiro faça login local
136
+ gh auth login
137
+
138
+ # Depois obtenha o token
139
+ gh auth token
140
+ # Resultado: gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
141
+
142
+ # Use este token no campo "GitHub Token (Optional)" do node
143
+ ```
102
144
 
103
- ### 2. Adicionar o Node
145
+ ### 1. Adicionar o Node
104
146
  1. Crie um novo workflow
105
147
  2. Procure por **GitHub Copilot** na lista de nodes
106
148
  3. Arraste para o canvas
107
- 4. Configure as credenciais criadas anteriormente
149
+ 4. **Deixe o campo token vazio** (se o servidor tem `gh auth login`)
150
+ 5. **OU** insira um token gerado por `gh auth token`
108
151
 
109
152
  ## 🎮 Como Usar
110
153
 
@@ -106,7 +106,7 @@ class GitHubCopilot {
106
106
  typeOptions: { password: true },
107
107
  default: '',
108
108
  placeholder: 'gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
109
- description: 'Optional GitHub Personal Access Token. If not provided, will use local GitHub CLI authentication. Create at: https://github.com/settings/tokens',
109
+ description: '⚠️ IMPORTANT: Only tokens generated by GitHub CLI itself work with Copilot. Personal Access Tokens from GitHub website DO NOT work. If not provided, will use local "gh auth login" authentication. To get a working token, use: gh auth token',
110
110
  },
111
111
  {
112
112
  displayName: 'Filter Output',
@@ -268,8 +268,8 @@ class GitHubCopilot {
268
268
  }
269
269
  else if (stderr.includes('401') || stderr.includes('Unauthorized') || stderr.includes('Bad credentials')) {
270
270
  const tokenHelp = useToken
271
- ? ' Please check your token has the required scopes: repo, read:org, gist, admin:public_key. Create new token at: https://github.com/settings/tokens'
272
- : ' Please run "gh auth login" on the server or provide a manual token.';
271
+ ? ' IMPORTANT: Only tokens generated by "gh auth token" command work with Copilot. Personal Access Tokens from GitHub website DO NOT work. Try: run "gh auth login" first, then use "gh auth token" to get a working token.'
272
+ : ' Please run "gh auth login" on the server first, or provide a token generated by "gh auth token" command.';
273
273
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub authentication failed (HTTP 401).${tokenHelp}${debugInfo} Full error response: ${stderr}`);
274
274
  }
275
275
  else if (stderr.includes('403') || stderr.includes('Forbidden')) {
@@ -0,0 +1,5 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class GitHubCopilotChatAPI implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,402 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.GitHubCopilotChatAPI = void 0;
27
+ async function makeApiRequest(context, endpoint, body) {
28
+ const credentials = await context.getCredentials('githubApi');
29
+ const options = {
30
+ method: 'POST',
31
+ headers: {
32
+ 'Authorization': `Bearer ${credentials.accessToken}`,
33
+ 'Content-Type': 'application/json',
34
+ 'User-Agent': 'n8n-github-copilot-chat/2.0.0',
35
+ },
36
+ body: JSON.stringify(body),
37
+ };
38
+ const response = await fetch(`https://api.githubcopilot.com${endpoint}`, options);
39
+ if (!response.ok) {
40
+ const errorText = await response.text();
41
+ throw new Error(`GitHub Copilot API error: ${response.status} ${response.statusText}. ${errorText}`);
42
+ }
43
+ return await response.json();
44
+ }
45
+ function getMimeType(filename) {
46
+ const ext = filename.toLowerCase().split('.').pop();
47
+ switch (ext) {
48
+ case 'jpg':
49
+ case 'jpeg':
50
+ return 'image/jpeg';
51
+ case 'png':
52
+ return 'image/png';
53
+ case 'webp':
54
+ return 'image/webp';
55
+ case 'gif':
56
+ return 'image/gif';
57
+ default:
58
+ return 'image/jpeg';
59
+ }
60
+ }
61
+ class GitHubCopilotChatAPI {
62
+ constructor() {
63
+ this.description = {
64
+ displayName: 'GitHub Copilot Chat API',
65
+ name: 'gitHubCopilotChatAPI',
66
+ icon: 'file:copilot.svg',
67
+ group: ['AI'],
68
+ version: 1,
69
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["model"]}}',
70
+ description: 'Use official GitHub Copilot Chat API with your subscription - access GPT-5, Claude, Gemini and more',
71
+ defaults: {
72
+ name: 'GitHub Copilot Chat API',
73
+ },
74
+ inputs: ["main"],
75
+ outputs: ["main"],
76
+ credentials: [
77
+ {
78
+ name: 'githubApi',
79
+ required: true,
80
+ },
81
+ ],
82
+ properties: [
83
+ {
84
+ displayName: 'Operation',
85
+ name: 'operation',
86
+ type: 'options',
87
+ options: [
88
+ {
89
+ name: 'Chat Completion',
90
+ value: 'chatCompletion',
91
+ description: 'Send a message and get AI response using Copilot models',
92
+ },
93
+ {
94
+ name: 'Audio Transcription',
95
+ value: 'audioTranscription',
96
+ description: 'Transcribe audio file to text using Copilot',
97
+ },
98
+ {
99
+ name: 'Image Analysis',
100
+ value: 'imageAnalysis',
101
+ description: 'Analyze image with AI (vision models)',
102
+ },
103
+ ],
104
+ default: 'chatCompletion',
105
+ },
106
+ {
107
+ displayName: 'Model',
108
+ name: 'model',
109
+ type: 'options',
110
+ options: [
111
+ {
112
+ name: 'GPT-5 (Latest)',
113
+ value: 'gpt-5',
114
+ description: 'OpenAI GPT-5 - Latest and most advanced model',
115
+ },
116
+ {
117
+ name: 'GPT-5 Mini',
118
+ value: 'gpt-5-mini',
119
+ description: 'OpenAI GPT-5 Mini - Faster and more efficient',
120
+ },
121
+ {
122
+ name: 'Claude Opus 4.1',
123
+ value: 'claude-opus-4.1',
124
+ description: 'Anthropic Claude Opus 4.1 - Advanced reasoning',
125
+ },
126
+ {
127
+ name: 'Gemini 2.5 Pro',
128
+ value: 'gemini-2.5-pro',
129
+ description: 'Google Gemini 2.5 Pro - Multimodal capabilities',
130
+ },
131
+ {
132
+ name: 'Grok Code Fast 1',
133
+ value: 'grok-code-fast-1',
134
+ description: 'xAI Grok - Optimized for coding tasks',
135
+ },
136
+ {
137
+ name: 'GPT-4.1 Copilot',
138
+ value: 'gpt-4.1-copilot',
139
+ description: 'GitHub Copilot optimized GPT-4.1 model',
140
+ },
141
+ ],
142
+ default: 'gpt-5',
143
+ description: 'Choose the AI model from your Copilot subscription',
144
+ },
145
+ {
146
+ displayName: 'Message',
147
+ name: 'message',
148
+ type: 'string',
149
+ typeOptions: {
150
+ rows: 4,
151
+ },
152
+ default: '',
153
+ placeholder: 'Enter your message here...',
154
+ description: 'The message to send to the AI',
155
+ displayOptions: {
156
+ show: {
157
+ operation: ['chatCompletion', 'imageAnalysis'],
158
+ },
159
+ },
160
+ },
161
+ {
162
+ displayName: 'Audio File',
163
+ name: 'audioFile',
164
+ type: 'string',
165
+ default: '',
166
+ placeholder: 'Path to audio file or base64 data',
167
+ description: 'Audio file to transcribe (supports MP3, WAV, M4A, FLAC, OGG)',
168
+ displayOptions: {
169
+ show: {
170
+ operation: ['audioTranscription'],
171
+ },
172
+ },
173
+ },
174
+ {
175
+ displayName: 'Audio Language',
176
+ name: 'audioLanguage',
177
+ type: 'options',
178
+ options: [
179
+ { name: 'Auto-detect', value: 'auto' },
180
+ { name: 'Portuguese (Brazil)', value: 'pt' },
181
+ { name: 'English', value: 'en' },
182
+ { name: 'Spanish', value: 'es' },
183
+ { name: 'French', value: 'fr' },
184
+ { name: 'German', value: 'de' },
185
+ { name: 'Italian', value: 'it' },
186
+ { name: 'Japanese', value: 'ja' },
187
+ { name: 'Chinese', value: 'zh' },
188
+ ],
189
+ default: 'auto',
190
+ description: 'Language of the audio (helps with accuracy)',
191
+ displayOptions: {
192
+ show: {
193
+ operation: ['audioTranscription'],
194
+ },
195
+ },
196
+ },
197
+ {
198
+ displayName: 'Image File',
199
+ name: 'imageFile',
200
+ type: 'string',
201
+ default: '',
202
+ placeholder: 'Path to image file or base64 data',
203
+ description: 'Image file to analyze (supports JPG, PNG, WebP, GIF)',
204
+ displayOptions: {
205
+ show: {
206
+ operation: ['imageAnalysis'],
207
+ },
208
+ },
209
+ },
210
+ {
211
+ displayName: 'System Prompt',
212
+ name: 'systemPrompt',
213
+ type: 'string',
214
+ typeOptions: {
215
+ rows: 2,
216
+ },
217
+ default: '',
218
+ placeholder: 'You are a helpful assistant...',
219
+ description: 'Optional system prompt to set AI behavior',
220
+ displayOptions: {
221
+ show: {
222
+ operation: ['chatCompletion', 'imageAnalysis'],
223
+ },
224
+ },
225
+ },
226
+ {
227
+ displayName: 'Temperature',
228
+ name: 'temperature',
229
+ type: 'number',
230
+ typeOptions: {
231
+ minValue: 0,
232
+ maxValue: 2,
233
+ numberStepSize: 0.1,
234
+ },
235
+ default: 1,
236
+ description: 'Controls randomness: 0 = focused, 2 = creative',
237
+ displayOptions: {
238
+ show: {
239
+ operation: ['chatCompletion', 'imageAnalysis'],
240
+ },
241
+ },
242
+ },
243
+ {
244
+ displayName: 'Max Tokens',
245
+ name: 'maxTokens',
246
+ type: 'number',
247
+ typeOptions: {
248
+ minValue: 1,
249
+ maxValue: 8192,
250
+ },
251
+ default: 2000,
252
+ description: 'Maximum tokens in response',
253
+ displayOptions: {
254
+ show: {
255
+ operation: ['chatCompletion', 'imageAnalysis'],
256
+ },
257
+ },
258
+ },
259
+ ],
260
+ };
261
+ }
262
+ async execute() {
263
+ const items = this.getInputData();
264
+ const returnData = [];
265
+ for (let i = 0; i < items.length; i++) {
266
+ try {
267
+ const operation = this.getNodeParameter('operation', i);
268
+ const model = this.getNodeParameter('model', i);
269
+ let result;
270
+ if (operation === 'chatCompletion') {
271
+ const message = this.getNodeParameter('message', i);
272
+ const systemPrompt = this.getNodeParameter('systemPrompt', i);
273
+ const temperature = this.getNodeParameter('temperature', i);
274
+ const maxTokens = this.getNodeParameter('maxTokens', i);
275
+ const messages = [];
276
+ if (systemPrompt) {
277
+ messages.push({ role: 'system', content: systemPrompt });
278
+ }
279
+ messages.push({ role: 'user', content: message });
280
+ const requestBody = {
281
+ model: model,
282
+ messages: messages,
283
+ temperature: temperature,
284
+ max_tokens: maxTokens,
285
+ stream: false,
286
+ };
287
+ const response = await makeApiRequest(this, '/chat/completions', requestBody);
288
+ result = {
289
+ response: response.choices[0].message.content,
290
+ model: model,
291
+ usage: response.usage,
292
+ finish_reason: response.choices[0].finish_reason,
293
+ timestamp: new Date().toISOString(),
294
+ };
295
+ }
296
+ else if (operation === 'audioTranscription') {
297
+ const audioFile = this.getNodeParameter('audioFile', i);
298
+ const language = this.getNodeParameter('audioLanguage', i);
299
+ const transcriptionPrompt = language === 'auto'
300
+ ? `Please transcribe this audio file to text. Detect the language automatically and provide the transcription.`
301
+ : `Please transcribe this audio file to text. The audio is in ${language} language.`;
302
+ const messages = [
303
+ {
304
+ role: 'system',
305
+ content: 'You are an expert at audio transcription. When given an audio file, provide an accurate transcription of the spoken content.'
306
+ },
307
+ {
308
+ role: 'user',
309
+ content: `${transcriptionPrompt}\n\nAudio file: ${audioFile}`
310
+ }
311
+ ];
312
+ const requestBody = {
313
+ model: model,
314
+ messages: messages,
315
+ temperature: 0.1,
316
+ max_tokens: 4000,
317
+ stream: false,
318
+ };
319
+ const response = await makeApiRequest(this, '/chat/completions', requestBody);
320
+ result = {
321
+ transcription: response.choices[0].message.content,
322
+ language: language,
323
+ model: model,
324
+ usage: response.usage,
325
+ timestamp: new Date().toISOString(),
326
+ };
327
+ }
328
+ else if (operation === 'imageAnalysis') {
329
+ const message = this.getNodeParameter('message', i);
330
+ const imageFile = this.getNodeParameter('imageFile', i);
331
+ const systemPrompt = this.getNodeParameter('systemPrompt', i);
332
+ const temperature = this.getNodeParameter('temperature', i);
333
+ const maxTokens = this.getNodeParameter('maxTokens', i);
334
+ let imageBase64;
335
+ if (imageFile.startsWith('data:image/')) {
336
+ imageBase64 = imageFile;
337
+ }
338
+ else if (imageFile.match(/^[A-Za-z0-9+/=]+$/)) {
339
+ imageBase64 = `data:image/jpeg;base64,${imageFile}`;
340
+ }
341
+ else {
342
+ const fs = await Promise.resolve().then(() => __importStar(require('fs')));
343
+ const imageBuffer = fs.readFileSync(imageFile);
344
+ const mimeType = getMimeType(imageFile);
345
+ imageBase64 = `data:${mimeType};base64,${imageBuffer.toString('base64')}`;
346
+ }
347
+ const messages = [];
348
+ if (systemPrompt) {
349
+ messages.push({ role: 'system', content: systemPrompt });
350
+ }
351
+ messages.push({
352
+ role: 'user',
353
+ content: [
354
+ { type: 'text', text: message },
355
+ { type: 'image_url', image_url: { url: imageBase64 } }
356
+ ]
357
+ });
358
+ const requestBody = {
359
+ model: model,
360
+ messages: messages,
361
+ temperature: temperature,
362
+ max_tokens: maxTokens,
363
+ stream: false,
364
+ };
365
+ const response = await makeApiRequest(this, '/chat/completions', requestBody);
366
+ result = {
367
+ response: response.choices[0].message.content,
368
+ model: model,
369
+ usage: response.usage,
370
+ finish_reason: response.choices[0].finish_reason,
371
+ timestamp: new Date().toISOString(),
372
+ };
373
+ }
374
+ else {
375
+ throw new Error(`Unknown operation: ${operation}`);
376
+ }
377
+ returnData.push({
378
+ json: result,
379
+ pairedItem: { item: i },
380
+ });
381
+ }
382
+ catch (error) {
383
+ if (this.continueOnFail()) {
384
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
385
+ returnData.push({
386
+ json: {
387
+ error: errorMessage,
388
+ operation: this.getNodeParameter('operation', i),
389
+ model: this.getNodeParameter('model', i),
390
+ },
391
+ pairedItem: { item: i },
392
+ });
393
+ }
394
+ else {
395
+ throw error;
396
+ }
397
+ }
398
+ }
399
+ return [returnData];
400
+ }
401
+ }
402
+ exports.GitHubCopilotChatAPI = GitHubCopilotChatAPI;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "n8n-nodes-github-copilot",
3
- "version": "2.0.0",
4
- "description": "n8n community node for GitHub Copilot CLI integration",
3
+ "version": "3.0.0",
4
+ "description": "n8n community node for GitHub Copilot with CLI integration and official Chat API access to GPT-5, Claude, Gemini and more using your existing Copilot credits",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/sufficit/n8n-nodes-github-copilot",
7
7
  "author": {
@@ -31,7 +31,8 @@
31
31
  "dist/credentials/GitHubApiManual.credentials.js"
32
32
  ],
33
33
  "nodes": [
34
- "dist/nodes/GitHubCopilot/GitHubCopilot.node.js"
34
+ "dist/nodes/GitHubCopilot/GitHubCopilot.node.js",
35
+ "dist/nodes/GitHubCopilotChatAPI/GitHubCopilotChatAPI.node.js"
35
36
  ]
36
37
  },
37
38
  "keywords": [
@@ -39,6 +40,12 @@
39
40
  "github",
40
41
  "copilot",
41
42
  "ai",
43
+ "gpt-5",
44
+ "claude",
45
+ "gemini",
46
+ "chat-completion",
47
+ "image-analysis",
48
+ "audio-transcription",
42
49
  "code-generation",
43
50
  "automation"
44
51
  ],