diff --git a/packages/tools/registryExecute/src/index.ts b/packages/tools/registryExecute/src/index.ts index 3b674f7..07df2e1 100644 --- a/packages/tools/registryExecute/src/index.ts +++ b/packages/tools/registryExecute/src/index.ts @@ -49,72 +49,101 @@ export const registryExecuteTool = tool({ additionalProperties: false, }), async execute({ toolId, params, env }) { - // Parse toolId format: "package::name" - const separatorIndex = toolId.lastIndexOf('::'); - if (separatorIndex === -1) { - throw new Error(`Invalid toolId format. Expected "package::name", got "${toolId}"`); + try { + // Parse toolId format: "package::name" + const separatorIndex = toolId.lastIndexOf('::'); + if (separatorIndex === -1) { + return { + error: true, + message: `Invalid toolId format. Expected "package::name", got "${toolId}"`, + toolId, + }; + } + + const packageName = toolId.substring(0, separatorIndex); + const name = toolId.substring(separatorIndex + 2); + + if (!packageName || !name) { + return { + error: true, + message: `Invalid toolId format. Expected "package::name", got "${toolId}"`, + toolId, + }; + } + + // Fetch tool metadata to get version and importUrl + const metaParams = new URLSearchParams({ + q: name, + limit: '10', + }); + const metaResponse = await fetch(`${TPMJS_API_URL}/api/tools/search?${metaParams}`); + + if (!metaResponse.ok) { + return { + error: true, + message: `Failed to fetch tool metadata: ${metaResponse.statusText}`, + toolId, + }; + } + + // biome-ignore lint/suspicious/noExplicitAny: API response types vary + const metaData = (await metaResponse.json()) as any; + const toolsArray = metaData.results?.tools || []; + + // Find the exact tool match + // biome-ignore lint/suspicious/noExplicitAny: API response types vary + const toolMeta = toolsArray.find( + (t: any) => t.package.npmPackageName === packageName && t.name === name + ); + + if (!toolMeta) { + return { + error: true, + message: `Tool not found: ${toolId}. Try using registrySearchTool to find available tools.`, + toolId, + }; + } + + const version = toolMeta.package.npmVersion; + const importUrl = `https://esm.sh/${packageName}@${version}`; + + // Execute via sandbox executor + const response = await fetch(`${TPMJS_EXECUTOR_URL}/execute-tool`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + packageName, + name, + version, + importUrl, + params, + env: env || {}, + }), + }); + + // biome-ignore lint/suspicious/noExplicitAny: API response types vary + const result = (await response.json()) as any; + + if (!result.success) { + return { + error: true, + message: result.error || 'Tool execution failed', + toolId, + executionTimeMs: result.executionTimeMs, + }; + } + + return { + toolId, + executionTimeMs: result.executionTimeMs, + output: result.output, + }; + } catch (error) { + return { + error: true, + message: error instanceof Error ? error.message : 'Unknown execution error', + toolId, + }; } - - const packageName = toolId.substring(0, separatorIndex); - const name = toolId.substring(separatorIndex + 2); - - if (!packageName || !name) { - throw new Error(`Invalid toolId format. Expected "package::name", got "${toolId}"`); - } - - // Fetch tool metadata to get version and importUrl - const metaParams = new URLSearchParams({ - q: name, - limit: '10', - }); - const metaResponse = await fetch(`${TPMJS_API_URL}/api/tools/search?${metaParams}`); - - if (!metaResponse.ok) { - throw new Error(`Failed to fetch tool metadata: ${metaResponse.statusText}`); - } - - // biome-ignore lint/suspicious/noExplicitAny: API response types vary - const metaData = (await metaResponse.json()) as any; - const toolsArray = metaData.results?.tools || []; - - // Find the exact tool match - // biome-ignore lint/suspicious/noExplicitAny: API response types vary - const toolMeta = toolsArray.find( - (t: any) => t.package.npmPackageName === packageName && t.name === name - ); - - if (!toolMeta) { - throw new Error(`Tool not found: ${toolId}`); - } - - const version = toolMeta.package.npmVersion; - const importUrl = `https://esm.sh/${packageName}@${version}`; - - // Execute via sandbox executor - const response = await fetch(`${TPMJS_EXECUTOR_URL}/execute-tool`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - packageName, - name, - version, - importUrl, - params, - env: env || {}, - }), - }); - - // biome-ignore lint/suspicious/noExplicitAny: API response types vary - const result = (await response.json()) as any; - - if (!result.success) { - throw new Error(result.error || 'Tool execution failed'); - } - - return { - toolId, - executionTimeMs: result.executionTimeMs, - output: result.output, - }; }, }); diff --git a/packages/tools/registrySearch/src/index.ts b/packages/tools/registrySearch/src/index.ts index 1d6247e..6bfbdcb 100644 --- a/packages/tools/registrySearch/src/index.ts +++ b/packages/tools/registrySearch/src/index.ts @@ -58,45 +58,61 @@ export const registrySearchTool = tool({ additionalProperties: false, }), async execute({ query, category, limit = 5 }) { - const params = new URLSearchParams({ - q: query, - limit: String(limit), - ...(category && { category }), - }); + try { + const params = new URLSearchParams({ + q: query, + limit: String(limit), + ...(category && { category }), + }); - const url = `${TPMJS_API_URL}/api/tools/search?${params}`; - const response = await fetch(url); + const url = `${TPMJS_API_URL}/api/tools/search?${params}`; + const response = await fetch(url); - if (!response.ok) { - throw new Error(`Search failed: ${response.statusText}`); + if (!response.ok) { + return { + error: true, + message: `Search failed: ${response.statusText}`, + query, + matchCount: 0, + tools: [], + }; + } + + // biome-ignore lint/suspicious/noExplicitAny: API response types vary + const data = (await response.json()) as any; + const toolsArray = data.results?.tools || []; + + return { + query, + matchCount: toolsArray.length, + // biome-ignore lint/suspicious/noExplicitAny: Tool types from API vary + tools: toolsArray.map((t: any) => ({ + // Unique identifier for registryExecuteTool + toolId: `${t.package.npmPackageName}::${t.name}`, + + // Human-readable info + name: t.name, + package: t.package.npmPackageName, + description: t.description, + category: t.package.category, + + // Execution requirements + requiredEnvVars: + t.package.env?.filter((e: any) => e.required).map((e: any) => e.name) || [], + + // Quality indicators + healthStatus: t.executionHealth, + qualityScore: t.qualityScore, + })), + }; + } catch (error) { + return { + error: true, + message: error instanceof Error ? error.message : 'Unknown search error', + query, + matchCount: 0, + tools: [], + }; } - - // biome-ignore lint/suspicious/noExplicitAny: API response types vary - const data = (await response.json()) as any; - const toolsArray = data.results?.tools || []; - - return { - query, - matchCount: toolsArray.length, - // biome-ignore lint/suspicious/noExplicitAny: Tool types from API vary - tools: toolsArray.map((t: any) => ({ - // Unique identifier for registryExecuteTool - toolId: `${t.package.npmPackageName}::${t.name}`, - - // Human-readable info - name: t.name, - package: t.package.npmPackageName, - description: t.description, - category: t.package.category, - - // Execution requirements - requiredEnvVars: - t.package.env?.filter((e: any) => e.required).map((e: any) => e.name) || [], - - // Quality indicators - healthStatus: t.executionHealth, - qualityScore: t.qualityScore, - })), - }; }, });