n8n-nodes-github-copilot 3.23.0 โ 3.24.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.
|
@@ -83,6 +83,230 @@ async function listAvailableModels(token, enableRetry = true, maxRetries = 3) {
|
|
|
83
83
|
},
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
|
+
async function consolidatedModelTest(token, enableRetry = true, maxRetries = 3) {
|
|
87
|
+
const testStartTime = Date.now();
|
|
88
|
+
const testResults = {};
|
|
89
|
+
let totalTests = 0;
|
|
90
|
+
let successfulTests = 0;
|
|
91
|
+
let failedTests = 0;
|
|
92
|
+
try {
|
|
93
|
+
console.log('๐งช Starting Consolidated Model Test...');
|
|
94
|
+
const modelsResponse = await listAvailableModels(token, enableRetry, maxRetries);
|
|
95
|
+
if (!modelsResponse.success || !modelsResponse.data) {
|
|
96
|
+
return {
|
|
97
|
+
success: false,
|
|
98
|
+
timestamp: new Date().toISOString(),
|
|
99
|
+
error: 'Failed to fetch models list for consolidated test',
|
|
100
|
+
details: modelsResponse,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const availableModels = modelsResponse.data;
|
|
104
|
+
const testMessage = "Hello! Please respond with just 'OK' to confirm you're working.";
|
|
105
|
+
const testsPerModel = 5;
|
|
106
|
+
console.log(`๐ Testing ${availableModels.length} models, ${testsPerModel} times each...`);
|
|
107
|
+
for (const modelItem of availableModels) {
|
|
108
|
+
const model = modelItem;
|
|
109
|
+
const modelId = model.id || model.name;
|
|
110
|
+
const modelResults = {
|
|
111
|
+
modelInfo: {
|
|
112
|
+
id: modelId,
|
|
113
|
+
name: model.name || modelId,
|
|
114
|
+
vendor: model.vendor || 'unknown',
|
|
115
|
+
capabilities: model.capabilities || {},
|
|
116
|
+
},
|
|
117
|
+
tests: [],
|
|
118
|
+
summary: {
|
|
119
|
+
totalAttempts: 0,
|
|
120
|
+
successful: 0,
|
|
121
|
+
failed: 0,
|
|
122
|
+
successRate: 0,
|
|
123
|
+
avgResponseTime: 0,
|
|
124
|
+
avgTokensUsed: 0,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
console.log(`๐ Testing model: ${modelId}`);
|
|
128
|
+
for (let testNum = 1; testNum <= testsPerModel; testNum++) {
|
|
129
|
+
const testStart = Date.now();
|
|
130
|
+
totalTests++;
|
|
131
|
+
modelResults.summary.totalAttempts++;
|
|
132
|
+
try {
|
|
133
|
+
const response = await fetch(GitHubCopilotEndpoints_1.GitHubCopilotEndpoints.getChatCompletionsUrl(), {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
headers: GitHubCopilotEndpoints_1.GitHubCopilotEndpoints.getAuthHeaders(token),
|
|
136
|
+
body: JSON.stringify({
|
|
137
|
+
model: modelId,
|
|
138
|
+
messages: [
|
|
139
|
+
{
|
|
140
|
+
role: 'user',
|
|
141
|
+
content: testMessage
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
max_tokens: 10,
|
|
145
|
+
temperature: 0.1,
|
|
146
|
+
}),
|
|
147
|
+
});
|
|
148
|
+
const testEnd = Date.now();
|
|
149
|
+
const responseTime = testEnd - testStart;
|
|
150
|
+
if (response.ok) {
|
|
151
|
+
const data = await response.json();
|
|
152
|
+
successfulTests++;
|
|
153
|
+
modelResults.summary.successful++;
|
|
154
|
+
const choices = data.choices || [];
|
|
155
|
+
const firstChoice = choices[0] || {};
|
|
156
|
+
const message = firstChoice.message || {};
|
|
157
|
+
const usage = data.usage || {};
|
|
158
|
+
const testResult = {
|
|
159
|
+
testNumber: testNum,
|
|
160
|
+
success: true,
|
|
161
|
+
responseTime: responseTime,
|
|
162
|
+
response: message.content || 'No content',
|
|
163
|
+
usage: usage || null,
|
|
164
|
+
finishReason: firstChoice.finish_reason || 'unknown',
|
|
165
|
+
timestamp: new Date().toISOString(),
|
|
166
|
+
};
|
|
167
|
+
modelResults.tests.push(testResult);
|
|
168
|
+
const totalTokens = usage.total_tokens;
|
|
169
|
+
if (totalTokens) {
|
|
170
|
+
modelResults.summary.avgTokensUsed += totalTokens;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
const errorText = await response.text();
|
|
175
|
+
failedTests++;
|
|
176
|
+
modelResults.summary.failed++;
|
|
177
|
+
modelResults.tests.push({
|
|
178
|
+
testNumber: testNum,
|
|
179
|
+
success: false,
|
|
180
|
+
responseTime: responseTime,
|
|
181
|
+
error: `HTTP ${response.status}: ${errorText}`,
|
|
182
|
+
timestamp: new Date().toISOString(),
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
const testEnd = Date.now();
|
|
188
|
+
const responseTime = testEnd - testStart;
|
|
189
|
+
failedTests++;
|
|
190
|
+
modelResults.summary.failed++;
|
|
191
|
+
modelResults.tests.push({
|
|
192
|
+
testNumber: testNum,
|
|
193
|
+
success: false,
|
|
194
|
+
responseTime: responseTime,
|
|
195
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
196
|
+
timestamp: new Date().toISOString(),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
200
|
+
}
|
|
201
|
+
const successfulResponses = modelResults.tests.filter((t) => {
|
|
202
|
+
const test = t;
|
|
203
|
+
return test.success === true;
|
|
204
|
+
});
|
|
205
|
+
if (successfulResponses.length > 0) {
|
|
206
|
+
const totalResponseTime = successfulResponses.reduce((sum, t) => {
|
|
207
|
+
const test = t;
|
|
208
|
+
return sum + (test.responseTime || 0);
|
|
209
|
+
}, 0);
|
|
210
|
+
modelResults.summary.avgResponseTime = Math.round(totalResponseTime / successfulResponses.length);
|
|
211
|
+
modelResults.summary.avgTokensUsed = Math.round(modelResults.summary.avgTokensUsed / successfulResponses.length);
|
|
212
|
+
}
|
|
213
|
+
modelResults.summary.successRate = Math.round((modelResults.summary.successful / modelResults.summary.totalAttempts) * 100);
|
|
214
|
+
testResults[modelId] = modelResults;
|
|
215
|
+
}
|
|
216
|
+
const testEndTime = Date.now();
|
|
217
|
+
const totalTestTime = testEndTime - testStartTime;
|
|
218
|
+
const consolidatedSummary = {
|
|
219
|
+
success: true,
|
|
220
|
+
timestamp: new Date().toISOString(),
|
|
221
|
+
testConfiguration: {
|
|
222
|
+
testsPerModel: testsPerModel,
|
|
223
|
+
totalModels: availableModels.length,
|
|
224
|
+
totalTests: totalTests,
|
|
225
|
+
retryEnabled: enableRetry,
|
|
226
|
+
maxRetries: maxRetries,
|
|
227
|
+
},
|
|
228
|
+
overallResults: {
|
|
229
|
+
totalTests: totalTests,
|
|
230
|
+
successfulTests: successfulTests,
|
|
231
|
+
failedTests: failedTests,
|
|
232
|
+
overallSuccessRate: Math.round((successfulTests / totalTests) * 100),
|
|
233
|
+
totalTestTime: totalTestTime,
|
|
234
|
+
avgTimePerTest: Math.round(totalTestTime / totalTests),
|
|
235
|
+
},
|
|
236
|
+
modelResults: testResults,
|
|
237
|
+
recommendations: generateTestRecommendations(testResults),
|
|
238
|
+
};
|
|
239
|
+
console.log('โ
Consolidated test completed successfully!');
|
|
240
|
+
return consolidatedSummary;
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
return {
|
|
244
|
+
success: false,
|
|
245
|
+
timestamp: new Date().toISOString(),
|
|
246
|
+
error: error instanceof Error ? error.message : 'Unknown error in consolidated test',
|
|
247
|
+
partialResults: testResults,
|
|
248
|
+
testDuration: Date.now() - testStartTime,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function generateTestRecommendations(testResults) {
|
|
253
|
+
const recommendations = [];
|
|
254
|
+
const modelStats = Object.entries(testResults).map(([modelId, results]) => {
|
|
255
|
+
const modelResult = results;
|
|
256
|
+
const summary = modelResult.summary;
|
|
257
|
+
const modelInfo = modelResult.modelInfo;
|
|
258
|
+
return {
|
|
259
|
+
modelId,
|
|
260
|
+
successRate: summary.successRate,
|
|
261
|
+
avgResponseTime: summary.avgResponseTime,
|
|
262
|
+
vendor: modelInfo.vendor,
|
|
263
|
+
};
|
|
264
|
+
});
|
|
265
|
+
const bestModels = modelStats
|
|
266
|
+
.filter(m => m.successRate === 100)
|
|
267
|
+
.sort((a, b) => a.avgResponseTime - b.avgResponseTime)
|
|
268
|
+
.slice(0, 3);
|
|
269
|
+
if (bestModels.length > 0) {
|
|
270
|
+
recommendations.push({
|
|
271
|
+
type: 'best_performance',
|
|
272
|
+
title: 'Top Performing Models (100% success rate)',
|
|
273
|
+
models: bestModels,
|
|
274
|
+
description: 'These models completed all tests successfully with fastest response times',
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
const problematicModels = modelStats.filter(m => m.successRate < 80);
|
|
278
|
+
if (problematicModels.length > 0) {
|
|
279
|
+
recommendations.push({
|
|
280
|
+
type: 'attention_needed',
|
|
281
|
+
title: 'Models Requiring Attention (< 80% success rate)',
|
|
282
|
+
models: problematicModels,
|
|
283
|
+
description: 'These models had reliability issues during testing',
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
const vendorStats = modelStats.reduce((acc, model) => {
|
|
287
|
+
const vendor = model.vendor;
|
|
288
|
+
if (!acc[vendor]) {
|
|
289
|
+
acc[vendor] = { count: 0, totalSuccessRate: 0, avgResponseTime: 0 };
|
|
290
|
+
}
|
|
291
|
+
const stats = acc[vendor];
|
|
292
|
+
stats.count++;
|
|
293
|
+
stats.totalSuccessRate += model.successRate;
|
|
294
|
+
stats.avgResponseTime += model.avgResponseTime;
|
|
295
|
+
return acc;
|
|
296
|
+
}, {});
|
|
297
|
+
Object.keys(vendorStats).forEach(vendor => {
|
|
298
|
+
const vendorData = vendorStats[vendor];
|
|
299
|
+
vendorData.avgSuccessRate = Math.round(vendorData.totalSuccessRate / vendorData.count);
|
|
300
|
+
vendorData.avgResponseTime = Math.round(vendorData.avgResponseTime / vendorData.count);
|
|
301
|
+
});
|
|
302
|
+
recommendations.push({
|
|
303
|
+
type: 'vendor_analysis',
|
|
304
|
+
title: 'Performance by Vendor',
|
|
305
|
+
vendors: vendorStats,
|
|
306
|
+
description: 'Comparative analysis of model performance by vendor',
|
|
307
|
+
});
|
|
308
|
+
return recommendations;
|
|
309
|
+
}
|
|
86
310
|
class GitHubCopilotTest {
|
|
87
311
|
constructor() {
|
|
88
312
|
this.description = {
|
|
@@ -116,6 +340,11 @@ class GitHubCopilotTest {
|
|
|
116
340
|
value: 'listModels',
|
|
117
341
|
description: 'Get all models available for your GitHub Copilot subscription',
|
|
118
342
|
},
|
|
343
|
+
{
|
|
344
|
+
name: 'Consolidated Model Test',
|
|
345
|
+
value: 'consolidatedTest',
|
|
346
|
+
description: 'Test all available models 5 times each and generate comprehensive report',
|
|
347
|
+
},
|
|
119
348
|
],
|
|
120
349
|
default: 'listModels',
|
|
121
350
|
description: 'Select the test function to execute',
|
|
@@ -163,6 +392,9 @@ class GitHubCopilotTest {
|
|
|
163
392
|
case 'listModels':
|
|
164
393
|
result = await listAvailableModels(token, enableRetry, maxRetries);
|
|
165
394
|
break;
|
|
395
|
+
case 'consolidatedTest':
|
|
396
|
+
result = await consolidatedModelTest(token, enableRetry, maxRetries);
|
|
397
|
+
break;
|
|
166
398
|
default:
|
|
167
399
|
throw new Error(`Unknown test function: ${testFunction}`);
|
|
168
400
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-github-copilot",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.24.0",
|
|
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",
|