@@ -8,6 +8,11 @@ const DEBOUNCE_TIME = 1000; // milliseconds
88const DYNAMIC_INSTRUCTIONS = "dynamic-instructions" ;
99
1010export type ToolType = "tool" | "context" | "agent" ;
11+ export type DependencyBlock = {
12+ content : string ;
13+ forTool : string ;
14+ type : string ;
15+ }
1116
1217interface EditContextProps {
1318 scriptPath : string ,
@@ -18,6 +23,7 @@ interface EditContextState {
1823 loading : boolean ;
1924 setLoading : ( loading : boolean ) => void ;
2025 root : Tool ;
26+ dependencies : DependencyBlock [ ] ; setDependencies : React . Dispatch < React . SetStateAction < DependencyBlock [ ] > > ;
2127 models : string [ ] , setModels : React . Dispatch < React . SetStateAction < string [ ] > > ;
2228 setRoot : React . Dispatch < React . SetStateAction < Tool > > ;
2329 tools : Tool [ ] ;
@@ -52,12 +58,16 @@ const EditContextProvider: React.FC<EditContextProps> = ({scriptPath, children})
5258 const [ visibility , setVisibility ] = useState < 'public' | 'private' | 'protected' > ( 'private' ) ;
5359 const [ models , setModels ] = useState < string [ ] > ( [ ] ) ;
5460 const debounceTimer = useRef < NodeJS . Timeout | null > ( null ) ;
55-
61+
5662 // Dynamic instructions are simply a text tool with the name "dynamic-instructions" that is
5763 // imported as a context in the root tool. This field is used to store the instructions for
5864 // that tool.
5965 const [ dynamicInstructions , setDynamicInstructions ] = useState < string > ( '' ) ;
6066
67+ // Dependencies are special text tools that reference a tool, type, and content. They are used
68+ // to store requirements.txt and package.json files for the script.
69+ const [ dependencies , setDependencies ] = useState < DependencyBlock [ ] > ( [ ] ) ;
70+
6171 useEffect ( ( ) => {
6272 getModels ( ) . then ( ( m ) => {
6373 setModels ( m )
@@ -85,7 +95,25 @@ const EditContextProvider: React.FC<EditContextProps> = ({scriptPath, children})
8595 useEffect ( ( ) => {
8696 if ( loading ) return ;
8797 update ( ) ;
88- } , [ root , tools , visibility ] )
98+ } , [ root , tools , dependencies , visibility ] )
99+
100+ useEffect ( ( ) => {
101+ setTools ( ( prevTools ) => {
102+ return [
103+ ...prevTools . filter ( ( t ) => t . name !== DYNAMIC_INSTRUCTIONS ) ,
104+ { name : DYNAMIC_INSTRUCTIONS , type : 'tool' , instructions : dynamicInstructions }
105+ ] as Tool [ ] ;
106+ } ) ;
107+
108+ setRoot ( ( prevRoot ) => {
109+ if ( prevRoot . context ?. includes ( DYNAMIC_INSTRUCTIONS ) ) return prevRoot ;
110+ return { ...prevRoot , context : [ ...( prevRoot . context || [ ] ) , DYNAMIC_INSTRUCTIONS ] } ;
111+ } ) ;
112+ } , [ dynamicInstructions ] ) ;
113+
114+ useEffect ( ( ) => {
115+
116+ } , [ dependencies ] )
89117
90118 // The first tool in the script is not always the root tool, so we find it
91119 // by finding the first non-text tool in the script.
@@ -119,11 +147,11 @@ const EditContextProvider: React.FC<EditContextProps> = ({scriptPath, children})
119147 debounceTimer . current = setTimeout ( async ( ) => {
120148 await updateScript ( {
121149 visibility : visibility ,
122- content : await stringify ( [ root , ...tools ] ) ,
150+ content : await stringify ( [ root , ...tools , ... dependenciesToText ( dependencies ) ] ) ,
123151 id : scriptId ,
124152 } ) . catch ( ( error ) => console . error ( error ) ) ;
125153 } , DEBOUNCE_TIME ) ;
126- } , [ scriptId , root , tools , visibility ] ) ;
154+ } , [ scriptId , root , tools , dependencies , visibility ] ) ;
127155
128156 const newestToolName = useCallback ( ( ) => {
129157 let num = 1
@@ -171,25 +199,26 @@ const EditContextProvider: React.FC<EditContextProps> = ({scriptPath, children})
171199 } ) ;
172200 }
173201
174- useEffect ( ( ) => {
175- setTools ( ( prevTools ) => {
176- return [
177- ... prevTools . filter ( ( t ) => t . name !== DYNAMIC_INSTRUCTIONS ) ,
178- { name : DYNAMIC_INSTRUCTIONS , type : 'tool' , instructions : dynamicInstructions }
179- ] as Tool [ ] ;
180- } ) ;
181-
182- setRoot ( ( prevRoot ) => {
183- if ( prevRoot . context ?. includes ( DYNAMIC_INSTRUCTIONS ) ) return prevRoot ;
184- return { ... prevRoot , context : [ ... ( prevRoot . context || [ ] ) , DYNAMIC_INSTRUCTIONS ] } ;
185- } ) ;
186- } , [ dynamicInstructions ] )
202+ const dependenciesToText = ( dependencies : DependencyBlock [ ] ) : Text [ ] => {
203+ return dependencies
204+ . filter ( ( dep ) => dep . content . trim ( ) !== '' ) // Filter out empty dependencies
205+ . map ( ( dep ) => {
206+ return {
207+ id : ` ${ dep . forTool } - ${ dep . type } ` ,
208+ format : `metadata: ${ dep . forTool } : ${ dep . type } ` ,
209+ type : 'text' ,
210+ content : dep . content ,
211+ name : dep . forTool ,
212+ }
213+ } ) ;
214+ }
187215
188216 // Provide the context value to the children components
189217 return (
190218 < EditContext . Provider
191219 value = { {
192220 scriptPath,
221+ dependencies, setDependencies,
193222 dynamicInstructions, setDynamicInstructions,
194223 models, setModels,
195224 loading, setLoading,
0 commit comments