n8n-nodes-github-copilot 3.2.0 → 3.2.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.
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GitHubCopilotChatAPI = void 0;
4
4
  const utils_1 = require("./utils");
5
+ const nodeProperties_1 = require("./nodeProperties");
5
6
  async function processAudioFileLegacy(context, itemIndex) {
6
7
  const audioSource = context.getNodeParameter('audioSource', itemIndex);
7
8
  try {
@@ -72,283 +73,7 @@ class GitHubCopilotChatAPI {
72
73
  required: true,
73
74
  },
74
75
  ],
75
- properties: [
76
- {
77
- displayName: 'Operation',
78
- name: 'operation',
79
- type: 'options',
80
- noDataExpression: true,
81
- options: [
82
- {
83
- name: 'Chat Completion',
84
- value: 'chat',
85
- description: 'Send messages to GitHub Copilot Chat API',
86
- },
87
- ],
88
- default: 'chat',
89
- },
90
- {
91
- displayName: 'Model',
92
- name: 'model',
93
- type: 'options',
94
- options: [
95
- {
96
- name: 'GPT-5',
97
- value: 'gpt-5',
98
- description: 'OpenAI GPT-5 (Latest and most capable)',
99
- },
100
- {
101
- name: 'GPT-5 Mini',
102
- value: 'gpt-5-mini',
103
- description: 'OpenAI GPT-5 Mini (Faster, cost-effective)',
104
- },
105
- {
106
- name: 'Claude Opus 4.1',
107
- value: 'claude-opus-4.1',
108
- description: 'Anthropic Claude Opus 4.1 (Advanced reasoning)',
109
- },
110
- {
111
- name: 'Gemini 2.5 Pro',
112
- value: 'gemini-2.5-pro',
113
- description: 'Google Gemini 2.5 Pro (Multimodal capabilities)',
114
- },
115
- {
116
- name: 'Grok Code Fast 1',
117
- value: 'grok-code-fast-1',
118
- description: 'xAI Grok Code Fast 1 (Optimized for coding)',
119
- },
120
- {
121
- name: 'GPT-4.1 Copilot',
122
- value: 'gpt-4.1-copilot',
123
- description: 'OpenAI GPT-4.1 specialized for coding assistance',
124
- },
125
- ],
126
- default: 'gpt-5-mini',
127
- description: 'Select AI model to use',
128
- },
129
- {
130
- displayName: 'Message',
131
- name: 'message',
132
- type: 'string',
133
- typeOptions: {
134
- rows: 4,
135
- },
136
- default: '',
137
- placeholder: 'What can I help you with?',
138
- description: 'The message to send to the AI model',
139
- },
140
- {
141
- displayName: 'System Message',
142
- name: 'systemMessage',
143
- type: 'string',
144
- typeOptions: {
145
- rows: 3,
146
- },
147
- default: '',
148
- placeholder: 'You are a helpful assistant...',
149
- description: 'System message to set the behavior of the AI model',
150
- },
151
- {
152
- displayName: 'Include Image',
153
- name: 'includeImage',
154
- type: 'boolean',
155
- default: false,
156
- description: 'Whether to include an image in the message',
157
- },
158
- {
159
- displayName: 'Image Source',
160
- name: 'imageSource',
161
- type: 'options',
162
- displayOptions: {
163
- show: {
164
- includeImage: [true],
165
- },
166
- },
167
- options: [
168
- {
169
- name: 'Manual Input',
170
- value: 'manual',
171
- description: 'Provide image as base64 string or file path',
172
- },
173
- {
174
- name: 'URL',
175
- value: 'url',
176
- description: 'Download image from URL',
177
- },
178
- {
179
- name: 'Binary Data',
180
- value: 'binary',
181
- description: 'Use binary data from previous node',
182
- },
183
- ],
184
- default: 'manual',
185
- description: 'Source of the image data',
186
- },
187
- {
188
- displayName: 'Image File',
189
- name: 'imageFile',
190
- type: 'string',
191
- displayOptions: {
192
- show: {
193
- includeImage: [true],
194
- imageSource: ['manual'],
195
- },
196
- },
197
- default: '',
198
- placeholder: 'Paste base64 string or file path',
199
- description: 'Image as base64 string or file path',
200
- },
201
- {
202
- displayName: 'Image URL',
203
- name: 'imageUrl',
204
- type: 'string',
205
- displayOptions: {
206
- show: {
207
- includeImage: [true],
208
- imageSource: ['url'],
209
- },
210
- },
211
- default: '',
212
- placeholder: 'https://example.com/image.jpg',
213
- description: 'URL of the image to download and include',
214
- },
215
- {
216
- displayName: 'Image Binary Property',
217
- name: 'imageBinaryProperty',
218
- type: 'string',
219
- displayOptions: {
220
- show: {
221
- includeImage: [true],
222
- imageSource: ['binary'],
223
- },
224
- },
225
- default: 'data',
226
- placeholder: 'data',
227
- description: 'Name of the binary property containing the image',
228
- },
229
- {
230
- displayName: 'Include Audio',
231
- name: 'includeAudio',
232
- type: 'boolean',
233
- default: false,
234
- description: 'Whether to include an audio file in the message',
235
- },
236
- {
237
- displayName: 'Audio Source',
238
- name: 'audioSource',
239
- type: 'options',
240
- displayOptions: {
241
- show: {
242
- includeAudio: [true],
243
- },
244
- },
245
- options: [
246
- {
247
- name: 'Manual Input',
248
- value: 'manual',
249
- description: 'Provide audio as base64 string or file path',
250
- },
251
- {
252
- name: 'URL',
253
- value: 'url',
254
- description: 'Download audio from URL',
255
- },
256
- {
257
- name: 'Binary Data',
258
- value: 'binary',
259
- description: 'Use binary data from previous node',
260
- },
261
- ],
262
- default: 'manual',
263
- description: 'Source of the audio data',
264
- },
265
- {
266
- displayName: 'Audio File',
267
- name: 'audioFile',
268
- type: 'string',
269
- displayOptions: {
270
- show: {
271
- includeAudio: [true],
272
- audioSource: ['manual'],
273
- },
274
- },
275
- default: '',
276
- placeholder: 'Paste base64 string or file path',
277
- description: 'Audio as base64 string or file path',
278
- },
279
- {
280
- displayName: 'Audio URL',
281
- name: 'audioUrl',
282
- type: 'string',
283
- displayOptions: {
284
- show: {
285
- includeAudio: [true],
286
- audioSource: ['url'],
287
- },
288
- },
289
- default: '',
290
- placeholder: 'https://example.com/audio.mp3',
291
- description: 'URL of the audio file to download and include',
292
- },
293
- {
294
- displayName: 'Audio Binary Property',
295
- name: 'audioBinaryProperty',
296
- type: 'string',
297
- displayOptions: {
298
- show: {
299
- includeAudio: [true],
300
- audioSource: ['binary'],
301
- },
302
- },
303
- default: 'data',
304
- placeholder: 'data',
305
- description: 'Name of the binary property containing the audio file',
306
- },
307
- {
308
- displayName: 'Advanced Options',
309
- name: 'advancedOptions',
310
- type: 'collection',
311
- placeholder: 'Add Field',
312
- default: {},
313
- options: [
314
- {
315
- displayName: 'Temperature',
316
- name: 'temperature',
317
- type: 'number',
318
- typeOptions: {
319
- minValue: 0,
320
- maxValue: 2,
321
- numberPrecision: 2,
322
- },
323
- default: 1,
324
- description: 'Controls randomness of the response. Higher values make output more random.',
325
- },
326
- {
327
- displayName: 'Max Tokens',
328
- name: 'max_tokens',
329
- type: 'number',
330
- typeOptions: {
331
- minValue: 1,
332
- maxValue: 128000,
333
- },
334
- default: 4096,
335
- description: 'Maximum number of tokens to generate in the response',
336
- },
337
- {
338
- displayName: 'Top P',
339
- name: 'top_p',
340
- type: 'number',
341
- typeOptions: {
342
- minValue: 0,
343
- maxValue: 1,
344
- numberPrecision: 2,
345
- },
346
- default: 1,
347
- description: 'Alternative to temperature, controls diversity via nucleus sampling',
348
- },
349
- ],
350
- },
351
- ],
76
+ properties: nodeProperties_1.nodeProperties,
352
77
  };
