| 6790 | return "completed"; |
| 6791 | } |
| 6792 | |
| 6793 | static bool responses_sse_reasoning_done(int fd, responses_stream *st, |
| 6794 | const char *finish) { |
| 6795 | /* If the stream terminates before `</think>` was actually observed the |
| 6796 | * reasoning item is partial — regardless of why generation stopped (EOS, |
| 6797 | * stop sequence, tool_calls, length, error). Force the item to incomplete |
| 6798 | * so a client replay rejects it instead of feeding unfinished hidden state |
| 6799 | * back as completed history. */ |
| 6800 | (void)finish; |
| 6801 | const char *item_status = |
| 6802 | st->reasoning_closed_naturally ? "completed" : "incomplete"; |
| 6803 | /* Mirror the message-item close sequence: emit summary_text.done + |
| 6804 | * summary_part.done before the output_item.done so clients that key off |
| 6805 | * part lifecycle don't see a dangling open summary part. */ |
| 6806 | buf b = {0}; |
| 6807 | buf_printf(&b, |
| 6808 | "{\"type\":\"response.reasoning_summary_text.done\"," |
| 6809 | "\"item_id\":\"%s\",\"output_index\":%d,\"summary_index\":0,\"text\":", |
| 6810 | st->reasoning_id, st->reasoning_index); |
| 6811 | json_escape_n(&b, st->reasoning_text.ptr ? st->reasoning_text.ptr : "", |
| 6812 | st->reasoning_text.len); |
| 6813 | buf_putc(&b, '}'); |
| 6814 | bool ok = responses_sse_emit_event(fd, st, b.ptr); |
| 6815 | if (!ok) { |
| 6816 | buf_free(&b); |
| 6817 | return false; |
| 6818 | } |
| 6819 | |
| 6820 | if (st->reasoning_summary_started) { |
| 6821 | buf_free(&b); |
| 6822 | buf_printf(&b, |
| 6823 | "{\"type\":\"response.reasoning_summary_part.done\"," |
| 6824 | "\"item_id\":\"%s\",\"output_index\":%d,\"summary_index\":0," |
| 6825 | "\"part\":{\"type\":\"summary_text\",\"text\":", |
| 6826 | st->reasoning_id, st->reasoning_index); |
| 6827 | json_escape_n(&b, st->reasoning_text.ptr ? st->reasoning_text.ptr : "", |
| 6828 | st->reasoning_text.len); |
| 6829 | buf_puts(&b, "}}"); |
| 6830 | ok = responses_sse_emit_event(fd, st, b.ptr); |
| 6831 | if (!ok) { |
no test coverage detected