On-demand Scout service (replaces the nightly aggregator): - FastAPI agent-mesh service; card name "matchmaking-service" (HTTP /a2a/tasks + Redis-stream worker matching the sibling-service pattern) - run_search: parallel multi-board sweep (Naukri/blackfalcondata + Foundit + LinkedIn), city-filtered at the board, cheapest-per-result first - per-board adapters + normalizers -> ScoutJob with rich read-only details and offsite apply links; recall mode + MVQ guard - result cache for dev replay ($0); per-board cost knobs; retry-on-5xx - research/: engine design, board cost economics, India-actor shortlist, POC
35 lines
1.0 KiB
Python
35 lines
1.0 KiB
Python
"""EventEmitter — async queue adapter (mirrors the established agent-mesh pattern).
|
|
|
|
Agent session handlers call ``self.ws.send_json(data)`` expecting a WebSocket-like
|
|
interface. This adapter puts each message into an ``asyncio.Queue`` so the Redis Stream
|
|
worker can consume them one by one and publish to the per-task response channel.
|
|
"""
|
|
|
|
import asyncio
|
|
|
|
|
|
class EventEmitter:
|
|
"""WebSocket-compatible adapter backed by an asyncio.Queue."""
|
|
|
|
def __init__(self):
|
|
self.queue: asyncio.Queue = asyncio.Queue()
|
|
self._done = False
|
|
|
|
async def accept(self):
|
|
pass
|
|
|
|
async def send_json(self, data: dict):
|
|
"""Called by session handlers via ``self.push()``."""
|
|
await self.queue.put(data)
|
|
|
|
async def receive_json(self):
|
|
raise StopIteration("EventEmitter does not support receive")
|
|
|
|
def query_params(self):
|
|
return {}
|
|
|
|
def mark_done(self):
|
|
"""Signal that the session handler has finished."""
|
|
self._done = True
|
|
self.queue.put_nowait(None)
|