353
78
  }
354
79
  async execute() {
@@ -393,9 +118,16 @@ class GitHubCopilotChatAPI {
393
118
  if (includeAudio) {
394
119
  const audioResult = await processAudioFileLegacy(this, i);
395
120
  if (audioResult.dataUrl) {
121
+ contentArray.push({
122
+ type: 'input_audio',
123
+ input_audio: {
124
+ data: audioResult.dataUrl.split(',')[1],
125
+ format: audioResult.dataUrl.includes('mp3') ? 'mp3' : 'wav'
126
+ },
127
+ });
396
128
  contentArray.push({
397
129
  type: 'text',
398
- text: `[Audio included: ${audioResult.description}]`,
130
+ text: `Please transcribe this audio: ${audioResult.description}`,
399
131
  });
400
132
  }
401
133
  else {
@@ -417,7 +149,8 @@ class GitHubCopilotChatAPI {
417
149
  stream: false,
418
150
  ...advancedOptions,
419
151
  };
420
- const response = await (0, utils_1.makeApiRequest)(this, '/chat/completions', requestBody);
152
+ const hasMedia = includeImage || includeAudio;
153
+ const response = await (0, utils_1.makeApiRequest)(this, '/chat/completions', requestBody, hasMedia);
421
154
  const result = {
422
155
  message: ((_b = (_a = response.choices[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content) || '',
423
156
  model,
@@ -0,0 +1,2 @@
1
+ import { INodeProperties } from 'n8n-workflow';
2
+ export declare const nodeProperties: INodeProperties[];
@@ -0,0 +1,280 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.nodeProperties = void 0;
4
+ exports.nodeProperties = [
5
+ {
6
+ displayName: 'Operation',
7
+ name: 'operation',
8
+ type: 'options',
9
+ noDataExpression: true,
10
+ options: [
11
+ {
12
+ name: 'Chat Completion',
13
+ value: 'chat',
14
+ description: 'Send messages to GitHub Copilot Chat API',
15
+ },
16
+ ],
17
+ default: 'chat',
18
+ },
19
+ {
20
+ displayName: 'Model',
21
+ name: 'model',
22
+ type: 'options',
23
+ options: [
24
+ {
25
+ name: 'GPT-5',
26
+ value: 'gpt-5',
27
+ description: 'OpenAI GPT-5 (Latest and most capable)',
28
+ },
29
+ {
30
+ name: 'GPT-5 Mini',
31
+ value: 'gpt-5-mini',
32
+ description: 'OpenAI GPT-5 Mini (Faster, cost-effective)',
33
+ },
34
+ {
35
+ name: 'Claude Opus 4.1',
36
+ value: 'claude-opus-4.1',
37
+ description: 'Anthropic Claude Opus 4.1 (Advanced reasoning)',
38
+ },
39
+ {
40
+ name: 'Gemini 2.5 Pro',
41
+ value: 'gemini-2.5-pro',
42
+ description: 'Google Gemini 2.5 Pro (Multimodal capabilities)',
43
+ },
44
+ {
45
+ name: 'Grok Code Fast 1',
46
+ value: 'grok-code-fast-1',
47
+ description: 'xAI Grok Code Fast 1 (Optimized for coding)',
48
+ },
49
+ {
50
+ name: 'GPT-4.1 Copilot',
51
+ value: 'gpt-4.1-copilot',
52
+ description: 'OpenAI GPT-4.1 specialized for coding assistance',
53
+ },
54
+ ],
55
+ default: 'gpt-5-mini',
56
+ description: 'Select AI model to use',
57
+ },
58
+ {
59
+ displayName: 'Message',
60
+ name: 'message',
61
+ type: 'string',
62
+ typeOptions: {
63
+ rows: 4,
64
+ },
65
+ default: '',
66
+ placeholder: 'What can I help you with?',
67
+ description: 'The message to send to the AI model',
68
+ },
69
+ {
70
+ displayName: 'System Message',
71
+ name: 'systemMessage',
72
+ type: 'string',
73
+ typeOptions: {
74
+ rows: 3,
75
+ },
76
+ default: '',
77
+ placeholder: 'You are a helpful assistant...',
78
+ description: 'System message to set the behavior of the AI model',
79
+ },
80
+ {
81
+ displayName: 'Include Image',
82
+ name: 'includeImage',
83
+ type: 'boolean',
84
+ default: false,
85
+ description: 'Whether to include an image in the message',
86
+ },
87
+ {
88
+ displayName: 'Image Source',
89
+ name: 'imageSource',
90
+ type: 'options',
91
+ displayOptions: {
92
+ show: {
93
+ includeImage: [true],
94
+ },
95
+ },
96
+ options: [
97
+ {
98
+ name: 'Manual Input',
99
+ value: 'manual',
100
+ description: 'Provide image as base64 string or file path',
101
+ },
102
+ {
103
+ name: 'URL',
104
+ value: 'url',
105
+ description: 'Download image from URL',
106
+ },
107
+ {
108
+ name: 'Binary Data',
109
+ value: 'binary',
110
+ description: 'Use binary data from previous node',
111
+ },
112
+ ],
113
+ default: 'manual',
114
+ description: 'Source of the image data',
115
+ },
116
+ {
117
+ displayName: 'Image File',
118
+ name: 'imageFile',
119
+ type: 'string',
120
+ displayOptions: {
121
+ show: {
122
+ includeImage: [true],
123
+ imageSource: ['manual'],
124
+ },
125
+ },
126
+ default: '',
127
+ placeholder: 'Paste base64 string or file path',
128
+ description: 'Image as base64 string or file path',
129
+ },
130
+ {
131
+ displayName: 'Image URL',
132
+ name: 'imageUrl',
133
+ type: 'string',
134
+ displayOptions: {
135
+ show: {
136
+ includeImage: [true],
137
+ imageSource: ['url'],
138
+ },
139
+ },
140
+ default: '',
141
+ placeholder: 'https://example.com/image.jpg',
142
+ description: 'URL of the image to download and include',
143
+ },
144
+ {
145
+ displayName: 'Image Binary Property',
146
+ name: 'imageBinaryProperty',
147
+ type: 'string',
148
+ displayOptions: {
149
+ show: {
150
+ includeImage: [true],
151
+ imageSource: ['binary'],
152
+ },
153
+ },
154
+ default: 'data',
155
+ placeholder: 'data',
156
+ description: 'Name of the binary property containing the image',
157
+ },
158
+ {
159
+ displayName: 'Include Audio',
160
+ name: 'includeAudio',
161
+ type: 'boolean',
162
+ default: false,
163
+ description: 'Whether to include an audio file in the message',
164
+ },
165
+ {
166
+ displayName: 'Audio Source',
167
+ name: 'audioSource',
168
+ type: 'options',
169
+ displayOptions: {
170
+ show: {
171
+ includeAudio: [true],
172
+ },
173
+ },
174
+ options: [
175
+ {
176
+ name: 'Manual Input',
177
+ value: 'manual',
178
+ description: 'Provide audio as base64 string or file path',
179
+ },
180
+ {
181
+ name: 'URL',
182
+ value: 'url',
183
+ description: 'Download audio from URL',
184
+ },
185
+ {
186
+ name: 'Binary Data',
187
+ value: 'binary',
188
+ description: 'Use binary data from previous node',
189
+ },
190
+ ],
191
+ default: 'manual',
192
+ description: 'Source of the audio data',
193
+ },
194
+ {
195
+ displayName: 'Audio File',
196
+ name: 'audioFile',
197
+ type: 'string',
198
+ displayOptions: {
199
+ show: {
200
+ includeAudio: [true],
201
+ audioSource: ['manual'],
202
+ },
203
+ },
204
+ default: '',
205
+ placeholder: 'Paste base64 string or file path',
206
+ description: 'Audio as base64 string or file path',
207
+ },
208
+ {
209
+ displayName: 'Audio URL',
210
+ name: 'audioUrl',
211
+ type: 'string',
212
+ displayOptions: {
213
+ show: {
214
+ includeAudio: [true],
215
+ audioSource: ['url'],
216
+ },
217
+ },
218
+ default: '',
219
+ placeholder: 'https://example.com/audio.mp3',
220
+ description: 'URL of the audio file to download and include',
221
+ },
222
+ {
223
+ displayName: 'Audio Binary Property',
224
+ name: 'audioBinaryProperty',
225
+ type: 'string',
226
+ displayOptions: {
227
+ show: {
228
+ includeAudio: [true],
229
+ audioSource: ['binary'],
230
+ },
231
+ },
232
+ default: 'data',
233
+ placeholder: 'data',
234
+ description: 'Name of the binary property containing the audio file',
235
+ },
236
+ {
237
+ displayName: 'Advanced Options',
238
+ name: 'advancedOptions',
239
+ type: 'collection',
240
+ placeholder: 'Add Field',
241
+ default: {},
242
+ options: [
243
+ {
244
+ displayName: 'Temperature',
245
+ name: 'temperature',
246
+ type: 'number',
247
+ typeOptions: {
248
+ minValue: 0,
249
+ maxValue: 2,
250
+ numberPrecision: 2,
251
+ },
252
+ default: 1,
253
+ description: 'Controls randomness of the response. Higher values make output more random.',
254
+ },
255
+ {
256
+ displayName: 'Max Tokens',
257
+ name: 'max_tokens',
258
+ type: 'number',
259
+ typeOptions: {
260
+ minValue: 1,
261
+ maxValue: 128000,
262
+ },
263
+ default: 4096,
264
+ description: 'Maximum number of tokens to generate in the response',
265
+ },
266
+ {
267
+ displayName: 'Top P',
268
+ name: 'top_p',
269
+ type: 'number',
270
+ typeOptions: {
271
+ minValue: 0,
272
+ maxValue: 1,
273
+ numberPrecision: 2,
274
+ },
275
+ default: 1,
276
+ description: 'Alternative to temperature, controls diversity via nucleus sampling',
277
+ },
278
+ ],
279
+ },
280
+ ];
@@ -2,7 +2,7 @@
2
2
  /// <reference types="node" />
3
3
  import { IExecuteFunctions } from 'n8n-workflow';
4
4
  import { CopilotResponse } from './types';
5
- export declare function makeApiRequest(context: IExecuteFunctions, endpoint: string, body: Record<string, unknown>): Promise<CopilotResponse>;
5
+ export declare function makeApiRequest(context: IExecuteFunctions, endpoint: string, body: Record<string, unknown>, hasMedia?: boolean): Promise<CopilotResponse>;
6
6
  export declare function downloadFileFromUrl(url: string): Promise<Buffer>;
7
7
  export declare function getFileFromBinary(context: IExecuteFunctions, itemIndex: number, propertyName: string): Promise<Buffer>;
8
8
  export declare function getImageMimeType(filename: string): string;
@@ -1,15 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.truncateToTokenLimit = exports.validateTokenLimit = exports.estimateTokens = exports.validateFileSize = exports.getAudioMimeType = exports.getImageMimeType = exports.getFileFromBinary = exports.downloadFileFromUrl = exports.makeApiRequest = void 0;
4
- async function makeApiRequest(context, endpoint, body) {
4
+ async function makeApiRequest(context, endpoint, body, hasMedia = false) {
5
5
  const credentials = await context.getCredentials('githubApi');
6
+ const headers = {
7
+ 'Authorization': `Bearer ${credentials.accessToken}`,
8
+ 'Content-Type': 'application/json',
9
+ 'User-Agent': 'n8n-github-copilot-chat-api-node',
10
+ };
11
+ if (hasMedia) {
12
+ headers['Copilot-Vision-Request'] = 'true';
13
+ headers['Copilot-Media-Request'] = 'true';
14
+ }
6
15
  const options = {
7
16
  method: 'POST',
8
- headers: {
9
- 'Authorization': `Bearer ${credentials.accessToken}`,
10
- 'Content-Type': 'application/json',
11
- 'User-Agent': 'n8n-github-copilot-chat-api-node',
12
- },
17
+ headers,
13
18
  body: JSON.stringify(body),
14
19
  };
15
20
  const response = await fetch(`https://api.githubcopilot.com${endpoint}`, options);
@@ -1,13 +1,18 @@
1
1
  import { IExecuteFunctions } from 'n8n-workflow';
2
2
  export interface ChatMessage {
3
3
  role: 'system' | 'user' | 'assistant';
4
- content: string | Array<{
5
- type: string;
6
- text?: string;
7
- image_url?: {
8
- url: string;
9
- };
10
- }>;
4
+ content: string | Array<ChatMessageContent>;
5
+ }
6
+ export interface ChatMessageContent {
7
+ type: string;
8
+ text?: string;
9
+ image_url?: {
10
+ url: string;
11
+ };
12
+ input_audio?: {
13
+ data: string;
14
+ format: string;
15
+ };
11
16
  }
12
17
  export interface CopilotResponse {
13
18
  choices: Array<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-github-copilot",
3
- "version": "3.2.0",
3
+ "version": "3.2.2",
4
4
  "description": "n8n community node for GitHub Copilot with CLI integration and official Chat API access to GPT-5, Claude, Gemini and more using your existing Copilot credits",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/sufficit/n8n-nodes-github-copilot",