llama-cpp-sys-4 0.4.4

Low Level Bindings to llama.cpp
Documentation
diff --git a/include/llama.h b/include/llama.h
index a3ceecf5e..60a5003e4 100644
--- a/include/llama.h
+++ b/include/llama.h
@@ -344,6 +344,21 @@ extern "C" {
         struct llama_sampler * sampler;
     };
 
+    // Exact decode lifecycle hooks used by safe callback owners. The begin
+    // callback runs before native state mutation. The end callback runs after
+    // every attempted decode and receives whether native decode succeeded.
+    typedef bool (*llama_decode_begin_callback)(
+            const struct llama_batch * batch,
+            void * user_data);
+    typedef bool (*llama_decode_end_callback)(
+            bool native_succeeded,
+            void * user_data);
+
+    // ABI guard: defined only in patched builds. The Rust binding references
+    // this symbol so an unpatched or ABI-mismatched prebuilt libllama fails at
+    // link time instead of silently disabling the decode hooks.
+    LLAMA_API int llama_cpp_rs_decode_hooks_abi_v1(void);
+
     // NOTE: changing the default values of parameters marked as [EXPERIMENTAL] may cause crashes or incorrect results in certain configurations
     //       https://github.com/ggml-org/llama.cpp/pull/7544
     struct llama_context_params {
@@ -405,6 +420,12 @@ extern "C" {
         // a source/target/parent context
         // can be utilized in various ways, for example by sharing results or llama_memory between 2 contexts
         struct llama_context * ctx_other;
+
+        // Exact decode lifecycle hooks. Appended at the end of the struct so
+        // every upstream field keeps its original offset — ABI-robust against a
+        // prebuilt libllama built without this patch.
+        llama_decode_begin_callback cb_decode_begin;
+        llama_decode_end_callback   cb_decode_end;
     };
 
     struct llama_model_tensor_override {
diff --git a/src/llama-context.cpp b/src/llama-context.cpp
index 5ef7becf6..1dac3b056 100644
--- a/src/llama-context.cpp
+++ b/src/llama-context.cpp
@@ -136,6 +136,8 @@ llama_context::llama_context(
 
     cparams.cb_eval           = params.cb_eval;
     cparams.cb_eval_user_data = params.cb_eval_user_data;
+    cparams.cb_decode_begin   = params.cb_decode_begin;
+    cparams.cb_decode_end     = params.cb_decode_end;
 
     cparams.ctx_other = nullptr;
 
@@ -3514,6 +3516,8 @@ llama_context_params llama_context_default_params() {
         /*.sampler                     =*/ nullptr,
         /*.n_sampler                   =*/ 0,
         /*.ctx_other                   =*/ nullptr,
+        /*.cb_decode_begin             =*/ nullptr,
+        /*.cb_decode_end               =*/ nullptr,
     };
 
     return result;
@@ -4094,10 +4098,24 @@ int32_t llama_encode(
     return ret;
 }
 
+int llama_cpp_rs_decode_hooks_abi_v1(void) {
+    return 1;
+}
+
 int32_t llama_decode(
         llama_context * ctx,
           llama_batch   batch) {
+    const auto & cparams = ctx->get_cparams();
+    if (cparams.cb_decode_begin &&
+            !cparams.cb_decode_begin(&batch, cparams.cb_eval_user_data)) {
+        return -4;
+    }
+
     const int ret = ctx->decode(batch);
+    if (cparams.cb_decode_end &&
+            !cparams.cb_decode_end(ret == 0, cparams.cb_eval_user_data)) {
+        return -4;
+    }
     if (ret != 0 && ret != 1) {
         LLAMA_LOG_ERROR("%s: failed to decode, ret = %d\n", __func__, ret);
     }
diff --git a/src/llama-cparams.h b/src/llama-cparams.h
index 5018170ed..d0e8ddc30 100644
--- a/src/llama-cparams.h
+++ b/src/llama-cparams.h
@@ -62,4 +62,8 @@ struct llama_cparams {
     void * cb_eval_user_data;
 
     llama_context * ctx_other;
+
+    // Exact decode lifecycle hooks (appended; see llama.h).
+    llama_decode_begin_callback cb_decode_begin;
+    llama_decode_end_callback   cb_decode_end;
 };