66
77use std:: collections:: HashMap ;
88use std:: convert:: Infallible ;
9+ use std:: path:: PathBuf ;
910use std:: str:: FromStr ;
1011use std:: sync:: atomic:: { AtomicU64 , Ordering } ;
1112use std:: sync:: Arc ;
@@ -24,6 +25,7 @@ use tokio::time::interval;
2425use utoipa:: { IntoParams , OpenApi , ToSchema } ;
2526
2627use crate :: router:: { AppState , CreateSessionRequest , PermissionReply } ;
28+ use crate :: search:: { FileSearchType , SearchFileParams , SearchSymbolParams , SearchTextParams } ;
2729use sandbox_agent_agent_management:: agents:: AgentId ;
2830use sandbox_agent_error:: SandboxError ;
2931use sandbox_agent_universal_agent_schema:: {
@@ -471,18 +473,26 @@ struct ToolQuery {
471473struct FindTextQuery {
472474 directory : Option < String > ,
473475 pattern : Option < String > ,
476+ #[ serde( rename = "caseSensitive" ) ]
477+ case_sensitive : Option < bool > ,
478+ limit : Option < usize > ,
474479}
475480
476481#[ derive( Debug , Deserialize , IntoParams ) ]
477482struct FindFilesQuery {
478483 directory : Option < String > ,
479484 query : Option < String > ,
485+ dirs : Option < String > ,
486+ #[ serde( rename = "type" ) ]
487+ kind : Option < String > ,
488+ limit : Option < usize > ,
480489}
481490
482491#[ derive( Debug , Deserialize , IntoParams ) ]
483492struct FindSymbolsQuery {
484493 directory : Option < String > ,
485494 query : Option < String > ,
495+ limit : Option < usize > ,
486496}
487497
488498#[ derive( Debug , Deserialize , IntoParams ) ]
@@ -3855,11 +3865,37 @@ async fn oc_file_status() -> impl IntoResponse {
38553865 responses( ( status = 200 ) ) ,
38563866 tag = "opencode"
38573867) ]
3858- async fn oc_find_text ( Query ( query) : Query < FindTextQuery > ) -> impl IntoResponse {
3859- if query. pattern . is_none ( ) {
3868+ async fn oc_find_text (
3869+ State ( state) : State < Arc < OpenCodeAppState > > ,
3870+ headers : HeaderMap ,
3871+ Query ( query) : Query < FindTextQuery > ,
3872+ ) -> impl IntoResponse {
3873+ let Some ( pattern) = query. pattern else {
38603874 return bad_request ( "pattern is required" ) . into_response ( ) ;
3875+ } ;
3876+
3877+ let directory = state
3878+ . opencode
3879+ . directory_for ( & headers, query. directory . as_ref ( ) ) ;
3880+ let worktree = state. opencode . worktree_for ( & directory) ;
3881+ let search_params = SearchTextParams {
3882+ root : PathBuf :: from ( worktree) ,
3883+ directory : PathBuf :: from ( directory) ,
3884+ pattern,
3885+ case_sensitive : query. case_sensitive ,
3886+ limit : query. limit ,
3887+ } ;
3888+
3889+ match state
3890+ . inner
3891+ . session_manager ( )
3892+ . search_service ( )
3893+ . search_text ( search_params)
3894+ . await
3895+ {
3896+ Ok ( matches) => ( StatusCode :: OK , Json ( matches) ) . into_response ( ) ,
3897+ Err ( err) => sandbox_error_response ( err) . into_response ( ) ,
38613898 }
3862- ( StatusCode :: OK , Json ( json ! ( [ ] ) ) ) . into_response ( )
38633899}
38643900
38653901#[ utoipa:: path(
@@ -3868,11 +3904,52 @@ async fn oc_find_text(Query(query): Query<FindTextQuery>) -> impl IntoResponse {
38683904 responses( ( status = 200 ) ) ,
38693905 tag = "opencode"
38703906) ]
3871- async fn oc_find_files ( Query ( query) : Query < FindFilesQuery > ) -> impl IntoResponse {
3872- if query. query . is_none ( ) {
3907+ async fn oc_find_files (
3908+ State ( state) : State < Arc < OpenCodeAppState > > ,
3909+ headers : HeaderMap ,
3910+ Query ( query) : Query < FindFilesQuery > ,
3911+ ) -> impl IntoResponse {
3912+ let Some ( query_value) = query. query else {
38733913 return bad_request ( "query is required" ) . into_response ( ) ;
3914+ } ;
3915+
3916+ let include_dirs = match query. dirs . as_deref ( ) {
3917+ Some ( "true" ) => Some ( true ) ,
3918+ Some ( "false" ) => Some ( false ) ,
3919+ Some ( _) => return bad_request ( "dirs must be true or false" ) . into_response ( ) ,
3920+ None => None ,
3921+ } ;
3922+
3923+ let file_type = match query. kind . as_deref ( ) {
3924+ Some ( "file" ) => Some ( FileSearchType :: File ) ,
3925+ Some ( "directory" ) => Some ( FileSearchType :: Directory ) ,
3926+ Some ( _) => return bad_request ( "type must be file or directory" ) . into_response ( ) ,
3927+ None => None ,
3928+ } ;
3929+
3930+ let directory = state
3931+ . opencode
3932+ . directory_for ( & headers, query. directory . as_ref ( ) ) ;
3933+ let worktree = state. opencode . worktree_for ( & directory) ;
3934+ let search_params = SearchFileParams {
3935+ root : PathBuf :: from ( worktree) ,
3936+ directory : PathBuf :: from ( directory) ,
3937+ query : query_value,
3938+ include_dirs,
3939+ file_type,
3940+ limit : query. limit ,
3941+ } ;
3942+
3943+ match state
3944+ . inner
3945+ . session_manager ( )
3946+ . search_service ( )
3947+ . search_files ( search_params)
3948+ . await
3949+ {
3950+ Ok ( results) => ( StatusCode :: OK , Json ( results) ) . into_response ( ) ,
3951+ Err ( err) => sandbox_error_response ( err) . into_response ( ) ,
38743952 }
3875- ( StatusCode :: OK , Json ( json ! ( [ ] ) ) ) . into_response ( )
38763953}
38773954
38783955#[ utoipa:: path(
@@ -3881,11 +3958,36 @@ async fn oc_find_files(Query(query): Query<FindFilesQuery>) -> impl IntoResponse
38813958 responses( ( status = 200 ) ) ,
38823959 tag = "opencode"
38833960) ]
3884- async fn oc_find_symbols ( Query ( query) : Query < FindSymbolsQuery > ) -> impl IntoResponse {
3885- if query. query . is_none ( ) {
3961+ async fn oc_find_symbols (
3962+ State ( state) : State < Arc < OpenCodeAppState > > ,
3963+ headers : HeaderMap ,
3964+ Query ( query) : Query < FindSymbolsQuery > ,
3965+ ) -> impl IntoResponse {
3966+ let Some ( query_value) = query. query else {
38863967 return bad_request ( "query is required" ) . into_response ( ) ;
3968+ } ;
3969+
3970+ let directory = state
3971+ . opencode
3972+ . directory_for ( & headers, query. directory . as_ref ( ) ) ;
3973+ let worktree = state. opencode . worktree_for ( & directory) ;
3974+ let search_params = SearchSymbolParams {
3975+ root : PathBuf :: from ( worktree) ,
3976+ directory : PathBuf :: from ( directory) ,
3977+ query : query_value,
3978+ limit : query. limit ,
3979+ } ;
3980+
3981+ match state
3982+ . inner
3983+ . session_manager ( )
3984+ . search_service ( )
3985+ . search_symbols ( search_params)
3986+ . await
3987+ {
3988+ Ok ( results) => ( StatusCode :: OK , Json ( results) ) . into_response ( ) ,
3989+ Err ( err) => sandbox_error_response ( err) . into_response ( ) ,
38873990 }
3888- ( StatusCode :: OK , Json ( json ! ( [ ] ) ) ) . into_response ( )
38893991}
38903992
38913993#[ utoipa:: path(
0 commit comments