()
| 405 | |
| 406 | // ── 6. Wire callbacks (extracted so transport-rebuild can re-wire) ────── |
| 407 | function wireTransportCallbacks(): void { |
| 408 | transport.setOnConnect(() => { |
| 409 | clearTimeout(connectDeadline) |
| 410 | logForDebugging('[remote-bridge] v2 transport connected') |
| 411 | logForDiagnosticsNoPII('info', 'bridge_repl_v2_transport_connected') |
| 412 | logEvent('tengu_bridge_repl_ws_connected', { |
| 413 | v2: true, |
| 414 | cause: |
| 415 | connectCause as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 416 | }) |
| 417 | |
| 418 | if (!initialFlushDone && initialMessages && initialMessages.length > 0) { |
| 419 | initialFlushDone = true |
| 420 | // Capture current transport — if 401/teardown happens mid-flush, |
| 421 | // the stale .finally() must not drain the gate or signal connected. |
| 422 | // (Same guard pattern as replBridge.ts:1119.) |
| 423 | const flushTransport = transport |
| 424 | void flushHistory(initialMessages) |
| 425 | .catch(e => |
| 426 | logForDebugging(`[remote-bridge] flushHistory failed: ${e}`), |
| 427 | ) |
| 428 | .finally(() => { |
| 429 | // authRecoveryInFlight catches the v1-vs-v2 asymmetry: v1 nulls |
| 430 | // transport synchronously in setOnClose (replBridge.ts:1175), so |
| 431 | // transport !== flushTransport trips immediately. v2 doesn't null — |
| 432 | // transport reassigned only at rebuildTransport:346, 3 awaits deep. |
| 433 | // authRecoveryInFlight is set synchronously at rebuildTransport entry. |
| 434 | if ( |
| 435 | transport !== flushTransport || |
| 436 | tornDown || |
| 437 | authRecoveryInFlight |
| 438 | ) { |
| 439 | return |
| 440 | } |
| 441 | drainFlushGate() |
| 442 | onStateChange?.('connected') |
| 443 | }) |
| 444 | } else if (!flushGate.active) { |
| 445 | onStateChange?.('connected') |
| 446 | } |
| 447 | }) |
| 448 | |
| 449 | transport.setOnData((data: string) => { |
| 450 | handleIngressMessage( |
| 451 | data, |
| 452 | recentPostedUUIDs, |
| 453 | recentInboundUUIDs, |
| 454 | onInboundMessage, |
| 455 | // Remote client answered the permission prompt — the turn resumes. |
| 456 | // Without this the server stays on requires_action until the next |
| 457 | // user message or turn-end result. |
| 458 | onPermissionResponse |
| 459 | ? res => { |
| 460 | transport.reportState('running') |
| 461 | onPermissionResponse(res) |
| 462 | } |
| 463 | : undefined, |
| 464 | req => |
no test coverage detected