| 97 | (endpoint) => new WebSocketUpstreamConnection(endpoint, logService); |
| 98 | |
| 99 | class WebSocketUpstreamConnection extends Disposable implements IUpstreamConnection { |
| 100 | private readonly _onFrame = this._register(new Emitter<string>()); |
| 101 | readonly onFrame: Event<string> = this._onFrame.event; |
| 102 | |
| 103 | private readonly _onClose = this._register(new Emitter<void>()); |
| 104 | readonly onClose: Event<void> = this._onClose.event; |
| 105 | |
| 106 | private _ws: wsTypes.WebSocket | undefined; |
| 107 | private _connectPromise: Promise<void> | undefined; |
| 108 | private _closeFired = false; |
| 109 | |
| 110 | constructor( |
| 111 | private readonly _endpoint: IAgentHostUpstreamEndpoint, |
| 112 | private readonly _logService: ILogService, |
| 113 | ) { |
| 114 | super(); |
| 115 | } |
| 116 | |
| 117 | connect(): Promise<void> { |
| 118 | if (this._store.isDisposed) { |
| 119 | return Promise.reject(new Error('UpstreamConnection is disposed')); |
| 120 | } |
| 121 | return this._connectPromise ??= this._doConnect(); |
| 122 | } |
| 123 | |
| 124 | private async _doConnect(): Promise<void> { |
| 125 | const ws = await loadWs(); |
| 126 | const url = this._buildUrl(); |
| 127 | const wsOptions = await this._buildWsOptions(); |
| 128 | |
| 129 | this._logService.info(`[AgentHostChannel] Opening upstream to ${this._endpoint.socketPath ?? url}`); |
| 130 | const socket = new ws.WebSocket(url, wsOptions); |
| 131 | this._ws = socket; |
| 132 | |
| 133 | return new Promise<void>((resolve, reject) => { |
| 134 | const onOpen = () => { |
| 135 | cleanup(); |
| 136 | this._logService.trace('[AgentHostChannel] Upstream open'); |
| 137 | socket.on('message', (data: Buffer | string) => { |
| 138 | const text = typeof data === 'string' ? data : data.toString('utf-8'); |
| 139 | this._onFrame.fire(text); |
| 140 | }); |
| 141 | socket.on('close', () => this._fireClose()); |
| 142 | socket.on('error', err => { |
| 143 | this._logService.warn('[AgentHostChannel] Upstream error', err); |
| 144 | this._fireClose(); |
| 145 | }); |
| 146 | resolve(); |
| 147 | }; |
| 148 | |
| 149 | const onError = (err: Error) => { |
| 150 | cleanup(); |
| 151 | this._logService.warn('[AgentHostChannel] Upstream connection failed', err); |
| 152 | this._fireClose(); |
| 153 | reject(err); |
| 154 | }; |
| 155 | |
| 156 | const onClose = () => { |
nothing calls this directly
no test coverage detected
searching dependent graphs…