n8n-nodes-github-copilot 3.38.24 → 3.38.26

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.
Files changed (36) hide show
  1. package/dist/credentials/GitHubCopilotApi.credentials.d.ts +1 -1
  2. package/dist/credentials/GitHubCopilotApi.credentials.js +25 -25
  3. package/dist/nodes/GitHubCopilot/GitHubCopilot.node.d.ts +1 -1
  4. package/dist/nodes/GitHubCopilot/GitHubCopilot.node.js +166 -166
  5. package/dist/nodes/GitHubCopilotAuthHelper/GitHubCopilotAuthHelper.node.d.ts +1 -1
  6. package/dist/nodes/GitHubCopilotAuthHelper/GitHubCopilotAuthHelper.node.js +539 -539
  7. package/dist/nodes/GitHubCopilotChatAPI/GitHubCopilotChatAPI.node.d.ts +1 -1
  8. package/dist/nodes/GitHubCopilotChatAPI/GitHubCopilotChatAPI.node.js +46 -44
  9. package/dist/nodes/GitHubCopilotChatAPI/nodeProperties.d.ts +1 -1
  10. package/dist/nodes/GitHubCopilotChatAPI/nodeProperties.js +82 -82
  11. package/dist/nodes/GitHubCopilotChatAPI/utils/helpers.d.ts +2 -2
  12. package/dist/nodes/GitHubCopilotChatAPI/utils/helpers.js +26 -26
  13. package/dist/nodes/GitHubCopilotChatAPI/utils/imageProcessor.d.ts +2 -2
  14. package/dist/nodes/GitHubCopilotChatAPI/utils/imageProcessor.js +12 -12
  15. package/dist/nodes/GitHubCopilotChatAPI/utils/index.d.ts +4 -4
  16. package/dist/nodes/GitHubCopilotChatAPI/utils/mediaDetection.d.ts +3 -3
  17. package/dist/nodes/GitHubCopilotChatAPI/utils/mediaDetection.js +19 -19
  18. package/dist/nodes/GitHubCopilotChatAPI/utils/modelCapabilities.d.ts +1 -1
  19. package/dist/nodes/GitHubCopilotChatAPI/utils/modelCapabilities.js +23 -23
  20. package/dist/nodes/GitHubCopilotChatAPI/utils/types.d.ts +5 -5
  21. package/dist/nodes/GitHubCopilotChatModel/GitHubCopilotChatModel.node.d.ts +1 -1
  22. package/dist/nodes/GitHubCopilotChatModel/GitHubCopilotChatModel.node.js +163 -110
  23. package/dist/nodes/GitHubCopilotEmbeddings/GitHubCopilotEmbeddings.node.d.ts +1 -1
  24. package/dist/nodes/GitHubCopilotEmbeddings/GitHubCopilotEmbeddings.node.js +114 -114
  25. package/dist/nodes/GitHubCopilotOpenAI/GitHubCopilotOpenAI.node.d.ts +1 -1
  26. package/dist/nodes/GitHubCopilotOpenAI/GitHubCopilotOpenAI.node.js +74 -69
  27. package/dist/nodes/GitHubCopilotOpenAI/nodeProperties.d.ts +1 -1
  28. package/dist/nodes/GitHubCopilotOpenAI/nodeProperties.js +181 -181
  29. package/dist/nodes/GitHubCopilotOpenAI/utils/index.d.ts +2 -2
  30. package/dist/nodes/GitHubCopilotOpenAI/utils/openaiCompat.d.ts +10 -10
  31. package/dist/nodes/GitHubCopilotOpenAI/utils/openaiCompat.js +53 -53
  32. package/dist/nodes/GitHubCopilotOpenAI/utils/types.d.ts +12 -12
  33. package/dist/nodes/GitHubCopilotTest/GitHubCopilotTest.node.d.ts +1 -1
  34. package/dist/nodes/GitHubCopilotTest/GitHubCopilotTest.node.js +120 -116
  35. package/dist/package.json +1 -1
  36. package/package.json +1 -1
