feat(ms22-p2): add agent status endpoints and chat routing (#684)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful

Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #684.
This commit is contained in:
2026-03-05 02:56:36 +00:00
committed by jason.woltje
parent b52c4e7ff9
commit 2f1ee53c8d
6 changed files with 116 additions and 10 deletions

View File

@@ -2,6 +2,7 @@ import {
BadGatewayException,
Injectable,
Logger,
NotFoundException,
ServiceUnavailableException,
} from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
@@ -18,6 +19,13 @@ interface ContainerConnection {
token: string;
}
interface AgentConfig {
name: string;
displayName: string;
personality: string;
primaryModel: string | null;
}
@Injectable()
export class ChatProxyService {
private readonly logger = new Logger(ChatProxyService.name);
@@ -38,21 +46,38 @@ export class ChatProxyService {
async proxyChat(
userId: string,
messages: ChatMessage[],
signal?: AbortSignal
signal?: AbortSignal,
agentName?: string
): Promise<Response> {
const { url: containerUrl, token: gatewayToken } = await this.getContainerConnection(userId);
const model = await this.getPreferredModel(userId);
// Get agent config if specified
let agentConfig: AgentConfig | null = null;
if (agentName) {
agentConfig = await this.getAgentConfig(userId, agentName);
}
const model = agentConfig?.primaryModel ?? (await this.getPreferredModel(userId));
const requestBody: Record<string, unknown> = {
messages,
model,
stream: true,
};
// Add agent config if available
if (agentConfig) {
requestBody.agent = agentConfig.name;
requestBody.agent_personality = agentConfig.personality;
}
const requestInit: RequestInit = {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${gatewayToken}`,
},
body: JSON.stringify({
messages,
model,
stream: true,
}),
body: JSON.stringify(requestBody),
};
if (signal) {
@@ -170,4 +195,32 @@ export class ChatProxyService {
return null;
}
}
private async getAgentConfig(userId: string, agentName: string): Promise<AgentConfig> {
const agent = await this.prisma.userAgent.findUnique({
where: { userId_name: { userId, name: agentName } },
select: {
name: true,
displayName: true,
personality: true,
primaryModel: true,
isActive: true,
},
});
if (!agent) {
throw new NotFoundException(`Agent "${agentName}" not found for user`);
}
if (!agent.isActive) {
throw new NotFoundException(`Agent "${agentName}" is not active`);
}
return {
name: agent.name,
displayName: agent.displayName,
personality: agent.personality,
primaryModel: agent.primaryModel,
};
}
}