n8n-nodes-github-copilot 3.1.0 → 3.2.1

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.
@@ -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
+ ];
@@ -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>, hasVision?: boolean): 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,130 @@
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, hasVision = false) {
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 (hasVision) {
12
+ headers['Copilot-Vision-Request'] = 'true';
13
+ }
14
+ const options = {
15
+ method: 'POST',
16
+ headers,
17
+ body: JSON.stringify(body),
18
+ };
19
+ const response = await fetch(`https://api.githubcopilot.com${endpoint}`, options);
20
+ if (!response.ok) {
21
+ const errorText = await response.text();
22
+ throw new Error(`GitHub Copilot API error: ${response.status} ${response.statusText}. ${errorText}`);
23
+ }
24
+ return await response.json();
25
+ }
26
+ exports.makeApiRequest = makeApiRequest;
27
+ async function downloadFileFromUrl(url) {
28
+ const response = await fetch(url);
29
+ if (!response.ok) {
30
+ throw new Error(`Failed to download file from URL: ${response.status} ${response.statusText}`);
31
+ }
32
+ return Buffer.from(await response.arrayBuffer());
33
+ }
34
+ exports.downloadFileFromUrl = downloadFileFromUrl;
35
+ async function getFileFromBinary(context, itemIndex, propertyName) {
36
+ const items = context.getInputData();
37
+ const item = items[itemIndex];
38
+ if (!item.binary || !item.binary[propertyName]) {
39
+ throw new Error(`No binary data found in property "${propertyName}"`);
40
+ }
41
+ const binaryData = item.binary[propertyName];
42
+ if (binaryData.data) {
43
+ return Buffer.from(binaryData.data, 'base64');
44
+ }
45
+ else if (binaryData.id) {
46
+ return await context.helpers.getBinaryDataBuffer(itemIndex, propertyName);
47
+ }
48
+ else {
49
+ throw new Error(`Invalid binary data format in property "${propertyName}"`);
50
+ }
51
+ }
52
+ exports.getFileFromBinary = getFileFromBinary;
53
+ function getImageMimeType(filename) {
54
+ const ext = filename.toLowerCase().split('.').pop();
55
+ switch (ext) {
56
+ case 'jpg':
57
+ case 'jpeg':
58
+ return 'image/jpeg';
59
+ case 'png':
60
+ return 'image/png';
61
+ case 'webp':
62
+ return 'image/webp';
63
+ case 'gif':
64
+ return 'image/gif';
65
+ default:
66
+ return 'image/jpeg';
67
+ }
68
+ }
69
+ exports.getImageMimeType = getImageMimeType;
70
+ function getAudioMimeType(filename) {
71
+ const ext = filename.toLowerCase().split('.').pop();
72
+ switch (ext) {
73
+ case 'mp3':
74
+ return 'audio/mpeg';
75
+ case 'wav':
76
+ return 'audio/wav';
77
+ case 'm4a':
78
+ return 'audio/mp4';
79
+ case 'flac':
80
+ return 'audio/flac';
81
+ case 'ogg':
82
+ return 'audio/ogg';
83
+ case 'aac':
84
+ return 'audio/aac';
85
+ default:
86
+ return 'audio/mpeg';
87
+ }
88
+ }
89
+ exports.getAudioMimeType = getAudioMimeType;
90
+ function validateFileSize(buffer, maxSizeKB = 1024) {
91
+ const sizeKB = buffer.length / 1024;
92
+ if (sizeKB > maxSizeKB) {
93
+ throw new Error(`File size ${sizeKB.toFixed(2)}KB exceeds limit of ${maxSizeKB}KB`);
94
+ }
95
+ }
96
+ exports.validateFileSize = validateFileSize;
97
+ function estimateTokens(base64String) {
98
+ return Math.ceil((base64String.length / 4 * 3) / 4);
99
+ }
100
+ exports.estimateTokens = estimateTokens;
101
+ function validateTokenLimit(estimatedTokens, maxTokens = 128000) {
102
+ if (estimatedTokens <= maxTokens) {
103
+ return { valid: true };
104
+ }
105
+ return {
106
+ valid: false,
107
+ message: `Content too large: ${estimatedTokens} tokens exceeds limit of ${maxTokens}. Consider using smaller files or text.`
108
+ };
109
+ }
110
+ exports.validateTokenLimit = validateTokenLimit;
111
+ function truncateToTokenLimit(content, maxTokens = 100000) {
112
+ const originalTokens = Math.ceil(content.length / 4);
113
+ if (originalTokens <= maxTokens) {
114
+ return {
115
+ content,
116
+ truncated: false,
117
+ originalTokens,
118
+ finalTokens: originalTokens
119
+ };
120
+ }
121
+ const targetLength = Math.floor(content.length * (maxTokens / originalTokens));
122
+ const truncatedContent = content.slice(0, targetLength) + '...[truncated]';
123
+ return {
124
+ content: truncatedContent,
125
+ truncated: true,
126
+ originalTokens,
127
+ finalTokens: Math.ceil(truncatedContent.length / 4)
128
+ };
129
+ }
130
+ 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,4 @@
1
+ export * from './types';
2
+ export * from './helpers';
3
+ export * from './audioProcessor';
4
+ export * from './imageProcessor';
@@ -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);