MCPcopy Create free account
hub / github.com/antirez/ds4 / parse_chat_request

Function parse_chat_request

ds4_server.c:2635–2804  ·  view source on GitHub ↗

The API parsers are intentionally selective JSON parsers: they keep only * fields that affect model semantics, rendering, streaming, or cache keys, and * skip extension fields. The output is always a rendered DS4 chat/completion * prompt plus the small amount of protocol state needed to translate the reply. */

Source from the content-addressed store, hash-verified

2633 * In the common agent tool path, the previous assistant tool-call turn is
2634 * already in the model session, including hidden thinking and exact sampled
2635 * DSML. The next request provides only the tool results, either as OpenAI
2636 * Responses tool-output items or Anthropic user content blocks. Re-rendering
2637 * the assistant call here would duplicate it and destroy cache alignment, so
2638 * this function starts at the first new item and emits only:
2639 *
2640 * previous EOS, tool results, and the next assistant prefix.
2641 *
2642 * This is intentionally independent from req.prompt's already-tokenized suffix:
2643 * suffix tokenization happens later after the cache decision, using the live
2644 * token prefix as the boundary. That avoids BPE merges across the visible
2645 * replay/live-KV boundary. */
2646static char *render_deepseek_live_tool_tail(const chat_msgs *msgs, int start,
2647 ds4_think_mode think_mode) {
2648 const bool think = ds4_think_mode_enabled(think_mode);
2649 buf out = {0};
2650 buf_puts(&out, "<|end▁of▁sentence|>");
2651
2652 bool pending_assistant = false;
2653 bool pending_tool_result = false;
2654 for (int i = start; msgs && i < msgs->len; i++) {
2655 const chat_msg *m = &msgs->v[i];
2656 if (role_is_system(m->role)) {
2657 continue;
2658 } else if (!strcmp(m->role, "user")) {
2659 buf_puts(&out, "<|User|>");
2660 buf_puts(&out, m->content ? m->content : "");
2661 pending_assistant = true;
2662 pending_tool_result = false;
2663 } else if (!strcmp(m->role, "tool") || !strcmp(m->role, "function")) {
2664 if (!pending_tool_result) buf_puts(&out, "<|User|>");
2665 buf_puts(&out, "<tool_result>");
2666 append_tool_result_text(&out, m->content);
2667 buf_puts(&out, "</tool_result>");
2668 pending_assistant = true;
2669 pending_tool_result = true;
2670 } else if (!strcmp(m->role, "assistant")) {
2671 if (pending_assistant) {
2672 buf_puts(&out, "<|Assistant|>");
2673 if (think) {
2674 buf_puts(&out, "<think>");
2675 buf_puts(&out, m->reasoning ? m->reasoning : "");
2676 buf_puts(&out, "</think>");
2677 } else {
2678 buf_puts(&out, "</think>");
2679 }
2680 }
2681 buf_puts(&out, m->content ? m->content : "");
2682 append_dsml_tool_calls_text(&out, &m->calls);
2683 buf_puts(&out, "<|end▁of▁sentence|>");
2684 pending_assistant = false;
2685 pending_tool_result = false;
2686 }
2687 }
2688
2689 if (pending_assistant) {
2690 buf_puts(&out, "<|Assistant|>");
2691 buf_puts(&out, think ? "<think>" : "</think>");
2692 }

Callers 3

client_mainFunction · 0.85
test_think_tool_recoveryFunction · 0.85

Calls 15

request_initFunction · 0.85
json_wsFunction · 0.85
json_stringFunction · 0.85
chat_msgs_freeFunction · 0.85
parse_messagesFunction · 0.85
parse_tools_valueFunction · 0.85
json_skip_valueFunction · 0.85
json_intFunction · 0.85
json_numberFunction · 0.85
json_boolFunction · 0.85
parse_stream_optionsFunction · 0.85

Tested by 2

test_think_tool_recoveryFunction · 0.68