diff --git a/apps/sim/tools/daytona/sandbox_path_safety.test.ts b/apps/sim/tools/daytona/sandbox_path_safety.test.ts index 0baf7d7d714..ca92eea3c61 100644 --- a/apps/sim/tools/daytona/sandbox_path_safety.test.ts +++ b/apps/sim/tools/daytona/sandbox_path_safety.test.ts @@ -16,7 +16,7 @@ import { describe, expect, it } from 'vitest' import * as daytonaTools from '@/tools/daytona/index' import { daytonaToolboxUrl, encodeSandboxId } from '@/tools/daytona/utils' -import type { ToolConfig } from '@/tools/types' +import type { ToolConfig, ToolResponse } from '@/tools/types' const TOOLBOX_PREFIX = '/toolbox/' const API_PREFIX = '/api/sandbox/' @@ -48,7 +48,14 @@ const LEGITIMATE_IDS = [ const SAFE_ID = 'SAFEID' -type AnyTool = ToolConfig +/** + * The slice of a tool this harness reads. `ToolConfig`'s param type sits in the + * contravariant position of `request.url`, so no concrete member of the barrel's + * union is assignable to a widened `ToolConfig, …>`. The + * barrel is therefore seeded as `unknown` below and narrowed by {@link isDaytonaTool}, + * which is the single point where the type is established. + */ +type AnyTool = ToolConfig, ToolResponse> function isDaytonaTool(value: unknown): value is AnyTool { return ( @@ -82,14 +89,14 @@ function buildPath(tool: AnyTool, sandboxId: string): string { if (typeof url !== 'function') { throw new Error(`${tool.id} does not build its URL from params`) } - return new URL(url(buildParams(tool, sandboxId) as any)).pathname + return new URL(url(buildParams(tool, sandboxId))).pathname } function segmentsOf(pathname: string): string[] { return pathname.split('/') } -const SANDBOX_SCOPED_TOOLS = Object.values(daytonaTools) +const SANDBOX_SCOPED_TOOLS = Object.values(daytonaTools) .filter(isDaytonaTool) .filter((tool) => typeof tool.request?.url === 'function') .filter((tool) => { diff --git a/apps/sim/tools/vercel/edge_config_path_safety.test.ts b/apps/sim/tools/vercel/edge_config_path_safety.test.ts index 44580ee1de3..0b0f6115c37 100644 --- a/apps/sim/tools/vercel/edge_config_path_safety.test.ts +++ b/apps/sim/tools/vercel/edge_config_path_safety.test.ts @@ -21,7 +21,7 @@ * output, because string matching is exactly what let this through. */ import { describe, expect, it } from 'vitest' -import type { ToolConfig } from '@/tools/types' +import type { ToolConfig, ToolResponse } from '@/tools/types' import { vercelDeleteEdgeConfigTool } from '@/tools/vercel/delete_edge_config' import { vercelGetEdgeConfigTool } from '@/tools/vercel/get_edge_config' import { vercelGetEdgeConfigItemsTool } from '@/tools/vercel/get_edge_config_items' @@ -64,7 +64,14 @@ const LEGITIMATE_IDS = [ const SAFE_ID = 'SAFEID' -type AnyTool = ToolConfig +/** + * The slice of a tool this harness reads. `ToolConfig`'s param type sits in the + * contravariant position of `request.url`, so no concrete member of the barrel's + * union is assignable to a widened `ToolConfig, …>`. The + * barrel is therefore seeded as `unknown` below and narrowed by {@link isVercelTool}, + * which is the single point where the type is established. + */ +type AnyTool = ToolConfig, ToolResponse> function isVercelTool(value: unknown): value is AnyTool { return ( @@ -102,14 +109,14 @@ function buildPath(tool: AnyTool, value: string): string { if (typeof url !== 'function') { throw new Error(`${tool.id} does not build its URL from params`) } - return new URL(url(buildParams(tool, value) as any)).pathname + return new URL(url(buildParams(tool, value))).pathname } function segmentsOf(pathname: string): string[] { return pathname.split('/') } -const DYNAMIC_PATH_TOOLS = Object.values(vercelTools) +const DYNAMIC_PATH_TOOLS = Object.values(vercelTools) .filter(isVercelTool) .filter((tool) => typeof tool.request?.url === 'function') .filter((tool) => {