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 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 08:00:57 -05:00
parent 8da2759fec
commit 5d936d58a0
5 changed files with 28 additions and 9 deletions

View File

@@ -40,9 +40,9 @@ export class AgentService implements OnModuleDestroy {
private readonly customTools: ToolDefinition[]; private readonly customTools: ToolDefinition[];
constructor( constructor(
private readonly providerService: ProviderService, @Inject(ProviderService) private readonly providerService: ProviderService,
@Inject(BRAIN) private readonly brain: Brain, @Inject(BRAIN) private readonly brain: Brain,
private readonly coordService: CoordService, @Inject(CoordService) private readonly coordService: CoordService,
) { ) {
this.customTools = [...createBrainTools(brain), ...createCoordTools(coordService)]; this.customTools = [...createBrainTools(brain), ...createCoordTools(coordService)];
this.logger.log(`Registered ${this.customTools.length} custom tools`); this.logger.log(`Registered ${this.customTools.length} custom tools`);

View File

@@ -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 type { RoutingCriteria } from '@mosaic/types';
import { AuthGuard } from '../auth/auth.guard.js'; import { AuthGuard } from '../auth/auth.guard.js';
import { ProviderService } from './provider.service.js'; import { ProviderService } from './provider.service.js';
@@ -8,8 +8,8 @@ import { RoutingService } from './routing.service.js';
@UseGuards(AuthGuard) @UseGuards(AuthGuard)
export class ProvidersController { export class ProvidersController {
constructor( constructor(
private readonly providerService: ProviderService, @Inject(ProviderService) private readonly providerService: ProviderService,
private readonly routingService: RoutingService, @Inject(RoutingService) private readonly routingService: RoutingService,
) {} ) {}
@Get() @Get()

View File

@@ -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 { ModelInfo } from '@mosaic/types';
import type { RoutingCriteria, RoutingResult, CostTier } from '@mosaic/types'; import type { RoutingCriteria, RoutingResult, CostTier } from '@mosaic/types';
import { ProviderService } from './provider.service.js'; import { ProviderService } from './provider.service.js';
@@ -14,7 +14,7 @@ const COST_TIER_THRESHOLDS: Record<CostTier, { maxInput: number }> = {
export class RoutingService { export class RoutingService {
private readonly logger = new Logger(RoutingService.name); 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. * Select the best available model for the given criteria.

View File

@@ -4,6 +4,7 @@ import {
Get, Get,
HttpCode, HttpCode,
HttpStatus, HttpStatus,
Inject,
NotFoundException, NotFoundException,
Param, Param,
UseGuards, UseGuards,
@@ -14,7 +15,7 @@ import { AgentService } from './agent.service.js';
@Controller('api/sessions') @Controller('api/sessions')
@UseGuards(AuthGuard) @UseGuards(AuthGuard)
export class SessionsController { export class SessionsController {
constructor(private readonly agentService: AgentService) {} constructor(@Inject(AgentService) private readonly agentService: AgentService) {}
@Get() @Get()
list() { list() {

View File

@@ -8,12 +8,30 @@ import {
Query, Query,
UseGuards, UseGuards,
} from '@nestjs/common'; } from '@nestjs/common';
import fs from 'node:fs';
import path from 'node:path'; import path from 'node:path';
import { AuthGuard } from '../auth/auth.guard.js'; import { AuthGuard } from '../auth/auth.guard.js';
import { CoordService } from './coord.service.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. */ /** 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 { function resolveAndValidatePath(raw: string | undefined): string {
const resolved = path.resolve(raw ?? process.cwd()); const resolved = path.resolve(raw ?? process.cwd());