- Create PredictionService for pre-task cost/token estimates - Refresh common predictions on startup - Integrate predictions into LLM telemetry tracker - Add GET /api/telemetry/estimate endpoint - Graceful degradation when no prediction data available - Add unit tests for prediction service Refs #373 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
93 lines
2.9 KiB
TypeScript
93 lines
2.9 KiB
TypeScript
import { Controller, Get, Query, UseGuards, BadRequestException } from "@nestjs/common";
|
|
import { AuthGuard } from "../auth/guards/auth.guard";
|
|
import { PredictionService } from "./prediction.service";
|
|
import {
|
|
TaskType,
|
|
Complexity,
|
|
Provider,
|
|
type PredictionResponse,
|
|
} from "@mosaicstack/telemetry-client";
|
|
|
|
/**
|
|
* Valid values for query parameter validation.
|
|
*/
|
|
const VALID_TASK_TYPES = new Set<string>(Object.values(TaskType));
|
|
const VALID_COMPLEXITIES = new Set<string>(Object.values(Complexity));
|
|
const VALID_PROVIDERS = new Set<string>(Object.values(Provider));
|
|
|
|
/**
|
|
* Response DTO for the estimate endpoint.
|
|
*/
|
|
interface EstimateResponseDto {
|
|
data: PredictionResponse | null;
|
|
}
|
|
|
|
/**
|
|
* Mosaic Telemetry Controller
|
|
*
|
|
* Provides API endpoints for accessing telemetry prediction data.
|
|
* All endpoints require authentication via AuthGuard.
|
|
*
|
|
* This controller is intentionally lightweight - it delegates to PredictionService
|
|
* for the actual prediction logic and returns results directly to the frontend.
|
|
*/
|
|
@Controller("telemetry")
|
|
@UseGuards(AuthGuard)
|
|
export class MosaicTelemetryController {
|
|
constructor(private readonly predictionService: PredictionService) {}
|
|
|
|
/**
|
|
* GET /api/telemetry/estimate
|
|
*
|
|
* Get a cost/token estimate for a given task configuration.
|
|
* Returns prediction data including confidence level, or null if
|
|
* no prediction is available.
|
|
*
|
|
* @param taskType - Task type enum value (e.g. "implementation", "planning")
|
|
* @param model - Model name (e.g. "claude-sonnet-4-5")
|
|
* @param provider - Provider enum value (e.g. "anthropic", "openai")
|
|
* @param complexity - Complexity level (e.g. "low", "medium", "high")
|
|
* @returns Prediction response with estimates and confidence
|
|
*/
|
|
@Get("estimate")
|
|
getEstimate(
|
|
@Query("taskType") taskType: string,
|
|
@Query("model") model: string,
|
|
@Query("provider") provider: string,
|
|
@Query("complexity") complexity: string
|
|
): EstimateResponseDto {
|
|
if (!taskType || !model || !provider || !complexity) {
|
|
throw new BadRequestException(
|
|
"Missing query parameters. Required: taskType, model, provider, complexity"
|
|
);
|
|
}
|
|
|
|
if (!VALID_TASK_TYPES.has(taskType)) {
|
|
throw new BadRequestException(
|
|
`Invalid taskType "${taskType}". Valid values: ${[...VALID_TASK_TYPES].join(", ")}`
|
|
);
|
|
}
|
|
|
|
if (!VALID_PROVIDERS.has(provider)) {
|
|
throw new BadRequestException(
|
|
`Invalid provider "${provider}". Valid values: ${[...VALID_PROVIDERS].join(", ")}`
|
|
);
|
|
}
|
|
|
|
if (!VALID_COMPLEXITIES.has(complexity)) {
|
|
throw new BadRequestException(
|
|
`Invalid complexity "${complexity}". Valid values: ${[...VALID_COMPLEXITIES].join(", ")}`
|
|
);
|
|
}
|
|
|
|
const prediction = this.predictionService.getEstimate(
|
|
taskType as TaskType,
|
|
model,
|
|
provider as Provider,
|
|
complexity as Complexity
|
|
);
|
|
|
|
return { data: prediction };
|
|
}
|
|
}
|