redesign fully scaffolded and web login works
This commit is contained in:
@@ -6,18 +6,24 @@ import type { InboundMessage } from '../types/messages.js';
|
||||
import { randomUUID } from 'crypto';
|
||||
|
||||
import type { ProviderConfig } from '../llm/provider.js';
|
||||
import type { SessionRegistry, EventSubscriber, Session } from '../events/index.js';
|
||||
|
||||
export interface WebSocketHandlerConfig {
|
||||
authenticator: Authenticator;
|
||||
providerConfig: ProviderConfig;
|
||||
sessionRegistry: SessionRegistry;
|
||||
eventSubscriber: EventSubscriber;
|
||||
}
|
||||
|
||||
/**
|
||||
* WebSocket channel handler
|
||||
*
|
||||
* Handles WebSocket connections for chat and integrates with the event system
|
||||
* for container-to-client notifications.
|
||||
*/
|
||||
export class WebSocketHandler {
|
||||
private config: WebSocketHandlerConfig;
|
||||
private sessions = new Map<string, AgentHarness>();
|
||||
private harnesses = new Map<string, AgentHarness>();
|
||||
|
||||
constructor(config: WebSocketHandlerConfig) {
|
||||
this.config = config;
|
||||
@@ -94,7 +100,30 @@ export class WebSocketHandler {
|
||||
|
||||
try {
|
||||
await harness.initialize();
|
||||
this.sessions.set(authContext.sessionId, harness);
|
||||
this.harnesses.set(authContext.sessionId, harness);
|
||||
|
||||
// Register session for event system
|
||||
// Container endpoint is derived from the MCP server URL (same container, different port)
|
||||
const containerEventEndpoint = this.getContainerEventEndpoint(authContext.license.mcpServerUrl);
|
||||
|
||||
const session: Session = {
|
||||
userId: authContext.userId,
|
||||
sessionId: authContext.sessionId,
|
||||
socket,
|
||||
channelType: 'websocket',
|
||||
containerEndpoint: containerEventEndpoint,
|
||||
connectedAt: new Date(),
|
||||
};
|
||||
|
||||
this.config.sessionRegistry.register(session);
|
||||
|
||||
// Subscribe to informational events from user's container
|
||||
await this.config.eventSubscriber.onSessionConnect(session);
|
||||
|
||||
logger.info(
|
||||
{ userId: authContext.userId, containerEndpoint: containerEventEndpoint },
|
||||
'Session registered for events'
|
||||
);
|
||||
|
||||
// Send connected message
|
||||
socket.send(
|
||||
@@ -145,11 +174,19 @@ export class WebSocketHandler {
|
||||
// Handle disconnection
|
||||
socket.on('close', async () => {
|
||||
logger.info({ sessionId: authContext.sessionId }, 'WebSocket disconnected');
|
||||
|
||||
// Unregister from event system
|
||||
const removedSession = this.config.sessionRegistry.unregister(authContext.sessionId);
|
||||
if (removedSession) {
|
||||
await this.config.eventSubscriber.onSessionDisconnect(removedSession);
|
||||
}
|
||||
|
||||
// Cleanup harness
|
||||
await harness.cleanup();
|
||||
this.sessions.delete(authContext.sessionId);
|
||||
this.harnesses.delete(authContext.sessionId);
|
||||
});
|
||||
|
||||
socket.on('error', (error) => {
|
||||
socket.on('error', (error: any) => {
|
||||
logger.error({ error, sessionId: authContext.sessionId }, 'WebSocket error');
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -158,4 +195,21 @@ export class WebSocketHandler {
|
||||
await harness.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive the container's XPUB event endpoint from the MCP server URL.
|
||||
*
|
||||
* MCP URL format: http://agent-user-abc123.dexorder-agents.svc.cluster.local:3000
|
||||
* Event endpoint: tcp://agent-user-abc123.dexorder-agents.svc.cluster.local:5570
|
||||
*/
|
||||
private getContainerEventEndpoint(mcpServerUrl: string): string {
|
||||
try {
|
||||
const url = new URL(mcpServerUrl);
|
||||
// Replace protocol and port
|
||||
return `tcp://${url.hostname}:5570`;
|
||||
} catch {
|
||||
// Fallback if URL parsing fails
|
||||
return mcpServerUrl.replace('http://', 'tcp://').replace(':3000', ':5570');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user