import pathlib
root=pathlib.Path('/home/lighthouse/esp32-dev/.cache/speech-playback-diagnostics-20261006')
p=root/'firmware/main/cloud_client.cpp'
s=p.read_text()
assert '[DIAG_RX]' not in s
s=s.replace('static unsigned s_rx_parts;', '''static unsigned s_rx_parts;
struct RxTrace { int64_t us; int offset, bytes, total; unsigned opcode, fin; };
static RxTrace s_rx_trace[16];''')
s=s.replace('if (event->op_code == 0x1 || event->op_code == 0x0) ++s_rx_parts;', '''if (event->op_code == 0x1 || event->op_code == 0x0) {
            if (s_rx_parts < 16) s_rx_trace[s_rx_parts] = {esp_timer_get_time(), event->payload_offset,
                event->data_len, event->payload_len, event->op_code, event->fin};
            ++s_rx_parts;
        }''')
s=s.replace('handle_message(s_text_receiver.data(), s_text_receiver.size());', '''if (s_text_receiver.size() > 9000) {
                const char *seq = strstr(s_text_receiver.data(), "\\\"sequence\\\"");
                const int sequence = seq ? atoi(strchr(seq, ':') + 1) : -1;
                // Retain timestamps during receive, print only after frame completion.
                for (unsigned i=0; i<s_rx_parts && i<16; ++i) {
                    const auto &t=s_rx_trace[i];
                    ESP_LOGI(TAG, "[DIAG_RX] seq=%d part=%u us=%lld off=%d bytes=%d total=%d op=%u fin=%u",
                        sequence, i, (long long)t.us, t.offset, t.bytes, t.total, t.opcode, t.fin);
                }
                ESP_LOGI(TAG, "[DIAG_RX] complete seq=%d us=%lld parts=%u bytes=%u elapsed_ms=%lld",
                    sequence, (long long)now, s_rx_parts, (unsigned)s_text_receiver.size(), (long long)elapsed_ms);
            }
            handle_message(s_text_receiver.data(), s_text_receiver.size());''')
p.write_text(s)
print('Added receive timestamps, buffers only metadata until frame completion')