@@ -14,8 +14,17 @@ class GitHubCopilotChatOpenAI extends openai_1.ChatOpenAI {
14
14
  this.context = context;
15
15
  this.options = options;
16
16
  }
17
+ invocationParams(options) {
18
+ const params = super.invocationParams(options);
19
+ params.model = this.model;
20
+ return params;
21
+ }
17
22
  async _generate(messages, options) {
18
- let copilotMessages = messages.map(msg => {
23
+ var _a;
24
+ if (!messages || messages.length === 0) {
25
+ throw new Error('No messages provided for generation');
26
+ }
27
+ let copilotMessages = messages.map((msg) => {
19
28
  let role;
20
29
  switch (msg._getType()) {
21
30
  case 'human':
@@ -28,54 +37,99 @@ class GitHubCopilotChatOpenAI extends openai_1.ChatOpenAI {
28
37
  role = 'system';
29
38
  break;
30
39
  default:
40
+ console.warn(`⚠️ Unknown message type: ${msg._getType()}, defaulting to 'user'`);
31
41
  role = 'user';
32
42
  }
43
+ let content = msg.content;
44
+ if (typeof content === 'string') {
45
+ }
46
+ else if (Array.isArray(content)) {
47
+ console.warn(`⚠️ Complex content detected, stringifying:`, content);
48
+ content = JSON.stringify(content);
49
+ }
50
+ else if (content === null || content === undefined) {
51
+ content = '';
52
+ }
53
+ else {
54
+ console.warn(`⚠️ Non-string content detected, stringifying:`, typeof content);
55
+ content = JSON.stringify(content);
56
+ }
33
57
  return {
34
58
  role,
35
- content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content),
59
+ content,
36
60
  };
37
61
  });
38
62
  if (this.options.systemMessage && this.options.systemMessage.trim()) {
39
- const hasSystemMessage = copilotMessages.some(msg => msg.role === 'system');
63
+ const hasSystemMessage = copilotMessages.some((msg) => msg.role === 'system');
40
64
  if (!hasSystemMessage) {
41
65
  copilotMessages.unshift({
42
66
  role: 'system',
43
67
  content: this.options.systemMessage,
44
68
  });
69
+ console.log(`🔧 Added system message from options`);
45
70
  }
46
71
  }
72
+ const validMessages = copilotMessages.filter((msg) => {
73
+ if (!msg.content || msg.content.trim() === '') {
74
+ console.warn(`⚠️ Filtering out empty message with role: ${msg.role}`);
75
+ return false;
76
+ }
77
+ return true;
78
+ });
79
+ if (validMessages.length === 0) {
80
+ throw new Error('No valid messages after filtering empty content');
81
+ }
47
82
  const requestBody = {
48
83
  model: this.modelName || this.model,
49
- messages: copilotMessages,
84
+ messages: validMessages,
50
85
  temperature: this.temperature,
51
86
  max_tokens: this.maxTokens,
52
87
  top_p: this.topP,
53
- stream: false,
88
+ stream: this.options.enableStreaming || false,
54
89
  };
55
90
  if (this.options.tools && this.options.tools.length > 0) {
56
91
  requestBody.tools = this.options.tools;
57
- requestBody.tool_choice = this.options.tool_choice || "auto";
92
+ requestBody.tool_choice = this.options.tool_choice || 'auto';
93
+ console.log(`🔧 Request includes ${this.options.tools.length} tools`);
58
94
  }
95
+ const startTime = Date.now();
59
96
  try {
60
97
  const response = await (0, GitHubCopilotApiUtils_1.makeGitHubCopilotRequest)(this.context, GitHubCopilotEndpoints_1.GITHUB_COPILOT_API.ENDPOINTS.CHAT_COMPLETIONS, requestBody, false);
98
+ const endTime = Date.now();
99
+ const latency = endTime - startTime;
100
+ console.log(`⏱️ GitHub Copilot API call completed in ${latency}ms`);
101
+ if (!response.choices || response.choices.length === 0) {
102
+ throw new Error('GitHub Copilot API returned no choices in response');
103
+ }
61
104
  const choice = response.choices[0];
105
+ if (!choice.message) {
106
+ throw new Error('GitHub Copilot API returned choice without message');
107
+ }
62
108
  const langchainMessage = {
63
109
  _getType: () => choice.message.role,
64
- content: choice.message.content || "",
110
+ content: choice.message.content || '',
65
111
  tool_calls: choice.message.tool_calls,
66
112
  };
113
+ console.log(`📝 Response: role=${choice.message.role}, content_length=${((_a = choice.message.content) === null || _a === void 0 ? void 0 : _a.length) || 0}, finish_reason=${choice.finish_reason}`);
67
114
  return {
68
- generations: [[{
69
- text: choice.message.content || "",
70
- generationInfo: {
71
- finish_reason: choice.finish_reason,
72
- },
73
- message: langchainMessage,
74
- }]],
75
- tokenUsage: response.usage,
115
+ generations: [
116
+ {
117
+ text: choice.message.content || '',
118
+ generationInfo: {
119
+ finish_reason: choice.finish_reason,
120
+ },
121
+ message: langchainMessage,
122
+ },
123
+ ],
124
+ llmOutput: {
125
+ tokenUsage: response.usage,
126
+ },
76
127
  };
77
128
  }
78
129
  catch (error) {
130
+ const endTime = Date.now();
131
+ const latency = endTime - startTime;
132
+ console.error(`❌ GitHub Copilot API call failed after ${latency}ms:`, error);
79
133
  throw new Error(`GitHub Copilot API error: ${error instanceof Error ? error.message : String(error)}`);
80
134
  }
81
135
  }
@@ -83,147 +137,146 @@ class GitHubCopilotChatOpenAI extends openai_1.ChatOpenAI {
83
137
  class GitHubCopilotChatModel {
84
138
  constructor() {
85
139
  this.description = {
86
- displayName: "GitHub Copilot Chat Model",
87
- name: "gitHubCopilotChatModel",
88
- icon: "file:../../shared/icons/copilot.svg",
89
- group: ["transform"],
140
+ displayName: 'GitHub Copilot Chat Model',
141
+ name: 'gitHubCopilotChatModel',
142
+ icon: 'file:../../shared/icons/copilot.svg',
143
+ group: ['transform'],
90
144
  version: 1,
91
- description: "GitHub Copilot chat model for AI workflows with full support for tools and function calling - access GPT-5, Claude, Gemini and more using your Copilot subscription",
145
+ description: 'GitHub Copilot chat model for AI workflows with full support for tools and function calling - access GPT-5, Claude, Gemini and more using your Copilot subscription',
92
146
  defaults: {
93
- name: "GitHub Copilot Chat Model",
147
+ name: 'GitHub Copilot Chat Model',
94
148
  },
95
149
  codex: {
96
- categories: ["AI"],
150
+ categories: ['AI'],
97
151
  subcategories: {
98
- AI: ["Language Models", "Root Nodes"],
99
- "Language Models": ["Chat Models (Recommended)"],
152
+ AI: ['Language Models', 'Root Nodes'],
153
+ 'Language Models': ['Chat Models (Recommended)'],
100
154
  },
101
155
  resources: {
102
156
  primaryDocumentation: [
103
157
  {
104
- url: "https://docs.github.com/copilot/using-github-copilot/using-github-copilot-chat",
158
+ url: 'https://docs.github.com/copilot/using-github-copilot/using-github-copilot-chat',
105
159
  },
106
160
  ],
107
161
  },
108
162
  },
109
163
  inputs: [],
110
- outputs: ["ai_languageModel"],
111
- outputNames: ["Model"],
164
+ outputs: ['ai_languageModel'],
165
+ outputNames: ['Model'],
112
166
  credentials: [
113
167
  {
114
- name: "githubCopilotApi",
168
+ name: 'githubCopilotApi',
115
169
  required: true,
116
170
  },
117
171
  ],
118
172
  properties: [
119
173
  ...ModelProperties_1.CHAT_MODEL_PROPERTIES,
120
174
  {
121
- displayName: "Options",
122
- name: "options",
123
- placeholder: "Add Option",
124
- description: "Additional options for the GitHub Copilot model",
125
- type: "collection",
175
+ displayName: 'Options',
176
+ name: 'options',
177
+ placeholder: 'Add Option',
178
+ description: 'Additional options for the GitHub Copilot model',
179
+ type: 'collection',
126
180
  default: {},
127
181
  options: [
128
182
  {
129
- displayName: "Temperature",
130
- name: "temperature",
183
+ displayName: 'Temperature',
184
+ name: 'temperature',
131
185
  default: 0.7,
132
186
  typeOptions: { maxValue: 2, minValue: 0, numberPrecision: 1 },
133
- description: "Controls randomness in output. Lower values make responses more focused.",
134
- type: "number",
187
+ description: 'Controls randomness in output. Lower values make responses more focused.',
188
+ type: 'number',
135
189
  },
136
190
  {
137
- displayName: "Maximum Number of Tokens",
138
- name: "maxTokens",
191
+ displayName: 'Maximum Number of Tokens',
192
+ name: 'maxTokens',
139
193
  default: 1000,
140
- description: "The maximum number of tokens to generate",
141
- type: "number",
194
+ description: 'The maximum number of tokens to generate',
195
+ type: 'number',
142
196
  typeOptions: {
143
197
  maxValue: 32768,
144
198
  },
145
199
  },
146
200
  {
147
- displayName: "Top P",
148
- name: "topP",
201
+ displayName: 'Top P',
202
+ name: 'topP',
149
203
  default: 1,
150
204
  typeOptions: { maxValue: 1, minValue: 0, numberPrecision: 2 },
151
- description: "Controls diversity of output by nucleus sampling",
152
- type: "number",
205
+ description: 'Controls diversity of output by nucleus sampling',
206
+ type: 'number',
153
207
  },
154
208
  {
155
- displayName: "Enable Vision",
156
- name: "enableVision",
157
- type: "boolean",
158
- default: true,
159
- description: "Whether to enable image processing capabilities",
209
+ displayName: 'Enable Streaming',
210
+ name: 'enableStreaming',
211
+ type: 'boolean',
212
+ default: false,
213
+ description: 'Enable streaming responses for real-time output (experimental)',
160
214
  },
161
215
  {
162
- displayName: "System Message",
163
- name: "systemMessage",
164
- type: "string",
165
- default: "",
166
- description: "System message to set the behavior of the assistant",
216
+ displayName: 'System Message',
217
+ name: 'systemMessage',
218
+ type: 'string',
219
+ default: '',
220
+ description: 'System message to set the behavior of the assistant',
167
221
  typeOptions: {
168
222
  rows: 3,
169
223
  },
170
224
  },
171
225
  {
172
- displayName: "Auto Retry on 403 Error",
173
- name: "enableRetry",
174
- type: "boolean",
226
+ displayName: 'Auto Retry on 403 Error',
227
+ name: 'enableRetry',
228
+ type: 'boolean',
175
229
  default: true,
176
- description: "Automatically retry requests when hitting TPM (Transactions Per Minute) quota limits (HTTP 403)",
230
+ description: 'Automatically retry requests when hitting TPM (Transactions Per Minute) quota limits (HTTP 403)',
177
231
  },
178
232
  {
179
- displayName: "Max Retry Attempts",
180
- name: "maxRetries",
181
- type: "number",
182
- default: 3,
183
- description: "Maximum number of retry attempts for 403 errors",
184
- displayOptions: {
185
- show: {
186
- enableRetry: [true],
187
- },
233
+ displayName: 'Request Timeout (seconds)',
234
+ name: 'timeout',
235
+ type: 'number',
236
+ default: 120,
237
+ description: 'Maximum time to wait for API response (in seconds)',
238
+ typeOptions: {
239
+ minValue: 10,
240
+ maxValue: 300,
188
241
  },
189
242
  },
190
243
  {
191
- displayName: "Tools (Function Calling)",
192
- name: "tools",
193
- type: "string",
194
- default: "",
195
- description: "Optional: Array of tools/functions available to the model (OpenAI format). Leave empty if not using function calling.",
244
+ displayName: 'Tools (Function Calling)',
245
+ name: 'tools',
246
+ type: 'string',
247
+ default: '',
248
+ description: 'Optional: Array of tools/functions available to the model (OpenAI format). Leave empty if not using function calling.',
196
249
  hint: "JSON array of tool definitions in OpenAI format. Leave this field empty if you don't need function calling.",
197
250
  typeOptions: {
198
251
  rows: 6,
199
252
  },
200
253
  },
201
254
  {
202
- displayName: "Tool Choice",
203
- name: "tool_choice",
204
- type: "options",
255
+ displayName: 'Tool Choice',
256
+ name: 'tool_choice',
257
+ type: 'options',
205
258
  options: [
206
259
  {
207
- name: "Auto",
208
- value: "auto",
209
- description: "Let the model decide when to use tools",
260
+ name: 'Auto',
261
+ value: 'auto',
262
+ description: 'Let the model decide when to use tools',
210
263
  },
211
264
  {
212
- name: "Required",
213
- value: "required",
214
- description: "Force the model to use at least one tool",
265
+ name: 'Required',
266
+ value: 'required',
267
+ description: 'Force the model to use at least one tool',
215
268
  },
216
269
  {
217
- name: "None",
218
- value: "none",
219
- description: "Disable tool usage",
270
+ name: 'None',
271
+ value: 'none',
272
+ description: 'Disable tool usage',
220
273
  },
221
274
  ],
222
- default: "auto",
223
- description: "Control how the model uses tools",
275
+ default: 'auto',
276
+ description: 'Control how the model uses tools',
224
277
  displayOptions: {
225
278
  show: {
226
- tools: ["/.+/"],
279
+ tools: ['/.+/'],
227
280
  },
228
281
  },
229
282
  },
@@ -240,10 +293,10 @@ class GitHubCopilotChatModel {
240
293
  };
241
294
  }
242
295
  async supplyData(itemIndex) {
243
- let model = this.getNodeParameter("model", itemIndex);
244
- if (model === "__manual__") {
245
- const customModel = this.getNodeParameter("customModel", itemIndex);
246
- if (!customModel || customModel.trim() === "") {
296
+ let model = this.getNodeParameter('model', itemIndex);
297
+ if (model === '__manual__') {
298
+ const customModel = this.getNodeParameter('customModel', itemIndex);
299
+ if (!customModel || customModel.trim() === '') {
247
300
  throw new Error("Custom model name is required when selecting '✏️ Enter Custom Model Name'");
248
301
  }
249
302
  model = customModel;
@@ -252,21 +305,21 @@ class GitHubCopilotChatModel {
252
305
  else {
253
306
  console.log(`✅ Using model from list: ${model}`);
254
307
  }
255
- const options = this.getNodeParameter("options", itemIndex, {});
308
+ const options = this.getNodeParameter('options', itemIndex, {});
256
309
  const modelInfo = GitHubCopilotModels_1.GitHubCopilotModelsManager.getModelByValue(model);
257
- const credentials = (await this.getCredentials("githubCopilotApi"));
310
+ const credentials = (await this.getCredentials('githubCopilotApi'));
258
311
  const token = credentials.token;
259
312
  if (!token) {
260
- console.error("❌ Available credential properties:", Object.keys(credentials));
261
- throw new Error("GitHub Copilot: No token found in credentials. Available properties: " +
262
- Object.keys(credentials).join(", "));
313
+ console.error('❌ Available credential properties:', Object.keys(credentials));
314
+ throw new Error('GitHub Copilot: No token found in credentials. Available properties: ' +
315
+ Object.keys(credentials).join(', '));
263
316
  }
264
- const tokenPrefix = token.substring(0, Math.min(4, token.indexOf("_") + 1)) || token.substring(0, 4);
317
+ const tokenPrefix = token.substring(0, Math.min(4, token.indexOf('_') + 1)) || token.substring(0, 4);
265
318
  const tokenSuffix = token.substring(Math.max(0, token.length - 5));
266
319
  console.log(`🔍 GitHub Copilot ChatModel OAuth2 Debug: Using token ${tokenPrefix}...${tokenSuffix}`);
267
- if (!token.startsWith("gho_") &&
268
- !token.startsWith("ghu_") &&
269
- !token.startsWith("github_pat_")) {
320
+ if (!token.startsWith('gho_') &&
321
+ !token.startsWith('ghu_') &&
322
+ !token.startsWith('github_pat_')) {
270
323
  console.warn(`⚠️ Unexpected token format: ${tokenPrefix}...${tokenSuffix}. Trying API call anyway.`);
271
324
  }
272
325
  const safeModel = modelInfo ? model : GitHubCopilotModels_1.DEFAULT_MODELS.GENERAL;
@@ -287,7 +340,7 @@ class GitHubCopilotChatModel {
287
340
  }
288
341
  }
289
342
  catch (error) {
290
- console.log(`⚠️ Failed to parse tools JSON: ${error instanceof Error ? error.message : "Unknown error"}`);
343
+ console.log(`⚠️ Failed to parse tools JSON: ${error instanceof Error ? error.message : 'Unknown error'}`);
291
344
  }
292
345
  }
293
346
  const modelConfig = {
@@ -298,22 +351,22 @@ class GitHubCopilotChatModel {
298
351
  maxRetries: options.enableRetry !== false ? options.maxRetries || 3 : 0,
299
352
  ...(parsedTools.length > 0 && {
300
353
  tools: parsedTools,
301
- tool_choice: options.tool_choice || "auto",
354
+ tool_choice: options.tool_choice || 'auto',
302
355
  }),
303
356
  configuration: {
304
357
  baseURL: GitHubCopilotEndpoints_1.GITHUB_COPILOT_API.BASE_URL,
305
358
  apiKey: token,
306
359
  defaultHeaders: {
307
- "User-Agent": "GitHubCopilotChat/1.0.0 n8n/3.10.1",
308
- Accept: "application/json",
309
- "Editor-Version": `vscode/${minVSCodeVersion}`,
310
- "Editor-Plugin-Version": "copilot-chat/0.12.0",
311
- "X-Request-Id": `n8n-chatmodel-${Date.now()}-${Math.random().toString(36).substring(7)}`,
360
+ 'User-Agent': 'GitHubCopilotChat/1.0.0 n8n/3.10.1',
361
+ Accept: 'application/json',
362
+ 'Editor-Version': `vscode/${minVSCodeVersion}`,
363
+ 'Editor-Plugin-Version': 'copilot-chat/0.12.0',
364
+ 'X-Request-Id': `n8n-chatmodel-${Date.now()}-${Math.random().toString(36).substring(7)}`,
312
365
  ...additionalHeaders,
313
366
  ...(options.enableVision &&
314
367
  (safeModelInfo === null || safeModelInfo === void 0 ? void 0 : safeModelInfo.capabilities.vision) && {
315
- "Copilot-Vision-Request": "true",
316
- "Copilot-Media-Request": "true",
368
+ 'Copilot-Vision-Request': 'true',
369
+ 'Copilot-Media-Request': 'true',
317
370
  }),
318
371
  },
319
372
  },
@@ -1,4 +1,4 @@
1
- import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, ILoadOptionsFunctions, INodePropertyOptions } from "n8n-workflow";
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, ILoadOptionsFunctions, INodePropertyOptions } from 'n8n-workflow';
2
2
  export declare class GitHubCopilotEmbeddings implements INodeType {
3
3
  description: INodeTypeDescription;
4
4
  methods: {