tpmjs/packages/package-executor/src/executor.ts

131 lines
3.1 KiB
TypeScript

/**
* Package executor client
* Calls the remote sandbox service for secure package execution
*/
import type { ExecutionResult, ExecutorOptions } from './types.js';
const DEFAULT_TIMEOUT = 10000; // 10 seconds
// Ensure URL has protocol
function getSandboxUrl(): string {
const url = process.env.SANDBOX_EXECUTOR_URL || 'http://localhost:3000';
// If URL doesn't start with http:// or https://, add https://
if (!url.startsWith('http://') && !url.startsWith('https://')) {
return `https://${url}`;
}
return url;
}
const SANDBOX_URL = getSandboxUrl();
/**
* Execute a package function with parameters via remote sandbox
*/
export async function executePackage(
packageName: string,
functionName: string,
params: Record<string, unknown>,
options: ExecutorOptions = {}
): Promise<ExecutionResult> {
const startTime = Date.now();
const timeout = options.timeout || DEFAULT_TIMEOUT;
try {
// Call the remote sandbox service
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
const response = await fetch(`${SANDBOX_URL}/execute-tool`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
packageName,
name: functionName,
version: 'latest',
params,
}),
signal: controller.signal,
});
clearTimeout(timeoutId);
const executionTimeMs = Date.now() - startTime;
if (!response.ok) {
const errorData = (await response.json().catch(() => ({ error: 'Unknown error' }))) as {
error?: string;
};
return {
success: false,
error: errorData.error || `Sandbox service error: ${response.status}`,
executionTimeMs,
};
}
const result = (await response.json()) as {
success: boolean;
output?: unknown;
error?: string;
executionTimeMs?: number;
};
return {
success: result.success,
output: result.output,
error: result.error,
executionTimeMs: result.executionTimeMs || executionTimeMs,
};
} catch (error) {
const executionTimeMs = Date.now() - startTime;
if (error instanceof Error && error.name === 'AbortError') {
return {
success: false,
error: 'Execution timeout',
executionTimeMs,
};
}
return {
success: false,
error: error instanceof Error ? error.message : String(error),
executionTimeMs,
};
}
}
/**
* Clear the package cache on the remote sandbox
*/
export async function clearCache(): Promise<void> {
try {
const response = await fetch(`${SANDBOX_URL}/cache/clear`, {
method: 'POST',
});
if (!response.ok) {
throw new Error(`Failed to clear cache: ${response.status}`);
}
} catch (error) {
console.error('Failed to clear sandbox cache:', error);
throw error;
}
}
/**
* Check if the sandbox service is healthy
*/
export async function checkHealth(): Promise<boolean> {
try {
const response = await fetch(`${SANDBOX_URL}/health`, {
method: 'GET',
});
return response.ok;
} catch {
return false;
}
}