n8n-nodes-github-copilot 3.32.0 → 3.32.1
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/dist/credentials/GitHubCopilotApi.credentials.js +24 -126
- package/dist/nodes/GitHubCopilotChatAPI/GitHubCopilotChatAPI.node.js +15 -8
- package/dist/nodes/GitHubCopilotOpenAI/GitHubCopilotOpenAI.node.js +12 -0
- package/dist/package.json +1 -1
- package/dist/shared/utils/GitHubCopilotApiUtils.d.ts +5 -0
- package/dist/shared/utils/GitHubCopilotApiUtils.js +21 -37
- package/package.json +1 -1
|
@@ -10,89 +10,20 @@ class GitHubCopilotApi {
|
|
|
10
10
|
this.documentationUrl = "https://docs.github.com/en/copilot/github-copilot-chat/copilot-chat-in-ides/using-github-copilot-chat-in-your-ide";
|
|
11
11
|
this.properties = [
|
|
12
12
|
{
|
|
13
|
-
displayName: "
|
|
14
|
-
name: "
|
|
15
|
-
type: "options",
|
|
16
|
-
options: [
|
|
17
|
-
{
|
|
18
|
-
name: "GitHub CLI Token (Auto OAuth) - RECOMMENDED",
|
|
19
|
-
value: "githubToken",
|
|
20
|
-
description: "Automatically generates and refreshes OAuth tokens every 20 minutes",
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
name: "Manual OAuth Token (Advanced)",
|
|
24
|
-
value: "oauthToken",
|
|
25
|
-
description: "Manually provide OAuth token (expires in 20 minutes)",
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
default: "githubToken",
|
|
29
|
-
description: "Choose how to authenticate with GitHub Copilot API",
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
displayName: "ℹ️ Auto OAuth Token Generation",
|
|
33
|
-
name: "autoOAuthNotice",
|
|
34
|
-
type: "notice",
|
|
35
|
-
default: "Your GitHub CLI token will be used to automatically generate OAuth tokens. Tokens are cached and refreshed automatically before expiration (every ~20 minutes). No manual intervention needed!",
|
|
36
|
-
displayOptions: {
|
|
37
|
-
show: {
|
|
38
|
-
authMethod: ["githubToken"],
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
displayName: "⚠️ IMPORTANT: GitHub CLI Token Required",
|
|
44
|
-
name: "warningNotice",
|
|
45
|
-
type: "notice",
|
|
46
|
-
default: "",
|
|
47
|
-
displayOptions: {
|
|
48
|
-
show: {
|
|
49
|
-
authMethod: ["githubToken"],
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
displayName: "🚀 Don't have GitHub CLI installed?",
|
|
55
|
-
name: "helperNotice1",
|
|
56
|
-
type: "notice",
|
|
57
|
-
default: "Use the visual 'GitHub Copilot Auth Helper' node to generate your token without touching the terminal!",
|
|
58
|
-
displayOptions: {
|
|
59
|
-
show: {
|
|
60
|
-
authMethod: ["githubToken"],
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
displayName: "📝 Step 1: Create Helper Workflow",
|
|
66
|
-
name: "helperNotice2",
|
|
67
|
-
type: "notice",
|
|
68
|
-
default: "Add a new workflow and insert the 'GitHub Copilot Auth Helper' trigger node.",
|
|
69
|
-
displayOptions: {
|
|
70
|
-
show: {
|
|
71
|
-
authMethod: ["githubToken"],
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
displayName: "▶️ Step 2: Activate & Access",
|
|
77
|
-
name: "helperNotice3",
|
|
78
|
-
type: "notice",
|
|
79
|
-
default: "Activate the workflow, then click 'Test workflow' to open the visual token generator in your browser.",
|
|
80
|
-
displayOptions: {
|
|
81
|
-
show: {
|
|
82
|
-
authMethod: ["githubToken"],
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
displayName: "📋 Step 3: Copy Token",
|
|
88
|
-
name: "helperNotice4",
|
|
13
|
+
displayName: "Setup Instructions",
|
|
14
|
+
name: "setupNotice",
|
|
89
15
|
type: "notice",
|
|
90
|
-
default: "
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
16
|
+
default: "ℹ️ Auto OAuth Token Generation\n" +
|
|
17
|
+
"Your GitHub CLI token will be used to automatically generate OAuth tokens. Tokens are cached and refreshed automatically before expiration (every ~20 minutes). No manual intervention needed!\n\n" +
|
|
18
|
+
"⚠️ IMPORTANT: GitHub CLI Token Required\n\n" +
|
|
19
|
+
"🚀 Don't have GitHub CLI installed?\n" +
|
|
20
|
+
"Use the visual 'GitHub Copilot Auth Helper' node to generate your token without touching the terminal!\n\n" +
|
|
21
|
+
"📝 Step 1: Create Helper Workflow\n" +
|
|
22
|
+
"Add a new workflow and insert the 'GitHub Copilot Auth Helper' trigger node.\n\n" +
|
|
23
|
+
"▶️ Step 2: Activate & Access\n" +
|
|
24
|
+
"Activate the workflow, then click 'Test workflow' to open the visual token generator in your browser.\n\n" +
|
|
25
|
+
"📋 Step 3: Copy Token\n" +
|
|
26
|
+
"Follow the on-screen instructions to authenticate with GitHub and copy the generated 'gho_' token back here.",
|
|
96
27
|
},
|
|
97
28
|
{
|
|
98
29
|
displayName: "GitHub CLI Token",
|
|
@@ -105,39 +36,6 @@ class GitHubCopilotApi {
|
|
|
105
36
|
required: true,
|
|
106
37
|
description: "Token generated by GitHub CLI (starts with 'gho_'). OAuth tokens will be auto-generated and refreshed from this token.",
|
|
107
38
|
placeholder: "gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
108
|
-
displayOptions: {
|
|
109
|
-
show: {
|
|
110
|
-
authMethod: ["githubToken"],
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
displayName: "⚠️ Manual OAuth Token (Advanced)",
|
|
116
|
-
name: "manualOAuthNotice",
|
|
117
|
-
type: "notice",
|
|
118
|
-
default: "OAuth tokens expire after ~20 minutes. You will need to manually regenerate and update this token frequently. Consider using GitHub CLI Token mode instead for automatic token management.",
|
|
119
|
-
displayOptions: {
|
|
120
|
-
show: {
|
|
121
|
-
authMethod: ["oauthToken"],
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
displayName: "OAuth Token",
|
|
127
|
-
name: "oauthToken",
|
|
128
|
-
type: "string",
|
|
129
|
-
typeOptions: {
|
|
130
|
-
password: true,
|
|
131
|
-
},
|
|
132
|
-
default: "",
|
|
133
|
-
required: true,
|
|
134
|
-
description: "Manual OAuth token (starts with 'tid='). Expires in ~20 minutes.",
|
|
135
|
-
placeholder: "tid=xxxxx;exp=xxxxx;sku=xxxxx;...",
|
|
136
|
-
displayOptions: {
|
|
137
|
-
show: {
|
|
138
|
-
authMethod: ["oauthToken"],
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
39
|
},
|
|
142
40
|
];
|
|
143
41
|
this.test = {
|
|
@@ -149,19 +47,19 @@ class GitHubCopilotApi {
|
|
|
149
47
|
};
|
|
150
48
|
}
|
|
151
49
|
async authenticate(credentials, requestOptions) {
|
|
152
|
-
const
|
|
50
|
+
const githubToken = credentials.token;
|
|
51
|
+
if (!githubToken) {
|
|
52
|
+
throw new Error("GitHub CLI token is required");
|
|
53
|
+
}
|
|
54
|
+
if (!githubToken.startsWith("gho_")) {
|
|
55
|
+
throw new Error("Invalid token format. GitHub CLI token must start with 'gho_'");
|
|
56
|
+
}
|
|
153
57
|
let authToken;
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
try {
|
|
157
|
-
authToken = await OAuthTokenManager_1.OAuthTokenManager.getValidOAuthToken(githubToken);
|
|
158
|
-
}
|
|
159
|
-
catch (error) {
|
|
160
|
-
throw new Error(`Failed to generate OAuth token: ${error instanceof Error ? error.message : String(error)}`);
|
|
161
|
-
}
|
|
58
|
+
try {
|
|
59
|
+
authToken = await OAuthTokenManager_1.OAuthTokenManager.getValidOAuthToken(githubToken);
|
|
162
60
|
}
|
|
163
|
-
|
|
164
|
-
|
|
61
|
+
catch (error) {
|
|
62
|
+
throw new Error(`Failed to generate OAuth token: ${error instanceof Error ? error.message : String(error)}`);
|
|
165
63
|
}
|
|
166
64
|
if (!requestOptions.headers) {
|
|
167
65
|
requestOptions.headers = {};
|
|
@@ -31,7 +31,7 @@ class GitHubCopilotChatAPI {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
async execute() {
|
|
34
|
-
var _a, _b, _c, _d;
|
|
34
|
+
var _a, _b, _c, _d, _e, _f;
|
|
35
35
|
const items = this.getInputData();
|
|
36
36
|
const returnData = [];
|
|
37
37
|
for (let i = 0; i < items.length; i++) {
|
|
@@ -109,34 +109,41 @@ class GitHubCopilotChatAPI {
|
|
|
109
109
|
const hasMedia = includeMedia;
|
|
110
110
|
let response = null;
|
|
111
111
|
let attempt = 1;
|
|
112
|
-
|
|
112
|
+
const totalAttempts = maxRetries + 1;
|
|
113
|
+
let retriesUsed = 0;
|
|
114
|
+
while (attempt <= totalAttempts) {
|
|
113
115
|
try {
|
|
114
116
|
response = await (0, utils_1.makeApiRequest)(this, GitHubCopilotEndpoints_1.GITHUB_COPILOT_API.ENDPOINTS.CHAT_COMPLETIONS, requestBody, hasMedia);
|
|
117
|
+
retriesUsed = ((_a = response._retryMetadata) === null || _a === void 0 ? void 0 : _a.retries) || 0;
|
|
118
|
+
attempt = ((_b = response._retryMetadata) === null || _b === void 0 ? void 0 : _b.attempts) || 1;
|
|
115
119
|
break;
|
|
116
120
|
}
|
|
117
121
|
catch (error) {
|
|
118
|
-
const isLastAttempt = attempt >=
|
|
122
|
+
const isLastAttempt = attempt >= totalAttempts;
|
|
119
123
|
const errorObj = error;
|
|
120
|
-
const is403Error = errorObj.status === 403 || ((
|
|
124
|
+
const is403Error = errorObj.status === 403 || ((_c = errorObj.message) === null || _c === void 0 ? void 0 : _c.includes("403"));
|
|
121
125
|
if (is403Error && enableRetry && !isLastAttempt) {
|
|
122
126
|
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 30000);
|
|
123
|
-
console.log(`GitHub Copilot API attempt ${attempt} failed with 403, retrying in ${delay}ms...`);
|
|
127
|
+
console.log(`GitHub Copilot API attempt ${attempt}/${totalAttempts} failed with 403, retrying in ${delay}ms...`);
|
|
124
128
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
125
129
|
attempt++;
|
|
126
130
|
continue;
|
|
127
131
|
}
|
|
132
|
+
retriesUsed = attempt - 1;
|
|
128
133
|
throw error;
|
|
129
134
|
}
|
|
130
135
|
}
|
|
131
136
|
if (!response) {
|
|
132
|
-
throw new Error(
|
|
137
|
+
throw new Error(`Failed to get response from GitHub Copilot API after ${totalAttempts} attempts (${retriesUsed} retries)`);
|
|
133
138
|
}
|
|
134
139
|
const result = {
|
|
135
|
-
message: ((
|
|
140
|
+
message: ((_e = (_d = response.choices[0]) === null || _d === void 0 ? void 0 : _d.message) === null || _e === void 0 ? void 0 : _e.content) || "",
|
|
136
141
|
model,
|
|
137
142
|
operation,
|
|
138
143
|
usage: response.usage || null,
|
|
139
|
-
finish_reason: ((
|
|
144
|
+
finish_reason: ((_f = response.choices[0]) === null || _f === void 0 ? void 0 : _f.finish_reason) || "unknown",
|
|
145
|
+
retries: retriesUsed,
|
|
146
|
+
attempts: attempt,
|
|
140
147
|
};
|
|
141
148
|
returnData.push({
|
|
142
149
|
json: result,
|
|
@@ -30,6 +30,7 @@ class GitHubCopilotOpenAI {
|
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
async execute() {
|
|
33
|
+
var _a, _b;
|
|
33
34
|
const items = this.getInputData();
|
|
34
35
|
const returnData = [];
|
|
35
36
|
for (let i = 0; i < items.length; i++) {
|
|
@@ -163,6 +164,11 @@ class GitHubCopilotOpenAI {
|
|
|
163
164
|
requestBody.seed = seed;
|
|
164
165
|
}
|
|
165
166
|
const response = await (0, utils_1.makeApiRequest)(this, GitHubCopilotEndpoints_1.GITHUB_COPILOT_API.ENDPOINTS.CHAT_COMPLETIONS, requestBody, false);
|
|
167
|
+
const retriesUsed = ((_a = response._retryMetadata) === null || _a === void 0 ? void 0 : _a.retries) || 0;
|
|
168
|
+
const attemptsUsed = ((_b = response._retryMetadata) === null || _b === void 0 ? void 0 : _b.attempts) || 1;
|
|
169
|
+
if (retriesUsed > 0) {
|
|
170
|
+
console.log(`ℹ️ Request completed after ${attemptsUsed} attempts (${retriesUsed} retries)`);
|
|
171
|
+
}
|
|
166
172
|
const cleanJsonFromMarkdown = (content) => {
|
|
167
173
|
if (!content || typeof content !== 'string') {
|
|
168
174
|
return content;
|
|
@@ -230,6 +236,12 @@ class GitHubCopilotOpenAI {
|
|
|
230
236
|
completion_tokens: 0,
|
|
231
237
|
total_tokens: 0,
|
|
232
238
|
},
|
|
239
|
+
...(retriesUsed > 0 && {
|
|
240
|
+
_retry_info: {
|
|
241
|
+
attempts: attemptsUsed,
|
|
242
|
+
retries: retriesUsed,
|
|
243
|
+
}
|
|
244
|
+
}),
|
|
233
245
|
};
|
|
234
246
|
returnData.push({
|
|
235
247
|
json: openAIResponse,
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-github-copilot",
|
|
3
|
-
"version": "3.32.
|
|
3
|
+
"version": "3.32.1",
|
|
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",
|
|
@@ -12,7 +12,7 @@ exports.truncateToTokenLimit = truncateToTokenLimit;
|
|
|
12
12
|
const GitHubCopilotEndpoints_1 = require("./GitHubCopilotEndpoints");
|
|
13
13
|
const OAuthTokenManager_1 = require("./OAuthTokenManager");
|
|
14
14
|
async function makeGitHubCopilotRequest(context, endpoint, body, hasMedia = false, retryConfig) {
|
|
15
|
-
var _a, _b, _c
|
|
15
|
+
var _a, _b, _c;
|
|
16
16
|
const MAX_RETRIES = (_a = retryConfig === null || retryConfig === void 0 ? void 0 : retryConfig.maxRetries) !== null && _a !== void 0 ? _a : 3;
|
|
17
17
|
const BASE_DELAY = (_b = retryConfig === null || retryConfig === void 0 ? void 0 : retryConfig.baseDelay) !== null && _b !== void 0 ? _b : 500;
|
|
18
18
|
const RETRY_ON_403 = (_c = retryConfig === null || retryConfig === void 0 ? void 0 : retryConfig.retryOn403) !== null && _c !== void 0 ? _c : true;
|
|
@@ -25,43 +25,21 @@ async function makeGitHubCopilotRequest(context, endpoint, body, hasMedia = fals
|
|
|
25
25
|
}
|
|
26
26
|
const credentials = await context.getCredentials(credentialType);
|
|
27
27
|
console.log(`🔍 ${credentialType} Credentials Debug:`, Object.keys(credentials));
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const githubToken = credentials.token;
|
|
32
|
-
if (!githubToken) {
|
|
33
|
-
throw new Error("GitHub token (gho_*) not found in credentials");
|
|
34
|
-
}
|
|
35
|
-
if (!githubToken.startsWith("gho_")) {
|
|
36
|
-
throw new Error("Invalid GitHub token format. Must start with gho_");
|
|
37
|
-
}
|
|
38
|
-
console.log(`🔄 Using GitHub token to generate OAuth token...`);
|
|
39
|
-
try {
|
|
40
|
-
token = await OAuthTokenManager_1.OAuthTokenManager.getValidOAuthToken(githubToken);
|
|
41
|
-
console.log(`✅ OAuth token ready (auto-generated from GitHub token)`);
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
throw new Error(`Failed to generate OAuth token: ${error instanceof Error ? error.message : String(error)}`);
|
|
45
|
-
}
|
|
28
|
+
const githubToken = credentials.token;
|
|
29
|
+
if (!githubToken) {
|
|
30
|
+
throw new Error("GitHub CLI token (gho_*) not found in credentials");
|
|
46
31
|
}
|
|
47
|
-
|
|
48
|
-
token
|
|
49
|
-
if (!token) {
|
|
50
|
-
throw new Error("OAuth token not found in credentials");
|
|
51
|
-
}
|
|
52
|
-
console.log(`✅ Using manual OAuth token`);
|
|
32
|
+
if (!githubToken.startsWith("gho_")) {
|
|
33
|
+
throw new Error("Invalid GitHub token format. Must start with gho_");
|
|
53
34
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
Object.keys(credentials).join(", "));
|
|
63
|
-
}
|
|
64
|
-
console.log(`⚠️ Using legacy token format (consider updating credential configuration)`);
|
|
35
|
+
console.log(`🔄 Using GitHub token to generate OAuth token...`);
|
|
36
|
+
let token;
|
|
37
|
+
try {
|
|
38
|
+
token = await OAuthTokenManager_1.OAuthTokenManager.getValidOAuthToken(githubToken);
|
|
39
|
+
console.log(`✅ OAuth token ready (auto-generated from GitHub token)`);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw new Error(`Failed to generate OAuth token: ${error instanceof Error ? error.message : String(error)}`);
|
|
65
43
|
}
|
|
66
44
|
if (!token) {
|
|
67
45
|
console.error(`❌ Available ${credentialType} credential properties:`, Object.keys(credentials));
|
|
@@ -118,7 +96,13 @@ async function makeGitHubCopilotRequest(context, endpoint, body, hasMedia = fals
|
|
|
118
96
|
if (attempt > 1) {
|
|
119
97
|
console.log(`✅ GitHub Copilot API succeeded on attempt ${attempt}/${MAX_RETRIES}`);
|
|
120
98
|
}
|
|
121
|
-
|
|
99
|
+
const responseData = await response.json();
|
|
100
|
+
responseData._retryMetadata = {
|
|
101
|
+
attempts: attempt,
|
|
102
|
+
retries: attempt - 1,
|
|
103
|
+
succeeded: true
|
|
104
|
+
};
|
|
105
|
+
return responseData;
|
|
122
106
|
}
|
|
123
107
|
catch (error) {
|
|
124
108
|
lastError = error instanceof Error ? error : new Error(String(error));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-github-copilot",
|
|
3
|
-
"version": "3.32.
|
|
3
|
+
"version": "3.32.1",
|
|
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",
|