diff --git a/apps/playground/src/lib/dynamic-tool-loader.ts b/apps/playground/src/lib/dynamic-tool-loader.ts index 14f7c4b..4327361 100644 --- a/apps/playground/src/lib/dynamic-tool-loader.ts +++ b/apps/playground/src/lib/dynamic-tool-loader.ts @@ -37,41 +37,6 @@ function getConversationEnv(conversationId: string): Record { return conversationEnv.get(conversationId) || {}; } -// Web app API URL for health status updates -const TPMJS_API_URL = process.env.TPMJS_API_URL || 'https://tpmjs.com'; - -/** - * Report tool execution result to centralized health service - * Non-blocking - calls web app API which has all the health logic - */ -async function reportToolResult( - packageName: string, - exportName: string, - success: boolean, - error?: string -): Promise { - try { - // Call the web app's centralized health report endpoint - const response = await fetch(`${TPMJS_API_URL}/api/tools/report-health`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - packageName, - exportName, - success, - error, - }), - }); - - if (!response.ok) { - console.warn(`⚠️ Failed to report health status: ${response.status}`); - } - } catch (err) { - // Non-blocking - just log the error - console.error('❌ Failed to report tool result:', err); - } -} - /** * Dynamically load a tool via Railway service * Railway service runs with --experimental-network-imports and can import from esm.sh @@ -126,15 +91,6 @@ export async function loadToolDynamically( if (!response.ok) { const errorText = await response.text(); console.error(`❌ Railway service error (${response.status}): ${errorText}`); - - // Report failure to centralized health service (non-blocking) - reportToolResult( - packageName, - exportName, - false, - `Railway service error (${response.status}): ${errorText}` - ); - return null; } @@ -143,10 +99,6 @@ export async function loadToolDynamically( if (!data || !data.success) { const errorMsg = data?.error || 'Unknown error'; console.error(`❌ Failed to load tool: ${errorMsg}`); - - // Report failure to centralized health service (non-blocking) - reportToolResult(packageName, exportName, false, errorMsg); - return null; } } catch (fetchError) { @@ -154,14 +106,6 @@ export async function loadToolDynamically( if (fetchError instanceof Error && fetchError.name === 'AbortError') { console.error(`❌ Railway request timeout after 120s for ${packageName}/${exportName}`); - - reportToolResult( - packageName, - exportName, - false, - 'Railway service timeout (120s) - tool dependencies may be too large' - ); - return null; } @@ -212,18 +156,11 @@ export async function loadToolDynamically( if (!result.success) { console.error(`❌ Tool execution failed: ${result.error}`); - - // Report failure to centralized health service (non-blocking) - reportToolResult(packageName, exportName, false, result.error || 'Tool execution failed'); - throw new Error(result.error || 'Tool execution failed'); } + // Health status is reported by the Railway executor console.log(`✅ Tool executed successfully in ${result.executionTimeMs}ms`); - - // Report success to centralized health service (non-blocking) - reportToolResult(packageName, exportName, true); - return result.output; }, }); diff --git a/apps/railway-executor/server.ts b/apps/railway-executor/server.ts index b2ee2e3..e554638 100644 --- a/apps/railway-executor/server.ts +++ b/apps/railway-executor/server.ts @@ -10,6 +10,44 @@ import { zodToJsonSchema } from 'https://esm.sh/zod-to-json-schema@3.25.0'; // biome-ignore lint/suspicious/noExplicitAny: Tool types are dynamic and vary by package const moduleCache = new Map(); +// Web app API URL for health status reporting +const TPMJS_API_URL = Deno.env.get('TPMJS_API_URL') || 'https://tpmjs.com'; + +/** + * Report tool execution result to centralized health service + * Non-blocking - fires and forgets to avoid slowing down execution + */ +async function reportToolHealth( + packageName: string, + exportName: string, + success: boolean, + error?: string +): Promise { + try { + const response = await fetch(`${TPMJS_API_URL}/api/tools/report-health`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + packageName, + exportName, + success, + error, + }), + }); + + if (response.ok) { + console.log( + `📊 Health reported for ${packageName}/${exportName}: ${success ? 'SUCCESS' : 'FAILURE'}` + ); + } else { + console.warn(`⚠️ Failed to report health: ${response.status}`); + } + } catch (err) { + // Non-blocking - just log + console.error('❌ Failed to report tool health:', err); + } +} + /** * Sanitize JSON Schema to fix common issues * - Replaces invalid type "None" with "object" @@ -546,15 +584,21 @@ async function executeTool(req: Request): Promise { const executionTimeMs = Date.now() - startTime; console.log(`✅ Execution complete in ${executionTimeMs}ms`); + // Report successful execution to health service (non-blocking) + reportToolHealth(packageName, exportName, true).catch(() => {}); + return Response.json({ success: true, output: result, executionTimeMs, }); } catch (error) { - const executionTimeMs = Date.now() - Date.now(); + const executionTimeMs = Date.now() - startTime; console.error('❌ Tool execution failed:', error); + // Report failed execution to health service (non-blocking) + reportToolHealth(packageName, exportName, false, error.message).catch(() => {}); + return Response.json( { success: false,