Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .claude/rules/github-actions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
paths:
- ".github/actions/**/*"
---

# GitHub Actions Standards

- Actions must represent a single purpose and a single concern.
- Compose actions if they need to provide a more complex functionality.
- GitHub actions must be named after their purpose and intent. Avoid names like "setup", "ci", and such. They need to describe the intention, and purpose behind them.
11 changes: 7 additions & 4 deletions .claude/rules/github-workflows.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
---
paths:
- ".github/**/*"
- ".github/workflows/**/*"
---

# GitHub Workflows Standards

- Always use Makefile targets in the workflow to avoid code duplication.
- Always use Makefile targets in the workflow to avoid code duplication (if they need to run something that is already present in a Makefile).
- Never add the tests that use LLMs to GitHub workflows, because the default GitHub worker does not have the capacity to run them.
- Only add unit tests to GitHub workflows.
- Only add unit tests or linters to GitHub workflows.
- Keep GitHub workflows responsible for only a single concern. For example, run linter, and tests in parallel.
- Do not collect code coverage in GitHub workflows. Do not instrument code.
- Treat GitHub workflows as a coding project. Use composable actions, factor similar concerns into actions.
- Encapsulate functionalities in composable actions.
- Keep the workflows clean and purposeful.
- GitHub workflows must be named after their purpose and intent. Avoid names like "setup", "ci", and such. They need to describe the intention, and purpose behind them.
12 changes: 12 additions & 0 deletions .claude/rules/nix-shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
paths:
- "**/shell.nix"
---

# Nix Shell Standards

- shell.nix must follow idiomatic NixOS ways of providing packages
- shell.nix must be minimal, and only providing project dependencies that would not be able to run natively otherwise
- shell.nix must not contain any workarounds
- shell.nix must not contain any kind of ELF patching
- shell.nix must not contain any kind of monkey patching
14 changes: 14 additions & 0 deletions .claude/rules/rust-integration-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
paths:
- "**/tests/**/*.rs"
---

# Rust Integration Tests Standards

- Each test needs to be named after what functionality, or issue it actually tests.
- Each test file needs to be named after what functionality, or issue it actually tests.
- Each test represents a specific scenario that the core project needs to support, or represent an uncovered issue.
- If you uncover a new issue while testing, create yet another targeted test that covers that.
- Every test muse use production code. Never recreate the original code to test something conceptually. Always use production code.
- They must be single-purpose.
- It must be clear what is being tested in the test file by just reading the filename.
13 changes: 13 additions & 0 deletions .claude/rules/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,16 @@ paths:
- Never use Result<> as a function argument.
- Never forward Result in enums if you can instead create a targeted error enum. It is always better to signal the specific issue, so it can be handled downstream.
- Always destructure structs in arguments if possible.

# Code Style

Imports/uses must not be mixed with other kinds of rust syntax.

Each file needs to follow this order:
1. `pub mod`/`mod` exports
2. vendor crate `use`
2. project crate `use`
3. local crate `use`
4. private function helpers
5. private struct helpers
6. single public export
59 changes: 43 additions & 16 deletions llama-cpp-bindings/src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,26 @@ impl Module {
}
}

#[cfg(target_env = "msvc")]
const fn ggml_log_level_to_i32(level: llama_cpp_bindings_sys::ggml_log_level) -> i32 {
level
}

#[cfg(not(target_env = "msvc"))]
const fn ggml_log_level_to_i32(level: llama_cpp_bindings_sys::ggml_log_level) -> i32 {
level.cast_signed()
}

#[cfg(target_env = "msvc")]
const fn ggml_log_level_from_i32(stored: i32) -> llama_cpp_bindings_sys::ggml_log_level {
stored
}

#[cfg(not(target_env = "msvc"))]
const fn ggml_log_level_from_i32(stored: i32) -> llama_cpp_bindings_sys::ggml_log_level {
stored.cast_unsigned()
}

fn meta_for_level(
level: llama_cpp_bindings_sys::ggml_log_level,
) -> Option<(&'static Metadata<'static>, &'static OverridableFields)> {
Expand Down Expand Up @@ -194,10 +214,10 @@ impl State {
*lock = Some((previous_log_level, buffer));
}
} else {
let level = self
.previous_level
.load(std::sync::atomic::Ordering::Acquire)
.cast_unsigned();
let level = ggml_log_level_from_i32(
self.previous_level
.load(std::sync::atomic::Ordering::Acquire),
);
tracing::warn!(
inferred_level = level,
text = text,
Expand Down Expand Up @@ -231,8 +251,10 @@ impl State {

self.is_buffering
.store(true, std::sync::atomic::Ordering::Release);
self.previous_level
.store(level.cast_signed(), std::sync::atomic::Ordering::Release);
self.previous_level.store(
ggml_log_level_to_i32(level),
std::sync::atomic::Ordering::Release,
);
}

/// Emit a normal unbuffered log message (not the CONT log level and the text ends with a newline).
Expand All @@ -254,8 +276,10 @@ impl State {
self.generate_log(buf_level, buf_text.as_str());
}

self.previous_level
.store(level.cast_signed(), std::sync::atomic::Ordering::Release);
self.previous_level.store(
ggml_log_level_to_i32(level),
std::sync::atomic::Ordering::Release,
);

let (text, _trailing_newline) = text.split_at(text.len() - 1);

Expand Down Expand Up @@ -294,8 +318,10 @@ impl State {
level: llama_cpp_bindings_sys::ggml_log_level,
) {
if level != llama_cpp_bindings_sys::GGML_LOG_LEVEL_CONT {
self.previous_level
.store(level.cast_signed(), std::sync::atomic::Ordering::Release);
self.previous_level.store(
ggml_log_level_to_i32(level),
std::sync::atomic::Ordering::Release,
);
}
}

Expand All @@ -304,9 +330,10 @@ impl State {
/// being checked on their own.
pub fn is_enabled_for_level(&self, level: llama_cpp_bindings_sys::ggml_log_level) -> bool {
let level = if level == llama_cpp_bindings_sys::GGML_LOG_LEVEL_CONT {
self.previous_level
.load(std::sync::atomic::Ordering::Relaxed)
.cast_unsigned()
ggml_log_level_from_i32(
self.previous_level
.load(std::sync::atomic::Ordering::Relaxed),
)
} else {
level
};
Expand Down Expand Up @@ -397,7 +424,7 @@ mod tests {

use tracing_subscriber::util::SubscriberInitExt;

use super::{Module, State, logs_to_trace};
use super::{Module, State, ggml_log_level_to_i32, logs_to_trace};
use crate::log_options::LogOptions;

#[test]
Expand Down Expand Up @@ -435,7 +462,7 @@ mod tests {

assert_eq!(
stored,
llama_cpp_bindings_sys::GGML_LOG_LEVEL_WARN.cast_signed()
ggml_log_level_to_i32(llama_cpp_bindings_sys::GGML_LOG_LEVEL_WARN)
);
}

Expand All @@ -452,7 +479,7 @@ mod tests {

assert_eq!(
stored,
llama_cpp_bindings_sys::GGML_LOG_LEVEL_ERROR.cast_signed()
ggml_log_level_to_i32(llama_cpp_bindings_sys::GGML_LOG_LEVEL_ERROR)
);
}

Expand Down
Loading