From 5d936d58a0efaf99f1211607226026f9521a772c Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Fri, 13 Mar 2026 08:00:57 -0500 Subject: [PATCH] fix: add missing @Inject() decorators and fix coord workspace root detection - Add @Inject() to all gateway constructor params (required without emitDecoratorMetadata) - AgentService: ProviderService, CoordService - RoutingService: ProviderService - ProvidersController: ProviderService, RoutingService - SessionsController: AgentService - Fix coord controller ALLOWED_ROOTS to walk up to monorepo root (pnpm-workspace.yaml) - Gateway now boots and serves all routes correctly Co-Authored-By: Claude Opus 4.6 --- apps/gateway/src/agent/agent.service.ts | 4 ++-- .../gateway/src/agent/providers.controller.ts | 6 +++--- apps/gateway/src/agent/routing.service.ts | 4 ++-- apps/gateway/src/agent/sessions.controller.ts | 3 ++- apps/gateway/src/coord/coord.controller.ts | 20 ++++++++++++++++++- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/apps/gateway/src/agent/agent.service.ts b/apps/gateway/src/agent/agent.service.ts index 0f948b5..9fe14f3 100644 --- a/apps/gateway/src/agent/agent.service.ts +++ b/apps/gateway/src/agent/agent.service.ts @@ -40,9 +40,9 @@ export class AgentService implements OnModuleDestroy { private readonly customTools: ToolDefinition[]; constructor( - private readonly providerService: ProviderService, + @Inject(ProviderService) private readonly providerService: ProviderService, @Inject(BRAIN) private readonly brain: Brain, - private readonly coordService: CoordService, + @Inject(CoordService) private readonly coordService: CoordService, ) { this.customTools = [...createBrainTools(brain), ...createCoordTools(coordService)]; this.logger.log(`Registered ${this.customTools.length} custom tools`); diff --git a/apps/gateway/src/agent/providers.controller.ts b/apps/gateway/src/agent/providers.controller.ts index 1c8a004..9a78a29 100644 --- a/apps/gateway/src/agent/providers.controller.ts +++ b/apps/gateway/src/agent/providers.controller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common'; +import { Body, Controller, Get, Inject, Post, UseGuards } from '@nestjs/common'; import type { RoutingCriteria } from '@mosaic/types'; import { AuthGuard } from '../auth/auth.guard.js'; import { ProviderService } from './provider.service.js'; @@ -8,8 +8,8 @@ import { RoutingService } from './routing.service.js'; @UseGuards(AuthGuard) export class ProvidersController { constructor( - private readonly providerService: ProviderService, - private readonly routingService: RoutingService, + @Inject(ProviderService) private readonly providerService: ProviderService, + @Inject(RoutingService) private readonly routingService: RoutingService, ) {} @Get() diff --git a/apps/gateway/src/agent/routing.service.ts b/apps/gateway/src/agent/routing.service.ts index 5902f71..96f8a19 100644 --- a/apps/gateway/src/agent/routing.service.ts +++ b/apps/gateway/src/agent/routing.service.ts @@ -1,4 +1,4 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { Inject, Injectable, Logger } from '@nestjs/common'; import type { ModelInfo } from '@mosaic/types'; import type { RoutingCriteria, RoutingResult, CostTier } from '@mosaic/types'; import { ProviderService } from './provider.service.js'; @@ -14,7 +14,7 @@ const COST_TIER_THRESHOLDS: Record = { export class RoutingService { private readonly logger = new Logger(RoutingService.name); - constructor(private readonly providerService: ProviderService) {} + constructor(@Inject(ProviderService) private readonly providerService: ProviderService) {} /** * Select the best available model for the given criteria. diff --git a/apps/gateway/src/agent/sessions.controller.ts b/apps/gateway/src/agent/sessions.controller.ts index 4ac8579..be6fd37 100644 --- a/apps/gateway/src/agent/sessions.controller.ts +++ b/apps/gateway/src/agent/sessions.controller.ts @@ -4,6 +4,7 @@ import { Get, HttpCode, HttpStatus, + Inject, NotFoundException, Param, UseGuards, @@ -14,7 +15,7 @@ import { AgentService } from './agent.service.js'; @Controller('api/sessions') @UseGuards(AuthGuard) export class SessionsController { - constructor(private readonly agentService: AgentService) {} + constructor(@Inject(AgentService) private readonly agentService: AgentService) {} @Get() list() { diff --git a/apps/gateway/src/coord/coord.controller.ts b/apps/gateway/src/coord/coord.controller.ts index f983d25..e8ba396 100644 --- a/apps/gateway/src/coord/coord.controller.ts +++ b/apps/gateway/src/coord/coord.controller.ts @@ -8,12 +8,30 @@ import { Query, UseGuards, } from '@nestjs/common'; +import fs from 'node:fs'; import path from 'node:path'; import { AuthGuard } from '../auth/auth.guard.js'; import { CoordService } from './coord.service.js'; +/** Walk up from cwd to find the monorepo root (has pnpm-workspace.yaml). */ +function findMonorepoRoot(start: string): string { + let dir = start; + for (let i = 0; i < 5; i++) { + try { + fs.accessSync(path.join(dir, 'pnpm-workspace.yaml')); + return dir; + } catch { + const parent = path.dirname(dir); + if (parent === dir) break; + dir = parent; + } + } + return start; +} + /** Only paths under these roots are allowed for coord queries. */ -const ALLOWED_ROOTS = [process.cwd()]; +const WORKSPACE_ROOT = process.env['MOSAIC_WORKSPACE_ROOT'] ?? findMonorepoRoot(process.cwd()); +const ALLOWED_ROOTS = [process.cwd(), WORKSPACE_ROOT]; function resolveAndValidatePath(raw: string | undefined): string { const resolved = path.resolve(raw ?? process.cwd());