40 max_marker_len_(
std::
max(open_marker_.size(), close_marker_.size())) {}
62bool StreamThinkFilter::match_tag(
const std::string&
buf,
bool& is_open)
const {
63 if (
buf == open_marker_) { is_open =
true;
return true; }
64 if (
buf == close_marker_) { is_open =
false;
return true; }
77 if (
byte < 0x80) {
return 1; }
79 if (
byte >= 0xF0) { result = 4; }
80 else if (
byte >= 0xE0) { result = 3; }
81 else if (
byte >= 0xC0) { result = 2; }
97void StreamThinkFilter::emit_utf8_safe(
const char* data,
size_t len) {
98 utf8_buf_.append(data,
len);
101 size_t safe = utf8_buf_.size();
102 if (
safe == 0) {
return; }
105 auto*
buf =
reinterpret_cast<const unsigned char*
>(utf8_buf_.data());
106 for (
size_t i = 1;
i <= 4 &&
i <=
safe; ++
i) {
121 cb_(utf8_buf_.data(),
safe, ud_);
123 utf8_buf_.erase(0,
safe);
139void StreamThinkFilter::process_byte(
char c) {
141 if (tag_buf_.empty() &&
c != open_marker_[0] &&
c != close_marker_[0]) {
142 if (!in_think_) { emit_utf8_safe(&
c, 1); }
146 bool is_open =
false;
147 if (match_tag(tag_buf_, is_open)) {
153 if (tag_buf_.size() > max_marker_len_) {
155 emit_utf8_safe(tag_buf_.data(), tag_buf_.size());
170 if (raw_cb_) { raw_cb_(
chunk,
len, raw_ud_); }
172 for (
size_t i = 0;
i <
len; ++
i) {
183 if (!tag_buf_.empty() && !in_think_) {
184 emit_utf8_safe(tag_buf_.data(), tag_buf_.size());
188 if (!utf8_buf_.empty()) {
189 cb_(utf8_buf_.data(), utf8_buf_.size(), ud_);
void set_raw_callback(TokenCallback cb, void *ud)
Set optional raw callback (receives ALL tokens unfiltered).
void on_token(const char *chunk, size_t len)
Process a chunk of tokens.
void flush()
Flush any buffered partial tag content.
StreamThinkFilter(TokenCallback cb, void *ud)
Construct with consumer callback.
Activate model on GPU (WARM → ACTIVE).
@ optional
optional: every escape asks the host's path approver
static int utf8_char_len(unsigned char byte)
Count expected bytes in a UTF-8 sequence from lead byte.
void(*)(const char *, size_t, void *) TokenCallback
Token callback type matching the C API signature.
Streaming filter that strips a model family's reasoning blocks.