mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-03-04 02:20:19 +01:00
Redesgin ToolOperationConfig so types are known for single/multiple/custom tools (#4221)
# Description of Changes Redesigns `ToolOperationConfig` so that the types of the functions are always known depending on whether the tool runs on single files, multiple files, or uses custom behaviour
This commit is contained in:
@@ -4,14 +4,15 @@ import { AutomationConfig, AutomationExecutionCallbacks } from '../types/automat
|
||||
import { AUTOMATION_CONSTANTS } from '../constants/automation';
|
||||
import { AutomationFileProcessor } from './automationFileProcessor';
|
||||
import { ResourceManager } from './resourceManager';
|
||||
import { ToolType } from '../hooks/tools/shared/useToolOperation';
|
||||
|
||||
|
||||
/**
|
||||
* Execute a tool operation directly without using React hooks
|
||||
*/
|
||||
export const executeToolOperation = async (
|
||||
operationName: string,
|
||||
parameters: any,
|
||||
operationName: string,
|
||||
parameters: any,
|
||||
files: File[],
|
||||
toolRegistry: ToolRegistry
|
||||
): Promise<File[]> => {
|
||||
@@ -22,14 +23,14 @@ export const executeToolOperation = async (
|
||||
* Execute a tool operation with custom prefix
|
||||
*/
|
||||
export const executeToolOperationWithPrefix = async (
|
||||
operationName: string,
|
||||
parameters: any,
|
||||
operationName: string,
|
||||
parameters: any,
|
||||
files: File[],
|
||||
toolRegistry: ToolRegistry,
|
||||
filePrefix: string = AUTOMATION_CONSTANTS.FILE_PREFIX
|
||||
): Promise<File[]> => {
|
||||
console.log(`🔧 Executing tool: ${operationName}`, { parameters, fileCount: files.length });
|
||||
|
||||
|
||||
const config = toolRegistry[operationName]?.operationConfig;
|
||||
if (!config) {
|
||||
console.error(`❌ Tool operation not supported: ${operationName}`);
|
||||
@@ -47,17 +48,17 @@ export const executeToolOperationWithPrefix = async (
|
||||
return resultFiles;
|
||||
}
|
||||
|
||||
if (config.multiFileEndpoint) {
|
||||
if (config.toolType === ToolType.multiFile) {
|
||||
// Multi-file processing - single API call with all files
|
||||
const endpoint = typeof config.endpoint === 'function'
|
||||
? config.endpoint(parameters)
|
||||
const endpoint = typeof config.endpoint === 'function'
|
||||
? config.endpoint(parameters)
|
||||
: config.endpoint;
|
||||
|
||||
|
||||
console.log(`🌐 Making multi-file request to: ${endpoint}`);
|
||||
const formData = (config.buildFormData as (params: any, files: File[]) => FormData)(parameters, files);
|
||||
console.log(`📤 FormData entries:`, Array.from(formData.entries()));
|
||||
|
||||
const response = await axios.post(endpoint, formData, {
|
||||
|
||||
const response = await axios.post(endpoint, formData, {
|
||||
responseType: 'blob',
|
||||
timeout: AUTOMATION_CONSTANTS.OPERATION_TIMEOUT
|
||||
});
|
||||
@@ -66,7 +67,7 @@ export const executeToolOperationWithPrefix = async (
|
||||
|
||||
// Multi-file responses are typically ZIP files, but may be single files (e.g. split with merge=true)
|
||||
let result;
|
||||
if (response.data.type === 'application/pdf' ||
|
||||
if (response.data.type === 'application/pdf' ||
|
||||
(response.headers && response.headers['content-type'] === 'application/pdf')) {
|
||||
// Single PDF response (e.g. split with merge option) - use original filename
|
||||
const originalFileName = files[0]?.name || 'document.pdf';
|
||||
@@ -80,19 +81,18 @@ export const executeToolOperationWithPrefix = async (
|
||||
// ZIP response
|
||||
result = await AutomationFileProcessor.extractAutomationZipFiles(response.data);
|
||||
}
|
||||
|
||||
|
||||
if (result.errors.length > 0) {
|
||||
console.warn(`⚠️ File processing warnings:`, result.errors);
|
||||
}
|
||||
|
||||
// Apply prefix to files, replacing any existing prefix
|
||||
const processedFiles = filePrefix
|
||||
const processedFiles = filePrefix
|
||||
? result.files.map(file => {
|
||||
const nameWithoutPrefix = file.name.replace(/^[^_]*_/, '');
|
||||
return new File([file], `${filePrefix}${nameWithoutPrefix}`, { type: file.type });
|
||||
})
|
||||
: result.files;
|
||||
|
||||
|
||||
console.log(`📁 Processed ${processedFiles.length} files from response`);
|
||||
return processedFiles;
|
||||
|
||||
@@ -100,18 +100,18 @@ export const executeToolOperationWithPrefix = async (
|
||||
// Single-file processing - separate API call per file
|
||||
console.log(`🔄 Processing ${files.length} files individually`);
|
||||
const resultFiles: File[] = [];
|
||||
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
const endpoint = typeof config.endpoint === 'function'
|
||||
? config.endpoint(parameters)
|
||||
const endpoint = typeof config.endpoint === 'function'
|
||||
? config.endpoint(parameters)
|
||||
: config.endpoint;
|
||||
|
||||
|
||||
console.log(`🌐 Making single-file request ${i+1}/${files.length} to: ${endpoint} for file: ${file.name}`);
|
||||
const formData = (config.buildFormData as (params: any, file: File) => FormData)(parameters, file);
|
||||
console.log(`📤 FormData entries:`, Array.from(formData.entries()));
|
||||
|
||||
const response = await axios.post(endpoint, formData, {
|
||||
|
||||
const response = await axios.post(endpoint, formData, {
|
||||
responseType: 'blob',
|
||||
timeout: AUTOMATION_CONSTANTS.OPERATION_TIMEOUT
|
||||
});
|
||||
@@ -119,9 +119,9 @@ export const executeToolOperationWithPrefix = async (
|
||||
console.log(`📥 Response ${i+1} status: ${response.status}, size: ${response.data.size} bytes`);
|
||||
|
||||
// Create result file with automation prefix
|
||||
|
||||
|
||||
const resultFile = ResourceManager.createResultFile(
|
||||
response.data,
|
||||
response.data,
|
||||
file.name,
|
||||
filePrefix
|
||||
);
|
||||
@@ -143,7 +143,7 @@ export const executeToolOperationWithPrefix = async (
|
||||
* Execute an entire automation sequence
|
||||
*/
|
||||
export const executeAutomationSequence = async (
|
||||
automation: any,
|
||||
automation: any,
|
||||
initialFiles: File[],
|
||||
toolRegistry: ToolRegistry,
|
||||
onStepStart?: (stepIndex: number, operationName: string) => void,
|
||||
@@ -153,7 +153,7 @@ export const executeAutomationSequence = async (
|
||||
console.log(`🚀 Starting automation sequence: ${automation.name || 'Unnamed'}`);
|
||||
console.log(`📁 Initial files: ${initialFiles.length}`);
|
||||
console.log(`🔧 Operations: ${automation.operations?.length || 0}`);
|
||||
|
||||
|
||||
if (!automation?.operations || automation.operations.length === 0) {
|
||||
throw new Error('No operations in automation');
|
||||
}
|
||||
@@ -163,26 +163,26 @@ export const executeAutomationSequence = async (
|
||||
|
||||
for (let i = 0; i < automation.operations.length; i++) {
|
||||
const operation = automation.operations[i];
|
||||
|
||||
|
||||
console.log(`📋 Step ${i + 1}/${automation.operations.length}: ${operation.operation}`);
|
||||
console.log(`📄 Input files: ${currentFiles.length}`);
|
||||
console.log(`⚙️ Parameters:`, operation.parameters || {});
|
||||
|
||||
|
||||
try {
|
||||
onStepStart?.(i, operation.operation);
|
||||
|
||||
|
||||
const resultFiles = await executeToolOperationWithPrefix(
|
||||
operation.operation,
|
||||
operation.parameters || {},
|
||||
operation.operation,
|
||||
operation.parameters || {},
|
||||
currentFiles,
|
||||
toolRegistry,
|
||||
i === automation.operations.length - 1 ? automationPrefix : '' // Only add prefix to final step
|
||||
);
|
||||
|
||||
|
||||
console.log(`✅ Step ${i + 1} completed: ${resultFiles.length} result files`);
|
||||
currentFiles = resultFiles;
|
||||
onStepComplete?.(i, resultFiles);
|
||||
|
||||
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Step ${i + 1} failed:`, error);
|
||||
onStepError?.(i, error.message);
|
||||
@@ -192,4 +192,4 @@ export const executeAutomationSequence = async (
|
||||
|
||||
console.log(`🎉 Automation sequence completed: ${currentFiles.length} final files`);
|
||||
return currentFiles;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user