n8n-nodes-github-copilot 3.1.0 → 3.2.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.
- package/dist/nodes/GitHubCopilotChatAPI/GitHubCopilotChatAPI.node.backup.d.ts +5 -0
- package/dist/nodes/GitHubCopilotChatAPI/GitHubCopilotChatAPI.node.backup.js +651 -0
- package/dist/nodes/GitHubCopilotChatAPI/GitHubCopilotChatAPI.node.js +263 -412
- package/dist/nodes/GitHubCopilotChatAPI/utils/audioProcessor.d.ts +11 -0
- package/dist/nodes/GitHubCopilotChatAPI/utils/audioProcessor.js +86 -0
- package/dist/nodes/GitHubCopilotChatAPI/utils/helpers.d.ts +21 -0
- package/dist/nodes/GitHubCopilotChatAPI/utils/helpers.js +126 -0
- package/dist/nodes/GitHubCopilotChatAPI/utils/imageProcessor.d.ts +8 -0
- package/dist/nodes/GitHubCopilotChatAPI/utils/imageProcessor.js +101 -0
- package/dist/nodes/GitHubCopilotChatAPI/utils/index.d.ts +4 -0
- package/dist/nodes/GitHubCopilotChatAPI/utils/index.js +20 -0
- package/dist/nodes/GitHubCopilotChatAPI/utils/types.d.ts +45 -0
- package/dist/nodes/GitHubCopilotChatAPI/utils/types.js +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IExecuteFunctions } from 'n8n-workflow';
|
|
2
|
+
import { ProcessedFileResult } from './types';
|
|
3
|
+
export declare function processAudioFile(context: IExecuteFunctions, itemIndex: number, audioSource: string, audioFile?: string, audioUrl?: string, audioProperty?: string): Promise<ProcessedFileResult>;
|
|
4
|
+
export declare function chunkAudioData(base64Data: string, maxChunkSize?: number): string[];
|
|
5
|
+
export declare function optimizeAudioForTokens(base64Data: string, maxTokens?: number): {
|
|
6
|
+
data: string;
|
|
7
|
+
truncated: boolean;
|
|
8
|
+
originalTokens: number;
|
|
9
|
+
finalTokens: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function createAudioSummary(filename: string, size: number, duration?: number): string;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAudioSummary = exports.optimizeAudioForTokens = exports.chunkAudioData = exports.processAudioFile = void 0;
|
|
4
|
+
const helpers_1 = require("./helpers");
|
|
5
|
+
async function processAudioFile(context, itemIndex, audioSource, audioFile, audioUrl, audioProperty) {
|
|
6
|
+
var _a, _b;
|
|
7
|
+
let audioBuffer;
|
|
8
|
+
let filename;
|
|
9
|
+
switch (audioSource) {
|
|
10
|
+
case 'file':
|
|
11
|
+
if (!audioFile) {
|
|
12
|
+
throw new Error('Audio file content is required when source is "file"');
|
|
13
|
+
}
|
|
14
|
+
audioBuffer = Buffer.from(audioFile, 'base64');
|
|
15
|
+
filename = 'uploaded_audio.mp3';
|
|
16
|
+
break;
|
|
17
|
+
case 'url':
|
|
18
|
+
if (!audioUrl) {
|
|
19
|
+
throw new Error('Audio URL is required when source is "url"');
|
|
20
|
+
}
|
|
21
|
+
audioBuffer = await (0, helpers_1.downloadFileFromUrl)(audioUrl);
|
|
22
|
+
filename = audioUrl.split('/').pop() || 'downloaded_audio.mp3';
|
|
23
|
+
break;
|
|
24
|
+
case 'binary':
|
|
25
|
+
if (!audioProperty) {
|
|
26
|
+
throw new Error('Audio property name is required when source is "binary"');
|
|
27
|
+
}
|
|
28
|
+
audioBuffer = await (0, helpers_1.getFileFromBinary)(context, itemIndex, audioProperty);
|
|
29
|
+
const items = context.getInputData();
|
|
30
|
+
const item = items[itemIndex];
|
|
31
|
+
filename = ((_b = (_a = item.binary) === null || _a === void 0 ? void 0 : _a[audioProperty]) === null || _b === void 0 ? void 0 : _b.fileName) || 'binary_audio.mp3';
|
|
32
|
+
break;
|
|
33
|
+
default:
|
|
34
|
+
throw new Error(`Invalid audio source: ${audioSource}`);
|
|
35
|
+
}
|
|
36
|
+
(0, helpers_1.validateFileSize)(audioBuffer, 25600);
|
|
37
|
+
const base64Audio = audioBuffer.toString('base64');
|
|
38
|
+
const estimatedTokens = (0, helpers_1.estimateTokens)(base64Audio);
|
|
39
|
+
if (estimatedTokens > 100000) {
|
|
40
|
+
throw new Error(`Audio file too large (${estimatedTokens} estimated tokens). Consider using a smaller file.`);
|
|
41
|
+
}
|
|
42
|
+
const mimeType = (0, helpers_1.getAudioMimeType)(filename);
|
|
43
|
+
return {
|
|
44
|
+
data: base64Audio,
|
|
45
|
+
mimeType,
|
|
46
|
+
filename,
|
|
47
|
+
size: audioBuffer.length,
|
|
48
|
+
estimatedTokens
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
exports.processAudioFile = processAudioFile;
|
|
52
|
+
function chunkAudioData(base64Data, maxChunkSize = 50000) {
|
|
53
|
+
const chunks = [];
|
|
54
|
+
for (let i = 0; i < base64Data.length; i += maxChunkSize) {
|
|
55
|
+
chunks.push(base64Data.slice(i, i + maxChunkSize));
|
|
56
|
+
}
|
|
57
|
+
return chunks;
|
|
58
|
+
}
|
|
59
|
+
exports.chunkAudioData = chunkAudioData;
|
|
60
|
+
function optimizeAudioForTokens(base64Data, maxTokens = 100000) {
|
|
61
|
+
const originalTokens = (0, helpers_1.estimateTokens)(base64Data);
|
|
62
|
+
if (originalTokens <= maxTokens) {
|
|
63
|
+
return {
|
|
64
|
+
data: base64Data,
|
|
65
|
+
truncated: false,
|
|
66
|
+
originalTokens,
|
|
67
|
+
finalTokens: originalTokens
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const compressionRatio = maxTokens / originalTokens;
|
|
71
|
+
const targetLength = Math.floor(base64Data.length * compressionRatio);
|
|
72
|
+
const compressedData = base64Data.slice(0, Math.max(targetLength, 1000));
|
|
73
|
+
return {
|
|
74
|
+
data: compressedData,
|
|
75
|
+
truncated: true,
|
|
76
|
+
originalTokens,
|
|
77
|
+
finalTokens: (0, helpers_1.estimateTokens)(compressedData)
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
exports.optimizeAudioForTokens = optimizeAudioForTokens;
|
|
81
|
+
function createAudioSummary(filename, size, duration) {
|
|
82
|
+
const sizeKB = Math.round(size / 1024);
|
|
83
|
+
const durationText = duration ? ` (${Math.round(duration)}s)` : '';
|
|
84
|
+
return `Audio file: ${filename} - ${sizeKB}KB${durationText}. File too large for direct processing, providing description instead.`;
|
|
85
|
+
}
|
|
86
|
+
exports.createAudioSummary = createAudioSummary;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { IExecuteFunctions } from 'n8n-workflow';
|
|
4
|
+
import { CopilotResponse } from './types';
|
|
5
|
+
export declare function makeApiRequest(context: IExecuteFunctions, endpoint: string, body: Record<string, unknown>): Promise<CopilotResponse>;
|
|
6
|
+
export declare function downloadFileFromUrl(url: string): Promise<Buffer>;
|
|
7
|
+
export declare function getFileFromBinary(context: IExecuteFunctions, itemIndex: number, propertyName: string): Promise<Buffer>;
|
|
8
|
+
export declare function getImageMimeType(filename: string): string;
|
|
9
|
+
export declare function getAudioMimeType(filename: string): string;
|
|
10
|
+
export declare function validateFileSize(buffer: Buffer, maxSizeKB?: number): void;
|
|
11
|
+
export declare function estimateTokens(base64String: string): number;
|
|
12
|
+
export declare function validateTokenLimit(estimatedTokens: number, maxTokens?: number): {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
message?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function truncateToTokenLimit(content: string, maxTokens?: number): {
|
|
17
|
+
content: string;
|
|
18
|
+
truncated: boolean;
|
|
19
|
+
originalTokens: number;
|
|
20
|
+
finalTokens: number;
|
|
21
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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) {
|
|
5
|
+
const credentials = await context.getCredentials('githubApi');
|
|
6
|
+
const options = {
|
|
7
|
+
method: 'POST',
|
|
8
|
+
headers: {
|
|
9
|
+
'Authorization': `Bearer ${credentials.accessToken}`,
|
|
10
|
+
'Content-Type': 'application/json',
|
|
11
|
+
'User-Agent': 'n8n-github-copilot-chat-api-node',
|
|
12
|
+
},
|
|
13
|
+
body: JSON.stringify(body),
|
|
14
|
+
};
|
|
15
|
+
const response = await fetch(`https://api.githubcopilot.com${endpoint}`, options);
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
const errorText = await response.text();
|
|
18
|
+
throw new Error(`GitHub Copilot API error: ${response.status} ${response.statusText}. ${errorText}`);
|
|
19
|
+
}
|
|
20
|
+
return await response.json();
|
|
21
|
+
}
|
|
22
|
+
exports.makeApiRequest = makeApiRequest;
|
|
23
|
+
async function downloadFileFromUrl(url) {
|
|
24
|
+
const response = await fetch(url);
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
throw new Error(`Failed to download file from URL: ${response.status} ${response.statusText}`);
|
|
27
|
+
}
|
|
28
|
+
return Buffer.from(await response.arrayBuffer());
|
|
29
|
+
}
|
|
30
|
+
exports.downloadFileFromUrl = downloadFileFromUrl;
|
|
31
|
+
async function getFileFromBinary(context, itemIndex, propertyName) {
|
|
32
|
+
const items = context.getInputData();
|
|
33
|
+
const item = items[itemIndex];
|
|
34
|
+
if (!item.binary || !item.binary[propertyName]) {
|
|
35
|
+
throw new Error(`No binary data found in property "${propertyName}"`);
|
|
36
|
+
}
|
|
37
|
+
const binaryData = item.binary[propertyName];
|
|
38
|
+
if (binaryData.data) {
|
|
39
|
+
return Buffer.from(binaryData.data, 'base64');
|
|
40
|
+
}
|
|
41
|
+
else if (binaryData.id) {
|
|
42
|
+
return await context.helpers.getBinaryDataBuffer(itemIndex, propertyName);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
throw new Error(`Invalid binary data format in property "${propertyName}"`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.getFileFromBinary = getFileFromBinary;
|
|
49
|
+
function getImageMimeType(filename) {
|
|
50
|
+
const ext = filename.toLowerCase().split('.').pop();
|
|
51
|
+
switch (ext) {
|
|
52
|
+
case 'jpg':
|
|
53
|
+
case 'jpeg':
|
|
54
|
+
return 'image/jpeg';
|
|
55
|
+
case 'png':
|
|
56
|
+
return 'image/png';
|
|
57
|
+
case 'webp':
|
|
58
|
+
return 'image/webp';
|
|
59
|
+
case 'gif':
|
|
60
|
+
return 'image/gif';
|
|
61
|
+
default:
|
|
62
|
+
return 'image/jpeg';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.getImageMimeType = getImageMimeType;
|
|
66
|
+
function getAudioMimeType(filename) {
|
|
67
|
+
const ext = filename.toLowerCase().split('.').pop();
|
|
68
|
+
switch (ext) {
|
|
69
|
+
case 'mp3':
|
|
70
|
+
return 'audio/mpeg';
|
|
71
|
+
case 'wav':
|
|
72
|
+
return 'audio/wav';
|
|
73
|
+
case 'm4a':
|
|
74
|
+
return 'audio/mp4';
|
|
75
|
+
case 'flac':
|
|
76
|
+
return 'audio/flac';
|
|
77
|
+
case 'ogg':
|
|
78
|
+
return 'audio/ogg';
|
|
79
|
+
case 'aac':
|
|
80
|
+
return 'audio/aac';
|
|
81
|
+
default:
|
|
82
|
+
return 'audio/mpeg';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.getAudioMimeType = getAudioMimeType;
|
|
86
|
+
function validateFileSize(buffer, maxSizeKB = 1024) {
|
|
87
|
+
const sizeKB = buffer.length / 1024;
|
|
88
|
+
if (sizeKB > maxSizeKB) {
|
|
89
|
+
throw new Error(`File size ${sizeKB.toFixed(2)}KB exceeds limit of ${maxSizeKB}KB`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.validateFileSize = validateFileSize;
|
|
93
|
+
function estimateTokens(base64String) {
|
|
94
|
+
return Math.ceil((base64String.length / 4 * 3) / 4);
|
|
95
|
+
}
|
|
96
|
+
exports.estimateTokens = estimateTokens;
|
|
97
|
+
function validateTokenLimit(estimatedTokens, maxTokens = 128000) {
|
|
98
|
+
if (estimatedTokens <= maxTokens) {
|
|
99
|
+
return { valid: true };
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
valid: false,
|
|
103
|
+
message: `Content too large: ${estimatedTokens} tokens exceeds limit of ${maxTokens}. Consider using smaller files or text.`
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
exports.validateTokenLimit = validateTokenLimit;
|
|
107
|
+
function truncateToTokenLimit(content, maxTokens = 100000) {
|
|
108
|
+
const originalTokens = Math.ceil(content.length / 4);
|
|
109
|
+
if (originalTokens <= maxTokens) {
|
|
110
|
+
return {
|
|
111
|
+
content,
|
|
112
|
+
truncated: false,
|
|
113
|
+
originalTokens,
|
|
114
|
+
finalTokens: originalTokens
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const targetLength = Math.floor(content.length * (maxTokens / originalTokens));
|
|
118
|
+
const truncatedContent = content.slice(0, targetLength) + '...[truncated]';
|
|
119
|
+
return {
|
|
120
|
+
content: truncatedContent,
|
|
121
|
+
truncated: true,
|
|
122
|
+
originalTokens,
|
|
123
|
+
finalTokens: Math.ceil(truncatedContent.length / 4)
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
exports.truncateToTokenLimit = truncateToTokenLimit;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IExecuteFunctions } from 'n8n-workflow';
|
|
2
|
+
import { ProcessedFileResult, OptimizationOptions } from './types';
|
|
3
|
+
export declare function processImageFile(context: IExecuteFunctions, itemIndex: number, imageSource: string, imageFile?: string, imageUrl?: string, imageProperty?: string, optimization?: OptimizationOptions): Promise<ProcessedFileResult>;
|
|
4
|
+
export declare function compressImageToTokenLimit(base64Data: string, maxTokens?: number): string;
|
|
5
|
+
export declare function resizeImageDimensions(originalWidth: number, originalHeight: number, maxWidth?: number, maxHeight?: number): {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resizeImageDimensions = exports.compressImageToTokenLimit = exports.processImageFile = void 0;
|
|
4
|
+
const helpers_1 = require("./helpers");
|
|
5
|
+
async function processImageFile(context, itemIndex, imageSource, imageFile, imageUrl, imageProperty, optimization) {
|
|
6
|
+
var _a, _b;
|
|
7
|
+
let imageBuffer;
|
|
8
|
+
let filename;
|
|
9
|
+
switch (imageSource) {
|
|
10
|
+
case 'file':
|
|
11
|
+
if (!imageFile) {
|
|
12
|
+
throw new Error('Image file content is required when source is "file"');
|
|
13
|
+
}
|
|
14
|
+
imageBuffer = Buffer.from(imageFile, 'base64');
|
|
15
|
+
filename = 'uploaded_image.jpg';
|
|
16
|
+
break;
|
|
17
|
+
case 'url':
|
|
18
|
+
if (!imageUrl) {
|
|
19
|
+
throw new Error('Image URL is required when source is "url"');
|
|
20
|
+
}
|
|
21
|
+
imageBuffer = await (0, helpers_1.downloadFileFromUrl)(imageUrl);
|
|
22
|
+
filename = imageUrl.split('/').pop() || 'downloaded_image.jpg';
|
|
23
|
+
break;
|
|
24
|
+
case 'binary':
|
|
25
|
+
if (!imageProperty) {
|
|
26
|
+
throw new Error('Image property name is required when source is "binary"');
|
|
27
|
+
}
|
|
28
|
+
imageBuffer = await (0, helpers_1.getFileFromBinary)(context, itemIndex, imageProperty);
|
|
29
|
+
const items = context.getInputData();
|
|
30
|
+
const item = items[itemIndex];
|
|
31
|
+
filename = ((_b = (_a = item.binary) === null || _a === void 0 ? void 0 : _a[imageProperty]) === null || _b === void 0 ? void 0 : _b.fileName) || 'binary_image.jpg';
|
|
32
|
+
break;
|
|
33
|
+
default:
|
|
34
|
+
throw new Error(`Invalid image source: ${imageSource}`);
|
|
35
|
+
}
|
|
36
|
+
if (optimization) {
|
|
37
|
+
imageBuffer = await optimizeImage(imageBuffer, optimization);
|
|
38
|
+
}
|
|
39
|
+
(0, helpers_1.validateFileSize)(imageBuffer, 20480);
|
|
40
|
+
const base64Image = imageBuffer.toString('base64');
|
|
41
|
+
const estimatedTokens = (0, helpers_1.estimateTokens)(base64Image);
|
|
42
|
+
if (estimatedTokens > 50000) {
|
|
43
|
+
const compressedBuffer = await optimizeImage(imageBuffer, {
|
|
44
|
+
quality: 70,
|
|
45
|
+
maxSizeKB: (optimization === null || optimization === void 0 ? void 0 : optimization.maxSizeKB) || 1024
|
|
46
|
+
});
|
|
47
|
+
const compressedBase64 = compressedBuffer.toString('base64');
|
|
48
|
+
const compressedTokens = (0, helpers_1.estimateTokens)(compressedBase64);
|
|
49
|
+
if (compressedTokens < estimatedTokens) {
|
|
50
|
+
return {
|
|
51
|
+
data: compressedBase64,
|
|
52
|
+
mimeType: (0, helpers_1.getImageMimeType)(filename),
|
|
53
|
+
filename,
|
|
54
|
+
size: compressedBuffer.length,
|
|
55
|
+
estimatedTokens: compressedTokens
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const mimeType = (0, helpers_1.getImageMimeType)(filename);
|
|
60
|
+
return {
|
|
61
|
+
data: base64Image,
|
|
62
|
+
mimeType,
|
|
63
|
+
filename,
|
|
64
|
+
size: imageBuffer.length,
|
|
65
|
+
estimatedTokens
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
exports.processImageFile = processImageFile;
|
|
69
|
+
async function optimizeImage(buffer, options) {
|
|
70
|
+
if (options.maxSizeKB && buffer.length / 1024 > options.maxSizeKB) {
|
|
71
|
+
const compressionRatio = Math.min(0.8, options.maxSizeKB / (buffer.length / 1024));
|
|
72
|
+
const targetSize = Math.floor(buffer.length * compressionRatio);
|
|
73
|
+
if (targetSize < buffer.length) {
|
|
74
|
+
return buffer.slice(0, Math.max(targetSize, 1024));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return buffer;
|
|
78
|
+
}
|
|
79
|
+
function compressImageToTokenLimit(base64Data, maxTokens = 50000) {
|
|
80
|
+
const estimatedTokens = (0, helpers_1.estimateTokens)(base64Data);
|
|
81
|
+
if (estimatedTokens <= maxTokens) {
|
|
82
|
+
return base64Data;
|
|
83
|
+
}
|
|
84
|
+
const compressionRatio = maxTokens / estimatedTokens;
|
|
85
|
+
const targetLength = Math.floor(base64Data.length * compressionRatio);
|
|
86
|
+
return base64Data.slice(0, Math.max(targetLength, 1000));
|
|
87
|
+
}
|
|
88
|
+
exports.compressImageToTokenLimit = compressImageToTokenLimit;
|
|
89
|
+
function resizeImageDimensions(originalWidth, originalHeight, maxWidth = 1024, maxHeight = 1024) {
|
|
90
|
+
let { width, height } = { width: originalWidth, height: originalHeight };
|
|
91
|
+
if (width > maxWidth) {
|
|
92
|
+
height = (height * maxWidth) / width;
|
|
93
|
+
width = maxWidth;
|
|
94
|
+
}
|
|
95
|
+
if (height > maxHeight) {
|
|
96
|
+
width = (width * maxHeight) / height;
|
|
97
|
+
height = maxHeight;
|
|
98
|
+
}
|
|
99
|
+
return { width: Math.round(width), height: Math.round(height) };
|
|
100
|
+
}
|
|
101
|
+
exports.resizeImageDimensions = resizeImageDimensions;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types"), exports);
|
|
18
|
+
__exportStar(require("./helpers"), exports);
|
|
19
|
+
__exportStar(require("./audioProcessor"), exports);
|
|
20
|
+
__exportStar(require("./imageProcessor"), exports);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { IExecuteFunctions } from 'n8n-workflow';
|
|
2
|
+
export interface ChatMessage {
|
|
3
|
+
role: 'system' | 'user' | 'assistant';
|
|
4
|
+
content: string | Array<{
|
|
5
|
+
type: string;
|
|
6
|
+
text?: string;
|
|
7
|
+
image_url?: {
|
|
8
|
+
url: string;
|
|
9
|
+
};
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
export interface CopilotResponse {
|
|
13
|
+
choices: Array<{
|
|
14
|
+
message: {
|
|
15
|
+
content: string;
|
|
16
|
+
};
|
|
17
|
+
finish_reason: string;
|
|
18
|
+
}>;
|
|
19
|
+
usage?: {
|
|
20
|
+
prompt_tokens: number;
|
|
21
|
+
completion_tokens: number;
|
|
22
|
+
total_tokens: number;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface FileProcessOptions {
|
|
26
|
+
context: IExecuteFunctions;
|
|
27
|
+
itemIndex: number;
|
|
28
|
+
source: 'manual' | 'url' | 'binary';
|
|
29
|
+
filePath?: string;
|
|
30
|
+
url?: string;
|
|
31
|
+
binaryProperty?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ProcessedFileResult {
|
|
34
|
+
data: string;
|
|
35
|
+
mimeType: string;
|
|
36
|
+
filename: string;
|
|
37
|
+
size: number;
|
|
38
|
+
estimatedTokens: number;
|
|
39
|
+
}
|
|
40
|
+
export interface OptimizationOptions {
|
|
41
|
+
maxWidth?: number;
|
|
42
|
+
maxHeight?: number;
|
|
43
|
+
quality?: number;
|
|
44
|
+
maxSizeKB?: number;
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-github-copilot",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
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",
|