@@ -1433,6 +1433,42 @@ json convert_responses_to_chatcmpl(const json & response_body) {
14331433 return chatcmpl_body;
14341434}
14351435
1436+ // Edits the cch section of an "x-anthropic-billing-header" system prompt.
1437+ // Does nothing to any other prompt.
1438+ //
1439+ // This is a claude message with a "cch=ef01a" attribute that breaks prefix caching.
1440+ // The cch stamp is a whitebox end-to-end integrity hint. It's not meaningful as a
1441+ // system prompt data, particularly to llama.cpp, but its presence means the prefix
1442+ // cache will not get past it: It changes on each request.
1443+ //
1444+ // Reference: https://github.com/ggml-org/llama.cpp/pull/21793
1445+ // Example header:
1446+ // ```
1447+ // x-anthropic-billing-header: cc_version=2.1.101.e51; cc_entrypoint=cli; cch=a5145;You are Claude Code, Anthropic's official CLI for Claude.
1448+ // ^^^^^
1449+ // ```
1450+ void normalize_anthropic_billing_header (std::string & system_text) {
1451+ if (system_text.rfind (" x-anthropic-billing-header:" , 0 ) != 0 ) {
1452+ return ;
1453+ }
1454+
1455+ const size_t header_prefix_length = strlen (" x-anthropic-billing-header:" );
1456+ const size_t cch_length = 5 ;
1457+ const size_t index_cch = system_text.find (" cch=" , header_prefix_length);
1458+ if (index_cch == std::string::npos) {
1459+ return ;
1460+ }
1461+
1462+ const size_t index_replace = index_cch + 4 ;
1463+ if (index_replace + cch_length < system_text.length () && system_text[index_replace + cch_length] == ' ;' ) {
1464+ for (size_t i = 0 ; i < cch_length; ++i) {
1465+ system_text[index_replace + i] = ' f' ;
1466+ }
1467+ } else {
1468+ LOG_ERR (" anthropic string not as expected: %s" , system_text.c_str ());
1469+ }
1470+ }
1471+
14361472json convert_anthropic_to_oai (const json & body) {
14371473 json oai_body;
14381474
@@ -1444,32 +1480,12 @@ json convert_anthropic_to_oai(const json & body) {
14441480
14451481 if (system_param.is_string ()) {
14461482 system_content = system_param.get <std::string>();
1483+ normalize_anthropic_billing_header (system_content);
14471484 } else if (system_param.is_array ()) {
14481485 for (const auto & block : system_param) {
14491486 if (json_value (block, " type" , std::string ()) == " text" ) {
14501487 auto system_text = json_value (block, " text" , std::string ());
1451- if (system_text.rfind (" x-anthropic-billing-header:" , 0 ) == 0 ) {
1452- // This is a claude message with a "cch=ef01a" attribute that breaks prefix caching.
1453- // The cch stamp is a whitebox end-to-end integrity hint. It's not meaningful as a
1454- // system prompt data, particularly to llama.cpp, but its presence means the prefix
1455- // cache will not get past it: It changes on each request.
1456- //
1457- // Reference: https://github.com/ggml-org/llama.cpp/pull/21793
1458- // Example header: x-anthropic-billing-header: cc_version=2.1.101.e51; cc_entrypoint=cli; cch=a5145;You are Claude Code, Anthropic's official CLI for Claude.
1459- // ^^^^^
1460- const size_t header_prefix_length = strlen (" x-anthropic-billing-header:" );
1461- const size_t cch_length = 5 ;
1462- size_t index_cch = system_text.find (" cch=" , header_prefix_length);
1463- size_t index_replace = index_cch + 4 ;
1464- if (index_cch != std::string::npos && index_replace + cch_length < system_text.length () && system_text[index_replace + cch_length] == ' ;' ) {
1465- // only change this value if the cch still looks right.
1466- for (size_t i = 0 ; i < cch_length; ++i) {
1467- system_text[index_replace + i] = ' f' ;
1468- }
1469- } else {
1470- LOG_ERR (" anthropic string not as expected: %s" , system_text.c_str ());
1471- }
1472- }
1488+ normalize_anthropic_billing_header (system_text);
14731489 system_content += system_text;
14741490 }
14751491 }
0 commit comments