n8n-nodes-github-copilot 3.31.1 → 3.31.2
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IWebhookFunctions, IWebhookResponseData, INodeType, INodeTypeDescription } from "n8n-workflow";
|
|
2
2
|
export declare class GitHubCopilotAuthHelper implements INodeType {
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
|
-
|
|
4
|
+
webhook(this: IWebhookFunctions): Promise<IWebhookResponseData>;
|
|
5
5
|
}
|
|
@@ -7,38 +7,53 @@ class GitHubCopilotAuthHelper {
|
|
|
7
7
|
displayName: "GitHub Copilot Auth Helper",
|
|
8
8
|
name: "githubCopilotAuthHelper",
|
|
9
9
|
icon: "file:../../shared/icons/copilot.svg",
|
|
10
|
-
group: ["
|
|
10
|
+
group: ["trigger"],
|
|
11
11
|
version: 1,
|
|
12
|
-
description: "Interactive OAuth Device Flow
|
|
12
|
+
description: "Interactive OAuth Device Flow - serves HTML page with proxy to avoid CORS",
|
|
13
13
|
defaults: {
|
|
14
|
-
name: "GitHub Copilot Auth
|
|
14
|
+
name: "GitHub Copilot Auth",
|
|
15
15
|
},
|
|
16
|
-
inputs: [
|
|
17
|
-
outputs: [
|
|
16
|
+
inputs: [],
|
|
17
|
+
outputs: [],
|
|
18
|
+
webhooks: [
|
|
19
|
+
{
|
|
20
|
+
name: "default",
|
|
21
|
+
httpMethod: "=",
|
|
22
|
+
responseMode: "onReceived",
|
|
23
|
+
path: "github-auth",
|
|
24
|
+
},
|
|
25
|
+
],
|
|
18
26
|
properties: [
|
|
19
27
|
{
|
|
20
|
-
displayName: "
|
|
28
|
+
displayName: "🎯 Como Usar",
|
|
21
29
|
name: "instructions",
|
|
22
30
|
type: "notice",
|
|
23
31
|
default: "",
|
|
24
32
|
description: `
|
|
25
|
-
<div style="background: #
|
|
26
|
-
<h3 style="margin-top: 0;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
<p><strong>
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
<div style="background: #e8f5e8; padding: 20px; border-left: 4px solid #4CAF50; border-radius: 4px;">
|
|
34
|
+
<h3 style="margin-top: 0; color: #2E7D32;">✨ Autenticação Visual - Sem Terminal!</h3>
|
|
35
|
+
|
|
36
|
+
<p><strong>1. Ative este workflow</strong></p>
|
|
37
|
+
<p>Clique em "Active" no canto superior direito</p>
|
|
38
|
+
|
|
39
|
+
<p><strong>2. Copie a URL do Webhook</strong></p>
|
|
40
|
+
<p>Clique em "Copy URL" abaixo e envie para o usuário</p>
|
|
41
|
+
|
|
42
|
+
<p><strong>3. Usuário acessa a URL no navegador</strong></p>
|
|
43
|
+
<p>Uma página bonita vai abrir com instruções claras</p>
|
|
44
|
+
|
|
45
|
+
<p><strong>4. Processo automático!</strong></p>
|
|
46
|
+
<ul style="margin: 10px 0; padding-left: 20px;">
|
|
47
|
+
<li>✅ Página solicita código do GitHub</li>
|
|
48
|
+
<li>✅ Mostra código grande para copiar</li>
|
|
38
49
|
<li>✅ Abre GitHub automaticamente</li>
|
|
39
|
-
<li>✅
|
|
50
|
+
<li>✅ Aguarda autorização (polling automático)</li>
|
|
40
51
|
<li>✅ Exibe token pronto para copiar</li>
|
|
41
52
|
</ul>
|
|
53
|
+
|
|
54
|
+
<p style="background: #fff3e0; padding: 10px; border-radius: 4px; margin-top: 15px;">
|
|
55
|
+
<strong>💡 Sem CORS!</strong> O n8n faz as chamadas para o GitHub, não o navegador!
|
|
56
|
+
</p>
|
|
42
57
|
</div>
|
|
43
58
|
`,
|
|
44
59
|
},
|
|
@@ -58,90 +73,86 @@ class GitHubCopilotAuthHelper {
|
|
|
58
73
|
required: true,
|
|
59
74
|
description: "OAuth scopes required for GitHub Copilot",
|
|
60
75
|
},
|
|
61
|
-
{
|
|
62
|
-
displayName: "Output Format",
|
|
63
|
-
name: "outputFormat",
|
|
64
|
-
type: "options",
|
|
65
|
-
options: [
|
|
66
|
-
{
|
|
67
|
-
name: "📄 Binary File (Download Ready)",
|
|
68
|
-
value: "binary",
|
|
69
|
-
description: "HTML as binary data ready to download as .html file",
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
name: "📋 HTML Text + Instructions",
|
|
73
|
-
value: "htmlWithInstructions",
|
|
74
|
-
description: "HTML text with usage instructions (copy & paste)",
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
name: "📝 HTML Text Only",
|
|
78
|
-
value: "html",
|
|
79
|
-
description: "Just the HTML code as text",
|
|
80
|
-
},
|
|
81
|
-
],
|
|
82
|
-
default: "binary",
|
|
83
|
-
description: "How to output the authentication page",
|
|
84
|
-
},
|
|
85
76
|
],
|
|
86
77
|
};
|
|
87
78
|
}
|
|
88
|
-
async
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
message: "✅ Authentication page generated successfully!",
|
|
103
|
-
instructions: "Download the binary file below and open it in your browser",
|
|
104
|
-
fileName: "github-copilot-auth.html",
|
|
105
|
-
fileSize: `${(buffer.length / 1024).toFixed(2)} KB`,
|
|
106
|
-
},
|
|
107
|
-
binary: {
|
|
108
|
-
authPage: {
|
|
109
|
-
data: buffer.toString("base64"),
|
|
110
|
-
mimeType: "text/html",
|
|
111
|
-
fileName: "github-copilot-auth.html",
|
|
79
|
+
async webhook() {
|
|
80
|
+
const req = this.getRequestObject();
|
|
81
|
+
const clientId = this.getNodeParameter("clientId");
|
|
82
|
+
const scopes = this.getNodeParameter("scopes");
|
|
83
|
+
if (req.method === "POST") {
|
|
84
|
+
const body = this.getBodyData();
|
|
85
|
+
const action = body.action;
|
|
86
|
+
try {
|
|
87
|
+
if (action === "device_code") {
|
|
88
|
+
const response = await fetch("https://github.com/login/device/code", {
|
|
89
|
+
method: "POST",
|
|
90
|
+
headers: {
|
|
91
|
+
"Accept": "application/json",
|
|
92
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
112
93
|
},
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
94
|
+
body: new URLSearchParams({
|
|
95
|
+
client_id: clientId,
|
|
96
|
+
scope: scopes,
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
const data = await response.json();
|
|
100
|
+
return {
|
|
101
|
+
webhookResponse: {
|
|
102
|
+
status: 200,
|
|
103
|
+
headers: { "Content-Type": "application/json" },
|
|
104
|
+
body: JSON.stringify(data),
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (action === "poll_token") {
|
|
109
|
+
const deviceCode = body.device_code;
|
|
110
|
+
const response = await fetch("https://github.com/login/oauth/access_token", {
|
|
111
|
+
method: "POST",
|
|
112
|
+
headers: {
|
|
113
|
+
"Accept": "application/json",
|
|
114
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
115
|
+
},
|
|
116
|
+
body: new URLSearchParams({
|
|
117
|
+
client_id: clientId,
|
|
118
|
+
device_code: deviceCode,
|
|
119
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
120
|
+
}),
|
|
121
|
+
});
|
|
122
|
+
const data = await response.json();
|
|
123
|
+
return {
|
|
124
|
+
webhookResponse: {
|
|
125
|
+
status: 200,
|
|
126
|
+
headers: { "Content-Type": "application/json" },
|
|
127
|
+
body: JSON.stringify(data),
|
|
128
|
+
},
|
|
129
|
+
};
|
|
132
130
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
throw new Error(`Unknown action: ${action}`);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
return {
|
|
135
|
+
webhookResponse: {
|
|
136
|
+
status: 500,
|
|
137
|
+
headers: { "Content-Type": "application/json" },
|
|
138
|
+
body: JSON.stringify({ error: error.message }),
|
|
139
|
+
},
|
|
136
140
|
};
|
|
137
141
|
}
|
|
138
|
-
returnData.push(output);
|
|
139
142
|
}
|
|
140
|
-
|
|
143
|
+
const webhookUrl = this.getNodeWebhookUrl("default");
|
|
144
|
+
const html = generateAuthPage(webhookUrl);
|
|
145
|
+
return {
|
|
146
|
+
webhookResponse: {
|
|
147
|
+
status: 200,
|
|
148
|
+
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
149
|
+
body: html,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
141
152
|
}
|
|
142
153
|
}
|
|
143
154
|
exports.GitHubCopilotAuthHelper = GitHubCopilotAuthHelper;
|
|
144
|
-
function generateAuthPage(
|
|
155
|
+
function generateAuthPage(proxyUrl) {
|
|
145
156
|
return `<!DOCTYPE html>
|
|
146
157
|
<html lang="pt-BR">
|
|
147
158
|
<head>
|
|
@@ -399,7 +410,7 @@ function generateAuthPage(clientId, scopes) {
|
|
|
399
410
|
<span>Copiar Token</span>
|
|
400
411
|
</button>
|
|
401
412
|
<p class="info-text" style="color: #155724; margin-top: 15px;">
|
|
402
|
-
✨ Cole este token na credencial "GitHub Copilot
|
|
413
|
+
✨ Cole este token na credencial "GitHub Copilot API" no n8n
|
|
403
414
|
</p>
|
|
404
415
|
</div>
|
|
405
416
|
|
|
@@ -410,10 +421,7 @@ function generateAuthPage(clientId, scopes) {
|
|
|
410
421
|
</div>
|
|
411
422
|
|
|
412
423
|
<script>
|
|
413
|
-
const
|
|
414
|
-
const SCOPES = "${scopes}";
|
|
415
|
-
const DEVICE_CODE_URL = "https://github.com/login/device/code";
|
|
416
|
-
const ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
424
|
+
const PROXY_URL = "${proxyUrl}";
|
|
417
425
|
|
|
418
426
|
let deviceCode = "";
|
|
419
427
|
let userCode = "";
|
|
@@ -425,16 +433,14 @@ function generateAuthPage(clientId, scopes) {
|
|
|
425
433
|
document.getElementById("step1").querySelector(".btn").disabled = true;
|
|
426
434
|
document.getElementById("step1").querySelector(".btn").innerHTML = '<span>⏳</span><span>Solicitando...</span>';
|
|
427
435
|
|
|
428
|
-
// Request device code
|
|
429
|
-
const response = await fetch(
|
|
436
|
+
// Request device code via n8n proxy
|
|
437
|
+
const response = await fetch(PROXY_URL, {
|
|
430
438
|
method: "POST",
|
|
431
439
|
headers: {
|
|
432
|
-
"
|
|
433
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
440
|
+
"Content-Type": "application/json",
|
|
434
441
|
},
|
|
435
|
-
body:
|
|
436
|
-
|
|
437
|
-
scope: SCOPES
|
|
442
|
+
body: JSON.stringify({
|
|
443
|
+
action: "device_code"
|
|
438
444
|
})
|
|
439
445
|
});
|
|
440
446
|
|
|
@@ -490,16 +496,14 @@ function generateAuthPage(clientId, scopes) {
|
|
|
490
496
|
document.getElementById("statusText").textContent = \`Verificando... (tentativa \${attempt}/\${maxAttempts})\`;
|
|
491
497
|
|
|
492
498
|
try {
|
|
493
|
-
const response = await fetch(
|
|
499
|
+
const response = await fetch(PROXY_URL, {
|
|
494
500
|
method: "POST",
|
|
495
501
|
headers: {
|
|
496
|
-
"
|
|
497
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
502
|
+
"Content-Type": "application/json",
|
|
498
503
|
},
|
|
499
|
-
body:
|
|
500
|
-
|
|
501
|
-
device_code: deviceCode
|
|
502
|
-
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
504
|
+
body: JSON.stringify({
|
|
505
|
+
action: "poll_token",
|
|
506
|
+
device_code: deviceCode
|
|
503
507
|
})
|
|
504
508
|
});
|
|
505
509
|
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-github-copilot",
|
|
3
|
-
"version": "3.31.
|
|
3
|
+
"version": "3.31.2",
|
|
4
4
|
"description": "n8n community node for GitHub Copilot with CLI integration, Chat API access, and AI Chat Model for workflows - access GPT-5, Claude, Gemini and more using your Copilot subscription",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/sufficit/n8n-nodes-github-copilot",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-github-copilot",
|
|
3
|
-
"version": "3.31.
|
|
3
|
+
"version": "3.31.2",
|
|
4
4
|
"description": "n8n community node for GitHub Copilot with CLI integration, Chat API access, and AI Chat Model for workflows - access GPT-5, Claude, Gemini and more using your Copilot subscription",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/sufficit/n8n-nodes-github-copilot",
|