Assist patch canvas (#3265)

* add agent info to assist and tracker

* removed AGENTS_CONNECTED event
This commit is contained in:
Andrey Babushkin 2025-04-03 18:22:08 +02:00 committed by GitHub
parent a9097270af
commit b0e7054f89
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 35 additions and 60 deletions

View file

@ -23,6 +23,7 @@ EVENTS_DEFINITION.emit = {
NO_AGENTS: "NO_AGENT", NO_AGENTS: "NO_AGENT",
AGENT_DISCONNECT: "AGENT_DISCONNECTED", AGENT_DISCONNECT: "AGENT_DISCONNECTED",
AGENTS_CONNECTED: "AGENTS_CONNECTED", AGENTS_CONNECTED: "AGENTS_CONNECTED",
AGENTS_INFO_CONNECTED: "AGENTS_INFO_CONNECTED",
NO_SESSIONS: "SESSION_DISCONNECTED", NO_SESSIONS: "SESSION_DISCONNECTED",
SESSION_ALREADY_CONNECTED: "SESSION_ALREADY_CONNECTED", SESSION_ALREADY_CONNECTED: "SESSION_ALREADY_CONNECTED",
SESSION_RECONNECTED: "SESSION_RECONNECTED", SESSION_RECONNECTED: "SESSION_RECONNECTED",

View file

@ -42,7 +42,7 @@ const findSessionSocketId = async (io, roomId, tabId) => {
}; };
async function getRoomData(io, roomID) { async function getRoomData(io, roomID) {
let tabsCount = 0, agentsCount = 0, tabIDs = [], agentIDs = [], config = null; let tabsCount = 0, agentsCount = 0, tabIDs = [], agentIDs = [], config = null, agentInfos = [];
const connected_sockets = await io.in(roomID).fetchSockets(); const connected_sockets = await io.in(roomID).fetchSockets();
if (connected_sockets.length > 0) { if (connected_sockets.length > 0) {
for (let socket of connected_sockets) { for (let socket of connected_sockets) {
@ -52,6 +52,7 @@ async function getRoomData(io, roomID) {
} else { } else {
agentsCount++; agentsCount++;
agentIDs.push(socket.id); agentIDs.push(socket.id);
agentInfos.push({ ...socket.handshake.query.agentInfo, socketId: socket.id });
if (socket.handshake.query.config !== undefined) { if (socket.handshake.query.config !== undefined) {
config = socket.handshake.query.config; config = socket.handshake.query.config;
} }
@ -60,8 +61,10 @@ async function getRoomData(io, roomID) {
} else { } else {
tabsCount = -1; tabsCount = -1;
agentsCount = -1; agentsCount = -1;
agentInfos = [];
agentIDs = [];
} }
return {tabsCount, agentsCount, tabIDs, agentIDs, config}; return {tabsCount, agentsCount, tabIDs, agentIDs, config, agentInfos};
} }
function processNewSocket(socket) { function processNewSocket(socket) {
@ -81,7 +84,7 @@ async function onConnect(socket) {
IncreaseOnlineConnections(socket.handshake.query.identity); IncreaseOnlineConnections(socket.handshake.query.identity);
const io = getServer(); const io = getServer();
const {tabsCount, agentsCount, tabIDs, agentIDs, config} = await getRoomData(io, socket.handshake.query.roomId); const {tabsCount, agentsCount, tabIDs, agentInfos, agentIDs, config} = await getRoomData(io, socket.handshake.query.roomId);
if (socket.handshake.query.identity === IDENTITIES.session) { if (socket.handshake.query.identity === IDENTITIES.session) {
// Check if session with the same tabID already connected, if so, refuse new connexion // Check if session with the same tabID already connected, if so, refuse new connexion
@ -105,6 +108,7 @@ async function onConnect(socket) {
logger.debug(`notifying new session about agent-existence`); logger.debug(`notifying new session about agent-existence`);
io.to(socket.id).emit(EVENTS_DEFINITION.emit.WEBRTC_CONFIG, config); io.to(socket.id).emit(EVENTS_DEFINITION.emit.WEBRTC_CONFIG, config);
io.to(socket.id).emit(EVENTS_DEFINITION.emit.AGENTS_CONNECTED, agentIDs); io.to(socket.id).emit(EVENTS_DEFINITION.emit.AGENTS_CONNECTED, agentIDs);
io.to(socket.id).emit(EVENTS_DEFINITION.emit.AGENTS_INFO_CONNECTED, agentInfos);
socket.to(socket.handshake.query.roomId).emit(EVENTS_DEFINITION.emit.SESSION_RECONNECTED, socket.id); socket.to(socket.handshake.query.roomId).emit(EVENTS_DEFINITION.emit.SESSION_RECONNECTED, socket.id);
} }
} else if (tabsCount <= 0) { } else if (tabsCount <= 0) {

View file

@ -348,7 +348,7 @@ export default class AssistManager {
); );
this.canvasReceiver = new CanvasReceiver( this.canvasReceiver = new CanvasReceiver(
this.peerID, this.peerID,
this.config, this.getIceServers(),
this.getNode, this.getNode,
{ {
...this.session.agentInfo, ...this.session.agentInfo,

View file

@ -28,7 +28,7 @@ export default class CanvasReceiver {
// sendSignal for sending signals (offer/answer/ICE) // sendSignal for sending signals (offer/answer/ICE)
constructor( constructor(
private readonly peerIdPrefix: string, private readonly peerIdPrefix: string,
private readonly config: RTCIceServer[] | null, private readonly config: RTCIceServer[],
private readonly getNode: MessageManager['getNode'], private readonly getNode: MessageManager['getNode'],
private readonly agentInfo: Record<string, any>, private readonly agentInfo: Record<string, any>,
private readonly socket: Socket, private readonly socket: Socket,
@ -66,9 +66,7 @@ export default class CanvasReceiver {
id: string, id: string,
): Promise<void> { ): Promise<void> {
const pc = new RTCPeerConnection({ const pc = new RTCPeerConnection({
iceServers: this.config iceServers: this.config,
? this.config
: [{ urls: 'stun:stun.l.google.com:19302' }],
}); });
// Save the connection // Save the connection
@ -177,44 +175,6 @@ function spawnVideo(stream: MediaStream, node: VElement) {
return videoEl; return videoEl;
} }
function spawnDebugVideo(stream: MediaStream, node: VElement) {
const video = document.createElement('video');
video.id = 'canvas-or-testing';
video.style.border = '1px solid red';
video.setAttribute('autoplay', 'true');
video.setAttribute('muted', 'true');
video.setAttribute('playsinline', 'true');
video.setAttribute('crossorigin', 'anonymous');
const coords = node.node.getBoundingClientRect();
Object.assign(video.style, {
position: 'absolute',
left: `${coords.left}px`,
top: `${coords.top}px`,
width: `${coords.width}px`,
height: `${coords.height}px`,
});
video.width = coords.width;
video.height = coords.height;
video.srcObject = stream;
document.body.appendChild(video);
video
.play()
.then(() => {
console.debug('started streaming canvas');
})
.catch((e) => {
console.error(e);
const waiter = () => {
void video.play();
document.removeEventListener('click', waiter);
};
document.addEventListener('click', waiter);
});
}
function checkId(id: string, cId: string): boolean { function checkId(id: string, cId: string): boolean {
return id.includes(cId); return id.includes(cId);
} }

View file

@ -26,6 +26,7 @@ interface AgentInfo {
name: string; name: string;
peerId: string; peerId: string;
query: string; query: string;
socketId?: string;
} }
export interface Options { export interface Options {
@ -436,11 +437,11 @@ export default class Assist {
} }
}); });
socket.on("AGENTS_CONNECTED", (ids: string[]) => { socket.on("AGENTS_INFO_CONNECTED", (agentsInfo: AgentInfo[]) => {
this.cleanCanvasConnections(); this.cleanCanvasConnections();
ids.forEach((id) => { agentsInfo.forEach((agentInfo) => {
const agentInfo = this.agents[id]?.agentInfo; if (!agentInfo.socketId) return;
this.agents[id] = { this.agents[agentInfo.socketId] = {
agentInfo, agentInfo,
onDisconnect: this.options.onAgentConnect?.(agentInfo), onDisconnect: this.options.onAgentConnect?.(agentInfo),
}; };
@ -448,6 +449,7 @@ export default class Assist {
if (this.app.active()) { if (this.app.active()) {
this.assistDemandedRestart = true; this.assistDemandedRestart = true;
this.app.stop(); this.app.stop();
this.app.clearBuffers();
this.app.waitStatus(0).then(() => { this.app.waitStatus(0).then(() => {
this.app.allowAppStart(); this.app.allowAppStart();
setTimeout(() => { setTimeout(() => {
@ -457,7 +459,7 @@ export default class Assist {
this.assistDemandedRestart = false; this.assistDemandedRestart = false;
}) })
.then(() => { .then(() => {
this.remoteControl?.reconnect(ids); this.remoteControl?.reconnect(Object.keys(this.agents));
}) })
.catch((e) => app.debug.error(e)); .catch((e) => app.debug.error(e));
}, 100); }, 100);
@ -522,6 +524,13 @@ export default class Assist {
} catch (e) { } catch (e) {
app.debug.error("Error adding ICE candidate", e); app.debug.error("Error adding ICE candidate", e);
} }
} else {
this.iceCandidatesBuffer.set(
data.id,
this.iceCandidatesBuffer
.get(data.id)
?.concat([data.candidate]) || [data.candidate]
);
} }
} }
); );
@ -889,6 +898,7 @@ export default class Assist {
iceServers: this.config, iceServers: this.config,
}); });
this.setupPeerListeners(uniqueId); this.setupPeerListeners(uniqueId);
this.applyBufferedIceCandidates(uniqueId);
stream.getTracks().forEach((track) => { stream.getTracks().forEach((track) => {
this.canvasPeers[uniqueId]?.addTrack(track, stream); this.canvasPeers[uniqueId]?.addTrack(track, stream);