@@ -3,7 +3,7 @@ import { ApifyClient } from 'apify-client';
33
44import { ACTOR_ADDITIONAL_INSTRUCTIONS , defaults , MAX_DESCRIPTION_LENGTH , ACTOR_README_MAX_LENGTH } from './const.js' ;
55import { log } from './logger.js' ;
6- import type { ActorDefinitionPruned , ActorDefinitionWithDesc , SchemaProperties , Tool } from './types.js' ;
6+ import type { ActorDefinitionPruned , ActorDefinitionWithDesc , IActorInputSchema , ISchemaProperties , Tool } from './types.js' ;
77
88export function actorNameToToolName ( actorName : string ) : string {
99 return actorName
@@ -67,7 +67,11 @@ function pruneActorDefinition(response: ActorDefinitionWithDesc): ActorDefinitio
6767 actorFullName : response . actorFullName || '' ,
6868 buildTag : response ?. buildTag || '' ,
6969 readme : response ?. readme || '' ,
70- input : response ?. input || null ,
70+ input : response ?. input && 'type' in response . input && 'properties' in response . input
71+ ? { ...response . input ,
72+ type : response . input . type as string ,
73+ properties : response . input . properties as Record < string , ISchemaProperties > }
74+ : undefined ,
7175 description : response . description ,
7276 defaultRunOptions : response . defaultRunOptions ,
7377 } ;
@@ -77,7 +81,7 @@ function pruneActorDefinition(response: ActorDefinitionWithDesc): ActorDefinitio
7781 * Shortens the description and enum values of schema properties.
7882 * @param properties
7983 */
80- export function shortenProperties ( properties : { [ key : string ] : SchemaProperties } ) : { [ key : string ] : SchemaProperties } {
84+ export function shortenProperties ( properties : { [ key : string ] : ISchemaProperties } ) : { [ key : string ] : ISchemaProperties } {
8185 for ( const property of Object . values ( properties ) ) {
8286 if ( property . description . length > MAX_DESCRIPTION_LENGTH ) {
8387 property . description = `${ property . description . slice ( 0 , MAX_DESCRIPTION_LENGTH ) } ...` ;
@@ -106,10 +110,10 @@ export function truncateActorReadme(readme: string, limit = ACTOR_README_MAX_LEN
106110 * Helps determine the type of items in an array schema property.
107111 * Priority order: explicit type in items > prefill type > default value type > editor type.
108112 */
109- export function inferArrayItemType ( property : SchemaProperties ) : string | null {
113+ function inferArrayItemType ( property : ISchemaProperties ) : string | null {
110114 return property . items ?. type
111- || ( property . prefill ? .length > 0 && typeof property . prefill [ 0 ] )
112- || ( property . default ? .length > 0 && typeof property . default [ 0 ] )
115+ || ( Array . isArray ( property . prefill ) && property . prefill . length > 0 && typeof property . prefill [ 0 ] )
116+ || ( Array . isArray ( property . default ) && property . default . length > 0 && typeof property . default [ 0 ] )
113117 || ( property . editor && getEditorItemType ( property . editor ) )
114118 || null ;
115119
@@ -128,7 +132,7 @@ export function inferArrayItemType(property: SchemaProperties): string | null {
128132 * Add enum values as string to property descriptions.
129133 * @param properties
130134 */
131- export function addEnumsToDescriptionsWithExamples ( properties : { [ key : string ] : SchemaProperties } ) : { [ key : string ] : SchemaProperties } {
135+ function addEnumsToDescriptionsWithExamples ( properties : { [ key : string ] : ISchemaProperties } ) : { [ key : string ] : ISchemaProperties } {
132136 for ( const property of Object . values ( properties ) ) {
133137 if ( property . enum && property . enum . length > 0 ) {
134138 property . description = `${ property . description } \nPossible values: ${ property . enum . join ( ',' ) } ` ;
@@ -146,21 +150,105 @@ export function addEnumsToDescriptionsWithExamples(properties: { [key: string]:
146150 * Filters schema properties to include only the necessary fields.
147151 * @param properties
148152 */
149- export function filterSchemaProperties ( properties : { [ key : string ] : SchemaProperties } ) : { [ key : string ] : SchemaProperties } {
150- const filteredProperties : { [ key : string ] : SchemaProperties } = { } ;
153+ export function filterSchemaProperties ( properties : { [ key : string ] : ISchemaProperties } ) : { [ key : string ] : ISchemaProperties } {
154+ const filteredProperties : { [ key : string ] : ISchemaProperties } = { } ;
151155 for ( const [ key , property ] of Object . entries ( properties ) ) {
152- const { title, description, enum : enumValues , type, default : defaultValue , prefill } = property ;
153- filteredProperties [ key ] = { title, description, enum : enumValues , type, default : defaultValue , prefill } ;
154- if ( type === 'array' ) {
156+ const { title, description, enum : enumValues , type,
157+ default : defaultValue , prefill, properties : subProperties ,
158+ items, required } = property ;
159+ filteredProperties [ key ] = { title,
160+ description,
161+ enum : enumValues ,
162+ type,
163+ default : defaultValue ,
164+ prefill,
165+ properties : subProperties ,
166+ items,
167+ required } ;
168+ if ( type === 'array' && ! items ?. type ) {
155169 const itemsType = inferArrayItemType ( property ) ;
156170 if ( itemsType ) {
157- filteredProperties [ key ] . items = { type : itemsType } ;
171+ filteredProperties [ key ] . items = {
172+ ...filteredProperties [ key ] . items ,
173+ title : filteredProperties [ key ] . title ?? 'Item' ,
174+ description : filteredProperties [ key ] . description ?? 'Item' ,
175+ type : itemsType ,
176+ } ;
158177 }
159178 }
160179 }
161180 return filteredProperties ;
162181}
163182
183+ /**
184+ * Marks input properties as required by adding a "REQUIRED" prefix to their descriptions.
185+ * Takes an IActorInput object and returns a modified Record of SchemaProperties.
186+ * @param {IActorInputSchema } input - Actor input object containing properties and required fields
187+ * @returns {Record<string, ISchemaProperties> } - Modified properties with required fields marked
188+ */
189+ function markInputPropertiesAsRequired ( input : IActorInputSchema ) : Record < string , ISchemaProperties > {
190+ const { required = [ ] , properties } = input ;
191+
192+ for ( const property of Object . keys ( properties ) ) {
193+ if ( required . includes ( property ) ) {
194+ properties [ property ] = {
195+ ...properties [ property ] ,
196+ description : `**REQUIRED** ${ properties [ property ] . description } ` ,
197+ } ;
198+ }
199+ }
200+
201+ return properties ;
202+ }
203+
204+ /**
205+ * Builds nested properties for object types in the schema.
206+ * @param {Record<string, ISchemaProperties> } properties - The input schema properties
207+ * @returns {Record<string, ISchemaProperties> } Modified properties with nested properties
208+ */
209+ function buildNestedProperties ( properties : Record < string , ISchemaProperties > ) : Record < string , ISchemaProperties > {
210+ const clonedProperties = { ...properties } ;
211+
212+ for ( const [ propertyName , property ] of Object . entries ( clonedProperties ) ) {
213+ if ( property . type === 'object' && property . editor === 'proxy' ) {
214+ clonedProperties [ propertyName ] = {
215+ ...property ,
216+ properties : {
217+ ...property . properties ,
218+ useApifyProxy : {
219+ title : 'Use Apify Proxy' ,
220+ type : 'boolean' ,
221+ description : 'Whether to use Apify Proxy - ALWAYS SET TO TRUE.' ,
222+ default : true ,
223+ examples : [ true ] ,
224+ } ,
225+ } ,
226+ required : [ 'useApifyProxy' ] ,
227+ } ;
228+ } else if ( property . type === 'array' && property . editor === 'requestListSources' ) {
229+ clonedProperties [ propertyName ] = {
230+ ...property ,
231+ items : {
232+ ...property . items ,
233+ type : 'object' ,
234+ title : 'Request list source' ,
235+ description : 'Request list source' ,
236+ properties : {
237+ url : {
238+ title : 'URL' ,
239+ type : 'string' ,
240+ description : 'URL of the request list source' ,
241+ } ,
242+ } ,
243+ } ,
244+ required : [ 'useApifyProxy' ] ,
245+ } ;
246+ }
247+ }
248+
249+ return clonedProperties ;
250+ }
251+
164252/**
165253 * Fetches actor input schemas by Actor IDs or Actor full names and creates MCP tools.
166254 *
@@ -179,8 +267,10 @@ export async function getActorsAsTools(actors: string[]): Promise<Tool[]> {
179267 for ( const result of results ) {
180268 if ( result ) {
181269 if ( result . input && 'properties' in result . input && result . input ) {
182- const properties = filterSchemaProperties ( result . input . properties as { [ key : string ] : SchemaProperties } ) ;
183- const propertiesShortened = shortenProperties ( properties ) ;
270+ const propertiesMarkedAsRequired = markInputPropertiesAsRequired ( result . input ) ;
271+ const propertiesObjectsBuilt = buildNestedProperties ( propertiesMarkedAsRequired ) ;
272+ const propertiesFiltered = filterSchemaProperties ( propertiesObjectsBuilt ) ;
273+ const propertiesShortened = shortenProperties ( propertiesFiltered ) ;
184274 result . input . properties = addEnumsToDescriptionsWithExamples ( propertiesShortened ) ;
185275 }
186276 try {
0 commit comments