| 826 | |
| 827 | static void request_free(request *r) { |
| 828 | ds4_tokens_free(&r->prompt); |
| 829 | free(r->model); |
| 830 | for (int i = 0; i < r->stops.len; i++) free(r->stops.v[i]); |
| 831 | free(r->stops.v); |
| 832 | free(r->raw_body); |
| 833 | free(r->prompt_text); |
| 834 | stop_list_clear(&r->responses_live_call_ids); |
| 835 | free(r->responses_live_call_ids.v); |
| 836 | free(r->responses_live_suffix_text); |
| 837 | stop_list_clear(&r->anthropic_live_call_ids); |
| 838 | free(r->anthropic_live_call_ids.v); |
| 839 | free(r->anthropic_live_suffix_text); |
| 840 | tool_schema_orders_free(&r->tool_orders); |
| 841 | memset(r, 0, sizeof(*r)); |
| 842 | } |
| 843 | |
| 844 | static ds4_think_mode think_mode_from_enabled(bool enabled, ds4_think_mode effort) { |
| 845 | if (!enabled || effort == DS4_THINK_NONE) return DS4_THINK_NONE; |
| 846 | return effort == DS4_THINK_MAX ? DS4_THINK_MAX : DS4_THINK_HIGH; |
| 847 | } |
| 848 | |
| 849 | static bool parse_reasoning_effort_name(const char *s, ds4_think_mode *out) { |
| 850 | if (!s) return false; |
| 851 | if (!strcmp(s, "max")) { |
| 852 | *out = DS4_THINK_MAX; |
| 853 | return true; |
| 854 | } |
| 855 | if (!strcmp(s, "xhigh") || !strcmp(s, "high") || |
| 856 | !strcmp(s, "medium") || !strcmp(s, "low") || |
| 857 | !strcmp(s, "minimal")) |
| 858 | { |
| 859 | /* DS4 only exposes HIGH and MAX above zero, so "minimal" collapses to |
| 860 | * the smallest non-zero level (HIGH). Callers that need *no* reasoning |
| 861 | * must use "none" instead. */ |
| 862 | *out = DS4_THINK_HIGH; |
| 863 | return true; |
| 864 | } |
| 865 | if (!strcmp(s, "none")) { |
| 866 | *out = DS4_THINK_NONE; |
| 867 | return true; |
| 868 | } |