1+ import { ChunkedFile } from '../../data/model/chunked_file' ;
2+ import { ChunkedFileChunk } from '../../data/model/chunked_file_chunk' ;
3+ import { Execution } from '../../data/model/execution' ;
4+ import { Result } from '../../data/model/result' ;
5+ import { DockerRepository } from '../../data/repository/docker_repository' ;
6+ import { FileRepository } from '../../data/repository/file_repository' ;
7+ import { SupabaseRepository } from '../../data/repository/supabase_repository' ;
8+ import { logDebugInfo , logError , logInfo , logSingleLine } from '../../utils/logger' ;
9+ import { ParamUseCase } from '../base/param_usecase' ;
10+
11+ export class AskActionUseCase implements ParamUseCase < Execution , Result [ ] > {
12+ taskId : string = 'AskActionUseCase' ;
13+ private dockerRepository : DockerRepository = new DockerRepository ( ) ;
14+ private fileRepository : FileRepository = new FileRepository ( ) ;
15+ private readonly CODE_INSTRUCTION_BLOCK = "Represent the code for semantic search" ;
16+ private readonly CODE_INSTRUCTION_LINE = "Represent each line of code for retrieval" ;
17+ private readonly CODE_INSTRUCTION_ASK = "Represent the question for retrieving relevant code snippets" ;
18+
19+ async invoke ( param : Execution ) : Promise < Result [ ] > {
20+ logInfo ( `Executing ${ this . taskId } .` )
21+
22+ const results : Result [ ] = [ ] ;
23+
24+ try {
25+ /**
26+ * Check if the user from the token is found.
27+ */
28+ if ( ! param . tokenUser ) {
29+ results . push (
30+ new Result ( {
31+ id : this . taskId ,
32+ success : false ,
33+ executed : false ,
34+ errors : [
35+ `User from token not found.` ,
36+ ] ,
37+ } )
38+ )
39+ return results ;
40+ }
41+
42+ /**
43+ * Get the comment body.
44+ */
45+ let commentBody = '' ;
46+ if ( param . issue . isIssueComment ) {
47+ commentBody = param . issue . commentBody ;
48+ } else if ( param . pullRequest . isPullRequestReviewComment ) {
49+ commentBody = param . pullRequest . commentBody ;
50+ } else {
51+ logError ( `Not a valid comment body.` ) ;
52+ results . push (
53+ new Result ( {
54+ id : this . taskId ,
55+ success : true ,
56+ executed : false ,
57+ } )
58+ )
59+ return results ;
60+ }
61+
62+ /**
63+ * Check if the comment body includes the user from the token.
64+ */
65+ if ( ! commentBody . includes ( param . tokenUser ) ) {
66+ results . push (
67+ new Result ( {
68+ id : this . taskId ,
69+ success : true ,
70+ executed : false ,
71+ } )
72+ )
73+ return results ;
74+ } else {
75+ commentBody = commentBody . replace ( param . tokenUser , '' ) . trim ( ) ;
76+ }
77+
78+ /**
79+ * Check if the supabase config is found.
80+ */
81+ if ( ! param . supabaseConfig ) {
82+ results . push (
83+ new Result ( {
84+ id : this . taskId ,
85+ success : false ,
86+ executed : true ,
87+ steps : [
88+ `Supabase config not found.` ,
89+ ] ,
90+ } )
91+ )
92+ return results ;
93+ }
94+
95+ const supabaseRepository : SupabaseRepository = new SupabaseRepository ( param . supabaseConfig ) ;
96+
97+ await this . dockerRepository . startContainer ( param ) ;
98+
99+ const systemInfo = await this . dockerRepository . getSystemInfo ( param ) ;
100+ const chunkSize = systemInfo . parameters . chunk_size as number ;
101+ const maxWorkers = systemInfo . parameters . max_workers as number ;
102+
103+ logInfo ( `🧑🏭 Max workers: ${ maxWorkers } ` ) ;
104+ logInfo ( `🚚 Chunk size: ${ chunkSize } ` ) ;
105+ logInfo ( `📦 Getting chunked files for ${ param . owner } /${ param . repo } /${ param . commit . branch } ` ) ;
106+
107+ const startTime = Date . now ( ) ;
108+
109+ const embeddings = await this . dockerRepository . getEmbedding (
110+ param ,
111+ [
112+ [ this . CODE_INSTRUCTION_ASK , commentBody ]
113+ ]
114+ ) ;
115+
116+ logInfo ( `🔎 Embeddings: ${ JSON . stringify ( embeddings , null , 2 ) } ` ) ;
117+
118+ const types = [ 'line' , 'block' ] ;
119+ const chunks : ChunkedFileChunk [ ] = [ ] ;
120+ for ( const type of types ) {
121+ logInfo ( `📦 🔎 Matching chunks for ${ param . owner } /${ param . repo } /${ param . commit . branch } ` ) ;
122+ const foundChunks = await supabaseRepository . matchChunks (
123+ param . owner ,
124+ param . repo ,
125+ param . commit . branch ,
126+ type ,
127+ embeddings [ 0 ] ,
128+ 5
129+ ) ;
130+
131+ for ( const chunk of foundChunks ) {
132+ logDebugInfo ( `📦 🔎 Chunk type: ${ type } - ${ chunk . path } ` ) ;
133+ }
134+
135+ chunks . push ( ...foundChunks ) ;
136+ }
137+
138+
139+
140+ const totalDurationSeconds = ( Date . now ( ) - startTime ) / 1000 ;
141+ logInfo ( `📦 🔎 Matched chunks for ${ param . owner } /${ param . repo } /${ param . commit . branch } :\n Total duration: ${ Math . ceil ( totalDurationSeconds ) } seconds` ) ;
142+
143+ results . push (
144+ new Result ( {
145+ id : this . taskId ,
146+ success : true ,
147+ executed : true ,
148+ steps : [
149+ `Vector action executed successfully.` ,
150+ ] ,
151+ } )
152+ ) ;
153+
154+ } catch ( error ) {
155+ logError ( `Error in ${ this . taskId } : ${ JSON . stringify ( error , null , 2 ) } ` ) ;
156+ results . push (
157+ new Result ( {
158+ id : this . taskId ,
159+ success : false ,
160+ executed : true ,
161+ steps : [
162+ `Error in ${ this . taskId } : ${ JSON . stringify ( error , null , 2 ) } ` ,
163+ ] ,
164+ } )
165+ ) ;
166+ } finally {
167+ await this . dockerRepository . stopContainer ( param ) ;
168+ }
169+
170+ return results ;
171+ }
172+ }
0 commit comments