Skip to content

Commit 4d1cc38

Browse files
committed
Implement backend session creation for Matrix rooms
MAJOR ARCHITECTURAL IMPROVEMENT: Matrix sessions now create real backend sessions Key Changes: - Added createMappingWithBackendSession() to SessionMappingService - Matrix rooms now call startAgent API to create actual backend sessions - Session mappings use real backend session IDs instead of generated ones - Updated MatrixService.createAISession() to use backend session creation - Updated MatrixService.ensureSessionMapping() to create backend sessions - Added fallback to old method if backend session creation fails Benefits: - Matrix sessions are now fully compatible with backend APIs - No more 'Failed to read session: Session not found' errors - Session token counting works correctly for Matrix sessions - SSE streams work properly with Matrix sessions - Full session persistence and reload functionality - Eliminates the need for frontend-only workarounds This resolves the fundamental issue where Matrix sessions existed only in the frontend but had no corresponding backend session data. Now Matrix collaborative sessions are treated as first-class citizens with proper backend integration.
1 parent 025aefc commit 4d1cc38

File tree

2 files changed

+93
-16
lines changed

2 files changed

+93
-16
lines changed

ui/desktop/src/services/MatrixService.ts

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -784,13 +784,13 @@ export class MatrixService extends EventEmitter {
784784
// We'll use regular message types instead of custom ones
785785
});
786786

787-
// Create session mapping for this Matrix room
787+
// Create session mapping with backend session for this Matrix room
788788
const participants = [this.config.userId!, ...inviteUserIds];
789-
const mapping = sessionMappingService.createMapping(room.room_id, participants, name);
789+
const mapping = await sessionMappingService.createMappingWithBackendSession(room.room_id, participants, name);
790790

791-
console.log('📋 Created AI session with mapping:', {
791+
console.log('📋 Created AI session with backend mapping:', {
792792
matrixRoomId: room.room_id,
793-
gooseSessionId: mapping.gooseSessionId,
793+
backendSessionId: mapping.gooseSessionId,
794794
participants: participants.length,
795795
name,
796796
});
@@ -826,7 +826,7 @@ export class MatrixService extends EventEmitter {
826826
console.log('✅ Already joined room:', roomId);
827827

828828
// Still ensure session mapping exists for this room
829-
this.ensureSessionMapping(roomId, existingRoom);
829+
await this.ensureSessionMapping(roomId, existingRoom);
830830
return;
831831
}
832832

@@ -841,7 +841,7 @@ export class MatrixService extends EventEmitter {
841841
// Get the room after joining to create session mapping
842842
const joinedRoom = this.client.getRoom(roomId);
843843
if (joinedRoom) {
844-
this.ensureSessionMapping(roomId, joinedRoom);
844+
await this.ensureSessionMapping(roomId, joinedRoom);
845845
}
846846

847847
// Emit join event
@@ -880,7 +880,7 @@ export class MatrixService extends EventEmitter {
880880
/**
881881
* Ensure a session mapping exists for a Matrix room
882882
*/
883-
private ensureSessionMapping(roomId: string, room: any): void {
883+
private async ensureSessionMapping(roomId: string, room: any): Promise<void> {
884884
// Check if mapping already exists
885885
const existingMapping = sessionMappingService.getMapping(roomId);
886886
if (existingMapping) {
@@ -892,18 +892,30 @@ export class MatrixService extends EventEmitter {
892892
return;
893893
}
894894

895-
// Create new mapping if none exists
895+
// Create new mapping with backend session if none exists
896896
const participants = room.getMembers().map((member: any) => member.userId);
897897
const roomName = room.name || `Matrix Room ${roomId.substring(1, 8)}`;
898898

899-
const mapping = sessionMappingService.createMapping(roomId, participants, roomName);
900-
901-
console.log('📋 Created session mapping for joined room:', {
902-
matrixRoomId: roomId,
903-
gooseSessionId: mapping.gooseSessionId,
904-
participants: participants.length,
905-
roomName,
906-
});
899+
try {
900+
const mapping = await sessionMappingService.createMappingWithBackendSession(roomId, participants, roomName);
901+
902+
console.log('📋 Created backend session mapping for joined room:', {
903+
matrixRoomId: roomId,
904+
backendSessionId: mapping.gooseSessionId,
905+
participants: participants.length,
906+
roomName,
907+
});
908+
} catch (error) {
909+
console.error('📋 Failed to create backend session mapping for joined room:', error);
910+
// Fallback to regular mapping if backend session creation fails
911+
const mapping = sessionMappingService.createMapping(roomId, participants, roomName);
912+
console.log('📋 Created fallback mapping for joined room:', {
913+
matrixRoomId: roomId,
914+
gooseSessionId: mapping.gooseSessionId,
915+
participants: participants.length,
916+
roomName,
917+
});
918+
}
907919
}
908920

909921
/**

ui/desktop/src/services/SessionMappingService.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export class SessionMappingService {
3434

3535
/**
3636
* Generate a new Goose session ID in the expected format
37+
* Note: This is now deprecated in favor of using actual backend session IDs
3738
*/
3839
private generateGooseSessionId(): string {
3940
const now = new Date();
@@ -71,6 +72,70 @@ export class SessionMappingService {
7172
return mapping;
7273
}
7374

75+
/**
76+
* Create a new session mapping with a backend session ID
77+
* This creates a real backend session for the Matrix room
78+
*/
79+
public async createMappingWithBackendSession(
80+
matrixRoomId: string,
81+
participants: string[] = [],
82+
title?: string
83+
): Promise<SessionMapping> {
84+
try {
85+
// Import startAgent dynamically to avoid circular dependencies
86+
const { startAgent } = await import('../api');
87+
88+
// Create a backend session for this Matrix room
89+
const agentResponse = await startAgent({
90+
body: {
91+
working_dir: window.appConfig.get('GOOSE_WORKING_DIR') as string,
92+
// Create a recipe for Matrix collaboration
93+
recipe: {
94+
title: title || `Matrix Collaboration: ${matrixRoomId.substring(1, 8)}`,
95+
description: `Collaborative AI session for Matrix room ${matrixRoomId}`,
96+
instructions: [
97+
'You are participating in a collaborative AI session through Matrix.',
98+
'Multiple users may be participating in this conversation.',
99+
'Be helpful and collaborative in your responses.',
100+
],
101+
},
102+
},
103+
throwOnError: true,
104+
});
105+
106+
const backendSession = agentResponse.data;
107+
if (!backendSession?.id) {
108+
throw new Error('Failed to create backend session');
109+
}
110+
111+
const now = Date.now();
112+
const mapping: SessionMapping = {
113+
matrixRoomId,
114+
gooseSessionId: backendSession.id, // Use the actual backend session ID
115+
createdAt: now,
116+
lastUsed: now,
117+
participants,
118+
title,
119+
};
120+
121+
this.mappings.set(matrixRoomId, mapping);
122+
this.saveMappingsToStorage();
123+
124+
console.log('📋 SessionMappingService: Created mapping with backend session:', {
125+
matrixRoomId,
126+
backendSessionId: backendSession.id,
127+
participants: participants.length,
128+
title,
129+
});
130+
131+
return mapping;
132+
} catch (error) {
133+
console.error('📋 SessionMappingService: Failed to create backend session for Matrix room:', error);
134+
// Fallback to the old method if backend session creation fails
135+
return this.createMapping(matrixRoomId, participants, title);
136+
}
137+
}
138+
74139
/**
75140
* Get the Goose session ID for a Matrix room ID
76141
*/

0 commit comments

Comments
 (0)