chore: consolidate new foundation and archive v1 (#1495)
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
Controller,
|
||||
Post,
|
||||
Body,
|
||||
Logger,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
NotFoundException,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { Throttle } from '@nestjs/throttler';
|
||||
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 { v4 as uuid } from 'uuid';
|
||||
import { ChatRequestDto } from './chat.dto.js';
|
||||
import { ChatRuntimeRouter } from './chat-runtime-router.js';
|
||||
import { ownConversation } from './chat-runtime.js';
|
||||
import type { LegacyRuntimeFailure } from './chat-runtime.js';
|
||||
|
||||
interface ChatResponse {
|
||||
conversationId: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
@Controller('api/chat')
|
||||
@UseGuards(AuthGuard)
|
||||
export class ChatController {
|
||||
private readonly logger = new Logger(ChatController.name);
|
||||
|
||||
constructor(private readonly runtime: ChatRuntimeRouter) {}
|
||||
|
||||
@Post()
|
||||
@Throttle({ default: { limit: 10, ttl: 60_000 } })
|
||||
async chat(
|
||||
@Body() body: ChatRequestDto,
|
||||
@CurrentUser() user: AuthenticatedUserLike,
|
||||
): Promise<ChatResponse> {
|
||||
const conversationId = body.conversationId ?? uuid();
|
||||
const scope = scopeFromUser(user);
|
||||
|
||||
this.logger.debug(`Handling chat request for user=${user.id}, conversation=${conversationId}`);
|
||||
|
||||
// The one exclusive runtime owns execution. In legacy mode this reaches the embedded runtime;
|
||||
// in pi-rpc it fails closed with `runtime_unsupported` before ever touching embedded execution.
|
||||
const result = await this.runtime.completeLegacyRestTurn(
|
||||
ownConversation(conversationId, scope),
|
||||
{ content: body.content },
|
||||
);
|
||||
|
||||
if (result.ok) {
|
||||
return { conversationId, text: result.value.text };
|
||||
}
|
||||
|
||||
throw this.toHttpException(result, conversationId);
|
||||
}
|
||||
|
||||
/** Maps a total {@link LegacyRuntimeFailure} to the fixed browser-safe HTTP surface. */
|
||||
private toHttpException(failure: LegacyRuntimeFailure, conversationId: string): HttpException {
|
||||
switch (failure.code) {
|
||||
case 'conversation_unavailable':
|
||||
return new NotFoundException('Session not found');
|
||||
case 'request_invalid':
|
||||
case 'thinking_level_invalid':
|
||||
return new HttpException('Invalid chat request', HttpStatus.BAD_REQUEST);
|
||||
case 'timeout':
|
||||
return new HttpException('Agent response timed out', HttpStatus.GATEWAY_TIMEOUT);
|
||||
case 'runtime_unsupported':
|
||||
case 'runtime_unavailable':
|
||||
return new HttpException('Agent runtime unavailable', HttpStatus.SERVICE_UNAVAILABLE);
|
||||
default:
|
||||
this.logger.error(`Chat turn failed for conversation=${conversationId}: ${failure.code}`);
|
||||
return new HttpException('Agent processing failed', HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user