()
| 378 | |
| 379 | // ── 6. Wire callbacks (extracted so transport-rebuild can re-wire) ────── |
| 380 | function wireTransportCallbacks(): void { |
| 381 | transport.setOnConnect(() => { |
| 382 | clearTimeout(connectDeadline) |
| 383 | logForDebugging('[remote-bridge] v2 transport connected') |
| 384 | logForDiagnosticsNoPII('info', 'bridge_repl_v2_transport_connected') |
| 385 | logEvent('tengu_bridge_repl_ws_connected', { |
| 386 | v2: true, |
| 387 | cause: |
| 388 | connectCause as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 389 | }) |
| 390 | |
| 391 | if (!initialFlushDone && initialMessages && initialMessages.length > 0) { |
| 392 | initialFlushDone = true |
| 393 | // Capture current transport — if 401/teardown happens mid-flush, |
| 394 | // the stale .finally() must not drain the gate or signal connected. |
| 395 | // (Same guard pattern as replBridge.ts:1119.) |
| 396 | const flushTransport = transport |
| 397 | void flushHistory(initialMessages) |
| 398 | .catch(e => |
| 399 | logForDebugging(`[remote-bridge] flushHistory failed: ${e}`), |
| 400 | ) |
| 401 | .finally(() => { |
| 402 | // authRecoveryInFlight catches the v1-vs-v2 asymmetry: v1 nulls |
| 403 | // transport synchronously in setOnClose (replBridge.ts:1175), so |
| 404 | // transport !== flushTransport trips immediately. v2 doesn't null — |
| 405 | // transport reassigned only at rebuildTransport:346, 3 awaits deep. |
| 406 | // authRecoveryInFlight is set synchronously at rebuildTransport entry. |
| 407 | if ( |
| 408 | transport !== flushTransport || |
| 409 | tornDown || |
| 410 | authRecoveryInFlight |
| 411 | ) { |
| 412 | return |
| 413 | } |
| 414 | drainFlushGate() |
| 415 | onStateChange?.('connected') |
| 416 | }) |
| 417 | } else if (!flushGate.active) { |
| 418 | onStateChange?.('connected') |
| 419 | } |
| 420 | }) |
| 421 | |
| 422 | transport.setOnData((data: string) => { |
| 423 | handleIngressMessage( |
| 424 | data, |
| 425 | recentPostedUUIDs, |
| 426 | recentInboundUUIDs, |
| 427 | onInboundMessage, |
| 428 | // Remote client answered the permission prompt — the turn resumes. |
| 429 | // Without this the server stays on requires_action until the next |
| 430 | // user message or turn-end result. |
| 431 | onPermissionResponse |
| 432 | ? res => { |
| 433 | transport.reportState('running') |
| 434 | onPermissionResponse(res) |
| 435 | } |
| 436 | : undefined, |
| 437 | req => |
no test coverage detected