n8n-nodes-github-copilot 3.2.2 → 3.2.3

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.
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GitHubCopilotChatAPI = void 0;
4
4
  const utils_1 = require("./utils");
5
5
  const nodeProperties_1 = require("./nodeProperties");
6
+ const modelCapabilities_1 = require("./utils/modelCapabilities");
6
7
  async function processAudioFileLegacy(context, itemIndex) {
7
8
  const audioSource = context.getNodeParameter('audioSource', itemIndex);
8
9
  try {
@@ -90,6 +91,15 @@ class GitHubCopilotChatAPI {
90
91
  const advancedOptions = this.getNodeParameter('advancedOptions', i, {});
91
92
  const includeImage = this.getNodeParameter('includeImage', i, false);
92
93
  const includeAudio = this.getNodeParameter('includeAudio', i, false);
94
+ const validation = (0, modelCapabilities_1.validateModelCapabilities)(model, includeImage, includeAudio);
95
+ if (!validation.isValid) {
96
+ throw new Error(validation.errorMessage || 'Model validation failed');
97
+ }
98
+ if (validation.warnings) {
99
+ for (const warning of validation.warnings) {
100
+ console.warn(`GitHub Copilot API Warning: ${warning}`);
101
+ }
102
+ }
93
103
  const messages = [];
94
104
  if (systemMessage) {
95
105
  messages.push({
@@ -118,16 +128,9 @@ class GitHubCopilotChatAPI {
118
128
  if (includeAudio) {
119
129
  const audioResult = await processAudioFileLegacy(this, i);
120
130
  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
- });
128
131
  contentArray.push({
129
132
  type: 'text',
130
- text: `Please transcribe this audio: ${audioResult.description}`,
133
+ text: `Please analyze this audio file: ${audioResult.description}\n\nAudio data (base64): ${audioResult.dataUrl}`,
131
134
  });
132
135
  }
133
136
  else {
@@ -24,32 +24,32 @@ exports.nodeProperties = [
24
24
  {
25
25
  name: 'GPT-5',
26
26
  value: 'gpt-5',
27
- description: 'OpenAI GPT-5 (Latest and most capable)',
27
+ description: 'OpenAI GPT-5 (Latest and most capable) ✓ Images',
28
28
  },
29
29
  {
30
30
  name: 'GPT-5 Mini',
31
31
  value: 'gpt-5-mini',
32
- description: 'OpenAI GPT-5 Mini (Faster, cost-effective)',
32
+ description: 'OpenAI GPT-5 Mini (Faster, cost-effective) ✓ Images',
33
33
  },
34
34
  {
35
35
  name: 'Claude Opus 4.1',
36
36
  value: 'claude-opus-4.1',
37
- description: 'Anthropic Claude Opus 4.1 (Advanced reasoning)',
37
+ description: 'Anthropic Claude Opus 4.1 (Advanced reasoning) ✗ Text only',
38
38
  },
39
39
  {
40
40
  name: 'Gemini 2.5 Pro',
41
41
  value: 'gemini-2.5-pro',
42
- description: 'Google Gemini 2.5 Pro (Multimodal capabilities)',
42
+ description: 'Google Gemini 2.5 Pro (Multimodal capabilities) ✓ Images',
43
43
  },
44
44
  {
45
45
  name: 'Grok Code Fast 1',
46
46
  value: 'grok-code-fast-1',
47
- description: 'xAI Grok Code Fast 1 (Optimized for coding)',
47
+ description: 'xAI Grok Code Fast 1 (Optimized for coding) ✗ Text only',
48
48
  },
49
49
  {
50
50
  name: 'GPT-4.1 Copilot',
51
51
  value: 'gpt-4.1-copilot',
52
- description: 'OpenAI GPT-4.1 specialized for coding assistance',
52
+ description: 'OpenAI GPT-4.1 specialized for coding assistance ✓ Images',
53
53
  },
54
54
  ],
55
55
  default: 'gpt-5-mini',
@@ -82,7 +82,7 @@ exports.nodeProperties = [
82
82
  name: 'includeImage',
83
83
  type: 'boolean',
84
84
  default: false,
85
- description: 'Whether to include an image in the message',
85
+ description: 'Whether to include an image in the message. ✓ Supported by GPT and Gemini models via GitHub Copilot API.',
86
86
  },
87
87
  {
88
88
  displayName: 'Image Source',
@@ -160,7 +160,7 @@ exports.nodeProperties = [
160
160
  name: 'includeAudio',
161
161
  type: 'boolean',
162
162
  default: false,
163
- description: 'Whether to include an audio file in the message',
163
+ description: 'Whether to include an audio file in the message. ⚠️ Audio is sent as base64 text to models for analysis (GitHub Copilot API limitation).',
164
164
  },
165
165
  {
166
166
  displayName: 'Audio Source',
@@ -0,0 +1,9 @@
1
+ import { IExecuteFunctions } from 'n8n-workflow';
2
+ export declare function processMediaFile(context: IExecuteFunctions, itemIndex: number, source: 'manual' | 'url' | 'binary', mediaFile?: string, mediaUrl?: string, binaryProperty?: string): Promise<{
3
+ type: 'image' | 'audio' | 'unknown';
4
+ dataUrl?: string;
5
+ description: string;
6
+ mimeType: string;
7
+ }>;
8
+ export declare function isImageMimeType(mimeType: string): boolean;
9
+ export declare function isAudioMimeType(mimeType: string): boolean;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isAudioMimeType = exports.isImageMimeType = exports.processMediaFile = void 0;
4
+ const index_1 = require("./index");
5
+ async function processMediaFile(context, itemIndex, source, mediaFile, mediaUrl, binaryProperty) {
6
+ try {
7
+ try {
8
+ const imageResult = await (0, index_1.processImageFile)(context, itemIndex, source, mediaFile, mediaUrl, binaryProperty);
9
+ return {
10
+ type: 'image',
11
+ dataUrl: `data:${imageResult.mimeType};base64,${imageResult.data}`,
12
+ description: `Image file: ${imageResult.filename} (${Math.round(imageResult.size / 1024)}KB)`,
13
+ mimeType: imageResult.mimeType,
14
+ };
15
+ }
16
+ catch (imageError) {
17
+ try {
18
+ const audioResult = await (0, index_1.processAudioFile)(context, itemIndex, source, mediaFile, mediaUrl, binaryProperty);
19
+ return {
20
+ type: 'audio',
21
+ dataUrl: `data:${audioResult.mimeType};base64,${audioResult.data}`,
22
+ description: `Audio file: ${audioResult.filename} (${Math.round(audioResult.size / 1024)}KB)`,
23
+ mimeType: audioResult.mimeType,
24
+ };
25
+ }
26
+ catch (audioError) {
27
+ throw new Error(`File is neither a valid image nor audio file. Image error: ${imageError instanceof Error ? imageError.message : 'Unknown'}. Audio error: ${audioError instanceof Error ? audioError.message : 'Unknown'}`);
28
+ }
29
+ }
30
+ }
31
+ catch (error) {
32
+ return {
33
+ type: 'unknown',
34
+ description: `Error processing media file: ${error instanceof Error ? error.message : 'Unknown error'}`,
35
+ mimeType: 'unknown',
36
+ };
37
+ }
38
+ }
39
+ exports.processMediaFile = processMediaFile;
40
+ function isImageMimeType(mimeType) {
41
+ return mimeType.startsWith('image/') && !mimeType.includes('svg');
42
+ }
43
+ exports.isImageMimeType = isImageMimeType;
44
+ function isAudioMimeType(mimeType) {
45
+ return mimeType.startsWith('audio/') ||
46
+ mimeType === 'application/ogg' ||
47
+ mimeType === 'video/mp4';
48
+ }
49
+ exports.isAudioMimeType = isAudioMimeType;
@@ -0,0 +1,5 @@
1
+ import { ModelCapabilities, ModelValidationResult } from './types';
2
+ export declare const MODEL_CAPABILITIES: Record<string, ModelCapabilities>;
3
+ export declare function validateModelCapabilities(model: string, includeImage: boolean, includeAudio: boolean): ModelValidationResult;
4
+ export declare function getSupportedModels(requireImages?: boolean, requireAudio?: boolean): string[];
5
+ export declare function getModelInfo(model: string): ModelCapabilities | null;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getModelInfo = exports.getSupportedModels = exports.validateModelCapabilities = exports.MODEL_CAPABILITIES = void 0;
4
+ exports.MODEL_CAPABILITIES = {
5
+ 'gpt-5': {
6
+ supportsImages: true,
7
+ supportsAudio: false,
8
+ maxContextTokens: 200000,
9
+ description: 'OpenAI GPT-5 with image support via GitHub Copilot API',
10
+ },
11
+ 'gpt-5-mini': {
12
+ supportsImages: true,
13
+ supportsAudio: false,
14
+ maxContextTokens: 128000,
15
+ description: 'OpenAI GPT-5 Mini with image support via GitHub Copilot API',
16
+ },
17
+ 'gpt-4.1-copilot': {
18
+ supportsImages: true,
19
+ supportsAudio: false,
20
+ maxContextTokens: 128000,
21
+ description: 'OpenAI GPT-4.1 with image support via GitHub Copilot API',
22
+ },
23
+ 'claude-opus-4.1': {
24
+ supportsImages: false,
25
+ supportsAudio: false,
26
+ maxContextTokens: 200000,
27
+ description: 'Anthropic Claude Opus 4.1 - Text only via GitHub Copilot API',
28
+ },
29
+ 'claude-3.5-sonnet': {
30
+ supportsImages: false,
31
+ supportsAudio: false,
32
+ maxContextTokens: 200000,
33
+ description: 'Anthropic Claude 3.5 Sonnet - Text only via GitHub Copilot API',
34
+ },
35
+ 'gemini-2.5-pro': {
36
+ supportsImages: true,
37
+ supportsAudio: false,
38
+ maxContextTokens: 1000000,
39
+ description: 'Google Gemini 2.5 Pro via GitHub Copilot API',
40
+ },
41
+ 'gemini-2.0-flash': {
42
+ supportsImages: true,
43
+ supportsAudio: false,
44
+ maxContextTokens: 1000000,
45
+ description: 'Google Gemini 2.0 Flash via GitHub Copilot API',
46
+ },
47
+ 'grok-code-fast-1': {
48
+ supportsImages: false,
49
+ supportsAudio: false,
50
+ maxContextTokens: 128000,
51
+ description: 'xAI Grok Code Fast 1 - Text only via GitHub Copilot API',
52
+ },
53
+ 'o3': {
54
+ supportsImages: false,
55
+ supportsAudio: false,
56
+ maxContextTokens: 200000,
57
+ description: 'OpenAI o3 - Text only via GitHub Copilot API',
58
+ },
59
+ 'o3-mini': {
60
+ supportsImages: false,
61
+ supportsAudio: false,
62
+ maxContextTokens: 128000,
63
+ description: 'OpenAI o3-mini - Text only via GitHub Copilot API',
64
+ },
65
+ };
66
+ function validateModelCapabilities(model, includeImage, includeAudio) {
67
+ const capabilities = exports.MODEL_CAPABILITIES[model];
68
+ if (!capabilities) {
69
+ return {
70
+ isValid: false,
71
+ errorMessage: `Unknown model: ${model}. Please check if the model name is correct.`,
72
+ };
73
+ }
74
+ const warnings = [];
75
+ let isValid = true;
76
+ let errorMessage;
77
+ if (includeImage && !capabilities.supportsImages) {
78
+ isValid = false;
79
+ errorMessage = `Model ${model} does not support image input. Please disable image upload or choose a different model (e.g., GPT-5, Gemini 2.5 Pro).`;
80
+ }
81
+ if (includeAudio && !capabilities.supportsAudio) {
82
+ isValid = false;
83
+ errorMessage = `Model ${model} does not support audio input. Please disable audio upload or choose a different model (e.g., GPT-5, Gemini 2.5 Pro).`;
84
+ }
85
+ if (model.includes('claude') && (includeImage || includeAudio)) {
86
+ warnings.push('Claude models typically work best with text-only input via GitHub Copilot API.');
87
+ }
88
+ if (model.includes('grok') && (includeImage || includeAudio)) {
89
+ warnings.push('Grok models are optimized for coding tasks and work best with text input.');
90
+ }
91
+ return {
92
+ isValid,
93
+ errorMessage,
94
+ warnings: warnings.length > 0 ? warnings : undefined,
95
+ };
96
+ }
97
+ exports.validateModelCapabilities = validateModelCapabilities;
98
+ function getSupportedModels(requireImages = false, requireAudio = false) {
99
+ return Object.entries(exports.MODEL_CAPABILITIES)
100
+ .filter(([, capabilities]) => {
101
+ if (requireImages && !capabilities.supportsImages)
102
+ return false;
103
+ if (requireAudio && !capabilities.supportsAudio)
104
+ return false;
105
+ return true;
106
+ })
107
+ .map(([model]) => model);
108
+ }
109
+ exports.getSupportedModels = getSupportedModels;
110
+ function getModelInfo(model) {
111
+ return exports.MODEL_CAPABILITIES[model] || null;
112
+ }
113
+ exports.getModelInfo = getModelInfo;
@@ -9,10 +9,6 @@ export interface ChatMessageContent {
9
9
  image_url?: {
10
10
  url: string;
11
11
  };
12
- input_audio?: {
13
- data: string;
14
- format: string;
15
- };
16
12
  }
17
13
  export interface CopilotResponse {
18
14
  choices: Array<{
@@ -48,3 +44,14 @@ export interface OptimizationOptions {
48
44
  quality?: number;
49
45
  maxSizeKB?: number;
50
46
  }
47
+ export interface ModelCapabilities {
48
+ supportsImages: boolean;
49
+ supportsAudio: boolean;
50
+ maxContextTokens: number;
51
+ description: string;
52
+ }
53
+ export interface ModelValidationResult {
54
+ isValid: boolean;
55
+ errorMessage?: string;
56
+ warnings?: string[];
57
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-github-copilot",
3
- "version": "3.2.2",
3
+ "version": "3.2.3",
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",