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.23.0",
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",