diff --git a/collector.py b/collector.py index a4ced9f..617b3f0 100644 --- a/collector.py +++ b/collector.py @@ -185,18 +185,48 @@ class CollectorBridge: # ─── Poll Gateway commands → local ─── + def _discover_local_projects(self) -> set[str]: + """Discover all project names registered by local Extension instances. + + Reads bridge/register/*.json files, which are written by each AG window's + Extension with {conversation_id, project_name}. Returns unique project names + found, always including self.project_name as a fallback. + """ + projects = {self.project_name} + register_dir = self.local.bridge_dir / "register" + if not register_dir.exists(): + return projects + for f in register_dir.glob("*.json"): + try: + data = json.loads(f.read_text(encoding="utf-8-sig")) + p = data.get("project_name", "") + if p: + projects.add(p) + except (json.JSONDecodeError, OSError): + pass + return projects + async def _poll_commands_loop(self): - """Poll Gateway for commands and write them locally for Extension.""" + """Poll Gateway for commands for ALL local projects. + + Discovers projects from bridge/register/ (written by each AG Extension) + and polls commands for each. Extension-side filtering (project_name check) + ensures each AG window only processes its own commands. + """ while self._running: try: # Skip cycle if rate-limited if not self.remote.is_rate_limited: - commands = await self.remote.apoll_commands(self.project_name) - for cmd in commands: - cmd_id = cmd.get("id", str(int(time.time() * 1000))) - fname = f"{cmd_id}.json" - self.local.write_json("commands", fname, cmd) - logger.info(f"[COLLECTOR] ← Gateway: command {cmd.get('text', '?')[:30]}") + projects = self._discover_local_projects() + for project in projects: + if self.remote.is_rate_limited: + break # Stop mid-cycle if rate-limited + commands = await self.remote.apoll_commands(project) + for cmd in commands: + cmd_id = cmd.get("id", str(int(time.time() * 1000))) + fname = f"{cmd_id}.json" + self.local.write_json("commands", fname, cmd) + logger.info(f"[COLLECTOR] ← Gateway: command [{project}] {cmd.get('text', '?')[:30]}") except Exception as e: logger.error(f"[COLLECTOR] poll_commands error: {e}")