n8n-nodes-github-copilot 1.2.2 → 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
 
@@ -59,53 +59,7 @@ class GitHubCopilot {
59
59
  },
60
60
  inputs: ["main"],
61
61
  outputs: ["main"],
62
- credentials: [
63
- {
64
- name: 'gitHubApi',
65
- displayName: 'GitHub API (OAuth2)',
66
- required: false,
67
- displayOptions: {
68
- show: {
69
- authType: ['oauth2'],
70
- },
71
- },
72
- },
73
- {
74
- name: 'gitHubApiManual',
75
- displayName: 'GitHub API (Manual Token)',
76
- required: false,
77
- displayOptions: {
78
- show: {
79
- authType: ['manual'],
80
- },
81
- },
82
- },
83
- ],
84
62
  properties: [
85
- {
86
- displayName: 'Authentication Type',
87
- name: 'authType',
88
- type: 'options',
89
- options: [
90
- {
91
- name: 'Local CLI Authentication',
92
- value: 'local',
93
- description: 'Use GitHub CLI local authentication (recommended)',
94
- },
95
- {
96
- name: 'OAuth2 (Automatic)',
97
- value: 'oauth2',
98
- description: 'Use OAuth2 authentication configured in n8n',
99
- },
100
- {
101
- name: 'Manual Token',
102
- value: 'manual',
103
- description: 'Use manually entered GitHub token',
104
- },
105
- ],
106
- default: 'local',
107
- description: 'Choose how to authenticate with GitHub',
108
- },
109
63
  {
110
64
  displayName: 'Operation',
111
65
  name: 'operation',
@@ -145,6 +99,15 @@ class GitHubCopilot {
145
99
  placeholder: 'Enter your request...',
146
100
  description: 'What you want GitHub Copilot to help with',
147
101
  },
102
+ {
103
+ displayName: 'GitHub Token (Optional)',
104
+ name: 'githubToken',
105
+ type: 'string',
106
+ typeOptions: { password: true },
107
+ default: '',
108
+ placeholder: 'gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
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
+ },
148
111
  {
149
112
  displayName: 'Filter Output',
150
113
  name: 'filterOutput',
@@ -220,39 +183,9 @@ class GitHubCopilot {
220
183
  const operation = this.getNodeParameter('operation', i);
221
184
  const prompt = this.getNodeParameter('prompt', i);
222
185
  const context = this.getNodeParameter('context', i, '');
223
- const authType = this.getNodeParameter('authType', i);
224
- let accessToken;
225
- let credentialType = '';
226
- if (authType === 'local') {
227
- credentialType = 'Local CLI';
228
- accessToken = undefined;
229
- }
230
- else if (authType === 'oauth2') {
231
- const oauthCredentials = await this.getCredentials('gitHubApi');
232
- console.log('OAuth2 credentials object:', JSON.stringify(oauthCredentials, null, 2));
233
- const creds = oauthCredentials;
234
- const oauthTokenData = creds === null || creds === void 0 ? void 0 : creds.oauthTokenData;
235
- if ((oauthTokenData === null || oauthTokenData === void 0 ? void 0 : oauthTokenData.access_token) && typeof oauthTokenData.access_token === 'string') {
236
- accessToken = oauthTokenData.access_token;
237
- credentialType = 'OAuth2';
238
- console.log('Using OAuth2 token from oauthTokenData.access_token:', accessToken.substring(0, 8) + '...');
239
- }
240
- else {
241
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `OAuth2 token not found in oauthTokenData.access_token. Available fields: ${Object.keys(oauthCredentials || {}).join(', ')}. Please switch to Manual Token.`);
242
- }
243
- }
244
- else {
245
- const manualCredentials = await this.getCredentials('gitHubApiManual');
246
- if ((manualCredentials === null || manualCredentials === void 0 ? void 0 : manualCredentials.accessToken) && typeof manualCredentials.accessToken === 'string') {
247
- accessToken = manualCredentials.accessToken;
248
- credentialType = 'Manual Token';
249
- const tokenPrefix = accessToken.substring(0, 4);
250
- console.log('Using manual token with prefix:', tokenPrefix + '...');
251
- }
252
- else {
253
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Manual token credentials not found or invalid. Please configure Manual Token authentication or switch to OAuth2.');
254
- }
255
- }
186
+ const githubToken = this.getNodeParameter('githubToken', i, '');
187
+ const useToken = githubToken && githubToken.trim() !== '';
188
+ const authMethod = useToken ? 'Manual Token' : 'Local CLI';
256
189
  let command;
257
190
  let fullPrompt = prompt;
258
191
  if (context) {
@@ -297,9 +230,8 @@ class GitHubCopilot {
297
230
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
298
231
  }
299
232
  console.log('Executing command:', command);
300
- console.log('Auth type:', authType);
301
- console.log('Token prefix:', accessToken ? accessToken.substring(0, 8) + '...' : 'none (using local CLI auth)');
302
- console.log('Token type:', accessToken ? (accessToken.startsWith('gho_') ? 'OAuth' : accessToken.startsWith('ghp_') ? 'Classic' : 'Unknown') : 'Local CLI');
233
+ console.log('Auth method:', authMethod);
234
+ console.log('Using token:', useToken ? 'Yes (Manual)' : 'No (Local CLI)');
303
235
  let stdout = '';
304
236
  let stderr = '';
305
237
  try {
@@ -307,9 +239,9 @@ class GitHubCopilot {
307
239
  ...process.env,
308
240
  HOME: '/opt/n8n-source/packages/cli/bin',
309
241
  };
310
- if (authType !== 'local' && accessToken) {
311
- envVars.GH_TOKEN = accessToken;
312
- envVars.GITHUB_TOKEN = accessToken;
242
+ if (useToken) {
243
+ envVars.GH_TOKEN = githubToken;
244
+ envVars.GITHUB_TOKEN = githubToken;
313
245
  }
314
246
  const result = await execAsync(command, {
315
247
  env: envVars,
@@ -324,74 +256,27 @@ class GitHubCopilot {
324
256
  stderr = err.stderr || err.message || String(execError);
325
257
  stdout = err.stdout || '';
326
258
  }
327
- async function checkTokenPermissions(token) {
328
- try {
329
- const authCheckCommand = `/usr/bin/gh auth status`;
330
- const apiCheckCommand = `/usr/bin/gh api user`;
331
- const envVarsCheck = {
332
- ...process.env,
333
- HOME: '/opt/n8n-source/packages/cli/bin',
334
- GH_TOKEN: token,
335
- GITHUB_TOKEN: token,
336
- };
337
- let permissionInfo = '';
338
- try {
339
- const authResult = await execAsync(authCheckCommand, { env: envVarsCheck, timeout: 10000 });
340
- permissionInfo += `Auth Status: ${authResult.stdout.trim()}\n`;
341
- }
342
- catch (authError) {
343
- const err = authError;
344
- permissionInfo += `Auth Status Error: ${err.stderr || err.message}\n`;
345
- }
346
- try {
347
- const apiResult = await execAsync(apiCheckCommand, { env: envVarsCheck, timeout: 10000 });
348
- const userInfo = JSON.parse(apiResult.stdout);
349
- permissionInfo += `User: ${userInfo.login} (${userInfo.name || 'no name'})\n`;
350
- }
351
- catch (apiError) {
352
- const err = apiError;
353
- permissionInfo += `API Access Error: ${err.stderr || err.message}\n`;
354
- }
355
- try {
356
- await execAsync(`/usr/bin/gh api -H "Accept: application/vnd.github+json" /user`, { env: envVarsCheck, timeout: 10000 });
357
- permissionInfo += `API Test: Success\n`;
358
- }
359
- catch (scopesError) {
360
- const err = scopesError;
361
- permissionInfo += `API Test Error: ${err.stderr || err.message}\n`;
362
- }
363
- return permissionInfo;
364
- }
365
- catch (error) {
366
- return `Permission check failed: ${error}`;
367
- }
368
- }
369
259
  if (stderr) {
370
- let debugTokenInfo = '';
371
- let permissionInfo = '';
372
- if (authType !== 'manual') {
373
- debugTokenInfo = authType === 'local'
374
- ? ' [Local CLI - no token passed]'
375
- : ` [Token used: ${accessToken || 'none'}]`;
376
- if (authType === 'oauth2' && accessToken) {
377
- permissionInfo = await checkTokenPermissions(accessToken);
378
- debugTokenInfo += `\n\nToken Permissions Check:\n${permissionInfo}`;
379
- }
380
- }
260
+ const debugInfo = useToken
261
+ ? ` [Using manual token: ${githubToken.substring(0, 4)}...]`
262
+ : ' [Using local CLI authentication]';
381
263
  if (stderr.includes('internal server error') || stderr.includes('code: 500')) {
382
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub Copilot service is temporarily unavailable (HTTP 500). This is a GitHub server issue. Please try again in a few moments.${debugTokenInfo} Error: ${stderr}`);
264
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub Copilot service is temporarily unavailable (HTTP 500). This is a GitHub server issue. Please try again in a few moments.${debugInfo} Error: ${stderr}`);
383
265
  }
384
266
  else if (stderr.includes('code: 400') || stderr.includes('Bad Request')) {
385
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub Copilot request failed (HTTP 400). The request is malformed or invalid.${debugTokenInfo} Full error response: ${stderr}`);
267
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub Copilot request failed (HTTP 400). The request is malformed or invalid.${debugInfo} Full error response: ${stderr}`);
386
268
  }
387
269
  else if (stderr.includes('401') || stderr.includes('Unauthorized') || stderr.includes('Bad credentials')) {
388
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub authentication failed (HTTP 401). Please check your token has Copilot permissions.${debugTokenInfo} Full error response: ${stderr}`);
270
+ const tokenHelp = useToken
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
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub authentication failed (HTTP 401).${tokenHelp}${debugInfo} Full error response: ${stderr}`);
389
274
  }
390
275
  else if (stderr.includes('403') || stderr.includes('Forbidden')) {
391
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub Copilot access denied (HTTP 403). Please ensure your account has Copilot subscription.${debugTokenInfo} Full error response: ${stderr}`);
276
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub Copilot access denied (HTTP 403). Please ensure your account has Copilot subscription.${debugInfo} Full error response: ${stderr}`);
392
277
  }
393
278
  else if (!stdout) {
394
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub Copilot CLI error:${debugTokenInfo} Full error response: ${stderr}`);
279
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `GitHub Copilot CLI error:${debugInfo} Full error response: ${stderr}`);
395
280
  }
396
281
  }
397
282
  const filterOutput = this.getNodeParameter('filterOutput', i, true);
@@ -404,9 +289,9 @@ class GitHubCopilot {
404
289
  operation,
405
290
  prompt: prompt,
406
291
  context: context || undefined,
407
- authType: authType,
408
- credentialType: credentialType,
409
- tokenPrefix: accessToken ? accessToken.substring(0, 4) + '...' : 'none',
292
+ authMethod: authMethod,
293
+ tokenUsed: useToken,
294
+ tokenPrefix: useToken ? githubToken.substring(0, 4) + '...' : 'none',
410
295
  language: operation === 'suggest' ? this.getNodeParameter('language', i) : undefined,
411
296
  commandType: operation === 'shell' ? this.getNodeParameter('commandType', i) : undefined,
412
297
  output: processedOutput,
@@ -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": "1.2.2",
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
  ],