UNPKG

chrome-devtools-frontend

Version:
118 lines (103 loc) 3.62 kB
// Copyright 2026 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. export class GreenDevAgentGeminiCliSocketClient { #websocket: WebSocket; #sessionId?: string; #activeMessage = ''; #messageLog: string[] = []; #promptResolve: ((response: string) => void)|null = null; sessionReady: Promise<void>; #sessionReadyResolve: ((value: void|PromiseLike<void>) => void)|null = null; constructor() { this.sessionReady = new Promise(resolve => { this.#sessionReadyResolve = resolve; }); this.#websocket = new WebSocket('ws://localhost:6655'); this.#websocket.onopen = this.#onOpen.bind(this); this.#websocket.onmessage = this.#onMessage.bind(this); this.#websocket.onclose = this.#onClose.bind(this); this.#websocket.onerror = this.#onError.bind(this); } #onOpen(): void { console.warn('WebSocket connected.'); this.#websocket.send( JSON.stringify({jsonrpc: '2.0', method: 'session/new', params: {cwd: '.', mcpServers: []}, id: 14})); } #onMessage(event: MessageEvent): void { this.#messageLog.push(event.data); try { const data = JSON.parse(event.data); if (data?.result?.sessionId && !this.#sessionId) { this.#sessionId = data.result.sessionId; console.warn(`Successfully created new session with ID: ${this.#sessionId}`); if (this.#sessionReadyResolve) { this.#sessionReadyResolve(); this.#sessionReadyResolve = null; } } const update = data?.params?.update; if (update?.sessionUpdate === 'agent_message_chunk') { this.#activeMessage += update.content?.text || ''; } if (data?.result?.stopReason) { if (this.#activeMessage) { console.warn(this.#activeMessage); } console.warn(`Stop Reason: ${data.result.stopReason}`, this.#messageLog); if (this.#promptResolve) { this.#promptResolve(this.#activeMessage); this.#promptResolve = null; } this.#activeMessage = ''; this.#messageLog = []; } else if (data?.method === 'session/request_permission') { // TODO(finnur): Needs augmenting once I turn off YOLO in the bridge. this.#websocket.send(JSON.stringify({ jsonrpc: '2.0', id: data.id, result: { outcome: { selected: { optionId: 'proceed_always', }, }, }, })); } } catch (e) { // Log the raw data if it's not valid JSON. console.error('Failed to parse WebSocket message or process data:', event.data, e); } } #onClose(): void { console.warn('WebSocket disconnected.'); } #onError(error: Event): void { console.error('WebSocket error:', error); } sendPrompt(promptText: string): Promise<string> { return new Promise((resolve, reject) => { if (this.#promptResolve) { reject(new Error('Another prompt is already in progress.')); return; } if (!this.#sessionId) { reject(new Error('Cannot send prompt without a session ID.')); return; } this.#promptResolve = resolve; console.warn(`Sending prompt: "${promptText}"`); console.warn('Thinking...'); this.#websocket.send(JSON.stringify({ jsonrpc: '2.0', method: 'session/prompt', params: { prompt: [{type: 'text', text: promptText}], sessionId: this.#sessionId, }, id: 15, })); }); } }