44 */
55
66import { defaults } from '../const.js' ;
7- import { addRemoveTools , getActorsAsTools , toolCategories , toolCategoriesEnabledByDefault } from '../tools/index.js' ;
7+ import { addTool } from '../tools/helpers.js' ;
8+ import { getActorsAsTools , toolCategories , toolCategoriesEnabledByDefault } from '../tools/index.js' ;
89import type { Input , ToolCategory , ToolEntry } from '../types.js' ;
910import { getExpectedToolsByCategories } from './tools.js' ;
1011
@@ -22,30 +23,100 @@ export async function loadToolsFromInput(
2223) : Promise < ToolEntry [ ] > {
2324 let tools : ToolEntry [ ] = [ ] ;
2425
25- // Load actors as tools
26- if ( input . actors !== undefined ) {
27- const actors = Array . isArray ( input . actors ) ? input . actors : [ input . actors ] ;
28- tools = await getActorsAsTools ( actors , apifyToken ) ;
26+ // Prepare lists for actor and internal tool/category selectors from `tools`
27+ let toolSelectors : ( string | ToolCategory ) [ ] | undefined ;
28+ if ( input . tools === undefined ) {
29+ toolSelectors = undefined ;
30+ } else if ( Array . isArray ( input . tools ) ) {
31+ toolSelectors = input . tools . filter ( ( s ) => String ( s ) . trim ( ) !== '' ) ;
2932 } else {
30- // Use default actors if no actors are specified
31- tools = await getActorsAsTools ( defaults . actors , apifyToken ) ;
33+ toolSelectors = [ input . tools ] . filter ( ( s ) => String ( s ) . trim ( ) !== '' ) ;
3234 }
3335
34- // Add tools for adding/removing actors if enabled
35- if ( input . enableAddingActors ) {
36- tools . push ( ...addRemoveTools ) ;
36+ // Build a name -> tool entry map for all known internal (category) tools
37+ const allCategoryTools : ToolEntry [ ] = getExpectedToolsByCategories ( Object . keys ( toolCategories ) as ToolCategory [ ] ) ;
38+ const toolNameMap = new Map < string , ToolEntry > ( ) ;
39+ for ( const entry of allCategoryTools ) {
40+ toolNameMap . set ( entry . tool . name , entry ) ;
3741 }
3842
39- // Add tools from enabled categories
40- if ( input . tools !== undefined ) {
41- const toolKeys = Array . isArray ( input . tools ) ? input . tools : [ input . tools ] ;
42- for ( const toolKey of toolKeys ) {
43- const keyTools = toolCategories [ toolKey as ToolCategory ] || [ ] ;
44- tools . push ( ...keyTools ) ;
43+ // Classify selectors from `tools` into categories/internal tools and actor names
44+ const internalCategoryEntries : ToolEntry [ ] = [ ] ;
45+ const actorSelectorsFromTools : string [ ] = [ ] ;
46+ if ( toolSelectors !== undefined ) {
47+ for ( const selector of toolSelectors ) {
48+ const categoryTools = toolCategories [ selector as ToolCategory ] ;
49+ if ( categoryTools && Array . isArray ( categoryTools ) ) {
50+ internalCategoryEntries . push ( ...categoryTools ) ;
51+ continue ;
52+ }
53+ const internalByName = toolNameMap . get ( String ( selector ) ) ;
54+ if ( internalByName ) {
55+ internalCategoryEntries . push ( internalByName ) ;
56+ continue ;
57+ }
58+ // Treat unknown selectors as Actor IDs/full names
59+ actorSelectorsFromTools . push ( String ( selector ) ) ;
4560 }
61+ }
62+
63+ // Resolve actor list to load
64+ let actorsFromInputField : string [ ] | undefined ;
65+ if ( input . actors === undefined ) {
66+ actorsFromInputField = undefined ; // use defaults later unless overridden by tools
67+ } else if ( Array . isArray ( input . actors ) ) {
68+ actorsFromInputField = input . actors ;
69+ } else {
70+ actorsFromInputField = [ input . actors ] ;
71+ }
72+
73+ let actorNamesToLoad : string [ ] = [ ] ;
74+ if ( actorsFromInputField !== undefined ) {
75+ actorNamesToLoad = actorsFromInputField ;
76+ } else if ( actorSelectorsFromTools . length > 0 ) {
77+ // If no explicit `actors` were provided, but `tools` includes actor names,
78+ // load exactly those instead of defaults
79+ actorNamesToLoad = actorSelectorsFromTools ;
80+ } else {
81+ // Use default actors if nothing specified anywhere
82+ actorNamesToLoad = defaults . actors ;
83+ }
84+
85+ // If both fields specify actors, merge them
86+ if ( actorsFromInputField !== undefined && actorSelectorsFromTools . length > 0 ) {
87+ const merged = new Set < string > ( [ ...actorNamesToLoad , ...actorSelectorsFromTools ] ) ;
88+ actorNamesToLoad = Array . from ( merged ) ;
89+ }
90+
91+ // Load actor tools (if any)
92+ if ( actorNamesToLoad . length > 0 ) {
93+ tools = await getActorsAsTools ( actorNamesToLoad , apifyToken ) ;
94+ }
95+
96+ // Add tool for dynamically adding actors if enabled
97+ if ( input . enableAddingActors ) {
98+ tools . push ( addTool ) ;
99+ }
100+
101+ // Add internal tools from categories/tool names or defaults when `tools` unspecified
102+ if ( toolSelectors !== undefined ) {
103+ // Respect disable flag: do not include add-actor even if explicitly requested
104+ const filteredInternal = input . enableAddingActors
105+ ? internalCategoryEntries
106+ : internalCategoryEntries . filter ( ( entry ) => entry . tool . name !== addTool . tool . name ) ;
107+ tools . push ( ...filteredInternal ) ;
46108 } else {
47109 tools . push ( ...getExpectedToolsByCategories ( toolCategoriesEnabledByDefault ) ) ;
48110 }
49111
112+ // De-duplicate by tool name
113+ const seen = new Set < string > ( ) ;
114+ tools = tools . filter ( ( entry ) => {
115+ const { name } = entry . tool ;
116+ if ( seen . has ( name ) ) return false ;
117+ seen . add ( name ) ;
118+ return true ;
119+ } ) ;
120+
50121 return tools ;
51122}
0 commit comments