| 862 | } |
| 863 | } else if (messages.is_string()) { |
| 864 | chat_msgs.push_back({"user", messages.get<std::string>()}); |
| 865 | } |
| 866 | |
| 867 | if (!system_parts.empty()) { |
| 868 | std::string merged_system; |
| 869 | for (size_t i = 0; i < system_parts.size(); i++) { |
| 870 | if (i) merged_system += "\n\n"; |
| 871 | merged_system += system_parts[i]; |
| 872 | } |
| 873 | chat_msgs.insert(chat_msgs.begin(), {"system", merged_system}); |
| 874 | } |
| 875 | |
| 876 | return chat_msgs; |
| 877 | } |
| 878 | |
| 879 | // ─── Disk-cache identity salt ─────────────────────────────────────────── |
| 880 | // Compute a 16-byte salt from inputs that affect KV cache validity: |
| 881 | // model path + stat(size + mtime) [covers rope/yarn — GGUF-derived], |
| 882 | // max_ctx, and sha1(chat_template_src). |
| 883 | // Returns all-zeroes if model_path is empty (back-compat / disk disabled). |
| 884 | static std::array<uint8_t, 16> compute_disk_cache_salt(const ServerConfig & cfg) { |
| 885 | std::array<uint8_t, 16> salt{}; |
| 886 | if (cfg.model_path.empty()) return salt; |
| 887 | |
| 888 | const std::string & path = cfg.model_path; |
| 889 | struct stat st{}; |
| 890 | int64_t file_size = 0; |
| 891 | int64_t file_mtime = 0; |
| 892 | if (::stat(path.c_str(), &st) == 0) { |
| 893 | file_size = (int64_t)st.st_size; |
| 894 | file_mtime = (int64_t)st.st_mtime; |
nothing calls this directly
no test coverage detected