Skip to content

Commit 469cc40

Browse files
committed
New tab opened for each /responses API call
1 parent 7f5e4cd commit 469cc40

File tree

1 file changed

+69
-9
lines changed

1 file changed

+69
-9
lines changed

eval-server/nodejs/src/api-server.js

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -375,22 +375,34 @@ class APIServer {
375375
}
376376
});
377377

378-
// Find a connected and ready client
379-
const readyClient = this.findReadyClient();
380-
if (!readyClient) {
381-
throw new Error('No DevTools client is connected and ready. Please ensure a DevTools client is connected to the evaluation server.');
382-
}
378+
// Find a client with existing tabs (not the dummy client)
379+
const baseClientId = this.findClientWithTabs();
380+
381+
// Open a new tab for this request
382+
logger.info('Opening new tab for responses request', { baseClientId });
383+
const tabResult = await this.evaluationServer.openTab(baseClientId, {
384+
url: 'about:blank',
385+
background: false
386+
});
387+
388+
logger.info('Tab opened successfully', {
389+
tabId: tabResult.tabId,
390+
compositeClientId: tabResult.compositeClientId
391+
});
392+
393+
// Wait for the new tab's DevTools to connect
394+
const tabClient = await this.waitForClientConnection(tabResult.compositeClientId);
383395

384396
// Create a dynamic evaluation for this request
385397
const evaluation = this.createDynamicEvaluationNested(requestBody.input, nestedModelConfig);
386398

387-
// Execute the evaluation on the DevTools client
388-
logger.info('Executing evaluation on DevTools client', {
389-
clientId: readyClient.clientId,
399+
// Execute the evaluation on the new tab's DevTools client
400+
logger.info('Executing evaluation on new tab', {
401+
compositeClientId: tabResult.compositeClientId,
390402
evaluationId: evaluation.id
391403
});
392404

393-
const result = await this.evaluationServer.executeEvaluation(readyClient, evaluation);
405+
const result = await this.evaluationServer.executeEvaluation(tabClient, evaluation);
394406

395407
// Debug: log the result structure
396408
logger.debug('executeEvaluation result:', result);
@@ -465,6 +477,54 @@ class APIServer {
465477
return null;
466478
}
467479

480+
/**
481+
* Find a client that has existing tabs (not the dummy client)
482+
* @returns {string} Base client ID
483+
*/
484+
findClientWithTabs() {
485+
const clients = this.evaluationServer.getClientManager().getAllClients();
486+
487+
for (const client of clients) {
488+
const tabs = this.evaluationServer.getClientManager().getClientTabs(client.id);
489+
if (tabs.length > 0) {
490+
logger.info('Found client with tabs', { clientId: client.id, tabCount: tabs.length });
491+
return client.id;
492+
}
493+
}
494+
495+
throw new Error('No client with existing tabs found. Please ensure at least one DevTools client with a tab is connected.');
496+
}
497+
498+
/**
499+
* Wait for a client connection to be established and ready
500+
* @param {string} compositeClientId - Composite client ID (baseClientId:tabId)
501+
* @param {number} maxWaitMs - Maximum time to wait in milliseconds
502+
* @returns {Promise<Object>} Connection object
503+
*/
504+
async waitForClientConnection(compositeClientId, maxWaitMs = 10000) {
505+
const startTime = Date.now();
506+
const pollInterval = 500; // Check every 500ms
507+
508+
logger.info('Waiting for client connection', { compositeClientId, maxWaitMs });
509+
510+
while (Date.now() - startTime < maxWaitMs) {
511+
const connection = this.evaluationServer.connectedClients.get(compositeClientId);
512+
513+
if (connection && connection.ready) {
514+
logger.info('Client connection established and ready', {
515+
compositeClientId,
516+
waitedMs: Date.now() - startTime
517+
});
518+
return connection;
519+
}
520+
521+
// Wait before next check
522+
await new Promise(resolve => setTimeout(resolve, pollInterval));
523+
}
524+
525+
throw new Error(`Timeout waiting for client connection: ${compositeClientId}. Tab may not have connected to eval-server.`);
526+
}
527+
468528
/**
469529
* Create a dynamic evaluation object with nested model configuration
470530
* @param {string} input - Input message for the evaluation

0 commit comments

Comments
 (0)