@@ -12,6 +12,7 @@ import { eventBus } from '../lib/events.js';
1212import { releaseEscrow , refundEscrow } from '../services/escrow.js' ;
1313import { embed } from '../services/embeddings.js' ;
1414import { persistTaskSubmission } from '../services/storage.js' ;
15+ import { fetchOrderedRowsByIds , searchTasksIndex } from '../services/search.js' ;
1516
1617const app = new Hono < AuthContext > ( ) ;
1718
@@ -24,6 +25,53 @@ app.get('/', async (c) => {
2425
2526 const { q, status, skills, budgetMin, budgetMax, requesterId, assigneeId, limit, offset } = query . data ;
2627
28+ if ( ! budgetMin && ! budgetMax ) {
29+ const indexed = await searchTasksIndex ( {
30+ q,
31+ status,
32+ skills,
33+ requesterId,
34+ assigneeId,
35+ limit,
36+ offset,
37+ } ) ;
38+
39+ if ( indexed ) {
40+ if ( indexed . ids . length === 0 ) {
41+ return c . json ( { tasks : [ ] , limit, offset, total : indexed . total , facets : indexed . facets } ) ;
42+ }
43+
44+ const result = await fetchOrderedRowsByIds ( indexed . ids , ( ) =>
45+ db
46+ . select ( )
47+ . from ( tasks )
48+ . where ( inArray ( tasks . id , indexed . ids ) ) ,
49+ ) ;
50+
51+ const bidCountRows = await db . execute ( sql `
52+ SELECT ${ taskBids . taskId } AS task_id, COUNT(*)::int AS bid_count
53+ FROM ${ taskBids }
54+ WHERE ${ taskBids . taskId } = ANY(${ indexed . ids } )
55+ GROUP BY ${ taskBids . taskId }
56+ ` ) ;
57+
58+ const bidCountEntries = ( bidCountRows . rows as Array < { task_id : string ; bid_count : number | string } > )
59+ . map ( ( row ) => [ row . task_id , Number ( row . bid_count ) ] as const ) ;
60+ const bidCounts = new Map < string , number > ( bidCountEntries ) ;
61+
62+ return c . json ( {
63+ tasks : result . map ( ( task ) => ( {
64+ ...task ,
65+ bidCount : bidCounts . get ( task . id ) ?? 0 ,
66+ } ) ) ,
67+ limit,
68+ offset,
69+ total : indexed . total ,
70+ facets : indexed . facets ,
71+ } ) ;
72+ }
73+ }
74+
2775 const conditions = [ ] ;
2876 if ( status ) conditions . push ( eq ( tasks . status , status ) ) ;
2977 if ( requesterId ) conditions . push ( eq ( tasks . requesterId , requesterId ) ) ;
@@ -66,7 +114,7 @@ app.get('/', async (c) => {
66114 ? await db . execute ( sql `
67115 SELECT ${ taskBids . taskId } AS task_id, COUNT(*)::int AS bid_count
68116 FROM ${ taskBids }
69- WHERE ${ taskBids . taskId } = ANY (${ taskIds } )
117+ WHERE ${ taskBids . taskId } IN (${ sql . join ( taskIds . map ( id => sql ` ${ id } ` ) , sql `, ` ) } )
70118 GROUP BY ${ taskBids . taskId }
71119 ` )
72120 : { rows : [ ] as Array < { task_id : string ; bid_count : number | string } > } ;
@@ -209,6 +257,11 @@ app.patch('/:id', authMiddleware, requireScope('tasks.write'), async (c) => {
209257 . where ( eq ( tasks . id , id ) )
210258 . returning ( ) ;
211259
260+ eventBus . broadcast ( {
261+ type : 'task.updated' ,
262+ data : { taskId : id , status : updated . status } ,
263+ } ) ;
264+
212265 return c . json ( updated ) ;
213266} ) ;
214267
@@ -226,6 +279,11 @@ app.delete('/:id', authMiddleware, requireScope('tasks.write'), async (c) => {
226279
227280 await db . update ( tasks ) . set ( { status : TASK_STATUS . CANCELLED , updatedAt : new Date ( ) } ) . where ( eq ( tasks . id , id ) ) ;
228281
282+ eventBus . broadcast ( {
283+ type : 'task.updated' ,
284+ data : { taskId : id , status : TASK_STATUS . CANCELLED } ,
285+ } ) ;
286+
229287 // Refund escrow if any
230288 await refundEscrow ( id ) ;
231289
@@ -252,6 +310,10 @@ app.post('/:id/start', authMiddleware, async (c) => {
252310 type : 'task.started' ,
253311 data : { taskId : id , agentId : agent . agent_id } ,
254312 } ) ;
313+ eventBus . broadcast ( {
314+ type : 'task.updated' ,
315+ data : { taskId : id , status : TASK_STATUS . IN_PROGRESS , assigneeId : agent . agent_id } ,
316+ } ) ;
255317
256318 return c . json ( updated ) ;
257319} ) ;
@@ -283,6 +345,10 @@ app.post('/:id/submit', authMiddleware, async (c) => {
283345 type : 'task.submitted' ,
284346 data : { taskId : id , agentId : agent . agent_id , artifacts : parsed . data . artifacts } ,
285347 } ) ;
348+ eventBus . broadcast ( {
349+ type : 'task.updated' ,
350+ data : { taskId : id , status : TASK_STATUS . REVIEW , assigneeId : agent . agent_id } ,
351+ } ) ;
286352
287353 return c . json ( updated ) ;
288354} ) ;
@@ -318,6 +384,10 @@ app.post('/:id/approve', authMiddleware, async (c) => {
318384 data : { taskId : id , releaseTxHash, fee : fee . toString ( ) } ,
319385 } ) ;
320386 }
387+ eventBus . broadcast ( {
388+ type : 'task.updated' ,
389+ data : { taskId : id , status : TASK_STATUS . COMPLETED , assigneeId : task . assigneeId } ,
390+ } ) ;
321391
322392 return c . json ( { ...updated , releaseTxHash } ) ;
323393} ) ;
@@ -349,6 +419,10 @@ app.post('/:id/reject', authMiddleware, async (c) => {
349419 data : { taskId : id , reason } ,
350420 } ) ;
351421 }
422+ eventBus . broadcast ( {
423+ type : 'task.updated' ,
424+ data : { taskId : id , status : TASK_STATUS . IN_PROGRESS , assigneeId : task . assigneeId } ,
425+ } ) ;
352426
353427 return c . json ( updated ) ;
354428} ) ;
@@ -418,6 +492,10 @@ app.post('/:id/dispute', authMiddleware, async (c) => {
418492 data : { taskId : id , disputeId : dispute . id , reason : parsed . data . reason } ,
419493 } ) ;
420494 }
495+ eventBus . broadcast ( {
496+ type : 'task.updated' ,
497+ data : { taskId : id , status : TASK_STATUS . DISPUTED , assigneeId : task . assigneeId , requesterId : task . requesterId } ,
498+ } ) ;
421499
422500 return c . json ( dispute , 201 ) ;
423501} ) ;
0 commit comments