66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
import {
|
|
Controller,
|
|
Get,
|
|
HttpException,
|
|
HttpStatus,
|
|
Inject,
|
|
Param,
|
|
UseGuards,
|
|
} from '@nestjs/common';
|
|
import { AuthGuard } from '../auth/auth.guard.js';
|
|
import { CurrentUser } from '../auth/current-user.decorator.js';
|
|
import { scopeFromUser, type AuthenticatedUserLike } from '../auth/session-scope.js';
|
|
import { HarnessAdapterUnavailableError, HarnessRegistry } from './harness.registry.js';
|
|
import { HARNESS_REGISTRY } from './harness.tokens.js';
|
|
import {
|
|
readContextFromScope,
|
|
toHarnessSummary,
|
|
toSafeCatalog,
|
|
type HarnessCatalogDto,
|
|
type HarnessSummaryDto,
|
|
} from './harness.dto.js';
|
|
|
|
/**
|
|
* Generic harness catalog surface. It exposes only harness-neutral, browser-safe
|
|
* fields (identity, capabilities, provider/model catalog) — never executables,
|
|
* native paths, home/cwd, env, or secrets. There is NO provider-probe route here;
|
|
* `/api/providers` and `POST /api/providers/test` are intentionally out of scope.
|
|
*/
|
|
@Controller('api/harnesses')
|
|
@UseGuards(AuthGuard)
|
|
export class HarnessController {
|
|
constructor(@Inject(HARNESS_REGISTRY) private readonly registry: HarnessRegistry) {}
|
|
|
|
@Get()
|
|
async list(@CurrentUser() user: AuthenticatedUserLike): Promise<HarnessSummaryDto[]> {
|
|
const context = readContextFromScope(scopeFromUser(user));
|
|
const summaries: HarnessSummaryDto[] = [];
|
|
for (const adapter of this.registry.list()) {
|
|
summaries.push(toHarnessSummary(await adapter.describe(context)));
|
|
}
|
|
return summaries;
|
|
}
|
|
|
|
@Get(':harnessId/catalog')
|
|
async catalog(
|
|
@CurrentUser() user: AuthenticatedUserLike,
|
|
@Param('harnessId') harnessId: string,
|
|
): Promise<HarnessCatalogDto> {
|
|
const context = readContextFromScope(scopeFromUser(user));
|
|
let adapter;
|
|
try {
|
|
adapter = this.registry.get(harnessId);
|
|
} catch (error) {
|
|
if (error instanceof HarnessAdapterUnavailableError) {
|
|
// Typed failure — NEVER a fallback catalog for an unknown harness id.
|
|
throw new HttpException(
|
|
{ code: error.code, message: error.message, harnessId },
|
|
HttpStatus.NOT_FOUND,
|
|
);
|
|
}
|
|
throw error;
|
|
}
|
|
return toSafeCatalog(await adapter.catalog(context));
|
|
}
|
|
}
|